home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / LZW.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  19KB  |  604 lines

  1. /*      SM0RGV data compression routines.
  2.  * This file implements the Lempel-Ziv Welch (LZW) data compression
  3.  * algorithm but with a variable code size, as in GIF format files.
  4.  *
  5.  * Copyright 1990 by Anders Klemets, SM0RGV. Permission granted for
  6.  * non-commercial distribution only.
  7.  */
  8.   
  9. #include <ctype.h>
  10. #include "global.h"
  11. #ifdef  LZW
  12. #include "mbuf.h"
  13. #include "proc.h"
  14. #include "lzw.h"
  15. #include "socket.h"
  16. #include "usock.h"
  17. #include "session.h"
  18. #include "cmdparse.h"
  19.  
  20. static int Lzwtrace = 0;
  21.   
  22. static void fastencode __ARGS((struct usock *up,char data));
  23. static void morebits __ARGS((struct lzw *lzw));
  24. static void cleartbl __ARGS((struct lzw *lzw));
  25. static void addtobuffer __ARGS((struct usock *up,int32 code));
  26. static void addchar __ARGS((char data,struct lzw *lzw));
  27. static void getstring __ARGS((int32 code,struct lzw *lzw));
  28. static char firstchar __ARGS((int32 code,struct lzw *lzw));
  29. static void decodetbl __ARGS((int32 code,struct lzw *lzw));
  30. static int32 nextcode __ARGS((struct usock *up));
  31. #pragma option -w-
  32.   
  33. int
  34. dolzw(argc,argv,p)
  35. int argc;
  36. char *argv[];
  37. void *p;
  38. {
  39.     if(argc > 1) {
  40.         switch(tolower(*argv[1])) {
  41.             case 'm':
  42.                 if(argc == 2) {
  43.                     tprintf("LZW mode: %s\n",Lzwmode ? "fast" : "compact");
  44.                 } else {
  45.                     Lzwmode = (tolower(*argv[2]) == 'f');
  46.                 }
  47.                 return 0;
  48.             case 'b':
  49.                 argc--;
  50.                 argv++;
  51.                 return setintrc(&Lzwbits,"LZW bits",argc,argv,9,16);
  52.             case 't':
  53.                 argc--;
  54.                 argv++;
  55.                 return setbool(&Lzwtrace,"Trace LZW compression ratios",argc,argv);
  56.             case '=':
  57.                 if(argc == 3) {
  58.                     struct session *sp;
  59.                     if((sp = sessptr(argv[2])) != NULLSESSION) {
  60.                         lzwinit(sp->s,Lzwbits,Lzwmode);
  61.                     }
  62.                 }
  63.                 return 0;
  64.         }
  65.     }
  66.     tputs("Usage: lzw <mode|bits|trace> <value>\n");
  67.     return -1;
  68. }
  69.   
  70. /* Initialize a socket for compression. Bits specifies the maximum number
  71.  * of bits per codeword. The input and output code tables might grow to
  72.  * about (2^bits * 3) bytes each. The bits parameter does only serve as a
  73.  * recommendation for the decoding, the actual number of bits may be
  74.  * larger, but not never more than 16.
  75.  */
  76. void
  77. lzwinit(s,bits,mode)
  78. int s;      /* socket to operate on */
  79. int bits;   /* maximum number of bits per codeword */
  80. int mode;   /* compression mode, LZWCOMPACT or LZWFAST */
  81. {
  82.     struct usock *up;
  83.     if((up = itop(s)) == NULLUSOCK)
  84.         return;
  85.     up->zout = (struct lzw *) callocw(1,sizeof(struct lzw));
  86.     up->zin = (struct lzw *) callocw(1,sizeof(struct lzw));
  87.     up->zout->codebits = LZWBITS;
  88.     if(bits < LZWBITS)
  89.         up->zout->maxbits = LZWBITS;
  90.     if(bits > 16 || bits == 0)
  91.         up->zout->maxbits = 16;
  92.     if(bits >= LZWBITS && bits <= 16)
  93.         up->zout->maxbits = bits;
  94.     up->zout->nextbit = 0;
  95.     up->zout->prefix = -1;
  96.     up->zout->version = -1;
  97.     up->zout->code = -1;
  98.     up->zout->mode = mode;
  99.     up->zout->next = ZFLUSH + 1;    /* used only in LZWFAST mode */
  100.     up->zin->codebits = LZWBITS;
  101.     up->zin->maxbits = -1;
  102.     up->zin->nextbit = 0;
  103.     up->zin->prefix = -1;
  104.     up->zin->version = -1;
  105.     up->zin->code = -1;
  106.     up->zin->next = ZFLUSH + 1;
  107.     up->zin->mode = LZWCOMPACT;
  108.     up->zin->buf = NULLBUF;
  109. }
  110.   
  111. void
  112. lzwfree(up)
  113. struct usock *up;
  114. {
  115.     int32 sent=0, recvd=0;
  116.  
  117.     if (Lzwtrace) {
  118.         if (up->type == TYPE_TCP)
  119.             rxtx_data_compute(up->cb.tcb,&sent,&recvd);
  120.  
  121.         if (up->zout != NULLLZW || up->zin != NULLLZW)
  122.             tputs("Compression ratios: compressed/uncompressed:\n");
  123.     }
  124.  
  125.     if(up->zout != NULLLZW) {
  126.         if (Lzwtrace && up->zout->cnt != 0L)
  127.             tprintf("Output: %ld/%ld = %ld\%\n",
  128.                 sent, up->zout->cnt,
  129.                 (up->zout->cnt - sent)*100L/up->zout->cnt);
  130.         cleartbl(up->zout);
  131.         free((char *)up->zout);
  132.         up->zout = NULLLZW;
  133.     }
  134.     if(up->zin != NULLLZW) {
  135.         if (Lzwtrace && up->zin->cnt != 0L)
  136.             tprintf("Input:  %ld/%ld = %ld\%\n",
  137.                 recvd, up->zin->cnt, 
  138.                 (up->zin->cnt - recvd)*100L/up->zin->cnt);
  139.         cleartbl(up->zin);
  140.         free_q(&up->zin->buf);
  141.         free((char *)up->zin);
  142.         up->zin = NULLLZW;
  143.     }
  144. }
  145. /* LZW encoding routine.
  146.  * See if the string specified by code + data is in the string table. If so,
  147.  * set prefix equal to the code of that string. Otherwise insert code + data
  148.  * in the string and set prefix equal to data.
  149.  */
  150. void
  151. lzwencode(s,data)
  152. int s;
  153. char data;
  154. {
  155.     struct usock *up;
  156.     register struct lzw *lzw;
  157.     int32 code, pagelim;
  158.     register unsigned int i,j;
  159.   
  160.     if((up = itop(s)) == NULLUSOCK)
  161.         return;
  162.     lzw = up->zout;
  163.     code = up->zout->prefix;
  164.     /* the first byte sent will be the version number */
  165.     if(lzw->version == -1) {
  166.         lzw->version = ZVERSION;
  167.         up->obuf->data[up->obuf->cnt++] = lzw->version;
  168.         /* then send our recommended maximum number of codebits */
  169.         up->obuf->data[up->obuf->cnt++] = lzw->maxbits;
  170.     }
  171.     lzw->cnt++;
  172.     if(code == -1) {
  173.         lzw->prefix = (int32) uchar(data);
  174.         return;
  175.     }
  176.     if(lzw->mode == LZWFAST) {
  177.         fastencode(up,data);
  178.         return;
  179.     }
  180.     pagelim = ((int32) 1 << lzw->codebits) / LZWBLK + 1;
  181.     if(code <= ZFLUSH)
  182.         i = j = 0;
  183.     else {
  184.         i = (code - ZFLUSH) / LZWBLK;
  185.         j = (code - ZFLUSH) % LZWBLK;
  186.     }
  187.     if(lzw->tu.tbl == (struct zentry **)0)
  188.         lzw->tu.tbl = (struct zentry **) callocw(1,
  189.         sizeof(struct zentry *) * pagelim);
  190.     for(;;) {
  191.         if(itop(s) == NULLUSOCK) /* the connection has been closed */
  192.             return;
  193.         if(up->zout == NULLLZW) /* ...or is about to be closed */
  194.             return;
  195.         if(lzw->tu.tbl[i] == (struct zentry *)0) {
  196.             lzw->tu.tbl[i] = (struct zentry *)
  197.             mallocw(LZWBLK * sizeof(struct zentry));
  198.             memset((char *)lzw->tu.tbl[i], 0xff,
  199.             LZWBLK * sizeof(struct zentry));
  200.         }
  201.         while(j < LZWBLK) {
  202.             if(lzw->tu.tbl[i][j].data == data &&
  203.             lzw->tu.tbl[i][j].code == (int16) code) {
  204.                 lzw->prefix = (int32)(i * LZWBLK + j +
  205.                 ZFLUSH + 1);
  206.                 return;
  207.             }
  208.             if(lzw->tu.tbl[i][j].code == 0xffff) {
  209.                 lzw->tu.tbl[i][j].code = (int16) code;
  210.                 lzw->tu.tbl[i][j].data = data;
  211.                 addtobuffer(up,code);
  212.                 lzw->prefix = (int32) uchar(data);
  213.                 lzw->next++;
  214.                 if(lzw->next == (int32) 1 << lzw->codebits)
  215.                     /* the current table is now full */
  216.                     morebits(lzw);
  217.                 if(lzw->next + 1 == (int32)
  218.                 1 << lzw->maxbits) {
  219.                 /* The last codeword has been reached.
  220.                  * (Or last - 1.) Signal this and start all
  221.                  * over again.
  222.                  */
  223.                     addtobuffer(up,lzw->prefix);
  224.                     if(lzw->next + 1 == (int32)
  225.                         1 << lzw->codebits)
  226.                         morebits(lzw);
  227.                     addtobuffer(up,ZCC);
  228.                     cleartbl(lzw);
  229.                 }
  230.                 return;
  231.             }
  232.             ++j;
  233.         }
  234.         pwait(NULL);
  235.         ++i;
  236.         j = 0;
  237.     }
  238. }
  239.   
  240. /* Used when LZWFAST mode is selected. Memory usage approx. (2^bits * 5)
  241.  * bytes.
  242.  */
  243. static void
  244. fastencode(up,data)
  245. struct usock *up;
  246. char data;
  247. {
  248.     register struct zfast *z;
  249.     register struct mbuf *bp;
  250.     register struct lzw *lzw = up->zout;
  251.     int32 code = up->zout->prefix;
  252.     register int16 cnt, h;
  253.   
  254.     if(lzw->tu.bpp == NULLBUFP)
  255.         lzw->tu.bpp = (struct mbuf **) callocw(1,
  256.         sizeof(struct mbuf *) * ZHASH);
  257.     h = lobyte(code);
  258.     h ^= hibyte(code);
  259.     h ^= data;
  260.     h = h % ZHASH;
  261.     if(lzw->tu.bpp[h] == NULLBUF)
  262.         lzw->tu.bpp[h] = ambufw(LZWBLK);
  263.     bp = lzw->tu.bpp[h];
  264.     cnt = bp->cnt / sizeof(struct zfast);
  265.     z = (struct zfast *) bp->data;
  266.     while(cnt > 0) {
  267.         if(z->data == data && z->code == (int16) code) {
  268.             lzw->prefix = (int32) z->owncode;
  269.             return;
  270.         }
  271.         z++;
  272.         if(--cnt == 0) {
  273.             if(bp->next == NULLBUF)
  274.                 break;
  275.             bp = bp->next;
  276.             cnt = bp->cnt / sizeof(struct zfast);
  277.             z = (struct zfast *) bp->data;
  278.         }
  279.     }
  280.     if(bp->size - bp->cnt >= sizeof(struct zfast)) {
  281.         z = (struct zfast *) &bp->data[bp->cnt];
  282.         bp->cnt += sizeof(struct zfast);
  283.     }
  284.     else {
  285.         bp->next = ambufw(LZWBLK);
  286.         z = (struct zfast *) bp->next->data;
  287.         bp->next->cnt = sizeof(struct zfast);
  288.     }
  289.     z->code = (int16) code;
  290.     z->data = data;
  291.     z->owncode = (int16) lzw->next++;
  292.     addtobuffer(up,code);
  293.     lzw->prefix = (int32) uchar(data);
  294.     if(lzw->next == (int32) 1 << lzw->codebits) {
  295.         /* Increase the number of bits per codeword */
  296.         morebits(lzw);
  297.     }
  298.     if(lzw->next + 1 == (int32) 1 << lzw->maxbits) {
  299.         /* The last codeword has been reached. (Or last - 1.)
  300.          * Signal this and start all over again.
  301.          */
  302.         addtobuffer(up,lzw->prefix);
  303.         if(lzw->next + 1 == (int32) 1 << lzw->codebits)
  304.             morebits(lzw);
  305.         addtobuffer(up,ZCC);
  306.         cleartbl(lzw);
  307.     }
  308.     pwait(NULL);
  309. }
  310.   
  311. /* increase the number of significant bits in the codewords, and increase
  312.  * the size of the string table accordingly.
  313.  */
  314. static void
  315. morebits(lzw)
  316. struct lzw *lzw;
  317. {
  318.     struct zentry **newt;
  319.     int32 pagelim, oldp;
  320.     oldp = ((int32) 1 << lzw->codebits) / LZWBLK + 1;
  321.     lzw->codebits++;
  322.     if(lzw->mode == LZWFAST)
  323.         return;
  324.     pagelim = ((int32) 1 << lzw->codebits) / LZWBLK + 1;
  325.     newt = (struct zentry **) callocw(1,sizeof(struct zentry *)*pagelim);
  326.     memcpy(newt,lzw->tu.tbl,sizeof(struct zentry *) * oldp);
  327.     free((char *)lzw->tu.tbl);
  328.     lzw->tu.tbl = newt;
  329. }
  330.   
  331. static void
  332. cleartbl(lzw)
  333. struct lzw *lzw;
  334. {
  335.     int32 pagelim,i;
  336.     pagelim = ((int32) 1 << lzw->codebits) / LZWBLK + 1;
  337.     lzw->codebits = LZWBITS;
  338.     lzw->prefix = -1;
  339.     lzw->next = ZFLUSH + 1;
  340.     if(lzw->tu.p == NULL)
  341.         return;
  342.     if(lzw->mode == LZWCOMPACT)
  343.         for(i=0; i < pagelim; ++i)
  344.             free((char *)lzw->tu.tbl[i]);
  345.     else
  346.         for(i=0; i < ZHASH; ++i)
  347.             free_p(lzw->tu.bpp[i]);
  348.     free((char *)lzw->tu.p);
  349.     lzw->tu.p = NULL;
  350. }
  351. /* Add a codeword to the code stream. Nextbit indicates at which bit in the
  352.  * code stream should be written first. The codeword ZFLUSH is used to
  353.  * pad the buffer to a byte boundary when the buffer will be flushed.
  354.  * The remaining bits of the ZFLUSH codeword are sent in the next buffer.
  355.  */
  356. static void
  357. addtobuffer(up,code)
  358. struct usock *up;
  359. int32 code;
  360. {
  361.     if(up->zout->code != -1) {
  362.         /* Insert remaining bits of ZFLUSH codeword */
  363.         up->obuf->data[up->obuf->cnt] =
  364.         up->zout->code >> up->zout->flushbit;
  365.         if(up->zout->flushbit + 8 >= up->zout->codebits) { /* done */
  366.             up->zout->nextbit = (up->zout->codebits -
  367.             up->zout->flushbit) % 8;
  368.             if(up->zout->nextbit == 0)
  369.                 ++up->obuf->cnt;
  370.             up->zout->code = -1;
  371.         }
  372.         else {
  373.             /* not done yet */
  374.             ++up->obuf->cnt;
  375.             up->zout->flushbit += 8;
  376.             addtobuffer(up,code);
  377.             return;
  378.         }
  379.     }
  380.     /* normal codewords are treated here */
  381.     if(up->zout->nextbit == 0) {
  382.         /* we are at a byte boundary */
  383.         if(code == ZFLUSH) {
  384.             up->zout->flushbit = 0;
  385.             up->zout->code = ZFLUSH;
  386.             return;
  387.         }
  388.         up->obuf->data[up->obuf->cnt++] = (char) code;
  389.     }
  390.     else
  391.         up->obuf->data[up->obuf->cnt++] |= code << up->zout->nextbit;
  392.     if(code == ZFLUSH) {
  393.         /* interrupt here and save the rest of the ZFLUSH
  394.          * codeword for later.
  395.          */
  396.         up->zout->flushbit = 8 - up->zout->nextbit;
  397.         up->zout->code = ZFLUSH;
  398.         return;
  399.     }
  400.     up->obuf->data[up->obuf->cnt] = code >> 8 - up->zout->nextbit;
  401.     /* start on a third byte if necessary */
  402.     if(16 - up->zout->nextbit < up->zout->codebits)
  403.         up->obuf->data[++up->obuf->cnt] =
  404.         code >> 16 - up->zout->nextbit;
  405.     up->zout->nextbit = (up->zout->nextbit + up->zout->codebits) % 8;
  406.     if(up->zout->nextbit == 0)
  407.         ++up->obuf->cnt;
  408. }
  409.   
  410. void
  411. lzwflush(up)
  412. struct usock *up;
  413. {
  414.     /* interrupt the encoding process and send the prefix codeword */
  415.     if(up->zout->prefix != -1) {
  416.         addtobuffer(up,up->zout->prefix);
  417.         if(up->zout->next + 1 == (int32) 1 << up->zout->codebits)
  418.             morebits(up->zout);
  419.         up->zout->prefix = -1;
  420.     }
  421.     /* signal this by sending the ZFLUSH codeword */
  422.     addtobuffer(up,ZFLUSH);
  423. }
  424.   
  425. int
  426. lzwdecode(up)
  427. struct usock *up;
  428. {
  429.     int32 code,data;
  430.     if(up->zin->version == -1 && (up->zin->version = PULLCHAR(&up->ibuf))
  431.         == -1)
  432.         return -1;
  433.     if(up->zin->maxbits == -1) {
  434.         /* receive a recommended value for the maximum no of bits */
  435.         if((up->zin->maxbits = PULLCHAR(&up->ibuf)) == -1)
  436.             return -1;
  437.         if(up->zout->maxbits > up->zin->maxbits) {
  438.             if(up->zout->codebits > up->zin->maxbits) {
  439.                 /* We are already using more bits than our
  440.                  * peer want us to, so clear the encoding
  441.                  * table immediately.
  442.                  */
  443.                 addtobuffer(up,up->zout->prefix);
  444.                 if(up->zout->next + 1 == (int32)
  445.                     1 << up->zout->codebits)
  446.                     morebits(up->zout);
  447.                 addtobuffer(up,ZCC);
  448.                 cleartbl(up->zout);
  449.             }
  450.             up->zout->maxbits = up->zin->maxbits;
  451.         }
  452.     }
  453.     for(;;) {
  454.         if((data = PULLCHAR(&up->zin->buf)) != -1)
  455.             return (int) data;
  456.         if((code = nextcode(up)) == -1)
  457.             return -1;
  458.         decodetbl(code,up->zin);
  459.         up->zin->cnt += len_p(up->zin->buf);
  460.     }
  461. }
  462.   
  463. static void
  464. addchar(data,lzw)
  465. char data;
  466. struct lzw *lzw;
  467. {
  468.     lzw->buf = pushdown(lzw->buf,1);
  469.     *lzw->buf->data = data;
  470. }
  471. static void
  472. getstring(code,lzw)
  473. int32 code;
  474. struct lzw *lzw;
  475. {
  476.     int i,j;
  477.     for(;;) {
  478.         if(code < ZFLUSH) {
  479.             addchar(uchar(code),lzw);
  480.             return;
  481.         }
  482.         i = (code - ZFLUSH - 1) / LZWBLK;
  483.         j = (code - ZFLUSH - 1) % LZWBLK;
  484.         addchar(lzw->tu.tbl[i][j].data,lzw);
  485.         code = (int32) lzw->tu.tbl[i][j].code;
  486.     }
  487. }
  488. static char
  489. firstchar(code,lzw)
  490. int32 code;
  491. struct lzw *lzw;
  492. {
  493.     int i,j;
  494.     for(;;) {
  495.         if(code < ZFLUSH)
  496.             return uchar(code);
  497.         i = (code - ZFLUSH - 1) / LZWBLK;
  498.         j = (code - ZFLUSH - 1) % LZWBLK;
  499.         code = (int32) lzw->tu.tbl[i][j].code;
  500.     }
  501. }
  502. static void
  503. decodetbl(code,lzw)
  504. int32 code;
  505. struct lzw *lzw;
  506. {
  507.     register unsigned int i,j;
  508.     int32 pagelim;
  509.   
  510.     if(code > lzw->next) {
  511.         printf("LZW protocol error, process %s\n",Curproc->name);
  512.         return;
  513.     }
  514.     if(lzw->buf == NULLBUF) {
  515.         lzw->buf = ambufw(512);
  516.         /* allow us to use pushdown() later */
  517.         lzw->buf->data += lzw->buf->size;
  518.     }
  519.     if(lzw->prefix == -1) {
  520.         getstring(code,lzw);
  521.         lzw->prefix = code;
  522.         return;
  523.     }
  524.     pagelim = ((int32) 1 << lzw->codebits) / LZWBLK + 1;
  525.     if(lzw->tu.tbl == (struct zentry **)0)
  526.         lzw->tu.tbl = (struct zentry **) callocw(1,
  527.         sizeof(struct zentry *) * pagelim);
  528.     if(code < ZFLUSH)
  529.         goto intable;
  530.     i = (code - ZFLUSH - 1) / LZWBLK;
  531.     j = (code - ZFLUSH - 1) % LZWBLK;
  532.     if(lzw->tu.tbl[i] == (struct zentry *)0) {
  533.         lzw->tu.tbl[i] = (struct zentry *)
  534.         mallocw(LZWBLK * sizeof(struct zentry));
  535.         memset((char *)lzw->tu.tbl[i], 0xff,
  536.         LZWBLK * sizeof(struct zentry));
  537.     }
  538.     if(lzw->tu.tbl[i][j].code == 0xffff) {
  539.         lzw->tu.tbl[i][j].data = firstchar(lzw->prefix,lzw);
  540.         lzw->tu.tbl[i][j].code = (int16) lzw->prefix;
  541.         getstring(code,lzw);
  542.         lzw->next = code + 1;
  543.         lzw->prefix = code;
  544.         if(lzw->next + 1 == (int32) 1 << lzw->codebits)
  545.             morebits(lzw);
  546.         return;
  547.     }
  548.     intable:
  549.     getstring(code,lzw);
  550.     i = (lzw->next - ZFLUSH - 1) / LZWBLK;
  551.     j = (lzw->next - ZFLUSH - 1) % LZWBLK;
  552.     if(lzw->tu.tbl[i] == (struct zentry *)0) {
  553.         lzw->tu.tbl[i] = (struct zentry *)
  554.         mallocw(LZWBLK * sizeof(struct zentry));
  555.         memset((char *)lzw->tu.tbl[i], 0xff,
  556.         LZWBLK * sizeof(struct zentry));
  557.     }
  558.     lzw->tu.tbl[i][j].data = firstchar(code,lzw);
  559.     lzw->tu.tbl[i][j].code = (int16) lzw->prefix;
  560.     lzw->next++;
  561.     lzw->prefix = code;
  562.     if(lzw->next + 1 == (int32) 1 << lzw->codebits)
  563.         morebits(lzw);
  564. }
  565.   
  566. /* extract the next codeword from the input stream */
  567. static int32
  568. nextcode(up)
  569. struct usock *up;
  570. {
  571.     int32 code;
  572.     if(up->zin->code == -1) {   /* read the first character */
  573.         if((code = PULLCHAR(&up->ibuf)) == -1)
  574.             return -1;
  575.         up->zin->code = code >> up->zin->nextbit;
  576.     }
  577.     if(up->ibuf == NULLBUF)     /* next byte is not available yet */
  578.         return -1;
  579.     /* continue assembling the codeword */
  580.     up->zin->code |= ((int32) uchar(*up->ibuf->data) <<
  581.     8 - up->zin->nextbit) & (((int32) 1 <<
  582.     up->zin->codebits) - 1);
  583.     if(16 - up->zin->nextbit < up->zin->codebits) {
  584.         (void) PULLCHAR(&up->ibuf);
  585.         up->zin->nextbit -= 8; /* pull bits from a third byte */
  586.         return nextcode(up);
  587.     }
  588.     code = up->zin->code;
  589.     up->zin->code = -1;
  590.     up->zin->nextbit = (up->zin->nextbit + up->zin->codebits) % 8;
  591.     if(up->zin->nextbit == 0)
  592.         (void) PULLCHAR(&up->ibuf);
  593.     if(code == ZCC) {
  594.         cleartbl(up->zin);
  595.         return nextcode(up);
  596.     }
  597.     if(code == ZFLUSH) {
  598.         up->zin->prefix = -1;
  599.         return nextcode(up);
  600.     }
  601.     return code;
  602. }
  603. #endif
  604.