home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 181_01 / lzwunc.c < prev    next >
Text File  |  1985-03-10  |  4KB  |  148 lines

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