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