home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 020 / squsq.arc / USQ.C
Encoding:
C/C++ Source or Header  |  1980-01-01  |  12.4 KB  |  388 lines

  1. /*
  2.    usq.c
  3. */
  4.  
  5. /* Program to unsqueeze files formed by sq.com
  6.  *
  7.  * Useage:
  8.  *
  9.  *      usq [-count] [-fcount] [file1] [file2] ... [filen]
  10.  *
  11.  * where file1 through filen represent one or more files to be compressed,
  12.  * and the following options may be specified:
  13.  *
  14.  *      -count          Previewing feature: redirects output
  15.  *                      files to standard output with parity stripped
  16.  *                      and unprintables except CR, LF, TAB and  FF
  17.  *                      converted to periods. Limits each file
  18.  *                      to first count lines.
  19.  *                      Defaults to console, but see below how
  20.  *                      to capture all in one file for further
  21.  *                      processing, such as by PIP.
  22.  *                      Count defaults to a very high value.
  23.  *                      No CRC check is performed when previewing.
  24.  *                      Use drive: to cancel this.
  25.  *
  26.  *      -fcount         Same as -count except formfeed
  27.  *                      appended to preview of each file.
  28.  *                      Example: -f10.
  29.  *
  30.  * If no such items are given on the command line you will be
  31.  * prompted for commands (one at a time). An empty command
  32.  * terminates the program.
  33.  *
  34.  * The unsqueezed file name is recorded in the squeezed file.
  35.  * 
  36.  */
  37. /* CHANGE HISTORY:
  38.  * 1.3  Close inbuff to avoid exceeding maximum number of
  39.  *      open files. Includes rearranging error exits.
  40.  * 1.4  Add -count option to allow quick inspection of files.
  41.  * 1.5  Break up long lines of introductory text
  42.  * 1.5  -count no longer appends formfeed to preview of each file.
  43.  *      -fcount (-f10, -F10) does append formfeed.
  44.  * 1.6  Modified to work correctly under MP/M II (DIO.C change) and
  45.  *      signon message shortened.
  46.  * 2.0  Modified to work with CI-C86 compiler (CP/M-86 and MS-DOS)
  47.  * 2.1  Modified for use in MLINK
  48.  * 2.2  Modified for use with optimizing CI-C86 compiler (MS-DOS)
  49.  * 3.0  Generalized for use under UNIX
  50.  *
  51.  * 3.2  Ported to Amiga & Lattice
  52.  *      Rick Schaeffer [70120,174] 12/03/85
  53.  * 3.3  Small changes to eliminate warning messages from Lattice C ver 3.02
  54.  *      Joanne Dow      jdow on bix - BYTE INFORMATION EXCHANGE
  55.  */
  56.  
  57. #include <stdio.h>
  58. #define ERROR -1
  59.  
  60. /* Definitions and external declarations */
  61.  
  62. #define RECOGNIZE 0xFF76        /* unlikely pattern */
  63.  
  64. /* *** Stuff for first translation module *** */
  65.  
  66. #define DLE 0x90
  67.  
  68. unsigned int crc;        /* error check code */
  69.  
  70. /* *** Stuff for second translation module *** */
  71.  
  72. #define SPEOF 256       /* special endfile token */
  73. #define NUMVALS 257     /* 256 data values plus SPEOF*/
  74. #define LARGE 30000
  75.  
  76. /* Decoding tree */
  77. struct {
  78.         int children[2];        /* left, right */
  79. } dnode[NUMVALS - 1];
  80.  
  81. int bpos;        /* last bit position read */
  82. int curin;       /* last byte value read */
  83.  
  84. /* Variables associated with repetition decoding */
  85. int repct;       /* Number of times to return value */
  86. int value;       /* current byte value or EOF */
  87. #define VERSION "3.3   12/13/85"
  88.  
  89. /* This must follow all include files */
  90. unsigned int dispcnt;   /* How many lines of each file to preview */
  91. char    ffflag;         /* y/n for formfeed between previewed files */
  92.  
  93. main(argc, argv)
  94. int argc;
  95. char *argv[];
  96. {
  97.         void obey();
  98.         int i,c;
  99.         char inparg[16];        /* parameter from input */
  100.  
  101.         dispcnt = 0;    /* Not in preview mode */
  102.  
  103.         printf("File unsqueezer version %s (original author: R. Greenlaw)\n\n", VERSION);
  104.  
  105.         /* Process the parameters in order */
  106.         for(i = 1; i < argc; ++i)
  107.                 obey(argv[i]);
  108.  
  109.         if(argc < 2) {
  110.                 printf("Enter file names, one line at a time, or type <RETURN> to quit.");
  111.                 do {
  112.                         printf("\n*");
  113.                         for(i = 0; i < 16; ++i) {
  114.                                 if((c = getchar()) == EOF)
  115.                                         c = '\n';       /* force empty (exit) command */
  116.                                 if((inparg[i] = c) == '\n') {
  117.                                         inparg[i] = '\0';
  118.                                         break;
  119.                                 }
  120.                         }
  121.                         if(inparg[0] != '\0')
  122.                                 obey(inparg);
  123.                 } while(inparg[0] != '\0');
  124.         }
  125. }
  126.  
  127. /* eject^Leject */
  128.  
  129. void obey(p)
  130. char *p;
  131. {
  132.         void unsqueeze();
  133.         char *q;
  134.  
  135.         if(*p == '-') {
  136.                 if(ffflag = ((*(p+1) == 'F') || (*(p+1) == 'f')))
  137.                         ++p;
  138.                 /* Set number of lines of each file to view */
  139.                 dispcnt = 65535;        /* default */
  140.                 if(*(p+1))
  141.                         if((dispcnt = atoi(p + 1)) == 0)
  142.                                 printf("\nBAD COUNT %s", p + 1);
  143.                 return;
  144.         }       
  145.  
  146.         /* Check for ambiguous (wild-card) name */
  147.         for(q = p; *q != '\0'; ++q)
  148.                 if(*q == '*' || *q == '?') {
  149.                         printf("\nCan't accept ambiguous name %s", p);
  150.                         return;
  151.                 }
  152.  
  153.         unsqueeze(p);
  154. }
  155.  
  156. /* eject^Leject */
  157.  
  158. void unsqueeze(infile)
  159. char *infile;
  160. {
  161.         unsigned int getx16();
  162.         FILE *inbuff, *outbuff; /* file buffers */
  163.         int i, c;
  164.         char cc;
  165.  
  166.         char *p;
  167.         unsigned int filecrc;   /* checksum */
  168.         int numnodes;           /* size of decoding tree */
  169.         char outfile[128];      /* output file name */
  170.         unsigned int linect;    /* count of number of lines previewed */
  171.         char obuf[128];         /* output buffer */
  172.         int oblen;              /* length of output buffer */
  173.         static char errmsg[] = "ERROR - write failure in %s\n";
  174.  
  175.         if(!(inbuff=fopen(infile, "rb"))) {
  176.                 printf("Can't open %s\n", infile);
  177.                 return;
  178.         }
  179.         /* Initialization */
  180.         linect = 0;
  181.         crc = 0;
  182.         init_cr();
  183.         init_huff();
  184.  
  185.         /* Process header */
  186.         if(getx16(inbuff) != RECOGNIZE) {
  187.                 printf("%s is not a squeezed file\n", infile);
  188.                 goto closein;
  189.         }
  190.  
  191.         filecrc = getw16(inbuff);
  192.  
  193.         /* Get original file name */
  194.         p = outfile;                    /* send it to array */
  195.         do {
  196.                 *p = getc(inbuff);
  197.         } while(*p++ != '\0');
  198.  
  199.         printf("%s -> %s: ", infile, outfile);
  200.  
  201.  
  202.         numnodes = getw16(inbuff);
  203.  
  204.         if(numnodes < 0 || numnodes >= NUMVALS) {
  205.                 printf("%s has invalid decode tree size\n", infile);
  206.                 goto closein;
  207.         }
  208.  
  209.         /* Initialize for possible empty tree (SPEOF only) */
  210.         dnode[0].children[0] = -(SPEOF + 1);
  211.         dnode[0].children[1] = -(SPEOF + 1);
  212.  
  213.         /* Get decoding tree from file */
  214.         for(i = 0; i < numnodes; ++i) {
  215.                 dnode[i].children[0] = getw16(inbuff);
  216.                 dnode[i].children[1] = getw16(inbuff);
  217.         }
  218.  
  219.         if(dispcnt) {
  220.                 /* Use standard output for previewing */
  221.                 putchar('\n');
  222.                 while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) {
  223.                         cc = 0x7f & c;  /* strip parity */
  224.                         if((cc < ' ') || (cc > '~'))
  225.                                 /* Unprintable */
  226.                                 switch(cc) {
  227.                                 case '\r':      /* return */
  228.                                         /* newline will generate CR-LF */
  229.                                         goto next;
  230.                                 case '\n':      /* newline */
  231.                                         ++linect;
  232.                                 case '\f':      /* formfeed */
  233.                                 case '\t':      /* tab */
  234.                                         break;
  235.                                 default:
  236.                                         cc = '.';
  237.                                 }
  238.                         putchar(cc);
  239.                 next: ;
  240.                 }
  241.                 if(ffflag)
  242.                         putchar('\f');  /* formfeed */
  243.         } else {
  244.                 /* Create output file */
  245.                 if(!(outbuff=fopen(outfile, "wb"))) {
  246.                         printf("Can't create %s\n", outfile);
  247.                         goto closeall;
  248.                 }
  249.                 printf("unsqueezing,");
  250.                 /* Get translated output bytes and write file */
  251.                 oblen = 0;
  252.                 while((c = getcr(inbuff)) != EOF) {
  253.                         crc += c;
  254.                         obuf[oblen++] = c;
  255.                         if (oblen >= sizeof(obuf)) {
  256.                                 if(!fwrite(obuf, sizeof(obuf), 1, outbuff)) {
  257.                                         printf(errmsg, outfile);
  258.                                         goto closeall;
  259.                                 }
  260.                                 oblen = 0;
  261.                         }
  262.                 }
  263.                 if (oblen && !fwrite(obuf, oblen, 1, outbuff)) {
  264.                         printf(errmsg, outfile);
  265.                         goto closeall;
  266.                 }
  267.  
  268.                 if((filecrc && 0xFFFF) != (crc && 0xFFFF))
  269.                         printf("ERROR - checksum error in %s\n", outfile);
  270.                 else    printf(" done.\n");
  271.  
  272.         closeall:
  273.                 fclose(outbuff);
  274.         }
  275.  
  276. closein:
  277.         fclose(inbuff);
  278. }
  279.  
  280. getw16(iob)                     /* get 16-bit word from file */
  281. FILE *iob;
  282. {
  283. int temp;
  284.  
  285. temp = getc(iob);               /* get low order byte */
  286. temp |= getc(iob) << 8;
  287. if (temp & 0x8000) temp |= (~0) << 15;  /* propogate sign for big ints */
  288. return temp;
  289.  
  290. }
  291.  
  292.  
  293. unsigned int getx16(iob)        /* get 16-bit (unsigned) word from file */
  294. FILE *iob;
  295. {
  296. int temp;
  297.  
  298. temp = getc(iob);               /* get low order byte */return temp | (getc(iob) << 8);
  299.  
  300. }
  301.  
  302. /* initialize decoding functions */
  303.  
  304. init_cr()
  305. {
  306.         repct = 0;
  307. }
  308.  
  309. init_huff()
  310. {
  311.         bpos = 99;      /* force initial read */
  312. }
  313.  
  314. /* Get bytes with decoding - this decodes repetition,
  315.  * calls getuhuff to decode file stream into byte
  316.  * level code with only repetition encoding.
  317.  *
  318.  * The code is simple passing through of bytes except
  319.  * that DLE is encoded as DLE-zero and other values
  320.  * repeated more than twice are encoded as value-DLE-count.
  321.  */
  322.  
  323. int
  324. getcr(ib)
  325. FILE *ib;
  326. {
  327.         int c;
  328.  
  329.         if(repct > 0) {
  330.                 /* Expanding a repeated char */
  331.                 --repct;
  332.                 return value;
  333.         } else {
  334.                 /* Nothing unusual */
  335.                 if((c = getuhuff(ib)) != DLE) {
  336.                         /* It's not the special delimiter */
  337.                         value = c;
  338.                         if(value == EOF)
  339.                                 repct = LARGE;
  340.                         return value;
  341.                 } else {
  342.                         /* Special token */
  343.                         if((repct = getuhuff(ib)) == 0)
  344.                                 /* DLE, zero represents DLE */
  345.                                 return DLE;
  346.                         else {
  347.                                 /* Begin expanding repetition */
  348.                                 repct -= 2;     /* 2nd time */
  349.                                 return value;
  350.                         }
  351.                 }
  352.         }
  353. }
  354.  
  355. /* eject^Leject */
  356.  
  357. /* Decode file stream into a byte level code with only
  358.  * repetition encoding remaining.
  359.  */
  360.  
  361. int
  362. getuhuff(ib)
  363. FILE *ib;
  364. {
  365.         int i;
  366.  
  367.         /* Follow bit stream in tree to a leaf*/
  368.         i = 0;  /* Start at root of tree */
  369.         do {
  370.                 if(++bpos > 7) {
  371.                         if((curin = getc(ib)) == ERROR)
  372.                                 return ERROR;
  373.                         bpos = 0;
  374.                         /* move a level deeper in tree */
  375.                         i = dnode[i].children[1 & curin];
  376.                 } else
  377.                         i = dnode[i].children[1 & (curin >>= 1)];
  378.         } while(i >= 0);
  379.  
  380.         /* Decode fake node index to original data value */
  381.         i = -(i + 1);
  382.         /* Decode special endfile token to normal EOF */
  383.         i = (i == SPEOF) ? EOF : i;
  384.         return i;
  385. }
  386.  
  387. /* end of program */
  388.