1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84#include "libbb.h"
85#include "bb_archive.h"
86
87
88
89
90
91
92#ifdef DEBUG
93# define Assert(cond,msg) { if (!(cond)) bb_error_msg(msg); }
94# define Trace(x) fprintf x
95# define Tracev(x) {if (verbose) fprintf x; }
96# define Tracevv(x) {if (verbose > 1) fprintf x; }
97# define Tracec(c,x) {if (verbose && (c)) fprintf x; }
98# define Tracecv(c,x) {if (verbose > 1 && (c)) fprintf x; }
99#else
100# define Assert(cond,msg)
101# define Trace(x)
102# define Tracev(x)
103# define Tracevv(x)
104# define Tracec(c,x)
105# define Tracecv(c,x)
106#endif
107
108
109
110
111#if CONFIG_GZIP_FAST == 0
112# define SMALL_MEM
113#elif CONFIG_GZIP_FAST == 1
114# define MEDIUM_MEM
115#elif CONFIG_GZIP_FAST == 2
116# define BIG_MEM
117#else
118# error "Invalid CONFIG_GZIP_FAST value"
119#endif
120
121#ifndef INBUFSIZ
122# ifdef SMALL_MEM
123# define INBUFSIZ 0x2000
124# else
125# define INBUFSIZ 0x8000
126# endif
127#endif
128
129#ifndef OUTBUFSIZ
130# ifdef SMALL_MEM
131# define OUTBUFSIZ 8192
132# else
133# define OUTBUFSIZ 16384
134# endif
135#endif
136
137#ifndef DIST_BUFSIZE
138# ifdef SMALL_MEM
139# define DIST_BUFSIZE 0x2000
140# else
141# define DIST_BUFSIZE 0x8000
142# endif
143#endif
144
145
146#define ASCII_FLAG 0x01
147#define CONTINUATION 0x02
148#define EXTRA_FIELD 0x04
149#define ORIG_NAME 0x08
150#define COMMENT 0x10
151#define RESERVED 0xC0
152
153
154#define UNKNOWN 0xffff
155#define BINARY 0
156#define ASCII 1
157
158#ifndef WSIZE
159# define WSIZE 0x8000
160#endif
161
162#define MIN_MATCH 3
163#define MAX_MATCH 258
164
165
166#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
167
168
169
170
171#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
172
173
174
175
176#ifndef MAX_PATH_LEN
177# define MAX_PATH_LEN 1024
178#endif
179
180#define seekable() 0
181#define translate_eol 0
182
183#ifndef BITS
184# define BITS 16
185#endif
186#define INIT_BITS 9
187
188#define BIT_MASK 0x1f
189
190
191
192
193
194
195
196
197
198#ifdef MAX_EXT_CHARS
199# define MAX_SUFFIX MAX_EXT_CHARS
200#else
201# define MAX_SUFFIX 30
202#endif
203
204
205
206
207
208
209
210
211
212
213
214#ifdef SMALL_MEM
215# define HASH_BITS 13
216#endif
217#ifdef MEDIUM_MEM
218# define HASH_BITS 14
219#endif
220#ifndef HASH_BITS
221# define HASH_BITS 15
222
223#endif
224
225#define HASH_SIZE (unsigned)(1<<HASH_BITS)
226#define HASH_MASK (HASH_SIZE-1)
227#define WMASK (WSIZE-1)
228
229#ifndef TOO_FAR
230# define TOO_FAR 4096
231#endif
232
233
234
235
236
237
238typedef uint8_t uch;
239typedef uint16_t ush;
240typedef uint32_t ulg;
241typedef int32_t lng;
242
243typedef ush Pos;
244typedef unsigned IPos;
245
246
247
248
249enum {
250 WINDOW_SIZE = 2 * WSIZE,
251
252
253
254
255 max_chain_length = 4096,
256
257
258
259
260 max_lazy_match = 258,
261
262
263
264
265
266 max_insert_length = max_lazy_match,
267
268
269
270
271
272 good_match = 32,
273
274
275
276
277
278
279
280
281 nice_match = 258,
282
283
284
285
286};
287
288
289struct globals {
290
291 lng block_start;
292
293
294
295
296 unsigned ins_h;
297
298#define H_SHIFT ((HASH_BITS+MIN_MATCH-1) / MIN_MATCH)
299
300
301
302
303
304
305 unsigned prev_length;
306
307
308
309
310
311 unsigned strstart;
312 unsigned match_start;
313 unsigned lookahead;
314
315
316
317#define DECLARE(type, array, size) \
318 type * array
319#define ALLOC(type, array, size) \
320 array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type))
321#define FREE(array) \
322 do { free(array); array = NULL; } while (0)
323
324
325
326
327
328 DECLARE(uch, l_buf, INBUFSIZ);
329
330 DECLARE(ush, d_buf, DIST_BUFSIZE);
331 DECLARE(uch, outbuf, OUTBUFSIZ);
332
333
334
335
336
337
338
339
340
341
342 DECLARE(uch, window, 2L * WSIZE);
343
344
345
346
347
348
349 DECLARE(ush, prev, 1L << BITS);
350
351
352
353#define head (G1.prev + WSIZE)
354
355
356 ulg isize;
357
358
359#define ifd STDIN_FILENO
360#define ofd STDOUT_FILENO
361
362#ifdef DEBUG
363 unsigned insize;
364#endif
365 unsigned outcnt;
366
367 smallint eofile;
368
369
370
371
372
373 unsigned short bi_buf;
374
375
376
377
378
379#undef BUF_SIZE
380#define BUF_SIZE (8 * sizeof(G1.bi_buf))
381
382
383
384
385 int bi_valid;
386
387
388
389#ifdef DEBUG
390 ulg bits_sent;
391#endif
392
393
394 uint32_t crc;
395};
396
397#define G1 (*(ptr_to_globals - 1))
398
399
400
401
402
403
404static void flush_outbuf(void)
405{
406 if (G1.outcnt == 0)
407 return;
408
409 xwrite(ofd, (char *) G1.outbuf, G1.outcnt);
410 G1.outcnt = 0;
411}
412
413
414
415
416
417#define put_8bit(c) \
418do { \
419 G1.outbuf[G1.outcnt++] = (c); \
420 if (G1.outcnt == OUTBUFSIZ) flush_outbuf(); \
421} while (0)
422
423
424static void put_16bit(ush w)
425{
426 if (G1.outcnt < OUTBUFSIZ - 2) {
427 G1.outbuf[G1.outcnt++] = w;
428 G1.outbuf[G1.outcnt++] = w >> 8;
429 } else {
430 put_8bit(w);
431 put_8bit(w >> 8);
432 }
433}
434
435static void put_32bit(ulg n)
436{
437 put_16bit(n);
438 put_16bit(n >> 16);
439}
440
441
442
443
444
445
446static void updcrc(uch * s, unsigned n)
447{
448 G1.crc = crc32_block_endian0(G1.crc, s, n, global_crc32_table );
449}
450
451
452
453
454
455
456
457static unsigned file_read(void *buf, unsigned size)
458{
459 unsigned len;
460
461 Assert(G1.insize == 0, "l_buf not empty");
462
463 len = safe_read(ifd, buf, size);
464 if (len == (unsigned)(-1) || len == 0)
465 return len;
466
467 updcrc(buf, len);
468 G1.isize += len;
469 return len;
470}
471
472
473
474
475
476
477static void send_bits(int value, int length)
478{
479#ifdef DEBUG
480 Tracev((stderr, " l %2d v %4x ", length, value));
481 Assert(length > 0 && length <= 15, "invalid length");
482 G1.bits_sent += length;
483#endif
484
485
486
487
488 if (G1.bi_valid > (int) BUF_SIZE - length) {
489 G1.bi_buf |= (value << G1.bi_valid);
490 put_16bit(G1.bi_buf);
491 G1.bi_buf = (ush) value >> (BUF_SIZE - G1.bi_valid);
492 G1.bi_valid += length - BUF_SIZE;
493 } else {
494 G1.bi_buf |= value << G1.bi_valid;
495 G1.bi_valid += length;
496 }
497}
498
499
500
501
502
503
504
505static unsigned bi_reverse(unsigned code, int len)
506{
507 unsigned res = 0;
508
509 while (1) {
510 res |= code & 1;
511 if (--len <= 0) return res;
512 code >>= 1;
513 res <<= 1;
514 }
515}
516
517
518
519
520
521static void bi_windup(void)
522{
523 if (G1.bi_valid > 8) {
524 put_16bit(G1.bi_buf);
525 } else if (G1.bi_valid > 0) {
526 put_8bit(G1.bi_buf);
527 }
528 G1.bi_buf = 0;
529 G1.bi_valid = 0;
530#ifdef DEBUG
531 G1.bits_sent = (G1.bits_sent + 7) & ~7;
532#endif
533}
534
535
536
537
538
539
540static void copy_block(char *buf, unsigned len, int header)
541{
542 bi_windup();
543
544 if (header) {
545 put_16bit(len);
546 put_16bit(~len);
547#ifdef DEBUG
548 G1.bits_sent += 2 * 16;
549#endif
550 }
551#ifdef DEBUG
552 G1.bits_sent += (ulg) len << 3;
553#endif
554 while (len--) {
555 put_8bit(*buf++);
556 }
557}
558
559
560
561
562
563
564
565
566
567
568static void fill_window(void)
569{
570 unsigned n, m;
571 unsigned more = WINDOW_SIZE - G1.lookahead - G1.strstart;
572
573
574
575
576
577 if (more == (unsigned) -1) {
578
579
580
581 more--;
582 } else if (G1.strstart >= WSIZE + MAX_DIST) {
583
584
585
586 Assert(WINDOW_SIZE == 2 * WSIZE, "no sliding with BIG_MEM");
587
588 memcpy(G1.window, G1.window + WSIZE, WSIZE);
589 G1.match_start -= WSIZE;
590 G1.strstart -= WSIZE;
591
592 G1.block_start -= WSIZE;
593
594 for (n = 0; n < HASH_SIZE; n++) {
595 m = head[n];
596 head[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
597 }
598 for (n = 0; n < WSIZE; n++) {
599 m = G1.prev[n];
600 G1.prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
601
602
603
604 }
605 more += WSIZE;
606 }
607
608 if (!G1.eofile) {
609 n = file_read(G1.window + G1.strstart + G1.lookahead, more);
610 if (n == 0 || n == (unsigned) -1) {
611 G1.eofile = 1;
612 } else {
613 G1.lookahead += n;
614 }
615 }
616}
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632static int longest_match(IPos cur_match)
633{
634 unsigned chain_length = max_chain_length;
635 uch *scan = G1.window + G1.strstart;
636 uch *match;
637 int len;
638 int best_len = G1.prev_length;
639 IPos limit = G1.strstart > (IPos) MAX_DIST ? G1.strstart - (IPos) MAX_DIST : 0;
640
641
642
643
644
645
646
647#if HASH_BITS < 8 || MAX_MATCH != 258
648# error Code too clever
649#endif
650 uch *strend = G1.window + G1.strstart + MAX_MATCH;
651 uch scan_end1 = scan[best_len - 1];
652 uch scan_end = scan[best_len];
653
654
655 if (G1.prev_length >= good_match) {
656 chain_length >>= 2;
657 }
658 Assert(G1.strstart <= WINDOW_SIZE - MIN_LOOKAHEAD, "insufficient lookahead");
659
660 do {
661 Assert(cur_match < G1.strstart, "no future");
662 match = G1.window + cur_match;
663
664
665
666
667 if (match[best_len] != scan_end
668 || match[best_len - 1] != scan_end1
669 || *match != *scan || *++match != scan[1]
670 ) {
671 continue;
672 }
673
674
675
676
677
678
679
680 scan += 2, match++;
681
682
683
684
685 do {
686 } while (*++scan == *++match && *++scan == *++match &&
687 *++scan == *++match && *++scan == *++match &&
688 *++scan == *++match && *++scan == *++match &&
689 *++scan == *++match && *++scan == *++match && scan < strend);
690
691 len = MAX_MATCH - (int) (strend - scan);
692 scan = strend - MAX_MATCH;
693
694 if (len > best_len) {
695 G1.match_start = cur_match;
696 best_len = len;
697 if (len >= nice_match)
698 break;
699 scan_end1 = scan[best_len - 1];
700 scan_end = scan[best_len];
701 }
702 } while ((cur_match = G1.prev[cur_match & WMASK]) > limit
703 && --chain_length != 0);
704
705 return best_len;
706}
707
708
709#ifdef DEBUG
710
711
712
713static void check_match(IPos start, IPos match, int length)
714{
715
716 if (memcmp(G1.window + match, G1.window + start, length) != 0) {
717 bb_error_msg(" start %d, match %d, length %d", start, match, length);
718 bb_error_msg("invalid match");
719 }
720 if (verbose > 1) {
721 bb_error_msg("\\[%d,%d]", start - match, length);
722 do {
723 bb_putchar_stderr(G1.window[start++]);
724 } while (--length != 0);
725 }
726}
727#else
728# define check_match(start, match, length) ((void)0)
729#endif
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781#define MAX_BITS 15
782
783
784#define MAX_BL_BITS 7
785
786
787#define LENGTH_CODES 29
788
789
790#define LITERALS 256
791
792
793#define END_BLOCK 256
794
795
796#define L_CODES (LITERALS+1+LENGTH_CODES)
797
798
799#define D_CODES 30
800
801
802#define BL_CODES 19
803
804
805
806static const uint8_t extra_lbits[LENGTH_CODES] ALIGN1 = {
807 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
808 4, 4, 5, 5, 5, 5, 0
809};
810
811
812static const uint8_t extra_dbits[D_CODES] ALIGN1 = {
813 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
814 10, 10, 11, 11, 12, 12, 13, 13
815};
816
817
818static const uint8_t extra_blbits[BL_CODES] ALIGN1 = {
819 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
820
821
822static const uint8_t bl_order[BL_CODES] ALIGN1 = {
823 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
824
825#define STORED_BLOCK 0
826#define STATIC_TREES 1
827#define DYN_TREES 2
828
829
830#ifndef LIT_BUFSIZE
831# ifdef SMALL_MEM
832# define LIT_BUFSIZE 0x2000
833# else
834# ifdef MEDIUM_MEM
835# define LIT_BUFSIZE 0x4000
836# else
837# define LIT_BUFSIZE 0x8000
838# endif
839# endif
840#endif
841#ifndef DIST_BUFSIZE
842# define DIST_BUFSIZE LIT_BUFSIZE
843#endif
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864#define REP_3_6 16
865
866#define REPZ_3_10 17
867
868#define REPZ_11_138 18
869
870
871
872
873
874typedef struct ct_data {
875 union {
876 ush freq;
877 ush code;
878 } fc;
879 union {
880 ush dad;
881 ush len;
882 } dl;
883} ct_data;
884
885#define Freq fc.freq
886#define Code fc.code
887#define Dad dl.dad
888#define Len dl.len
889
890#define HEAP_SIZE (2*L_CODES + 1)
891
892
893typedef struct tree_desc {
894 ct_data *dyn_tree;
895 ct_data *static_tree;
896 const uint8_t *extra_bits;
897 int extra_base;
898 int elems;
899 int max_length;
900 int max_code;
901} tree_desc;
902
903struct globals2 {
904
905 ush heap[HEAP_SIZE];
906 int heap_len;
907 int heap_max;
908
909
910
911
912
913 ct_data dyn_ltree[HEAP_SIZE];
914 ct_data dyn_dtree[2 * D_CODES + 1];
915
916 ct_data static_ltree[L_CODES + 2];
917
918
919
920
921
922
923
924 ct_data static_dtree[D_CODES];
925
926
927
928
929
930 ct_data bl_tree[2 * BL_CODES + 1];
931
932
933
934 tree_desc l_desc;
935 tree_desc d_desc;
936 tree_desc bl_desc;
937
938 ush bl_count[MAX_BITS + 1];
939
940
941
942
943
944 uch depth[2 * L_CODES + 1];
945
946
947
948 uch length_code[MAX_MATCH - MIN_MATCH + 1];
949
950
951
952 uch dist_code[512];
953
954
955
956
957
958
959 int base_length[LENGTH_CODES];
960
961
962
963 int base_dist[D_CODES];
964
965
966
967 uch flag_buf[LIT_BUFSIZE / 8];
968
969
970
971
972
973 unsigned last_lit;
974 unsigned last_dist;
975 unsigned last_flags;
976 uch flags;
977 uch flag_bit;
978
979
980
981
982
983
984 ulg opt_len;
985 ulg static_len;
986
987 ulg compressed_len;
988};
989
990#define G2ptr ((struct globals2*)(ptr_to_globals))
991#define G2 (*G2ptr)
992
993
994
995
996static void gen_codes(ct_data * tree, int max_code);
997static void build_tree(tree_desc * desc);
998static void scan_tree(ct_data * tree, int max_code);
999static void send_tree(ct_data * tree, int max_code);
1000static int build_bl_tree(void);
1001static void send_all_trees(int lcodes, int dcodes, int blcodes);
1002static void compress_block(ct_data * ltree, ct_data * dtree);
1003
1004
1005#ifndef DEBUG
1006
1007# define SEND_CODE(c, tree) send_bits(tree[c].Code, tree[c].Len)
1008#else
1009# define SEND_CODE(c, tree) \
1010{ \
1011 if (verbose > 1) bb_error_msg("\ncd %3d ", (c)); \
1012 send_bits(tree[c].Code, tree[c].Len); \
1013}
1014#endif
1015
1016#define D_CODE(dist) \
1017 ((dist) < 256 ? G2.dist_code[dist] : G2.dist_code[256 + ((dist)>>7)])
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028static void init_block(void)
1029{
1030 int n;
1031
1032
1033 for (n = 0; n < L_CODES; n++)
1034 G2.dyn_ltree[n].Freq = 0;
1035 for (n = 0; n < D_CODES; n++)
1036 G2.dyn_dtree[n].Freq = 0;
1037 for (n = 0; n < BL_CODES; n++)
1038 G2.bl_tree[n].Freq = 0;
1039
1040 G2.dyn_ltree[END_BLOCK].Freq = 1;
1041 G2.opt_len = G2.static_len = 0;
1042 G2.last_lit = G2.last_dist = G2.last_flags = 0;
1043 G2.flags = 0;
1044 G2.flag_bit = 1;
1045}
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057#define SMALLER(tree, n, m) \
1058 (tree[n].Freq < tree[m].Freq \
1059 || (tree[n].Freq == tree[m].Freq && G2.depth[n] <= G2.depth[m]))
1060
1061static void pqdownheap(ct_data * tree, int k)
1062{
1063 int v = G2.heap[k];
1064 int j = k << 1;
1065
1066 while (j <= G2.heap_len) {
1067
1068 if (j < G2.heap_len && SMALLER(tree, G2.heap[j + 1], G2.heap[j]))
1069 j++;
1070
1071
1072 if (SMALLER(tree, v, G2.heap[j]))
1073 break;
1074
1075
1076 G2.heap[k] = G2.heap[j];
1077 k = j;
1078
1079
1080 j <<= 1;
1081 }
1082 G2.heap[k] = v;
1083}
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096static void gen_bitlen(tree_desc * desc)
1097{
1098 ct_data *tree = desc->dyn_tree;
1099 const uint8_t *extra = desc->extra_bits;
1100 int base = desc->extra_base;
1101 int max_code = desc->max_code;
1102 int max_length = desc->max_length;
1103 ct_data *stree = desc->static_tree;
1104 int h;
1105 int n, m;
1106 int bits;
1107 int xbits;
1108 ush f;
1109 int overflow = 0;
1110
1111 for (bits = 0; bits <= MAX_BITS; bits++)
1112 G2.bl_count[bits] = 0;
1113
1114
1115
1116
1117 tree[G2.heap[G2.heap_max]].Len = 0;
1118
1119 for (h = G2.heap_max + 1; h < HEAP_SIZE; h++) {
1120 n = G2.heap[h];
1121 bits = tree[tree[n].Dad].Len + 1;
1122 if (bits > max_length) {
1123 bits = max_length;
1124 overflow++;
1125 }
1126 tree[n].Len = (ush) bits;
1127
1128
1129 if (n > max_code)
1130 continue;
1131
1132 G2.bl_count[bits]++;
1133 xbits = 0;
1134 if (n >= base)
1135 xbits = extra[n - base];
1136 f = tree[n].Freq;
1137 G2.opt_len += (ulg) f *(bits + xbits);
1138
1139 if (stree)
1140 G2.static_len += (ulg) f * (stree[n].Len + xbits);
1141 }
1142 if (overflow == 0)
1143 return;
1144
1145 Trace((stderr, "\nbit length overflow\n"));
1146
1147
1148
1149 do {
1150 bits = max_length - 1;
1151 while (G2.bl_count[bits] == 0)
1152 bits--;
1153 G2.bl_count[bits]--;
1154 G2.bl_count[bits + 1] += 2;
1155 G2.bl_count[max_length]--;
1156
1157
1158
1159 overflow -= 2;
1160 } while (overflow > 0);
1161
1162
1163
1164
1165
1166
1167 for (bits = max_length; bits != 0; bits--) {
1168 n = G2.bl_count[bits];
1169 while (n != 0) {
1170 m = G2.heap[--h];
1171 if (m > max_code)
1172 continue;
1173 if (tree[m].Len != (unsigned) bits) {
1174 Trace((stderr, "code %d bits %d->%d\n", m, tree[m].Len, bits));
1175 G2.opt_len += ((int32_t) bits - tree[m].Len) * tree[m].Freq;
1176 tree[m].Len = bits;
1177 }
1178 n--;
1179 }
1180 }
1181}
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192static void gen_codes(ct_data * tree, int max_code)
1193{
1194 ush next_code[MAX_BITS + 1];
1195 ush code = 0;
1196 int bits;
1197 int n;
1198
1199
1200
1201
1202 for (bits = 1; bits <= MAX_BITS; bits++) {
1203 next_code[bits] = code = (code + G2.bl_count[bits - 1]) << 1;
1204 }
1205
1206
1207
1208 Assert(code + G2.bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
1209 "inconsistent bit counts");
1210 Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
1211
1212 for (n = 0; n <= max_code; n++) {
1213 int len = tree[n].Len;
1214
1215 if (len == 0)
1216 continue;
1217
1218 tree[n].Code = bi_reverse(next_code[len]++, len);
1219
1220 Tracec(tree != G2.static_ltree,
1221 (stderr, "\nn %3d %c l %2d c %4x (%x) ", n,
1222 (n > ' ' ? n : ' '), len, tree[n].Code,
1223 next_code[len] - 1));
1224 }
1225}
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240#define SMALLEST 1
1241
1242
1243#define PQREMOVE(tree, top) \
1244do { \
1245 top = G2.heap[SMALLEST]; \
1246 G2.heap[SMALLEST] = G2.heap[G2.heap_len--]; \
1247 pqdownheap(tree, SMALLEST); \
1248} while (0)
1249
1250static void build_tree(tree_desc * desc)
1251{
1252 ct_data *tree = desc->dyn_tree;
1253 ct_data *stree = desc->static_tree;
1254 int elems = desc->elems;
1255 int n, m;
1256 int max_code = -1;
1257 int node = elems;
1258
1259
1260
1261
1262
1263 G2.heap_len = 0;
1264 G2.heap_max = HEAP_SIZE;
1265
1266 for (n = 0; n < elems; n++) {
1267 if (tree[n].Freq != 0) {
1268 G2.heap[++G2.heap_len] = max_code = n;
1269 G2.depth[n] = 0;
1270 } else {
1271 tree[n].Len = 0;
1272 }
1273 }
1274
1275
1276
1277
1278
1279
1280 while (G2.heap_len < 2) {
1281 int new = G2.heap[++G2.heap_len] = (max_code < 2 ? ++max_code : 0);
1282
1283 tree[new].Freq = 1;
1284 G2.depth[new] = 0;
1285 G2.opt_len--;
1286 if (stree)
1287 G2.static_len -= stree[new].Len;
1288
1289 }
1290 desc->max_code = max_code;
1291
1292
1293
1294
1295 for (n = G2.heap_len / 2; n >= 1; n--)
1296 pqdownheap(tree, n);
1297
1298
1299
1300
1301 do {
1302 PQREMOVE(tree, n);
1303 m = G2.heap[SMALLEST];
1304
1305 G2.heap[--G2.heap_max] = n;
1306 G2.heap[--G2.heap_max] = m;
1307
1308
1309 tree[node].Freq = tree[n].Freq + tree[m].Freq;
1310 G2.depth[node] = MAX(G2.depth[n], G2.depth[m]) + 1;
1311 tree[n].Dad = tree[m].Dad = (ush) node;
1312#ifdef DUMP_BL_TREE
1313 if (tree == G2.bl_tree) {
1314 bb_error_msg("\nnode %d(%d), sons %d(%d) %d(%d)",
1315 node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
1316 }
1317#endif
1318
1319 G2.heap[SMALLEST] = node++;
1320 pqdownheap(tree, SMALLEST);
1321
1322 } while (G2.heap_len >= 2);
1323
1324 G2.heap[--G2.heap_max] = G2.heap[SMALLEST];
1325
1326
1327
1328
1329 gen_bitlen((tree_desc *) desc);
1330
1331
1332 gen_codes((ct_data *) tree, max_code);
1333}
1334
1335
1336
1337
1338
1339
1340
1341
1342static void scan_tree(ct_data * tree, int max_code)
1343{
1344 int n;
1345 int prevlen = -1;
1346 int curlen;
1347 int nextlen = tree[0].Len;
1348 int count = 0;
1349 int max_count = 7;
1350 int min_count = 4;
1351
1352 if (nextlen == 0) {
1353 max_count = 138;
1354 min_count = 3;
1355 }
1356 tree[max_code + 1].Len = 0xffff;
1357
1358 for (n = 0; n <= max_code; n++) {
1359 curlen = nextlen;
1360 nextlen = tree[n + 1].Len;
1361 if (++count < max_count && curlen == nextlen)
1362 continue;
1363
1364 if (count < min_count) {
1365 G2.bl_tree[curlen].Freq += count;
1366 } else if (curlen != 0) {
1367 if (curlen != prevlen)
1368 G2.bl_tree[curlen].Freq++;
1369 G2.bl_tree[REP_3_6].Freq++;
1370 } else if (count <= 10) {
1371 G2.bl_tree[REPZ_3_10].Freq++;
1372 } else {
1373 G2.bl_tree[REPZ_11_138].Freq++;
1374 }
1375 count = 0;
1376 prevlen = curlen;
1377
1378 max_count = 7;
1379 min_count = 4;
1380 if (nextlen == 0) {
1381 max_count = 138;
1382 min_count = 3;
1383 } else if (curlen == nextlen) {
1384 max_count = 6;
1385 min_count = 3;
1386 }
1387 }
1388}
1389
1390
1391
1392
1393
1394
1395static void send_tree(ct_data * tree, int max_code)
1396{
1397 int n;
1398 int prevlen = -1;
1399 int curlen;
1400 int nextlen = tree[0].Len;
1401 int count = 0;
1402 int max_count = 7;
1403 int min_count = 4;
1404
1405
1406 if (nextlen == 0)
1407 max_count = 138, min_count = 3;
1408
1409 for (n = 0; n <= max_code; n++) {
1410 curlen = nextlen;
1411 nextlen = tree[n + 1].Len;
1412 if (++count < max_count && curlen == nextlen) {
1413 continue;
1414 } else if (count < min_count) {
1415 do {
1416 SEND_CODE(curlen, G2.bl_tree);
1417 } while (--count);
1418 } else if (curlen != 0) {
1419 if (curlen != prevlen) {
1420 SEND_CODE(curlen, G2.bl_tree);
1421 count--;
1422 }
1423 Assert(count >= 3 && count <= 6, " 3_6?");
1424 SEND_CODE(REP_3_6, G2.bl_tree);
1425 send_bits(count - 3, 2);
1426 } else if (count <= 10) {
1427 SEND_CODE(REPZ_3_10, G2.bl_tree);
1428 send_bits(count - 3, 3);
1429 } else {
1430 SEND_CODE(REPZ_11_138, G2.bl_tree);
1431 send_bits(count - 11, 7);
1432 }
1433 count = 0;
1434 prevlen = curlen;
1435 if (nextlen == 0) {
1436 max_count = 138;
1437 min_count = 3;
1438 } else if (curlen == nextlen) {
1439 max_count = 6;
1440 min_count = 3;
1441 } else {
1442 max_count = 7;
1443 min_count = 4;
1444 }
1445 }
1446}
1447
1448
1449
1450
1451
1452
1453static int build_bl_tree(void)
1454{
1455 int max_blindex;
1456
1457
1458 scan_tree(G2.dyn_ltree, G2.l_desc.max_code);
1459 scan_tree(G2.dyn_dtree, G2.d_desc.max_code);
1460
1461
1462 build_tree(&G2.bl_desc);
1463
1464
1465
1466
1467
1468
1469
1470
1471 for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
1472 if (G2.bl_tree[bl_order[max_blindex]].Len != 0)
1473 break;
1474 }
1475
1476 G2.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
1477 Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", G2.opt_len, G2.static_len));
1478
1479 return max_blindex;
1480}
1481
1482
1483
1484
1485
1486
1487
1488static void send_all_trees(int lcodes, int dcodes, int blcodes)
1489{
1490 int rank;
1491
1492 Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
1493 Assert(lcodes <= L_CODES && dcodes <= D_CODES
1494 && blcodes <= BL_CODES, "too many codes");
1495 Tracev((stderr, "\nbl counts: "));
1496 send_bits(lcodes - 257, 5);
1497 send_bits(dcodes - 1, 5);
1498 send_bits(blcodes - 4, 4);
1499 for (rank = 0; rank < blcodes; rank++) {
1500 Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
1501 send_bits(G2.bl_tree[bl_order[rank]].Len, 3);
1502 }
1503 Tracev((stderr, "\nbl tree: sent %ld", G1.bits_sent));
1504
1505 send_tree((ct_data *) G2.dyn_ltree, lcodes - 1);
1506 Tracev((stderr, "\nlit tree: sent %ld", G1.bits_sent));
1507
1508 send_tree((ct_data *) G2.dyn_dtree, dcodes - 1);
1509 Tracev((stderr, "\ndist tree: sent %ld", G1.bits_sent));
1510}
1511
1512
1513
1514
1515
1516
1517static int ct_tally(int dist, int lc)
1518{
1519 G1.l_buf[G2.last_lit++] = lc;
1520 if (dist == 0) {
1521
1522 G2.dyn_ltree[lc].Freq++;
1523 } else {
1524
1525 dist--;
1526 Assert((ush) dist < (ush) MAX_DIST
1527 && (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH)
1528 && (ush) D_CODE(dist) < (ush) D_CODES, "ct_tally: bad match"
1529 );
1530
1531 G2.dyn_ltree[G2.length_code[lc] + LITERALS + 1].Freq++;
1532 G2.dyn_dtree[D_CODE(dist)].Freq++;
1533
1534 G1.d_buf[G2.last_dist++] = dist;
1535 G2.flags |= G2.flag_bit;
1536 }
1537 G2.flag_bit <<= 1;
1538
1539
1540 if ((G2.last_lit & 7) == 0) {
1541 G2.flag_buf[G2.last_flags++] = G2.flags;
1542 G2.flags = 0;
1543 G2.flag_bit = 1;
1544 }
1545
1546 if ((G2.last_lit & 0xfff) == 0) {
1547
1548 ulg out_length = G2.last_lit * 8L;
1549 ulg in_length = (ulg) G1.strstart - G1.block_start;
1550 int dcode;
1551
1552 for (dcode = 0; dcode < D_CODES; dcode++) {
1553 out_length += G2.dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]);
1554 }
1555 out_length >>= 3;
1556 Trace((stderr,
1557 "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
1558 G2.last_lit, G2.last_dist, in_length, out_length,
1559 100L - out_length * 100L / in_length));
1560 if (G2.last_dist < G2.last_lit / 2 && out_length < in_length / 2)
1561 return 1;
1562 }
1563 return (G2.last_lit == LIT_BUFSIZE - 1 || G2.last_dist == DIST_BUFSIZE);
1564
1565
1566
1567
1568}
1569
1570
1571
1572
1573static void compress_block(ct_data * ltree, ct_data * dtree)
1574{
1575 unsigned dist;
1576 int lc;
1577 unsigned lx = 0;
1578 unsigned dx = 0;
1579 unsigned fx = 0;
1580 uch flag = 0;
1581 unsigned code;
1582 int extra;
1583
1584 if (G2.last_lit != 0) do {
1585 if ((lx & 7) == 0)
1586 flag = G2.flag_buf[fx++];
1587 lc = G1.l_buf[lx++];
1588 if ((flag & 1) == 0) {
1589 SEND_CODE(lc, ltree);
1590 Tracecv(lc > ' ', (stderr, " '%c' ", lc));
1591 } else {
1592
1593 code = G2.length_code[lc];
1594 SEND_CODE(code + LITERALS + 1, ltree);
1595 extra = extra_lbits[code];
1596 if (extra != 0) {
1597 lc -= G2.base_length[code];
1598 send_bits(lc, extra);
1599 }
1600 dist = G1.d_buf[dx++];
1601
1602 code = D_CODE(dist);
1603 Assert(code < D_CODES, "bad d_code");
1604
1605 SEND_CODE(code, dtree);
1606 extra = extra_dbits[code];
1607 if (extra != 0) {
1608 dist -= G2.base_dist[code];
1609 send_bits(dist, extra);
1610 }
1611 }
1612 flag >>= 1;
1613 } while (lx < G2.last_lit);
1614
1615 SEND_CODE(END_BLOCK, ltree);
1616}
1617
1618
1619
1620
1621
1622
1623
1624static ulg flush_block(char *buf, ulg stored_len, int eof)
1625{
1626 ulg opt_lenb, static_lenb;
1627 int max_blindex;
1628
1629 G2.flag_buf[G2.last_flags] = G2.flags;
1630
1631
1632 build_tree(&G2.l_desc);
1633 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", G2.opt_len, G2.static_len));
1634
1635 build_tree(&G2.d_desc);
1636 Tracev((stderr, "\ndist data: dyn %ld, stat %ld", G2.opt_len, G2.static_len));
1637
1638
1639
1640
1641
1642
1643
1644 max_blindex = build_bl_tree();
1645
1646
1647 opt_lenb = (G2.opt_len + 3 + 7) >> 3;
1648 static_lenb = (G2.static_len + 3 + 7) >> 3;
1649
1650 Trace((stderr,
1651 "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
1652 opt_lenb, G2.opt_len, static_lenb, G2.static_len, stored_len,
1653 G2.last_lit, G2.last_dist));
1654
1655 if (static_lenb <= opt_lenb)
1656 opt_lenb = static_lenb;
1657
1658
1659
1660
1661
1662 if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) {
1663
1664 if (buf == NULL)
1665 bb_error_msg("block vanished");
1666
1667 copy_block(buf, (unsigned) stored_len, 0);
1668 G2.compressed_len = stored_len << 3;
1669
1670 } else if (stored_len + 4 <= opt_lenb && buf != NULL) {
1671
1672
1673
1674
1675
1676
1677
1678 send_bits((STORED_BLOCK << 1) + eof, 3);
1679 G2.compressed_len = (G2.compressed_len + 3 + 7) & ~7L;
1680 G2.compressed_len += (stored_len + 4) << 3;
1681
1682 copy_block(buf, (unsigned) stored_len, 1);
1683
1684 } else if (static_lenb == opt_lenb) {
1685 send_bits((STATIC_TREES << 1) + eof, 3);
1686 compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree);
1687 G2.compressed_len += 3 + G2.static_len;
1688 } else {
1689 send_bits((DYN_TREES << 1) + eof, 3);
1690 send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1,
1691 max_blindex + 1);
1692 compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree);
1693 G2.compressed_len += 3 + G2.opt_len;
1694 }
1695 Assert(G2.compressed_len == G1.bits_sent, "bad compressed size");
1696 init_block();
1697
1698 if (eof) {
1699 bi_windup();
1700 G2.compressed_len += 7;
1701 }
1702 Tracev((stderr, "\ncomprlen %lu(%lu) ", G2.compressed_len >> 3,
1703 G2.compressed_len - 7 * eof));
1704
1705 return G2.compressed_len >> 3;
1706}
1707
1708
1709
1710
1711
1712
1713
1714
1715#define UPDATE_HASH(h, c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730#define FLUSH_BLOCK(eof) \
1731 flush_block( \
1732 G1.block_start >= 0L \
1733 ? (char*)&G1.window[(unsigned)G1.block_start] \
1734 : (char*)NULL, \
1735 (ulg)G1.strstart - G1.block_start, \
1736 (eof) \
1737 )
1738
1739
1740
1741
1742
1743
1744
1745#define INSERT_STRING(s, match_head) \
1746do { \
1747 UPDATE_HASH(G1.ins_h, G1.window[(s) + MIN_MATCH-1]); \
1748 G1.prev[(s) & WMASK] = match_head = head[G1.ins_h]; \
1749 head[G1.ins_h] = (s); \
1750} while (0)
1751
1752static ulg deflate(void)
1753{
1754 IPos hash_head;
1755 IPos prev_match;
1756 int flush;
1757 int match_available = 0;
1758 unsigned match_length = MIN_MATCH - 1;
1759
1760
1761 while (G1.lookahead != 0) {
1762
1763
1764
1765 INSERT_STRING(G1.strstart, hash_head);
1766
1767
1768
1769 G1.prev_length = match_length;
1770 prev_match = G1.match_start;
1771 match_length = MIN_MATCH - 1;
1772
1773 if (hash_head != 0 && G1.prev_length < max_lazy_match
1774 && G1.strstart - hash_head <= MAX_DIST
1775 ) {
1776
1777
1778
1779
1780 match_length = longest_match(hash_head);
1781
1782 if (match_length > G1.lookahead)
1783 match_length = G1.lookahead;
1784
1785
1786 if (match_length == MIN_MATCH && G1.strstart - G1.match_start > TOO_FAR) {
1787
1788
1789
1790 match_length--;
1791 }
1792 }
1793
1794
1795
1796 if (G1.prev_length >= MIN_MATCH && match_length <= G1.prev_length) {
1797 check_match(G1.strstart - 1, prev_match, G1.prev_length);
1798 flush = ct_tally(G1.strstart - 1 - prev_match, G1.prev_length - MIN_MATCH);
1799
1800
1801
1802
1803 G1.lookahead -= G1.prev_length - 1;
1804 G1.prev_length -= 2;
1805 do {
1806 G1.strstart++;
1807 INSERT_STRING(G1.strstart, hash_head);
1808
1809
1810
1811
1812
1813 } while (--G1.prev_length != 0);
1814 match_available = 0;
1815 match_length = MIN_MATCH - 1;
1816 G1.strstart++;
1817 if (flush) {
1818 FLUSH_BLOCK(0);
1819 G1.block_start = G1.strstart;
1820 }
1821 } else if (match_available) {
1822
1823
1824
1825
1826 Tracevv((stderr, "%c", G1.window[G1.strstart - 1]));
1827 if (ct_tally(0, G1.window[G1.strstart - 1])) {
1828 FLUSH_BLOCK(0);
1829 G1.block_start = G1.strstart;
1830 }
1831 G1.strstart++;
1832 G1.lookahead--;
1833 } else {
1834
1835
1836
1837 match_available = 1;
1838 G1.strstart++;
1839 G1.lookahead--;
1840 }
1841 Assert(G1.strstart <= G1.isize && lookahead <= G1.isize, "a bit too far");
1842
1843
1844
1845
1846
1847
1848 while (G1.lookahead < MIN_LOOKAHEAD && !G1.eofile)
1849 fill_window();
1850 }
1851 if (match_available)
1852 ct_tally(0, G1.window[G1.strstart - 1]);
1853
1854 return FLUSH_BLOCK(1);
1855}
1856
1857
1858
1859
1860
1861static void bi_init(void)
1862{
1863 G1.bi_buf = 0;
1864 G1.bi_valid = 0;
1865#ifdef DEBUG
1866 G1.bits_sent = 0L;
1867#endif
1868}
1869
1870
1871
1872
1873
1874static void lm_init(ush * flagsp)
1875{
1876 unsigned j;
1877
1878
1879 memset(head, 0, HASH_SIZE * sizeof(*head));
1880
1881
1882
1883 *flagsp |= 2;
1884
1885
1886 G1.strstart = 0;
1887 G1.block_start = 0L;
1888
1889 G1.lookahead = file_read(G1.window,
1890 sizeof(int) <= 2 ? (unsigned) WSIZE : 2 * WSIZE);
1891
1892 if (G1.lookahead == 0 || G1.lookahead == (unsigned) -1) {
1893 G1.eofile = 1;
1894 G1.lookahead = 0;
1895 return;
1896 }
1897 G1.eofile = 0;
1898
1899
1900
1901 while (G1.lookahead < MIN_LOOKAHEAD && !G1.eofile)
1902 fill_window();
1903
1904 G1.ins_h = 0;
1905 for (j = 0; j < MIN_MATCH - 1; j++)
1906 UPDATE_HASH(G1.ins_h, G1.window[j]);
1907
1908
1909
1910}
1911
1912
1913
1914
1915
1916
1917
1918
1919static void ct_init(void)
1920{
1921 int n;
1922 int length;
1923 int code;
1924 int dist;
1925
1926 G2.compressed_len = 0L;
1927
1928#ifdef NOT_NEEDED
1929 if (G2.static_dtree[0].Len != 0)
1930 return;
1931#endif
1932
1933
1934 length = 0;
1935 for (code = 0; code < LENGTH_CODES - 1; code++) {
1936 G2.base_length[code] = length;
1937 for (n = 0; n < (1 << extra_lbits[code]); n++) {
1938 G2.length_code[length++] = code;
1939 }
1940 }
1941 Assert(length == 256, "ct_init: length != 256");
1942
1943
1944
1945
1946 G2.length_code[length - 1] = code;
1947
1948
1949 dist = 0;
1950 for (code = 0; code < 16; code++) {
1951 G2.base_dist[code] = dist;
1952 for (n = 0; n < (1 << extra_dbits[code]); n++) {
1953 G2.dist_code[dist++] = code;
1954 }
1955 }
1956 Assert(dist == 256, "ct_init: dist != 256");
1957 dist >>= 7;
1958 for (; code < D_CODES; code++) {
1959 G2.base_dist[code] = dist << 7;
1960 for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
1961 G2.dist_code[256 + dist++] = code;
1962 }
1963 }
1964 Assert(dist == 256, "ct_init: 256+dist != 512");
1965
1966
1967
1968
1969
1970
1971 n = 0;
1972 while (n <= 143) {
1973 G2.static_ltree[n++].Len = 8;
1974 G2.bl_count[8]++;
1975 }
1976 while (n <= 255) {
1977 G2.static_ltree[n++].Len = 9;
1978 G2.bl_count[9]++;
1979 }
1980 while (n <= 279) {
1981 G2.static_ltree[n++].Len = 7;
1982 G2.bl_count[7]++;
1983 }
1984 while (n <= 287) {
1985 G2.static_ltree[n++].Len = 8;
1986 G2.bl_count[8]++;
1987 }
1988
1989
1990
1991
1992 gen_codes((ct_data *) G2.static_ltree, L_CODES + 1);
1993
1994
1995 for (n = 0; n < D_CODES; n++) {
1996 G2.static_dtree[n].Len = 5;
1997 G2.static_dtree[n].Code = bi_reverse(n, 5);
1998 }
1999
2000
2001 init_block();
2002}
2003
2004
2005
2006
2007
2008
2009
2010static void zip(ulg time_stamp)
2011{
2012 ush deflate_flags = 0;
2013
2014 G1.outcnt = 0;
2015
2016
2017
2018
2019
2020 put_32bit(0x00088b1f);
2021 put_32bit(time_stamp);
2022
2023
2024 G1.crc = ~0;
2025
2026 bi_init();
2027 ct_init();
2028 lm_init(&deflate_flags);
2029
2030 put_8bit(deflate_flags);
2031 put_8bit(3);
2032
2033 deflate();
2034
2035
2036 put_32bit(~G1.crc);
2037 put_32bit(G1.isize);
2038
2039 flush_outbuf();
2040}
2041
2042
2043
2044static
2045IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM)
2046{
2047 struct stat s;
2048
2049
2050 G1.outcnt = 0;
2051#ifdef DEBUG
2052 G1.insize = 0;
2053#endif
2054 G1.isize = 0;
2055
2056
2057 memset(&G2, 0, sizeof(G2));
2058 G2.l_desc.dyn_tree = G2.dyn_ltree;
2059 G2.l_desc.static_tree = G2.static_ltree;
2060 G2.l_desc.extra_bits = extra_lbits;
2061 G2.l_desc.extra_base = LITERALS + 1;
2062 G2.l_desc.elems = L_CODES;
2063 G2.l_desc.max_length = MAX_BITS;
2064
2065 G2.d_desc.dyn_tree = G2.dyn_dtree;
2066 G2.d_desc.static_tree = G2.static_dtree;
2067 G2.d_desc.extra_bits = extra_dbits;
2068
2069 G2.d_desc.elems = D_CODES;
2070 G2.d_desc.max_length = MAX_BITS;
2071
2072 G2.bl_desc.dyn_tree = G2.bl_tree;
2073
2074 G2.bl_desc.extra_bits = extra_blbits,
2075
2076 G2.bl_desc.elems = BL_CODES;
2077 G2.bl_desc.max_length = MAX_BL_BITS;
2078
2079
2080 s.st_ctime = 0;
2081 fstat(STDIN_FILENO, &s);
2082 zip(s.st_ctime);
2083 return 0;
2084}
2085
2086#if ENABLE_FEATURE_GZIP_LONG_OPTIONS
2087static const char gzip_longopts[] ALIGN1 =
2088 "stdout\0" No_argument "c"
2089 "to-stdout\0" No_argument "c"
2090 "force\0" No_argument "f"
2091 "verbose\0" No_argument "v"
2092#if ENABLE_GUNZIP
2093 "decompress\0" No_argument "d"
2094 "uncompress\0" No_argument "d"
2095 "test\0" No_argument "t"
2096#endif
2097 "quiet\0" No_argument "q"
2098 "fast\0" No_argument "1"
2099 "best\0" No_argument "9"
2100 ;
2101#endif
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2118#if ENABLE_GUNZIP
2119int gzip_main(int argc, char **argv)
2120#else
2121int gzip_main(int argc UNUSED_PARAM, char **argv)
2122#endif
2123{
2124 unsigned opt;
2125
2126#if ENABLE_FEATURE_GZIP_LONG_OPTIONS
2127 applet_long_options = gzip_longopts;
2128#endif
2129
2130 opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "q123456789n");
2131#if ENABLE_GUNZIP
2132 if (opt & 0x18)
2133 return gunzip_main(argc, argv);
2134#endif
2135 option_mask32 &= 0x7;
2136
2137
2138
2139 argv += optind;
2140
2141 SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2))
2142 + sizeof(struct globals));
2143
2144
2145 ALLOC(uch, G1.l_buf, INBUFSIZ);
2146 ALLOC(uch, G1.outbuf, OUTBUFSIZ);
2147 ALLOC(ush, G1.d_buf, DIST_BUFSIZE);
2148 ALLOC(uch, G1.window, 2L * WSIZE);
2149 ALLOC(ush, G1.prev, 1L << BITS);
2150
2151
2152 global_crc32_table = crc32_filltable(NULL, 0);
2153
2154 return bbunpack(argv, pack_gzip, append_ext, "gz");
2155}
2156