DPRINT->DPRINT1 in key places (when something fails we shouldn't keep silence).
[reactos.git] / rosapps / dflat32 / huffc.c
1 /* ------------------- huffc.c -------------------- */
2
3 #include "dflat.h"
4 #include "htree.h"
5
6 extern struct DfHTree *ht;
7 extern int root;
8 extern int treect;
9 static int lastchar = '\n';
10
11 static void compress(FILE *, int, int);
12 static void outbit(FILE *fo, int bit);
13
14 static int fgetcx(FILE *fi)
15 {
16 int c;
17
18 /* ------- bypass comments ------- */
19 if ((c = fgetc(fi)) == ';' && lastchar == '\n')
20 do {
21 while (c != '\n' && c != EOF)
22 c = fgetc(fi);
23 } while (c == ';');
24 lastchar = c;
25 return c;
26 }
27
28 void main(int argc, char *argv[])
29 {
30 FILE *fi, *fo;
31 int c;
32 DF_BYTECOUNTER bytectr = 0;
33
34 if (argc < 3) {
35 printf("\nusage: huffc infile outfile");
36 exit(1);
37 }
38
39 if ((fi = fopen(argv[1], "rb")) == NULL) {
40 printf("\nCannot open %s", argv[1]);
41 exit(1);
42 }
43 if ((fo = fopen(argv[2], "wb")) == NULL) {
44 printf("\nCannot open %s", argv[2]);
45 fclose(fi);
46 exit(1);
47 }
48
49 ht = calloc(256, sizeof(struct DfHTree));
50
51 /* - read the input file and count character frequency - */
52 while ((c = fgetcx(fi)) != EOF) {
53 c &= 255;
54 ht[c].cnt++;
55 bytectr++;
56 }
57
58 /* ---- build the huffman tree ---- */
59 DfBuildTree();
60
61 /* --- write the byte count to the output file --- */
62 fwrite(&bytectr, sizeof bytectr, 1, fo);
63
64 /* --- write the tree count to the output file --- */
65 fwrite(&treect, sizeof treect, 1, fo);
66
67 /* --- write the root offset to the output file --- */
68 fwrite(&root, sizeof root, 1, fo);
69
70 /* -- write the tree to the output file -- */
71 for (c = 256; c < treect; c++) {
72 int lf = ht[c].left;
73 int rt = ht[c].right;
74 fwrite(&lf, sizeof lf, 1, fo);
75 fwrite(&rt, sizeof rt, 1, fo);
76 }
77
78 /* ------ compress the file ------ */
79 fseek(fi, 0L, 0);
80 while ((c = fgetcx(fi)) != EOF)
81 compress(fo, (c & 255), 0);
82 outbit(fo, -1);
83 fclose(fi);
84 fclose(fo);
85 free(ht);
86 exit(0);
87 }
88
89 /* ---- compress a character value into a bit stream ---- */
90 static void compress(FILE *fo, int h, int child)
91 {
92 if (ht[h].parent != -1)
93 compress(fo, ht[h].parent, h);
94 if (child) {
95 if (child == ht[h].right)
96 outbit(fo, 0);
97 else if (child == ht[h].left)
98 outbit(fo, 1);
99 }
100 }
101
102 static char out8;
103 static int ct8;
104
105 /* -- collect and write bits to the compressed output file -- */
106 static void outbit(FILE *fo, int bit)
107 {
108 if (ct8 == 8 || bit == -1) {
109 while (ct8 < 8) {
110 out8 <<= 1;
111 ct8++;
112 }
113 fputc(out8, fo);
114 ct8 = 0;
115 }
116 out8 = (out8 << 1) | bit;
117 ct8++;
118 }