137da2899SCharles.Forsyth# gzip-compatible decompression filter. 237da2899SCharles.Forsyth 337da2899SCharles.Forsythimplement Filter; 437da2899SCharles.Forsyth 537da2899SCharles.Forsythinclude "sys.m"; 637da2899SCharles.Forsyth sys: Sys; 737da2899SCharles.Forsythinclude "filter.m"; 837da2899SCharles.Forsyth 937da2899SCharles.ForsythGZMAGIC1: con byte 16r1f; 1037da2899SCharles.ForsythGZMAGIC2: con byte 16r8b; 1137da2899SCharles.Forsyth 1237da2899SCharles.ForsythGZDEFLATE: con byte 8; 1337da2899SCharles.Forsyth 1437da2899SCharles.ForsythGZFTEXT: con 1 << 0; # file is text 1537da2899SCharles.ForsythGZFHCRC: con 1 << 1; # crc of header included 1637da2899SCharles.ForsythGZFEXTRA: con 1 << 2; # extra header included 1737da2899SCharles.ForsythGZFNAME: con 1 << 3; # name of file included 1837da2899SCharles.ForsythGZFCOMMENT: con 1 << 4; # header comment included 1937da2899SCharles.ForsythGZFMASK: con (1 << 5) - 1; # mask of specified bits 2037da2899SCharles.Forsyth 2137da2899SCharles.ForsythGZXBEST: con byte 2; # used maximum compression algorithm 2237da2899SCharles.ForsythGZXFAST: con byte 4; # used fast algorithm little compression 2337da2899SCharles.Forsyth 2437da2899SCharles.ForsythGZOSFAT: con byte 0; # FAT file system 2537da2899SCharles.ForsythGZOSAMIGA: con byte 1; # Amiga 2637da2899SCharles.ForsythGZOSVMS: con byte 2; # VMS or OpenVMS 2737da2899SCharles.ForsythGZOSUNIX: con byte 3; # Unix 2837da2899SCharles.ForsythGZOSVMCMS: con byte 4; # VM/CMS 2937da2899SCharles.ForsythGZOSATARI: con byte 5; # Atari TOS 3037da2899SCharles.ForsythGZOSHPFS: con byte 6; # HPFS file system 3137da2899SCharles.ForsythGZOSMAC: con byte 7; # Macintosh 3237da2899SCharles.ForsythGZOSZSYS: con byte 8; # Z-System 3337da2899SCharles.ForsythGZOSCPM: con byte 9; # CP/M 3437da2899SCharles.ForsythGZOSTOPS20: con byte 10; # TOPS-20 3537da2899SCharles.ForsythGZOSNTFS: con byte 11; # NTFS file system 3637da2899SCharles.ForsythGZOSQDOS: con byte 12; # QDOS 3737da2899SCharles.ForsythGZOSACORN: con byte 13; # Acorn RISCOS 3837da2899SCharles.ForsythGZOSUNK: con byte 255; 3937da2899SCharles.Forsyth 4037da2899SCharles.ForsythGZCRCPOLY: con int 16redb88320; 4137da2899SCharles.ForsythGZOSINFERNO: con GZOSUNIX; 4237da2899SCharles.Forsyth 4337da2899SCharles.Forsyth# huffman code table 4437da2899SCharles.ForsythHuff: adt 4537da2899SCharles.Forsyth{ 4637da2899SCharles.Forsyth bits: int; # length of the code 4737da2899SCharles.Forsyth encode: int; # the code 4837da2899SCharles.Forsyth}; 4937da2899SCharles.Forsyth 5037da2899SCharles.Forsyth# huffman decode table 5137da2899SCharles.ForsythDeHuff: adt 5237da2899SCharles.Forsyth{ 5337da2899SCharles.Forsyth l1: array of L1; # the table 5437da2899SCharles.Forsyth nb1: int; # no. of bits in first level 5537da2899SCharles.Forsyth nb2: int; # no. of bits in second level 5637da2899SCharles.Forsyth}; 5737da2899SCharles.Forsyth 5837da2899SCharles.Forsyth# first level of decode table 5937da2899SCharles.ForsythL1: adt 6037da2899SCharles.Forsyth{ 6137da2899SCharles.Forsyth bits: int; # length of the code 6237da2899SCharles.Forsyth decode: int; # the symbol 6337da2899SCharles.Forsyth l2: array of L2; 6437da2899SCharles.Forsyth}; 6537da2899SCharles.Forsyth 6637da2899SCharles.Forsyth# second level 6737da2899SCharles.ForsythL2: adt 6837da2899SCharles.Forsyth{ 6937da2899SCharles.Forsyth bits: int; # length of the code 7037da2899SCharles.Forsyth decode: int; # the symbol 7137da2899SCharles.Forsyth}; 7237da2899SCharles.Forsyth 7337da2899SCharles.ForsythDeflateUnc: con 0; # uncompressed block 7437da2899SCharles.ForsythDeflateFix: con 1; # fixed huffman codes 7537da2899SCharles.ForsythDeflateDyn: con 2; # dynamic huffman codes 7637da2899SCharles.ForsythDeflateErr: con 3; # reserved BTYPE (error) 7737da2899SCharles.Forsyth 7837da2899SCharles.ForsythDeflateEob: con 256; # end of block code in lit/len book 7937da2899SCharles.Forsyth 8037da2899SCharles.ForsythLenStart: con 257; # start of length codes in litlen 8137da2899SCharles.ForsythLenEnd: con 285; # greatest valid length code 8237da2899SCharles.ForsythNlitlen: con 288; # number of litlen codes 8337da2899SCharles.ForsythNoff: con 30; # number of offset codes 8437da2899SCharles.ForsythNclen: con 19; # number of codelen codes 8537da2899SCharles.Forsyth 8637da2899SCharles.ForsythMaxHuffBits: con 15; # max bits in a huffman code 8737da2899SCharles.ForsythRunlenBits: con 7; # max bits in a run-length huffman code 8837da2899SCharles.ForsythMaxOff: con 32*1024; # max lempel-ziv distance 8937da2899SCharles.Forsyth 9037da2899SCharles.ForsythBlocksize: con 32 * 1024; 9137da2899SCharles.Forsyth 9237da2899SCharles.Forsyth# tables from RFC 1951, section 3.2.5 9337da2899SCharles.Forsythlitlenbase := array[Noff] of 9437da2899SCharles.Forsyth{ 9537da2899SCharles.Forsyth 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 9637da2899SCharles.Forsyth 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 9737da2899SCharles.Forsyth 67, 83, 99, 115, 131, 163, 195, 227, 258 9837da2899SCharles.Forsyth}; 9937da2899SCharles.Forsyth 10037da2899SCharles.Forsythlitlenextra := array[Noff] of 10137da2899SCharles.Forsyth{ 10237da2899SCharles.Forsyth 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 10337da2899SCharles.Forsyth 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 10437da2899SCharles.Forsyth 5, 5, 5, 5, 0 10537da2899SCharles.Forsyth}; 10637da2899SCharles.Forsyth 10737da2899SCharles.Forsythoffbase := array[Noff] of 10837da2899SCharles.Forsyth{ 10937da2899SCharles.Forsyth 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 11037da2899SCharles.Forsyth 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 11137da2899SCharles.Forsyth 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 11237da2899SCharles.Forsyth}; 11337da2899SCharles.Forsyth 11437da2899SCharles.Forsythoffextra := array[Noff] of 11537da2899SCharles.Forsyth{ 11637da2899SCharles.Forsyth 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 11737da2899SCharles.Forsyth 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 11837da2899SCharles.Forsyth 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 11937da2899SCharles.Forsyth}; 12037da2899SCharles.Forsyth 12137da2899SCharles.Forsyth# order of run-length codes 12237da2899SCharles.Forsythclenorder := array[Nclen] of 12337da2899SCharles.Forsyth{ 12437da2899SCharles.Forsyth 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 12537da2899SCharles.Forsyth}; 12637da2899SCharles.Forsyth 12737da2899SCharles.Forsyth# fixed huffman tables 12837da2899SCharles.Forsythlitlentab: array of Huff; 12937da2899SCharles.Forsythofftab: array of Huff; 13037da2899SCharles.Forsyth 13137da2899SCharles.Forsyth# their decoding table counterparts 13237da2899SCharles.Forsythlitlendec: ref DeHuff; 13337da2899SCharles.Forsythoffdec: ref DeHuff; 13437da2899SCharles.Forsyth 13537da2899SCharles.Forsythrevtab: array of byte; # bit reversal for endian swap of huffman codes 13637da2899SCharles.Forsythmask: array of int; # for masking low-order n bits of an int 13737da2899SCharles.Forsyth 138*ce02cfb2SCharles.ForsythHnone, Hgzip, Hzlib: con iota; # State.headers 13937da2899SCharles.ForsythState: adt { 14037da2899SCharles.Forsyth ibuf, obuf: array of byte; 14137da2899SCharles.Forsyth c: chan of ref Rq; 14237da2899SCharles.Forsyth rc: chan of int; 14337da2899SCharles.Forsyth in: int; # next byte to consume from input buffer 14437da2899SCharles.Forsyth ein: int; # valid bytes in input buffer 14537da2899SCharles.Forsyth out: int; # valid bytes in output buffer 14637da2899SCharles.Forsyth hist: array of byte; # history buffer for lempel-ziv backward references 14737da2899SCharles.Forsyth usehist: int; # == 1 if 'hist' is valid 14837da2899SCharles.Forsyth crctab: array of int; 149*ce02cfb2SCharles.Forsyth crc, tot: int; # for gzip trailer 150*ce02cfb2SCharles.Forsyth sum: big; # for zlib trailer 15137da2899SCharles.Forsyth 15237da2899SCharles.Forsyth reg: int; # 24-bit shift register 15337da2899SCharles.Forsyth nbits: int; # number of valid bits in reg 15437da2899SCharles.Forsyth svreg: int; # save reg for efficient ungets 15537da2899SCharles.Forsyth svn: int; # number of bits gotten in last call to getn() 15637da2899SCharles.Forsyth # reg bits are consumed from right to left 15737da2899SCharles.Forsyth # so low-order byte of reg came first in the input stream 15837da2899SCharles.Forsyth headers: int; 15937da2899SCharles.Forsyth}; 16037da2899SCharles.Forsyth 16137da2899SCharles.Forsyth 16237da2899SCharles.Forsythinit() 16337da2899SCharles.Forsyth{ 16437da2899SCharles.Forsyth sys = load Sys Sys->PATH; 16537da2899SCharles.Forsyth 16637da2899SCharles.Forsyth # byte reverse table 16737da2899SCharles.Forsyth revtab = array[256] of byte; 16837da2899SCharles.Forsyth for(i := 0; i < 256; i++){ 16937da2899SCharles.Forsyth revtab[i] = byte 0; 17037da2899SCharles.Forsyth for(j := 0; j < 8; j++) { 17137da2899SCharles.Forsyth if(i & (1 << j)) 17237da2899SCharles.Forsyth revtab[i] |= byte 16r80 >> j; 17337da2899SCharles.Forsyth } 17437da2899SCharles.Forsyth } 17537da2899SCharles.Forsyth 17637da2899SCharles.Forsyth # bit-masking table 17737da2899SCharles.Forsyth mask = array[MaxHuffBits+1] of int; 17837da2899SCharles.Forsyth for(i = 0; i <= MaxHuffBits; i++) 17937da2899SCharles.Forsyth mask[i] = (1 << i) - 1; 18037da2899SCharles.Forsyth 18137da2899SCharles.Forsyth litlentab = array[Nlitlen] of Huff; 18237da2899SCharles.Forsyth 18337da2899SCharles.Forsyth # static litlen bit lengths 18437da2899SCharles.Forsyth for(i = 0; i < 144; i++) 18537da2899SCharles.Forsyth litlentab[i].bits = 8; 18637da2899SCharles.Forsyth for(i = 144; i < 256; i++) 18737da2899SCharles.Forsyth litlentab[i].bits = 9; 18837da2899SCharles.Forsyth for(i = 256; i < 280; i++) 18937da2899SCharles.Forsyth litlentab[i].bits = 7; 19037da2899SCharles.Forsyth for(i = 280; i < Nlitlen; i++) 19137da2899SCharles.Forsyth litlentab[i].bits = 8; 19237da2899SCharles.Forsyth 19337da2899SCharles.Forsyth bitcount := array[MaxHuffBits+1] of { * => 0 }; 19437da2899SCharles.Forsyth bitcount[8] += 144 - 0; 19537da2899SCharles.Forsyth bitcount[9] += 256 - 144; 19637da2899SCharles.Forsyth bitcount[7] += 280 - 256; 19737da2899SCharles.Forsyth bitcount[8] += Nlitlen - 280; 19837da2899SCharles.Forsyth 19937da2899SCharles.Forsyth hufftabinit(litlentab, Nlitlen, bitcount, 9); 20037da2899SCharles.Forsyth litlendec = decodeinit(litlentab, Nlitlen, 9, 0); 20137da2899SCharles.Forsyth 20237da2899SCharles.Forsyth offtab = array[Noff] of Huff; 20337da2899SCharles.Forsyth 20437da2899SCharles.Forsyth # static offset bit lengths 20537da2899SCharles.Forsyth for(i = 0; i < Noff; i++) 20637da2899SCharles.Forsyth offtab[i].bits = 5; 20737da2899SCharles.Forsyth 20837da2899SCharles.Forsyth for(i = 0; i < 5; i++) 20937da2899SCharles.Forsyth bitcount[i] = 0; 21037da2899SCharles.Forsyth bitcount[5] = Noff; 21137da2899SCharles.Forsyth 21237da2899SCharles.Forsyth hufftabinit(offtab, Noff, bitcount, 5); 21337da2899SCharles.Forsyth offdec = decodeinit(offtab, Noff, 5, 0); 21437da2899SCharles.Forsyth} 21537da2899SCharles.Forsyth 21637da2899SCharles.Forsythstart(params: string): chan of ref Rq 21737da2899SCharles.Forsyth{ 21837da2899SCharles.Forsyth s := ref State; 21937da2899SCharles.Forsyth s.c = chan of ref Rq; 22037da2899SCharles.Forsyth s.rc = chan of int; 22137da2899SCharles.Forsyth s.ibuf = array[Blocksize] of byte; 22237da2899SCharles.Forsyth s.obuf = array[Blocksize] of byte; 22337da2899SCharles.Forsyth s.in = 0; 22437da2899SCharles.Forsyth s.ein = 0; 22537da2899SCharles.Forsyth s.out = 0; 22637da2899SCharles.Forsyth s.usehist = 0; 22737da2899SCharles.Forsyth s.reg = 0; 22837da2899SCharles.Forsyth s.nbits = 0; 22937da2899SCharles.Forsyth s.crc = 0; 23037da2899SCharles.Forsyth s.tot = 0; 231*ce02cfb2SCharles.Forsyth s.sum = big 1; 23237da2899SCharles.Forsyth s.hist = array[Blocksize] of byte; 233*ce02cfb2SCharles.Forsyth s.headers = Hnone; 234*ce02cfb2SCharles.Forsyth if(params != nil) { 235*ce02cfb2SCharles.Forsyth if(params[0] == 'h') 236*ce02cfb2SCharles.Forsyth s.headers = Hgzip; 237*ce02cfb2SCharles.Forsyth if(params[0] == 'z') 238*ce02cfb2SCharles.Forsyth s.headers = Hzlib; 239*ce02cfb2SCharles.Forsyth } 240*ce02cfb2SCharles.Forsyth if (s.headers == Hgzip) 24137da2899SCharles.Forsyth s.crctab = mkcrctab(GZCRCPOLY); 24237da2899SCharles.Forsyth spawn inflate(s); 24337da2899SCharles.Forsyth return s.c; 24437da2899SCharles.Forsyth} 24537da2899SCharles.Forsyth 24637da2899SCharles.Forsythinflate(s: ref State) 24737da2899SCharles.Forsyth{ 24837da2899SCharles.Forsyth s.c <-= ref Rq.Start(sys->pctl(0, nil)); 24937da2899SCharles.Forsyth header(s); 25037da2899SCharles.Forsyth 25137da2899SCharles.Forsyth for(;;) { 25237da2899SCharles.Forsyth bfinal := getn(s, 1, 0); 25337da2899SCharles.Forsyth btype := getn(s, 2, 0); 25437da2899SCharles.Forsyth case(btype) { 25537da2899SCharles.Forsyth DeflateUnc => 25637da2899SCharles.Forsyth flushbits(s); 25737da2899SCharles.Forsyth unclen := getb(s); 25837da2899SCharles.Forsyth unclen |= getb(s) << 8; 25937da2899SCharles.Forsyth nlen := getb(s); 26037da2899SCharles.Forsyth nlen |= getb(s) << 8; 26137da2899SCharles.Forsyth if(unclen != (~nlen & 16rFFFF)) 26237da2899SCharles.Forsyth fatal(s, "corrupted data"); 26337da2899SCharles.Forsyth for(; unclen > 0; unclen--) { 26437da2899SCharles.Forsyth # inline putb(s, getb(s)); 26537da2899SCharles.Forsyth b := byte getb(s); 26637da2899SCharles.Forsyth if(s.out >= MaxOff) 26737da2899SCharles.Forsyth flushout(s); 26837da2899SCharles.Forsyth s.obuf[s.out++] = b; 26937da2899SCharles.Forsyth } 27037da2899SCharles.Forsyth DeflateFix => 27137da2899SCharles.Forsyth decodeblock(s, litlendec, offdec); 27237da2899SCharles.Forsyth DeflateDyn => 27337da2899SCharles.Forsyth dynhuff(s); 27437da2899SCharles.Forsyth DeflateErr => 27537da2899SCharles.Forsyth fatal(s, "bad block type"); 27637da2899SCharles.Forsyth } 27737da2899SCharles.Forsyth if(bfinal) { 27837da2899SCharles.Forsyth if(s.out) { 27937da2899SCharles.Forsyth outblock(s); 28037da2899SCharles.Forsyth s.c <- = ref Rq.Result(s.obuf[0:s.out], s.rc); 28137da2899SCharles.Forsyth flag := <- s.rc; 28237da2899SCharles.Forsyth if (flag == -1) 28337da2899SCharles.Forsyth exit; 28437da2899SCharles.Forsyth } 28537da2899SCharles.Forsyth flushbits(s); 28637da2899SCharles.Forsyth footer(s); 28737da2899SCharles.Forsyth s.c <-= ref Rq.Finished(s.ibuf[s.in - s.nbits/8:s.ein]); 28837da2899SCharles.Forsyth exit; 28937da2899SCharles.Forsyth } 29037da2899SCharles.Forsyth } 29137da2899SCharles.Forsyth} 29237da2899SCharles.Forsyth 293*ce02cfb2SCharles.Forsythheadergzip(s: ref State) 29437da2899SCharles.Forsyth{ 29537da2899SCharles.Forsyth if(byte getb(s) != GZMAGIC1 || byte getb(s) != GZMAGIC2) 29637da2899SCharles.Forsyth fatal(s, "not a gzip file"); 29737da2899SCharles.Forsyth 29837da2899SCharles.Forsyth if(byte getb(s) != GZDEFLATE) 29937da2899SCharles.Forsyth fatal(s, "not compressed with deflate"); 30037da2899SCharles.Forsyth 30137da2899SCharles.Forsyth flags := getb(s); 30237da2899SCharles.Forsyth if(flags & ~GZFMASK) 30337da2899SCharles.Forsyth fatal(s, "reserved flag bits set"); 30437da2899SCharles.Forsyth 30537da2899SCharles.Forsyth # read modification time (ignored) 30637da2899SCharles.Forsyth mtime := getb(s); 30737da2899SCharles.Forsyth mtime |= (getb(s) << 8); 30837da2899SCharles.Forsyth mtime |= (getb(s) << 16); 30937da2899SCharles.Forsyth mtime |= (getb(s) << 24); 31037da2899SCharles.Forsyth s.c <-= ref Rq.Info("mtime " + string mtime); 3119b29ac7eSCharles.Forsyth getb(s); # xfl 3129b29ac7eSCharles.Forsyth getb(s); # os 31337da2899SCharles.Forsyth 31437da2899SCharles.Forsyth # skip optional "extra field" 31537da2899SCharles.Forsyth if(flags & GZFEXTRA) { 31637da2899SCharles.Forsyth skip := getb(s); 31737da2899SCharles.Forsyth skip |= getb(s) << 8; 31837da2899SCharles.Forsyth while (skip-- > 0) 31937da2899SCharles.Forsyth getb(s); 32037da2899SCharles.Forsyth } 32137da2899SCharles.Forsyth 32237da2899SCharles.Forsyth # read optional filename (ignored) 32337da2899SCharles.Forsyth file: string; 32437da2899SCharles.Forsyth if(flags & GZFNAME){ 32537da2899SCharles.Forsyth n := 0; 32637da2899SCharles.Forsyth while(c := getb(s)) 32737da2899SCharles.Forsyth file[n++] = c; 32837da2899SCharles.Forsyth s.c <-= ref Rq.Info("file " + file); 32937da2899SCharles.Forsyth } 33037da2899SCharles.Forsyth 33137da2899SCharles.Forsyth # skip optional comment 33237da2899SCharles.Forsyth if(flags & GZFCOMMENT) { 33337da2899SCharles.Forsyth while(getb(s)) 33437da2899SCharles.Forsyth ; 33537da2899SCharles.Forsyth } 33637da2899SCharles.Forsyth 33737da2899SCharles.Forsyth # skip optional CRC16 field 33837da2899SCharles.Forsyth if(flags & GZFHCRC) { 33937da2899SCharles.Forsyth getb(s); 34037da2899SCharles.Forsyth getb(s); 34137da2899SCharles.Forsyth } 34237da2899SCharles.Forsyth} 34337da2899SCharles.Forsyth 344*ce02cfb2SCharles.Forsythheaderzlib(s: ref State) 345*ce02cfb2SCharles.Forsyth{ 346*ce02cfb2SCharles.Forsyth Fdict: con 1<<5; 347*ce02cfb2SCharles.Forsyth CMshift: con 8; 348*ce02cfb2SCharles.Forsyth CMmask: con (1<<4)-1; 349*ce02cfb2SCharles.Forsyth CMdeflate: con 8; 350*ce02cfb2SCharles.Forsyth 351*ce02cfb2SCharles.Forsyth h := 0; 352*ce02cfb2SCharles.Forsyth h |= getb(s)<<8; 353*ce02cfb2SCharles.Forsyth h |= getb(s); 354*ce02cfb2SCharles.Forsyth if(h % 31 != 0) 355*ce02cfb2SCharles.Forsyth fatal(s, "invalid zlib header"); 356*ce02cfb2SCharles.Forsyth if(h&Fdict) 357*ce02cfb2SCharles.Forsyth fatal(s, "preset dictionary not supported"); 358*ce02cfb2SCharles.Forsyth if(((h>>CMshift)&CMmask) != CMdeflate) 359*ce02cfb2SCharles.Forsyth fatal(s, "zlib compression method not deflate"); 360*ce02cfb2SCharles.Forsyth} 361*ce02cfb2SCharles.Forsyth 362*ce02cfb2SCharles.Forsythheader(s: ref State) 363*ce02cfb2SCharles.Forsyth{ 364*ce02cfb2SCharles.Forsyth case s.headers { 365*ce02cfb2SCharles.Forsyth Hgzip => headergzip(s); 366*ce02cfb2SCharles.Forsyth Hzlib => headerzlib(s); 367*ce02cfb2SCharles.Forsyth } 368*ce02cfb2SCharles.Forsyth} 369*ce02cfb2SCharles.Forsyth 370*ce02cfb2SCharles.Forsythfootergzip(s: ref State) 37137da2899SCharles.Forsyth{ 37237da2899SCharles.Forsyth fcrc := getword(s); 37337da2899SCharles.Forsyth if(s.crc != fcrc) 37437da2899SCharles.Forsyth fatal(s, sys->sprint("crc mismatch: computed %ux, expected %ux", s.crc, fcrc)); 37537da2899SCharles.Forsyth ftot := getword(s); 37637da2899SCharles.Forsyth if(s.tot != ftot) 37737da2899SCharles.Forsyth fatal(s, sys->sprint("byte count mismatch: computed %d, expected %d", s.tot, ftot)); 37837da2899SCharles.Forsyth} 37937da2899SCharles.Forsyth 380*ce02cfb2SCharles.Forsythfooterzlib(s: ref State) 381*ce02cfb2SCharles.Forsyth{ 382*ce02cfb2SCharles.Forsyth sum := big 0; 383*ce02cfb2SCharles.Forsyth sum = (sum<<8)|big getb(s); 384*ce02cfb2SCharles.Forsyth sum = (sum<<8)|big getb(s); 385*ce02cfb2SCharles.Forsyth sum = (sum<<8)|big getb(s); 386*ce02cfb2SCharles.Forsyth sum = (sum<<8)|big getb(s); 387*ce02cfb2SCharles.Forsyth if(sum != s.sum) 388*ce02cfb2SCharles.Forsyth fatal(s, sys->sprint("adler32 mismatch: computed %bux, expected %bux", s.sum, sum)); 389*ce02cfb2SCharles.Forsyth} 390*ce02cfb2SCharles.Forsyth 391*ce02cfb2SCharles.Forsythfooter(s: ref State) 392*ce02cfb2SCharles.Forsyth{ 393*ce02cfb2SCharles.Forsyth case s.headers { 394*ce02cfb2SCharles.Forsyth Hgzip => footergzip(s); 395*ce02cfb2SCharles.Forsyth Hzlib => footerzlib(s); 396*ce02cfb2SCharles.Forsyth } 397*ce02cfb2SCharles.Forsyth} 398*ce02cfb2SCharles.Forsyth 39937da2899SCharles.Forsythgetword(s: ref State): int 40037da2899SCharles.Forsyth{ 40137da2899SCharles.Forsyth n := 0; 40237da2899SCharles.Forsyth for(i := 0; i < 4; i++) 40337da2899SCharles.Forsyth n |= getb(s) << (8 * i); 40437da2899SCharles.Forsyth return n; 40537da2899SCharles.Forsyth} 40637da2899SCharles.Forsyth 40737da2899SCharles.Forsyth# 40837da2899SCharles.Forsyth# uncompress a block using given huffman decoding tables 40937da2899SCharles.Forsyth# 41037da2899SCharles.Forsythdecodeblock(s: ref State, litlendec, offdec: ref DeHuff) 41137da2899SCharles.Forsyth{ 41237da2899SCharles.Forsyth b: byte; 41337da2899SCharles.Forsyth 41437da2899SCharles.Forsyth for(;;) { 41537da2899SCharles.Forsyth sym := decodesym(s, litlendec); 41637da2899SCharles.Forsyth if(sym < DeflateEob) { # literal byte 41737da2899SCharles.Forsyth # inline putb(s, byte sym); 41837da2899SCharles.Forsyth b = byte sym; 41937da2899SCharles.Forsyth if(s.out >= MaxOff) 42037da2899SCharles.Forsyth flushout(s); 42137da2899SCharles.Forsyth s.obuf[s.out++] = b; 42237da2899SCharles.Forsyth } else if(sym == DeflateEob) { # End-of-block 42337da2899SCharles.Forsyth break; 42437da2899SCharles.Forsyth } else { # lempel-ziv <length, distance> 42537da2899SCharles.Forsyth if(sym > LenEnd) 42637da2899SCharles.Forsyth fatal(s, "symbol too long"); 42737da2899SCharles.Forsyth xbits := litlenextra[sym - LenStart]; 42837da2899SCharles.Forsyth xtra := 0; 42937da2899SCharles.Forsyth if(xbits) 43037da2899SCharles.Forsyth xtra = getn(s, xbits, 0); 43137da2899SCharles.Forsyth length := litlenbase[sym - LenStart] + xtra; 43237da2899SCharles.Forsyth 43337da2899SCharles.Forsyth sym = decodesym(s, offdec); 43437da2899SCharles.Forsyth if(sym >= Noff) 43537da2899SCharles.Forsyth fatal(s, "symbol too long"); 43637da2899SCharles.Forsyth xbits = offextra[sym]; 43737da2899SCharles.Forsyth if(xbits) 43837da2899SCharles.Forsyth xtra = getn(s, xbits, 0); 43937da2899SCharles.Forsyth else 44037da2899SCharles.Forsyth xtra = 0; 44137da2899SCharles.Forsyth dist := offbase[sym] + xtra; 44237da2899SCharles.Forsyth if(dist > s.out && s.usehist == 0) 44337da2899SCharles.Forsyth fatal(s, "corrupted data"); 44437da2899SCharles.Forsyth for(i := 0; i < length; i++) { 44537da2899SCharles.Forsyth # inline putb(lzbyte(dist)); 44637da2899SCharles.Forsyth ix := s.out - dist; 44737da2899SCharles.Forsyth if(dist <= s.out) 44837da2899SCharles.Forsyth b = s.obuf[ix]; 44937da2899SCharles.Forsyth else 45037da2899SCharles.Forsyth b = s.hist[MaxOff + ix]; 45137da2899SCharles.Forsyth if(s.out >= MaxOff) 45237da2899SCharles.Forsyth flushout(s); 45337da2899SCharles.Forsyth s.obuf[s.out++] = b; 45437da2899SCharles.Forsyth } 45537da2899SCharles.Forsyth } 45637da2899SCharles.Forsyth } 45737da2899SCharles.Forsyth} 45837da2899SCharles.Forsyth 45937da2899SCharles.Forsyth# 46037da2899SCharles.Forsyth# decode next symbol in input stream using given huffman decoding table 46137da2899SCharles.Forsyth# 46237da2899SCharles.Forsythdecodesym(s: ref State, dec: ref DeHuff): int 46337da2899SCharles.Forsyth{ 46437da2899SCharles.Forsyth code, bits, n: int; 46537da2899SCharles.Forsyth 46637da2899SCharles.Forsyth l1 := dec.l1; 46737da2899SCharles.Forsyth nb1 := dec.nb1; 46837da2899SCharles.Forsyth nb2 := dec.nb2; 46937da2899SCharles.Forsyth 47037da2899SCharles.Forsyth code = getn(s, nb1, 1); 47137da2899SCharles.Forsyth l2 := l1[code].l2; 47237da2899SCharles.Forsyth if(l2 == nil) { # first level table has answer 47337da2899SCharles.Forsyth bits = l1[code].bits; 47437da2899SCharles.Forsyth if(bits == 0) 47537da2899SCharles.Forsyth fatal(s, "corrupt data"); 47637da2899SCharles.Forsyth if(nb1 > bits) { 47737da2899SCharles.Forsyth # inline ungetn(nb1 - bits); 47837da2899SCharles.Forsyth n = nb1 - bits; 47937da2899SCharles.Forsyth s.reg = s.svreg >> (s.svn - n); 48037da2899SCharles.Forsyth s.nbits += n; 48137da2899SCharles.Forsyth } 48237da2899SCharles.Forsyth return l1[code].decode; 48337da2899SCharles.Forsyth } 48437da2899SCharles.Forsyth # must advance to second-level table 48537da2899SCharles.Forsyth code = getn(s, nb2, 1); 48637da2899SCharles.Forsyth bits = l2[code].bits; 48737da2899SCharles.Forsyth if(bits == 0) 48837da2899SCharles.Forsyth fatal(s, "corrupt data"); 48937da2899SCharles.Forsyth if(nb1 + nb2 > bits) { 49037da2899SCharles.Forsyth # inline ungetn(nb1 + nb2 - bits); 49137da2899SCharles.Forsyth n = nb1 + nb2 - bits; 49237da2899SCharles.Forsyth s.reg = s.svreg >> (s.svn - n); 49337da2899SCharles.Forsyth s.nbits += n; 49437da2899SCharles.Forsyth } 49537da2899SCharles.Forsyth return l2[code].decode; 49637da2899SCharles.Forsyth} 49737da2899SCharles.Forsyth 49837da2899SCharles.Forsyth# 49937da2899SCharles.Forsyth# uncompress a block that was encoded with dynamic huffman codes 50037da2899SCharles.Forsyth# RFC 1951, section 3.2.7 50137da2899SCharles.Forsyth# 50237da2899SCharles.Forsythdynhuff(s: ref State) 50337da2899SCharles.Forsyth{ 50437da2899SCharles.Forsyth hlit := getn(s, 5, 0) + 257; 50537da2899SCharles.Forsyth hdist := getn(s, 5, 0) + 1; 50637da2899SCharles.Forsyth hclen := getn(s, 4, 0) + 4; 50737da2899SCharles.Forsyth if(hlit > Nlitlen || hlit < 257 || hdist > Noff) 50837da2899SCharles.Forsyth fatal(s, "corrupt data"); 50937da2899SCharles.Forsyth 51037da2899SCharles.Forsyth runlentab := array[Nclen] of { * => Huff(0, 0) }; 51137da2899SCharles.Forsyth count := array[RunlenBits+1] of { * => 0 }; 51237da2899SCharles.Forsyth for(i := 0; i < hclen; i++) { 51337da2899SCharles.Forsyth nb := getn(s, 3, 0); 51437da2899SCharles.Forsyth if(nb) { 51537da2899SCharles.Forsyth runlentab[clenorder[i]].bits = nb; 51637da2899SCharles.Forsyth count[nb]++; 51737da2899SCharles.Forsyth } 51837da2899SCharles.Forsyth } 51937da2899SCharles.Forsyth hufftabinit(runlentab, Nclen, count, RunlenBits); 52037da2899SCharles.Forsyth runlendec := decodeinit(runlentab, Nclen, RunlenBits, 0); 52137da2899SCharles.Forsyth if(runlendec == nil) 52237da2899SCharles.Forsyth fatal(s, "corrupt data"); 52337da2899SCharles.Forsyth 52437da2899SCharles.Forsyth lengths := decodelen(s, runlendec, hlit+hdist); 52537da2899SCharles.Forsyth if(lengths == nil) 52637da2899SCharles.Forsyth fatal(s, "corrupt length table"); 52737da2899SCharles.Forsyth 52837da2899SCharles.Forsyth dlitlendec := decodedyn(s, lengths[0:hlit], hlit, 9); 52937da2899SCharles.Forsyth doffdec := decodedyn(s, lengths[hlit:], hdist, 5); 53037da2899SCharles.Forsyth decodeblock(s, dlitlendec, doffdec); 53137da2899SCharles.Forsyth} 53237da2899SCharles.Forsyth 53337da2899SCharles.Forsyth# 53437da2899SCharles.Forsyth# return the decoded combined length table for literal and distance alphabets 53537da2899SCharles.Forsyth# 53637da2899SCharles.Forsythdecodelen(s: ref State, runlendec: ref DeHuff, nlen: int): array of int 53737da2899SCharles.Forsyth{ 53837da2899SCharles.Forsyth lengths := array[nlen] of int; 53937da2899SCharles.Forsyth for(n := 0; n < nlen;) { 54037da2899SCharles.Forsyth nb := decodesym(s, runlendec); 54137da2899SCharles.Forsyth nr := 1; 54237da2899SCharles.Forsyth case nb { 54337da2899SCharles.Forsyth 0 to 15 => 54437da2899SCharles.Forsyth ; 54537da2899SCharles.Forsyth 16 => 54637da2899SCharles.Forsyth nr = getn(s, 2, 0) + 3; 54737da2899SCharles.Forsyth if(n == 0) 54837da2899SCharles.Forsyth return nil; 54937da2899SCharles.Forsyth nb = lengths[n-1]; 55037da2899SCharles.Forsyth 17 => 55137da2899SCharles.Forsyth nr = getn(s, 3, 0) + 3; 55237da2899SCharles.Forsyth nb = 0; 55337da2899SCharles.Forsyth 18 => 55437da2899SCharles.Forsyth nr = getn(s, 7, 0) + 11; 55537da2899SCharles.Forsyth nb = 0; 55637da2899SCharles.Forsyth * => 55737da2899SCharles.Forsyth return nil; 55837da2899SCharles.Forsyth } 55937da2899SCharles.Forsyth if(n+nr > nlen) 56037da2899SCharles.Forsyth return nil; 56137da2899SCharles.Forsyth while(--nr >= 0) 56237da2899SCharles.Forsyth lengths[n++] = nb; 56337da2899SCharles.Forsyth } 56437da2899SCharles.Forsyth return lengths; 56537da2899SCharles.Forsyth} 56637da2899SCharles.Forsyth 56737da2899SCharles.Forsyth# 56837da2899SCharles.Forsyth# (1) read a dynamic huffman code from the input stream 56937da2899SCharles.Forsyth# (2) decode it using the run-length huffman code 57037da2899SCharles.Forsyth# (3) return the decode table for the dynamic huffman code 57137da2899SCharles.Forsyth# 57237da2899SCharles.Forsythdecodedyn(s: ref State, lengths: array of int, nlen, nb1: int): ref DeHuff 57337da2899SCharles.Forsyth{ 57437da2899SCharles.Forsyth hufftab := array[nlen] of Huff; 57537da2899SCharles.Forsyth count := array[MaxHuffBits+1] of { * => 0 }; 57637da2899SCharles.Forsyth 57737da2899SCharles.Forsyth maxnb := 0; 57837da2899SCharles.Forsyth for(n := 0; n < nlen; n++) { 57937da2899SCharles.Forsyth c := lengths[n]; 58037da2899SCharles.Forsyth if(c) { 58137da2899SCharles.Forsyth hufftab[n].bits = c; 58237da2899SCharles.Forsyth count[c]++; 58337da2899SCharles.Forsyth if(c > maxnb) 58437da2899SCharles.Forsyth maxnb = c; 58537da2899SCharles.Forsyth }else 58637da2899SCharles.Forsyth hufftab[n].bits = 0; 58737da2899SCharles.Forsyth hufftab[n].encode = 0; 58837da2899SCharles.Forsyth } 58937da2899SCharles.Forsyth hufftabinit(hufftab, nlen, count, maxnb); 59037da2899SCharles.Forsyth nb2 := 0; 59137da2899SCharles.Forsyth if(maxnb > nb1) 59237da2899SCharles.Forsyth nb2 = maxnb - nb1; 59337da2899SCharles.Forsyth d := decodeinit(hufftab, nlen, nb1, nb2); 59437da2899SCharles.Forsyth if (d == nil) 59537da2899SCharles.Forsyth fatal(s, "decodeinit failed"); 59637da2899SCharles.Forsyth return d; 59737da2899SCharles.Forsyth} 59837da2899SCharles.Forsyth 59937da2899SCharles.Forsyth# 60037da2899SCharles.Forsyth# RFC 1951, section 3.2.2 60137da2899SCharles.Forsyth# 60237da2899SCharles.Forsythhufftabinit(tab: array of Huff, n: int, bitcount: array of int, nbits: int) 60337da2899SCharles.Forsyth{ 60437da2899SCharles.Forsyth nc := array[MaxHuffBits+1] of int; 60537da2899SCharles.Forsyth 60637da2899SCharles.Forsyth code := 0; 60737da2899SCharles.Forsyth for(bits := 1; bits <= nbits; bits++) { 60837da2899SCharles.Forsyth code = (code + bitcount[bits-1]) << 1; 60937da2899SCharles.Forsyth nc[bits] = code; 61037da2899SCharles.Forsyth } 61137da2899SCharles.Forsyth 61237da2899SCharles.Forsyth for(i := 0; i < n; i++) { 61337da2899SCharles.Forsyth bits = tab[i].bits; 61437da2899SCharles.Forsyth # differences from Deflate module: 61537da2899SCharles.Forsyth # (1) leave huffman code right-justified in encode 61637da2899SCharles.Forsyth # (2) don't reverse it 61737da2899SCharles.Forsyth if(bits != 0) 61837da2899SCharles.Forsyth tab[i].encode = nc[bits]++; 61937da2899SCharles.Forsyth } 62037da2899SCharles.Forsyth} 62137da2899SCharles.Forsyth 62237da2899SCharles.Forsyth# 62337da2899SCharles.Forsyth# convert 'array of Huff' produced by hufftabinit() 62437da2899SCharles.Forsyth# into 2-level lookup table for decoding 62537da2899SCharles.Forsyth# 62637da2899SCharles.Forsyth# nb1(nb2): number of bits handled by first(second)-level table 62737da2899SCharles.Forsyth# 62837da2899SCharles.Forsythdecodeinit(tab: array of Huff, n, nb1, nb2: int): ref DeHuff 62937da2899SCharles.Forsyth{ 63037da2899SCharles.Forsyth i, j, k, d: int; 63137da2899SCharles.Forsyth 63237da2899SCharles.Forsyth dehuff := ref DeHuff(array[1<<nb1] of { * => L1(0, 0, nil) }, nb1, nb2); 63337da2899SCharles.Forsyth l1 := dehuff.l1; 63437da2899SCharles.Forsyth for(i = 0; i < n; i++) { 63537da2899SCharles.Forsyth bits := tab[i].bits; 63637da2899SCharles.Forsyth if(bits == 0) 63737da2899SCharles.Forsyth continue; 63837da2899SCharles.Forsyth l1x := tab[i].encode; 63937da2899SCharles.Forsyth if(l1x >= (1 << bits)) 64037da2899SCharles.Forsyth return nil; 64137da2899SCharles.Forsyth if(bits <= nb1) { 64237da2899SCharles.Forsyth d = nb1 - bits; 64337da2899SCharles.Forsyth l1x <<= d; 64437da2899SCharles.Forsyth k = l1x + mask[d]; 64537da2899SCharles.Forsyth for(j = l1x; j <= k; j++) { 64637da2899SCharles.Forsyth l1[j].decode = i; 64737da2899SCharles.Forsyth l1[j].bits = bits; 64837da2899SCharles.Forsyth } 64937da2899SCharles.Forsyth continue; 65037da2899SCharles.Forsyth } 65137da2899SCharles.Forsyth # advance to second-level table 65237da2899SCharles.Forsyth d = bits - nb1; 65337da2899SCharles.Forsyth l2x := l1x & mask[d]; 65437da2899SCharles.Forsyth l1x >>= d; 65537da2899SCharles.Forsyth if(l1[l1x].l2 == nil) 65637da2899SCharles.Forsyth l1[l1x].l2 = array[1<<nb2] of { * => L2(0, 0) }; 65737da2899SCharles.Forsyth l2 := l1[l1x].l2; 65837da2899SCharles.Forsyth d = (nb1 + nb2) - bits; 65937da2899SCharles.Forsyth l2x <<= d; 66037da2899SCharles.Forsyth k = l2x + mask[d]; 66137da2899SCharles.Forsyth for(j = l2x; j <= k; j++) { 66237da2899SCharles.Forsyth l2[j].decode = i; 66337da2899SCharles.Forsyth l2[j].bits = bits; 66437da2899SCharles.Forsyth } 66537da2899SCharles.Forsyth } 66637da2899SCharles.Forsyth 66737da2899SCharles.Forsyth return dehuff; 66837da2899SCharles.Forsyth} 66937da2899SCharles.Forsyth 67037da2899SCharles.Forsyth# 67137da2899SCharles.Forsyth# get next byte from reg 67237da2899SCharles.Forsyth# assumptions: 67337da2899SCharles.Forsyth# (1) flushbits() has been called 67437da2899SCharles.Forsyth# (2) ungetn() won't be called after a getb() 67537da2899SCharles.Forsyth# 67637da2899SCharles.Forsythgetb(s: ref State): int 67737da2899SCharles.Forsyth{ 67837da2899SCharles.Forsyth if(s.nbits < 8) 67937da2899SCharles.Forsyth need(s, 8); 68037da2899SCharles.Forsyth b := byte s.reg; 68137da2899SCharles.Forsyth s.reg >>= 8; 68237da2899SCharles.Forsyth s.nbits -= 8; 68337da2899SCharles.Forsyth return int b; 68437da2899SCharles.Forsyth} 68537da2899SCharles.Forsyth 68637da2899SCharles.Forsyth# 68737da2899SCharles.Forsyth# get next n bits from reg; if r != 0, reverse the bits 68837da2899SCharles.Forsyth# 68937da2899SCharles.Forsythgetn(s: ref State, n, r: int): int 69037da2899SCharles.Forsyth{ 69137da2899SCharles.Forsyth if(s.nbits < n) 69237da2899SCharles.Forsyth need(s, n); 69337da2899SCharles.Forsyth s.svreg = s.reg; 69437da2899SCharles.Forsyth s.svn = n; 69537da2899SCharles.Forsyth i := s.reg & mask[n]; 69637da2899SCharles.Forsyth s.reg >>= n; 69737da2899SCharles.Forsyth s.nbits -= n; 69837da2899SCharles.Forsyth if(r) { 69937da2899SCharles.Forsyth if(n <= 8) { 70037da2899SCharles.Forsyth i = int revtab[i]; 70137da2899SCharles.Forsyth i >>= 8 - n; 70237da2899SCharles.Forsyth } else { 70337da2899SCharles.Forsyth i = ((int revtab[i & 16rff]) << 8) 70437da2899SCharles.Forsyth | (int revtab[i >> 8]); 70537da2899SCharles.Forsyth i >>= 16 - n; 70637da2899SCharles.Forsyth } 70737da2899SCharles.Forsyth } 70837da2899SCharles.Forsyth return i; 70937da2899SCharles.Forsyth} 71037da2899SCharles.Forsyth 71137da2899SCharles.Forsyth# 71237da2899SCharles.Forsyth# ensure that at least n bits are available in reg 71337da2899SCharles.Forsyth# 71437da2899SCharles.Forsythneed(s: ref State, n: int) 71537da2899SCharles.Forsyth{ 71637da2899SCharles.Forsyth while(s.nbits < n) { 71737da2899SCharles.Forsyth if(s.in >= s.ein) { 71837da2899SCharles.Forsyth s.c <-= ref Rq.Fill(s.ibuf, s.rc); 71937da2899SCharles.Forsyth s.ein = <- s.rc; 72037da2899SCharles.Forsyth if (s.ein < 0) 72137da2899SCharles.Forsyth exit; 72237da2899SCharles.Forsyth if (s.ein == 0) 72337da2899SCharles.Forsyth fatal(s, "premature end of stream"); 72437da2899SCharles.Forsyth s.in = 0; 72537da2899SCharles.Forsyth } 72637da2899SCharles.Forsyth s.reg = ((int s.ibuf[s.in++]) << s.nbits) | s.reg; 72737da2899SCharles.Forsyth s.nbits += 8; 72837da2899SCharles.Forsyth } 72937da2899SCharles.Forsyth} 73037da2899SCharles.Forsyth 73137da2899SCharles.Forsyth# 73237da2899SCharles.Forsyth# if partial byte consumed from reg, dispose of remaining bits 73337da2899SCharles.Forsyth# 73437da2899SCharles.Forsythflushbits(s: ref State) 73537da2899SCharles.Forsyth{ 73637da2899SCharles.Forsyth drek := s.nbits % 8; 73737da2899SCharles.Forsyth if(drek) { 73837da2899SCharles.Forsyth s.reg >>= drek; 73937da2899SCharles.Forsyth s.nbits -= drek; 74037da2899SCharles.Forsyth } 74137da2899SCharles.Forsyth} 74237da2899SCharles.Forsyth 74337da2899SCharles.Forsyth# 74437da2899SCharles.Forsyth# output buffer is full, so flush it 74537da2899SCharles.Forsyth# 74637da2899SCharles.Forsythflushout(s: ref State) 74737da2899SCharles.Forsyth{ 74837da2899SCharles.Forsyth outblock(s); 74937da2899SCharles.Forsyth s.c <-= ref Rq.Result(s.obuf[0:s.out], s.rc); 75037da2899SCharles.Forsyth flag := <- s.rc; 75137da2899SCharles.Forsyth if (flag == -1) 75237da2899SCharles.Forsyth exit; 75337da2899SCharles.Forsyth buf := s.hist; 75437da2899SCharles.Forsyth s.hist = s.obuf; 75537da2899SCharles.Forsyth s.usehist = 1; 75637da2899SCharles.Forsyth s.obuf = buf; 75737da2899SCharles.Forsyth s.out = 0; 75837da2899SCharles.Forsyth} 75937da2899SCharles.Forsyth 76037da2899SCharles.Forsythmkcrctab(poly: int): array of int 76137da2899SCharles.Forsyth{ 76237da2899SCharles.Forsyth crctab := array[256] of int; 76337da2899SCharles.Forsyth for(i := 0; i < 256; i++){ 76437da2899SCharles.Forsyth crc := i; 76537da2899SCharles.Forsyth for(j := 0; j < 8; j++){ 76637da2899SCharles.Forsyth c := crc & 1; 76737da2899SCharles.Forsyth crc = (crc >> 1) & 16r7fffffff; 76837da2899SCharles.Forsyth if(c) 76937da2899SCharles.Forsyth crc ^= poly; 77037da2899SCharles.Forsyth } 77137da2899SCharles.Forsyth crctab[i] = crc; 77237da2899SCharles.Forsyth } 77337da2899SCharles.Forsyth return crctab; 77437da2899SCharles.Forsyth} 77537da2899SCharles.Forsyth 776*ce02cfb2SCharles.Forsythoutblockgzip(s: ref State) 77737da2899SCharles.Forsyth{ 77837da2899SCharles.Forsyth buf := s.obuf; 77937da2899SCharles.Forsyth n := s.out; 78037da2899SCharles.Forsyth crc := s.crc; 78137da2899SCharles.Forsyth crc ^= int 16rffffffff; 78237da2899SCharles.Forsyth for(i := 0; i < n; i++) 78337da2899SCharles.Forsyth crc = s.crctab[int(byte crc ^ buf[i])] ^ ((crc >> 8) & 16r00ffffff); 78437da2899SCharles.Forsyth s.crc = crc ^ int 16rffffffff; 78537da2899SCharles.Forsyth s.tot += n; 78637da2899SCharles.Forsyth} 78737da2899SCharles.Forsyth 788*ce02cfb2SCharles.Forsythoutblockzlib(s: ref State) 789*ce02cfb2SCharles.Forsyth{ 790*ce02cfb2SCharles.Forsyth ZLADLERBASE: con big 65521; 791*ce02cfb2SCharles.Forsyth 792*ce02cfb2SCharles.Forsyth buf := s.obuf; 793*ce02cfb2SCharles.Forsyth n := s.out; 794*ce02cfb2SCharles.Forsyth 795*ce02cfb2SCharles.Forsyth s1 := s.sum & big 16rffff; 796*ce02cfb2SCharles.Forsyth s2 := (s.sum>>16) & big 16rffff; 797*ce02cfb2SCharles.Forsyth 798*ce02cfb2SCharles.Forsyth for(i := 0; i < n; i++) { 799*ce02cfb2SCharles.Forsyth s1 = (s1 + big buf[i]) % ZLADLERBASE; 800*ce02cfb2SCharles.Forsyth s2 = (s2 + s1) % ZLADLERBASE; 801*ce02cfb2SCharles.Forsyth } 802*ce02cfb2SCharles.Forsyth s.sum = (s2<<16) + s1; 803*ce02cfb2SCharles.Forsyth} 804*ce02cfb2SCharles.Forsyth 805*ce02cfb2SCharles.Forsythoutblock(s: ref State) 806*ce02cfb2SCharles.Forsyth{ 807*ce02cfb2SCharles.Forsyth case s.headers { 808*ce02cfb2SCharles.Forsyth Hgzip => outblockgzip(s); 809*ce02cfb2SCharles.Forsyth Hzlib => outblockzlib(s); 810*ce02cfb2SCharles.Forsyth } 811*ce02cfb2SCharles.Forsyth} 812*ce02cfb2SCharles.Forsyth 81337da2899SCharles.Forsyth# 81437da2899SCharles.Forsyth# irrecoverable error; invariably denotes data corruption 81537da2899SCharles.Forsyth# 81637da2899SCharles.Forsythfatal(s: ref State, e: string) 81737da2899SCharles.Forsyth{ 81837da2899SCharles.Forsyth s.c <-= ref Rq.Error(e); 81937da2899SCharles.Forsyth exit; 82037da2899SCharles.Forsyth} 821