/* Program to unsqueeze files formed by sq.com * * Useage: * * usq [-count] [-fcount] [file1] [file2] ... [filen] * * where file1 through filen represent one or more files to be compressed, * and the following options may be specified: * * -count Previewing feature: redirects output * files to standard output with parity stripped * and unprintables except CR, LF, TAB and FF * converted to periods. Limits each file * to first count lines. * Defaults to console, but see below how * to capture all in one file for further * processing, such as by PIP. * Count defaults to a very high value. * No CRC check is performed when previewing. * Use drive: to cancel this. * * -fcount Same as -count except formfeed * appended to preview of each file. * Example: -f10. * * If no such items are given on the command line you will be * prompted for commands (one at a time). An empty command * terminates the program. * * The unsqueezed file name is recorded in the squeezed file. * */ /* CHANGE HISTORY: * 1.3 Close inbuff to avoid exceeding maximum number of * open files. Includes rearranging error exits. * 1.4 Add -count option to allow quick inspection of files. * 1.5 Break up long lines of introductory text * 1.5 -count no longer appends formfeed to preview of each file. * -fcount (-f10, -F10) does append formfeed. * 1.6 Modified to work correctly under MP/M II (DIO.C change) and * signon message shortened. * 2.0 Modified to work with CI-C86 compiler (CP/M-86 and MS-DOS) * 2.1 Modified for use in MLINK * 2.2 Modified for use with optimizing CI-C86 compiler (MS-DOS) * 3.0 Generalized for use under UNIX * 3.3 Modified to work with c/70 (#define C70) as per Mike Barker. * Modified to work with ULTRIX (#define ULTRIX) as per Tom Reid. * Fixed non-ASCII name problem, as per Ted Medin. */ /* eject eject */ #define SQMAIN #include #include "sqcom.h" #include "usq.h" #ifdef TOPS20 #include #endif #define VERSION "3.3 10/29/86" /* This must follow all include files */ unsigned int dispcnt; /* How much of each file to preview */ char ffflag; /* should formfeed separate preview from different files */ #ifdef TOPS20 struct filename req; #endif main(argc, argv) int argc; char *argv[]; { int i,c; char inparg[16]; /* parameter from input */ dispcnt = 0; /* Not in preview mode */ printf("File unsqueezer version %s (original author: R. Greenlaw)\n\n", VERSION); /* Process the parameters in order */ for(i = 1; i < argc; ++i) obey(argv[i]); if(argc < 2) { printf("Enter file names, one line at a time, or type to quit."); do { printf("\n*"); #ifdef TOPS20 fflush (stdout); #endif for(i = 0; i < 16; ++i) { if((c = getchar()) == EOF) c = '\n'; /* force empty (exit) command */ if((inparg[i] = c) == '\n') { inparg[i] = '\0'; break; } } if(inparg[0] != '\0') obey(inparg); } while(inparg[0] != '\0'); } } /* eject eject */ obey(p) char *p; { #ifdef TOPS20 char *d, *dir (); /* directory junk */ int flag; #else char *q, cc; #endif if(*p == '-') { if(ffflag = ((*(p+1) == 'F') || (*(p+1) == 'f'))) ++p; /* Set number of lines of each file to view */ dispcnt = 65535; /* default */ if(*(p+1)) if((dispcnt = atoi(p + 1)) == 0) printf("\nBAD COUNT %s", p + 1); #ifdef TOPS20 exit (1); #endif return; } #ifdef TOPS20 flag = 1; for (d = dir (p, 0); *d; d = dir (NULL, 0)) { flag = 0; unsqueeze (d); } if (flag) { printf ("File, %s, not found\n", p); } #else /* Check for ambiguous (wild-card) name */ for(q = p; *q != '\0'; ++q) if(*q == '*' || *q == '?') { printf("\nCan't accept ambiguous name %s", p); return; } unsqueeze(p); #endif } /* eject eject */ unsqueeze(infile) char *infile; { FILE *inbuff, *outbuff; /* file buffers */ #ifdef C70 int magictemp; #endif int i, c; char cc; #ifdef TOPS20 int r; char cmd[200]; #endif char *p; unsigned int filecrc; /* checksum */ int numnodes; /* size of decoding tree */ char outfile[128]; /* output file name */ unsigned int linect; /* count of number of lines previewed */ char obuf[128]; /* output buffer */ int oblen; /* length of output buffer */ static char errmsg[] = "ERROR - write failure in %s\n"; #ifdef TOPS20 strcpy (req.name, infile); if ((r = fullfname(&req, "RAW")) != 0) { if (r == 1) { printf ("JFNS error encountered\n"); } printf ("File, %s, not found\n", infile); return (-1); } #endif #ifdef ULTRIX if(!(inbuff=fopen(infile, "r"))) { #else #ifdef TOPS20 if(!(inbuff=fopen(req.qname, "r"))) { #else if(!(inbuff=fopen(infile, "rb"))) { #endif #endif printf("Can't open %s\n", infile); return; } /* Initialization */ linect = 0; crc = 0; init_cr(); init_huff(); /* Process header */ #ifdef C70 magictemp = getx16(inbuff); if(magictemp != RECOGNIZE) { printf("magic number is %x, not %x.\n", magictemp,RECOGNIZE); #else if(getx16(inbuff) != RECOGNIZE) { printf("%s is not a squeezed file\n", infile); #endif goto closein; } #if defined(C70) || defined(TOPS20) filecrc = getx16(inbuff); #else filecrc = getw16(inbuff); #endif /* Get original file name */ p = outfile; /* send it to array */ do { /* *p = getc(inbuff); */ *p = getc(inbuff) & 0x7f; /*3.3 Must be ASCII.*/ } while(*p++ != '\0'); #ifdef TOPS20 /* UPPERcase output filename */ upper (outfile); printf("%s -> %s: ", req.name, outfile); fflush (stdout); enquote (outfile); #else printf("%s -> %s: ", infile, outfile); #endif #if defined(C70) || defined(TOPS20) numnodes = getx16(inbuff); #else numnodes = getw16(inbuff); #endif if(numnodes < 0 || numnodes >= NUMVALS) { #ifdef C70 printf("Number of nodes is %x, not %x.\n",numnodes,NUMVALS); #else printf("%s has invalid decode tree size\n", infile); #endif goto closein; } /* Initialize for possible empty tree (SPEOF only) */ dnode[0].children[0] = -(SPEOF + 1); dnode[0].children[1] = -(SPEOF + 1); /* Get decoding tree from file */ for(i = 0; i < numnodes; ++i) { dnode[i].children[0] = getw16(inbuff); dnode[i].children[1] = getw16(inbuff); } if(dispcnt) { /* Use standard output for previewing */ putchar('\n'); while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) { cc = 0x7f & c; /* strip parity */ if((cc < ' ') || (cc > '~')) /* Unprintable */ switch(cc) { case '\r': /* return */ /* newline will generate CR-LF */ goto next; case '\n': /* newline */ ++linect; case '\f': /* formfeed */ case '\t': /* tab */ break; #ifdef TOPS20 case '\032': /* CP/M EOF (^Z) */ goto closein; #endif default: cc = '.'; } putchar(cc); next: ; } if(ffflag) putchar('\f'); /* formfeed */ } else { /* Create output file */ #ifdef TOPS20 if(!(outbuff=fopen("USQ.OUT", "w8"))) { printf("Cannot create USQ.OUT\n"); #else #ifdef ULTRIX if(!(outbuff=fopen(outfile, "w"))) { #else if(!(outbuff=fopen(outfile, "wb"))) { #endif printf("Can't create %s\n", outfile); #endif goto closeall; } printf("unsqueezing,"); #ifdef TOPS20 fflush (stdout); #endif /* Get translated output bytes and write file */ oblen = 0; while((c = getcr(inbuff)) != EOF) { crc += c; #ifdef TOPS20 crc &= 0xffff; #endif obuf[oblen++] = c; if (oblen >= sizeof(obuf)) { if(!fwrite(obuf, sizeof(obuf), 1, outbuff)) { printf(errmsg, outfile); goto closeall; } oblen = 0; } } if (oblen && !fwrite(obuf, oblen, 1, outbuff)) { printf(errmsg, outfile); goto closeall; } if((filecrc && 0xFFFF) != (crc && 0xFFFF)) printf("ERROR - checksum error in %s\n", outfile); else printf(" done.\n"); closeall: fclose(outbuff); #ifdef TOPS20 sprintf (cmd, "ASCIFY USQ.OUT/DWIM/SILENT %s", outfile); system (cmd); if (access (outfile, 04) != (-1)) { unlink ("USQ.OUT"); } else { rename ("USQ.OUT", outfile); } #endif } closein: fclose(inbuff); } getw16(iob) /* get 16-bit word from file */ FILE *iob; { #ifdef TOPS20 int temp; temp = fgetc(iob) & 0xFF; /* get low order byte */ temp |= (fgetc(iob) & 0xFF) << 8; if (temp & 0x8000) temp |= (~0) << 15; /* propogate sign for big ints */ return (temp); #else int temp; temp = getc(iob); /* get low order byte */ temp |= getc(iob) << 8; if (temp & 0x8000) temp |= (~0) << 15; /* propogate sign for big ints */ return (temp); #endif } getx16(iob) /* get 16-bit (unsigned) word from file */ FILE *iob; { int temp; #ifdef TOPS20 temp = fgetc(iob) & 0xFF; /* get low order byte */ temp |= (fgetc(iob) & 0xFF) << 8; return (temp); #else temp = getc(iob); /* get low order byte */ temp |= getc(iob) << 8; return(temp); #endif }