1# gzip-compatible decompression filter. 2 3implement Filter; 4 5include "sys.m"; 6 sys: Sys; 7include "filter.m"; 8 9GZMAGIC1: con byte 16r1f; 10GZMAGIC2: con byte 16r8b; 11 12GZDEFLATE: con byte 8; 13 14GZFTEXT: con 1 << 0; # file is text 15GZFHCRC: con 1 << 1; # crc of header included 16GZFEXTRA: con 1 << 2; # extra header included 17GZFNAME: con 1 << 3; # name of file included 18GZFCOMMENT: con 1 << 4; # header comment included 19GZFMASK: con (1 << 5) - 1; # mask of specified bits 20 21GZXBEST: con byte 2; # used maximum compression algorithm 22GZXFAST: con byte 4; # used fast algorithm little compression 23 24GZOSFAT: con byte 0; # FAT file system 25GZOSAMIGA: con byte 1; # Amiga 26GZOSVMS: con byte 2; # VMS or OpenVMS 27GZOSUNIX: con byte 3; # Unix 28GZOSVMCMS: con byte 4; # VM/CMS 29GZOSATARI: con byte 5; # Atari TOS 30GZOSHPFS: con byte 6; # HPFS file system 31GZOSMAC: con byte 7; # Macintosh 32GZOSZSYS: con byte 8; # Z-System 33GZOSCPM: con byte 9; # CP/M 34GZOSTOPS20: con byte 10; # TOPS-20 35GZOSNTFS: con byte 11; # NTFS file system 36GZOSQDOS: con byte 12; # QDOS 37GZOSACORN: con byte 13; # Acorn RISCOS 38GZOSUNK: con byte 255; 39 40GZCRCPOLY: con int 16redb88320; 41GZOSINFERNO: con GZOSUNIX; 42 43# huffman code table 44Huff: adt 45{ 46 bits: int; # length of the code 47 encode: int; # the code 48}; 49 50# huffman decode table 51DeHuff: adt 52{ 53 l1: array of L1; # the table 54 nb1: int; # no. of bits in first level 55 nb2: int; # no. of bits in second level 56}; 57 58# first level of decode table 59L1: adt 60{ 61 bits: int; # length of the code 62 decode: int; # the symbol 63 l2: array of L2; 64}; 65 66# second level 67L2: adt 68{ 69 bits: int; # length of the code 70 decode: int; # the symbol 71}; 72 73DeflateUnc: con 0; # uncompressed block 74DeflateFix: con 1; # fixed huffman codes 75DeflateDyn: con 2; # dynamic huffman codes 76DeflateErr: con 3; # reserved BTYPE (error) 77 78DeflateEob: con 256; # end of block code in lit/len book 79 80LenStart: con 257; # start of length codes in litlen 81LenEnd: con 285; # greatest valid length code 82Nlitlen: con 288; # number of litlen codes 83Noff: con 30; # number of offset codes 84Nclen: con 19; # number of codelen codes 85 86MaxHuffBits: con 15; # max bits in a huffman code 87RunlenBits: con 7; # max bits in a run-length huffman code 88MaxOff: con 32*1024; # max lempel-ziv distance 89 90Blocksize: con 32 * 1024; 91 92# tables from RFC 1951, section 3.2.5 93litlenbase := array[Noff] of 94{ 95 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 96 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 97 67, 83, 99, 115, 131, 163, 195, 227, 258 98}; 99 100litlenextra := array[Noff] of 101{ 102 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 103 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 104 5, 5, 5, 5, 0 105}; 106 107offbase := array[Noff] of 108{ 109 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 110 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 111 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 112}; 113 114offextra := array[Noff] of 115{ 116 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 117 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 118 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 119}; 120 121# order of run-length codes 122clenorder := array[Nclen] of 123{ 124 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 125}; 126 127# fixed huffman tables 128litlentab: array of Huff; 129offtab: array of Huff; 130 131# their decoding table counterparts 132litlendec: ref DeHuff; 133offdec: ref DeHuff; 134 135revtab: array of byte; # bit reversal for endian swap of huffman codes 136mask: array of int; # for masking low-order n bits of an int 137 138Hnone, Hgzip, Hzlib: con iota; # State.headers 139State: adt { 140 ibuf, obuf: array of byte; 141 c: chan of ref Rq; 142 rc: chan of int; 143 in: int; # next byte to consume from input buffer 144 ein: int; # valid bytes in input buffer 145 out: int; # valid bytes in output buffer 146 hist: array of byte; # history buffer for lempel-ziv backward references 147 usehist: int; # == 1 if 'hist' is valid 148 crctab: array of int; 149 crc, tot: int; # for gzip trailer 150 sum: big; # for zlib trailer 151 152 reg: int; # 24-bit shift register 153 nbits: int; # number of valid bits in reg 154 svreg: int; # save reg for efficient ungets 155 svn: int; # number of bits gotten in last call to getn() 156 # reg bits are consumed from right to left 157 # so low-order byte of reg came first in the input stream 158 headers: int; 159}; 160 161 162init() 163{ 164 sys = load Sys Sys->PATH; 165 166 # byte reverse table 167 revtab = array[256] of byte; 168 for(i := 0; i < 256; i++){ 169 revtab[i] = byte 0; 170 for(j := 0; j < 8; j++) { 171 if(i & (1 << j)) 172 revtab[i] |= byte 16r80 >> j; 173 } 174 } 175 176 # bit-masking table 177 mask = array[MaxHuffBits+1] of int; 178 for(i = 0; i <= MaxHuffBits; i++) 179 mask[i] = (1 << i) - 1; 180 181 litlentab = array[Nlitlen] of Huff; 182 183 # static litlen bit lengths 184 for(i = 0; i < 144; i++) 185 litlentab[i].bits = 8; 186 for(i = 144; i < 256; i++) 187 litlentab[i].bits = 9; 188 for(i = 256; i < 280; i++) 189 litlentab[i].bits = 7; 190 for(i = 280; i < Nlitlen; i++) 191 litlentab[i].bits = 8; 192 193 bitcount := array[MaxHuffBits+1] of { * => 0 }; 194 bitcount[8] += 144 - 0; 195 bitcount[9] += 256 - 144; 196 bitcount[7] += 280 - 256; 197 bitcount[8] += Nlitlen - 280; 198 199 hufftabinit(litlentab, Nlitlen, bitcount, 9); 200 litlendec = decodeinit(litlentab, Nlitlen, 9, 0); 201 202 offtab = array[Noff] of Huff; 203 204 # static offset bit lengths 205 for(i = 0; i < Noff; i++) 206 offtab[i].bits = 5; 207 208 for(i = 0; i < 5; i++) 209 bitcount[i] = 0; 210 bitcount[5] = Noff; 211 212 hufftabinit(offtab, Noff, bitcount, 5); 213 offdec = decodeinit(offtab, Noff, 5, 0); 214} 215 216start(params: string): chan of ref Rq 217{ 218 s := ref State; 219 s.c = chan of ref Rq; 220 s.rc = chan of int; 221 s.ibuf = array[Blocksize] of byte; 222 s.obuf = array[Blocksize] of byte; 223 s.in = 0; 224 s.ein = 0; 225 s.out = 0; 226 s.usehist = 0; 227 s.reg = 0; 228 s.nbits = 0; 229 s.crc = 0; 230 s.tot = 0; 231 s.sum = big 1; 232 s.hist = array[Blocksize] of byte; 233 s.headers = Hnone; 234 if(params != nil) { 235 if(params[0] == 'h') 236 s.headers = Hgzip; 237 if(params[0] == 'z') 238 s.headers = Hzlib; 239 } 240 if (s.headers == Hgzip) 241 s.crctab = mkcrctab(GZCRCPOLY); 242 spawn inflate(s); 243 return s.c; 244} 245 246inflate(s: ref State) 247{ 248 s.c <-= ref Rq.Start(sys->pctl(0, nil)); 249 header(s); 250 251 for(;;) { 252 bfinal := getn(s, 1, 0); 253 btype := getn(s, 2, 0); 254 case(btype) { 255 DeflateUnc => 256 flushbits(s); 257 unclen := getb(s); 258 unclen |= getb(s) << 8; 259 nlen := getb(s); 260 nlen |= getb(s) << 8; 261 if(unclen != (~nlen & 16rFFFF)) 262 fatal(s, "corrupted data"); 263 for(; unclen > 0; unclen--) { 264 # inline putb(s, getb(s)); 265 b := byte getb(s); 266 if(s.out >= MaxOff) 267 flushout(s); 268 s.obuf[s.out++] = b; 269 } 270 DeflateFix => 271 decodeblock(s, litlendec, offdec); 272 DeflateDyn => 273 dynhuff(s); 274 DeflateErr => 275 fatal(s, "bad block type"); 276 } 277 if(bfinal) { 278 if(s.out) { 279 outblock(s); 280 s.c <- = ref Rq.Result(s.obuf[0:s.out], s.rc); 281 flag := <- s.rc; 282 if (flag == -1) 283 exit; 284 } 285 flushbits(s); 286 footer(s); 287 s.c <-= ref Rq.Finished(s.ibuf[s.in - s.nbits/8:s.ein]); 288 exit; 289 } 290 } 291} 292 293headergzip(s: ref State) 294{ 295 if(byte getb(s) != GZMAGIC1 || byte getb(s) != GZMAGIC2) 296 fatal(s, "not a gzip file"); 297 298 if(byte getb(s) != GZDEFLATE) 299 fatal(s, "not compressed with deflate"); 300 301 flags := getb(s); 302 if(flags & ~GZFMASK) 303 fatal(s, "reserved flag bits set"); 304 305 # read modification time (ignored) 306 mtime := getb(s); 307 mtime |= (getb(s) << 8); 308 mtime |= (getb(s) << 16); 309 mtime |= (getb(s) << 24); 310 s.c <-= ref Rq.Info("mtime " + string mtime); 311 getb(s); # xfl 312 getb(s); # os 313 314 # skip optional "extra field" 315 if(flags & GZFEXTRA) { 316 skip := getb(s); 317 skip |= getb(s) << 8; 318 while (skip-- > 0) 319 getb(s); 320 } 321 322 # read optional filename (ignored) 323 file: string; 324 if(flags & GZFNAME){ 325 n := 0; 326 while(c := getb(s)) 327 file[n++] = c; 328 s.c <-= ref Rq.Info("file " + file); 329 } 330 331 # skip optional comment 332 if(flags & GZFCOMMENT) { 333 while(getb(s)) 334 ; 335 } 336 337 # skip optional CRC16 field 338 if(flags & GZFHCRC) { 339 getb(s); 340 getb(s); 341 } 342} 343 344headerzlib(s: ref State) 345{ 346 Fdict: con 1<<5; 347 CMshift: con 8; 348 CMmask: con (1<<4)-1; 349 CMdeflate: con 8; 350 351 h := 0; 352 h |= getb(s)<<8; 353 h |= getb(s); 354 if(h % 31 != 0) 355 fatal(s, "invalid zlib header"); 356 if(h&Fdict) 357 fatal(s, "preset dictionary not supported"); 358 if(((h>>CMshift)&CMmask) != CMdeflate) 359 fatal(s, "zlib compression method not deflate"); 360} 361 362header(s: ref State) 363{ 364 case s.headers { 365 Hgzip => headergzip(s); 366 Hzlib => headerzlib(s); 367 } 368} 369 370footergzip(s: ref State) 371{ 372 fcrc := getword(s); 373 if(s.crc != fcrc) 374 fatal(s, sys->sprint("crc mismatch: computed %ux, expected %ux", s.crc, fcrc)); 375 ftot := getword(s); 376 if(s.tot != ftot) 377 fatal(s, sys->sprint("byte count mismatch: computed %d, expected %d", s.tot, ftot)); 378} 379 380footerzlib(s: ref State) 381{ 382 sum := big 0; 383 sum = (sum<<8)|big getb(s); 384 sum = (sum<<8)|big getb(s); 385 sum = (sum<<8)|big getb(s); 386 sum = (sum<<8)|big getb(s); 387 if(sum != s.sum) 388 fatal(s, sys->sprint("adler32 mismatch: computed %bux, expected %bux", s.sum, sum)); 389} 390 391footer(s: ref State) 392{ 393 case s.headers { 394 Hgzip => footergzip(s); 395 Hzlib => footerzlib(s); 396 } 397} 398 399getword(s: ref State): int 400{ 401 n := 0; 402 for(i := 0; i < 4; i++) 403 n |= getb(s) << (8 * i); 404 return n; 405} 406 407# 408# uncompress a block using given huffman decoding tables 409# 410decodeblock(s: ref State, litlendec, offdec: ref DeHuff) 411{ 412 b: byte; 413 414 for(;;) { 415 sym := decodesym(s, litlendec); 416 if(sym < DeflateEob) { # literal byte 417 # inline putb(s, byte sym); 418 b = byte sym; 419 if(s.out >= MaxOff) 420 flushout(s); 421 s.obuf[s.out++] = b; 422 } else if(sym == DeflateEob) { # End-of-block 423 break; 424 } else { # lempel-ziv <length, distance> 425 if(sym > LenEnd) 426 fatal(s, "symbol too long"); 427 xbits := litlenextra[sym - LenStart]; 428 xtra := 0; 429 if(xbits) 430 xtra = getn(s, xbits, 0); 431 length := litlenbase[sym - LenStart] + xtra; 432 433 sym = decodesym(s, offdec); 434 if(sym >= Noff) 435 fatal(s, "symbol too long"); 436 xbits = offextra[sym]; 437 if(xbits) 438 xtra = getn(s, xbits, 0); 439 else 440 xtra = 0; 441 dist := offbase[sym] + xtra; 442 if(dist > s.out && s.usehist == 0) 443 fatal(s, "corrupted data"); 444 for(i := 0; i < length; i++) { 445 # inline putb(lzbyte(dist)); 446 ix := s.out - dist; 447 if(dist <= s.out) 448 b = s.obuf[ix]; 449 else 450 b = s.hist[MaxOff + ix]; 451 if(s.out >= MaxOff) 452 flushout(s); 453 s.obuf[s.out++] = b; 454 } 455 } 456 } 457} 458 459# 460# decode next symbol in input stream using given huffman decoding table 461# 462decodesym(s: ref State, dec: ref DeHuff): int 463{ 464 code, bits, n: int; 465 466 l1 := dec.l1; 467 nb1 := dec.nb1; 468 nb2 := dec.nb2; 469 470 code = getn(s, nb1, 1); 471 l2 := l1[code].l2; 472 if(l2 == nil) { # first level table has answer 473 bits = l1[code].bits; 474 if(bits == 0) 475 fatal(s, "corrupt data"); 476 if(nb1 > bits) { 477 # inline ungetn(nb1 - bits); 478 n = nb1 - bits; 479 s.reg = s.svreg >> (s.svn - n); 480 s.nbits += n; 481 } 482 return l1[code].decode; 483 } 484 # must advance to second-level table 485 code = getn(s, nb2, 1); 486 bits = l2[code].bits; 487 if(bits == 0) 488 fatal(s, "corrupt data"); 489 if(nb1 + nb2 > bits) { 490 # inline ungetn(nb1 + nb2 - bits); 491 n = nb1 + nb2 - bits; 492 s.reg = s.svreg >> (s.svn - n); 493 s.nbits += n; 494 } 495 return l2[code].decode; 496} 497 498# 499# uncompress a block that was encoded with dynamic huffman codes 500# RFC 1951, section 3.2.7 501# 502dynhuff(s: ref State) 503{ 504 hlit := getn(s, 5, 0) + 257; 505 hdist := getn(s, 5, 0) + 1; 506 hclen := getn(s, 4, 0) + 4; 507 if(hlit > Nlitlen || hlit < 257 || hdist > Noff) 508 fatal(s, "corrupt data"); 509 510 runlentab := array[Nclen] of { * => Huff(0, 0) }; 511 count := array[RunlenBits+1] of { * => 0 }; 512 for(i := 0; i < hclen; i++) { 513 nb := getn(s, 3, 0); 514 if(nb) { 515 runlentab[clenorder[i]].bits = nb; 516 count[nb]++; 517 } 518 } 519 hufftabinit(runlentab, Nclen, count, RunlenBits); 520 runlendec := decodeinit(runlentab, Nclen, RunlenBits, 0); 521 if(runlendec == nil) 522 fatal(s, "corrupt data"); 523 524 lengths := decodelen(s, runlendec, hlit+hdist); 525 if(lengths == nil) 526 fatal(s, "corrupt length table"); 527 528 dlitlendec := decodedyn(s, lengths[0:hlit], hlit, 9); 529 doffdec := decodedyn(s, lengths[hlit:], hdist, 5); 530 decodeblock(s, dlitlendec, doffdec); 531} 532 533# 534# return the decoded combined length table for literal and distance alphabets 535# 536decodelen(s: ref State, runlendec: ref DeHuff, nlen: int): array of int 537{ 538 lengths := array[nlen] of int; 539 for(n := 0; n < nlen;) { 540 nb := decodesym(s, runlendec); 541 nr := 1; 542 case nb { 543 0 to 15 => 544 ; 545 16 => 546 nr = getn(s, 2, 0) + 3; 547 if(n == 0) 548 return nil; 549 nb = lengths[n-1]; 550 17 => 551 nr = getn(s, 3, 0) + 3; 552 nb = 0; 553 18 => 554 nr = getn(s, 7, 0) + 11; 555 nb = 0; 556 * => 557 return nil; 558 } 559 if(n+nr > nlen) 560 return nil; 561 while(--nr >= 0) 562 lengths[n++] = nb; 563 } 564 return lengths; 565} 566 567# 568# (1) read a dynamic huffman code from the input stream 569# (2) decode it using the run-length huffman code 570# (3) return the decode table for the dynamic huffman code 571# 572decodedyn(s: ref State, lengths: array of int, nlen, nb1: int): ref DeHuff 573{ 574 hufftab := array[nlen] of Huff; 575 count := array[MaxHuffBits+1] of { * => 0 }; 576 577 maxnb := 0; 578 for(n := 0; n < nlen; n++) { 579 c := lengths[n]; 580 if(c) { 581 hufftab[n].bits = c; 582 count[c]++; 583 if(c > maxnb) 584 maxnb = c; 585 }else 586 hufftab[n].bits = 0; 587 hufftab[n].encode = 0; 588 } 589 hufftabinit(hufftab, nlen, count, maxnb); 590 nb2 := 0; 591 if(maxnb > nb1) 592 nb2 = maxnb - nb1; 593 d := decodeinit(hufftab, nlen, nb1, nb2); 594 if (d == nil) 595 fatal(s, "decodeinit failed"); 596 return d; 597} 598 599# 600# RFC 1951, section 3.2.2 601# 602hufftabinit(tab: array of Huff, n: int, bitcount: array of int, nbits: int) 603{ 604 nc := array[MaxHuffBits+1] of int; 605 606 code := 0; 607 for(bits := 1; bits <= nbits; bits++) { 608 code = (code + bitcount[bits-1]) << 1; 609 nc[bits] = code; 610 } 611 612 for(i := 0; i < n; i++) { 613 bits = tab[i].bits; 614 # differences from Deflate module: 615 # (1) leave huffman code right-justified in encode 616 # (2) don't reverse it 617 if(bits != 0) 618 tab[i].encode = nc[bits]++; 619 } 620} 621 622# 623# convert 'array of Huff' produced by hufftabinit() 624# into 2-level lookup table for decoding 625# 626# nb1(nb2): number of bits handled by first(second)-level table 627# 628decodeinit(tab: array of Huff, n, nb1, nb2: int): ref DeHuff 629{ 630 i, j, k, d: int; 631 632 dehuff := ref DeHuff(array[1<<nb1] of { * => L1(0, 0, nil) }, nb1, nb2); 633 l1 := dehuff.l1; 634 for(i = 0; i < n; i++) { 635 bits := tab[i].bits; 636 if(bits == 0) 637 continue; 638 l1x := tab[i].encode; 639 if(l1x >= (1 << bits)) 640 return nil; 641 if(bits <= nb1) { 642 d = nb1 - bits; 643 l1x <<= d; 644 k = l1x + mask[d]; 645 for(j = l1x; j <= k; j++) { 646 l1[j].decode = i; 647 l1[j].bits = bits; 648 } 649 continue; 650 } 651 # advance to second-level table 652 d = bits - nb1; 653 l2x := l1x & mask[d]; 654 l1x >>= d; 655 if(l1[l1x].l2 == nil) 656 l1[l1x].l2 = array[1<<nb2] of { * => L2(0, 0) }; 657 l2 := l1[l1x].l2; 658 d = (nb1 + nb2) - bits; 659 l2x <<= d; 660 k = l2x + mask[d]; 661 for(j = l2x; j <= k; j++) { 662 l2[j].decode = i; 663 l2[j].bits = bits; 664 } 665 } 666 667 return dehuff; 668} 669 670# 671# get next byte from reg 672# assumptions: 673# (1) flushbits() has been called 674# (2) ungetn() won't be called after a getb() 675# 676getb(s: ref State): int 677{ 678 if(s.nbits < 8) 679 need(s, 8); 680 b := byte s.reg; 681 s.reg >>= 8; 682 s.nbits -= 8; 683 return int b; 684} 685 686# 687# get next n bits from reg; if r != 0, reverse the bits 688# 689getn(s: ref State, n, r: int): int 690{ 691 if(s.nbits < n) 692 need(s, n); 693 s.svreg = s.reg; 694 s.svn = n; 695 i := s.reg & mask[n]; 696 s.reg >>= n; 697 s.nbits -= n; 698 if(r) { 699 if(n <= 8) { 700 i = int revtab[i]; 701 i >>= 8 - n; 702 } else { 703 i = ((int revtab[i & 16rff]) << 8) 704 | (int revtab[i >> 8]); 705 i >>= 16 - n; 706 } 707 } 708 return i; 709} 710 711# 712# ensure that at least n bits are available in reg 713# 714need(s: ref State, n: int) 715{ 716 while(s.nbits < n) { 717 if(s.in >= s.ein) { 718 s.c <-= ref Rq.Fill(s.ibuf, s.rc); 719 s.ein = <- s.rc; 720 if (s.ein < 0) 721 exit; 722 if (s.ein == 0) 723 fatal(s, "premature end of stream"); 724 s.in = 0; 725 } 726 s.reg = ((int s.ibuf[s.in++]) << s.nbits) | s.reg; 727 s.nbits += 8; 728 } 729} 730 731# 732# if partial byte consumed from reg, dispose of remaining bits 733# 734flushbits(s: ref State) 735{ 736 drek := s.nbits % 8; 737 if(drek) { 738 s.reg >>= drek; 739 s.nbits -= drek; 740 } 741} 742 743# 744# output buffer is full, so flush it 745# 746flushout(s: ref State) 747{ 748 outblock(s); 749 s.c <-= ref Rq.Result(s.obuf[0:s.out], s.rc); 750 flag := <- s.rc; 751 if (flag == -1) 752 exit; 753 buf := s.hist; 754 s.hist = s.obuf; 755 s.usehist = 1; 756 s.obuf = buf; 757 s.out = 0; 758} 759 760mkcrctab(poly: int): array of int 761{ 762 crctab := array[256] of int; 763 for(i := 0; i < 256; i++){ 764 crc := i; 765 for(j := 0; j < 8; j++){ 766 c := crc & 1; 767 crc = (crc >> 1) & 16r7fffffff; 768 if(c) 769 crc ^= poly; 770 } 771 crctab[i] = crc; 772 } 773 return crctab; 774} 775 776outblockgzip(s: ref State) 777{ 778 buf := s.obuf; 779 n := s.out; 780 crc := s.crc; 781 crc ^= int 16rffffffff; 782 for(i := 0; i < n; i++) 783 crc = s.crctab[int(byte crc ^ buf[i])] ^ ((crc >> 8) & 16r00ffffff); 784 s.crc = crc ^ int 16rffffffff; 785 s.tot += n; 786} 787 788outblockzlib(s: ref State) 789{ 790 ZLADLERBASE: con big 65521; 791 792 buf := s.obuf; 793 n := s.out; 794 795 s1 := s.sum & big 16rffff; 796 s2 := (s.sum>>16) & big 16rffff; 797 798 for(i := 0; i < n; i++) { 799 s1 = (s1 + big buf[i]) % ZLADLERBASE; 800 s2 = (s2 + s1) % ZLADLERBASE; 801 } 802 s.sum = (s2<<16) + s1; 803} 804 805outblock(s: ref State) 806{ 807 case s.headers { 808 Hgzip => outblockgzip(s); 809 Hzlib => outblockzlib(s); 810 } 811} 812 813# 814# irrecoverable error; invariably denotes data corruption 815# 816fatal(s: ref State, e: string) 817{ 818 s.c <-= ref Rq.Error(e); 819 exit; 820} 821