home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / vmskermit32.zip / vmslz2.arc < prev    next >
Text File  |  1988-08-16  |  23KB  |  932 lines

  1. -h- lzdcm1.c    Wed Jul 24 11:49:34 1985    USER$A:[MINOW.LZ]LZDCM1.C;11
  2. /*
  3.  *        lzdcmp [-options] [infile [outfile]]
  4.  */
  5. #ifdef    DOCUMENTATION
  6.  
  7. title    lzdcmp    File Decompression
  8. index        File decompression
  9.  
  10. synopsis
  11.     .s.nf
  12.     lzdcmp [-options] [infile [outfile]]
  13.     .s.f
  14. description
  15.  
  16.     lzdcmp decompresses files compressed by lzcomp.  The
  17.     documentation for lzcomp describes the process in
  18.     greater detail.
  19.  
  20.     Options may be given in either case.
  21.     .lm +8
  22.     .p -8
  23.     -B    Output file is "binary", not text.  (Ignored
  24.     in VMS private mode.)
  25.     .p -8
  26.     -X 3    To read files compressed by an old Unix version
  27.     that doesn't generate header records.
  28.     .p -8
  29.     -V val    Verbose (print status messages and debugging
  30.     information).  The value selects the amount of verbosity.
  31.  
  32. Author
  33.  
  34.     This version by Martin Minow.  See lzcomp for more
  35.     details.
  36.  
  37. #endif
  38.  
  39. /*
  40.  * Compatible with compress.c, v3.0 84/11/27
  41.  */
  42.  
  43. /*)BUILD
  44.  *        $(PROGRAM) = lzdcmp
  45.  *        $(INCLUDE) = lz.h
  46.  *        $(FILES) = { lzdcm1.c lzdcm2.c lzdcm3.c lzio.c lzvio.c }
  47.  */
  48.  
  49. #include    "lz.h"
  50.  
  51. /*
  52.  * These global parameters are read from the compressed file.
  53.  * The decompressor needs them.
  54.  */
  55. short        maxbits = BITS;        /* settable max # bits/code    */
  56. code_int    maxmaxcode = 1 << BITS;
  57.  
  58. /*
  59.  * Note, if export is zero or 1, the "true" value will be set from
  60.  * the file header.  If it is 2, no header will be read.
  61.  */
  62. #if VMS_V4
  63. flag        export = 0;        /* Assume VMS private        */
  64. #else
  65. flag        export = 1;        /* Assume Unix compatible    */
  66. #endif
  67. flag        binary = FALSE;        /* Read text if false        */
  68. flag        block_compress = TRUE;    /* TRUE if CLEAR enabled    */
  69. flag        noheader = FALSE;    /* No magic header if TRUE    */
  70. flag        verbose = VERBOSE_DEFAULT; /* Non-zero for status/debug    */
  71. flag        background = FALSE;    /* TRUE (Unix) if detached    */
  72. flag        is_compress = FALSE;    /* For lzio.c (?)        */
  73. char        *infilename = NULL;    /* For error printouts        */
  74. char        *outfilename = NULL;    /* For openoutput and errors    */
  75. int        firstcode;        /* First code after internals    */
  76. static long    start_time;        /* Time we started (in msec)    */
  77. extern long    cputime();        /* Returns process time in msec    */
  78. jmp_buf        failure;
  79. STREAM        instream;
  80. STREAM        outstream;
  81. char_type    inbuffer[MAXIO];
  82. char_type    outbuffer[MAXIO];
  83. static STREAM    mem_stream;
  84. #if VMS_V4
  85. #include <descrip.h>
  86. #ifndef FDLSTUFF
  87. #define FDLSTUFF char
  88. #endif
  89. FDLSTUFF    *fdl_input;
  90. FDLSTUFF    *fdl_output;
  91. static struct dsc$descriptor fdl_descriptor;
  92. #endif
  93.  
  94. main(argc, argv)
  95. int        argc;
  96. char        *argv[];
  97. /*
  98.  * Decompress mainline
  99.  */
  100. {
  101.     int        result;
  102.  
  103. #ifndef    decus
  104.     /*
  105.      * background is TRUE if running detached from the command terminal.
  106.      */
  107.     background = (signal(SIGINT, SIG_IGN) == SIG_IGN) ? TRUE : FALSE;
  108.     if (!background)
  109.         background = !isatty(fileno(stderr));
  110.     if (!background) {
  111.         if (verbose > 0)
  112.         signal(SIGINT, abort);
  113.         else {
  114.         signal(SIGINT, interrupt);
  115.         signal(SIGSEGV, address_error);
  116.         }
  117.     }
  118. #endif
  119.     if (setjmp(failure) == 0) {
  120.         setup(argc, argv);
  121.         openinput();
  122.         get_magic_header();            /* Sets export, etc.    */
  123.         openoutput();
  124.         if (verbose > 0)
  125.         start_time = cputime();
  126.         init_decompress();
  127.         result = decompress(&outstream);
  128.         if (!export
  129.          && result != LZ_ETX
  130.          && getcode() != (code_int) LZ_ETX) {
  131.         fprintf(stderr, "Decompress didn't finish correctly.\n");
  132.         goto fail;
  133.         }
  134.         lz_flush(&outstream);
  135. #if DEBUG
  136.         if ((verbose & 04) != 0)
  137.         dump_tab(stdout);
  138. #endif
  139.         if (verbose > 0) {
  140.         start_time = cputime() - start_time;
  141.         fprintf(stderr,
  142.             "%ld.%02ld seconds (process time) for decompression.\n",
  143.             start_time / 1000L, (start_time % 1000L) / 10L);
  144.         }
  145.         exit(IO_SUCCESS);
  146.     }
  147.     else {
  148. fail:        fprintf(stderr, "Error when decompressing \"%s\" to \"%s\"\n",
  149.         (infilename  == NULL) ? 
  150.             "<input file unknown>" : infilename,
  151.         (outfilename == NULL) ?
  152.             "<no output file>" : outfilename);
  153.         if (errno != 0)
  154.         perror("lzdcmp fatal error");
  155.         exit(IO_ERROR);
  156.     }
  157. }
  158.  
  159. static
  160. get_magic_header()
  161. {
  162.     int        head1;
  163.     int        head2;
  164.     int        head3;
  165.  
  166.     head2 = 0;
  167.     if (export != 2) {
  168.         if ((head1 = GET(&instream)) != HEAD1_MAGIC) {
  169.         fprintf(stderr, "Incorrect first header byte 0x%X\n",
  170.             head1);
  171.         FAIL("can't get header");
  172.         }
  173.         head2 = GET(&instream);
  174.         head3 = GET(&instream);
  175.         switch (head2) {
  176.         case HEAD2_MAGIC:
  177.         export = 1;
  178.         break;
  179.  
  180.         case VMS_HEAD2_MAGIC:
  181.         export = 0;
  182.         break;
  183.  
  184.         default:
  185.         fprintf(stderr, "Incorrect second header byte 0x%X\n",
  186.             head2);
  187.         FAIL("can't get header");
  188.         }
  189.         maxbits = head3 & BIT_MASK;
  190.         block_compress = ((head3 & BLOCK_MASK) != 0) ? TRUE : FALSE;
  191. #if DEBUG
  192.         if (verbose > 1) {
  193.         fprintf(stderr, "%s: compressed with %d bits,",
  194.            infilename, maxbits);
  195.         fprintf(stderr, " block compression %s.\n",
  196.             (block_compress != 0) ? "enabled" : "disabled");
  197.         }
  198. #endif
  199.     }
  200.     if (maxbits > BITS) {
  201.         fprintf(stderr, "%s: compressed with %d bits,",
  202.         infilename, maxbits);
  203.         fprintf(stderr, " lzdcmp can only handle %d bits\n", BITS);
  204.         FAIL("too many bits");
  205.     }
  206.     maxmaxcode = 1 << maxbits;
  207.     if (export == 0)
  208.         firstcode = GET(&instream) + 0x100;    /* From compressed file    */
  209.     else if (block_compress)
  210.         firstcode = LZ_CLEAR + 1;        /* Default        */
  211.     else
  212.         firstcode = 256;            /* Backwards compatible    */
  213. #if VMS_V4
  214.     if (!export) {
  215.         register code_int    code;
  216.         char        text[256];
  217.         /*
  218.          * Get the attribute record.
  219.          */
  220.         if ((code = getcode()) != LZ_SOH) {
  221.         fprintf(stderr, "Expected header, read 0x%X\n", code);
  222.         FAIL("can't get header (private)");
  223.         }
  224.         init_decompress();
  225.         code = mem_decompress(text, sizeof text);
  226.         text[code] = EOS;
  227.         if (strncmp(text, ATT_NAME, ATT_SIZE) != 0) {
  228.         fprintf(stderr, "Expected \"%s\", read \"%.*s\"\n",
  229.             ATT_NAME, code, text);
  230.         FAIL("can't get attribute block header");
  231.         }
  232.         code = atoi(text + ATT_SIZE);
  233.         fdl_descriptor.dsc$a_pointer = malloc(code);
  234.         fdl_descriptor.dsc$w_length = code;
  235.         if ((code = mem_decompress(fdl_descriptor.dsc$a_pointer, code))
  236.             != fdl_descriptor.dsc$w_length) {
  237.         fprintf(stderr, "\nError reading fdl attributes block,");
  238.         fprintf(stderr, " expected %d bytes, read %d bytes\n",
  239.             fdl_descriptor.dsc$w_length, code);
  240.         FAIL("can't get attribute block data");
  241.         }
  242.         if (verbose > 1) {
  243.         fprintf(stderr, "\nFDL information read from \"%s\"\n",
  244.             infilename);
  245.         fdl_dump(&fdl_descriptor, stderr);
  246.         }
  247.         if ((code = getcode()) != LZ_STX) {
  248.         fprintf(stderr, "\nExpecting start of text, got 0x%X\n", code);
  249.         FAIL("no start of text");
  250.         }
  251.     }
  252. #endif
  253. }
  254.  
  255. int
  256. mem_decompress(buffer, size)
  257. char_type    *buffer;
  258. int        size;
  259. /*
  260.  * Decompress up to size bytes to buffer.  Return actual size.
  261.  */
  262. {
  263.     int        result;
  264.  
  265.     mem_stream.bp = mem_stream.bstart = buffer;
  266.     mem_stream.bend = buffer + size;
  267.     mem_stream.bsize = size;
  268.     mem_stream.func = lz_fail;
  269.     if ((result = decompress(&mem_stream)) == LZ_EOR
  270.      || result == LZ_ETX)
  271.         return (mem_stream.bp - buffer);
  272.     else {
  273.         fprintf(stderr, "Decompress to memory failed.\n");
  274.         FAIL("can't decompress to memory");
  275.     }
  276.     return (-1);                /* Can't happen        */
  277. }
  278.  
  279. static readonly char *helptext[] = {
  280.     "The following options are valid:",
  281.     "-B\tBinary file (important on VMS/RSX, ignored on Unix)",
  282.     "-M val\tSet the maximum number of code bits (unless header present)",
  283.     "-V val\tPrint status information or debugging data.",
  284.     "-X val\tSet export (compatibility) mode:",
  285.     "-X 0\tVMS private mode",
  286.     "-X 1\tCompatibility with Unix compress",
  287.     "-X 2\tDo not read a header, disable \"block-compress\" mode",
  288.     "\t(If a header is present, lzdcmp will properly configure itself,",
  289.     "\toverriding the -X, -B and -M flag values.",
  290.     NULL,
  291. };
  292.  
  293. static
  294. setup(argc, argv)
  295. int        argc;
  296. char        *argv[];
  297. /*
  298.  * Get parameters and open files.  Exit fatally on errors.
  299.  */
  300. {
  301.     register char    *ap;
  302.     register int    c;
  303.     char        **hp;
  304.     auto int    i;
  305.     int        j;
  306.  
  307. #ifdef    vms
  308.     argc = getredirection(argc, argv);
  309. #endif
  310.     for (i = j = 1; i < argc; i++) {
  311.         ap = argv[i];
  312.         if (*ap++ != '-' || *ap == EOS)    /* Filename?        */
  313.         argv[j++] = argv[i];        /* Just copy it        */
  314.         else {
  315.         while ((c = *ap++) != EOS) {
  316.             if (islower(c))
  317.             c = toupper(c);
  318.             switch (c) {
  319.             case 'B':
  320.             binary = TRUE;
  321.             break;
  322.  
  323.             case 'M':
  324.             maxbits = getvalue(ap, &i, argv);
  325.             if (maxbits < MIN_BITS) {
  326.                 fprintf(stderr, "Illegal -M value\n");
  327.                 goto usage;
  328.             }
  329.             break;
  330.  
  331.             case 'V':
  332.             verbose = getvalue(ap, &i, argv);
  333.             break;
  334.  
  335.             case 'X':
  336.             export = getvalue(ap, &i, argv);
  337.             if (export < 0 || export > 3) {
  338.                 fprintf(stderr, "Illegal -X value: %d\n", export);
  339.                 goto usage;
  340.             }
  341.             block_compress = (export < 2);
  342.             noheader = (export == 3);
  343.             break;
  344.  
  345.             default:
  346.             fprintf(stderr, "Unknown option '%c' in \"%s\"\n",
  347.                 *ap, argv[i]);
  348. usage:            for (hp = helptext; *hp != NULL; hp++)
  349.                 fprintf(stderr, "%s\n", *hp);
  350.             FAIL("unknown option");
  351.             }                /* Switch on options    */
  352.         }                /* Everything for -xxx    */
  353.         }                    /* If -option        */
  354.     }                    /* For all argc's    */
  355.     /*  infilename = NULL; */        /* Set "stdin"  signal    */
  356.     /* outfilename = NULL; */        /* Set "stdout" signal    */
  357.     switch (j) {                /* Any file arguments?    */
  358.     case 3:                    /* both files given    */
  359.         if (!streq(argv[2], "-"))        /* But - means stdout    */
  360.         outfilename = argv[2];
  361.     case 2:                    /* Input file given    */
  362.         if (!streq(argv[1], "-")) {
  363.         infilename = argv[1];
  364.         }
  365.         break;
  366.  
  367.     case 0:                    /* None!        */
  368.     case 1:                    /* No file arguments    */
  369.         break;
  370.  
  371.     default:
  372.         fprintf(stderr, "Too many file arguments\n");
  373.         FAIL("too many files");
  374.     }
  375. }
  376.  
  377. static int
  378. getvalue(ap, ip, argv)
  379. register char        *ap;
  380. int            *ip;
  381. char            *argv[];
  382. /*
  383.  * Compile a "value".  We are currently scanning *ap, part of argv[*ip].
  384.  * The following are possible:
  385.  *    -x123        return (123) and set *ap to EOS so the caller
  386.  *    ap^        cycles to the next argument.
  387.  *
  388.  *    -x 123        *ap == EOS and argv[*ip + 1][0] is a digit.
  389.  *            return (123) and increment *i to skip over the
  390.  *            next argument.
  391.  *
  392.  *    -xy or -x y    return(1), don't touch *ap or *ip.
  393.  *
  394.  * Note that the default for "flag option without value" is 1.  This
  395.  * can only cause a problem for the -M option where the value is
  396.  * mandatory.  However, the result of 1 is illegal as it is less
  397.  * than INIT_BITS.
  398.  */
  399. {
  400.     register int    result;
  401.     register int    i;
  402.  
  403.     i = *ip + 1;
  404.     if (isdigit(*ap)) {
  405.         result = atoi(ap);
  406.         *ap = EOS;
  407.     }
  408.     else if (*ap == EOS
  409.           && argv[i] != NULL
  410.           && isdigit(argv[i][0])) {
  411.         result = atoi(argv[i]);
  412.         *ip = i;
  413.     }
  414.     else {
  415.         result = 1;
  416.     }
  417.     return (result);
  418. }
  419.  
  420. openinput()
  421. {
  422. #ifdef    decus
  423.     if (infilename == NULL) {
  424.         infilename = malloc(257);
  425.         fgetname(stdin, infilename);
  426.         infilename = realloc(infilename, strlen(infilename) + 1);
  427.     }
  428.     if (freopen(infilename, "rn", stdin) == NULL) {
  429.         perror(infilename);
  430.         FAIL("can't open compressed input");
  431.     }
  432. #else
  433. #ifdef vms
  434. #if VMS_V4
  435.     if (!export) {
  436.         if (infilename == NULL) {
  437.         infilename = malloc(256 + 1);
  438.         fgetname(stdin, infilename);
  439.         infilename = realloc(infilename, strlen(infilename) + 1);
  440.         }
  441.         if ((fdl_input = fdl_open(infilename, NULL)) == NULL) {
  442.         fdl_message(NULL, infilename);
  443.         FAIL("can't open compressed input (vms private)");
  444.         }
  445.     }
  446.     else
  447. #endif
  448.     {
  449.         if (infilename == NULL) {
  450.         infilename = malloc(256 + 1);
  451.         fgetname(stdin, infilename);
  452.         infilename = realloc(infilename, strlen(infilename) + 1);
  453.         }
  454.         else {
  455.         if (freopen(infilename, "r", stdin) == NULL) {
  456.             perror(infilename);
  457.             FAIL("can't open compressed input (export)");
  458.         }
  459.         }
  460.     }
  461. #else
  462.     if (infilename == NULL)
  463.         infilename = "<stdin>";
  464.     else {
  465.         if (freopen(infilename, "r", stdin) == NULL) {
  466.         perror(infilename);
  467.         FAIL("can't open input");
  468.         }
  469.     }
  470. #endif
  471. #endif
  472.     instream.bp = instream.bend = NULL;
  473.     instream.bstart = inbuffer;
  474.     instream.bsize = sizeof inbuffer;
  475.     instream.func = lz_fill;
  476. }
  477.  
  478. openoutput()
  479. {
  480. #ifdef vms
  481. #if VMS_V4
  482.     if (!export) {
  483.         fclose(stdout);
  484.         stdout = NULL;
  485.         if ((fdl_output =
  486.             fdl_create(&fdl_descriptor, outfilename)) == NULL) {
  487.         fprintf(stderr, "Can't create output file\n");
  488.         if ((fdl_status & 01) == 0)
  489.             fdl_message(NULL, outfilename);
  490.         FAIL("can't create output (vms private)");
  491.         }
  492.         if (outfilename == NULL) {
  493.         outfilename = malloc(256 + 1);
  494.         fdl_getname(fdl_output, outfilename);
  495.         outfilename = realloc(outfilename, strlen(outfilename) + 1);
  496.         }
  497.     }
  498.     else
  499. #endif
  500.     {
  501.         /*
  502.          * Not VMS Version 4, or export mode.
  503.          */
  504.         if (outfilename == NULL) {
  505.         outfilename = malloc(256 + 1);
  506.         fgetname(stdout, outfilename);
  507.         outfilename = realloc(outfilename, strlen(outfilename) + 1);
  508.         if (!binary)
  509.             goto do_reopen;
  510.         }
  511.         else {
  512.         if (binary) {
  513.             if (freopen(outfilename, "w", stdout) == NULL) {
  514.             perror(outfilename);
  515.             FAIL("can't create output (binary)");
  516.             }
  517.         }
  518.         else {
  519.             int        i;
  520. do_reopen:
  521.             if ((i = creat(outfilename, 0, "rat=cr", "rfm=var")) == -1
  522.              || dup2(i, fileno(stdout)) == -1) {
  523.             perror(outfilename);
  524.             FAIL("can't create output (text)");
  525.             }
  526.         }
  527.         }
  528.     }
  529. #else
  530. #ifdef decus
  531.     if (outfilename == NULL) {
  532.         outfilename = malloc(256 + 1);
  533.         fgetname(stdout, outfilename);
  534.         outfilename = realloc(outfilename, strlen(outfilename) + 1);
  535.         if (binary) {
  536.         if (freopen(outfilename, "wn", stdout) == NULL) {
  537.             perror(outfilename);
  538.             FAIL("can't create (binary)");
  539.         }
  540.         }
  541.     }
  542.     else {
  543.         if (freopen(outfilename, (binary) ? "wn" : "w", stdout) == NULL) {
  544.         perror(outfilename);
  545.         FAIL("can't create");
  546.         }
  547.     }
  548. #else
  549.     if (outfilename == NULL)
  550.         outfilename = "<stdout>";
  551.     else {
  552.         if (freopen(outfilename, "w", stdout) == NULL) {
  553.         perror(outfilename);
  554.         FAIL("can't create");
  555.         }
  556.     }
  557. #endif
  558. #endif
  559.     outstream.bp = outstream.bstart = outbuffer;
  560.     outstream.bend = outbuffer + sizeof outbuffer;
  561.     outstream.bsize = sizeof outbuffer;
  562.     outstream.func = lz_flush;
  563. }
  564. -h- lzdcm2.c    Wed Jul 24 11:49:34 1985    USER$A:[MINOW.LZ]LZDCM2.C;10
  565. /*
  566.  *            l z d c m 2 . c
  567.  *
  568.  * Actual decompression code
  569.  */
  570.  
  571. #include "lz.h"
  572.  
  573. /*
  574.  * These global parameters are read from the compressed file.
  575.  * The decompressor needs them.
  576.  */
  577. extern short    maxbits;        /* settable max # bits/code    */
  578. extern code_int    maxmaxcode;        /* 1 << maxbits            */
  579.  
  580. static flag    first_clear = TRUE;
  581.  
  582. /*
  583.  * Big data storage stuff
  584.  */
  585.  
  586. static char_type    stack[MAXSTACK];
  587. #define    STACK_TOP    (&stack[MAXSTACK])
  588. static U_short        tab_prefix[1 << BITS];    /* prefix code        */
  589. static char_type      tab_suffix[1 << BITS];    /* last char in string    */
  590. code_int        next_code;
  591.  
  592. #if DEBUG
  593. #define    CHECK(what)                        \
  594.     if (stp <= stack) {                    \
  595.         fprintf(stderr, "Stack overflow -- %s\n", what);    \
  596.         abort();                        \
  597.     }
  598. #else
  599. #define CHECK(what)
  600. #endif
  601.  
  602. int
  603. decompress(out)
  604. STREAM        *out;
  605. /*
  606.  * Decompress instream (global) to out.  Returns "end" signal:
  607.  *    -1    end of file
  608.  *    LZ_EOR    end of record
  609.  *    LZ_ETX    end of segment
  610.  */
  611. {
  612.     register char_type    *stp;        /* Stack pointer    */
  613.     register code_int code, oldcode, incode;
  614.     register int        final;    /* End of a sequence?    */
  615.     extern code_int        getcode();
  616.  
  617.     stp = STACK_TOP;
  618.     final = oldcode = getcode();
  619.     PUT((char) final, out);
  620.     while ((code = getcode()) >= 0) {
  621. test:        if (code >= LZ_CLEAR && code < firstcode) {
  622.         lz_putbuf(stp, STACK_TOP - stp, out);
  623.         stp = STACK_TOP;
  624.         switch (code) {
  625.         case LZ_ETX:
  626.         case LZ_EOR:
  627.             goto finish;
  628.  
  629.         case LZ_SOH:            /* Unexpected        */
  630.         case LZ_STX:            /* Unexpected        */
  631.         default:
  632.             fprintf(stderr, "\nUnexpected control 0x%X\n", code);
  633.             FAIL("Unexpected control");
  634.  
  635.         case LZ_CLEAR:
  636.             init_decompress();        /* Before getcode() !! */
  637.             if ((code = getcode()) < 0
  638.               || (export && code == LZ_CLEAR))
  639.             goto finish;
  640.             else {
  641.             /*
  642.              * init_decompress has set next_code to firstcode,
  643.              * however, for magical reasons, we want to toss
  644.              * the next substring, so we set next_code so
  645.              * that the tab_... entry is effectively ignored.
  646.              * Note below that tab_prefix[next_code] is set
  647.              * to the character before the LZ_CLEAR and
  648.              * tab_suffix to the character after the LZ_CLEAR.
  649.              * But, these values have no relationship to one
  650.              * another, so, by decrementing next_code, they
  651.              * will be ignored.  (I think.)
  652.              */
  653.             next_code--;
  654.             goto test;
  655.             }
  656.         }
  657.         }
  658.         incode = code;
  659.         /*
  660.          * Special case for KwKwK string.
  661.          */
  662.         if (code >= next_code) {
  663.         CHECK("KwKwK");
  664.         *--stp = final;
  665.         code = oldcode;
  666.         }
  667.         /*
  668.          * Generate output characters in reverse order
  669.          */
  670. #ifdef interdata
  671.         while (((unsigned long) code) >= ((unsigned long) NBR_CHAR)) {
  672. #else
  673.         while (code >= NBR_CHAR) {
  674. #endif
  675.         CHECK("generate output");
  676.         *--stp = tab_suffix[code];
  677.         code = tab_prefix[code];
  678.         }
  679.         CHECK("final char");
  680.         *--stp = final = tab_suffix[code];
  681.         /*
  682.          * And put them out in forward order
  683.          */
  684.         lz_putbuf(stp, STACK_TOP - stp, out);
  685.         stp = STACK_TOP;
  686.         /*
  687.          * Generate the new entry.
  688.          */
  689.         if ((code = next_code) < maxmaxcode) {
  690.         tab_prefix[code] = (U_short) oldcode;
  691.         tab_suffix[code] = final;
  692.         next_code++;
  693.         } 
  694.         /*
  695.          * Remember previous code.
  696.          */
  697.         oldcode = incode;
  698.     }
  699. finish:
  700.     return (code);
  701. }
  702.  
  703. init_decompress()
  704. /*
  705.  * Called on cold start, or on LZ_SOH, LZ_STX, LZ_CLEAR.
  706.  */
  707. {
  708.     register char_type    *cp;
  709.     register U_short    *up;
  710.     register int        code;
  711.  
  712.     if (first_clear) {
  713.         for (cp = &tab_suffix[0], code = 0; cp < &tab_suffix[NBR_CHAR];)
  714.         *cp++ = code++;
  715.         first_clear = FALSE;
  716.     }
  717.     else {
  718. #if ((NBR_CHAR % 8) != 0)
  719.         << error, the following won't work >>
  720. #endif
  721.         for (up = &tab_prefix[0]; up < &tab_prefix[NBR_CHAR];) {
  722.         *up++ = 0;
  723.         *up++ = 0;
  724.         *up++ = 0;
  725.         *up++ = 0;
  726.         *up++ = 0;
  727.         *up++ = 0;
  728.         *up++ = 0;
  729.         *up++ = 0;
  730.         }
  731.     }
  732.     next_code = firstcode;
  733. }
  734.  
  735. #if DEBUG
  736. dump_tab(dumpfd)
  737. FILE        *dumpfd;
  738. /*
  739.  * dump string table
  740.  */
  741. {
  742.     register char_type    *stp;    /* Stack pointer        */
  743.     register int        i;
  744.     register int        ent;
  745.     extern char        *dumpchar();
  746.  
  747.     stp = STACK_TOP;
  748.     fprintf(dumpfd, "%d %s in string table\n",
  749.         next_code, (next_code == 1) ? "entry" : "entries");
  750.     for (i = 0; i < next_code; i++) {
  751.         fprintf(dumpfd, "%5d: %5d/'%s' ",
  752.         i, tab_prefix[i], dumpchar(tab_suffix[i]));
  753.         for (ent = i;;) {
  754.         *--stp = tab_suffix[ent];
  755.         if (ent < firstcode)
  756.             break;
  757.         ent = tab_prefix[ent];
  758.         }
  759.         dumptext(stp, STACK_TOP - stp, dumpfd);
  760.         stp = STACK_TOP;
  761.     }
  762. }
  763. #endif
  764. -h- lzdcm3.c    Wed Jul 24 11:49:34 1985    USER$A:[MINOW.LZ]LZDCM3.C;14
  765. /*
  766.  *            l z d c m 3 . c
  767.  *
  768.  * Read codes from the input stream.
  769.  */
  770.  
  771. #include "lz.h"
  772.  
  773.  
  774. #if !vax_asm
  775. static readonly char_type rmask[9] = {
  776.     0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
  777. };
  778. #endif
  779. #if DEBUG
  780. extern int    col;
  781. static int    todump;
  782. #endif
  783.  
  784. /*
  785.  * getcode()
  786.  *
  787.  * Read one code from the standard input.  If EOF, return -1.
  788.  * Inputs:
  789.  *     stdin (via GET)
  790.  * Outputs:
  791.  *     code or -1 is returned.
  792.  */
  793.  
  794. extern code_int        next_code;
  795. extern STREAM        instream;
  796. extern code_int        maxmaxcode;
  797. extern short        maxbits;
  798. static short        n_bits = INIT_BITS;
  799. static code_int        maxcode = MAXCODE(INIT_BITS);
  800.  
  801. /*
  802.  * buf[] contains 8-bit data read from the input stream.  getcode()
  803.  * treats buf[] as a vector of bits, repacking it into variable-bit codes.
  804.  */
  805. static char_type    buf[BITS];
  806. static int        offset = 0;    /* Offset into buf    IN BITS     */
  807. static int        size = 0;    /* Actual size of buf IN BITS     */
  808.  
  809. code_int
  810. getcode()
  811. {
  812.     /*
  813.      * On the VAX (4.2 bsd), it is important to have the register
  814.      * declarations in exactly the order given, or the asm will break.
  815.      */
  816.     register code_int     code;
  817.     register int        r_off, bits;
  818.     register char_type    *bp;
  819.  
  820.     bp = buf;
  821.     if (next_code > maxcode) {
  822.         n_bits++;
  823.         if (n_bits == maxbits)
  824.         maxcode = maxmaxcode;
  825.         else {
  826.         maxcode = MAXCODE(n_bits);
  827.         }
  828.         size = 0;
  829. #if DEBUG
  830.         if (verbose > 2) {
  831.         fprintf(stderr, "\nChange to %d bits", n_bits);
  832.         col = 74;
  833.         }
  834. #endif
  835.     }
  836.     if (offset >= size) {
  837.         size = lz_getbuf(buf, n_bits, &instream);
  838. #if DEBUG
  839.         if (verbose > 4 || todump > 0) {
  840.         dumphex(buf, size, stderr);
  841.         if (todump > 0)
  842.             todump -= size;
  843.         }
  844. #endif
  845.         if (size <= 0)
  846.         return (-1);            /* end of file        */
  847.         offset = 0;
  848.         /*
  849.          * Round size down to integral number of codes in the buffer.
  850.          * (Expressed as a number of bits).
  851.          */
  852.         size = (size << 3) - (n_bits - 1);
  853.     }
  854.     r_off = offset;
  855.     bits = n_bits;
  856. #if vax_asm
  857.     asm("extzv   r10,r9,(r8),r11");
  858. #else
  859.     /*
  860.      * Get to the first byte.
  861.      */
  862.     bp += (r_off >> 3);
  863.     r_off &= 7;
  864.     /*
  865.      * Get first part (low order bits)
  866.      */
  867. #if UCHAR
  868.     code = (*bp++ >> r_off);
  869. #else
  870.     /*
  871.      * Don't touch the 0xFF; it prevents sign extension.
  872.      */
  873.     code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xFF;
  874. #endif
  875.     bits -= (8 - r_off);
  876.     r_off = 8 - r_off;        /* now, offset into code word    */
  877.     /*
  878.      * Get any 8 bit parts in the middle (<=1 for up to 16 bits).
  879.      */
  880.     if (bits >= 8) {
  881. #if UCHAR
  882.         code |= *bp++ << r_off;
  883. #else
  884.         code |= (*bp++ & 0xFF) << r_off;
  885. #endif
  886.         r_off += 8;
  887.         bits -= 8;
  888.     }
  889.     /* high order bits. */
  890. #if UCHAR
  891.     code |= (*bp & rmask[bits]) << r_off;
  892. #else
  893.     code |= (*bp & rmask[bits]) << r_off;
  894. #endif
  895.     /*
  896.      * End of non-vax (Unix) specific code.
  897.      */
  898. #endif
  899.     offset += n_bits;
  900.     if (code >= LZ_CLEAR && code < firstcode) {
  901.         switch (code) {
  902.         case LZ_SOH:
  903.         case LZ_STX:
  904.         case LZ_CLEAR:
  905.         size = 0;            /* Force read next time    */
  906.         n_bits = INIT_BITS;
  907.         maxcode = MAXCODE(INIT_BITS);
  908. #if DEBUG
  909.         if (verbose > 1) {
  910.             fprintf(stderr, "Read %s (%d)\n",
  911.             lz_names[code - LZ_CLEAR], code);
  912.             todump = 32;
  913.         }
  914. #endif
  915.         break;
  916.         }
  917.     }
  918. #if DEBUG
  919.     if (verbose > 3) {
  920.         fprintf(stderr, "%c%5d %5d",
  921.         ((col += 12) >= 72) ? (col = 0, '\n') : ' ',
  922.         code, next_code);
  923.         if (code >= LZ_CLEAR && code < firstcode) {
  924.         fprintf(stderr, " = %s", lz_names[code - LZ_CLEAR]);
  925.             col = 74;
  926.         }
  927.     }
  928. #endif
  929.     return (code);
  930. }
  931.  
  932.