home *** CD-ROM | disk | FTP | other *** search
/ CBM Funet Archive / cbm-funet-archive-2003.iso / cbm / csbruce / unbcode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-25  |  18.3 KB  |  723 lines

  1. /*  unbcode: BCODE DECODER VERSION 1.03-KR BY cRAIG bRUCE 07-oCT-93, 09-nOV-93.
  2. **
  3. **  aDDED CODE FOR REMOVE AND RENAME.  tO ACTIVATE, ADD -dno_remove AND/OR 
  4. **  -dno_rename AS NEEDED.  15-oCT-93 (BJS)
  5. **
  6. **  crc-32 CODE BASED ON "fILE vERIFICATION uSING crc" BY mARK r. nELSON IN
  7. **  dR. dOBB'S jOURNAL, mAY 1992, PP. 64-67.  nOTE THAT crc-32 VALUES are THE
  8. **  SAME AS IN zmodem AND pkzip.
  9. */
  10.  
  11. #INCLUDE <STDIO.H>
  12. #INCLUDE <STDLIB.H>
  13. #INCLUDE <STRING.H>
  14.  
  15. #DEFINE version"1.03-KR"
  16. #DEFINE max_chunk64
  17. #DEFINE max_line85
  18. #DEFINE max_filename85
  19. #DEFINE max_have1000
  20. #DEFINE max_tempname20
  21. #DEFINE copy_buf_size4096
  22.  
  23. #IFDEF no_remove
  24. #DEFINE REMOVE(X) UNLINK(X)
  25. #ENDIF
  26.  
  27. TYPEDEF UNSIGNED CHAR byte;
  28. TYPEDEF CHAR sbyte;
  29. TYPEDEF UNSIGNED LONG ulong;
  30. TYPEDEF INT bool;
  31. #DEFINE true1
  32. #DEFINE false0
  33.  
  34. TYPEDEF STRUCT {$7b}
  35. ulongFROMsEG;
  36. ulongTOsEG;
  37. boolISeND;
  38. ulongTEMPfILEnAME;
  39. CHAR   *FILENAME;
  40. {$7d} haverec;
  41.  
  42. VOIDMAIN();
  43. VOIDdECODEfILE();
  44. ulongfINDhEADER();
  45. VOIDlOADsTATUSfILE();
  46. VOIDsAVEsTATUSfILE();
  47. VOIDwRITEsTATUSdATA();
  48. INTrEADlINE();
  49. VOIDbUILDdECODEtABLE();
  50. booldECODEsEG();
  51. INTdECODElINE();
  52. file   *gETtEMPfILE();
  53. ulongiNSERThAVErEC();
  54. VOIDcHECKcOALESCE();
  55. VOIDcHECKcOMPLETE();
  56. VOIDrEMOVEhAVErEC();
  57. VOIDgETtEMPnAMEsTR();
  58.  
  59. CHAR   *PROGNAME;
  60. boolINFORMATIVE;
  61. boolVERBOSE;
  62. boolDEBUG;
  63. CHAR   *READfILENAME;
  64. ulongREADlINEnUM;
  65.  
  66. haverecHAVES[max_have];
  67. INTHAVEcOUNT;
  68. boolSTATUSfILEeXISTS;
  69. ulongNEXTtEMPnAME;
  70. CHARTEMPpREFIX[max_filename];
  71. byteCOPYbUF[copy_buf_size];
  72. sbyteDECODEtABLE[ 256 ];
  73. ulongCRCtABLE[256] = {$7b}
  74.     0X00000000, 0X77073096, 0Xee0e612c, 0X990951ba, 0X076dc419, 0X706af48f, 
  75.     0Xe963a535, 0X9e6495a3, 0X0edb8832, 0X79dcb8a4, 0Xe0d5e91e, 0X97d2d988, 
  76.     0X09b64c2b, 0X7eb17cbd, 0Xe7b82d07, 0X90bf1d91, 0X1db71064, 0X6ab020f2, 
  77.     0Xf3b97148, 0X84be41de, 0X1adad47d, 0X6ddde4eb, 0Xf4d4b551, 0X83d385c7, 
  78.     0X136c9856, 0X646ba8c0, 0Xfd62f97a, 0X8a65c9ec, 0X14015c4f, 0X63066cd9, 
  79.     0Xfa0f3d63, 0X8d080df5, 0X3b6e20c8, 0X4c69105e, 0Xd56041e4, 0Xa2677172, 
  80.     0X3c03e4d1, 0X4b04d447, 0Xd20d85fd, 0Xa50ab56b, 0X35b5a8fa, 0X42b2986c, 
  81.     0Xdbbbc9d6, 0Xacbcf940, 0X32d86ce3, 0X45df5c75, 0Xdcd60dcf, 0Xabd13d59, 
  82.     0X26d930ac, 0X51de003a, 0Xc8d75180, 0Xbfd06116, 0X21b4f4b5, 0X56b3c423, 
  83.     0Xcfba9599, 0Xb8bda50f, 0X2802b89e, 0X5f058808, 0Xc60cd9b2, 0Xb10be924, 
  84.     0X2f6f7c87, 0X58684c11, 0Xc1611dab, 0Xb6662d3d, 0X76dc4190, 0X01db7106, 
  85.     0X98d220bc, 0Xefd5102a, 0X71b18589, 0X06b6b51f, 0X9fbfe4a5, 0Xe8b8d433, 
  86.     0X7807c9a2, 0X0f00f934, 0X9609a88e, 0Xe10e9818, 0X7f6a0dbb, 0X086d3d2d, 
  87.     0X91646c97, 0Xe6635c01, 0X6b6b51f4, 0X1c6c6162, 0X856530d8, 0Xf262004e, 
  88.     0X6c0695ed, 0X1b01a57b, 0X8208f4c1, 0Xf50fc457, 0X65b0d9c6, 0X12b7e950, 
  89.     0X8bbeb8ea, 0Xfcb9887c, 0X62dd1ddf, 0X15da2d49, 0X8cd37cf3, 0Xfbd44c65, 
  90.     0X4db26158, 0X3ab551ce, 0Xa3bc0074, 0Xd4bb30e2, 0X4adfa541, 0X3dd895d7, 
  91.     0Xa4d1c46d, 0Xd3d6f4fb, 0X4369e96a, 0X346ed9fc, 0Xad678846, 0Xda60b8d0, 
  92.     0X44042d73, 0X33031de5, 0Xaa0a4c5f, 0Xdd0d7cc9, 0X5005713c, 0X270241aa, 
  93.     0Xbe0b1010, 0Xc90c2086, 0X5768b525, 0X206f85b3, 0Xb966d409, 0Xce61e49f, 
  94.     0X5edef90e, 0X29d9c998, 0Xb0d09822, 0Xc7d7a8b4, 0X59b33d17, 0X2eb40d81, 
  95.     0Xb7bd5c3b, 0Xc0ba6cad, 0Xedb88320, 0X9abfb3b6, 0X03b6e20c, 0X74b1d29a, 
  96.     0Xead54739, 0X9dd277af, 0X04db2615, 0X73dc1683, 0Xe3630b12, 0X94643b84, 
  97.     0X0d6d6a3e, 0X7a6a5aa8, 0Xe40ecf0b, 0X9309ff9d, 0X0a00ae27, 0X7d079eb1, 
  98.     0Xf00f9344, 0X8708a3d2, 0X1e01f268, 0X6906c2fe, 0Xf762575d, 0X806567cb, 
  99.     0X196c3671, 0X6e6b06e7, 0Xfed41b76, 0X89d32be0, 0X10da7a5a, 0X67dd4acc, 
  100.     0Xf9b9df6f, 0X8ebeeff9, 0X17b7be43, 0X60b08ed5, 0Xd6d6a3e8, 0Xa1d1937e, 
  101.     0X38d8c2c4, 0X4fdff252, 0Xd1bb67f1, 0Xa6bc5767, 0X3fb506dd, 0X48b2364b, 
  102.     0Xd80d2bda, 0Xaf0a1b4c, 0X36034af6, 0X41047a60, 0Xdf60efc3, 0Xa867df55, 
  103.     0X316e8eef, 0X4669be79, 0Xcb61b38c, 0Xbc66831a, 0X256fd2a0, 0X5268e236, 
  104.     0Xcc0c7795, 0Xbb0b4703, 0X220216b9, 0X5505262f, 0Xc5ba3bbe, 0Xb2bd0b28, 
  105.     0X2bb45a92, 0X5cb36a04, 0Xc2d7ffa7, 0Xb5d0cf31, 0X2cd99e8b, 0X5bdeae1d, 
  106.     0X9b64c2b0, 0Xec63f226, 0X756aa39c, 0X026d930a, 0X9c0906a9, 0Xeb0e363f, 
  107.     0X72076785, 0X05005713, 0X95bf4a82, 0Xe2b87a14, 0X7bb12bae, 0X0cb61b38, 
  108.     0X92d28e9b, 0Xe5d5be0d, 0X7cdcefb7, 0X0bdbdf21, 0X86d3d2d4, 0Xf1d4e242, 
  109.     0X68ddb3f8, 0X1fda836e, 0X81be16cd, 0Xf6b9265b, 0X6fb077e1, 0X18b74777, 
  110.     0X88085ae6, 0Xff0f6a70, 0X66063bca, 0X11010b5c, 0X8f659eff, 0Xf862ae69, 
  111.     0X616bffd3, 0X166ccf45, 0Xa00ae278, 0Xd70dd2ee, 0X4e048354, 0X3903b3c2, 
  112.     0Xa7672661, 0Xd06016f7, 0X4969474d, 0X3e6e77db, 0Xaed16a4a, 0Xd9d65adc, 
  113.     0X40df0b66, 0X37d83bf0, 0Xa9bcae53, 0Xdebb9ec5, 0X47b2cf7f, 0X30b5ffe9, 
  114.     0Xbdbdf21c, 0Xcabac28a, 0X53b39330, 0X24b4a3a6, 0Xbad03605, 0Xcdd70693, 
  115.     0X54de5729, 0X23d967bf, 0Xb3667a2e, 0Xc4614ab8, 0X5d681b02, 0X2a6f2b94, 
  116.     0Xb40bbe37, 0Xc30c8ea1, 0X5a05df1b, 0X2d02ef8d
  117. {$7d};
  118.  
  119. /****************************************************************************/
  120. VOID MAIN( ARGC, ARGV )
  121. INTARGC;
  122. CHAR   *ARGV[];
  123. {$7b}
  124. file   *FIN;
  125. INTI;
  126. boolFILENAMEuSED;
  127.  
  128. PROGNAME     = ARGV[0];
  129. FILENAMEuSED = false;
  130. INFORMATIVE  = false;
  131. VERBOSE      = false;
  132. DEBUG        = false;
  133. STRCPY( TEMPpREFIX, "" );
  134. bUILDdECODEtABLE();
  135. lOADsTATUSfILE();
  136.  
  137. I = 1;
  138. WHILE (I<ARGC) {$7b}
  139. IF (ARGV[I][0] == '-') {$7b}
  140. SWITCH (ARGV[I][1]) {$7b}
  141. CASE 'I':
  142. INFORMATIVE = true;
  143. BREAK;
  144. CASE 'D':
  145. VERBOSE = true;
  146. INFORMATIVE = true;
  147. DEBUG = true;
  148. FPRINTF(STDERR, "UNBCODE VERSION %S\N",
  149. version );
  150. FPRINTF(STDERR, "DEBUGGING MODE ACTIVATED\N");
  151. FPRINTF(STDERR,
  152. "---cURRENT-fILE-sEGMENTS---\N");
  153. wRITEsTATUSdATA( STDERR );
  154. FPRINTF(STDERR,
  155. "--eND-OF-cURRENT-sEGMENTS--\N");
  156. BREAK;
  157. CASE 'V':
  158. VERBOSE = true;
  159. INFORMATIVE = true;
  160. FPRINTF(STDERR, "UNBCODE VERSION %S\N",
  161. version);
  162. BREAK;
  163. DEFAULT:
  164. FPRINTF(STDERR, "%S: UNRECOGNIZED OPTION\N",
  165. PROGNAME);
  166. FPRINTF(STDERR,
  167. "USAGE: %S [-V] [-I] [-D] [FILENAME] ...\N",
  168. PROGNAME);
  169. EXIT( 1 );
  170. BREAK;
  171. {$7d}
  172. {$7d} ELSE {$7b}
  173. FILENAMEuSED = true;
  174. IF (VERBOSE) {$7b}
  175. FPRINTF(STDERR, "%S: DECODING FILE \"%S\"\N",
  176. PROGNAME, ARGV[I]);
  177. {$7d}
  178. IF( (FIN = FOPEN(ARGV[I], "R")) == null) {$7b}
  179. FPRINTF(STDERR, "%S: ERROR OPENING \"%S\"\N",
  180. PROGNAME, ARGV[I]);
  181. {$7d} ELSE {$7b}
  182. READfILENAME = ARGV[I];
  183. READlINEnUM = 0;
  184. dECODEfILE( FIN );
  185. FCLOSE( FIN );
  186. {$7d}
  187. {$7d}
  188. I++;
  189. {$7d}
  190. IF (!FILENAMEuSED) {$7b}
  191. IF (VERBOSE) {$7b}
  192. FPRINTF(STDERR, "%S: DECODING FROM STANDARD INPUT\N",
  193. PROGNAME);
  194. {$7d}
  195. READfILENAME = "<STDIN>";
  196. READlINEnUM = 0;
  197. dECODEfILE( STDIN );
  198. {$7d}
  199. sAVEsTATUSfILE();
  200. {$7d}
  201.  
  202. /****************************************************************************/
  203. VOID dECODEfILE( FIN )
  204. file *FIN;
  205. {$7b}
  206. CHARFILENAME[max_filename];
  207. ulongSEGNUM;
  208. file   *FOUT;
  209. boolERR, ISeND;
  210. ulongHAVErEC;
  211.  
  212. WHILE (true) {$7b}
  213. SEGNUM = fINDhEADER( FIN, FILENAME );
  214. IF (SEGNUM == 0) RETURN;
  215. IF (VERBOSE) {$7b}
  216. FPRINTF(STDERR, "DECODING SEGMENT %LU OF FILE %S\N",
  217. SEGNUM, FILENAME);
  218. {$7d}
  219. FOUT = gETtEMPfILE( FILENAME, SEGNUM, &HAVErEC );
  220. IF (FOUT == null) CONTINUE;
  221. ERR = dECODEsEG( FIN, FOUT, SEGNUM, &ISeND );
  222. IF (ERR) {$7b}
  223. /* SHOULD DO SOMETHING TO INVALIDATE DATA HERE */
  224. FPRINTF(STDERR,
  225. "ERROR DECODING SEGMENT #%LU OF FILE \"%S\", IGNORING.\N", SEGNUM, FILENAME);
  226. {$7d} ELSE {$7b}
  227. HAVES[HAVErEC].ISeND = ISeND;
  228. {$7d}
  229. FCLOSE( FOUT );
  230. cHECKcOALESCE( HAVErEC );
  231. cHECKcOMPLETE( HAVErEC );
  232. IF (DEBUG) {$7b}
  233. FPRINTF(STDERR, "---fILE-sEGMENTS---\N");
  234. wRITEsTATUSdATA( STDERR );
  235. FPRINTF(STDERR, "--eND-OF-sEGMENTS--\N");
  236. {$7d}
  237. {$7d}
  238. {$7d}
  239.  
  240. /****************************************************************************/
  241. ulong fINDhEADER( FIN, FILENAME )
  242. file *FIN;
  243. CHAR *FILENAME;
  244. {$7b}
  245. CHARLINE[max_line];
  246. INTLEN, SCAN;
  247. ulongSEGNUM;
  248.  
  249. SEGNUM = 0;
  250. WHILE( SEGNUM == 0 ) {$7b}
  251. LEN = rEADlINE( FIN, LINE );
  252. IF (LEN == -1) RETURN( 0 );
  253. IF (LINE[0]=='-' && LINE[1]=='-' && LINE[2]=='B') {$7b}
  254. SCAN = SSCANF(LINE,"--BCODE-BEGIN %LU %S", &SEGNUM,
  255. FILENAME);
  256. IF (SCAN != 2 {$7c}{$7c} SEGNUM < 1) SEGNUM = 0;
  257. {$7d}
  258. {$7d}
  259. RETURN( SEGNUM );
  260. {$7d}
  261.  
  262. /****************************************************************************/
  263. INT rEADlINE( FIN, BUF )
  264. file *FIN;
  265. CHAR *BUF;
  266. {$7b}
  267. CHAR   *R;
  268. CHARJUNKLINE[max_line];
  269. INTLEN;
  270.  
  271. R = FGETS( BUF, max_line, FIN );
  272. IF (R==null) RETURN( -1 );
  273. LEN = STRLEN(BUF)-1;
  274. IF (BUF[LEN] == '\N') {$7b}
  275. BUF[LEN] = '\0';
  276. {$7d} ELSE {$7b}
  277. LEN++;
  278. DO {$7b}
  279. R = FGETS( JUNKLINE, max_line, FIN );
  280. {$7d} WHILE (R!=null && JUNKLINE[STRLEN(JUNKLINE)-1]!='\N');
  281. {$7d}
  282. READlINEnUM++;
  283. RETURN( LEN );
  284. {$7d}
  285.  
  286. /****************************************************************************/
  287. VOID bUILDdECODEtABLE()
  288. {$7b}
  289. INTI, V;
  290.  
  291. FOR (I=0; I<=255; I++) DECODEtABLE[I] = -1;
  292.  
  293. V = 0;
  294. FOR (I='a'; I<='z'; I++) DECODEtABLE[I] = V++;
  295. FOR (I='A'; I<='Z'; I++) DECODEtABLE[I] = V++;
  296. FOR (I='0'; I<='9'; I++) DECODEtABLE[I] = V++;
  297. DECODEtABLE['+'] = V++;
  298. DECODEtABLE['/'] = V++;
  299. DECODEtABLE['='] = 0;
  300. {$7d}
  301.  
  302. /****************************************************************************/
  303. bool dECODEsEG( FIN, FOUT, SEGNUM, ISeND )
  304. file *FIN;
  305. file *FOUT;
  306. ulong SEGNUM;
  307. bool *ISeND;
  308. {$7b}
  309. ulongSEGLEN, SEGCRC;
  310. ulongSTATnUM, STATlEN, STATcRC;
  311. INTLEN, SCAN, OFF;
  312. byteBUF[max_chunk+3];
  313. byteLINE[max_line];
  314.  
  315. SEGLEN = 0;
  316. SEGCRC = 0Xffffffff;
  317. WHILE( true ) {$7b}
  318. LEN = rEADlINE( FIN, (CHAR*)LINE );
  319. IF (LEN == -1) {$7b}
  320. FPRINTF(STDERR, "UNEXPECTED eof ENCOUNTERED\N");
  321. RETURN( true );
  322. {$7d}
  323. IF (LINE[0]=='-') BREAK;
  324. LEN = dECODElINE( LINE, LEN, BUF, &SEGCRC );
  325. IF (LEN == -1) RETURN( true );
  326. FWRITE( BUF, SIZEOF(byte), LEN, FOUT );
  327. SEGLEN += LEN;
  328. {$7d}
  329. SEGCRC ^= 0Xffffffff;
  330.  
  331. IF( STRNCMP("--BCODE-END ", LINE, 12)==0 ) {$7b}
  332. OFF = 12;
  333. *ISeND = true;
  334. {$7d} ELSE IF( STRNCMP("--BCODE-CONTINUED ", LINE, 18)==0 ) {$7b}
  335. OFF = 18;
  336. *ISeND = false;
  337. {$7d} ELSE {$7b}
  338. FPRINTF(STDERR, "INVALID CONTROL TOKEN\N");
  339. RETURN( true );
  340. {$7d}
  341. SCAN = SSCANF(&LINE[OFF], "%LU %LU %08LX", &STATnUM, &STATlEN,
  342. &STATcRC);
  343. IF (SCAN != 3) {$7b}
  344. FPRINTF(STDERR, "INVALID CONTROL LINE FORMAT\N");
  345. RETURN( true );
  346. {$7d}
  347. IF (STATnUM != SEGNUM) {$7b}
  348. FPRINTF(STDERR, "MISMATCHING SEGMENT NUMBERS\N");
  349. RETURN( true );
  350. {$7d}
  351. IF (STATlEN != SEGLEN) {$7b}
  352. FPRINTF(STDERR, "MISMATCHING SEGMENT LENGTHS\N");
  353. RETURN( true );
  354. {$7d}
  355. IF (STATcRC != SEGCRC) {$7b}
  356. FPRINTF(STDERR, "MISMATCHING crc VALUES\N");
  357. RETURN( true );
  358. {$7d}
  359. RETURN( false );
  360. {$7d}
  361.  
  362. /****************************************************************************/
  363. INT dECODElINE( LINE, LINElEN, BUF, TOTALcRC )
  364. byte LINE[];
  365. INT LINElEN;
  366. byte BUF[];
  367. ulong *TOTALcRC;
  368. {$7b}
  369. REGISTER INTC0,C1,C2,C3;
  370. REGISTER ulongCRC;
  371. REGISTER INTBUFPOS, LINEPOS, LEN;
  372.  
  373. CRC = *TOTALcRC;
  374. IF (LINElEN%4 != 0) {$7b}
  375. FPRINTF(STDERR, "INVALID BCODE LINE LENGTH\N");
  376. RETURN( -1 );
  377. {$7d}
  378. IF (LINElEN == 0) RETURN( 0 );
  379. FOR (BUFPOS = 0,LINEPOS = 0; LINEPOS < LINElEN; BUFPOS+=3,LINEPOS+=4) {$7b}
  380. C0 = DECODEtABLE[ LINE[LINEPOS  ] ];
  381. C1 = DECODEtABLE[ LINE[LINEPOS+1] ];
  382. C2 = DECODEtABLE[ LINE[LINEPOS+2] ];
  383. C3 = DECODEtABLE[ LINE[LINEPOS+3] ];
  384. IF (C0==-1 {$7c}{$7c} C1==-1 {$7c}{$7c} C2==-1 {$7c}{$7c} C3==-1) {$7b}
  385. FPRINTF(STDERR, "INVALID CHARACTER IN BCODE DATA\N");
  386. RETURN( -1 );
  387. {$7d}
  388. BUF[BUFPOS  ] = (C0<<2) {$7c} ((C1&0X30)>>4);
  389. BUF[BUFPOS+1] = ((C1&0X0f)<<4) {$7c} ((C2&0X3c)>>2);
  390. BUF[BUFPOS+2] = ((C2&0X03)<<6) {$7c} C3;
  391. {$7d}
  392.  
  393. /* FIX NON-INTEGRAL-LENGTH (LAST) LINE */
  394. IF (LINE[LINElEN-1] == '=') BUFPOS--;
  395. IF (LINE[LINElEN-2] == '=') BUFPOS--;
  396. LEN = BUFPOS;
  397.  
  398. /* TAKE CRC OF BINARY DATA */
  399. FOR( BUFPOS=0; BUFPOS < LEN; BUFPOS++ ) {$7b}
  400. CRC = ((CRC>>8) & 0X00ffffff)
  401. ^ CRCtABLE[ (CRC^BUF[BUFPOS]) & 0Xff];
  402. {$7d}
  403. *TOTALcRC = CRC;
  404. RETURN( LEN );
  405. {$7d}
  406.  
  407. /****************************************************************************/
  408. VOID lOADsTATUSfILE()
  409. {$7b}
  410. CHARLINE[max_line];
  411. CHARFILENAME[max_filename];
  412. file   *FIN;
  413. INTSCAN;
  414. haverec*H;
  415. CHARINTERPRET[4];
  416.  
  417. HAVEcOUNT = 0;
  418. STATUSfILEeXISTS = false;
  419. NEXTtEMPnAME = 1;
  420. SPRINTF(FILENAME, "%S0bc-stat", TEMPpREFIX);
  421. IF( (FIN = FOPEN(FILENAME, "R")) == null) RETURN;
  422. STATUSfILEeXISTS = true;
  423. WHILE ( rEADlINE( FIN, LINE ) != -1 ) {$7b}
  424. H = & HAVES[HAVEcOUNT];
  425. SCAN = SSCANF(LINE, "%05LU-%05LU  %C%C%C  0bc%05LX  %S",
  426. &H->FROMsEG, &H->TOsEG, &INTERPRET[0], &INTERPRET[1],
  427. &INTERPRET[2], &H->TEMPfILEnAME, FILENAME);
  428. IF (SCAN != 7) {$7b}
  429. FPRINTF(STDERR, "bAD sTATUS lINE: %S\N", LINE);
  430. {$7d} ELSE {$7b}
  431. H->ISeND = (INTERPRET[0] == 'E');
  432. H->FILENAME = (CHAR*)MALLOC( STRLEN(FILENAME)+1 );
  433. STRCPY( H->FILENAME, FILENAME );
  434. HAVEcOUNT++;
  435. IF (HAVEcOUNT>=max_have) {$7b}
  436. FPRINTF(STDERR,
  437. "TOO MANY STATUS FRAGMENTS, fatal\N");
  438. EXIT( 1 );
  439. {$7d}
  440. {$7d}
  441. {$7d}
  442. FCLOSE( FIN );
  443. {$7d}
  444.  
  445. /****************************************************************************/
  446. VOID sAVEsTATUSfILE()
  447. {$7b}
  448. CHARFILENAME[max_filename];
  449. file   *FOUT;
  450. INTERR;
  451.  
  452. SPRINTF(FILENAME, "%S0bc-stat", TEMPpREFIX);
  453. IF (HAVEcOUNT == 0) {$7b}
  454. IF (STATUSfILEeXISTS) {$7b}
  455. ERR = REMOVE( FILENAME );
  456. IF (ERR) {$7b}
  457. FPRINTF(STDERR,"CANNOT REMOVE %S\N", FILENAME);
  458. {$7d}
  459. {$7d}
  460. RETURN;
  461. {$7d}
  462. IF( (FOUT = FOPEN(FILENAME, "W")) == null) {$7b}
  463. FPRINTF(STDERR, "CANNOT OPEN %S FOR SAVING STATUS\N",FILENAME);
  464. RETURN;
  465. {$7d}
  466. wRITEsTATUSdATA( FOUT );
  467. FCLOSE( FOUT );
  468. {$7d}
  469.  
  470. /****************************************************************************/
  471. VOID wRITEsTATUSdATA( FOUT )
  472. file *FOUT;
  473. {$7b}
  474. ulongI;
  475. haverec *H;
  476. CHAR    INTERPRET[4];
  477.  
  478. FOR (I=0; I<HAVEcOUNT; I++) {$7b}
  479. H = & HAVES[I];
  480. IF (H->ISeND) {$7b}
  481. STRCPY( INTERPRET, "END" );
  482. {$7d} ELSE {$7b}
  483. IF (H->FROMsEG == 1) {$7b}
  484. STRCPY( INTERPRET, "BEG" );
  485. {$7d} ELSE {$7b}
  486. STRCPY( INTERPRET, "MID" );
  487. {$7d}
  488. {$7d}
  489. FPRINTF(FOUT, "%05LU-%05LU  %S  0bc%05LU  %S\N", H->FROMsEG,
  490. H->TOsEG, INTERPRET, H->TEMPfILEnAME, H->FILENAME);
  491. {$7d}
  492. {$7d}
  493.  
  494. /****************************************************************************/
  495. file *gETtEMPfILE( FILENAME, SEGNUM, HAVErEC )
  496. CHAR *FILENAME;
  497. ulong SEGNUM;
  498. ulong *HAVErEC;
  499. {$7b}
  500. haverec *H;
  501. ulongI, J, REC, TEMPnAME;
  502. CHARTEMPNAME[max_filename];
  503. CHARTEMPMODE[4];
  504. boolAPPEND;
  505. file   *FOUT;
  506.  
  507. /* SEARCH TO APPEND TO EXISTING FILE */
  508. APPEND = false;
  509. FOR (I=0; I<HAVEcOUNT; I++) {$7b}
  510. H = & HAVES[I];
  511. IF (STRCMP(FILENAME, H->FILENAME)==0) {$7b}
  512. IF (H->FROMsEG<=SEGNUM && SEGNUM<=H->TOsEG) {$7b}
  513. FPRINTF(STDERR,
  514. "IGNORING DUPLICATE SEGMENT %LU OF \"%S\"\N",
  515. SEGNUM, FILENAME);
  516. RETURN( null );
  517. {$7d}
  518. IF (SEGNUM == H->TOsEG + 1) {$7b}
  519. /* APPEND */
  520. TEMPnAME = H->TEMPfILEnAME;
  521. STRCPY( TEMPMODE, "AB" );
  522. APPEND = true;
  523. H->TOsEG = SEGNUM;
  524. H->ISeND = false;
  525. REC = I;
  526. BREAK;
  527. {$7d}
  528. {$7d}
  529. {$7d}
  530.  
  531. IF (!APPEND) {$7b}
  532. /* FIND NEW TEMPNAME */
  533. FOR (I=0; I<100000; I++) {$7b}
  534. TEMPnAME = NEXTtEMPnAME;
  535. NEXTtEMPnAME = (NEXTtEMPnAME + 1) % 100000;
  536. FOR (J=0; J<HAVEcOUNT; J++) {$7b}
  537. IF (HAVES[J].TEMPfILEnAME == TEMPnAME) {$7b}
  538. J = -1;
  539. BREAK;
  540. {$7d}
  541. {$7d}
  542. IF (J != -1) BREAK;
  543. IF (I==100000-1) {$7b}
  544. FPRINTF(STDERR, "CANNOT FIND TEMP NAME!!!\N");
  545. RETURN( null );
  546. {$7d}
  547. {$7d}
  548.  
  549. /* CREATE NEW HAVE RECORD */
  550. REC = iNSERThAVErEC( SEGNUM, TEMPnAME, FILENAME );
  551. STRCPY(TEMPMODE, "WB");
  552. {$7d}
  553.  
  554. /* OPEN THE TEMPORARY FILE */
  555. gETtEMPnAMEsTR( TEMPnAME, TEMPNAME );
  556. IF( (FOUT = FOPEN(TEMPNAME, TEMPMODE)) == null) {$7b}
  557. FPRINTF(STDERR, "%S: ERROR OPENING \"%S\" FOR WRITE, fatal!\N",
  558. PROGNAME, FILENAME);
  559. EXIT( 1 );
  560. {$7d}
  561. *HAVErEC = REC;
  562. RETURN( FOUT );
  563. {$7d}
  564.  
  565. /****************************************************************************/
  566. ulong iNSERThAVErEC( SEGNUM, TEMPnAME, FILENAME )
  567. ulong SEGNUM;
  568. ulong TEMPnAME;
  569. CHAR *FILENAME;
  570. {$7b}
  571. ulongREC;
  572. LONGI;
  573. haverec*H;
  574. INTCMP;
  575.  
  576. REC = HAVEcOUNT;
  577. HAVEcOUNT++;
  578. IF (HAVEcOUNT >= max_have) {$7b}
  579. HAVEcOUNT--;
  580. FPRINTF(STDERR, "INPUT DATA TOO FRAGMENTED; fatal!\N");
  581. EXIT( 1 );
  582. {$7d}
  583.  
  584. /* INSERTION SORT NEW ENTRY INTO PLACE */
  585. FOR (I=REC-1; I>=0; I--) {$7b}
  586. CMP = STRCMP(FILENAME, HAVES[I].FILENAME);
  587. IF (CMP > 0) {$7b}
  588. BREAK;
  589. {$7d} ELSE IF (CMP==0 && SEGNUM>HAVES[I].FROMsEG) {$7b}
  590. BREAK;
  591. {$7d}
  592. HAVES[I+1] = HAVES[I];
  593. {$7d}
  594.  
  595. /* INITIALIZE NEW RECORD */
  596. REC = I+1;
  597. H = & HAVES[REC];
  598. H->FROMsEG = SEGNUM;
  599. H->TOsEG = SEGNUM;
  600. H->ISeND = false;
  601. H->TEMPfILEnAME = TEMPnAME;
  602. H->FILENAME = (CHAR*)MALLOC( STRLEN(FILENAME)+1 );
  603. STRCPY( H->FILENAME, FILENAME );
  604. RETURN( REC );
  605. {$7d}
  606.  
  607. /****************************************************************************/
  608. VOID cHECKcOALESCE( HAVErEC )
  609. ulong HAVErEC;
  610. {$7b}
  611. haverec *P, *Q;
  612. CHARTEMPNAME[max_filename];
  613. INTERR;
  614. file   *FIN, *FOUT;
  615. ulongBYTES;
  616.  
  617. IF (HAVErEC >= HAVEcOUNT-1) RETURN;
  618. P = & HAVES[HAVErEC];
  619. Q = & HAVES[HAVErEC+1];
  620. IF (STRCMP(P->FILENAME, Q->FILENAME)!=0 {$7c}{$7c} P->TOsEG+1 != Q->FROMsEG) {$7b}
  621. RETURN;
  622. {$7d}
  623.  
  624. /* COALESCE */
  625. IF (DEBUG) {$7b}
  626. FPRINTF(STDERR,
  627. "cOALESCING SEGS %LU-%LU AND SEGS %LU-%LU OF FILE %S\N",
  628. P->FROMsEG, P->TOsEG, Q->FROMsEG, Q->TOsEG, P->FILENAME);
  629. {$7d}
  630.  
  631. /* COPY FILE CONTENTS */
  632. gETtEMPnAMEsTR( Q->TEMPfILEnAME, TEMPNAME );
  633. IF( (FIN = FOPEN(TEMPNAME, "RB")) == null) {$7b}
  634. FPRINTF(STDERR, "%S: ERROR OPENING \"%S\", fatal\N",
  635. PROGNAME, TEMPNAME);
  636. EXIT( 1 );
  637. {$7d}
  638. gETtEMPnAMEsTR( P->TEMPfILEnAME, TEMPNAME );
  639. IF( (FOUT = FOPEN(TEMPNAME, "AB")) == null) {$7b}
  640. FPRINTF(STDERR, "%S: ERROR OPENING \"%S\", fatal\N",
  641. PROGNAME, TEMPNAME);
  642. EXIT( 1 );
  643. {$7d}
  644. WHILE ( (BYTES=FREAD( COPYbUF, SIZEOF(byte), copy_buf_size, FIN)) >0) {$7b}
  645. FWRITE( COPYbUF, SIZEOF(byte), BYTES, FOUT );
  646. {$7d}
  647. FCLOSE( FOUT );
  648. FCLOSE( FIN );
  649.  
  650.  
  651. /* REMOVE OLD RECORD AND TEMP FILE */
  652. P->TOsEG = Q->TOsEG;
  653. P->ISeND = Q->ISeND;
  654. gETtEMPnAMEsTR( Q->TEMPfILEnAME, TEMPNAME );
  655. ERR = REMOVE( TEMPNAME );
  656. IF (ERR) {$7b}
  657. FPRINTF(STDERR, "CANNOT REMOVE %S, CONTINUING.\N", TEMPNAME);
  658. {$7d}
  659. rEMOVEhAVErEC( HAVErEC+1 );
  660. {$7d}
  661.  
  662. /****************************************************************************/
  663. VOID cHECKcOMPLETE( HAVErEC )
  664. ulong HAVErEC;
  665. {$7b}
  666. CHARTEMPNAME[max_filename];
  667. INTERR;
  668. haverec*H;
  669.  
  670. H = & HAVES[HAVErEC];
  671. IF (!H->ISeND {$7c}{$7c} H->FROMsEG!=1) RETURN;
  672.  
  673. gETtEMPnAMEsTR( H->TEMPfILEnAME, TEMPNAME );
  674. ERR = RENAME( TEMPNAME, H->FILENAME );
  675. IF (ERR) {$7b}
  676. FPRINTF(STDERR, "CANNOT RENAME %S TO %S, CONTINUING.",
  677. TEMPNAME, H->FILENAME );
  678. {$7d}
  679. IF (INFORMATIVE) {$7b}
  680. FPRINTF(STDERR,
  681. "i HAVE PIECED TOGETHER ALL SEGMENTS OF \"%S\"\N",
  682. H->FILENAME );
  683. {$7d}
  684. rEMOVEhAVErEC( HAVErEC );
  685. {$7d}
  686.  
  687. /****************************************************************************/
  688. VOID rEMOVEhAVErEC( REC )
  689. ulong REC;
  690. {$7b}
  691. LONGI;
  692.  
  693. /* FREE DYNAMIC MEMORY OF FILENAME */
  694. FREE( HAVES[REC].FILENAME );
  695.  
  696. /* PULL ALL HIGHER ENTRIES BACK ONE POSITION */
  697. FOR (I=REC; I<HAVEcOUNT-1; I++) {$7b}
  698. HAVES[I] = HAVES[I+1];
  699. {$7d}
  700.  
  701. HAVEcOUNT--;
  702. {$7d}
  703.  
  704. /****************************************************************************/
  705. VOID gETtEMPnAMEsTR( TEMPnAME, S )
  706. ulong TEMPnAME;
  707. CHAR *S;
  708. {$7b}
  709. SPRINTF(S, "%S0bc%05LU", TEMPpREFIX, TEMPnAME);
  710. {$7d}
  711.  
  712. #IFDEF no_rename
  713. /****************************************************************************/
  714. INT RENAME( OLDNAME, NEWNAME )
  715. CHAR *OLDNAME, *NEWNAME;
  716. {$7b}
  717. IF ( LINK( OLDNAME, NEWNAME ))
  718. RETURN( -1 );
  719. ELSE
  720. RETURN( UNLINK( OLDNAME ));
  721. {$7d}
  722. #ENDIF
  723.