home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / COMPRESS / LZW.ZIP / LZWUNC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-08-20  |  4.1 KB  |  146 lines

  1.  
  2. /* LZWUNC - FILE UNCOMPRESSOR UTILITY                                   */
  3. #include "stdio.h"
  4. #include "debug.h"
  5. #define FALSE    0
  6. #define TRUE     !FALSE
  7. #define TABSIZE  4096
  8. #define STACKSIZE TABSIZE
  9. #define NO_PRED  0xFFFF
  10. #define EMPTY    0xF000
  11. #define NOT_FND  0xFFFF
  12. #define NO_UPDATE FALSE
  13. #define UEOF ((unsigned)EOF)
  14.  
  15. struct entry {
  16.   char used;
  17.   unsigned int next;        /* hi bit is 'used' flag                        */
  18.   unsigned int predecessor; /* 12 bit code                  */
  19.   unsigned char follower;
  20. } string_tab[TABSIZE];
  21.  
  22. /*   routines common to compress and decompress, contained in CommLZW.c */
  23. unsigned hash();
  24. unsigned unhash();
  25. unsigned getcode();
  26. putcode();
  27. init_tab();
  28. upd_tab();
  29.  
  30. FILE *op; /* global file pointer - gets assigned from outfd so that getch can
  31.              determine whether or not to print stuff to the screen */
  32.  
  33. main(argc,argv)
  34. int argc; char *argv[];
  35. {
  36.   register unsigned int c;
  37.   int tempc, code, oldcode, incode, finchar,lastchar;
  38.   char unknown = FALSE;
  39.   int code_count = TABSIZE - 256;
  40.   FILE *infd, *outfd;
  41.   register struct entry *ep;
  42.  
  43.   if (3 != argc) {
  44.     fprintf(stderr,"Usage : lzwunc squeezefilename newfilename\n");
  45.     exit(0);
  46.   }
  47.   if ( -1 == (infd = fopen( *++argv, "r")) ) {
  48.     fprintf(stderr,"Cant open %s\n", *argv);
  49.     exit(0);
  50.   }
  51.   if ( -1 == (op = outfd = fopen(*++argv,"w")) ) {
  52.     fprintf(stderr,"Cant create %s\n",*argv);
  53.     exit(0);
  54.   }
  55.  
  56.   init_tab();                           /* set up atomic code definitions*/
  57.   code = oldcode = getcode(infd);
  58.   c = string_tab[code].follower;        /* first code always known      */
  59.   putc(c,outfd);
  60.   DEBUGGER(\
  61.        putc(c,stderr);\
  62.        fprintf(stderr,"\n%x\n",code);\
  63.   )
  64.   finchar = c;
  65.  
  66.   while ( UEOF != (code = incode = getcode(infd)) ) {
  67.     DEBUGGER(fprintf(stderr,"\n%x\n",code);)
  68.     ep = &string_tab[code];             /* initialize pointer           */
  69.     if ( !ep->used ) 
  70.     {                  /* if code isn't known          */
  71.       lastchar = finchar;
  72.       code = oldcode;
  73.       unknown = TRUE;
  74.       ep = &string_tab[code];           /* re-initialize pointer        */
  75.     }
  76.  
  77.     while (NO_PRED != ep->predecessor) 
  78.     {
  79.       push( ep->follower);              /* decode string backwards into */
  80.                                         /* stack                        */
  81.       code = ep->predecessor;
  82.       ep = &string_tab[code];
  83.     }
  84.  
  85.     finchar = ep->follower;
  86.     /* above loop terminates, one way or another, with                  */
  87.     /* string_tab[code].follower = first char in string                 */
  88.  
  89.     putc(finchar,outfd);
  90.     DEBUGGER(putc(finchar,stderr);)
  91.     /* pop anything stacked during code parsing                         */
  92.     while ( EMPTY != (tempc = pop()) ) 
  93.     {
  94.       putc(tempc,outfd);
  95.       DEBUGGER(\
  96.         putc(tempc,stderr);\
  97.       )
  98.     }
  99.     if ( unknown ) {                  /* if code isn't known          */
  100.       putc(finchar = lastchar,outfd); /* the follower char of last    */
  101.       unknown = FALSE;
  102.       DEBUGGER(\
  103.           putc(lastchar,stderr);\
  104.         fprintf(stderr,"\nunknown code\n");\
  105.       )
  106.     }
  107.     if ( code_count ) 
  108.     {
  109.       upd_tab(oldcode,finchar);
  110.       --code_count;
  111.       DEBUGGER(fprintf(stderr,"\nAdding %x,%c = %x\n",\
  112.                   oldcode,finchar,unhash(oldcode,finchar));)
  113.     }
  114.     oldcode = incode;
  115.   }
  116.   flushout(outfd);      /* write out fractional buffer, if any          */
  117.   exit(0);              /* close all files and quit                     */
  118. }
  119.  
  120. char stack[STACKSIZE];  /* stack for pushing and popping characters     */
  121. int sp = 0;             /* current stack pointer                        */
  122.  
  123. push(c)
  124. register int c;
  125. {
  126.   stack[sp] = ((char) c);/* coerce passed integer into a character      */
  127.   ++sp;
  128.   if (sp >= STACKSIZE) {
  129.     fprintf(stderr,"Stack overflow, aborting\n");
  130.     exit(1);            /* non-0 exit parameter terminates batch job    */
  131.   }
  132. }
  133.  
  134. pop() 
  135. {
  136.   if (sp > 0) 
  137.   {
  138.     --sp;               /* push leaves sp pointing to next empty slot   */
  139.     return ( (int) stack[sp] ); /* make sure pop returns char           */
  140.   }
  141.   else
  142.     return EMPTY;
  143. }
  144.     
  145.  
  146.