home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume02 / ucomp16 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  7.5 KB

  1. From mipos3!omepd!littlei!uunet!husc6!think!ames!necntc!ncoast!allbery Sat Apr  9 17:00:13 PDT 1988
  2. Article 340 of comp.sources.misc:
  3. Path: td2cad!mipos3!omepd!littlei!uunet!husc6!think!ames!necntc!ncoast!allbery
  4. From: uucpa@gamma.UUCP (UNIX-to-UNIX Copy)
  5. Newsgroups: comp.sources.misc
  6. Subject: v02i087: "Stripped" 16-bit uncompress
  7. Message-ID: <8804040317.AA15327@gamma.UUCP>
  8. Date: 4 Apr 88 03:17:49 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: uucpa@gamma.UUCP (UNIX-to-UNIX Copy)
  11. Lines: 267
  12. Approved: allbery@ncoast.UUCP
  13. comp.sources.misc: Volume 2, Issue 87
  14. Submitted-By: "UNIX-to-UNIX Copy" <uucpa@gamma.UUCP>
  15. Archive-Name: ucomp16
  16.  
  17. comp.sources.misc: Volume 2, Issue 87
  18. Submitted-By: "UNIX-to-UNIX Copy" <uucpa@gamma.UUCP>
  19. Archive-Name: ucomp16
  20.  
  21. The following is a stripped uncompress derived by rote from
  22. compress 3.x.  I did not keep the proper headers for this file
  23. to give proper credit to the authors since what i was trying to do
  24. was to get the 16 bit decompression on a machine that simply would
  25. not allow the resultant executable size.
  26.  
  27. MY APLOLOGIES AHEAD OF TIME!!!!!!!!
  28.  
  29. this conversion should be modified to include the original
  30. notices and things. and is only published to fill the gap
  31. on the smaller machines that can't handle the regular compress
  32. software.
  33.  
  34. sorry if this Tee 's anyone off.
  35.  
  36. ron tribble
  37. ....mibte!ccd700!ron
  38.  
  39. echo x - ucomp16.c
  40. sed 's/^X//' >ucomp16.c <<'*-*-END-of-ucomp16.c-*-*'
  41. X#define PBITS 16
  42. X#define BITS PBITS
  43. X
  44. Xunsigned    char magic_header[] = { 
  45. X    "\037\235" };    /* 1F 9D */
  46. X
  47. X/* Defines for third byte of header */
  48. X#define BIT_MASK    0x1f
  49. X#define BLOCK_MASK    0x80
  50. X/* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  51. Xa fourth header byte (for expansion).
  52. X*/
  53. X#define INIT_BITS 9        /* initial number of bits/code */
  54. X
  55. X#include <stdio.h>
  56. X
  57. Xint n_bits;                /* number of bits/code */
  58. Xint maxbits = BITS;            /* user settable max # bits/code */
  59. Xlong    int maxcode;            /* maximum code, given n_bits */
  60. Xlong    int maxmaxcode = 1 << BITS;    /* should NEVER generate this code */
  61. X# define MAXCODE(n_bits)    ((1 << (n_bits)) - 1)
  62. X
  63. X/*
  64. X* One code could conceivably represent (1<<BITS) characters, but
  65. X* to get a code of length N requires an input string of at least
  66. X* N*(N-1)/2 characters.  With 5000 chars in the stack, an input
  67. X* file would have to contain a 25Mb string of a single character.
  68. X* This seems unlikely.
  69. X*/
  70. X# define MAXSTACK    8000        /* size of output stack */
  71. X
  72. Xunsigned short tab_prefix [69001];
  73. Xunsigned    char      tab_suffix[1<<BITS];    /* last char in this entry */
  74. X
  75. Xlong    int free_ent = 0;            /* first unused entry */
  76. Xint exit_stat = 0;
  77. X
  78. Xlong    int getcode();
  79. X
  80. X/*
  81. X* block compression parameters -- after all codes are used up,
  82. X* and compression rate changes, start over.
  83. X*/
  84. Xint block_compress = BLOCK_MASK;
  85. Xint clear_flg = 0;
  86. X/*
  87. X* the next two codes should not be changed lightly, as they must not
  88. X* lie within the contiguous general code space.
  89. X*/
  90. X#define FIRST    257    /* first free entry */
  91. X#define    CLEAR    256    /* table clear output code */
  92. X
  93. Xmain()
  94. X{
  95. X    if(maxbits < INIT_BITS) maxbits = INIT_BITS;
  96. X    if (maxbits > BITS) maxbits = BITS;
  97. X    maxmaxcode = 1 << maxbits;
  98. X
  99. X    exit_stat = 0;
  100. X    /* Check the magic number */
  101. X    if ((getchar() != (magic_header[0] & 0xFF))
  102. X        || (getchar() != (magic_header[1] & 0xFF))) {
  103. X        fprintf(stderr,"not in compressed format\n");
  104. X        exit(1);
  105. X    }
  106. X    maxbits = getchar();    /* set -b from file */
  107. X    block_compress = maxbits & BLOCK_MASK;
  108. X    maxbits &= BIT_MASK;
  109. X    maxmaxcode = 1 << maxbits;
  110. X    if(maxbits > BITS) {
  111. X        fprintf(stderr,
  112. X            "compressed with %d bits, can only handle %d bits\n",
  113. X            maxbits, BITS);
  114. X        exit(1);
  115. X    }
  116. X    decompress();
  117. X    exit(exit_stat);
  118. X}
  119. Xunsigned    char rmask[9] = {
  120. X    0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  121. Xdecompress() {
  122. X    register int stack_top = MAXSTACK;
  123. X    register long    int code, oldcode, incode;
  124. X    register int finchar;
  125. X    char stack[MAXSTACK];
  126. X
  127. X    /*
  128. X* As above, initialize the first 256 entries in the table.
  129. X*/
  130. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  131. X    for ( code = 255; code >= 0; code-- ) {
  132. X        tab_prefix[code] = 0;
  133. X        tab_suffix[code] = (unsigned    char)code;
  134. X    }
  135. X    free_ent = ((block_compress) ? FIRST : 256 );
  136. X
  137. X    finchar = oldcode = getcode();
  138. X    putchar( (char)finchar );        /* first code must be 8 bits = char */
  139. X
  140. X    while ( (code = getcode()) != -1 ) {
  141. X
  142. X        if ( (code == CLEAR) && block_compress ) {
  143. X            for ( code = 255; code > 0; code -= 4 ) {
  144. X                tab_prefix [code-3] = 0;
  145. X                tab_prefix [code-2] = 0;
  146. X                tab_prefix [code-1] = 0;
  147. X                tab_prefix [code] = 0;
  148. X            }
  149. X            clear_flg = 1;
  150. X            free_ent = FIRST - 1;
  151. X            if ( (code = getcode ()) == -1 )    /* O, untimely death! */
  152. X                break;
  153. X        }
  154. X        incode = code;
  155. X        /*
  156. X* Special case for KwKwK string.
  157. X*/
  158. X        if ( code >= free_ent ) {
  159. X            stack[--stack_top] = finchar;
  160. X            code = oldcode;
  161. X        }
  162. X
  163. X        /*
  164. X* Generate output characters in reverse order
  165. X*/
  166. X        while ( code >= 256 ) {
  167. X            stack[--stack_top] = tab_suffix[code];
  168. X            code = tab_prefix[code];
  169. X        }
  170. X        stack[--stack_top] = finchar = tab_suffix[code];
  171. X
  172. X        /*
  173. X* And put them out in forward order
  174. X*/
  175. X        for ( ; stack_top < MAXSTACK; stack_top++ )
  176. X            putchar(stack[stack_top]);
  177. X        if (ferror(stdout))
  178. X            writeerr ( );
  179. X        stack_top = MAXSTACK;
  180. X
  181. X        /*
  182. X* Generate the new entry.
  183. X*/
  184. X        if ( (code=free_ent) < maxmaxcode ) {
  185. X            tab_prefix[code] = (unsigned short)oldcode;
  186. X            tab_suffix[code] = finchar;
  187. X            free_ent = code+1;
  188. X        }
  189. X        /*
  190. X* Remember previous code.
  191. X*/
  192. X        oldcode = incode;
  193. X    }
  194. X    fflush( stdout );
  195. X    if(ferror(stdout))
  196. X        writeerr();
  197. X}
  198. X
  199. X
  200. X/*****************************************************************
  201. X* TAG( getcode )
  202. X*
  203. X* Read one code from the standard input.  If EOF, return -1.
  204. X* Inputs:
  205. X*     stdin
  206. X* Outputs:
  207. X*     code or -1 is returned.
  208. X*/
  209. X
  210. Xlong    int
  211. Xgetcode() {
  212. X    /*
  213. X* On the VAX, it is important to have the register declarations
  214. X* in exactly the order given, or the asm will break.
  215. X*/
  216. X    register long    int code;
  217. X    static int offset = 0, size = 0;
  218. X    static unsigned    char buf[BITS];
  219. X    register int r_off, bits;
  220. X    register unsigned    char *bp = buf;
  221. X
  222. X    if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
  223. X        /*
  224. X* If the next entry will be too big for the current code
  225. X* size, then we must increase the size.  This implies reading
  226. X* a new buffer full, too.
  227. X*/
  228. X        if ( free_ent > maxcode ) {
  229. X            n_bits++;
  230. X            if ( n_bits == maxbits )
  231. X                maxcode = maxmaxcode;    /* won't get any bigger now */
  232. X            else
  233. X                maxcode = MAXCODE(n_bits);
  234. X        }
  235. X        if ( clear_flg > 0) {
  236. X            maxcode = MAXCODE (n_bits = INIT_BITS);
  237. X            clear_flg = 0;
  238. X        }
  239. X        size = fread( buf, 1, n_bits, stdin );
  240. X        if ( size <= 0 )
  241. X            return -1;            /* end of file */
  242. X        offset = 0;
  243. X        /* Round size down to integral number of codes */
  244. X        size = (size << 3) - (n_bits - 1);
  245. X    }
  246. X    r_off = offset;
  247. X    bits = n_bits;
  248. X    /*
  249. X* Get to the first byte.
  250. X*/
  251. X    bp += (r_off >> 3);
  252. X    r_off &= 7;
  253. X    /* Get first part (low order bits) */
  254. X    code = (*bp++ >> r_off);
  255. X    bits -= (8 - r_off);
  256. X    r_off = 8 - r_off;        /* now, offset into code word */
  257. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  258. X    if ( bits >= 8 ) {
  259. X        code |= *bp++ << r_off;
  260. X        r_off += 8;
  261. X        bits -= 8;
  262. X    }
  263. X    /* high order bits. */
  264. X    code |= (*bp & rmask[bits]) << r_off;
  265. X    offset += n_bits;
  266. X
  267. X    return code;
  268. X}
  269. X/*****************************************************************
  270. X* TAG( writeerr )
  271. X*
  272. X* Exits with a message.  We only check for write errors often enough
  273. X* to avoid a lot of "file system full" messages, not on every write.
  274. X* ferror() check after fflush will catch any others (I trust).
  275. X*
  276. X*/
  277. X
  278. Xwriteerr()
  279. X{
  280. X    exit ( 1 );
  281. X}
  282. *-*-END-of-ucomp16.c-*-*
  283. exit
  284.  
  285.  
  286.