home *** CD-ROM | disk | FTP | other *** search
- /* unbcode: BCODE DECODER VERSION 1.03-KR BY cRAIG bRUCE 07-oCT-93, 09-nOV-93.
- **
- ** aDDED CODE FOR REMOVE AND RENAME. tO ACTIVATE, ADD -dno_remove AND/OR
- ** -dno_rename AS NEEDED. 15-oCT-93 (BJS)
- **
- ** crc-32 CODE BASED ON "fILE vERIFICATION uSING crc" BY mARK r. nELSON IN
- ** dR. dOBB'S jOURNAL, mAY 1992, PP. 64-67. nOTE THAT crc-32 VALUES are THE
- ** SAME AS IN zmodem AND pkzip.
- */
-
- #INCLUDE <STDIO.H>
- #INCLUDE <STDLIB.H>
- #INCLUDE <STRING.H>
-
- #DEFINE version"1.03-KR"
- #DEFINE max_chunk64
- #DEFINE max_line85
- #DEFINE max_filename85
- #DEFINE max_have1000
- #DEFINE max_tempname20
- #DEFINE copy_buf_size4096
-
- #IFDEF no_remove
- #DEFINE REMOVE(X) UNLINK(X)
- #ENDIF
-
- TYPEDEF UNSIGNED CHAR byte;
- TYPEDEF CHAR sbyte;
- TYPEDEF UNSIGNED LONG ulong;
- TYPEDEF INT bool;
- #DEFINE true1
- #DEFINE false0
-
- TYPEDEF STRUCT {$7b}
- ulongFROMsEG;
- ulongTOsEG;
- boolISeND;
- ulongTEMPfILEnAME;
- CHAR *FILENAME;
- {$7d} haverec;
-
- VOIDMAIN();
- VOIDdECODEfILE();
- ulongfINDhEADER();
- VOIDlOADsTATUSfILE();
- VOIDsAVEsTATUSfILE();
- VOIDwRITEsTATUSdATA();
- INTrEADlINE();
- VOIDbUILDdECODEtABLE();
- booldECODEsEG();
- INTdECODElINE();
- file *gETtEMPfILE();
- ulongiNSERThAVErEC();
- VOIDcHECKcOALESCE();
- VOIDcHECKcOMPLETE();
- VOIDrEMOVEhAVErEC();
- VOIDgETtEMPnAMEsTR();
-
- CHAR *PROGNAME;
- boolINFORMATIVE;
- boolVERBOSE;
- boolDEBUG;
- CHAR *READfILENAME;
- ulongREADlINEnUM;
-
- haverecHAVES[max_have];
- INTHAVEcOUNT;
- boolSTATUSfILEeXISTS;
- ulongNEXTtEMPnAME;
- CHARTEMPpREFIX[max_filename];
- byteCOPYbUF[copy_buf_size];
- sbyteDECODEtABLE[ 256 ];
- ulongCRCtABLE[256] = {$7b}
- 0X00000000, 0X77073096, 0Xee0e612c, 0X990951ba, 0X076dc419, 0X706af48f,
- 0Xe963a535, 0X9e6495a3, 0X0edb8832, 0X79dcb8a4, 0Xe0d5e91e, 0X97d2d988,
- 0X09b64c2b, 0X7eb17cbd, 0Xe7b82d07, 0X90bf1d91, 0X1db71064, 0X6ab020f2,
- 0Xf3b97148, 0X84be41de, 0X1adad47d, 0X6ddde4eb, 0Xf4d4b551, 0X83d385c7,
- 0X136c9856, 0X646ba8c0, 0Xfd62f97a, 0X8a65c9ec, 0X14015c4f, 0X63066cd9,
- 0Xfa0f3d63, 0X8d080df5, 0X3b6e20c8, 0X4c69105e, 0Xd56041e4, 0Xa2677172,
- 0X3c03e4d1, 0X4b04d447, 0Xd20d85fd, 0Xa50ab56b, 0X35b5a8fa, 0X42b2986c,
- 0Xdbbbc9d6, 0Xacbcf940, 0X32d86ce3, 0X45df5c75, 0Xdcd60dcf, 0Xabd13d59,
- 0X26d930ac, 0X51de003a, 0Xc8d75180, 0Xbfd06116, 0X21b4f4b5, 0X56b3c423,
- 0Xcfba9599, 0Xb8bda50f, 0X2802b89e, 0X5f058808, 0Xc60cd9b2, 0Xb10be924,
- 0X2f6f7c87, 0X58684c11, 0Xc1611dab, 0Xb6662d3d, 0X76dc4190, 0X01db7106,
- 0X98d220bc, 0Xefd5102a, 0X71b18589, 0X06b6b51f, 0X9fbfe4a5, 0Xe8b8d433,
- 0X7807c9a2, 0X0f00f934, 0X9609a88e, 0Xe10e9818, 0X7f6a0dbb, 0X086d3d2d,
- 0X91646c97, 0Xe6635c01, 0X6b6b51f4, 0X1c6c6162, 0X856530d8, 0Xf262004e,
- 0X6c0695ed, 0X1b01a57b, 0X8208f4c1, 0Xf50fc457, 0X65b0d9c6, 0X12b7e950,
- 0X8bbeb8ea, 0Xfcb9887c, 0X62dd1ddf, 0X15da2d49, 0X8cd37cf3, 0Xfbd44c65,
- 0X4db26158, 0X3ab551ce, 0Xa3bc0074, 0Xd4bb30e2, 0X4adfa541, 0X3dd895d7,
- 0Xa4d1c46d, 0Xd3d6f4fb, 0X4369e96a, 0X346ed9fc, 0Xad678846, 0Xda60b8d0,
- 0X44042d73, 0X33031de5, 0Xaa0a4c5f, 0Xdd0d7cc9, 0X5005713c, 0X270241aa,
- 0Xbe0b1010, 0Xc90c2086, 0X5768b525, 0X206f85b3, 0Xb966d409, 0Xce61e49f,
- 0X5edef90e, 0X29d9c998, 0Xb0d09822, 0Xc7d7a8b4, 0X59b33d17, 0X2eb40d81,
- 0Xb7bd5c3b, 0Xc0ba6cad, 0Xedb88320, 0X9abfb3b6, 0X03b6e20c, 0X74b1d29a,
- 0Xead54739, 0X9dd277af, 0X04db2615, 0X73dc1683, 0Xe3630b12, 0X94643b84,
- 0X0d6d6a3e, 0X7a6a5aa8, 0Xe40ecf0b, 0X9309ff9d, 0X0a00ae27, 0X7d079eb1,
- 0Xf00f9344, 0X8708a3d2, 0X1e01f268, 0X6906c2fe, 0Xf762575d, 0X806567cb,
- 0X196c3671, 0X6e6b06e7, 0Xfed41b76, 0X89d32be0, 0X10da7a5a, 0X67dd4acc,
- 0Xf9b9df6f, 0X8ebeeff9, 0X17b7be43, 0X60b08ed5, 0Xd6d6a3e8, 0Xa1d1937e,
- 0X38d8c2c4, 0X4fdff252, 0Xd1bb67f1, 0Xa6bc5767, 0X3fb506dd, 0X48b2364b,
- 0Xd80d2bda, 0Xaf0a1b4c, 0X36034af6, 0X41047a60, 0Xdf60efc3, 0Xa867df55,
- 0X316e8eef, 0X4669be79, 0Xcb61b38c, 0Xbc66831a, 0X256fd2a0, 0X5268e236,
- 0Xcc0c7795, 0Xbb0b4703, 0X220216b9, 0X5505262f, 0Xc5ba3bbe, 0Xb2bd0b28,
- 0X2bb45a92, 0X5cb36a04, 0Xc2d7ffa7, 0Xb5d0cf31, 0X2cd99e8b, 0X5bdeae1d,
- 0X9b64c2b0, 0Xec63f226, 0X756aa39c, 0X026d930a, 0X9c0906a9, 0Xeb0e363f,
- 0X72076785, 0X05005713, 0X95bf4a82, 0Xe2b87a14, 0X7bb12bae, 0X0cb61b38,
- 0X92d28e9b, 0Xe5d5be0d, 0X7cdcefb7, 0X0bdbdf21, 0X86d3d2d4, 0Xf1d4e242,
- 0X68ddb3f8, 0X1fda836e, 0X81be16cd, 0Xf6b9265b, 0X6fb077e1, 0X18b74777,
- 0X88085ae6, 0Xff0f6a70, 0X66063bca, 0X11010b5c, 0X8f659eff, 0Xf862ae69,
- 0X616bffd3, 0X166ccf45, 0Xa00ae278, 0Xd70dd2ee, 0X4e048354, 0X3903b3c2,
- 0Xa7672661, 0Xd06016f7, 0X4969474d, 0X3e6e77db, 0Xaed16a4a, 0Xd9d65adc,
- 0X40df0b66, 0X37d83bf0, 0Xa9bcae53, 0Xdebb9ec5, 0X47b2cf7f, 0X30b5ffe9,
- 0Xbdbdf21c, 0Xcabac28a, 0X53b39330, 0X24b4a3a6, 0Xbad03605, 0Xcdd70693,
- 0X54de5729, 0X23d967bf, 0Xb3667a2e, 0Xc4614ab8, 0X5d681b02, 0X2a6f2b94,
- 0Xb40bbe37, 0Xc30c8ea1, 0X5a05df1b, 0X2d02ef8d
- {$7d};
-
- /****************************************************************************/
- VOID MAIN( ARGC, ARGV )
- INTARGC;
- CHAR *ARGV[];
- {$7b}
- file *FIN;
- INTI;
- boolFILENAMEuSED;
-
- PROGNAME = ARGV[0];
- FILENAMEuSED = false;
- INFORMATIVE = false;
- VERBOSE = false;
- DEBUG = false;
- STRCPY( TEMPpREFIX, "" );
- bUILDdECODEtABLE();
- lOADsTATUSfILE();
-
- I = 1;
- WHILE (I<ARGC) {$7b}
- IF (ARGV[I][0] == '-') {$7b}
- SWITCH (ARGV[I][1]) {$7b}
- CASE 'I':
- INFORMATIVE = true;
- BREAK;
- CASE 'D':
- VERBOSE = true;
- INFORMATIVE = true;
- DEBUG = true;
- FPRINTF(STDERR, "UNBCODE VERSION %S\N",
- version );
- FPRINTF(STDERR, "DEBUGGING MODE ACTIVATED\N");
- FPRINTF(STDERR,
- "---cURRENT-fILE-sEGMENTS---\N");
- wRITEsTATUSdATA( STDERR );
- FPRINTF(STDERR,
- "--eND-OF-cURRENT-sEGMENTS--\N");
- BREAK;
- CASE 'V':
- VERBOSE = true;
- INFORMATIVE = true;
- FPRINTF(STDERR, "UNBCODE VERSION %S\N",
- version);
- BREAK;
- DEFAULT:
- FPRINTF(STDERR, "%S: UNRECOGNIZED OPTION\N",
- PROGNAME);
- FPRINTF(STDERR,
- "USAGE: %S [-V] [-I] [-D] [FILENAME] ...\N",
- PROGNAME);
- EXIT( 1 );
- BREAK;
- {$7d}
- {$7d} ELSE {$7b}
- FILENAMEuSED = true;
- IF (VERBOSE) {$7b}
- FPRINTF(STDERR, "%S: DECODING FILE \"%S\"\N",
- PROGNAME, ARGV[I]);
- {$7d}
- IF( (FIN = FOPEN(ARGV[I], "R")) == null) {$7b}
- FPRINTF(STDERR, "%S: ERROR OPENING \"%S\"\N",
- PROGNAME, ARGV[I]);
- {$7d} ELSE {$7b}
- READfILENAME = ARGV[I];
- READlINEnUM = 0;
- dECODEfILE( FIN );
- FCLOSE( FIN );
- {$7d}
- {$7d}
- I++;
- {$7d}
- IF (!FILENAMEuSED) {$7b}
- IF (VERBOSE) {$7b}
- FPRINTF(STDERR, "%S: DECODING FROM STANDARD INPUT\N",
- PROGNAME);
- {$7d}
- READfILENAME = "<STDIN>";
- READlINEnUM = 0;
- dECODEfILE( STDIN );
- {$7d}
- sAVEsTATUSfILE();
- {$7d}
-
- /****************************************************************************/
- VOID dECODEfILE( FIN )
- file *FIN;
- {$7b}
- CHARFILENAME[max_filename];
- ulongSEGNUM;
- file *FOUT;
- boolERR, ISeND;
- ulongHAVErEC;
-
- WHILE (true) {$7b}
- SEGNUM = fINDhEADER( FIN, FILENAME );
- IF (SEGNUM == 0) RETURN;
- IF (VERBOSE) {$7b}
- FPRINTF(STDERR, "DECODING SEGMENT %LU OF FILE %S\N",
- SEGNUM, FILENAME);
- {$7d}
- FOUT = gETtEMPfILE( FILENAME, SEGNUM, &HAVErEC );
- IF (FOUT == null) CONTINUE;
- ERR = dECODEsEG( FIN, FOUT, SEGNUM, &ISeND );
- IF (ERR) {$7b}
- /* SHOULD DO SOMETHING TO INVALIDATE DATA HERE */
- FPRINTF(STDERR,
- "ERROR DECODING SEGMENT #%LU OF FILE \"%S\", IGNORING.\N", SEGNUM, FILENAME);
- {$7d} ELSE {$7b}
- HAVES[HAVErEC].ISeND = ISeND;
- {$7d}
- FCLOSE( FOUT );
- cHECKcOALESCE( HAVErEC );
- cHECKcOMPLETE( HAVErEC );
- IF (DEBUG) {$7b}
- FPRINTF(STDERR, "---fILE-sEGMENTS---\N");
- wRITEsTATUSdATA( STDERR );
- FPRINTF(STDERR, "--eND-OF-sEGMENTS--\N");
- {$7d}
- {$7d}
- {$7d}
-
- /****************************************************************************/
- ulong fINDhEADER( FIN, FILENAME )
- file *FIN;
- CHAR *FILENAME;
- {$7b}
- CHARLINE[max_line];
- INTLEN, SCAN;
- ulongSEGNUM;
-
- SEGNUM = 0;
- WHILE( SEGNUM == 0 ) {$7b}
- LEN = rEADlINE( FIN, LINE );
- IF (LEN == -1) RETURN( 0 );
- IF (LINE[0]=='-' && LINE[1]=='-' && LINE[2]=='B') {$7b}
- SCAN = SSCANF(LINE,"--BCODE-BEGIN %LU %S", &SEGNUM,
- FILENAME);
- IF (SCAN != 2 {$7c}{$7c} SEGNUM < 1) SEGNUM = 0;
- {$7d}
- {$7d}
- RETURN( SEGNUM );
- {$7d}
-
- /****************************************************************************/
- INT rEADlINE( FIN, BUF )
- file *FIN;
- CHAR *BUF;
- {$7b}
- CHAR *R;
- CHARJUNKLINE[max_line];
- INTLEN;
-
- R = FGETS( BUF, max_line, FIN );
- IF (R==null) RETURN( -1 );
- LEN = STRLEN(BUF)-1;
- IF (BUF[LEN] == '\N') {$7b}
- BUF[LEN] = '\0';
- {$7d} ELSE {$7b}
- LEN++;
- DO {$7b}
- R = FGETS( JUNKLINE, max_line, FIN );
- {$7d} WHILE (R!=null && JUNKLINE[STRLEN(JUNKLINE)-1]!='\N');
- {$7d}
- READlINEnUM++;
- RETURN( LEN );
- {$7d}
-
- /****************************************************************************/
- VOID bUILDdECODEtABLE()
- {$7b}
- INTI, V;
-
- FOR (I=0; I<=255; I++) DECODEtABLE[I] = -1;
-
- V = 0;
- FOR (I='a'; I<='z'; I++) DECODEtABLE[I] = V++;
- FOR (I='A'; I<='Z'; I++) DECODEtABLE[I] = V++;
- FOR (I='0'; I<='9'; I++) DECODEtABLE[I] = V++;
- DECODEtABLE['+'] = V++;
- DECODEtABLE['/'] = V++;
- DECODEtABLE['='] = 0;
- {$7d}
-
- /****************************************************************************/
- bool dECODEsEG( FIN, FOUT, SEGNUM, ISeND )
- file *FIN;
- file *FOUT;
- ulong SEGNUM;
- bool *ISeND;
- {$7b}
- ulongSEGLEN, SEGCRC;
- ulongSTATnUM, STATlEN, STATcRC;
- INTLEN, SCAN, OFF;
- byteBUF[max_chunk+3];
- byteLINE[max_line];
-
- SEGLEN = 0;
- SEGCRC = 0Xffffffff;
- WHILE( true ) {$7b}
- LEN = rEADlINE( FIN, (CHAR*)LINE );
- IF (LEN == -1) {$7b}
- FPRINTF(STDERR, "UNEXPECTED eof ENCOUNTERED\N");
- RETURN( true );
- {$7d}
- IF (LINE[0]=='-') BREAK;
- LEN = dECODElINE( LINE, LEN, BUF, &SEGCRC );
- IF (LEN == -1) RETURN( true );
- FWRITE( BUF, SIZEOF(byte), LEN, FOUT );
- SEGLEN += LEN;
- {$7d}
- SEGCRC ^= 0Xffffffff;
-
- IF( STRNCMP("--BCODE-END ", LINE, 12)==0 ) {$7b}
- OFF = 12;
- *ISeND = true;
- {$7d} ELSE IF( STRNCMP("--BCODE-CONTINUED ", LINE, 18)==0 ) {$7b}
- OFF = 18;
- *ISeND = false;
- {$7d} ELSE {$7b}
- FPRINTF(STDERR, "INVALID CONTROL TOKEN\N");
- RETURN( true );
- {$7d}
- SCAN = SSCANF(&LINE[OFF], "%LU %LU %08LX", &STATnUM, &STATlEN,
- &STATcRC);
- IF (SCAN != 3) {$7b}
- FPRINTF(STDERR, "INVALID CONTROL LINE FORMAT\N");
- RETURN( true );
- {$7d}
- IF (STATnUM != SEGNUM) {$7b}
- FPRINTF(STDERR, "MISMATCHING SEGMENT NUMBERS\N");
- RETURN( true );
- {$7d}
- IF (STATlEN != SEGLEN) {$7b}
- FPRINTF(STDERR, "MISMATCHING SEGMENT LENGTHS\N");
- RETURN( true );
- {$7d}
- IF (STATcRC != SEGCRC) {$7b}
- FPRINTF(STDERR, "MISMATCHING crc VALUES\N");
- RETURN( true );
- {$7d}
- RETURN( false );
- {$7d}
-
- /****************************************************************************/
- INT dECODElINE( LINE, LINElEN, BUF, TOTALcRC )
- byte LINE[];
- INT LINElEN;
- byte BUF[];
- ulong *TOTALcRC;
- {$7b}
- REGISTER INTC0,C1,C2,C3;
- REGISTER ulongCRC;
- REGISTER INTBUFPOS, LINEPOS, LEN;
-
- CRC = *TOTALcRC;
- IF (LINElEN%4 != 0) {$7b}
- FPRINTF(STDERR, "INVALID BCODE LINE LENGTH\N");
- RETURN( -1 );
- {$7d}
- IF (LINElEN == 0) RETURN( 0 );
- FOR (BUFPOS = 0,LINEPOS = 0; LINEPOS < LINElEN; BUFPOS+=3,LINEPOS+=4) {$7b}
- C0 = DECODEtABLE[ LINE[LINEPOS ] ];
- C1 = DECODEtABLE[ LINE[LINEPOS+1] ];
- C2 = DECODEtABLE[ LINE[LINEPOS+2] ];
- C3 = DECODEtABLE[ LINE[LINEPOS+3] ];
- IF (C0==-1 {$7c}{$7c} C1==-1 {$7c}{$7c} C2==-1 {$7c}{$7c} C3==-1) {$7b}
- FPRINTF(STDERR, "INVALID CHARACTER IN BCODE DATA\N");
- RETURN( -1 );
- {$7d}
- BUF[BUFPOS ] = (C0<<2) {$7c} ((C1&0X30)>>4);
- BUF[BUFPOS+1] = ((C1&0X0f)<<4) {$7c} ((C2&0X3c)>>2);
- BUF[BUFPOS+2] = ((C2&0X03)<<6) {$7c} C3;
- {$7d}
-
- /* FIX NON-INTEGRAL-LENGTH (LAST) LINE */
- IF (LINE[LINElEN-1] == '=') BUFPOS--;
- IF (LINE[LINElEN-2] == '=') BUFPOS--;
- LEN = BUFPOS;
-
- /* TAKE CRC OF BINARY DATA */
- FOR( BUFPOS=0; BUFPOS < LEN; BUFPOS++ ) {$7b}
- CRC = ((CRC>>8) & 0X00ffffff)
- ^ CRCtABLE[ (CRC^BUF[BUFPOS]) & 0Xff];
- {$7d}
- *TOTALcRC = CRC;
- RETURN( LEN );
- {$7d}
-
- /****************************************************************************/
- VOID lOADsTATUSfILE()
- {$7b}
- CHARLINE[max_line];
- CHARFILENAME[max_filename];
- file *FIN;
- INTSCAN;
- haverec*H;
- CHARINTERPRET[4];
-
- HAVEcOUNT = 0;
- STATUSfILEeXISTS = false;
- NEXTtEMPnAME = 1;
- SPRINTF(FILENAME, "%S0bc-stat", TEMPpREFIX);
- IF( (FIN = FOPEN(FILENAME, "R")) == null) RETURN;
- STATUSfILEeXISTS = true;
- WHILE ( rEADlINE( FIN, LINE ) != -1 ) {$7b}
- H = & HAVES[HAVEcOUNT];
- SCAN = SSCANF(LINE, "%05LU-%05LU %C%C%C 0bc%05LX %S",
- &H->FROMsEG, &H->TOsEG, &INTERPRET[0], &INTERPRET[1],
- &INTERPRET[2], &H->TEMPfILEnAME, FILENAME);
- IF (SCAN != 7) {$7b}
- FPRINTF(STDERR, "bAD sTATUS lINE: %S\N", LINE);
- {$7d} ELSE {$7b}
- H->ISeND = (INTERPRET[0] == 'E');
- H->FILENAME = (CHAR*)MALLOC( STRLEN(FILENAME)+1 );
- STRCPY( H->FILENAME, FILENAME );
- HAVEcOUNT++;
- IF (HAVEcOUNT>=max_have) {$7b}
- FPRINTF(STDERR,
- "TOO MANY STATUS FRAGMENTS, fatal\N");
- EXIT( 1 );
- {$7d}
- {$7d}
- {$7d}
- FCLOSE( FIN );
- {$7d}
-
- /****************************************************************************/
- VOID sAVEsTATUSfILE()
- {$7b}
- CHARFILENAME[max_filename];
- file *FOUT;
- INTERR;
-
- SPRINTF(FILENAME, "%S0bc-stat", TEMPpREFIX);
- IF (HAVEcOUNT == 0) {$7b}
- IF (STATUSfILEeXISTS) {$7b}
- ERR = REMOVE( FILENAME );
- IF (ERR) {$7b}
- FPRINTF(STDERR,"CANNOT REMOVE %S\N", FILENAME);
- {$7d}
- {$7d}
- RETURN;
- {$7d}
- IF( (FOUT = FOPEN(FILENAME, "W")) == null) {$7b}
- FPRINTF(STDERR, "CANNOT OPEN %S FOR SAVING STATUS\N",FILENAME);
- RETURN;
- {$7d}
- wRITEsTATUSdATA( FOUT );
- FCLOSE( FOUT );
- {$7d}
-
- /****************************************************************************/
- VOID wRITEsTATUSdATA( FOUT )
- file *FOUT;
- {$7b}
- ulongI;
- haverec *H;
- CHAR INTERPRET[4];
-
- FOR (I=0; I<HAVEcOUNT; I++) {$7b}
- H = & HAVES[I];
- IF (H->ISeND) {$7b}
- STRCPY( INTERPRET, "END" );
- {$7d} ELSE {$7b}
- IF (H->FROMsEG == 1) {$7b}
- STRCPY( INTERPRET, "BEG" );
- {$7d} ELSE {$7b}
- STRCPY( INTERPRET, "MID" );
- {$7d}
- {$7d}
- FPRINTF(FOUT, "%05LU-%05LU %S 0bc%05LU %S\N", H->FROMsEG,
- H->TOsEG, INTERPRET, H->TEMPfILEnAME, H->FILENAME);
- {$7d}
- {$7d}
-
- /****************************************************************************/
- file *gETtEMPfILE( FILENAME, SEGNUM, HAVErEC )
- CHAR *FILENAME;
- ulong SEGNUM;
- ulong *HAVErEC;
- {$7b}
- haverec *H;
- ulongI, J, REC, TEMPnAME;
- CHARTEMPNAME[max_filename];
- CHARTEMPMODE[4];
- boolAPPEND;
- file *FOUT;
-
- /* SEARCH TO APPEND TO EXISTING FILE */
- APPEND = false;
- FOR (I=0; I<HAVEcOUNT; I++) {$7b}
- H = & HAVES[I];
- IF (STRCMP(FILENAME, H->FILENAME)==0) {$7b}
- IF (H->FROMsEG<=SEGNUM && SEGNUM<=H->TOsEG) {$7b}
- FPRINTF(STDERR,
- "IGNORING DUPLICATE SEGMENT %LU OF \"%S\"\N",
- SEGNUM, FILENAME);
- RETURN( null );
- {$7d}
- IF (SEGNUM == H->TOsEG + 1) {$7b}
- /* APPEND */
- TEMPnAME = H->TEMPfILEnAME;
- STRCPY( TEMPMODE, "AB" );
- APPEND = true;
- H->TOsEG = SEGNUM;
- H->ISeND = false;
- REC = I;
- BREAK;
- {$7d}
- {$7d}
- {$7d}
-
- IF (!APPEND) {$7b}
- /* FIND NEW TEMPNAME */
- FOR (I=0; I<100000; I++) {$7b}
- TEMPnAME = NEXTtEMPnAME;
- NEXTtEMPnAME = (NEXTtEMPnAME + 1) % 100000;
- FOR (J=0; J<HAVEcOUNT; J++) {$7b}
- IF (HAVES[J].TEMPfILEnAME == TEMPnAME) {$7b}
- J = -1;
- BREAK;
- {$7d}
- {$7d}
- IF (J != -1) BREAK;
- IF (I==100000-1) {$7b}
- FPRINTF(STDERR, "CANNOT FIND TEMP NAME!!!\N");
- RETURN( null );
- {$7d}
- {$7d}
-
- /* CREATE NEW HAVE RECORD */
- REC = iNSERThAVErEC( SEGNUM, TEMPnAME, FILENAME );
- STRCPY(TEMPMODE, "WB");
- {$7d}
-
- /* OPEN THE TEMPORARY FILE */
- gETtEMPnAMEsTR( TEMPnAME, TEMPNAME );
- IF( (FOUT = FOPEN(TEMPNAME, TEMPMODE)) == null) {$7b}
- FPRINTF(STDERR, "%S: ERROR OPENING \"%S\" FOR WRITE, fatal!\N",
- PROGNAME, FILENAME);
- EXIT( 1 );
- {$7d}
- *HAVErEC = REC;
- RETURN( FOUT );
- {$7d}
-
- /****************************************************************************/
- ulong iNSERThAVErEC( SEGNUM, TEMPnAME, FILENAME )
- ulong SEGNUM;
- ulong TEMPnAME;
- CHAR *FILENAME;
- {$7b}
- ulongREC;
- LONGI;
- haverec*H;
- INTCMP;
-
- REC = HAVEcOUNT;
- HAVEcOUNT++;
- IF (HAVEcOUNT >= max_have) {$7b}
- HAVEcOUNT--;
- FPRINTF(STDERR, "INPUT DATA TOO FRAGMENTED; fatal!\N");
- EXIT( 1 );
- {$7d}
-
- /* INSERTION SORT NEW ENTRY INTO PLACE */
- FOR (I=REC-1; I>=0; I--) {$7b}
- CMP = STRCMP(FILENAME, HAVES[I].FILENAME);
- IF (CMP > 0) {$7b}
- BREAK;
- {$7d} ELSE IF (CMP==0 && SEGNUM>HAVES[I].FROMsEG) {$7b}
- BREAK;
- {$7d}
- HAVES[I+1] = HAVES[I];
- {$7d}
-
- /* INITIALIZE NEW RECORD */
- REC = I+1;
- H = & HAVES[REC];
- H->FROMsEG = SEGNUM;
- H->TOsEG = SEGNUM;
- H->ISeND = false;
- H->TEMPfILEnAME = TEMPnAME;
- H->FILENAME = (CHAR*)MALLOC( STRLEN(FILENAME)+1 );
- STRCPY( H->FILENAME, FILENAME );
- RETURN( REC );
- {$7d}
-
- /****************************************************************************/
- VOID cHECKcOALESCE( HAVErEC )
- ulong HAVErEC;
- {$7b}
- haverec *P, *Q;
- CHARTEMPNAME[max_filename];
- INTERR;
- file *FIN, *FOUT;
- ulongBYTES;
-
- IF (HAVErEC >= HAVEcOUNT-1) RETURN;
- P = & HAVES[HAVErEC];
- Q = & HAVES[HAVErEC+1];
- IF (STRCMP(P->FILENAME, Q->FILENAME)!=0 {$7c}{$7c} P->TOsEG+1 != Q->FROMsEG) {$7b}
- RETURN;
- {$7d}
-
- /* COALESCE */
- IF (DEBUG) {$7b}
- FPRINTF(STDERR,
- "cOALESCING SEGS %LU-%LU AND SEGS %LU-%LU OF FILE %S\N",
- P->FROMsEG, P->TOsEG, Q->FROMsEG, Q->TOsEG, P->FILENAME);
- {$7d}
-
- /* COPY FILE CONTENTS */
- gETtEMPnAMEsTR( Q->TEMPfILEnAME, TEMPNAME );
- IF( (FIN = FOPEN(TEMPNAME, "RB")) == null) {$7b}
- FPRINTF(STDERR, "%S: ERROR OPENING \"%S\", fatal\N",
- PROGNAME, TEMPNAME);
- EXIT( 1 );
- {$7d}
- gETtEMPnAMEsTR( P->TEMPfILEnAME, TEMPNAME );
- IF( (FOUT = FOPEN(TEMPNAME, "AB")) == null) {$7b}
- FPRINTF(STDERR, "%S: ERROR OPENING \"%S\", fatal\N",
- PROGNAME, TEMPNAME);
- EXIT( 1 );
- {$7d}
- WHILE ( (BYTES=FREAD( COPYbUF, SIZEOF(byte), copy_buf_size, FIN)) >0) {$7b}
- FWRITE( COPYbUF, SIZEOF(byte), BYTES, FOUT );
- {$7d}
- FCLOSE( FOUT );
- FCLOSE( FIN );
-
-
- /* REMOVE OLD RECORD AND TEMP FILE */
- P->TOsEG = Q->TOsEG;
- P->ISeND = Q->ISeND;
- gETtEMPnAMEsTR( Q->TEMPfILEnAME, TEMPNAME );
- ERR = REMOVE( TEMPNAME );
- IF (ERR) {$7b}
- FPRINTF(STDERR, "CANNOT REMOVE %S, CONTINUING.\N", TEMPNAME);
- {$7d}
- rEMOVEhAVErEC( HAVErEC+1 );
- {$7d}
-
- /****************************************************************************/
- VOID cHECKcOMPLETE( HAVErEC )
- ulong HAVErEC;
- {$7b}
- CHARTEMPNAME[max_filename];
- INTERR;
- haverec*H;
-
- H = & HAVES[HAVErEC];
- IF (!H->ISeND {$7c}{$7c} H->FROMsEG!=1) RETURN;
-
- gETtEMPnAMEsTR( H->TEMPfILEnAME, TEMPNAME );
- ERR = RENAME( TEMPNAME, H->FILENAME );
- IF (ERR) {$7b}
- FPRINTF(STDERR, "CANNOT RENAME %S TO %S, CONTINUING.",
- TEMPNAME, H->FILENAME );
- {$7d}
- IF (INFORMATIVE) {$7b}
- FPRINTF(STDERR,
- "i HAVE PIECED TOGETHER ALL SEGMENTS OF \"%S\"\N",
- H->FILENAME );
- {$7d}
- rEMOVEhAVErEC( HAVErEC );
- {$7d}
-
- /****************************************************************************/
- VOID rEMOVEhAVErEC( REC )
- ulong REC;
- {$7b}
- LONGI;
-
- /* FREE DYNAMIC MEMORY OF FILENAME */
- FREE( HAVES[REC].FILENAME );
-
- /* PULL ALL HIGHER ENTRIES BACK ONE POSITION */
- FOR (I=REC; I<HAVEcOUNT-1; I++) {$7b}
- HAVES[I] = HAVES[I+1];
- {$7d}
-
- HAVEcOUNT--;
- {$7d}
-
- /****************************************************************************/
- VOID gETtEMPnAMEsTR( TEMPnAME, S )
- ulong TEMPnAME;
- CHAR *S;
- {$7b}
- SPRINTF(S, "%S0bc%05LU", TEMPpREFIX, TEMPnAME);
- {$7d}
-
- #IFDEF no_rename
- /****************************************************************************/
- INT RENAME( OLDNAME, NEWNAME )
- CHAR *OLDNAME, *NEWNAME;
- {$7b}
- IF ( LINK( OLDNAME, NEWNAME ))
- RETURN( -1 );
- ELSE
- RETURN( UNLINK( OLDNAME ));
- {$7d}
- #ENDIF
-