home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / CPM68K / XLU68K.LBR / USQ.CQ / USQ.C
Text File  |  2000-06-30  |  12KB  |  351 lines

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