home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3607 < prev    next >
Encoding:
Text File  |  1991-07-11  |  47.2 KB  |  1,636 lines

  1. Newsgroups: alt.sources
  2. Subject: zoo 2.1 source part 04/15
  3. Message-ID: <12770@bsu-cs.bsu.edu>
  4. From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
  5. Date: 10 Jul 91 09:18:52 GMT
  6.  
  7. Checksum: 1481112143 (verify with "brik -cv")
  8. Submitted-by: dhesi@bsu-cs.bsu.edu
  9. Archive-name: zoo210/part04
  10.  
  11. ---- Cut Here and feed the following to sh ----
  12. #!/bin/sh
  13. # This is part 04 of zoo210
  14. # ============= lzd.asm ==============
  15. if test -f 'lzd.asm' -a X"$1" != X"-c"; then
  16.     echo 'x - skipping lzd.asm (File already exists)'
  17. else
  18. echo 'x - extracting lzd.asm (Text)'
  19. sed 's/^X//' << 'SHAR_EOF' > 'lzd.asm' &&
  20. title    Lempel-Ziv Decompressor
  21. ; $Source: /usr/home/dhesi/zoo/RCS/lzd.asm,v $
  22. ; $Id: lzd.asm,v 1.3 91/07/07 09:36:23 dhesi Exp $
  23. X
  24. ;Derived from Tom Pfau's public domain assembly code.
  25. ;The contents of this file are hereby released to the public domain.
  26. ;                                   -- Rahul Dhesi 1988/08/24
  27. X
  28. UNBUF_IO    equ    1        ;use unbuffered I/O
  29. X
  30. public    _lzd,memflag,docrc
  31. X
  32. X    include    asmconst.ai
  33. X    include macros.ai
  34. X
  35. ;Hash table entry
  36. hash_rec    struc
  37. next    dw    ?            ; prefix code
  38. char    db    ?            ; suffix char
  39. hash_rec    ends
  40. X
  41. extrn    _addbfcrc:near            ;External C function for CRC
  42. X
  43. ifdef    UNBUF_IO
  44. extrn    _read:near
  45. extrn    _blockwrite:near
  46. else
  47. extrn    _zooread:near
  48. extrn    _zoowrite:near
  49. endif
  50. X
  51. ;Declare segments
  52. _text    segment byte public 'code'
  53. _text    ends
  54. X
  55. dgroup    group    _data
  56. X    assume ds:dgroup,es:dgroup
  57. _data    segment word public 'data'
  58. extrn    _out_buf_adr:word        ;address of C output buffer
  59. extrn    _in_buf_adr:word        ;address of C input buffer
  60. X
  61. memflag        db    0        ;Memory allocated?  flag
  62. save_bp        dw    ?
  63. save_sp        dw    ?
  64. X
  65. input_handle    dw    ?
  66. output_handle    dw    ?
  67. hash_seg    dw    ?
  68. cur_code    dw    ?
  69. old_code    dw    ?
  70. in_code        dw    ?
  71. free_code    dw    first_free
  72. X
  73. ;Note:  for re-entrancy, following 3 must be re-initialized each time
  74. stack_count    dw    0
  75. nbits        dw    9
  76. max_code    dw    512
  77. X
  78. fin_char    db    ?
  79. k        db    ?
  80. masks        dw    1ffh,3ffh,7ffh,0fffh,1fffh
  81. X
  82. ;Note:  for re-entrancy, following 2 must be re-initialized each time
  83. bit_offset    dw    0
  84. output_offset    dw    0
  85. _data    ends
  86. X
  87. memory    segment para public 'memory'
  88. hash    label    hash_rec
  89. memory    ends
  90. X
  91. call_index macro
  92. X    mov    bp,bx            ;bx = bx * 3 (3 byte entries)
  93. X    shl    bx,1            ;bp = bx
  94. X    add    bx,bp            ;bx = bx * 2 + bp
  95. X    endm
  96. X
  97. call_write_char macro
  98. X    local    wc$1
  99. X    mov    di,output_offset    ;Get offset in buffer
  100. X    cmp    di,outbufsiz        ;Full?
  101. X    jb    wc$1            ;no
  102. X    call    write_char_partial
  103. X    sub    di,di            ;so we add zero in next statement
  104. wc$1:    add    di,[_out_buf_adr]    ;di <- buffer address + di
  105. X    stosb                ;Store char
  106. X    inc    output_offset        ;Increment number of chars in buffer
  107. X    endm
  108. X
  109. add_code macro
  110. X    mov    bx,free_code        ;Get new code
  111. X    ;call    index            ;convert to address
  112. X    call_index
  113. X    push    es            ;point to hash table
  114. X    mov    es,hash_seg
  115. X    mov    al,k            ;get suffix char
  116. X    mov    es:[bx].char,al        ;save it
  117. X    mov    ax,old_code        ;get prefix code
  118. X    mov    es:[bx].next,ax        ;save it
  119. X    pop    es
  120. X    inc    free_code        ;set next code
  121. X    endm
  122. X
  123. ;Start coding
  124. _text    segment
  125. X    assume    cs:_text,ds:dgroup,es:dgroup,ss:nothing
  126. X
  127. write_char_partial proc    near
  128. X    push    cx
  129. X    mov    cx,di            ;byte count
  130. X    call    write_block
  131. X    pop    cx
  132. X    mov    output_offset,0        ;Restore buffer pointer
  133. X    ret
  134. write_char_partial endp
  135. X
  136. _lzd    proc    near
  137. X
  138. X    push    bp            ;Standard C entry code
  139. X    mov    bp,sp
  140. X    push    di
  141. X    push    si
  142. X    
  143. X    push    ds            ;Save ds to be sure
  144. X    mov    [save_bp],bp        ;And bp too!
  145. X    mov    bx,ds
  146. X    mov    es,bx
  147. X
  148. ;Get two parameters, both integers, that are input file handle and
  149. ;output file handle
  150. X    mov    ax,[bp+4]
  151. X    mov    [input_handle],ax
  152. X    mov    ax,[bp+6]
  153. X    mov    [output_handle],ax
  154. X
  155. X    call    decompress        ;Compress file & get status in AX
  156. X
  157. X    mov    bp,[save_bp]        ;Restore bp
  158. X    pop    ds
  159. X    pop    si            ;Standard C return code
  160. X    pop    di
  161. X    mov    sp,bp
  162. X    pop    bp
  163. X    ret
  164. _lzd    endp
  165. X
  166. ;Note:  Procedure decompress returns AX=0 for successful decompression and
  167. ;    AX=1 for I/O error and AX=2 for malloc failure.  
  168. decompress    proc    near
  169. X    mov    [save_sp],sp        ;Save SP in case of error return
  170. X
  171. ;Initialize variables -- required for serial re-entrancy
  172. X    mov    [nbits],9
  173. X    mov    [max_code],512
  174. X    mov    [free_code],first_free
  175. X    mov    [stack_count],0
  176. X    mov    [bit_offset],0
  177. X    mov    [output_offset],0
  178. X
  179. X    test    memflag,0ffH        ;Memory allocated?
  180. X    jnz    gotmem            ;If allocated, continue
  181. X    malloc    <((maxmax * 3) / 16 + 20)>    ;allocate it
  182. X    jnc    here1
  183. X    jmp    MALLOC_err
  184. here1:
  185. X    mov    hash_seg,ax        ;Save segment address of mem block
  186. X    mov    memflag,0ffh        ;Set flag to remind us later
  187. gotmem:
  188. X
  189. X    mov    ax,inbufsiz
  190. X    push    ax            ;byte count
  191. X    push    _in_buf_adr        ;buffer address
  192. X    push    input_handle        ;zoofile
  193. ifdef    UNBUF_IO
  194. X    call    _read
  195. else
  196. X    call    _zooread
  197. endif
  198. X    add    sp,6
  199. X
  200. X    cmp    ax,-1
  201. X    jz    IO_err            ;I/O error
  202. here2:
  203. X
  204. l1:    call    read_code        ;Get a code
  205. X    cmp    ax,eof            ;End of file?
  206. X    jne    l2            ;no
  207. X    cmp    output_offset,0        ;Data in output buffer?
  208. X    je    OK_ret            ;no
  209. X    mov    cx,[output_offset]    ;byte count
  210. X    call    write_block        ;write block of cx bytes
  211. OK_ret:    
  212. X    xor    ax,ax            ;Normal return -- decompressed
  213. X    ret                ;done
  214. IO_err:
  215. X    mov    ax,2            ;I/O error return 
  216. X    mov    sp,[save_sp]        ;Restore stack pointer
  217. X    ret    
  218. X
  219. MALLOC_err:
  220. X    mov    ax,1            ;Malloc error return
  221. X    mov    sp,[save_sp]        ;Restore stack pointer
  222. X    ret
  223. X
  224. l2:    cmp    ax,clear        ;Clear code?
  225. X    jne    l7            ;no
  226. X    call    init_tab        ;Initialize table
  227. X    call    read_code        ;Read next code
  228. X    mov    cur_code,ax        ;Initialize variables
  229. X    mov    old_code,ax
  230. X    mov    k,al
  231. X    mov    fin_char,al
  232. X    mov    al,k
  233. X    ;call    write_char        ;Write character
  234. X    call_write_char
  235. X    jmp    l1            ;Get next code
  236. l7:    mov    cur_code,ax        ;Save new code
  237. X    mov    in_code,ax
  238. X    mov    es,hash_seg        ;Point to hash table
  239. X    cmp    ax,free_code        ;Code in table? (k<w>k<w>k)
  240. X    jb    l11            ;yes
  241. X    mov    ax,old_code        ;get previous code
  242. X    mov    cur_code,ax        ;make current
  243. X    mov    al,fin_char        ;get old last char
  244. X    push    ax            ;push it
  245. X    inc    stack_count
  246. X
  247. ;old code -- two memory references
  248. ;l11:    
  249. ;    cmp    cur_code,255        ;Code or character?
  250. ;    jbe    l15            ;Char
  251. ;    mov    bx,cur_code        ;Convert code to address
  252. ;new code -- 0 or 1 memory references
  253. X    mov    ax,cur_code
  254. l11:
  255. X    ;All paths in must have ax containing cur_code
  256. X    cmp    ax,255
  257. X    jbe    l15
  258. X    mov    bx,ax
  259. ;end code
  260. X    ;call    index
  261. X    call_index
  262. X    mov    al,es:2[bx]        ;Get suffix char
  263. X    push    ax            ;push it
  264. X    inc    stack_count
  265. X    mov    ax,es:[bx]        ;Get prefix code
  266. X    mov    cur_code,ax        ;Save it
  267. X    jmp    l11            ;Translate again
  268. l15:    
  269. ;old code
  270. ;    push    ds            ;Restore seg reg
  271. ;    pop    es
  272. ;new code
  273. X    mov    ax,ds            ;faster than push/pop
  274. X    mov    es,ax
  275. ;end code
  276. X    mov    ax,cur_code        ;Get code
  277. X    mov    fin_char,al        ;Save as final, k
  278. X    mov    k,al
  279. X    push    ax            ;Push it
  280. X
  281. ;old code
  282. ;    inc    stack_count
  283. ;    mov    cx,stack_count        ;Pop stack
  284. ;new code -- slightly faster because INC of memory is slow
  285. X    mov    cx,stack_count
  286. X    inc    cx
  287. X    mov    stack_count,cx
  288. ;end code
  289. X    jcxz    l18            ;If anything there
  290. l17:    pop    ax
  291. X    ;call    write_char
  292. X    call_write_char
  293. X    loop    l17
  294. X
  295. ;old code
  296. ;l18:    
  297. ;    mov    stack_count,cx        ;Clear count on stack
  298. ;new code -- because stack_count is already zero on earlier "jcxz l18"
  299. X    mov    stack_count,cx
  300. l18:
  301. ;end code
  302. X
  303. X    ;call    add_code        ;Add new code to table
  304. X    add_code
  305. X    mov    ax,in_code        ;Save input code
  306. X    mov    old_code,ax
  307. X    mov    bx,free_code        ;Hit table limit?
  308. X    cmp    bx,max_code
  309. X    jb    l23            ;Less means no
  310. X    cmp    nbits,maxbits        ;Still within maxbits?
  311. X    je    l23            ;no (next code should be clear)
  312. X    inc    nbits            ;Increase code size
  313. X    shl    max_code,1        ;Double max code
  314. l23:    jmp    l1            ;Get next code
  315. decompress    endp    
  316. X
  317. read_code    proc    near
  318. X
  319. ;old code
  320. ;    mov    ax,bit_offset        ;Get bit offset
  321. ;    add    ax,nbits        ;Adjust by code size
  322. ;    xchg    bit_offset,ax        ;Swap
  323. ;    mov    dx,ax            ;dx <- ax
  324. ;new code
  325. X    mov    ax,bit_offset
  326. X    mov    dx,ax            ;dx <- bit_offset
  327. X    add    ax,nbits
  328. X    mov    bit_offset,ax
  329. X    mov    ax,dx
  330. ;end code
  331. X
  332. X    shr    ax,1
  333. X    shr    ax,1
  334. X    shr    ax,1            ;ax <- ax div 8
  335. X    and    dx,07            ;dx <- ax mod 8
  336. X    cmp    ax,inbufsiz-3        ;Approaching end of buffer?
  337. X    jb    rd0            ;no
  338. X    push    dx            ;Save offset in byte
  339. X    add    dx,nbits        ;Calculate new bit offset
  340. X    mov    bit_offset,dx
  341. X    mov    cx,inbufsiz
  342. X    mov    bp,ax            ;save byte offset
  343. X    sub    cx,ax            ;Calculate bytes left
  344. X    add    ax,_in_buf_adr
  345. X    mov    si,ax
  346. X    mov    di,_in_buf_adr
  347. rep    movsb                ;Move last chars down
  348. X
  349. X    push    bp            ;byte count
  350. X    push    di            ;buffer address
  351. X    push    input_handle        ;zoofile
  352. ifdef    UNBUF_IO
  353. X    call _read
  354. else
  355. X    call    _zooread
  356. endif
  357. X    add    sp,6
  358. X
  359. X    cmp    ax,-1
  360. X    jnz    here4
  361. X    jmp    IO_err            ;I/O error
  362. X
  363. here4:
  364. X    xor    ax,ax            ;Clear ax
  365. X    pop    dx            ;Restore offset in byte
  366. rd0:    
  367. X    add    ax,_in_buf_adr
  368. X    mov    si,ax
  369. X    lodsw                ;Get word
  370. X    mov    bx,ax            ;Save in AX
  371. X    lodsb                ;Next byte
  372. X    mov    cx,dx            ;Offset in byte
  373. X    jcxz    rd2            ;If zero, skip shifts
  374. rd1:    shr    al,1            ;Put code in low (code size) bits of BX
  375. X    rcr    bx,1
  376. X    loop    rd1
  377. rd2:    mov    ax,bx            ;put code in ax
  378. X    mov    bx,nbits        ;mask off unwanted bits
  379. X    sub    bx,9
  380. X    shl    bx,1
  381. X    and    ax,masks[bx]
  382. X    ret
  383. read_code    endp
  384. X
  385. init_tab    proc    near
  386. X    mov    nbits,9            ;Initialize variables
  387. X    mov    max_code,512
  388. X    mov    free_code,first_free
  389. X    ret
  390. init_tab    endp
  391. X
  392. comment #
  393. index        proc    near
  394. X    mov    bp,bx            ;bx = bx * 3 (3 byte entries)
  395. X    shl    bx,1            ;bp = bx
  396. X    add    bx,bp            ;bx = bx * 2 + bp
  397. X    ret
  398. index        endp
  399. #end comment
  400. X
  401. docrc    proc    near
  402. ;On entry, ax=char count, dx=buffer address.
  403. ;Do crc on character count, in buffer.
  404. ;****** Update CRC value -- call external C program
  405. X    ;External program is:    addbfcrc(buffer, count)
  406. X    ;            char *buffer;
  407. X    ;            int count;
  408. X
  409. X    push    ax        ;SAVE AX
  410. X    push    bx        ;SAVE BX
  411. X    push    cx
  412. X    push    dx
  413. X
  414. X    push    ax        ;param 2: char count
  415. X    push    dx        ;param 1: buffer address
  416. X    call    _addbfcrc
  417. X    add    sp,4        ;Restore 2 params from stack
  418. X
  419. X    pop    dx
  420. X    pop    cx
  421. X    pop    bx        ;RESTORE BX
  422. X    pop    ax        ;RESTORE AX
  423. X    ret
  424. docrc    endp
  425. X
  426. write_block proc near
  427. ;Input:  CX=byte count to write
  428. X    push    ax
  429. X    push    bx
  430. X    push    cx
  431. X    push    dx
  432. X    push    si            ;may not be necessary to save si & di
  433. X    push    di
  434. X
  435. X    push    cx            ;save count
  436. X
  437. X    push    cx            ;count
  438. X    push    _out_buf_adr        ;buffer
  439. X    push    output_handle        ;zoofile
  440. ifdef    UNBUF_IO
  441. X    call    _blockwrite
  442. else
  443. X    call    _zoowrite
  444. endif
  445. X    add    sp,6
  446. X
  447. X    pop    cx            ;restore count
  448. X
  449. X    ;ax = actual number of bytes written
  450. X    cmp    ax,cx            ;all bytes written?
  451. X    je    written            ;if yes, OK
  452. X    jmp    IO_err
  453. written:
  454. X    mov    dx,_out_buf_adr
  455. X    call    docrc            ;do crc on ax bytes in buffer dx
  456. X    mov    output_offset,0        ;restore buffer ptr to zero
  457. X
  458. X    pop    di
  459. X    pop    si
  460. X    pop    dx
  461. X    pop    cx
  462. X    pop    bx
  463. X    pop    ax
  464. X    ret
  465. write_block endp
  466. X
  467. _text    ends
  468. X
  469. X    end
  470. SHAR_EOF
  471. chmod 0644 lzd.asm ||
  472. echo 'restore of lzd.asm failed'
  473. Wc_c="`wc -c < 'lzd.asm'`"
  474. test 9144 -eq "$Wc_c" ||
  475.     echo 'lzd.asm: original size 9144, current size' "$Wc_c"
  476. fi
  477. # ============= lzd.c ==============
  478. if test -f 'lzd.c' -a X"$1" != X"-c"; then
  479.     echo 'x - skipping lzd.c (File already exists)'
  480. else
  481. echo 'x - extracting lzd.c (Text)'
  482. sed 's/^X//' << 'SHAR_EOF' > 'lzd.c' &&
  483. #ifndef LINT
  484. static char sccsid[]="@(#) lzd.c 2.6 88/01/30 20:39:18";
  485. #endif /* LINT */
  486. X
  487. /*********************************************************************/
  488. /* This file contains two versions of the lzd() decompression routine.
  489. The default is to use a fast version coded by Ray Gardner.  If the
  490. symbol SLOW_LZD is defined, the older slower one is used.  I have tested
  491. Ray's code and it seems to be portable and reliable.  But if you
  492. suspect any problems you can define SLOW_LZD for your system in
  493. options.h and cause the older code to be used.  --R.D. */
  494. /*********************************************************************/
  495. X
  496. #include "options.h"
  497. #include "zoo.h"
  498. #include "zooio.h"
  499. #include "various.h"
  500. #include "zoofns.h"           /* function definitions */
  501. #include "zoomem.h"
  502. #include "debug.h"
  503. #include "assert.h"
  504. #include "lzconst.h"
  505. X
  506. #ifndef SLOW_LZD
  507. X
  508. /* Extensive modifications for speed by Ray Gardner
  509. ** Public domain by Raymond D. Gardner  9/26/88
  510. **
  511. ** I apologize for the comments being so dense in places as to impair
  512. ** readability, but some of the stuff isn't very obvious and needs
  513. ** some explaining.  I am also sorry for the messy control structure
  514. ** (quite a few labels and goto's) and very long lzd() function, but
  515. ** I don't know how to do this any other way without loss of speed.
  516. **
  517. ** Ray Gardner
  518. ** 6374 S. Monaco Ct.
  519. ** Englewood, CO 80111
  520. */
  521. X
  522. #ifdef ANSI_HDRS
  523. # include <string.h>        /* to get memcpy */
  524. #else
  525. X  VOIDPTR memcpy();
  526. #endif
  527. X
  528. #define  STACKSIZE   4000  /* allows for about 8Mb string in worst case? */
  529. /* stack grows backwards in this version, using pointers, not counters */
  530. static char *stack;
  531. static char *stack_pointer;
  532. static char *stack_lim;
  533. X
  534. void init_dtab PARMS((void));
  535. unsigned rd_dcode PARMS((void));
  536. /* void wr_dchar (char); */        /* now a macro */
  537. void ad_dcode PARMS((void));
  538. X
  539. #ifdef FILTER
  540. /* to send data back to zoofilt */
  541. extern unsigned int filt_lzd_word;
  542. #endif /* FILTER */
  543. X
  544. void xwr_dchar PARMS ((char));
  545. static int firstchar PARMS ((int));
  546. static void cbfill PARMS ((void));
  547. X
  548. /* wr_dchar() is a macro for speed */
  549. #define wr_dchar(c) {                             \
  550. X                           if (outbufp<outbuflim) \
  551. X                              *outbufp++=(c);     \
  552. X                           else                   \
  553. X                              xwr_dchar(c);       \
  554. X                    }
  555. X
  556. extern char *out_buf_adr;        /* output buffer */
  557. extern char *in_buf_adr;         /* input buffer */
  558. X                      /* use pointers (not counters) for buffer (for speed) */
  559. static char *outbufp;            /* output buffer pointer */
  560. static char *outbuflim;          /* output buffer limit */
  561. static char *outbufguard;        /* output buffer "guard" */
  562. X
  563. char memflag = 0;                /* memory allocated? flag */
  564. int *head;                       /* lzw prefix codes */
  565. char *tail;                      /* lzw suffix codes */
  566. static unsigned cur_code;
  567. static unsigned old_code;
  568. static unsigned in_code;
  569. X
  570. static unsigned free_code;
  571. static int nbits;
  572. static unsigned max_code;
  573. X
  574. /* We use a buffer of codes to avoid a function call to unpack each
  575. ** one as needed.  We allocate an extra slot past the end of the buffer
  576. ** and put a CLEAR code in it, to serve as a sentinel.  This way we can
  577. ** fold the test for code buffer runout into the test for a clear code
  578. ** and avoid having an extra test on each code processed.  Also, we don't
  579. ** always use the code buffer.  We can only use it when the input buffer
  580. ** is at a byte boundary, and when we know that the codesize won't change
  581. ** before we fill the code buffer, and when we know we won't run out of
  582. ** bytes in the input buffer before filling the code buffer.  So we start
  583. ** with the code buffer pointer pointing to the sentinel, and we always
  584. ** have it pointing at the sentinel when we can't (for one reason or
  585. ** another) be getting our codes from the code buffer.  We check for this
  586. ** condition whenever we get a CLEAR code, and if so, we get the code
  587. ** via the good old rd_dcode() routine.
  588. **
  589. ** One other problem with the code buffer approach is that we might get
  590. ** a CLEAR code in the middle of the buffer.  This means that the next
  591. ** code is only 9 bits, but we have probably already unpacked a number of
  592. ** larger codes from the input into the buffer before we discover this.
  593. ** So we remember where (in the input buffer) the code buffer was filled
  594. ** from, and when a CLEAR code is encountered in the buffer (not the
  595. ** sentinel at the end) we back up the bit_offset pointer in the input
  596. ** buffer, and reset things to start unpacking the 9-bit codes from there.
  597. */
  598. X
  599. #define CODEBUF_SIZE 64      /* must be multiple of 8, experiment for best */
  600. static unsigned codebuf[CODEBUF_SIZE+1];     /* code buffer */
  601. static unsigned *codebufp;       /* code buffer pointer */
  602. static unsigned *codebuflim;     /* code buffer limit */
  603. X      /* bit offset within the input buffer of where the code buffer began */
  604. static unsigned codebufoffset;
  605. X
  606. static unsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
  607. X                        0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
  608. static unsigned bit_offset;   /* note this only allows max 8K input buffer!!*/
  609. X
  610. #ifdef UNBUF_IO
  611. #define        BLOCKFILE        int
  612. #define        BLOCKREAD        read
  613. #define        BLOCKWRITE        blockwrite
  614. int read PARMS ((int, VOIDPTR, unsigned));
  615. int write PARMS ((int, VOIDPTR, unsigned));
  616. int blockwrite PARMS ((int, VOIDPTR, unsigned));
  617. #else
  618. #define        BLOCKFILE        ZOOFILE
  619. #define        BLOCKREAD        zooread
  620. #define        BLOCKWRITE        zoowrite
  621. #endif /* UNBUF_IO */
  622. X
  623. static BLOCKFILE in_f, out_f;
  624. X
  625. /* rd_dcode() reads a code from the input (compressed) file and returns
  626. its value. */
  627. unsigned rd_dcode()
  628. {
  629. X   register char *ptra, *ptrb;    /* miscellaneous pointers */
  630. X   unsigned word;                     /* first 16 bits in buffer */
  631. X   unsigned byte_offset;
  632. X   char nextch;                           /* next 8 bits in buffer */
  633. X   unsigned ofs_inbyte;               /* offset within byte */
  634. X
  635. X   ofs_inbyte = bit_offset % 8;
  636. X   byte_offset = bit_offset / 8;
  637. X   bit_offset = bit_offset + nbits;
  638. X
  639. X   assert(nbits >= 9 && nbits <= 13);
  640. X
  641. X   if (byte_offset >= INBUFSIZ - 5) {
  642. X      int space_left;
  643. X
  644. X      assert(byte_offset >= INBUFSIZ - 5);
  645. X      debug((printf ("lzd: byte_offset near end of buffer\n")))
  646. X
  647. X      bit_offset = ofs_inbyte + nbits;
  648. X      space_left = INBUFSIZ - byte_offset;
  649. X      ptrb = byte_offset + in_buf_adr;          /* point to char */
  650. X      ptra = in_buf_adr;
  651. X      /* we now move the remaining characters down buffer beginning */
  652. X      debug((printf ("rd_dcode: space_left = %d\n", space_left)))
  653. X      while (space_left > 0) {
  654. X         *ptra++ = *ptrb++;
  655. X         space_left--;
  656. X      }
  657. X      assert(ptra - in_buf_adr == ptrb - (in_buf_adr + byte_offset));
  658. X      assert(space_left == 0);
  659. X      if (BLOCKREAD (in_f, ptra, byte_offset) == -1)
  660. X         prterror ('f', "I/O error in lzd:rd_dcode.\n");
  661. X      byte_offset = 0;
  662. X   }
  663. X   ptra = byte_offset + in_buf_adr;
  664. X /* NOTE:  "word = *((int *) ptra)" would not be independent of byte order. */
  665. X   word = (unsigned char) *ptra; ptra++;
  666. X   word = word | ( ((unsigned char) *ptra) << 8 ); ptra++;
  667. X
  668. X   nextch = *ptra;
  669. X   if (ofs_inbyte != 0) {
  670. X      /* shift nextch right by ofs_inbyte bits */
  671. X      /* and shift those bits right into word; */
  672. X      word = (word >> ofs_inbyte) | (((unsigned)nextch) << (16-ofs_inbyte));
  673. X   }
  674. X   return (word & masks[nbits]); 
  675. } /* rd_dcode() */
  676. X
  677. void init_dtab()
  678. {
  679. X   nbits = 9;
  680. X   max_code = 512;
  681. X   free_code = FIRST_FREE;
  682. }
  683. X
  684. /* By making wr_dchar() a macro and calling this routine only on buffer
  685. ** full condition, we save a lot of function call overhead.
  686. ** We also use pointers instead of counters for efficiency (in the macro).
  687. */
  688. void xwr_dchar (ch)
  689. char ch;
  690. {
  691. X   if (outbufp >= outbuflim) {      /* if buffer full */
  692. X      if (BLOCKWRITE (out_f, out_buf_adr, outbufp - out_buf_adr)
  693. X                                                != outbufp - out_buf_adr)
  694. X         prterror ('f', "Write error in lzd:wr_dchar.\n");
  695. X      addbfcrc(out_buf_adr, outbufp - out_buf_adr);     /* update CRC */
  696. X      outbufp = out_buf_adr;                  /* restore empty buffer */
  697. X   }
  698. X   assert(outbufp - out_buf_adr < OUTBUFSIZ);
  699. X   *outbufp++ = ch;
  700. } /* wr_dchar() */
  701. X
  702. X
  703. /* Code buffer fill routines
  704. **
  705. ** We use a separate function for each code size.
  706. ** Each function unpacks 8 codes from a packed buffer (f)
  707. ** to an unpacked buffer (t)
  708. ** A lot of code space, but really speeds up bit picking.
  709. */
  710. static unsigned char f[13];   /* must be unsigned for right shifts */
  711. static unsigned t[8];
  712. X
  713. static void cb9fill ()
  714. {
  715. X   t[0] = (f[0]     ) | ((f[1] &   1) << 8);
  716. X   t[1] = (f[1] >> 1) | ((f[2] &   3) << 7);
  717. X   t[2] = (f[2] >> 2) | ((f[3] &   7) << 6);
  718. X   t[3] = (f[3] >> 3) | ((f[4] &  15) << 5);
  719. X   t[4] = (f[4] >> 4) | ((f[5] &  31) << 4);
  720. X   t[5] = (f[5] >> 5) | ((f[6] &  63) << 3);
  721. X   t[6] = (f[6] >> 6) | ((f[7] & 127) << 2);
  722. X   t[7] = (f[7] >> 7) | ((f[8]      ) << 1);
  723. }
  724. X
  725. static void cb10fill ()
  726. {
  727. X   t[0] = (f[0]     ) | ((f[1] &   3) << 8);
  728. X   t[1] = (f[1] >> 2) | ((f[2] &  15) << 6);
  729. X   t[2] = (f[2] >> 4) | ((f[3] &  63) << 4);
  730. X   t[3] = (f[3] >> 6) | ((f[4]      ) << 2);
  731. X   t[4] = (f[5]     ) | ((f[6] &   3) << 8);
  732. X   t[5] = (f[6] >> 2) | ((f[7] &  15) << 6);
  733. X   t[6] = (f[7] >> 4) | ((f[8] &  63) << 4);
  734. X   t[7] = (f[8] >> 6) | ((f[9]      ) << 2);
  735. }
  736. X
  737. static void cb11fill ()
  738. {
  739. X   t[0] = (f[0]     ) | ((f[1] &   7) << 8);
  740. X   t[1] = (f[1] >> 3) | ((f[2] &  63) << 5);
  741. X   t[2] = (f[2] >> 6) | (f[3] << 2) | ((f[4] &  1) << 10);
  742. X   t[3] = (f[4] >> 1) | ((f[5] &  15) << 7);
  743. X   t[4] = (f[5] >> 4) | ((f[6] & 127) << 4);
  744. X   t[5] = (f[6] >> 7) | (f[7] << 1) | ((f[8] &  3) <<  9);
  745. X   t[6] = (f[8] >> 2) | ((f[9] &  31) << 6);
  746. X   t[7] = (f[9] >> 5) | ((f[10]     ) << 3);
  747. }
  748. X
  749. static void cb12fill ()
  750. {
  751. X   t[0] = (f[0]     )  | ((f[1] & 15) << 8);
  752. X   t[1] = (f[1] >> 4)  | ((f[2]     ) << 4);
  753. X   t[2] = (f[3]     )  | ((f[4] & 15) << 8);
  754. X   t[3] = (f[4] >> 4)  | ((f[5]     ) << 4);
  755. X   t[4] = (f[6]     )  | ((f[7] & 15) << 8);
  756. X   t[5] = (f[7] >> 4)  | ((f[8]     ) << 4);
  757. X   t[6] = (f[9]     )  | ((f[10] & 15) << 8);
  758. X   t[7] = (f[10] >> 4) | ((f[11]     ) << 4);
  759. }
  760. X
  761. static void cb13fill ()
  762. {
  763. X   t[0] = (f[0] ) | ((f[1] & 31) << 8);
  764. X   t[1] = (f[1] >> 5) | (f[2] << 3) | ((f[3] & 3) << 11);
  765. X   t[2] = (f[3] >> 2) | ((f[4] & 127) << 6);
  766. X   t[3] = (f[4] >> 7) | (f[5] << 1) | ((f[6] & 15) << 9);
  767. X   t[4] = (f[6] >> 4) | (f[7] << 4) | ((f[8] & 1) << 12);
  768. X   t[5] = (f[8] >> 1) | ((f[9] & 63) << 7);
  769. X   t[6] = (f[9] >> 6) | (f[10] << 2) | ((f[11] & 7) << 10);
  770. X   t[7] = (f[11] >> 3) | (f[12] << 5);
  771. }
  772. X
  773. /* vector of code buffer fill routines
  774. */
  775. void (*cbfillvec[])  PARMS ((void)) = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
  776. X         cb9fill, cb10fill, cb11fill, cb12fill, cb13fill };
  777. X
  778. /* cbfill -- main code buffer fill routine
  779. **
  780. ** moves data from inbuf[] to f[]
  781. ** then calls via vector to unpack to t[]
  782. ** then moves from t[] to codebuf[]
  783. ** A lot of moving around, but still faster than a lot of shifting and
  784. ** masking via variables (at least on a micro -- don't know about VAXen)
  785. **  Uses memcpy() for block move
  786. */
  787. X
  788. static void cbfill ()
  789. {
  790. X   char *inbp;
  791. X   inbp = in_buf_adr + bit_offset / 8;
  792. X   codebufp = codebuf;
  793. X   while ( codebufp < codebuflim ) {
  794. X     memcpy((VOIDPTR) f, inbp, nbits);
  795. X      (*cbfillvec[nbits])();
  796. X      memcpy((VOIDPTR) codebufp, (VOIDPTR) t, 8 * sizeof(unsigned int));
  797. X      inbp += nbits;
  798. X      codebufp += 8;
  799. X   }
  800. X   bit_offset += nbits * CODEBUF_SIZE;
  801. }
  802. X
  803. /* The following is used in the KwKwK case because it's a pretty rare
  804. ** case, and doing it this way avoids the overhead of remembering the
  805. ** "finchar" (first input character) of every string
  806. */
  807. static int firstchar(code)    /* find first character of a code */
  808. int code;
  809. {
  810. X   while ( code > 255 )
  811. X      code = head[code];
  812. X   return code;
  813. }
  814. X
  815. int lzd(input_f, output_f)
  816. BLOCKFILE input_f, output_f;          /* input & output files */
  817. {
  818. X   in_f = input_f;                 /* make it avail to other fns */
  819. X   out_f = output_f;               /* ditto */
  820. X   nbits = 9;
  821. X   max_code = 512;
  822. X   free_code = FIRST_FREE;
  823. X   bit_offset = 0;
  824. X   outbuflim = out_buf_adr + OUTBUFSIZ;   /* setup out buffer limit */
  825. X   outbufguard = outbuflim - 12;     /* for checking avail. room in outbuf */
  826. X      /* note must allow for as many characters as we special-case (8) */
  827. X      /* used 12 for extra fudge factor (Rahul does it, so I can too) */
  828. X   outbufp = out_buf_adr;                 /* setup output buffer ptr */ 
  829. X   codebufp = codebuflim = &codebuf[CODEBUF_SIZE]; /* code buf ptr & limit */
  830. X   *codebuflim = CLEAR; /* phony CLEAR sentinel past end of code buffer */
  831. X
  832. X   if (BLOCKREAD (in_f, in_buf_adr, INBUFSIZ) == -1) /* fill input buffer */
  833. X      return(IOERR);
  834. X   if (memflag == 0) {
  835. X     head = (int *) ealloc((MAXMAX+10) * sizeof(int));
  836. X     tail = (char *) ealloc((MAXMAX+10) * sizeof(char));
  837. X     stack = (char *) ealloc (sizeof (unsigned) * STACKSIZE + 20);
  838. X     memflag++;
  839. X   }
  840. X
  841. X   stack_pointer = stack_lim = stack + STACKSIZE; /* setup stack ptr, limit*/
  842. X   init_dtab();             /* initialize table */
  843. X
  844. loop:
  845. X   cur_code = *codebufp++; /* get code from code buffer */
  846. X
  847. goteof: /* special case for CLEAR then Z_EOF, for 0-length files */
  848. X   if (cur_code == Z_EOF) {
  849. X      debug((printf ("lzd: Z_EOF\n")))
  850. X
  851. X      if (outbufp != out_buf_adr) {
  852. X          if (BLOCKWRITE (out_f, out_buf_adr, outbufp - out_buf_adr)
  853. X                                                  != outbufp - out_buf_adr)
  854. X             prterror ('f', "Output error in lzd().\n");
  855. X            addbfcrc(out_buf_adr, outbufp - out_buf_adr);
  856. X
  857. X      }
  858. #ifdef FILTER
  859. X        /* get next two bytes and put them where zoofilt can find them */
  860. X        /* nbits known to be in range 9..13 */
  861. X        bit_offset = ((bit_offset + 7) / 8) * 8; /* round up to next byte */
  862. X        filt_lzd_word = rd_dcode();
  863. X        filt_lzd_word |= (rd_dcode() << nbits);
  864. X        filt_lzd_word &= 0xffff;
  865. #endif
  866. X      return (0);
  867. X   }
  868. X
  869. X   assert(nbits >= 9 && nbits <= 13);
  870. X
  871. X   if (cur_code == CLEAR) {          /* was it sentinel or real CLEAR ? */
  872. X      if ( codebufp > codebuflim ) { /* it was the sentinel             */
  873. X         if ( bit_offset % 8 == 0 && /* if we're on byte boundary and   */
  874. X                   /* codesize won't change before codebuf is filled and */
  875. X                   /* codebuf can be filled without running out of inbuf */
  876. X                free_code + CODEBUF_SIZE < max_code &&
  877. X                bit_offset / 8 + (CODEBUF_SIZE * 13 / 8) < INBUFSIZ - 10 ) {
  878. X            codebufoffset = bit_offset; /* remember where we were when */
  879. X            cbfill();             /* we filled the code buffer */
  880. X            codebufp = codebuf;   /* setup code buffer pointer */
  881. X            goto loop;            /* now go get codes from code buffer */
  882. X         }                 /* otherwise, use rd_dcode to get code */
  883. X         codebufp = codebuflim;   /* reset codebuf ptr to sentinel */
  884. X         cur_code = rd_dcode();   /* get code via rd_dcode() */
  885. X         if ( cur_code != CLEAR ) /* if it's not CLEAR */
  886. X            goto got_code;        /* then go handle it */
  887. X      } else {          /* else it's really a CLEAR code, not sentinel */
  888. X /* reset bit_offset to get next code in input buf after CLEAR code */
  889. X         bit_offset = codebufoffset + (codebufp - codebuf) * nbits;
  890. X      } 
  891. X      codebufp = codebuflim;      /* set code buf ptr to sentinel */
  892. X      debug((printf ("lzd: CLEAR\n")))
  893. X      init_dtab();                /* init decompression table, etc. */
  894. X      old_code = cur_code = rd_dcode(); /* get next code after CLEAR */
  895. X        if (cur_code == Z_EOF)        /* special case for 0-length files */
  896. X            goto goteof;
  897. X      wr_dchar(cur_code);         /* write it out */
  898. X      goto loop;                  /* and get next code */
  899. X   }
  900. X
  901. got_code: /* we got a code and it's not a CLEAR */
  902. X
  903. X   if (cur_code == Z_EOF) {
  904. X      debug((printf ("lzd: Z_EOF\n")))
  905. X      if (outbufp != out_buf_adr) {
  906. X          if (BLOCKWRITE (out_f, out_buf_adr, outbufp - out_buf_adr)
  907. X                                                  != outbufp - out_buf_adr)
  908. X             prterror ('f', "Output error in lzd().\n");
  909. X         addbfcrc(out_buf_adr, outbufp - out_buf_adr);
  910. X      }
  911. X      return (0);
  912. X   }
  913. X
  914. X   in_code = cur_code;              /* save original code */
  915. X   if (cur_code >= free_code) {        /* if code not in table (k<w>k<w>k) */
  916. X      cur_code = old_code;             /* previous code becomes current */
  917. X                                       /* push first character of old code */
  918. X      *--stack_pointer = firstchar(old_code);
  919. X      goto unwind;                     /* and go "unwind" the current code */
  920. X   }              /* (use general unwind because the stack isn't empty now) */
  921. X
  922. /* Unwind a code.  The basic idea is to use a sort of loop-unrolling
  923. ** approach to really speed up the processing by treating the codes
  924. ** which represent short strings (the vast majority of codes) as
  925. ** special cases.  Avoid a lot of stack overflow checking safely.
  926. */
  927. X
  928. X   if (cur_code > 255) {                  /* if cur_code is not atomic */
  929. X      *--stack_pointer = tail[cur_code];  /* push its tail code */
  930. X      cur_code = head[cur_code];          /* and replace with its head code */
  931. X   } else {                        /* else 1-byte string */
  932. X      if ( outbufp > outbufguard ) /* if outbuf near end, */
  933. X         goto write_stack;         /* write via general routine */
  934. X      *outbufp++ = cur_code;       /* we got space, put char out */
  935. X      goto add_code;               /* add code to table */
  936. X   }
  937. X
  938. X   if (cur_code > 255) {                  /* if cur_code is not atomic */
  939. X      *--stack_pointer = tail[cur_code];  /* push its tail code */
  940. X      cur_code = head[cur_code];          /* and replace with its head code */
  941. X   } else {                        /* else 2-byte string */
  942. X      if ( outbufp > outbufguard ) /* if outbuf near end, */
  943. X         goto write_stack;         /* write via general routine */
  944. X      *outbufp++ = cur_code;       /* we got space, put char out, and */
  945. X      goto move_1_char;            /* go move rest of stack to outbuf */
  946. X   }
  947. X   if (cur_code > 255) {                  /* if cur_code is not atomic */
  948. X      *--stack_pointer = tail[cur_code];  /* push its tail code */
  949. X      cur_code = head[cur_code];          /* and replace with its head code */
  950. X   } else {                        /* else 3-byte string */
  951. X      if ( outbufp > outbufguard ) /* if outbuf near end, */
  952. X         goto write_stack;         /* write via general routine */
  953. X      *outbufp++ = cur_code;       /* we got space, put char out, and */
  954. X      goto move_2_char;            /* go move rest of stack to outbuf */
  955. X   }
  956. X
  957. /* we handle codes representing strings of 4 thru 8 bytes similarly */
  958. X
  959. X   if (cur_code > 255) {
  960. X      *--stack_pointer = tail[cur_code];
  961. X      cur_code = head[cur_code];
  962. X   } else {                        /* 4-byte string */
  963. X      if ( outbufp > outbufguard )
  964. X         goto write_stack;
  965. X      *outbufp++ = cur_code;
  966. X      goto move_3_char;
  967. X   }
  968. X   if (cur_code > 255) {
  969. X      *--stack_pointer = tail[cur_code];
  970. X      cur_code = head[cur_code];
  971. X   } else {                        /* 5-byte string */
  972. X      if ( outbufp > outbufguard )
  973. X         goto write_stack;
  974. X      *outbufp++ = cur_code;
  975. X      goto move_4_char;
  976. X   }
  977. X   if (cur_code > 255) {
  978. X      *--stack_pointer = tail[cur_code];
  979. X      cur_code = head[cur_code];
  980. X   } else {                        /* 6-byte string */
  981. X      if ( outbufp > outbufguard )
  982. X         goto write_stack;
  983. X      *outbufp++ = cur_code;
  984. X      goto move_5_char;
  985. X   }
  986. X   if (cur_code > 255) {
  987. X      *--stack_pointer = tail[cur_code];
  988. X      cur_code = head[cur_code];
  989. X   } else {                        /* 7-byte string */
  990. X      if ( outbufp > outbufguard )
  991. X         goto write_stack;
  992. X      *outbufp++ = cur_code;
  993. X      goto move_6_char;
  994. X   }
  995. X   if (cur_code > 255) {
  996. X      *--stack_pointer = tail[cur_code];
  997. X      cur_code = head[cur_code];
  998. X   } else {                        /* 8-byte string */
  999. X      if ( outbufp > outbufguard )
  1000. X         goto write_stack;
  1001. X      *outbufp++ = cur_code;
  1002. X      goto move_7_char;
  1003. X   }
  1004. X
  1005. /* Here for KwKwK case and strings longer than 8 bytes */
  1006. /* Note we have to check stack here, but not elsewhere */
  1007. X
  1008. unwind:
  1009. X   while (cur_code > 255) {               /* if code, not character */
  1010. X      *--stack_pointer = tail[cur_code];         /* push suffix char */
  1011. X      if (stack_pointer < stack+12)
  1012. X         prterror ('f', "Stack overflow in lzd().\n");
  1013. X      cur_code = head[cur_code];          /* head of code is new code */
  1014. X   }
  1015. X
  1016. /* General routine to write stack with check for output buffer full */
  1017. X
  1018. write_stack:
  1019. X   assert(nbits >= 9 && nbits <= 13);
  1020. X   wr_dchar(cur_code);    /* write this code, don't need to stack it first */
  1021. X   while ( stack_pointer < stack_lim ) {
  1022. X      wr_dchar(*stack_pointer++);
  1023. X   }
  1024. X   goto add_code;                           /* now go add code to table */
  1025. X
  1026. /* Here to move strings from stack to output buffer */
  1027. /* only if we know we have enough room in output buffer */
  1028. /* because (outbufp <= outbufguard) */
  1029. X
  1030. move_7_char:
  1031. X   *outbufp++ = *stack_pointer++;
  1032. move_6_char:
  1033. X   *outbufp++ = *stack_pointer++;
  1034. move_5_char:
  1035. X   *outbufp++ = *stack_pointer++;
  1036. move_4_char:
  1037. X   *outbufp++ = *stack_pointer++;
  1038. move_3_char:
  1039. X   *outbufp++ = *stack_pointer++;
  1040. move_2_char:
  1041. X   *outbufp++ = *stack_pointer++;
  1042. move_1_char:
  1043. X   *outbufp++ = *stack_pointer++;
  1044. X
  1045. assert(stack_pointer == stack_lim); /* I haven't tested this! rdg */
  1046. X
  1047. /* add_code is now inline to avoid overhead of function call on */
  1048. /*   each code processed */
  1049. X
  1050. add_code:
  1051. X   assert(nbits >= 9 && nbits <= 13);
  1052. X   assert(free_code <= MAXMAX+1);
  1053. X   tail[free_code] = cur_code;                /* save suffix char */
  1054. X   head[free_code] = old_code;                /* save prefix code */
  1055. X   free_code++;
  1056. X   assert(nbits >= 9 && nbits <= 13);
  1057. X   if (free_code >= max_code) {
  1058. X      if (nbits < MAXBITS) {
  1059. X         debug((printf("lzd: nbits was %d\n", nbits)))
  1060. X         nbits++;
  1061. X         assert(nbits >= 9 && nbits <= 13);
  1062. X         debug((printf("lzd: nbits now %d\n", nbits)))
  1063. X         max_code = max_code << 1;        /* double max_code */
  1064. X         debug((printf("lzd: max_code now %d\n", max_code)))
  1065. X      }
  1066. X   }
  1067. X   old_code = in_code;
  1068. X
  1069. X   assert(nbits >= 9 && nbits <= 13);
  1070. X
  1071. X   goto loop;
  1072. } /* lzd() */
  1073. X
  1074. #else /* SLOW_LZD defined, so use following instead */
  1075. X
  1076. /*********************************************************************/
  1077. /* Original slower lzd().                                            */
  1078. /*********************************************************************/
  1079. X
  1080. /*
  1081. Lempel-Ziv decompression.  Mostly based on Tom Pfau's assembly language
  1082. code.  The contents of this file are hereby released to the public domain.
  1083. X                                 -- Rahul Dhesi 1986/11/14
  1084. */
  1085. X
  1086. #define  STACKSIZE   4000
  1087. X
  1088. struct tabentry {
  1089. X   unsigned next;
  1090. X   char z_ch;
  1091. };
  1092. X
  1093. void init_dtab PARMS((void));
  1094. unsigned rd_dcode PARMS((void));
  1095. void wr_dchar PARMS((int));
  1096. void ad_dcode PARMS((void));
  1097. X
  1098. #ifdef FILTER
  1099. /* to send data back to zoofilt */
  1100. extern unsigned int filt_lzd_word;
  1101. #endif /* FILTER */
  1102. X
  1103. X
  1104. static unsigned stack_pointer = 0;
  1105. static unsigned *stack;
  1106. X
  1107. #define  push(x)  {  \
  1108. X                     stack[stack_pointer++] = (x);                   \
  1109. X                     if (stack_pointer >= STACKSIZE)                 \
  1110. X                        prterror ('f', "Stack overflow in lzd().\n");\
  1111. X                  }
  1112. #define  pop()    (stack[--stack_pointer])
  1113. X
  1114. extern char *out_buf_adr;        /* output buffer */
  1115. extern char *in_buf_adr;         /* input buffer */
  1116. X
  1117. char memflag = 0;                /* memory allocated? flag */
  1118. extern struct tabentry *table;   /* hash table from lzc.c */
  1119. static unsigned cur_code;
  1120. static unsigned old_code;
  1121. static unsigned in_code;
  1122. X
  1123. static unsigned free_code;
  1124. static int nbits;
  1125. static unsigned max_code;
  1126. X
  1127. static char fin_char;
  1128. static char k;
  1129. static unsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1130. X                        0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
  1131. static unsigned bit_offset;
  1132. static unsigned output_offset;
  1133. X
  1134. #ifdef UNBUF_IO
  1135. #define        BLOCKFILE        int
  1136. #define        BLOCKREAD        read
  1137. #define        BLOCKWRITE        blockwrite
  1138. int read PARMS ((int, VOIDPTR, unsigned));
  1139. int write PARMS ((int, VOIDPTR, unsigned));
  1140. #else
  1141. #define        BLOCKFILE        ZOOFILE
  1142. #define        BLOCKREAD        zooread
  1143. #define        BLOCKWRITE        zoowrite
  1144. #endif /* UNBUF_IO */
  1145. X
  1146. static BLOCKFILE in_f, out_f; 
  1147. X
  1148. int lzd(input_f, output_f)
  1149. BLOCKFILE input_f, output_f;          /* input & output file handles */
  1150. {
  1151. X   in_f = input_f;                 /* make it avail to other fns */
  1152. X   out_f = output_f;               /* ditto */
  1153. X   nbits = 9;
  1154. X   max_code = 512;
  1155. X   free_code = FIRST_FREE;
  1156. X   stack_pointer = 0;
  1157. X   bit_offset = 0;
  1158. X   output_offset = 0;
  1159. X
  1160. X   if (BLOCKREAD (in_f, in_buf_adr, INBUFSIZ) == -1)
  1161. X      return(IOERR);
  1162. X   if (memflag == 0) {
  1163. X     table = (struct tabentry *) ealloc((MAXMAX+10) * sizeof(struct tabentry));
  1164. X     stack = (unsigned *) ealloc (sizeof (unsigned) * STACKSIZE + 20);
  1165. X     memflag++;
  1166. X   }
  1167. X
  1168. X   init_dtab();             /* initialize table */
  1169. X
  1170. loop:
  1171. X   cur_code = rd_dcode();
  1172. goteof: /* special case for CLEAR then Z_EOF, for 0-length files */
  1173. X   if (cur_code == Z_EOF) {
  1174. X      debug((printf ("lzd: Z_EOF\n")))
  1175. X      if (output_offset != 0) {
  1176. X         if (BLOCKWRITE (out_f, out_buf_adr, output_offset) != output_offset)
  1177. X            prterror ('f', "Output error in lzd().\n");
  1178. X         addbfcrc(out_buf_adr, output_offset);
  1179. X      }
  1180. #ifdef FILTER
  1181. X        /* get next two bytes and put them where zoofilt can find them */
  1182. X        /* nbits known to be in range 9..13 */
  1183. X        bit_offset = ((bit_offset + 7) / 8) * 8; /* round up to next byte */
  1184. X        filt_lzd_word = rd_dcode();
  1185. X        filt_lzd_word |= (rd_dcode() << nbits);
  1186. X        filt_lzd_word &= 0xffff;
  1187. #endif
  1188. X      return (0);
  1189. X   }
  1190. X
  1191. X   assert(nbits >= 9 && nbits <= 13);
  1192. X
  1193. X   if (cur_code == CLEAR) {
  1194. X      debug((printf ("lzd: CLEAR\n")))
  1195. X      init_dtab();
  1196. X      fin_char = k = old_code = cur_code = rd_dcode();
  1197. X        if (cur_code == Z_EOF)        /* special case for 0-length files */
  1198. X            goto goteof;
  1199. X      wr_dchar(k);
  1200. X      goto loop;
  1201. X   }
  1202. X
  1203. X   in_code = cur_code;
  1204. X   if (cur_code >= free_code) {        /* if code not in table (k<w>k<w>k) */
  1205. X      cur_code = old_code;             /* previous code becomes current */
  1206. X      push(fin_char);
  1207. X   }
  1208. X
  1209. X   while (cur_code > 255) {               /* if code, not character */
  1210. X      push(table[cur_code].z_ch);         /* push suffix char */
  1211. X      cur_code = table[cur_code].next;    /* <w> := <w>.code */
  1212. X   }
  1213. X
  1214. X   assert(nbits >= 9 && nbits <= 13);
  1215. X
  1216. X   k = fin_char = cur_code;
  1217. X   push(k);
  1218. X   while (stack_pointer != 0) {
  1219. X      wr_dchar(pop());
  1220. X   }
  1221. X   assert(nbits >= 9 && nbits <= 13);
  1222. X   ad_dcode();
  1223. X   old_code = in_code;
  1224. X
  1225. X   assert(nbits >= 9 && nbits <= 13);
  1226. X
  1227. X   goto loop;
  1228. } /* lzd() */
  1229. X
  1230. /* rd_dcode() reads a code from the input (compressed) file and returns
  1231. its value. */
  1232. unsigned rd_dcode()
  1233. {
  1234. X   register char *ptra, *ptrb;    /* miscellaneous pointers */
  1235. X   unsigned word;                     /* first 16 bits in buffer */
  1236. X   unsigned byte_offset;
  1237. X   char nextch;                           /* next 8 bits in buffer */
  1238. X   unsigned ofs_inbyte;               /* offset within byte */
  1239. X
  1240. X   ofs_inbyte = bit_offset % 8;
  1241. X   byte_offset = bit_offset / 8;
  1242. X   bit_offset = bit_offset + nbits;
  1243. X
  1244. X   assert(nbits >= 9 && nbits <= 13);
  1245. X
  1246. X   if (byte_offset >= INBUFSIZ - 5) {
  1247. X      int space_left;
  1248. X
  1249. #ifdef CHECK_BREAK
  1250. X    check_break();
  1251. #endif
  1252. X
  1253. X      assert(byte_offset >= INBUFSIZ - 5);
  1254. X      debug((printf ("lzd: byte_offset near end of buffer\n")))
  1255. X
  1256. X      bit_offset = ofs_inbyte + nbits;
  1257. X      space_left = INBUFSIZ - byte_offset;
  1258. X      ptrb = byte_offset + in_buf_adr;          /* point to char */
  1259. X      ptra = in_buf_adr;
  1260. X      /* we now move the remaining characters down buffer beginning */
  1261. X      debug((printf ("rd_dcode: space_left = %d\n", space_left)))
  1262. X      while (space_left > 0) {
  1263. X         *ptra++ = *ptrb++;
  1264. X         space_left--;
  1265. X      }
  1266. X      assert(ptra - in_buf_adr == ptrb - (in_buf_adr + byte_offset));
  1267. X      assert(space_left == 0);
  1268. X      if (BLOCKREAD (in_f, ptra, byte_offset) == -1)
  1269. X         prterror ('f', "I/O error in lzd:rd_dcode.\n");
  1270. X      byte_offset = 0;
  1271. X   }
  1272. X   ptra = byte_offset + in_buf_adr;
  1273. X   /* NOTE:  "word = *((int *) ptra)" would not be independent of byte order. */
  1274. X   word = (unsigned char) *ptra; ptra++;
  1275. X   word = word | ( ((unsigned char) *ptra) << 8 ); ptra++;
  1276. X
  1277. X   nextch = *ptra;
  1278. X   if (ofs_inbyte != 0) {
  1279. X      /* shift nextch right by ofs_inbyte bits */
  1280. X      /* and shift those bits right into word; */
  1281. X      word = (word >> ofs_inbyte) | (((unsigned)nextch) << (16-ofs_inbyte));
  1282. X   }
  1283. X   return (word & masks[nbits]); 
  1284. } /* rd_dcode() */
  1285. X
  1286. void init_dtab()
  1287. {
  1288. X   nbits = 9;
  1289. X   max_code = 512;
  1290. X   free_code = FIRST_FREE;
  1291. }
  1292. X
  1293. void wr_dchar (ch)
  1294. int ch;
  1295. {
  1296. X   if (output_offset >= OUTBUFSIZ) {      /* if buffer full */
  1297. #ifdef CHECK_BREAK
  1298. X    check_break();
  1299. #endif
  1300. X      if (BLOCKWRITE (out_f, out_buf_adr, output_offset) != output_offset)
  1301. X         prterror ('f', "Write error in lzd:wr_dchar.\n");
  1302. X      addbfcrc(out_buf_adr, output_offset);     /* update CRC */
  1303. X      output_offset = 0;                  /* restore empty buffer */
  1304. X   }
  1305. X   assert(output_offset < OUTBUFSIZ);
  1306. X   out_buf_adr[output_offset++] = ch;        /* store character */
  1307. } /* wr_dchar() */
  1308. X
  1309. /* adds a code to table */
  1310. void ad_dcode()
  1311. {
  1312. X   assert(nbits >= 9 && nbits <= 13);
  1313. X   assert(free_code <= MAXMAX+1);
  1314. X   table[free_code].z_ch = k;                /* save suffix char */
  1315. X   table[free_code].next = old_code;         /* save prefix code */
  1316. X   free_code++;
  1317. X   assert(nbits >= 9 && nbits <= 13);
  1318. X   if (free_code >= max_code) {
  1319. X      if (nbits < MAXBITS) {
  1320. X         debug((printf("lzd: nbits was %d\n", nbits)))
  1321. X         nbits++;
  1322. X         assert(nbits >= 9 && nbits <= 13);
  1323. X         debug((printf("lzd: nbits now %d\n", nbits)))
  1324. X         max_code = max_code << 1;        /* double max_code */
  1325. X         debug((printf("lzd: max_code now %d\n", max_code)))
  1326. X      }
  1327. X   }
  1328. }
  1329. #endif /* ! SLOW_LZD */
  1330. SHAR_EOF
  1331. chmod 0644 lzd.c ||
  1332. echo 'restore of lzd.c failed'
  1333. Wc_c="`wc -c < 'lzd.c'`"
  1334. test 29821 -eq "$Wc_c" ||
  1335.     echo 'lzd.c: original size 29821, current size' "$Wc_c"
  1336. fi
  1337. # ============= lzh.c ==============
  1338. if test -f 'lzh.c' -a X"$1" != X"-c"; then
  1339.     echo 'x - skipping lzh.c (File already exists)'
  1340. else
  1341. echo 'x - extracting lzh.c (Text)'
  1342. sed 's/^X//' << 'SHAR_EOF' > 'lzh.c' &&
  1343. /* $Id: lzh.c,v 1.15 91/07/06 19:18:51 dhesi Exp $ */
  1344. /*
  1345. lzh compression and uncompression interface module
  1346. */
  1347. X
  1348. #include "options.h"
  1349. #include "zoo.h"
  1350. #include "ar.h"
  1351. #include "errors.i"
  1352. X
  1353. FILE *arcfile;
  1354. X
  1355. extern void prterror();
  1356. X
  1357. extern char *out_buf_adr;            /* address of buffer */
  1358. X
  1359. int lzh_encode(infile, outfile)
  1360. FILE *infile;
  1361. FILE *outfile;
  1362. {
  1363. X    extern void encode();
  1364. X    encode(infile, outfile);
  1365. X    return 0;
  1366. }
  1367. X
  1368. /*
  1369. lzh_decode decodes its input and sends it to output.
  1370. Should return error status or byte count, but currently
  1371. returns 0.
  1372. */
  1373. X
  1374. #undef COUNT_BYTES        /* define for debugging */
  1375. X
  1376. int lzh_decode(infile, outfile)
  1377. FILE *infile;
  1378. FILE *outfile;
  1379. {
  1380. X    int n;
  1381. X    extern int decoded;
  1382. #ifdef COUNT_BYTES
  1383. X    int bytes_decoded = 0;        /*debug*/ /* count bytes after decoding */
  1384. #endif
  1385. X
  1386. X    arcfile = infile;                    /* stream to be decoded */
  1387. X
  1388. X    decode_start();
  1389. X    while (!decoded) {
  1390. X        n = decode((uint) DICSIZ, out_buf_adr); /* n = count of chars decoded */
  1391. #ifdef COUNT_BYTES
  1392. X        bytes_decoded += n;    /*debug*/
  1393. #endif
  1394. #ifdef CHECK_BREAK
  1395. X        check_break();
  1396. #endif
  1397. X        fwrite_crc(out_buf_adr, n, outfile);
  1398. #ifdef SHOW_DOTS
  1399. X        (void) putc('.', stderr);
  1400. X        (void) fflush(stderr);
  1401. #endif
  1402. X    }
  1403. #ifdef COUNT_BYTES
  1404. X    (void) fprintf(stderr, "bytes decoded = %d\n", bytes_decoded);
  1405. #endif
  1406. X    return 0;
  1407. }
  1408. SHAR_EOF
  1409. chmod 0644 lzh.c ||
  1410. echo 'restore of lzh.c failed'
  1411. Wc_c="`wc -c < 'lzh.c'`"
  1412. test 1255 -eq "$Wc_c" ||
  1413.     echo 'lzh.c: original size 1255, current size' "$Wc_c"
  1414. fi
  1415. # ============= lzh.h ==============
  1416. if test -f 'lzh.h' -a X"$1" != X"-c"; then
  1417.     echo 'x - skipping lzh.h (File already exists)'
  1418. else
  1419. echo 'x - extracting lzh.h (Text)'
  1420. sed 's/^X//' << 'SHAR_EOF' > 'lzh.h' &&
  1421. /*$Source: /usr/home/dhesi/zoo/RCS/lzh.h,v $*/
  1422. /*$Id: lzh.h,v 1.3 91/07/09 01:39:23 dhesi Exp $*/
  1423. X
  1424. /*
  1425. Adapted from "ar" archiver written by Haruhiko Okumura.
  1426. */
  1427. X
  1428. /* Define some things if they aren't defined in header files */
  1429. #ifndef CHAR_BIT
  1430. # define CHAR_BIT 8
  1431. #endif
  1432. X
  1433. #ifndef UCHAR_MAX
  1434. # define UCHAR_MAX 255
  1435. #endif
  1436. X
  1437. /* io.c */
  1438. X
  1439. extern FILE *arcfile, *lzh_infile, *lzh_infile;
  1440. extern t_uint16 bitbuf;
  1441. #define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
  1442. X
  1443. /* encode.c and decode.c */
  1444. X
  1445. #define MATCHBIT   8    /* bits for MAXMATCH - THRESHOLD */
  1446. #define MAXMATCH 256    /* formerly F (not more than UCHAR_MAX + 1) */
  1447. #define THRESHOLD  3    /* choose optimal value */
  1448. #define PERC_FLAG ((unsigned) 0x8000)
  1449. X
  1450. /* huf.c */
  1451. X
  1452. #define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
  1453. X    /* alphabet = {0, 1, 2, ..., NC - 1} */
  1454. #define CBIT 9  /* $\lfloor \log_2 NC \rfloor + 1$ */
  1455. #define CODE_BIT  16  /* codeword length */
  1456. X
  1457. extern ushort left[], right[];
  1458. SHAR_EOF
  1459. chmod 0644 lzh.h ||
  1460. echo 'restore of lzh.h failed'
  1461. Wc_c="`wc -c < 'lzh.h'`"
  1462. test 934 -eq "$Wc_c" ||
  1463.     echo 'lzh.h: original size 934, current size' "$Wc_c"
  1464. fi
  1465. # ============= machine.c ==============
  1466. if test -f 'machine.c' -a X"$1" != X"-c"; then
  1467.     echo 'x - skipping machine.c (File already exists)'
  1468. else
  1469. echo 'x - extracting machine.c (Text)'
  1470. sed 's/^X//' << 'SHAR_EOF' > 'machine.c' &&
  1471. #ifndef LINT
  1472. /* @(#) machine.c 2.3 88/01/02 01:21:44 */
  1473. static char sccsid[]="@(#) machine.c 2.3 88/01/02 01:21:44";
  1474. #endif /* LINT */
  1475. X
  1476. /*
  1477. The contents of this file are hereby released to the public domain.
  1478. X
  1479. X                                    -- Rahul Dhesi  1986/12/31
  1480. */
  1481. X
  1482. /* This file is in two parts. */
  1483. X
  1484. #include "options.h"
  1485. #include "zooio.h"
  1486. #include "zoo.h"
  1487. #include "zoofns.h"
  1488. #include "various.h"
  1489. X
  1490. /***********************************************************************/
  1491. /* PART 1.  FOR UNBUFFERED I/O ONLY.  DO NOT CHANGE.                   */
  1492. /***********************************************************************/
  1493. X
  1494. #ifdef UNBUF_IO
  1495. int write PARMS ((int, VOIDPTR, unsigned));
  1496. X
  1497. /*
  1498. blockwrite() is like write() except that it ignores all
  1499. output to file descriptor -2, which stands for the null file.
  1500. */
  1501. int blockwrite (fd, buf, count)
  1502. int fd;
  1503. #ifdef VOIDPTR
  1504. VOIDPTR buf;
  1505. #else
  1506. char *buf;
  1507. #endif /* VOIDPTR */
  1508. unsigned count;
  1509. {
  1510. X    if (fd == -2)
  1511. X        return (count);
  1512. X    else
  1513. X        return (write (fd, buf, count));
  1514. }
  1515. #endif
  1516. X
  1517. /***********************************************************************/
  1518. /* PART 2.  FOR EACH SPECIFIC SYSTEM, INCLUDE A C FILE HERE.           */
  1519. /***********************************************************************/
  1520. X
  1521. #ifdef SYS_V
  1522. #include "sysv.c"
  1523. #endif
  1524. X
  1525. #ifdef GENERIC
  1526. #include "generic.c"
  1527. #endif
  1528. X
  1529. #ifdef BSD4_3
  1530. #include "bsd.c"
  1531. #endif
  1532. X
  1533. #ifdef DLC
  1534. #include "generic.c"
  1535. #endif
  1536. X
  1537. #ifdef VMS
  1538. #include "vms.c"
  1539. #endif
  1540. X
  1541. #ifdef MSC
  1542. #include "ERROR -- NOT SUPPORTED"
  1543. #endif
  1544. X
  1545. #ifdef TURBOC
  1546. #ifdef PORTABLE
  1547. #include "generic.c"
  1548. #else
  1549. #include "turboc.c"
  1550. #endif
  1551. #endif
  1552. SHAR_EOF
  1553. chmod 0644 machine.c ||
  1554. echo 'restore of machine.c failed'
  1555. Wc_c="`wc -c < 'machine.c'`"
  1556. test 1589 -eq "$Wc_c" ||
  1557.     echo 'machine.c: original size 1589, current size' "$Wc_c"
  1558. fi
  1559. # ============= machine.h ==============
  1560. if test -f 'machine.h' -a X"$1" != X"-c"; then
  1561.     echo 'x - skipping machine.h (File already exists)'
  1562. else
  1563. echo 'x - extracting machine.h (Text)'
  1564. sed 's/^X//' << 'SHAR_EOF' > 'machine.h' &&
  1565. /* @(#) machine.h 2.1 87/12/25 12:22:43 */
  1566. X
  1567. /*
  1568. The contents of this file are hereby released to the public domain.
  1569. X
  1570. X                           -- Rahul Dhesi 1986/11/14
  1571. */
  1572. X
  1573. /* 
  1574. This file holds definitions that usually do not change
  1575. between different systems, except when using REALLY strange systems.  But
  1576. options.h and machine.c hold stuff that does change quite a bit.
  1577. */
  1578. X
  1579. /* 
  1580. MAXLONG is the maximum size of a long integer.  Right now it doesn't have to
  1581. be accurate since it's only used within zooext() to fake infinite disk space.
  1582. */
  1583. #define  MAXLONG  ((unsigned long) (~0L))
  1584. X
  1585. /* 
  1586. Type BYTE must hold exactly 8 bits.  The code will collapse badly if BYTE is
  1587. anything other than exactly 8 bits. To avoid sign extension when casting
  1588. BYTE to a longer size, it must be declared unsigned.  For machine-
  1589. independence, Zoo does all I/O of archive headers and directory entries 
  1590. in units of BYTE.  The actual file data are not written in units of
  1591. BYTE, however, so portability may not be absolute.
  1592. */
  1593. typedef  unsigned char BYTE;  /* type corresponding to an 8-bit byte */
  1594. X
  1595. SHAR_EOF
  1596. chmod 0644 machine.h ||
  1597. echo 'restore of machine.h failed'
  1598. Wc_c="`wc -c < 'machine.h'`"
  1599. test 1069 -eq "$Wc_c" ||
  1600.     echo 'machine.h: original size 1069, current size' "$Wc_c"
  1601. fi
  1602. # ============= macros.ai ==============
  1603. if test -f 'macros.ai' -a X"$1" != X"-c"; then
  1604.     echo 'x - skipping macros.ai (File already exists)'
  1605. else
  1606. echo 'x - extracting macros.ai (Text)'
  1607. sed 's/^X//' << 'SHAR_EOF' > 'macros.ai' &&
  1608. ; $Source: /usr/home/dhesi/zoo/RCS/macros.ai,v $
  1609. ; $Id: macros.ai,v 1.2 91/07/07 09:37:52 dhesi Exp $
  1610. ;procedure index, used in-line to save some microseconds
  1611. call_index    macro
  1612. X    mov    si,bx            ;si = bx * 5 (5 byte hash entries)
  1613. X    shl    si,1            ;si = bx * 2 * 2 + bx
  1614. X    shl    si,1
  1615. X    add    si,bx
  1616. X    endm    
  1617. X
  1618. malloc    macro    siz
  1619. X    ifdif    <bx>,<siz>
  1620. X    mov    bx,siz
  1621. X    endif
  1622. X    mov    ah,48h
  1623. X    int    21h
  1624. X    endm
  1625. X
  1626. SHAR_EOF
  1627. chmod 0644 macros.ai ||
  1628. echo 'restore of macros.ai failed'
  1629. Wc_c="`wc -c < 'macros.ai'`"
  1630. test 369 -eq "$Wc_c" ||
  1631.     echo 'macros.ai: original size 369, current size' "$Wc_c"
  1632. fi
  1633. true || echo 'restore of makefile failed'
  1634. echo End of part 4, continue with part 5
  1635. exit 0
  1636.