/* LZWUNC - FILE UNCOMPRESSOR UTILITY */ #include "stdio.h" #include "fcntl.h" #include "sgtty.h" #define FALSE 0 #define TRUE !FALSE #define TABSIZE 4096 #define STACKSIZE TABSIZE #define NO_PRED -1 #define EMPTY -1 #define NOT_FND -1 #define NO_UPDATE FALSE struct entry { char used; int next; /* hi bit is 'used' flag */ int predecessor; /* 12 bit code */ char follower; } string_tab[TABSIZE]; char is_a_con = FALSE; /* suppresses printing dots during operation if outfd is the console */ /* routines common to compress and decompress, contained in CommLZW.c */ hash(); unhash(); getcode(); putcode(); init_tab(); upd_tab(); main(argc,argv) int argc; char *argv[]; { int c, tempc, code, oldcode, incode, finchar; int code_count = TABSIZE - 256; int infd, outfd; register struct entry *ep; if (3 != argc) { printf("Usage : lzwunc squeezefilename newfilename\n"); exit(0); } if ( -1 == (infd = open( *++argv, O_RDONLY )) ) { printf("Cant open %s\n", *argv); exit(0); } if ( -1 == (outfd = creat(*++argv,0666)) ) { printf("Cant create %s\n",*argv); exit(0); } is_a_con = isatty(outfd); /* suppress dots if it is */ init_tab(); /* set up atomic code definitions*/ code = oldcode = getcode(infd); c = string_tab[code].follower; /* first code always known */ writec(outfd,c); finchar = c; while ( EOF != (code = incode = getcode(infd)) ) { ep = &string_tab[code]; /* initialize pointer */ if ( !ep->used ) { /* if code isn't known */ writec(outfd,finchar); /* the follower char of last */ code = oldcode; /* revert to last known code */ incode = hash(oldcode,finchar,NO_UPDATE); ep = &string_tab[code]; /* re-initialize pointer */ } while (NO_PRED != ep->predecessor) { push( ep->follower); /* decode string backwards into */ /* stack */ code = ep->predecessor; ep = &string_tab[code]; } /* above loop terminates, one way or another, with */ /* string_tab[code].follower = first char in string */ finchar = ep->follower; writec(outfd, finchar); #ifdef DEBUG putchar(finchar); #endif /* pop anything stacked during code parsing */ while ( EMPTY != (tempc = pop()) ) { writec(outfd,tempc); #ifdef DEBUG putchar(tempc); #endif } if ( code_count ) { upd_tab(oldcode,finchar); --code_count; } oldcode = incode; } flushout(outfd); /* write out fractional buffer, if any */ exit(0); /* close all files and quit */ } char stack[STACKSIZE]; /* stack for pushing and popping characters */ int sp = 0; /* current stack pointer */ push(c) int c; { stack[sp] = ((char) c);/* coerce passed integer into a character */ ++sp; if (sp >= STACKSIZE) { printf("Stack overflow, aborting\n"); exit(1); /* non-0 exit parameter terminates batch job */ } } pop() { if (sp > 0) { --sp; /* push leaves sp pointing to next empty slot */ return ( (int) stack[sp] ); /* make sure pop returns char */ } else return EMPTY; }