mxmora@unix.SRI.COM (Matt Mora) (03/22/90)
Does anyone have some code that compresses and expands text? I have a program that needs to use about 200 files that are between 2k-20k big. The files take up about 1.5 megs. What I would like to be able to do is read in the compressed text uncompress it and then display in on the screen. Does anyone have code that can do this or information where to get some code? Thanks -- ___________________________________________________________ Matthew Mora SRI International mxmora@unix.sri.com ___________________________________________________________
gz@spt.entity.com (Gail Zacharias) (03/23/90)
In article <10314@unix.SRI.COM> mxmora@sri-unix.sri.com (Matt Mora) writes: >Does anyone have some code that compresses and expands text? Sure. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # makefile.hqx # mcompress.c # compstream.a # if test -f 'README' then echo shar: will not over-write existing file "'README'" else echo x - 'README' sed 's/^X//' >'README' << 'SHAR_EOF' XYou should have the following files: X Xcompstream.a - (MPW assembler source). A library for doing unix-compatible X compression and decompression. Documentation is near the top of the X source. Xmcompress.c - (MPW C source). A very simple MPW tool (i.e. no bells and X whistles) to demonstrate the use of the compsteam library. It implements X unix-compatible compress/decompress. 'mcompress -H' will print a short X help message. Xmakefile.hqx - a binhex'ed MPW make file for mcompress. X X enjoy, X gz@entity.com SHAR_EOF if test 522 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 522 characters)' fi fi if test -f 'makefile.hqx' then echo shar: will not over-write existing file "'makefile.hqx'" else echo x - 'makefile.hqx' sed 's/^X//' >'makefile.hqx' << 'SHAR_EOF' X(This file must be converted with BinHex 4.0) X X:#'eKDf9QD@aP!&4&@&40380"!3!!!!$F!!!"I[!kE@0[EA"bCA0c#F3*E@0[EA" XbCA0c,Q-ZEb"MEfe`Fh4bC@&Y,Q%ZE`d*E'PZDb!YEb"YBfpYF(*PFh-J,@-J*de X38b!R)#ed)#G08&08*b"YBfpYF(*PFh-ZBbj[)'0[EA"cG(*PB@dZB5j[),B0#5! XJ)RY$E'PLFQ&bD@9cI805G@jdD@eP,QmL)#*l3daTBR*KFQPPFhe$5@jdCA*QB@0 XP,QmL),B0#5!J)RY$6'PLFQ&bD@9cI90dC%0-D@)ZEb)J)RY$6'PLFQ&bD@9cI80 X6B@jP6'PL,QmL$B60!!!"!!!!!8`!!!"-!!!!-Pd!Q#B!!!)!!!!)!!!0!!!ARb# Xh!fKN-3!!!!!!!!!!#'eKDf9QD@aPE!)!!!"849K868&$33!!!!!!!!!!!!!!!&4 X&@&40380"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)SMbSJ!!!0`!!!&q!!!!!!! X#B!!!!!%`!!!!!!!!!!!!"-!!!6!"-!ae!6!!!!!!!!!!!!!!!!!!!!!!!!!!!!! X!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! X!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%J!#8e[EQ&ME`!!!&!!!6* XZ!!P0EfjKBfm!!!!"-`!!!!!!!!B!#!!T!!-"8`(p!33!!!&6!IdLL2+L!!!!!!! X!!!!!!!!!!3!!!!%!!!!"6!!!!%`!!!!b!"45m!Kd!!!!(!!b!!"08&05!!!!#J2 XYrrm!!!!!!"96$Q25: SHAR_EOF if test 911 -ne "`wc -c < 'makefile.hqx'`" then echo shar: error transmitting "'makefile.hqx'" '(should have been 911 characters)' fi fi if test -f 'mcompress.c' then echo shar: will not over-write existing file "'mcompress.c'" else echo x - 'mcompress.c' sed 's/^X//' >'mcompress.c' << 'SHAR_EOF' X/* Copyright 1988, Gail Zacharias. All rights reserved. X * Permission is hereby granted to copy, reproduce, redistribute or X * otherwise use this software provided there is no monetary profit X * gained specifically from its use or reproduction, it is not sold, X * rented, traded or otherwise marketed, and this copyright notice X * and the software version number is included prominently in any copy X * made. X * This is mcompress version 1.0. X * X * Send comments, suggestions, bug reports (not bloody likely), feature X * requests, etc. to gz@entity.com. X * X */ X X/* This program demonstrates the use of the compstream library. It X implements a simple unix-compatible compress/decompress MPW tool. X It only handles data forks of files for now. X */ X X#include <stdio.h> X Xextern long compinit(), uncompinit(); Xextern int compwrite(), uncompread(), compclose(), uncompclose(); X Xstdwrite (stream, size, buf) X FILE *stream; X char *buf; X{ X return (size == fwrite(buf, 1, size, stream)) ? 0 : -1; X} X Xstdread (stream, size, buf) X FILE *stream; X char *buf; X{ X return fread(buf, 1, size, stream); X} X Xmain (argc, argv) X char **argv; X{ X int block_compress = 1, nbits = 0, header = 1; X int decomp = 0; X FILE *inf, *outf; X char buf[512]; X long cstream; X int n; X X while (--argc > 0 && **++argv == '-') { X char *argp = &argv[0][1]; X if (!*argp) break; X do switch (*argp++) { X case 'd': decomp = 1; break; X case 'C': block_compress = 0; break; X case 'n': header = 0; break; X case 'b': if (*argp == '\0') { X if (--argc == 0) goto badarg; X argp = *++argv; X } X nbits = 0; X while ('0' <= *argp && *argp <= '9') X nbits = nbits*10 + (*argp++ - '0'); X if (*argp || nbits < 9 || nbits > 16) goto badarg; X break; X /* case 'm': macbinary = 1; break; /* not yet */ X default: goto badarg; X } while (*argp); X } X if (decomp && (!nbits && !header || nbits && header)) goto badarg; X if (argc > 2) goto badarg; X if (!nbits) nbits = 16; X inf = stdin; outf = stdout; X if (argc > 0 && strcmp("-", argv[0])) { X if (!(inf = fopen(argv[0], "r"))) { X fprintf(stderr, "mcompress: can't open \"%s\" for reading\n", argv[0]); X return 1; X } X if (!decomp && argc == 1) { X strcpy(buf, argv[0]); X strcat(buf, ".Z"); X if (outf = fopen(buf, "r")) { X fclose(outf); X fprintf(stderr, "mcompress: will not overwrite \"%s\"\n", buf); X return 1; X } X argv[1] = buf; X argc++; X } X } X if (argc > 1 && strcmp("-", argv[1])) { X if (!(outf = fopen(argv[1], "w"))) { X fprintf(stderr, "mcompress: can't open \"%s\" for writing\n", argv[1]); X return 1; X } X } X if (decomp) { X if (header) { X if (getc(inf) != 037 || getc(inf) != 0235 || (n = getc(inf)) == EOF) { X fprintf(stderr, "mcompress: That's not a compressed file!\n"); X return 1; X } X nbits = n & 0x1F; X block_compress = n & 0x80; X } X if (!(cstream = uncompinit(n & 0x1F, n & 0x80, stdread, inf))) { X fprintf(stderr, "mcompress: not enough memory\n"); X return 1; X } X while ((n=uncompread(cstream, sizeof(buf), buf)) > 0) fwrite(buf, 1, n, outf); X uncompclose(cstream); X } X else { X if (header) { X buf[0] = 037; X buf[1] = 0235; X buf[2] = nbits; X if (block_compress) buf[2] |= 0x80; X stdwrite(outf, 3, buf); X } X if (!(cstream = compinit(nbits, block_compress, stdwrite, outf))) { X fprintf(stderr, "mcompress: not enough memory\n"); X return 1; X } X while ((n=fread(buf, 1, sizeof(buf), inf)) > 0) compwrite(cstream, n, buf); X compclose(cstream); X } X fflush(outf); X if (ferror(inf) || ferror(outf)) { X fprintf(stderr, "mcompress: I/O error\n"); X return 2; X } X if (inf != stdin) fclose(inf); X if (outf != stdout) fclose(outf); X return 0; X Xbadarg: X fprintf(stderr, "mcompress v1.0, by gz@entity.com. Usage:\n\ Xmcompress [-dCnH] [-b maxbits] [inputfile [outputfile]]\n\ X -d = Do decompression rather than compression.\n\ X -b maxbits = max number of bits/code. Must be between 9 and 16.\n\ X The default is 16. Smaller values give worse results but require\n\ X less memory at runtime.\n\ X This option cannot be given for decompression unless -n is also specified.\n\ X -C = Do not perform 'block compression' (use only for compatibility with\n\ X obsolete versions of unix compress).\n\ X -n = Do not create/expect compress file header (for obsolete compatibility)\n\ X If this option is specified for decompression, -b must also be given.\n\ X -H = show this help message\n\ XIf no files are specified, reads standard input and writes standard output.\n\ XIf inputfile is specified but no outputfile, the output defaults as follows:\n\ X for compress: the input filename with \".Z\" appended.\n\ X for decompress: standard output.\n\ XOnly the data fork of the input file is processed.\n\ XNote that unlike the unix version, the input file is NOT deleted.\n\ X\n\ XThis is freeware. If you paid money for this program, you got ripped off.\n"); X return 2; X} X SHAR_EOF if test 5060 -ne "`wc -c < 'mcompress.c'`" then echo shar: error transmitting "'mcompress.c'" '(should have been 5060 characters)' fi fi if test -f 'compstream.a' then echo shar: will not over-write existing file "'compstream.a'" else echo x - 'compstream.a' sed 's/^X//' >'compstream.a' << 'SHAR_EOF' X;; Copyright 1988, Gail Zacharias. All rights reserved. X;; Permission is hereby granted to copy, reproduce, redistribute or X;; otherwise use this software provided there is no monetary profit X;; gained specifically from its use or reproduction, it is not sold, X;; rented, traded or otherwise marketed, and this copyright notice X;; and the software version number is included prominently in any copy X;; made. X;; This is compstream version 1.1. X;; X;; Send comments, suggestions, bug reports (not bloody likely), feature X;; requests, etc. to gz@entity.com. X;; X X load 'FlowCtlMacs.d' X case object X X export (compinit, compwrite, compclose):code X export (uncompinit, uncompread, uncompclose):code X X; This is a library for use with MPW C programs. It implements compression X; and uncompression compatible with the unix compress/uncompress programs. X; (But note that the unix programs create files with a 3 byte header which X; is NOT handled by this library. It's up to the caller to take care of X; any headers). X; X;The compress module consists of three functions: X;(1) long compinit (maxbits, block_compress, outputfn, param) X; int maxbits, block_compress; X; int (*outputfn)(); X; long param; X;This function allocates and initializes a compress stream and returns a X;'stream handle', or 0 if it can't allocate enough memory for its data X;structures (in which case MemErr contains the error code). X;maxbits must be an integer between 9 and 16. Larger values result in X; better compression but require more memory. X;block_compress should be non-zero to do 'block compression'. This is X; almost always a win, so use it. It requires no extra memory. X;outputfn should be the function to do actual I/O. It must be a function X; of 3 arguments: X; int outputfn(param, size, buffer) X; long param; X; int size; X; char *buffer; X; param will be the same param argument that was passed to compinit. X; The function should output the size bytes in buffer, and return a X; non-negative value if successful, or a negative value if an error X; occured. The outputfn will not be called again after it returns X; an error. X;(2) int compwrite (cstream, size, buffer) X; long cstream; X; int size; X; char *buffer; X; This function adds the size bytes in buffer to the compress stream. cstream X; is the stream handle returned by compinit. compwrite returns a non-negative X; value if successful or a negative value if an error occured. The value is X; actually the same as the value of last call to outputfn. Note that compwrite X; does buffering and so the calls to compwrite and outputfn are not precisely X; synchronized - a given call to compwrite might call outputfn several times or X; it might not call it at all. Once outputfn returns an error, compwrite will X; continue to return that error and never call outputfn again. X;(3) int compclose (cstream) X; long cstream; X; This function writes out any remaining characters in the stream buffer and X; frees its data structures. It returns an error code like compwrite. X X;The uncompress module consists of three functions: X;(1) long uncompinit (maxbits, block_compress, inputfn, param) X; int maxbits, block_compress; X; int (*inputfn)(); X; long param; X;This function allocates and initializes an uncompress stream and returns a X;'stream handle', or 0 if it can't allocate enough memory for its data X;structures (in which case MemErr contains the error code). X;maxbits and block_compress must be the values which were used by compress. X;inputfn should be the function to do actual I/O. It must be a function X; of 3 arguments: X; int inputfn(param, size, buffer) X; long param; X; int size; X; char *buffer; X; param will be the same param argument that was passed to compinit. X; The function should try to read size bytes into buffer, and return X; the number of bytes actually read. A negative value means an error X; occured, zero means end of file (no more bytes to be read). The inputfn X; will not be called again after it returns a non-positive value. X;(2) int uncompread (cstream, size, buffer) X; long cstream; X; int size; X; char *buffer; X; This function stores (at most) size bytes into buffer. cstream is the X; stream handle returned by uncompinit. uncompread returns the number of X; bytes read, or a non-positive value if there are no more bytes (in which case X; the value is actually the value returned by the last call to the inputfn). X; Note that uncompread does buffering and so the calls to uncompread and X; inputfn are not precisely synchronized - a given call to uncompread might X; call inputfn several times or it might not call it at all. Once inputfn X; returns a non-positive value, uncompread will continue to return that value X; and never call inputfn again. X;(3) int uncompclose (cstream) X; long cstream; X; This function frees the data structures used by the stream. It currently X; always returns 0 (no errors are possible). X X; Edit history X; 6/3/88 gz 1.1 Started edit history. Fix in < 16 bit compression. X XMemErr equ $220 X_NewPtr opword $A100+30 X_DisposPtr opword $A000+31 X_Debugger opword $A9FF X X Xcompress proc X XBUFSIZE equ 512 ;Output buffer size. X XCHECK_DIST equ 10000 X Xh equ d2 Xh2 equ d3 Xch equ d4 Xlastcode equ d5 Xncodes equ d6 Xinpos equ d7 X Xcodeptr equ a1 ;must be a1 (see write8codes) Xchtab equ a2 Xlasttab equ a3 Xcodetab equ a4 X Xmyregs reg d2-d7/a0-a4 Xmyregsz equ 44 Xhisregs reg d2-d7/a2-a4/a6 Xhisregsz equ 40 X Xfprec record 0 Xhsize ds.l 1 Xhshift ds.w 1 Xrd_cnt ds.l 1 Xrd_ptr ds.l 1 Xwr_cnt ds.w 1 Xwr_ptr ds.l 1 Xwr_param ds.l 1 Xwr_fn ds.l 1 Xwr_error ds.l 1 Xoutpos ds.l 1 Xcd_cnt ds.w 1 Xcd_buf ds.w 9 Xcheckpos ds.l 1 Xratio ds.l 1 Xcodesz ds.w 1 Xcodelim ds.l 1 Xmaxcodelim ds.l 1 Xsavedregs ds.b myregsz Xwr_buf ds.b BUFSIZE Xfprecsz equ * X endr X X macro X writecode.&sz &code X subq.w #1,cd_cnt(a6) X if# mi then.s X bsr.&default(&sz,'w') write8codes X endif# X move.w &code,-(codeptr) X endm X X macro X getchar.&sz &ch,&eoflab X subq.l #1,rd_cnt(a6) X if# ge then.s X move.l rd_ptr(a6),a0 X moveq #0,&ch X move.b (a0)+,&ch X move.l a0,rd_ptr(a6) X else#.s X bsr filbuf X move.l d0,&ch X bmi.&default(&sz,'w') &eoflab X endif# X addq.l #1,inpos X endm X X with fprec X X;compinit (maxbits, block_compress, outputfn, param) X export compinit Xcompinit X move.l #fprecsz,d0 X _NewPtr X if# ne then.s X moveq #0,d0 X rts X endif# X movem.l hisregs,-(sp) X move.l a0,a6 X move.l hisregsz+16(sp),wr_param(a6) X move.l hisregsz+12(sp),wr_fn(a6) X clr.l wr_error(a6) X lea wr_buf(a6),a0 X move.l a0,wr_ptr(a6) X move.w #BUFSIZE,wr_cnt(a6) X move.l hisregsz+4(sp),d0 ;maxbits X moveq #9,d1 X if# d0 lt.l d1 then.s X move.l d1,d0 X endif# X moveq #16,d1 X if# d0 gt.l d1 then.s X move.l d1,d0 X endif# X moveq #1,d1 X lsl.l d0,d1 X move.l d1,maxcodelim(a6) X subq.w #8,d0 X move.w d0,hshift(a6) X lsl.w #2,d0 X lea hsizes(pc),a0 X move.l -4(a0,d0.w),hsize(a6) X move.l hsize(a6),d1 X move.l d1,d0 X _NewPtr X bne @memer1 X move.l a0,chtab X add.l d1,d1 X move.l d1,d0 X _NewPtr X bne @memer2 X move.l a0,lasttab X move.l d1,d0 X _NewPtr X bne @memer3 X move.l a0,codetab X clr.l ratio(a6) X moveq #0,inpos X move.l #3,outpos(a6) X move.l #CHECK_DIST,checkpos(a6) X move.w #9,codesz(a6) X move.l #$200,codelim(a6) X move.l #257,ncodes X tst.l hisregsz+8(sp) ;block_compress X if# eq then.s X subq.l #1,ncodes X move.l #-1,checkpos(a6) X endif# X move.l codetab,a0 X moveq #0,d0 X move.l hsize(a6),d1 X lsr.l #1,d1 X bra.s *+4 X move.l d0,(a0)+ X dbf d1,*-2 X move.w d0,(a0) X move.w #8,cd_cnt(a6) X lea cd_buf+16(a6),codeptr X X move.l a6,d0 X bsr filret X move.l d0,lastcode X bmi @done X addq.l #1,inpos X X@loop getchar ch,@done X move.l ch,h X move.w hshift(a6),d0 X lsl.w d0,h X eor.w lastcode,h X move.l h,h2 X add.l h2,h2 X move.w 0(codetab,h2.l),d0 X if# ne then.s X if# ch eq.b 0(chtab,h.l) then.s X if# lastcode eq.w 0(lasttab,h2.l) then.s X move.w d0,lastcode X bra.s @loop X endif# X endif# X moveq #1,d1 X tst.l h X if# ne then.s X move.l hsize(a6),d1 X sub.l h,d1 X endif# X@search sub.l d1,h X if# mi then.s X add.l hsize(a6),h X endif# X move.l h,h2 X add.l h2,h2 X move.w 0(codetab,h2.l),d0 X if# ne then.s X if# ch eq.b 0(chtab,h.l) then.s X if# lastcode eq.w 0(lasttab,h2.l) then.s X move.w d0,lastcode X bra.s @loop X endif# X endif# X ;;This imitates what looks to me like bug in unix compress, X ;;just to stay exactly compatible... X tst.b 0(chtab,h.l) X bne.s @search X tst.w 0(lasttab,h2.l) X bne.s @search X endif# X endif# X writecode lastcode X if# ncodes eq.l codelim(a6) then.s X bsr write8codes X addq.w #1,cd_cnt(a6) X addq.w #1,codesz(a6) X move.l codelim(a6),d0 X add.l d0,d0 X if# d0 eq.l maxcodelim(a6) then.s X addq.l #1,d0 X endif# X move.l d0,codelim(a6) X endif# X if# ncodes lt.l maxcodelim(a6) then.s X move.w ncodes,0(codetab,h2.l) X move.b ch,0(chtab,h.l) X move.w lastcode,0(lasttab,h2.l) X addq.l #1,ncodes X else#.s X if# inpos cc.l checkpos(a6) then.s X move.l inpos,d0 X add.l #CHECK_DIST,d0 X move.l d0,checkpos(a6) X move.l inpos,d1 X moveq #8,d2 X sub.w cd_cnt(a6),d2 X mulu codesz(a6),d2 X lsr.w #3,d2 X add.l outpos(a6),d2 X bsr ScaledQuo X if# d0 hi.l ratio(a6) then.s X move.l d0,ratio(a6) X else#.s X writecode #256 X bsr write8codes X addq.w #1,cd_cnt(a6) X clr.l ratio(a6) X move.l codetab,a0 X moveq #0,d0 X move.l hsize(a6),d1 X lsr.l #1,d1 X bra.s *+4 X move.l d0,(a0)+ X dbf d1,*-2 X move.w d0,(a0) X move.l #257,ncodes X move.w #9,codesz(a6) X move.l #$200,codelim(a6) X endif# X endif# X endif# X move.l ch,lastcode X bra @loop X X@done writecode lastcode X bsr forcebuf X move.l codetab,a0 X _DisposPtr X@memer3 move.w MemErr,-(sp) X move.l lasttab,a0 X _DisposPtr X move.w (sp)+,MemErr X@memer2 move.w MemErr,-(sp) X move.l chtab,a0 X _DisposPtr X move.w (sp)+,MemErr X@memer1 move.l wr_error(a6),-(sp) X move.w MemErr,-(sp) X move.l a6,a0 X _DisposPtr X move.w (sp)+,MemErr X move.l (sp)+,d0 X movem.l (sp)+,hisregs X rts X Xhsizes: X dc.l 887 ;9 X dc.l 1559 ;10 X dc.l 2801 ;11 X dc.l 5003 ;12 X dc.l 9001 ;13 X dc.l 18013 ;14 X dc.l 35023 ;15 X dc.l 69001 ;16 X X;256*(D1/D2) -> D0 XScaledQuo: X if# d1 ls.l #$FFFFFF then.s X lsl.l #8,d1 X else#.s X lsr.l #8,d2 X if# eq then.s X moveq #-1,d0 X rts X endif# X endif# X if# d2 ls.l #$FFFF then.s X swap d1 X moveq #0,d0 X move.w d1,d0 X divu d2,d0 X swap d0 X move.w d0,d1 X swap d1 X divu d2,d1 X move.w d1,d0 X rts X endif# X moveq #0,d0 X move.w d1,d0 X swap d0 X clr.w d1 X swap d1 X move.l d2,a0 X moveq #16-1,d2 X@next add.l d0,d0 X addx.l d1,d1 X if# a0 ls.l d1 then.s X sub.l a0,d1 X addq.w #1,d0 X endif# X dbf d2,@next X rts X Xforcebuf: ;clobbers codeptr(=a1) and ncodes X move.w cd_cnt(a6),ncodes X cmp.w #8,ncodes X if# ne then.s X subq.w #1,cd_cnt(a6) X if# pl then.s X clr.w -(codeptr) X endif# X bsr.s write8codes X mulu codesz(a6),ncodes ;Correction for really < 8 codes... X lsr.w #3,ncodes X sub.l ncodes,outpos(a6) X add.w ncodes,wr_cnt(a6) X sub.l ncodes,wr_ptr(a6) X endif# X tst.l wr_error(a6) X if# pl then.s X pea wr_buf(a6) X move.l wr_ptr(a6),d0 X sub.l (sp),d0 X move.l d0,-(sp) X move.l wr_param(a6),-(sp) X move.l wr_fn(a6),a0 X jsr (a0) X lea 12(sp),sp X move.l d0,wr_error(a6) X endif# X rts X X;assumes codeptr = a1 Xwrite8codes: X movem.l d2-d4,-(sp) X@rewr moveq #0,d3 X move.w codesz(a6),d3 X move.l wr_ptr(a6),a0 X add.l d3,wr_ptr(a6) X sub.w d3,wr_cnt(a6) X if# mi then.s X add.w wr_cnt(a6),d3 X pea wr_buf(a6) X move.l (sp),wr_ptr(a6) X lea BUFSIZE,a0 X move.w a0,wr_cnt(a6) X sub.w d3,a0 X move.l a0,-(sp) X move.l wr_param(a6),-(sp) X tst.l wr_error(a6) X if# pl then.s X move.l wr_fn(a6),a0 X jsr (a0) X move.l d0,wr_error(a6) X endif# X lea 12(sp),sp X bra.s @rewr X endif# X add.l d3,outpos(a6) X moveq #0,d1 ;d1 = leftover byte X moveq #0,d2 ;d2 = # bits in this byte X subq.w #8,d3 ;d3 = codesz - 8 X moveq #8-1,d4 ;d4 = count X lea cd_buf+16(a6),codeptr X@loop moveq #0,d0 X move.w -(codeptr),d0 X lsl.l d2,d0 X or.b d1,d0 X add.w d3,d2 X subq.w #8,d2 X if# mi then.s X addq.w #8,d2 X move.w d0,(codeptr)+ X move.b -(codeptr),(a0)+ X move.b -(codeptr),d1 X else#.s X move.l d0,(codeptr)+ X move.b -(codeptr),(a0)+ X move.b -(codeptr),(a0)+ X move.b -(codeptr),d1 X subq #1,codeptr X endif# X dbf d4,@loop X lea cd_buf+16(a6),codeptr X move.w #8-1,cd_cnt(a6) X movem.l (sp)+,d2-d4 X rts X X;compwrite(cstream, size, buf) X export compwrite Xcompwrite: X movem.l hisregs,-(sp) X move.l hisregsz+4(sp),a6 ;cstream X movem.l savedregs(a6),myregs X move.l a0,-(sp) X move.l wr_error(a6),d0 X bmi.s filret X move.l hisregsz+4+12(sp),a0 ;buf X move.l hisregsz+4+8(sp),d0 ;size X subq.l #1,d0 X blt.s filbuf X move.l d0,rd_cnt(a6) X moveq #0,d0 X move.b (a0)+,d0 X move.l a0,rd_ptr(a6) X rts Xfilbuf move.l wr_error(a6),d0 Xfilret move.l (sp)+,a0 X movem.l myregs,savedregs(a6) X movem.l (sp)+,hisregs X rts X X;compclose(cstream) X export compclose Xcompclose: X move.l 4(sp),d0 X if# eq then.s X rts X endif# X movem.l hisregs,-(sp) X move.l d0,a6 X movem.l savedregs(a6),myregs X moveq #-1,d0 X jmp (a0) X X endwith X endproc X Xuncompress proc X XBUFSIZE equ 512 X XSTRSIZE equ 8000 X Xlastchar equ d2 Xlastcode equ d3 Xncodes equ d4 Xcodelim equ d5 Xcodesz equ d6 Xreadcnt equ d7 Xcodeptr equ a1 Xstrptr equ a2 Xchartab equ a3 Xcodetab equ a4 X Xmyregs reg d1-d7/a0-a4 Xmyregsz equ 48 Xhisregs reg d2-d7/a2-a4/a6 Xhisregsz equ 40 X Xfprec record 0 Xcodebuf ds.w 9 Xstrend ds.l 1 Xmaxcodelim ds.l 1 Xrd_param ds.l 1 Xrd_fn ds.l 1 Xrd_ptr ds.l 1 Xrd_cnt ds.w 1 Xrd_error ds.l 1 Xwr_cnt ds.l 1 Xwr_ptr ds.l 1 Xtempbuf ds.b 16 Xsavedregs ds.b myregsz Xrd_buf ds.b BUFSIZE Xfprecsz equ * X endr X X with fprec X X macro X readcode.&sz &dreg,&eoflab X sub.w codesz,readcnt X if# mi then.s X bsr.&default(&sz,'w') read8codes X bmi.&default(&sz,'w') &eoflab X endif# X moveq #0,&dreg X move.w -(codeptr),&dreg X endm X X macro X putchar X subq.l #1,wr_cnt(a6) X if# ge then.s X move.l wr_ptr(a6),a0 X move.b d1,(a0)+ X move.l a0,wr_ptr(a6) X else#.s X bsr flsbuf X endif# X endm X X X;uncompinit (maxbits, block_compress, inputfn, param) X export uncompinit Xuncompinit X move.l #fprecsz,d0 X _NewPtr X if# ne then.s X moveq #0,d0 X rts X endif# X movem.l hisregs,-(sp) X move.l a0,a6 X move.l hisregsz+16(sp),rd_param(a6) X move.l hisregsz+12(sp),rd_fn(a6) X clr.w rd_cnt(a6) X move.l #1,rd_error(a6) X move.l hisregsz+4(sp),d0 ;maxbits X moveq #9,d1 X if# d0 lt.l d1 then.s X move.l d1,d0 X endif# X moveq #16,d1 X if# d0 gt.l d1 then.s X move.l d1,d0 X endif# X moveq #1,d1 X lsl.l d0,d1 X move.l d1,maxcodelim(a6) X sub.l #256,d1 X move.l d1,d0 X _NewPtr X bne memer1 X lea -256(a0),chartab X move.l d1,d0 X add.l d0,d0 X _NewPtr X bne memer2 X lea -512(a0),codetab X move.l #STRSIZE,d0 X _NewPtr X bne memer3 X lea STRSIZE(a0),strptr X move.l strptr,strend(a6) X X moveq #9,codesz X move.l #$200,codelim X moveq #0,readcnt X X move.l #256,ncodes X tst.l hisregsz+8(sp) ;block_compress X if# ne then.s X addq.l #1,ncodes X bset #31,readcnt ;use high word for flag... X endif# X X move.l a6,d0 X moveq #-1,d1 X bsr flsret ;Init wr_cnt and wr_ptr. X X readcode lastcode,@done X move.b lastcode,lastchar X X move.l lastcode,d1 X putchar X X@loop readcode d0,@done X if# d0 eq.w #256 then.s X tst.l readcnt X if# mi then.s X move.l d0,ncodes X moveq #9,codesz X move.l #$200,codelim X clr.w readcnt X readcode.s d0,@done X endif# X endif# X move.l d0,d1 X if# d0 cc.l ncodes then.s X move.b lastchar,-(strptr) X move.l lastcode,d0 X endif# X move.l d0,lastchar X bra.s @get X@getlp move.l lastchar,d0 X move.b 0(chartab,d0.l),-(strptr) X add.l d0,d0 X move.w 0(codetab,d0.l),lastchar X@get cmp.w #256,lastchar X bcc.s @getlp X X if# ncodes lt.l maxcodelim(a6) then.s X move.l ncodes,d0 X move.b lastchar,0(chartab,d0.l) X add.l d0,d0 X move.w lastcode,0(codetab,d0.l) X addq.l #1,ncodes X endif# X move.l d1,lastcode X if# ncodes eq.l codelim then.s X addq.w #1,codesz X add.l codelim,codelim X if# codelim eq.l maxcodelim(a6) then.s X addq.l #1,codelim ;make it so this never triggers again X endif# X clr.w readcnt X endif# X move.b lastchar,d1 X bra.s @put X@putlp move.b (strptr)+,d1 X@put putchar X cmp.l strend(a6),strptr X bne.s @putlp X bra @loop X X@done bsr flush X _debugger ;Shouldn't return X X;Read 8 codes into codebuf X;Input: codesz X;Output: readcnt, codeptr or MI flag set if end of file. Xread8codes: X movem.l d2-d5,-(sp) X move.l rd_ptr(a6),a0 X move.l codesz,d0 X sub.w d0,rd_cnt(a6) X if# lt then.s X bsr.s fillbuf X else#.s X add.l d0,rd_ptr(a6) X endif# X lsl.w #3,d0 X sub.w codesz,d0 X bmi.s @ret X move.w d0,readcnt X moveq #1,d2 ;d2 = mask X lsl.w codesz,d2 X subq.w #1,d2 X move.w codesz,d3 ;d3 = codesz - 8 X subq.w #8,d3 X lea codebuf+18(a6),codeptr X move.w codesz,d4 ;d4 = byte count X moveq #0,d5 ;d5 = # used bits in this byte X@loop move.w d5,d1 ;save bit count X add.w d3,d5 X move.b (a0)+,-(codeptr) X subq #1,d4 X subq.w #8,d5 X if# lt then.s X addq.w #8,d5 X move.b (a0),-(codeptr) X move.w (codeptr)+,d0 X lsr.w d1,d0 X and.w d2,d0 X move.w d0,-(codeptr) X bra.s @loop X endif# X move.b (a0)+,-(codeptr) X move.b (a0),-(codeptr) X subq #1,codeptr X move.l (codeptr)+,d0 X lsr.l d1,d0 X and.w d2,d0 X move.w d0,-(codeptr) X subq #1,d4 X bne.s @loop X lea codebuf+18(a6),codeptr X@ret movem.l (sp)+,d2-d5 X rts X Xfillbuf: X lea tempbuf(a6),codeptr ;handy areg.... X move.w rd_cnt(a6),d1 X add.w d1,d0 X bra.s @more X move.b (a0)+,(codeptr)+ X@more dbf d0,*-2 X move.l rd_error(a6),d0 X if# gt then.s X movem.l d1/a1,-(sp) X pea rd_buf(a6) X pea BUFSIZE X move.l rd_param(a6),-(sp) X move.l rd_fn(a6),a0 X jsr (a0) X lea 12(sp),sp X movem.l (sp)+,d1/a1 X move.l d0,rd_error(a6) X endif# X if# gt then.s X lea rd_buf(a6),a0 X add.w d0,d1 X bmi.s @more X sub.w d1,d0 X bra.s *+4 X move.b (a0)+,(codeptr)+ X dbf d0,*-2 X move.w d1,rd_cnt(a6) X move.l a0,rd_ptr(a6) X else#.s X clr.w rd_cnt(a6) X endif# X move.l codeptr,d0 X lea tempbuf(a6),a0 X sub.l a0,d0 X rts X X;uncompread(cstream, size, buf) X export uncompread Xuncompread: X movem.l hisregs,-(sp) X move.l hisregsz+4(sp),a6 ;cstream X movem.l savedregs(a6),myregs X move.l a0,-(sp) X move.l hisregsz+4+12(sp),a0 ;buf X move.l hisregsz+4+8(sp),d0 ;size X tst.l d1 ;we doing flush or flsbuf? X if# mi then.s X tst.l rd_error(a6) X ble.s flseof X else#.s X subq.l #1,d0 X blt.s flsbuf X move.b d1,(a0)+ X endif# X move.l a0,wr_ptr(a6) X move.l d0,wr_cnt(a6) X rts Xflsbuf: move.l hisregsz+4+8(sp),d0 ;size Xflsret: move.l (sp)+,a0 X movem.l myregs,savedregs(a6) X movem.l (sp)+,hisregs X rts X Xflush moveq #-1,d1 X move.l hisregsz+4+8(sp),d0 X sub.l wr_cnt(a6),d0 X bne.s flsret Xflseof: move.l rd_error(a6),d0 X bra.s flsret X X;uncompclose(cstream) X export uncompclose Xuncompclose: X move.l 4(sp),d0 X if# eq then.s X rts X endif# X movem.l hisregs,-(sp) X move.l d0,a6 X movem.l savedregs(a6),myregs X move.l strend(a6),a0 X lea -STRSIZE(a0),a0 X _DisposPtr Xmemer3 move.w MemErr,-(sp) X lea 512(codetab),a0 X _DisposPtr X move.w (sp)+,MemErr Xmemer2 move.w MemErr,-(sp) X lea 256(chartab),a0 X _DisposPtr X move.w (sp)+,MemErr Xmemer1 move.w MemErr,-(sp) X move.l a6,a0 X _DisposPtr X move.w (sp)+,MemErr X moveq #0,d0 X movem.l (sp)+,hisregs X rts X endwith X endproc X X X end SHAR_EOF if test 19133 -ne "`wc -c < 'compstream.a'`" then echo shar: error transmitting "'compstream.a'" '(should have been 19133 characters)' fi fi echo Done exit 0 -- gz@entity.com ...!mit-eddie!spt!gz Unix: when you can't afford the very best.