This is atob.c in view mode; [Download] [Up]
/* atob.c */ /* Written by Paul Rutter, Joe Orost & Stefan Parmark. */ #include <stdio.h> #ifdef AMIGA #include <stdlib.h> #include <string.h> #endif AMIGA #include "btoa.h" #if USE_MACROS #include "chksum.h" #endif USE_MACROS BYTE atob(infile) register FILE *infile; { register BYTE error; register LONG filepos; int maxperline; LONG n1, n2, oeor, osum, orot, lastline; static BYTE outfilename[BUFSIZE]; extern LONG Ceor, Csum, Crot; extern FILE *outfile; extern BYTE new_version, openoutput, buffer[BUFSIZE]; error = FALSE; /* Search for archive header. */ do { filepos = ftell(infile); if (readbuffer(buffer, "archive", infile)) error = TRUE; } while (!(error || strncmp(buffer, "xbtoa", 5) == 0)); if (!error) if (strcmp(buffer, "xbtoa Begin\n") == 0) { new_version = FALSE; fprintf(stderr, "btoa: Old btoa format.\n"); } else if (sscanf(buffer, "xbtoa5 %d %s Begin\n", &maxperline, outfilename) == 2) { new_version = TRUE; /* Naming a file overrides the read-name-from-file function. */ if (!openoutput && strcmp(outfilename, "-") != 0) if ((outfile = fopen_write(outfilename)) == NULL) error = TRUE; else openoutput = TRUE; } else { fprintf(stderr, "btoa: Illegal archive header.\n"); error = TRUE; } if (!error) { Ceor = Csum = Crot = 0; if (new_version) error = new_decodefile(infile, &lastline, filepos, maxperline); else error = old_decodefile(infile, &lastline); } if (!error) { if (sscanf(buffer, "xbtoa End N %ld %lx E %lx S %lx R %lx\n", &n1, &n2, &oeor, &osum, &orot) != 5) { fprintf(stderr, "btoa: Bad format on line %ld. Can't repair file.\n", lastline); error = TRUE; } else if ((n1 != n2) || (oeor != Ceor) || (osum != Csum) || (orot != Crot)) { fprintf(stderr, "btoa: Bad file checksum. Can't repair file.\n"); error = TRUE; } else /* Flush last characters. */ decode_line(NULL, (int) ((n1 - 1) & 0x03)); } return(error); } /* Peek at the next byte without moving the file pointer. */ int nextbyte(infile) register FILE *infile; { register int ch; register LONG filepos; filepos = ftell(infile); ch = fgetc(infile); fseek(infile, filepos, 0); return(ch); } BYTE new_decodefile(infile, lastline, filepos, maxperline) register FILE *infile; LONG *lastline, filepos; int maxperline; { register int length; int ch; register BYTE stop, error, newerror, errorstart; register LONG line, prevfilepos, startpos; struct Diagnosis diagnosislist; extern LONG Csum; extern BYTE buffer[BUFSIZE]; error = FALSE; line = 1; /* Current line number. */ /* A sequence of errors is indicated by errorstart. When it */ /* changes from TRUE to FALSE a diagnosis record will be */ /* generated. */ stop = errorstart = FALSE; /* File position of the line before the error sequence. */ /* That is the last correct line. */ startpos = 0; while (!stop) { prevfilepos = filepos; filepos = ftell(infile); /* Newerror indicates an error on the current line. */ newerror = FALSE; line++; if (readbuffer(buffer, "archive", infile)) newerror = stop = TRUE; else if (buffer[0] == 'x') /* End of archive found. */ stop = TRUE; else if ((length = strlen(buffer) - 1) != maxperline || buffer[length] != '\n') { /* If last character wasn't end-of-line, then we */ /* have to read until it is found. */ if (buffer[length] != '\n') { newerror = TRUE; while ((ch = fgetc(infile)) != EOF && (BYTE)ch != '\n') ; if (ch == EOF) stop = TRUE; } else if (length > maxperline || nextbyte(infile) != 'x') { newerror = TRUE; Csum = DECODE(buffer[length - 1]); /* Make Csum correct (modulo 85). */ } if (newerror) fprintf(stderr, "btoa: Bad line length on line %ld.\n", line); } if (!(newerror || stop)) { if (decode_line(buffer, length - 1)) { if (!error) fprintf(stderr, "btoa: Bad character on line %ld.\n", line); newerror = TRUE; } /* Examine checksum. */ if ((ch = buffer[length - 1]) == ENCODE(Csum % 85)) { if (errorstart) { intodiagnosislist(&diagnosislist, startpos, filepos); errorstart = FALSE; } } else { newerror = TRUE; fprintf(stderr, "btoa: Bad checksum on line %ld.\n", line); Csum = DECODE(ch); /* Make Csum correct (modulo 85). */ } } if (newerror) { if (!error) { fprintf(stderr, "btoa: Starting diagnosis.\n"); diagnosislist.next = diagnosislist.last = NULL; } error = TRUE; if (!errorstart) { errorstart = TRUE; startpos = prevfilepos; } } } if (error) { if (errorstart) intodiagnosislist(&diagnosislist, startpos, filepos); producediagnosis(&diagnosislist, infile); } *lastline = line; return(error); } BYTE old_decodefile(infile, lastline) register FILE *infile; LONG *lastline; { register int length; register BYTE stop, error; register LONG line; extern BYTE buffer[BUFSIZE]; error = FALSE; line = 1; stop = FALSE; while (!stop) { line ++; if (readbuffer(buffer, "archive", infile)) error = stop = TRUE; else if (buffer[0] == 'x') /* End of archive found. */ stop = TRUE; else { length = strlen(buffer) - 1; if (buffer[length] != '\n') error = stop = TRUE; /* The line was longer than the buffer. */ } if (!stop) { if (decode_line(buffer, length)) { fprintf(stderr, "btoa: Bad character on line %ld.\n", line); error = stop = TRUE; } } } *lastline = line; return(error); } BYTE decode_line(buffer, length) register BYTE *buffer; register int length; { register int ch; register BYTE error; register LONG tmp_codeword; extern BYTE new_version; extern FILE *outfile; static LONG codeword; static int ch1, ch2, ch3, ch4; static BYTE bytecount = 0; error = FALSE; if (buffer == NULL) /* Flush last characters. */ { if (bytecount > 0) { fputc(ch1, outfile); if (length > 0) fputc(ch2, outfile); if (length > 1) fputc(ch3, outfile); if (length > 2) fputc(ch4, outfile); } } else { while (length > 0) { length--; ch = *buffer++; /* Delayed output. This is to make sure that files with lengths */ /* that are not multiples of 4 won't become too long. */ if (bytecount == 5) { fputc(ch1, outfile); fputc(ch2, outfile); fputc(ch3, outfile); fputc(ch4, outfile); bytecount = 0; } if (new_version) calcchecksum(ch); if (((BYTE)ch >= '!') && ((BYTE)ch < ('!' + 85))) /* Valid characters. */ { /* See if we can take all 5 bytes and decode them right away. */ /* That is, if all remaining bytes are on the current line. */ if (length >= 4 - bytecount) { length -= 4 - bytecount; if (bytecount == 0) codeword = DECODE(ch); else codeword = codeword * 85 + DECODE(ch); for (bytecount++; bytecount < 5; bytecount++) { ch = *buffer++; if (new_version) calcchecksum(ch); codeword = codeword * 85 + DECODE(ch); } } else { /* Shift codeword and insert character. */ if (bytecount == 0) { codeword = DECODE(ch); bytecount = 1; } else /* bytecount < 5 */ { codeword = codeword * 85 + DECODE(ch); bytecount ++; } } if (bytecount == 5) { tmp_codeword = codeword; ch4 = (int)tmp_codeword & 0xFF; ch3 = (int)(tmp_codeword >>= 8) & 0xFF; ch2 = (int)(tmp_codeword >>= 8) & 0xFF; ch1 = (int)(tmp_codeword >> 8) & 0xFF; if (!new_version) { calcchecksum(ch1); calcchecksum(ch2); calcchecksum(ch3); calcchecksum(ch4); } } } else if ((BYTE)ch == 'z' || (new_version && (BYTE)ch == 'y')) { if (bytecount != 0) error = TRUE; else { ch1 = ch2 = ch3 = ch4 = (ch == 'z') ? 0 : ' '; if (!new_version) { calcchecksum(ch1); calcchecksum(ch1); calcchecksum(ch1); calcchecksum(ch1); } bytecount = 5; } } else error = TRUE; } } return(error); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.