home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3608 < prev    next >
Encoding:
Internet Message Format  |  1991-07-11  |  42.3 KB

  1. From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
  2. Newsgroups: alt.sources
  3. Subject: zoo 2.1 source part 03/15
  4. Message-ID: <12769@bsu-cs.bsu.edu>
  5. Date: 10 Jul 91 09:03:42 GMT
  6.  
  7. Checksum:  733558324 (verify with "brik -cv")
  8. Submitted-by: dhesi@bsu-cs.bsu.edu
  9. Archive-name: zoo210/part03
  10.  
  11. ---- Cut Here and feed the following to sh ----
  12. #!/bin/sh
  13. # This is part 03 of zoo210
  14. # ============= generic.c ==============
  15. if test -f 'generic.c' -a X"$1" != X"-c"; then
  16.     echo 'x - skipping generic.c (File already exists)'
  17. else
  18. echo 'x - extracting generic.c (Text)'
  19. sed 's/^X//' << 'SHAR_EOF' > 'generic.c' &&
  20. #ifndef LINT
  21. static char genericid[]="@(#) generic.c 2.2 88/01/24 12:44:03";
  22. #endif /* LINT */
  23. X
  24. /* 
  25. Generic template for machine-dependent functions.
  26. X
  27. The contents of this file are hereby released to the public domain
  28. X
  29. X                                            -- Rahul Dhesi 1991/07/05
  30. */
  31. X
  32. /****************
  33. Date and time functions are assumed to be standard **IX-style functions.
  34. */
  35. X
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include <time.h>
  39. X
  40. /* Function isadir() returns 1 if the supplied handle is a directory, 
  41. else it returns 0.  
  42. */
  43. X
  44. int isadir (file)
  45. ZOOFILE file;
  46. {
  47. X   int handle = fileno(file);
  48. X   struct stat buf;           /* buffer to hold file information */
  49. X   if (fstat (handle, &buf) == -1) {
  50. X      return (0);             /* inaccessible -- assume not dir */
  51. X   } else {
  52. X      if (buf.st_mode & S_IFDIR)
  53. X         return (1);
  54. X      else
  55. X         return (0);
  56. X   }
  57. }
  58. X
  59. /****************
  60. Function fixfname() converts the supplied filename to a syntax
  61. legal for the host system.  It is used during extraction.
  62. */
  63. X
  64. char *fixfname(fname)
  65. char *fname;
  66. {
  67. X    fname[FNLIMIT] = '\0';        /* Just truncate at filename size limit */
  68. X    return fname;
  69. }
  70. X
  71. /* The function gettz() returns the offset from GMT in seconds, taking
  72. into account the local timezone and any daylight savings time. */
  73. X
  74. /* This version of gettz should be portable to all Unices, although it
  75. can't be described as elegant.  Users immediately west of the International
  76. Date Line (Polynesia, Soviet Far East) may get times out by 24 hours.
  77. Contributed by: Ian Phillipps <igp@camcon.co.uk> */
  78. X
  79. long gettz()
  80. {
  81. #define NOONOFFSET 43200
  82. #define SEC_IN_DAY    (24L * 60L * 60L)
  83. #define INV_VALUE        (SEC_IN_DAY + 1L)
  84. X    static long retval = INV_VALUE;         /* cache, init to impossible value */
  85. X    extern long time();
  86. X    extern struct tm *localtime();
  87. X    long now;
  88. X    long noon;
  89. X    struct tm *noontm;
  90. X    if (retval != INV_VALUE)                 /* if have cached value, return it */
  91. X        return retval;
  92. X   now = time((long *) 0);
  93. X   /* Find local time for GMT noon today */
  94. X   noon = now - now % SEC_IN_DAY + NOONOFFSET ;
  95. X   noontm = localtime( &noon );
  96. X   retval = NOONOFFSET - 60 * ( 60 * noontm->tm_hour - noontm->tm_min );
  97. X    return retval;
  98. #undef NOONOFFSET
  99. }
  100. X
  101. /* Standard UNIX-compatible time functions */
  102. #include "nixtime.i"
  103. X
  104. /* Standard UNIX-specific file attribute routines */
  105. #include "nixmode.i"
  106. X
  107. /* Assume no file truncate system call.  Ok to be a no-op. */
  108. /*ARGSUSED*/
  109. int zootrunc(f) FILE *f; { return 0; }
  110. X    
  111. SHAR_EOF
  112. chmod 0644 generic.c ||
  113. echo 'restore of generic.c failed'
  114. Wc_c="`wc -c < 'generic.c'`"
  115. test 2422 -eq "$Wc_c" ||
  116.     echo 'generic.c: original size 2422, current size' "$Wc_c"
  117. fi
  118. # ============= getfile.c ==============
  119. if test -f 'getfile.c' -a X"$1" != X"-c"; then
  120.     echo 'x - skipping getfile.c (File already exists)'
  121. else
  122. echo 'x - extracting getfile.c (Text)'
  123. sed 's/^X//' << 'SHAR_EOF' > 'getfile.c' &&
  124. #ifndef LINT
  125. static char sccsid[]="@(#) getfile.c 2.7 88/01/24 12:44:23";
  126. #endif /* LINT */
  127. X
  128. /*
  129. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  130. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  131. */
  132. X
  133. #include "options.h"
  134. /*
  135. This function copies n characters from the source file to the destination
  136. X
  137. Input:   out_f:            destination file
  138. X         in_f:             source file
  139. X         count:         count of characters to copy
  140. X         docrc:         0 if crc not wanted
  141. X
  142. If count is -1, copying is done until eof is encountered.
  143. X
  144. The source file is transferred to the current file pointer position in the
  145. destination file, using the handles provided.  Function return value is 0
  146. if no error, 2 if write error, and 3 if read error.
  147. X
  148. If docrc is not 0, the global variable crccode is updated via addbfcrc().
  149. This is done even if the output is to the null device.
  150. X
  151. If UNBUF_IO is defined, and if more than UNBUF_LIMIT bytes are 
  152. being transferred or copying is to end of file, the data transfer 
  153. is done using low-level read() and write() functions, which must 
  154. be defined elsewhere.  File descriptors are obtained for this 
  155. purpose using the fileno() macro, which must be provided elsewhere 
  156. too.  This is meant to provide greater efficiency on some systems.
  157. The files of type ZOOFILE are synchronized with their file 
  158. descriptors by doing a reasonable number of seeks and other
  159. miscellaneous operations before and after the transfer.  Such 
  160. simultaneous use of buffered and unbuffered files is not
  161. portable and should not be used without extensive testing.
  162. */
  163. X
  164. #ifdef UNBUF_IO
  165. int read PARMS ((int, VOIDPTR, unsigned));
  166. int write PARMS ((int, VOIDPTR, unsigned));
  167. long lseek PARMS ((int, long, int));
  168. long tell PARMS ((int));
  169. #endif /* UNBUF_IO */
  170. X
  171. #include "zoo.h"        /* satisfy declarations in zooio.h */
  172. #include "zooio.h"
  173. #include "various.h"
  174. #include "zoofns.h"
  175. #include "zoomem.h"
  176. X
  177. int getfile (in_f, out_f, count, docrc)
  178. ZOOFILE in_f, out_f;
  179. long count;
  180. int docrc;
  181. {
  182. X   register int how_much;
  183. #ifdef UNBUF_IO
  184. X    int in_d, out_d;    /* file descriptors for unbuffered I/O */
  185. #endif /* UNBUF_IO */
  186. X
  187. #ifdef UNBUF_IO
  188. X    if (out_f != NULLFILE && (count == -1 || count > UNBUF_LIMIT)) {
  189. X        in_d = fileno (in_f);        /* get ..                        */
  190. X        out_d = fileno (out_f);        /* ... file descriptors        */
  191. X
  192. X        /* Synchronize buffered and unbuffered files */
  193. X        zooseek (in_f, zootell (in_f), 0);
  194. X        zooseek (out_f, zootell (out_f), 0);
  195. X
  196. #if 0
  197. X        lseek (in_d, zootell (in_f), 0);
  198. X        lseek (out_d, zootell (out_f), 0);
  199. #endif
  200. X
  201. X        if (count == -1) {
  202. X            while ((how_much = read (in_d, out_buf_adr, MEM_BLOCK_SIZE)) > 0) {
  203. X                if (how_much == -1 ||
  204. X                        write (out_d, out_buf_adr, how_much) != how_much)
  205. X                    return (2);
  206. X                if (docrc)
  207. X                    addbfcrc (out_buf_adr,how_much);
  208. X            }
  209. X            zooseek (in_f, tell (in_d), 0);        /* resynch    */
  210. X            zooseek (out_f, tell (out_d), 0);    /* resynch    */
  211. X
  212. #ifndef NDEBUG
  213. X            if (ftell (in_f) != tell (in_d) || ftell (out_f) != tell (out_d)) {
  214. X                prterror ('w', "seek mismatch in copy to EOF\n");
  215. X                printf ("in_f =%6ld, in_d =%6ld\n", ftell (in_f),  tell (in_d));
  216. X                printf ("out_f=%6ld, out_d=%6ld\n", ftell (out_f), tell (out_d));
  217. X            }
  218. #endif /* NDEBUG */
  219. X
  220. X            return (0);
  221. X        }
  222. X
  223. X        while (count > 0) {
  224. X            if (count > MEM_BLOCK_SIZE)
  225. X                how_much = MEM_BLOCK_SIZE;
  226. X            else
  227. X                how_much = (int) count;
  228. X            count -= how_much;
  229. X            if (read (in_d, out_buf_adr, how_much) != how_much)
  230. X                return (3);
  231. X            if (docrc)
  232. X                addbfcrc (out_buf_adr, how_much);
  233. X            if (write (out_d, out_buf_adr, how_much) != how_much)
  234. X                return (2);
  235. X        }
  236. X        zooseek (in_f, tell (in_d), 0);        /* resynch    */
  237. X        zooseek (out_f, tell (out_d), 0);    /* resynch    */
  238. #ifndef NDEBUG
  239. X        if (ftell (in_f) != tell (in_d) || ftell (out_f) != tell (out_d))
  240. X             prterror ('w', "seek mismatch in fixed length copy\n");
  241. #endif /* NDEBUG */
  242. X        return (0);
  243. X    }
  244. #endif /* UNBUF_IO */
  245. X
  246. X   if (count == -1) {
  247. X      while ((how_much = zooread (in_f, out_buf_adr, MEM_BLOCK_SIZE)) > 0) {
  248. X         if (how_much == -1 ||
  249. X               zoowrite (out_f, out_buf_adr, how_much) != how_much)
  250. X            return (2);
  251. X         if (docrc)
  252. X            addbfcrc (out_buf_adr,how_much);
  253. X      }
  254. X      return (0);
  255. X   }
  256. X
  257. X   while (count > 0) {
  258. X      if (count > MEM_BLOCK_SIZE)
  259. X         how_much = MEM_BLOCK_SIZE;
  260. X      else
  261. X         how_much = (int) count;
  262. X      count -= how_much;
  263. X      if (zooread (in_f, out_buf_adr, how_much) != how_much)
  264. X         return (3);
  265. X      if (docrc)
  266. X         addbfcrc (out_buf_adr, how_much);
  267. X      if (zoowrite (out_f, out_buf_adr, how_much) != how_much)
  268. X         return (2);
  269. X   }
  270. X   return (0);
  271. }
  272. SHAR_EOF
  273. chmod 0644 getfile.c ||
  274. echo 'restore of getfile.c failed'
  275. Wc_c="`wc -c < 'getfile.c'`"
  276. test 4549 -eq "$Wc_c" ||
  277.     echo 'getfile.c: original size 4549, current size' "$Wc_c"
  278. fi
  279. # ============= huf.c ==============
  280. if test -f 'huf.c' -a X"$1" != X"-c"; then
  281.     echo 'x - skipping huf.c (File already exists)'
  282. else
  283. echo 'x - extracting huf.c (Text)'
  284. sed 's/^X//' << 'SHAR_EOF' > 'huf.c' &&
  285. /*$Source: /usr/home/dhesi/zoo/RCS/huf.c,v $*/
  286. /*$Id: huf.c,v 1.9 91/07/09 01:39:55 dhesi Exp $*/
  287. /***********************************************************
  288. X    huf.c -- static Huffman
  289. X
  290. Adapted from "ar" archiver written by Haruhiko Okumura.
  291. ***********************************************************/
  292. #include "options.h"
  293. #include "zoo.h"
  294. #include "ar.h"
  295. #include "lzh.h"
  296. #include "errors.i"
  297. X
  298. extern void prterror();
  299. X
  300. #ifdef ANSI_HDRS
  301. # include <stdlib.h>
  302. #endif
  303. X
  304. #define NP (DICBIT + 1)
  305. #define NT (CODE_BIT + 3)
  306. #define PBIT 4  /* smallest integer such that (1U << PBIT) > NP */
  307. #define TBIT 5  /* smallest integer such that (1U << TBIT) > NT */
  308. #if NT > NP
  309. # define NPT NT
  310. #else
  311. # define NPT NP
  312. #endif
  313. X
  314. int decoded;        /* for use in decode.c */
  315. X
  316. ushort left[2 * NC - 1], right[2 * NC - 1];
  317. static uchar *buf, c_len[NC], pt_len[NPT];
  318. static uint   bufsiz = 0, blocksize;
  319. static ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],
  320. X              p_freq[2 * NP - 1], pt_table[256], pt_code[NPT],
  321. X              t_freq[2 * NT - 1];
  322. X
  323. /***** encoding *****/
  324. X
  325. static void count_t_freq()
  326. {
  327. X    int i, k, n, count;
  328. X
  329. X    for (i = 0; i < NT; i++) t_freq[i] = 0;
  330. X    n = NC;
  331. X    while (n > 0 && c_len[n - 1] == 0) n--;
  332. X    i = 0;
  333. X    while (i < n) {
  334. X        k = c_len[i++];
  335. X        if (k == 0) {
  336. X            count = 1;
  337. X            while (i < n && c_len[i] == 0) {  i++;  count++;  }
  338. X            if (count <= 2) t_freq[0] += count;
  339. X            else if (count <= 18) t_freq[1]++;
  340. X            else if (count == 19) {  t_freq[0]++;  t_freq[1]++;  }
  341. X            else t_freq[2]++;
  342. X        } else t_freq[k + 2]++;
  343. X    }
  344. }
  345. X
  346. static void write_pt_len(n, nbit, i_special)
  347. int n;
  348. int nbit;
  349. int i_special;
  350. {
  351. X    int i, k;
  352. X
  353. X    while (n > 0 && pt_len[n - 1] == 0) n--;
  354. X    putbits(nbit, (uint) n);
  355. X    i = 0;
  356. X    while (i < n) {
  357. X        k = pt_len[i++];
  358. X        if (k <= 6) putbits(3, (uint) k);
  359. X        else putbits(k - 3, (uint) (((unsigned) 1 << (k - 3)) - 2));
  360. X        if (i == i_special) {
  361. X            while (i < 6 && pt_len[i] == 0) i++;
  362. X            putbits(2, (uint) ((i - 3) & 3));
  363. X        }
  364. X    }
  365. }
  366. X
  367. static void write_c_len()
  368. {
  369. X    int i, k, n, count;
  370. X
  371. X    n = NC;
  372. X    while (n > 0 && c_len[n - 1] == 0) n--;
  373. X    putbits(CBIT, (uint) n);
  374. X    i = 0;
  375. X    while (i < n) {
  376. X        k = c_len[i++];
  377. X        if (k == 0) {
  378. X            count = 1;
  379. X            while (i < n && c_len[i] == 0) {  i++;  count++;  }
  380. X            if (count <= 2) {
  381. X                for (k = 0; k < count; k++)
  382. X                    putbits((int) pt_len[0], (uint) pt_code[0]);
  383. X            } else if (count <= 18) {
  384. X                putbits((int) pt_len[1], (uint) pt_code[1]);
  385. X                putbits(4, (uint) (count - 3));
  386. X            } else if (count == 19) {
  387. X                putbits((int) pt_len[0], (uint) pt_code[0]);
  388. X                putbits((int) pt_len[1], (uint) pt_code[1]);
  389. X                putbits(4, 15);
  390. X            } else {
  391. X                putbits((int) pt_len[2], (uint) pt_code[2]);
  392. X                putbits(CBIT, (uint) (count - 20));
  393. X            }
  394. X        } else putbits((int) pt_len[k + 2], (uint) pt_code[k + 2]);
  395. X    }
  396. }
  397. X
  398. static void encode_c(c)
  399. int c;
  400. {
  401. X    putbits((int) c_len[c], (uint) c_code[c]);
  402. }
  403. X
  404. static void encode_p(p)
  405. uint p;
  406. {
  407. X    uint c, q;
  408. X
  409. X    c = 0;  q = p;  while (q) {  q >>= 1;  c++;  }
  410. X    putbits((int) pt_len[c], (uint) pt_code[c]);
  411. X    if (c > 1) putbits((int) (c - 1), (uint) (p & ((unsigned) 0xFFFF >> (17 - c))));
  412. }
  413. X
  414. static void send_block()
  415. {
  416. X    uint i, k, flags, root, pos, size;
  417. X
  418. X    root = make_tree(NC, c_freq, c_len, c_code);
  419. X    size = c_freq[root];
  420. #if 0
  421. X    /*debug*/ (void) fprintf(stderr, "\nsize = %u\n", size);
  422. #endif
  423. X    putbits(16, size);
  424. X    if (root >= NC) {
  425. X        count_t_freq();
  426. X        root = make_tree(NT, t_freq, pt_len, pt_code);
  427. X        if (root >= NT) {
  428. X            write_pt_len(NT, TBIT, 3);
  429. X        } else {
  430. X            putbits(TBIT, 0);  putbits(TBIT, root);
  431. X        }
  432. X        write_c_len();
  433. X    } else {
  434. X        putbits(TBIT, 0);  putbits(TBIT, 0);
  435. X        putbits(CBIT, 0);  putbits(CBIT, root);
  436. X    }
  437. X    root = make_tree(NP, p_freq, pt_len, pt_code);
  438. X    if (root >= NP) {
  439. X        write_pt_len(NP, PBIT, -1);
  440. X    } else {
  441. X        putbits(PBIT, 0);  putbits(PBIT, root);
  442. X    }
  443. X    pos = 0;
  444. X    for (i = 0; i < size; i++) {
  445. X        if (i % CHAR_BIT == 0) flags = buf[pos++];  else flags <<= 1;
  446. X        if (flags & ((unsigned) 1 << (CHAR_BIT - 1))) {
  447. X            encode_c((int) (buf[pos++] + ((unsigned) 1 << CHAR_BIT)));
  448. X            k = buf[pos++] << CHAR_BIT;  k += buf[pos++];
  449. X            encode_p(k);
  450. X        } else encode_c((int) buf[pos++]);
  451. X        if (unpackable) return;
  452. X    }
  453. X    for (i = 0; i < NC; i++) c_freq[i] = 0;
  454. X    for (i = 0; i < NP; i++) p_freq[i] = 0;
  455. }
  456. X
  457. static uint output_pos, output_mask;
  458. X
  459. void output(c, p)
  460. uint c;
  461. uint p;
  462. {
  463. X    static uint cpos;
  464. X
  465. X    if ((output_mask >>= 1) == 0) {
  466. X        output_mask = (unsigned) 1 << (CHAR_BIT - 1);
  467. X        if (output_pos >= bufsiz - 3 * CHAR_BIT) {
  468. X            send_block();
  469. X            if (unpackable) return;
  470. X            output_pos = 0;
  471. X        }
  472. X        cpos = output_pos++;  buf[cpos] = 0;
  473. X    }
  474. X    buf[output_pos++] = (uchar) c;  c_freq[c]++;
  475. X    if (c >= ((unsigned) 1 << CHAR_BIT)) {
  476. X        buf[cpos] |= output_mask;
  477. X        buf[output_pos++] = (uchar)(p >> CHAR_BIT);
  478. X        buf[output_pos++] = (uchar) p;
  479. X        c = 0;  while (p) {  p >>= 1;  c++;  }
  480. X        p_freq[c]++;
  481. X    }
  482. }
  483. X
  484. void huf_encode_start()
  485. {
  486. X    int i;
  487. X
  488. X    if (bufsiz == 0) {
  489. X        bufsiz = 16 * (unsigned) 1024;
  490. X        while ((buf = (uchar *) malloc(bufsiz)) == NULL) {
  491. X            bufsiz = (bufsiz / (unsigned) 10) * (unsigned) 9;
  492. X            if (bufsiz < 4 * (unsigned) 1024) 
  493. X                prterror('f', no_memory);
  494. X        }
  495. X    }
  496. X    buf[0] = 0;
  497. X    for (i = 0; i < NC; i++) c_freq[i] = 0;
  498. X    for (i = 0; i < NP; i++) p_freq[i] = 0;
  499. X    output_pos = output_mask = 0;
  500. X    init_putbits();
  501. }
  502. X
  503. void huf_encode_end()
  504. {
  505. X    if (! unpackable) {
  506. X        send_block();
  507. X        putbits(CHAR_BIT - 1, 0);  /* flush remaining bits */
  508. X        putbits(16, 0);                /* EOF marker */
  509. X    }
  510. }
  511. X
  512. /***** decoding *****/
  513. X
  514. static void read_pt_len(nn, nbit, i_special)
  515. int nn;
  516. int nbit;
  517. int i_special;
  518. {
  519. X    int i, c, n;
  520. X    uint mask;
  521. X
  522. X    n = getbits(nbit);
  523. X    if (n == 0) {
  524. X        c = getbits(nbit);
  525. X        for (i = 0; i < nn; i++) pt_len[i] = 0;
  526. X        for (i = 0; i < 256; i++) pt_table[i] = c;
  527. X    } else {
  528. X        i = 0;
  529. X        while (i < n) {
  530. X            c = bitbuf >> (BITBUFSIZ - 3);
  531. X            if (c == 7) {
  532. X                mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3);
  533. X                while (mask & bitbuf) {  mask >>= 1;  c++;  }
  534. X            }
  535. X            fillbuf((c < 7) ? 3 : c - 3);
  536. X            pt_len[i++] = c;
  537. X            if (i == i_special) {
  538. X                c = getbits(2);
  539. X                while (--c >= 0) pt_len[i++] = 0;
  540. X            }
  541. X        }
  542. X        while (i < nn) pt_len[i++] = 0;
  543. X        make_table(nn, pt_len, 8, pt_table);
  544. X    }
  545. }
  546. X
  547. static void read_c_len()
  548. {
  549. X    int i, c, n;
  550. X    uint mask;
  551. X
  552. X    n = getbits(CBIT);
  553. X    if (n == 0) {
  554. X        c = getbits(CBIT);
  555. X        for (i = 0; i < NC; i++) c_len[i] = 0;
  556. X        for (i = 0; i < 4096; i++) c_table[i] = c;
  557. X    } else {
  558. X        i = 0;
  559. X        while (i < n) {
  560. X            c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
  561. X            if (c >= NT) {
  562. X                mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
  563. X                do {
  564. X                    if (bitbuf & mask) c = right[c];
  565. X                    else               c = left [c];
  566. X                    mask >>= 1;
  567. X                } while (c >= NT);
  568. X            }
  569. X            fillbuf((int) pt_len[c]);
  570. X            if (c <= 2) {
  571. X                if      (c == 0) c = 1;
  572. X                else if (c == 1) c = getbits(4) + 3;
  573. X                else             c = getbits(CBIT) + 20;
  574. X                while (--c >= 0) c_len[i++] = 0;
  575. X            } else c_len[i++] = c - 2;
  576. X        }
  577. X        while (i < NC) c_len[i++] = 0;
  578. X        make_table(NC, c_len, 12, c_table);
  579. X    }
  580. }
  581. X
  582. uint decode_c()
  583. {
  584. X    uint j, mask;
  585. X
  586. X    if (blocksize == 0) {
  587. X        blocksize = getbits(16);
  588. X        if (blocksize == 0) {
  589. #if 0
  590. X            (void) fprintf(stderr, "block size = 0, decoded\n");  /* debug */
  591. #endif
  592. X            decoded = 1;
  593. X            return 0;
  594. X        }
  595. X        read_pt_len(NT, TBIT, 3);
  596. X        read_c_len();
  597. X        read_pt_len(NP, PBIT, -1);
  598. X    }
  599. X    blocksize--;
  600. X    j = c_table[bitbuf >> (BITBUFSIZ - 12)];
  601. X    if (j >= NC) {
  602. X        mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12);
  603. X        do {
  604. X            if (bitbuf & mask) j = right[j];
  605. X            else               j = left [j];
  606. X            mask >>= 1;
  607. X        } while (j >= NC);
  608. X    }
  609. X    fillbuf((int) c_len[j]);
  610. X    return j;
  611. }
  612. X
  613. uint decode_p()
  614. {
  615. X    uint j, mask;
  616. X
  617. X    j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
  618. X    if (j >= NP) {
  619. X        mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
  620. X        do {
  621. X            if (bitbuf & mask) j = right[j];
  622. X            else               j = left [j];
  623. X            mask >>= 1;
  624. X        } while (j >= NP);
  625. X    }
  626. X    fillbuf((int) pt_len[j]);
  627. X    if (j != 0) j = ((unsigned) 1 << (j - 1)) + getbits((int) (j - 1));
  628. X    return j;
  629. }
  630. X
  631. void huf_decode_start()
  632. {
  633. X    init_getbits();  blocksize = 0;
  634. }
  635. SHAR_EOF
  636. chmod 0644 huf.c ||
  637. echo 'restore of huf.c failed'
  638. Wc_c="`wc -c < 'huf.c'`"
  639. test 7757 -eq "$Wc_c" ||
  640.     echo 'huf.c: original size 7757, current size' "$Wc_c"
  641. fi
  642. # ============= io.c ==============
  643. if test -f 'io.c' -a X"$1" != X"-c"; then
  644.     echo 'x - skipping io.c (File already exists)'
  645. else
  646. echo 'x - extracting io.c (Text)'
  647. sed 's/^X//' << 'SHAR_EOF' > 'io.c' &&
  648. /*$Source: /usr/home/dhesi/zoo/RCS/io.c,v $*/
  649. /*$Id: io.c,v 1.14 91/07/09 01:39:54 dhesi Exp $*/
  650. /***********************************************************
  651. X    io.c -- input/output
  652. X
  653. Adapted from "ar" archiver written by Haruhiko Okumura.
  654. ***********************************************************/
  655. #ifdef ANSI_HDRS
  656. # include <stdlib.h>
  657. # include <string.h>
  658. #endif
  659. X
  660. #include "options.h"
  661. #include "zoo.h"
  662. #include "ar.h"
  663. #include "lzh.h"
  664. #include "zooio.h"    /* for NULLFILE */
  665. #include "portable.h"
  666. X
  667. extern void prterror();
  668. X
  669. #include "errors.i"
  670. X
  671. #define JUST_LZH        /* for stand-alone compression */
  672. X
  673. #if 0
  674. # define CRCPOLY  0xA001  /* ANSI CRC-16 */ /* CCITT: 0x8408 */
  675. # define UPDATE_CRC(c) \
  676. X    crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT)
  677. static ushort crctable[UCHAR_MAX + 1];
  678. t_uint16 crc;
  679. #endif
  680. X
  681. extern FILE *arcfile, *lzh_outfile;
  682. t_uint16 bitbuf;
  683. int unpackable;
  684. X
  685. ulong compsize, origsize;
  686. X
  687. static uint  subbitbuf;
  688. static int   bitcount;
  689. X
  690. #if 0
  691. void make_crctable()
  692. {
  693. X    uint i, j, r;
  694. X
  695. X    for (i = 0; i <= UCHAR_MAX; i++) {
  696. X        r = i;
  697. X        for (j = 0; j < CHAR_BIT; j++)
  698. X            if (r & 1) r = (r >> 1) ^ CRCPOLY;
  699. X            else       r >>= 1;
  700. X        crctable[i] = r;
  701. X    }
  702. }
  703. #endif
  704. X
  705. void fillbuf(n)  /* Shift bitbuf n bits left, read n bits */
  706. int n;
  707. {
  708. X    bitbuf <<= n;
  709. X    while (n > bitcount) {
  710. X        bitbuf |= subbitbuf << (n -= bitcount);
  711. #ifdef JUST_LZH
  712. X        if (feof(arcfile))
  713. X            subbitbuf = 0;
  714. X        else
  715. X            subbitbuf = (uchar) zgetc(arcfile);
  716. #else
  717. X        if (compsize != 0) {
  718. X            compsize--;  subbitbuf = (uchar) zgetc(arcfile);
  719. X        } else subbitbuf = 0;
  720. #endif /* JUST_LZH */
  721. X        bitcount = CHAR_BIT;
  722. X    }
  723. X    bitbuf |= subbitbuf >> (bitcount -= n);
  724. }
  725. X
  726. uint getbits(n)
  727. int n;
  728. {
  729. X    uint x;
  730. X
  731. X    x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n);
  732. X    return x;
  733. }
  734. X
  735. void putbits(n, x)  /* Write rightmost n bits of x */
  736. int n;
  737. uint x;
  738. {
  739. X    if (n < bitcount) {
  740. X        subbitbuf |= x << (bitcount -= n);
  741. X    } else {
  742. #ifdef JUST_LZH
  743. X        (void) putc((int) (subbitbuf | (x >> (n -= bitcount))), lzh_outfile);
  744. X        compsize++;
  745. #else
  746. X        if (compsize < origsize) {
  747. X            (void) zputc((int) (subbitbuf | (x >> (n -= bitcount))), lzh_outfile);
  748. X            compsize++;
  749. X        } else unpackable = 1;
  750. #endif /* JUST_LZH */
  751. X
  752. X        if (n < CHAR_BIT) {
  753. X            subbitbuf = x << (bitcount = CHAR_BIT - n);
  754. X        } else {
  755. #ifdef JUST_LZH
  756. X            (void) putc((int) (x >> (n - CHAR_BIT)), lzh_outfile);
  757. X            compsize++;
  758. #else
  759. X            if (compsize < origsize) {
  760. X                (void) zputc((int) (x >> (n - CHAR_BIT)), lzh_outfile);
  761. X                compsize++;
  762. X            } else unpackable = 1;
  763. #endif /* JUST_LZH */
  764. X            subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);
  765. X        }
  766. X    }
  767. }
  768. X
  769. extern void addbfcrc();
  770. X
  771. int fread_crc(p, n, f)
  772. uchar *p;
  773. int n;
  774. FILE *f;
  775. {
  776. X    int i;
  777. X
  778. X    i = n = fread((char *) p, 1, n, f);  origsize += n;
  779. X    addbfcrc(p, i);
  780. X    return n;
  781. }
  782. X
  783. void fwrite_crc(p, n, f)
  784. uchar *p;
  785. int n;
  786. FILE *f;
  787. {
  788. X    if (f != NULLFILE) {
  789. X        if (fwrite((char *) p, 1, n, f) < n) 
  790. X            prterror('f', disk_full);
  791. X    }
  792. X    addbfcrc(p, n);
  793. }
  794. X
  795. void init_getbits()
  796. {
  797. X    bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
  798. X    fillbuf(BITBUFSIZ);
  799. }
  800. X
  801. void init_putbits()
  802. {
  803. X    bitcount = CHAR_BIT;  subbitbuf = 0;
  804. }
  805. SHAR_EOF
  806. chmod 0644 io.c ||
  807. echo 'restore of io.c failed'
  808. Wc_c="`wc -c < 'io.c'`"
  809. test 3003 -eq "$Wc_c" ||
  810.     echo 'io.c: original size 3003, current size' "$Wc_c"
  811. fi
  812. # ============= lzc.asm ==============
  813. if test -f 'lzc.asm' -a X"$1" != X"-c"; then
  814.     echo 'x - skipping lzc.asm (File already exists)'
  815. else
  816. echo 'x - extracting lzc.asm (Text)'
  817. sed 's/^X//' << 'SHAR_EOF' > 'lzc.asm' &&
  818. title    Lempel-Ziv Compressor
  819. ; $Source: /usr/home/dhesi/zoo/RCS/lzc.asm,v $
  820. ; $Id: lzc.asm,v 1.4 91/07/07 09:36:18 dhesi Exp $
  821. X
  822. ;Derived from Tom Pfau's public domain assembly code.
  823. ;The contents of this file are hereby released to the public domain.
  824. ;                                   -- Rahul Dhesi 1988/08/24
  825. X
  826. UNBUF_IO    equ    1        ;use unbuffered I/O
  827. X
  828. public    _lzc
  829. X
  830. X    include asmconst.ai
  831. X    include macros.ai
  832. X
  833. check_gap    equ    4000        ;Check ratio every so many bits
  834. scale_limit    equ    32000        ;scale down if bitsout > scale_limit
  835. rat_thresh    equ    0ffffh        ;don't reset if rat > rat_thresh
  836. X
  837. ;Hash table entry
  838. hash_rec    struc
  839. first    dw    ?            ; First entry with this value
  840. next    dw    ?            ; Next entry along chain
  841. char    db    ?            ; Suffix char
  842. hash_rec    ends
  843. X
  844. extrn    docrc:near            ;Procedure for block CRC in lzd.asm
  845. X
  846. ifdef    UNBUF_IO
  847. extrn    _read:near
  848. extrn    _blockwrite:near
  849. else
  850. extrn    _zooread:near
  851. extrn    _zoowrite:near
  852. endif
  853. X
  854. ;Declare Segments
  855. _text    segment byte public 'code'
  856. _text    ends
  857. X
  858. dgroup    group    _data
  859. X    assume ds:dgroup,es:dgroup
  860. _data    segment word public 'data'
  861. extrn    _out_buf_adr:word        ;address of C output buffer
  862. extrn    _in_buf_adr:word        ;address of C input buffer
  863. X
  864. extrn    memflag:byte            ;got memory? flag
  865. X
  866. save_sp        dw    ?
  867. X
  868. bytesin        dw    ?        ;count of bytes read
  869. bitsout        dw    ?        ;count of bits written
  870. ratio        dw    ?        ;recent ratio
  871. ratflag        db    ?        ;flag to remind us to check ratio
  872. bit_interval    dw    ?        ;interval at which to test ratio
  873. X
  874. input_handle    dw    ?
  875. output_handle    dw    ?
  876. hash_seg    dw    ?
  877. prefix_code    dw    ?
  878. free_code    dw    ?
  879. max_code    dw    ?
  880. nbits        dw    ?
  881. k        db    ?
  882. bit_offset    dw    ?
  883. input_offset    dw    0
  884. input_size    dw    0
  885. _data    ends
  886. X
  887. memory    segment para public 'memory'
  888. hash    label    hash_rec
  889. memory    ends
  890. X
  891. add_code macro
  892. X    local    ac1,ac2,ac3
  893. X    mov    bx,free_code        ;Get code to use
  894. X    push    ds            ;point to hash table
  895. X    mov    ds,hash_seg
  896. X    or    di,di            ;First use of this prefix?
  897. X    jz    ac1            ;zero means yes
  898. X    mov    [si].next,bx        ;point last use to new entry
  899. X    jmp    short ac2
  900. ac1:    mov    [si].first,bx        ;Point first use to new entry
  901. ac2:    cmp    bx,maxmax        ;Have we reached code limit?
  902. X    je    ac3            ;equal means yes, just return
  903. X
  904. X    ;call    index            ;get address of new entry
  905. X    call_index            ;macro for speed
  906. X
  907. X    mov    [si].first,-1        ;initialize pointers
  908. X    mov    [si].next,-1
  909. X    mov    [si].char,al        ;save suffix char
  910. X    inc    es:free_code        ;adjust next code
  911. ac3:    pop    ds            ;restore seg reg
  912. X    endm
  913. X
  914. read_char macro                ;Macro for speed
  915. X    local m$1,m$2,m$3,m$4
  916. X    inc    [bytesin]        ;Maintain input byte count for ratio 
  917. X    mov    di,input_offset        ;Anything left in buffer?
  918. X    cmp    di,input_size
  919. X    jb    m$1            ;less means yes
  920. X
  921. X    mov    cx,inbufsiz
  922. X    call    doread            ;read block
  923. X
  924. X    cmp    ax,-1
  925. X    jnz    m$3
  926. X    jmp    IO_err            ;input error
  927. m$3:
  928. X    mov    dx,_in_buf_adr        ;for docrc
  929. X    call    docrc
  930. X    or    ax,ax            ;Anything left?
  931. X    jz    m$2            ;zero means no, finished
  932. X    mov    input_size,ax        ;Save bytes read
  933. X    mov    input_offset,0        ;Point to beginning of buffer
  934. X    mov    di,0
  935. m$1:    
  936. X    mov    si,_in_buf_adr
  937. X    add    si,di
  938. X    lodsb                ;Read it in
  939. X    inc    input_offset        ;Adjust pointer
  940. X    clc                ;Success
  941. X    jmp    short m$4
  942. m$2:    stc                ;Nothing left
  943. m$4:
  944. X    endm
  945. X
  946. ;Start writing code
  947. _text    segment
  948. X    assume    cs:_text,ds:dgroup,es:dgroup,ss:nothing
  949. X
  950. _lzc    proc    near
  951. X    push    bp            ;Standard C entry code
  952. X    mov    bp,sp
  953. X    push    di
  954. X    push    si
  955. X    
  956. X    push    ds            ;Save ds to be sure
  957. X    mov    bx,ds
  958. X    mov    es,bx
  959. X
  960. ;Get two parameters, both integers, that are input file handle and
  961. ;output file handle
  962. X    mov    ax,[bp+4]
  963. X    mov    [input_handle],ax
  964. X    mov    ax,[bp+6]
  965. X    mov    [output_handle],ax
  966. X
  967. X    call    compress        ;Compress file
  968. X                    ;Status received back in AX
  969. X    pop    ds
  970. X    pop    si            ;Standard C return code
  971. X    pop    di
  972. X    mov    sp,bp
  973. X    pop    bp
  974. X    ret
  975. X
  976. _lzc    endp
  977. X
  978. compress    proc    near
  979. X    mov    [save_sp],sp        ;Save SP in case of error return
  980. X
  981. ;Initialize variables for serial re-entrancy
  982. X    mov    [bit_offset],0
  983. X    mov    [input_offset],0
  984. X    mov    [input_size],0
  985. X
  986. X    test    memflag,0ffH        ;Memory allocated?
  987. X    jnz    gotmem            ;If allocated, continue
  988. X    malloc    <((maxmax * 5) / 16 + 20)>    ;allocate it
  989. X    jnc    here1
  990. X    jmp    MALLOC_err1
  991. here1:
  992. X    mov    hash_seg,ax        ;Save segment address of mem block
  993. X    mov    memflag,0ffh        ;Set flag to remind us later
  994. gotmem:
  995. X
  996. l1:    call    init_table        ;Initialize the table and some vars
  997. X    mov    ax,clear        ;Write a clear code
  998. X    call    write_code
  999. X    ;call    read_char        ;Read first char
  1000. X    read_char            ;macro for speed
  1001. l4:    
  1002. X
  1003. ;new code to check compression ratio
  1004. X    test    [ratflag],0FFH        ;Time to check ratio?
  1005. X    jz    rd$1            ;Skip checking if zero
  1006. X    call    check_ratio
  1007. rd$1:
  1008. X    xor    ah,ah            ;Turn char into code
  1009. l4a:    mov    prefix_code,ax        ;Set prefix code
  1010. X    ;call    read_char        ;Read next char
  1011. X    read_char            ;macro for speed
  1012. X    jc    l17            ;Carry means eof
  1013. X    mov    k,al            ;Save char in k
  1014. X    mov    bx,prefix_code        ;Get prefix code
  1015. X
  1016. X    call    lookup_code        ;See if this pair in table
  1017. X
  1018. X    jnc    l4a            ;nc means yes, new code in ax
  1019. X    ;call    add_code        ;Add pair to table
  1020. X    add_code            ;Macro for speed
  1021. X    push    bx            ;Save new code
  1022. X    mov    ax,prefix_code        ;Write old prefix code
  1023. X    call    write_code
  1024. X    pop    bx
  1025. X    mov    al,k            ;Get last char
  1026. X    cmp    bx,max_code        ;Exceed code size?
  1027. X
  1028. X    jnb    l4$
  1029. X    jmp    l4
  1030. l4$:
  1031. X    cmp    nbits,maxbits        ;Currently less than maxbits?
  1032. X    jb    l14            ;yes
  1033. X    mov    ax,clear        ;Write a clear code
  1034. X    call    write_code
  1035. X    call    init_table        ;Reinit table
  1036. X    mov    al,k            ;get last char
  1037. X    jmp    l4            ;Start over
  1038. l14:    inc    nbits            ;Increase number of bits
  1039. X    shl    max_code,1        ;Double max code size
  1040. X    jmp    l4            ;Get next char
  1041. l17:    mov    ax,prefix_code        ;Write last code
  1042. X    call    write_code
  1043. X    mov    ax,eof            ;Write eof code
  1044. X    call    write_code
  1045. X    mov    ax,bit_offset        ;Make sure buffer is flushed to file
  1046. X    cmp    ax,0
  1047. X    je    OK_ret
  1048. X    mov    dx,ax            ;dx <- ax
  1049. X    shr    ax,1
  1050. X    shr    ax,1
  1051. X    shr    ax,1            ;ax <- ax div 8
  1052. X    and    dx,07            ;dx <- ax mod 8
  1053. X                    ;If extra bits, make sure they get
  1054. X    je    l17a            ;written
  1055. X    inc    ax
  1056. l17a:    call    flush
  1057. OK_ret:    
  1058. X    xor    ax,ax            ;Normal return -- compressed
  1059. X    ret
  1060. IO_err:
  1061. X    mov    ax,2            ;I/O error return 
  1062. X    mov    sp,[save_sp]        ;Restore stack pointer
  1063. X    ret    
  1064. X
  1065. MALLOC_err1:                ;hash table alloc error
  1066. X    mov    ax,1            ;Malloc error return
  1067. X    mov    sp,[save_sp]        ;Restore stack pointer
  1068. X    ret
  1069. compress    endp
  1070. X
  1071. init_table    proc    near
  1072. X    mov    [bytesin],0        ;Input byte count
  1073. X    mov    [bitsout],0        ;Output bit count
  1074. X    mov    [ratio],0
  1075. X    mov    [ratflag],0
  1076. X    mov    [bit_interval],check_gap
  1077. X
  1078. X    mov    nbits,9            ;Set code size to 9
  1079. X    mov    max_code,512        ;Set max code to 512
  1080. X    push    es            ;Save seg reg
  1081. X    mov    es,hash_seg        ;Address hash table
  1082. X    mov    ax,-1            ;Unused flag
  1083. X    mov    cx,640            ;Clear first 256 entries
  1084. X    mov    di,offset hash        ;Point to first entry
  1085. rep    stosw                ;Clear it out
  1086. X    pop    es            ;Restore seg reg
  1087. X    mov    free_code,first_free    ;Set next code to use
  1088. X    ret                ;done
  1089. init_table    endp
  1090. X
  1091. write_code    proc    near
  1092. X    push    ax            ;Save code
  1093. X    mov    cx,nbits
  1094. X    add    [bitsout],cx        ;Maintain output bit count for ratio
  1095. X    sub    [bit_interval],cx
  1096. X    jg    rd$2            ;OK if not reached interval
  1097. X    mov    [ratflag],1        ;else set flag -- check ratio soon
  1098. rd$2:
  1099. X    mov    ax,bit_offset        ;Get bit offset
  1100. X    mov    cx,nbits        ;Adjust bit offset by code size
  1101. X    add    bit_offset,cx
  1102. X
  1103. X    mov    dx,ax            ;dx <- ax
  1104. X    shr    ax,1
  1105. X    shr    ax,1
  1106. X    shr    ax,1            ;ax <- ax div 8
  1107. X    and    dx,07            ;dx <- ax mod 8
  1108. X
  1109. X    ;Now ax contains byte offset and
  1110. X    ;dx contains bit offset within that byte (I think)
  1111. X
  1112. X    cmp    ax,outbufsiz-4        ;Approaching end of buffer?
  1113. X    jb    wc1            ;less means no
  1114. X    call    flush            ;Write the buffer
  1115. X
  1116. X    push    dx            ;dx contains offset within byte
  1117. X    add    dx,nbits        ;adjust by code size
  1118. X    mov    bit_offset,dx        ;new bit offset
  1119. X    pop    dx            ;restore dx
  1120. X
  1121. ;ax is an index into output buffer.  Next, ax <- address of buffer[ax]
  1122. X    add    ax,[_out_buf_adr]
  1123. X    mov    si,ax            ;put in si
  1124. X    mov    al,byte ptr [si]    ;move byte to first position
  1125. X
  1126. ;put value of al into first byte of output buffer
  1127. X    push    bx
  1128. X    mov    bx,[_out_buf_adr]
  1129. X    mov    [bx],al
  1130. X    pop    bx
  1131. X    xor    ax,ax            ;Byte offset of zero
  1132. wc1:    add    ax,[_out_buf_adr]    ;Point into buffer
  1133. X    mov    di,ax            ;Destination
  1134. X    pop    ax            ;Restore code
  1135. X    mov    cx,dx            ;offset within byte
  1136. X    xor    dx,dx            ;dx will catch bits rotated out
  1137. X    jcxz    wc3            ;If offset in byte is zero, skip shift
  1138. wc2:    shl    ax,1            ;Rotate code
  1139. X    rcl    dx,1
  1140. X    loop    wc2
  1141. X    or    al,byte ptr [di]    ;Grab bits currently in buffer
  1142. wc3:    stosw                ;Save data
  1143. X    mov    al,dl            ;Grab extra bits
  1144. X    stosb                ;and save
  1145. X    ret
  1146. write_code    endp
  1147. X
  1148. flush    proc    near
  1149. X    push    ax            ;Save all registers
  1150. X    push    bx            ;AX contains number of bytes to write
  1151. X    push    cx
  1152. X    push    dx
  1153. X
  1154. X    push    si            ;may not be necessary to save si & di
  1155. X    push    di
  1156. X
  1157. X    push    ax            ;save byte count
  1158. X
  1159. X    push    ax            ;byte count
  1160. X    push    _out_buf_adr        ;buffer address
  1161. X    push    output_handle        ;zoofile
  1162. ifdef    UNBUF_IO
  1163. X    call    _blockwrite
  1164. else
  1165. X    call    _zoowrite
  1166. endif
  1167. X    add    sp,6
  1168. X
  1169. X    pop    cx            ;recover byte count
  1170. X
  1171. X    cmp    ax,cx
  1172. X
  1173. X    jz    here2
  1174. X    jmp    IO_err        ;I/O error
  1175. X
  1176. here2:
  1177. X    pop    di
  1178. X    pop    si
  1179. X
  1180. X    pop    dx
  1181. X    pop    cx
  1182. X    pop    bx
  1183. X    pop    ax
  1184. X    ret
  1185. flush        endp
  1186. X
  1187. lookup_code    proc    near
  1188. X    push    ds            ;Save seg reg
  1189. X    mov    ds,hash_seg        ;point to hash table
  1190. X
  1191. X    ;call    index            ;convert code to address
  1192. X    call_index            ;macro for speed
  1193. X
  1194. X    mov    di,0            ;flag
  1195. X    mov    bx,[si].first
  1196. X    cmp    bx,-1            ;Has this code been used?
  1197. X    je    gc4            ;equal means no
  1198. X    inc    di            ;set flag
  1199. gc2:    
  1200. X    ;call    index            ;convert code to address
  1201. X    call_index            ;macro for speed
  1202. X
  1203. X    cmp    [si].char,al        ;is char the same?
  1204. X    jne    gc3            ;ne means no
  1205. X    clc                ;success
  1206. X    mov    ax,bx            ;put found code in ax
  1207. X    pop    ds            ;restore seg reg
  1208. X    ret                ;done
  1209. gc3:    
  1210. X    mov    bx,[si].next
  1211. X    cmp    bx,-1            ;More left with this prefix?
  1212. X    je    gc4            ;equal means no
  1213. X    jmp    gc2            ;try again
  1214. gc4:    stc                ;not found
  1215. X    pop    ds            ;restore seg reg
  1216. X    ret                ;done
  1217. lookup_code    endp
  1218. X
  1219. comment #
  1220. index    proc    near
  1221. X    mov    si,bx            ;si = bx * 5 (5 byte hash entries)
  1222. X    shl    si,1            ;si = bx * 2 * 2 + bx
  1223. X    shl    si,1
  1224. X    add    si,bx
  1225. X    ret
  1226. index        endp
  1227. # end comment
  1228. X
  1229. check_ratio    proc    near
  1230. X    push    ax
  1231. X
  1232. ;    mov    dl,'*'            ;'*' printed means checking ratio
  1233. ;    call    sendout
  1234. X
  1235. X    ;Getting ready to check ratios.  If bitsout is over scale_limit,
  1236. X    ;then we scale down both bitsout and bytesin by a factor 
  1237. X    ;of 4.  This will avoid overflow.
  1238. X    mov    cx,[bitsout]
  1239. X    cmp    cx,scale_limit
  1240. X    jb    scale_ok
  1241. X
  1242. X    mov    cl,2
  1243. X    shr    [bytesin],cl
  1244. X    shr    [bitsout],cl
  1245. X
  1246. scale_ok:
  1247. X    ;Note MASM bug:  "mov ah,high [bytesin]" and
  1248. X    ;"mov al,low [bytesin]" don't work.
  1249. X    mov    ah,byte ptr [bytesin]
  1250. X    mov    dl,byte ptr [bytesin+1]
  1251. X
  1252. X    sub    al,al
  1253. X    sub    dh,dh            ;dx:ax = 8 * bitsin = 256 * bytesin
  1254. X    mov    cx,[bitsout]        ;cx <- bitsout
  1255. X    or    cx,cx            ;Division by zero?
  1256. X    jnz    candivide        ;No -- go ahead divide
  1257. X    mov    ax,0FFFFH        ;yes -- assume max poss value    
  1258. X    jmp    short divided
  1259. candivide:
  1260. X    ;Calculate cx as (bytesin * 256) / bitsout  = bitsin * 8 / bitsout
  1261. X    div    cx            ;ax <- rat <- dx:ax / cx
  1262. X    shl    ax,1
  1263. X    shl    ax,1            ;rat <- 4 * bytes_in / bytes_out
  1264. divided:
  1265. X    ;Enter here with ax = rat = bitsin / bitsout.
  1266. X
  1267. ;    call print_data            ;print info for debugging
  1268. X
  1269. X    ;If rat > rat_thresh then ratio is good;  do not reset table
  1270. ;    cmp    ax,rat_thresh
  1271. ;    ja    ratdone
  1272. X
  1273. X    ;Compare rat against ratio
  1274. X    mov    bx,ax            ;save rat in bx
  1275. X    cmp    ax,[ratio]        ;cmp rat,ratio
  1276. X    jb    ratless            ;trouble if ratio is now smaller
  1277. X    mov    ax,[ratio]
  1278. X    call    mul7            ;ax <- 7 * ratio
  1279. X    add    ax,bx            ;ax = 7 * ratio + rat
  1280. X    shr    ax,1
  1281. X    shr    ax,1
  1282. X    shr    ax,1            ;ax = (7 * ratio + rat) / 8
  1283. X    mov    [ratio],ax        ;ratio = (7 * ratio + rat) / 8
  1284. X    jmp    short ratdone
  1285. ratless:                ;ratio is going down, so...
  1286. X    mov    [bytesin],0
  1287. X    mov    [bitsout],0
  1288. X
  1289. ;    mov    dl,'#'            ;'#' printed means table reset
  1290. ;    call    sendout
  1291. X
  1292. X    mov    ax,clear        ;Write a clear code
  1293. X    call    write_code
  1294. X    call    init_table        ;Reinit table
  1295. ratdone:
  1296. X    mov    [ratflag],0
  1297. X    mov    [bit_interval],check_gap
  1298. X    pop    ax
  1299. X    ret
  1300. check_ratio    endp
  1301. X
  1302. comment #
  1303. sendout    proc    near            ;char in dl send to console
  1304. X    push    ax
  1305. X    mov    ah,02
  1306. X    int    21H
  1307. X    pop    ax
  1308. X    ret
  1309. sendout    endp
  1310. # end comment
  1311. X
  1312. mul7    proc    near            ;multiply ax by 7
  1313. X    push    dx
  1314. X    mov    dx,7
  1315. X    mul    dx            ;dx:ax <- 7 * ax
  1316. X    pop    dx
  1317. X    ret
  1318. mul7    endp
  1319. X
  1320. comment #
  1321. mul3    proc    near            ;multiply ax by 3
  1322. X    push    dx
  1323. X    mov    dx,3
  1324. X    mul    dx            ;dx:ax <- 3 * ax
  1325. X    pop    dx
  1326. X    ret
  1327. mul3    endp
  1328. # end comment
  1329. X
  1330. comment #
  1331. mul1_125 proc    near            ;multiply ax by 1.125
  1332. X    push    bx
  1333. X    mov    bx,ax
  1334. X    shr    bx,1
  1335. X    shr    bx,1
  1336. X    shr    bx,1            ;bx = n / 8
  1337. X    add    ax,bx            ;ax <- n + n / 8
  1338. X    pop    bx
  1339. X    ret
  1340. mul1_125 endp
  1341. # end comment
  1342. X
  1343. comment #
  1344. print_data proc near
  1345. X    ;Debugging -- print bytesin, bitsout, rat, and ratio
  1346. X    push    ax
  1347. X    push    bx
  1348. X    push    cx
  1349. X    push    dx
  1350. X
  1351. X    push    ax        ;print rat
  1352. X    call    _prtint
  1353. X    add    sp,2
  1354. X
  1355. X    push    [ratio]        ;print ratio
  1356. X    call    _prtint
  1357. X    add    sp,2
  1358. X
  1359. X    push    [bytesin]
  1360. X    call    _prtint
  1361. X    add    sp,2
  1362. X
  1363. X    push    [bitsout]
  1364. X    call    _prtint
  1365. X    add    sp,2
  1366. X
  1367. X    pop    dx
  1368. X    pop    cx
  1369. X    pop    bx
  1370. X    pop    ax
  1371. X    ret
  1372. print_data endp
  1373. # end comment
  1374. X
  1375. ;doread reads cx characters and stores them in input buffer
  1376. ;return value from zooread is returned in ax
  1377. doread    proc    near        ;reads block
  1378. X    push    bx
  1379. X    push    cx
  1380. X    push    dx
  1381. X    push    si
  1382. X    push    di
  1383. X
  1384. X    push    cx            ;byte count
  1385. X    push    _in_buf_adr        ;buffer address
  1386. X    push    input_handle        ;zoofile
  1387. ifdef    UNBUF_IO
  1388. X    call    _read
  1389. else
  1390. X    call    _zooread
  1391. endif
  1392. X    add    sp,6
  1393. X
  1394. X    pop    di
  1395. X    pop    si
  1396. X    pop    dx
  1397. X    pop    cx
  1398. X    pop    bx
  1399. X    ret
  1400. doread    endp
  1401. X
  1402. _text    ends
  1403. X
  1404. end
  1405. X
  1406. SHAR_EOF
  1407. chmod 0644 lzc.asm ||
  1408. echo 'restore of lzc.asm failed'
  1409. Wc_c="`wc -c < 'lzc.asm'`"
  1410. test 12283 -eq "$Wc_c" ||
  1411.     echo 'lzc.asm: original size 12283, current size' "$Wc_c"
  1412. fi
  1413. # ============= lzc.c ==============
  1414. if test -f 'lzc.c' -a X"$1" != X"-c"; then
  1415.     echo 'x - skipping lzc.c (File already exists)'
  1416. else
  1417. echo 'x - extracting lzc.c (Text)'
  1418. sed 's/^X//' << 'SHAR_EOF' > 'lzc.c' &&
  1419. #ifndef LINT
  1420. static char sccsid[]="@(#) lzc.c 2.6 88/01/30 18:39:15";
  1421. #endif /* LINT */
  1422. X
  1423. /*
  1424. Lempel-Ziv compression.  Mostly based on Tom Pfau's assembly language
  1425. code.
  1426. X
  1427. The contents of this file are hereby released to the public domain.
  1428. X
  1429. X                                    -- Rahul Dhesi  1986/12/31
  1430. */
  1431. X
  1432. #include "options.h"
  1433. #include "zoo.h"
  1434. #include "zooio.h"
  1435. #include "various.h"
  1436. #include "zoofns.h"           /* function definitions */
  1437. /* zoomem.h defines IN_BUF_SIZE & OUT_BUF_SIZE */
  1438. #include "zoomem.h"
  1439. #include "debug.h"
  1440. #include "assert.h"
  1441. /* lzconst.h contains constants for lzd() and lzc() */
  1442. #include "lzconst.h"
  1443. X
  1444. void init_ctab PARMS((void));
  1445. void wr_ccode PARMS((int));
  1446. int rd_cch PARMS((void));
  1447. int lukup_ccode PARMS((int, int, int *));
  1448. void ad_ccode PARMS((int, int, int));
  1449. void check_ratio PARMS((void));
  1450. void flush_c PARMS((int));
  1451. X
  1452. /* interval at which to check ratio */
  1453. #define CHECKGAP 4000
  1454. #define NEXT_USE  1
  1455. #define FIRST_USE 2
  1456. #define FOUND 0
  1457. X
  1458. struct   tabentry {
  1459. X   int first;
  1460. X   int next;
  1461. X   char z_ch;
  1462. };
  1463. X
  1464. extern char *out_buf_adr;
  1465. extern char *in_buf_adr;
  1466. extern char memflag;                    /* memory allocated? */
  1467. struct tabentry *table;                 /* this table also used by lzd.c */
  1468. static unsigned int free_code;
  1469. static int nbits;
  1470. static unsigned int max_code;
  1471. static unsigned int bitsout;
  1472. static int bit_interval;
  1473. static unsigned int bytesin, ratio, ratflag;
  1474. static unsigned int in_offset, in_size;
  1475. static unsigned int bit_offset;
  1476. X
  1477. #ifdef UNBUF_IO
  1478. #define        BLOCKFILE        int
  1479. #define        BLOCKREAD        read
  1480. #define        BLOCKWRITE        write
  1481. int read PARMS ((int, VOIDPTR, unsigned));
  1482. int write PARMS ((int, VOIDPTR, unsigned));
  1483. #else
  1484. #define        BLOCKFILE        ZOOFILE
  1485. #define        BLOCKREAD        zooread
  1486. #define        BLOCKWRITE        zoowrite
  1487. #endif /* UNBUF_IO */
  1488. X
  1489. static BLOCKFILE in_f, out_f;
  1490. X
  1491. int lzc (input_f, output_f)
  1492. BLOCKFILE input_f, output_f;
  1493. {
  1494. X   int nextch, prefix_code, k;
  1495. X   int status;
  1496. X   int where;
  1497. X
  1498. X   in_f = input_f;
  1499. X   out_f = output_f;
  1500. X
  1501. X   bit_offset = in_offset = in_size = 0;
  1502. X
  1503. X   if (memflag == 0) {
  1504. X     table = (struct tabentry *) ealloc((MAXMAX+10) * sizeof(struct tabentry));
  1505. X     memflag++;
  1506. X   }
  1507. X
  1508. X   init_ctab();
  1509. X   wr_ccode(CLEAR);
  1510. X   nextch = rd_cch();
  1511. X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
  1512. X      wr_ccode (Z_EOF);
  1513. X        flush_c ((int) ((bit_offset + 7) / 8));
  1514. X      return (0);                         /* normal return from compress */
  1515. X   }
  1516. X
  1517. X   /* compression loop begins here with nextch holding the next input char */
  1518. loop1:
  1519. X   if (ratflag != 0)
  1520. X      check_ratio();
  1521. X   nextch &= 0xff;                       /* turn character to code */
  1522. X   assert(nextch < 256);
  1523. loop2:
  1524. X   prefix_code = nextch;
  1525. X   nextch = rd_cch();
  1526. X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
  1527. X      wr_ccode (prefix_code);
  1528. X      wr_ccode (Z_EOF);
  1529. X        flush_c ((int) ((bit_offset + 7) / 8));
  1530. X      return (0);                         /* normal return from compress */
  1531. X   }
  1532. X   nextch &= 0xff;                        /* force to 8 bits */
  1533. X   assert(nextch < 256);
  1534. X
  1535. X   k = nextch;
  1536. X   status = lukup_ccode (prefix_code, nextch, &where);
  1537. X   if (status == FOUND) {
  1538. X      nextch = where;                     /* where found */
  1539. X      goto loop2;
  1540. X   }
  1541. X   assert(status == FIRST_USE || status == NEXT_USE);
  1542. X
  1543. X   /* reach here with status = FIRST_USE or NEXT_USE */
  1544. X   ad_ccode (status, nextch, where);
  1545. X
  1546. X   wr_ccode (prefix_code);
  1547. X   nextch = k;
  1548. X
  1549. X   if (free_code <= max_code)
  1550. X      goto loop1;
  1551. X   assert(nbits >= 9 && nbits <= MAXBITS);
  1552. X   if (nbits >= MAXBITS) {
  1553. X   /* To continue using table after it is full, remove next two lines */
  1554. X      wr_ccode (CLEAR);
  1555. X      init_ctab();
  1556. X
  1557. X      goto loop1;
  1558. X   }
  1559. X
  1560. X   nbits++;
  1561. X   assert(nbits >= 9 && nbits <= MAXBITS);
  1562. X   max_code = max_code << 1;
  1563. X   goto loop1;
  1564. } /* end lzc() */
  1565. X
  1566. void wr_ccode (code)
  1567. int code;
  1568. {
  1569. X   unsigned int ofs_inbyte, hibits;
  1570. X   int byte_offset;
  1571. X
  1572. #ifdef DEBUG
  1573. if (code == CLEAR)
  1574. X   printf(" CLEAR\n");
  1575. #endif
  1576. X
  1577. X   assert(nbits >= 9 && nbits <= MAXBITS);
  1578. X   bitsout += nbits;                /* total number of bits written */
  1579. X   bit_interval -= nbits;
  1580. X   if (bit_interval < 0)
  1581. X      ratflag = 1;                  /* time to check ratio */
  1582. X
  1583. X   byte_offset = bit_offset / 8;
  1584. X   ofs_inbyte = bit_offset % 8;     /* offset within byte */
  1585. X   bit_offset += nbits;             /* allowing for new code */
  1586. X
  1587. X   if (byte_offset >= OUTBUFSIZ - 4) {
  1588. X      flush_c (byte_offset);
  1589. X      bit_offset = ofs_inbyte + nbits;
  1590. X      out_buf_adr[0] = out_buf_adr [byte_offset];
  1591. X      byte_offset = 0;
  1592. X   }
  1593. X
  1594. X   code = code & 0xffff;            /* force to 16 bits */
  1595. X
  1596. X   if (ofs_inbyte == 0)
  1597. X      out_buf_adr[byte_offset]  = code & 0xff;
  1598. X   else
  1599. X      out_buf_adr[byte_offset] |= (code << ofs_inbyte) & 0xff;
  1600. X
  1601. X   hibits = ((unsigned int) code) >> (8 - ofs_inbyte);
  1602. X   out_buf_adr[byte_offset+1] = hibits & 0xff;
  1603. X   out_buf_adr[byte_offset+2] = (((unsigned int) hibits) >> 8) & 0xff;
  1604. X
  1605. X   assert(nbits >= 9 && nbits <= MAXBITS);
  1606. } /* end wr_ccode() */
  1607. X
  1608. void init_ctab()
  1609. {
  1610. X   int i;
  1611. X   bytesin = bitsout = ratio = ratflag = 0;
  1612. X   bit_interval = CHECKGAP;
  1613. X   nbits = 9;
  1614. X   max_code = 512;
  1615. #ifdef COMMENT
  1616. X   for (i = 0; i < 256; i++) {
  1617. #endif
  1618. X   for (i = 0; i < MAXMAX+1; i++) {
  1619. X      table[i].z_ch = table[i].first = table[i].next = -1;
  1620. X   }
  1621. #ifdef COMMENT
  1622. X   /*DEBUG*/ table[MAXMAX].first   = table[MAXMAX].next = -1;
  1623. X   /*DEBUG*/ table[MAXMAX-1].first = table[MAXMAX-1].next = -1;
  1624. #endif
  1625. X   free_code = FIRST_FREE;
  1626. } /* end init_ctab() */
  1627. X
  1628. int rd_cch()
  1629. {
  1630. X   int count;
  1631. X   bytesin++;
  1632. X   if (in_offset == in_size) {
  1633. X      count = BLOCKREAD (in_f, in_buf_adr, INBUFSIZ);
  1634. X      if (count == -1)
  1635. X         prterror ('f', "Error reading input file during compression.\n");
  1636. X      addbfcrc (in_buf_adr, count);
  1637. X      if (count == 0) {
  1638. X         debug((printf("\nEOF on input\n")))
  1639. X         return (EOF);              /* real EOF, not Z_EOF */
  1640. X      }
  1641. X      in_size = count;
  1642. X      debug((printf("\ninput %d chars\n", count)))
  1643. X      in_offset = 0;
  1644. X   }
  1645. X   in_offset++;
  1646. X   return (in_buf_adr[in_offset-1] & 0xff);
  1647. } /* end rd_cch () */
  1648. X
  1649. void check_ratio()
  1650. {
  1651. #ifdef COMMENT
  1652. X   int rat;
  1653. X   if (bitsout > 16383) {     /* avoid overflow */
  1654. X      bitsout /= 4;
  1655. X      bytesin /= 4;
  1656. X   }
  1657. X   rat = (2 * bitsout) / bytesin;
  1658. X   if (1.1 * rat < ratio) {
  1659. X      printf("#");
  1660. X      wr_ccode (CLEAR);
  1661. X      init_ctab();
  1662. X      bit_interval = CHECKGAP;
  1663. X      bitsout = 0;
  1664. X      bytesin = 0;
  1665. X      ratio = 0;
  1666. X   } else
  1667. X      ratio = ((ratio << 2) + ((2 * bitsout) / bytesin)) / 5;
  1668. #else
  1669. X   bit_interval = CHECKGAP;
  1670. X   bitsout = 0;
  1671. X   bytesin = 0;
  1672. #endif
  1673. } /* end check_ratio() */
  1674. X
  1675. void ad_ccode (status, ch, index)
  1676. int status, index, ch;
  1677. {
  1678. X   assert(status == FIRST_USE || status == NEXT_USE);
  1679. #ifdef COMMENT
  1680. X   if (free_code >= MAXMAX)      /* to fix apparent bug in original */
  1681. X      return;
  1682. #endif
  1683. #ifdef COMMENT
  1684. X   if (status == NEXT_USE)
  1685. X      table[index].next = free_code;
  1686. X   else                 /* else must be FIRST_USE */
  1687. X      table[index].first = free_code;
  1688. #endif
  1689. X   if (status == NEXT_USE)
  1690. X      table[index].next = (free_code >= MAXMAX ? -1 : free_code);
  1691. X   else                 /* else must be FIRST_USE */
  1692. X      table[index].first = (free_code >= MAXMAX ? -1 : free_code);
  1693. X
  1694. #ifdef COMMENT
  1695. X   if (free_code < MAXMAX) {
  1696. #endif
  1697. X   if (free_code <= MAXMAX) {
  1698. X      table[free_code].first = table[free_code].next = -1;
  1699. X      table[free_code].z_ch = ch & 0xff;
  1700. X      free_code++;
  1701. X   }
  1702. } /* end ad_ccode() */
  1703. X
  1704. int lukup_ccode (index, ch, where)
  1705. int index;                        /* where to start looking */
  1706. int ch;                             /* char to look for */
  1707. int *where;                       /* last entry looked at */
  1708. {
  1709. X   *where = index;
  1710. X   index = table[index].first;
  1711. X   if (index == -1) {
  1712. X      return (FIRST_USE);           /* not found, first use */
  1713. X   } else {
  1714. X      while (1) {
  1715. X         if ((table[index].z_ch & 0xff) == (ch & 0xff)) {
  1716. X            *where = index;
  1717. X            return (FOUND);
  1718. X         }
  1719. X         *where = index;
  1720. X         index = table[index].next;
  1721. X         if (index == -1) {
  1722. X            return (NEXT_USE);
  1723. X         }
  1724. X      } /* end while */
  1725. X   } /* end else */
  1726. } /* end lukup_ccode() */
  1727. X
  1728. void flush_c (count)
  1729. int count;
  1730. {
  1731. X   int status;
  1732. #ifdef DEBUG
  1733. printf(" <flushed %d bytes> ", count);
  1734. #endif
  1735. X
  1736. #ifdef CHECK_BREAK
  1737. X    check_break();
  1738. #endif
  1739. X
  1740. X    if (count != 0) {
  1741. X        status = BLOCKWRITE (out_f, out_buf_adr, count);
  1742. X        if (status == -1)
  1743. X            prterror ('f', "Error writing during compression.\n");
  1744. X    }
  1745. }
  1746. SHAR_EOF
  1747. chmod 0644 lzc.c ||
  1748. echo 'restore of lzc.c failed'
  1749. Wc_c="`wc -c < 'lzc.c'`"
  1750. test 8393 -eq "$Wc_c" ||
  1751.     echo 'lzc.c: original size 8393, current size' "$Wc_c"
  1752. fi
  1753. # ============= lzconst.h ==============
  1754. if test -f 'lzconst.h' -a X"$1" != X"-c"; then
  1755.     echo 'x - skipping lzconst.h (File already exists)'
  1756. else
  1757. echo 'x - extracting lzconst.h (Text)'
  1758. sed 's/^X//' << 'SHAR_EOF' > 'lzconst.h' &&
  1759. /* @(#) lzconst.h 2.1 87/12/25 12:22:30 */
  1760. X
  1761. /*
  1762. The contents of this file are hereby released to the public domain.
  1763. X
  1764. X                                    -- Rahul Dhesi  1986/12/31
  1765. */
  1766. X
  1767. #define  INBUFSIZ    (IN_BUF_SIZE - 10)   /* avoid obo errors */
  1768. #define  OUTBUFSIZ   (OUT_BUF_SIZE - 10)
  1769. #define  MEMERR      2
  1770. #define  IOERR       1
  1771. #define  MAXBITS     13
  1772. #define  CLEAR       256         /* clear code */
  1773. #define  Z_EOF       257         /* end of file marker */
  1774. #define  FIRST_FREE  258         /* first free code */
  1775. #define  MAXMAX      8192        /* max code + 1 */
  1776. SHAR_EOF
  1777. chmod 0644 lzconst.h ||
  1778. echo 'restore of lzconst.h failed'
  1779. Wc_c="`wc -c < 'lzconst.h'`"
  1780. test 574 -eq "$Wc_c" ||
  1781.     echo 'lzconst.h: original size 574, current size' "$Wc_c"
  1782. fi
  1783. true || echo 'restore of lzd.asm failed'
  1784. echo End of part 3, continue with part 4
  1785. exit 0
  1786.