home *** CD-ROM | disk | FTP | other *** search
- static char *sccsid = "@(#)usq.c 1.7u (UCF) 82/12/15";
- /*
- * usq.c - CP/M compatible file unsqueezer utility
- *
- * compile as follows:
- * cc [-DVAX] -O usq.c -o usq
- * (define VAX only if running on VAX)
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <limits.h>
- #include <signal.h>
- #include <ctype.h>
-
- #define ERROR (-1)
- #define PATHLEN 312 /* Number of characters allowed in pathname */
- #define OK 0
-
- #define RECOGNIZE 0xFF76 /* unlikely pattern */
- #define DLE 0x90 /* repeat byte flag */
- #define SPEOF 256 /* special endfile token */
- #define NUMVALS 257 /* 256 data values plus SPEOF*/
-
- /* 16 bit ints, please */
- typedef int INT16;
- typedef unsigned UNSIGNED;
- typedef long LONG32;
-
- struct sqleaf { /* Decoding tree */
- INT16 children[2]; /* left, right */
- };
- struct sqleaf Dnode[NUMVALS - 1];
-
- INT16 Bpos; /* last bit position read */
- INT16 Curin; /* last byte value read */
- INT16 Repct; /* Number of times to return value */
- INT16 Value; /* current byte value or EOF */
-
- INT16 getcr(void);
- INT16 getuhuff(void);
- INT16 portgetw(FILE *f);
- LONG32 remap(LONG32);
-
- main(int argc, char *argv[])
- {
- squeeze(argv[1]);
- }
-
- /*
- The following code is primarily from typesq.c and utr.c. Typesq
- is a modification of USQ by Dick Greenlaw. Those modifications (usq
- to typesq) were made by Bob Mathias, I am responsible for the butchery
- done to make it work with cat.
-
- */
-
- FILE *in;
- squeeze(fname)
- char *fname;
- {
- register INT16 i, c;
- register char *p;
- register INT16 numnodes; /* size of decoding tree */
- register UNSIGNED crc;
- UNSIGNED filecrc;
- char inl[BUFSIZ];
- INT16 inlcnt;
-
- init_cr(); init_huff(); crc=0;
-
- if((in=fopen( fname, "rb"))==NULL) {
- fprintf(stderr, "usq: can't open %s\n", fname);
- return ERROR;
- }
- if(portgetw(in) != (INT16) RECOGNIZE) {/* Process header */
- fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
- return(ERROR);
- }
- filecrc = (UNSIGNED) portgetw(in); /* checksum */
- while (getc(in)) /* Read and discard the name */
- ;
-
- numnodes = portgetw(in);
- if(numnodes < 0 || numnodes >= NUMVALS) {
- fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
- fclose(in);
- return(ERROR);
- }
- /* Initialize for possible empty tree (SPEOF only) */
- Dnode[0].children[0] = -(SPEOF + 1);
- Dnode[0].children[1] = -(SPEOF + 1);
-
- for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
- Dnode[i].children[0] = portgetw(in);
- Dnode[i].children[1] = portgetw(in);
- }
- inlcnt = 0;
- while (fgets(inl, sizeof(inl), stdin)){
- if (++inlcnt == 7) {
- sprintf(inl, "%ld\n", remap(atol(inl)));
- inlcnt = 0;
- }
- fputs(inl, stdout);
- }
- fclose(in);
- return(OK);
- }
-
- /* Map the original source position into the compressed bit position.
- *
- */
- LONG32
- remap(LONG32 pos)
- {
- static LONG32 inpos = 0L;
- int c;
-
- while (pos != inpos) {
- if ((c = getcr()) == EOF)
- abort();
- #ifdef notdef
- putchar(c);
- #endif
- inpos++;
- }
- fprintf(stderr, "ftell() = %ld, Bpos = %d\n", ftell(in), Bpos);
- if (Bpos == 99)
- return (ftell(in) << 3) + ((Bpos == 99)?0:(Bpos+1));
- return ((ftell(in)-1) << 3) + Bpos+1;
- }
-
-
- /*** from utr.c - */
- /* initialize decoding functions */
-
- init_cr()
- {
- Repct = 0;
- }
-
- init_huff()
- {
- Bpos = 99; /* force initial read */
- }
-
- /* Get bytes with decoding - this decodes repetition,
- * calls getuhuff to decode file stream into byte
- * level code with only repetition encoding.
- *
- * The code is simple passing through of bytes except
- * that DLE is encoded as DLE-zero and other values
- * repeated more than twice are encoded as value-DLE-count.
- */
-
- INT16
- getcr()
- {
- register INT16 c;
-
- if(Repct > 0) {
- /* Expanding a repeated char */
- --Repct;
- return(Value);
- } else {
- /* Nothing unusual */
- if((c = getuhuff()) != DLE) {
- /* It's not the special delimiter */
- Value = c;
- if(Value == EOF)
- Repct = INT_MAX;
- return(Value);
- } else {
- /* Special token */
- if((Repct = getuhuff()) == 0)
- /* DLE, zero represents DLE */
- return(DLE);
- else {
- /* Begin expanding repetition */
- Repct -= 2; /* 2nd time */
- return(Value);
- }
- }
- }
- }
- /* Decode file stream into a byte level code with only
- * repetition encoding remaining.
- */
-
- INT16
- getuhuff()
- {
- register INT16 i;
-
- /* Follow bit stream in tree to a leaf*/
- i = 0; /* Start at root of tree */
- do {
- if(++Bpos > 7) {
- if((Curin = getc(in)) == EOF)
- return(ERROR);
- Bpos = 0;
- /* move a level deeper in tree */
- i = Dnode[i].children[1 & Curin];
- } else
- i = Dnode[i].children[1 & (Curin >>= 1)];
- } while(i >= 0);
-
- /* Decode fake node index to original data value */
- i = -(i + 1);
- /* Decode special endfile token to normal EOF */
- return(i == SPEOF) ? EOF : i;
- }
- /*
- * Machine independent getw which always gets bytes in the same order
- * as the CP/M version of SQ wrote them
- */
- INT16
- portgetw(f)
- FILE *f;
- {
- register INT16 c;
-
- c = getc(f) & 0377;
- return(c | (getc(f) << 8));
- }
-