File: huffc.c

package info (click to toggle)
dosemu-freedos 1%3A0.0.b9r5a%2Betch.1-0etch1
  • links: PTS
  • area: contrib
  • in suites: etch
  • size: 19,744 kB
  • ctags: 23,279
  • sloc: ansic: 143,864; asm: 20,397; makefile: 3,868; perl: 1,106; yacc: 690; sh: 553; pascal: 297; xml: 150; cpp: 67
file content (153 lines) | stat: -rw-r--r-- 3,255 bytes parent folder | download | duplicates (2)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*  FreeDOS Edit Help Compiler

    Part of the FreeDOS Project
    Originally part of D-Flat, by Dr. Dobbs Journal
    Modified by Joe Cosentino 2002.

*/

/* I N C L U D E S /////////////////////////////////////////////////////// */

#include "dflat.h"
#include "htree.h"

/* G L O B A L S ///////////////////////////////////////////////////////// */

extern struct htree *ht;
extern int root;
extern int treect;
static int lastchar='\n';
static int ct8;
static char out8;

/* P R O T O T Y P E S /////////////////////////////////////////////////// */

static void compress(FILE *, int, int);
static void outbit(FILE *, int);

/* F U N C T I O N S ///////////////////////////////////////////////////// */

static int fgetcx(FILE *fi)
{
    int c;

    /* Bypass comments */
    if ((c=fgetc(fi))==';' && lastchar=='\n')
        do
            {
            while (c != '\n' && c != EOF)
                c=fgetc(fi);

            }
        while (c==';');

    lastchar=c;
    return c;

}

/* Compress a character value into a bit stream */
static void compress(FILE *fo, int h, int child)
{
    if (ht[h].parent != -1)
        compress(fo, ht[h].parent, h);

    if (child)
        {
        if (child == ht[h].right)
            outbit(fo, 0);
        else if (child == ht[h].left)
            outbit(fo, 1);

        }

}

/* Collect and write bits to the compressed output file */
static void outbit(FILE *fo, int bit)
{
    if (ct8==8 || bit==-1)
        {
        while (ct8<8)
            {
            out8 <<= 1;
            ct8++;
            }

        fputc(out8, fo);
        ct8=0;
        }

    out8=(out8 << 1) | bit;
    ct8++;

}

void main(int argc, char *argv[])
{
    FILE *fi, *fo;
    int c;
    BYTECOUNTER bytectr = 0;

    if (argc < 3)
        {
        printf("Syntax: HUFFC infile outfile\n");
        exit(1);
        }

    if ((fi = fopen(argv[1], "rb")) == NULL)
        {
        printf("Cannot open %s\n", argv[1]);
        exit(1);
        }

    if ((fo = fopen(argv[2], "wb")) == NULL)
        {
        printf("Cannot open %s\n", argv[2]);
        fclose(fi);
        exit(1);
        }

    ht = calloc(256, sizeof(struct htree));

    /* Read the input file and count character frequency */
    while ((c = fgetcx(fi)) != EOF)
        {
        c &= 255;
        ht[c].cnt++;
        bytectr++;
        }

    /* Build the huffman tree */
    buildtree();

    /* Write the byte count to the output file */
    fwrite(&bytectr, sizeof bytectr, 1, fo);

    /* Write the tree count to the output file */
    fwrite(&treect, sizeof treect, 1, fo);

    /* Write the root offset to the output file */
    fwrite(&root, sizeof root, 1, fo);

    /* Write the tree to the output file */
    for (c=256;c<treect;c++)
        {
        int lf=ht[c].left,rt=ht[c].right;

        fwrite(&lf, sizeof lf, 1, fo);
        fwrite(&rt, sizeof rt, 1, fo);
        }

    /* Compress the file */
    fseek(fi, 0L, 0);
    while ((c = fgetcx(fi)) != EOF)
        compress(fo, (c & 255), 0);

    outbit(fo, -1);
    fclose(fi);
    fclose(fo);
    free(ht);
    exit(0);

}