|
faluco@133
|
1 |
/* compress.c -- Byte Pair Encoding compression */ |
|
faluco@133
|
2 |
/* Copyright 1996 Philip Gage */ |
|
faluco@133
|
3 |
|
|
faluco@133
|
4 |
/* This program appeared in the September 1997 issue of |
|
faluco@133
|
5 |
* C/C++ Users Journal. The original source code may still |
|
faluco@133
|
6 |
* be found at the web site of the magazine (www.cuj.com). |
|
faluco@133
|
7 |
* |
|
faluco@133
|
8 |
* It has been modified by me (Thiadmer Riemersma) to |
|
faluco@133
|
9 |
* compress only a section of the input file and to store |
|
faluco@133
|
10 |
* the compressed output along with the input as "C" strings. |
|
faluco@133
|
11 |
* |
|
faluco@133
|
12 |
* Compiling instructions: |
|
faluco@133
|
13 |
* Borland C++ 16-bit (large memory model is required): |
|
faluco@133
|
14 |
* bcc -ml scpack.c |
|
faluco@133
|
15 |
* |
|
faluco@133
|
16 |
* Watcom C/C++ 32-bit: |
|
faluco@133
|
17 |
* wcl386 scpack.c |
|
faluco@133
|
18 |
* |
|
faluco@133
|
19 |
* GNU C (Linux), 32-bit: |
|
faluco@133
|
20 |
* gcc scpack.c -o scpack |
|
faluco@133
|
21 |
*/ |
|
faluco@133
|
22 |
|
|
faluco@133
|
23 |
#include <assert.h> |
|
faluco@133
|
24 |
#include <limits.h> |
|
faluco@133
|
25 |
#include <stdio.h> |
|
faluco@133
|
26 |
#include <stdlib.h> |
|
faluco@133
|
27 |
#include <string.h> |
|
faluco@133
|
28 |
|
|
faluco@133
|
29 |
#if UINT_MAX > 0xFFFFU |
|
faluco@133
|
30 |
#define MAXSIZE 1024*1024L |
|
faluco@133
|
31 |
#else |
|
faluco@133
|
32 |
#define MAXSIZE UINT_MAX /* Input file buffer size */ |
|
faluco@133
|
33 |
#endif |
|
faluco@133
|
34 |
#define HASHSIZE 8192 /* Hash table size, power of 2 */ |
|
faluco@133
|
35 |
#define THRESHOLD 3 /* Increase for speed, min 3 */ |
|
faluco@133
|
36 |
|
|
faluco@133
|
37 |
#define START_TOKEN "#ifdef SCPACK" /* start reading the buffer here */ |
|
faluco@133
|
38 |
#define NAME_TOKEN "#define SCPACK_TABLE" |
|
faluco@133
|
39 |
#define SEP_TOKEN "#define SCPACK_SEPARATOR" |
|
faluco@133
|
40 |
#define TERM_TOKEN "#define SCPACK_TERMINATOR" |
|
faluco@133
|
41 |
#define TEMPFILE "~SCPACK.TMP" |
|
faluco@133
|
42 |
static char tablename[32+1] = "scpack_table"; |
|
faluco@133
|
43 |
static char separator[16]=","; |
|
faluco@133
|
44 |
static char terminator[16]=""; |
|
faluco@133
|
45 |
|
|
faluco@133
|
46 |
int compress(unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2]) |
|
faluco@133
|
47 |
{ |
|
faluco@133
|
48 |
unsigned char *left, *right, *count; |
|
faluco@133
|
49 |
unsigned char a, b, bestcount; |
|
faluco@133
|
50 |
unsigned i, j, index, bestindex, code=128; |
|
faluco@133
|
51 |
|
|
faluco@133
|
52 |
/* Dynamically allocate buffers and check for errors */ |
|
faluco@133
|
53 |
left = (unsigned char *)malloc(HASHSIZE); |
|
faluco@133
|
54 |
right = (unsigned char *)malloc(HASHSIZE); |
|
faluco@133
|
55 |
count = (unsigned char *)malloc(HASHSIZE); |
|
faluco@133
|
56 |
if (left==NULL || right==NULL || count==NULL) { |
|
faluco@133
|
57 |
printf("Error allocating memory\n"); |
|
faluco@133
|
58 |
exit(1); |
|
faluco@133
|
59 |
} |
|
faluco@133
|
60 |
|
|
faluco@133
|
61 |
/* Check for errors */ |
|
faluco@133
|
62 |
for (i=0; i<buffersize; i++) |
|
faluco@133
|
63 |
if (buffer[i] > 127) { |
|
faluco@133
|
64 |
printf("This program works only on text files (7-bit ASCII)\n"); |
|
faluco@133
|
65 |
exit(1); |
|
faluco@133
|
66 |
} |
|
faluco@133
|
67 |
|
|
faluco@133
|
68 |
memset(pairtable, 0, 128*2*sizeof(char)); |
|
faluco@133
|
69 |
|
|
faluco@133
|
70 |
do { /* Replace frequent pairs with bytes 128..255 */ |
|
faluco@133
|
71 |
|
|
faluco@133
|
72 |
/* Enter counts of all byte pairs into hash table */ |
|
faluco@133
|
73 |
memset(count,0,HASHSIZE); |
|
faluco@133
|
74 |
for (i=0; i<buffersize-1; i++) { |
|
faluco@133
|
75 |
a = buffer[i]; |
|
faluco@133
|
76 |
b = buffer[i+1]; |
|
faluco@133
|
77 |
/* ignore any pair with a '\0' */ |
|
faluco@133
|
78 |
if (a == 0 || b == 0) |
|
faluco@133
|
79 |
continue; |
|
faluco@133
|
80 |
index = (a ^ (b << 6)) & (HASHSIZE-1); |
|
faluco@133
|
81 |
while ((left[index] != a || right[index] != b) && |
|
faluco@133
|
82 |
count[index] != 0) |
|
faluco@133
|
83 |
index = (index + 1) & (HASHSIZE-1); |
|
faluco@133
|
84 |
left[index] = a; |
|
faluco@133
|
85 |
right[index] = b; |
|
faluco@133
|
86 |
if (count[index] < 255) |
|
faluco@133
|
87 |
count[index] += (unsigned char)1; |
|
faluco@133
|
88 |
} |
|
faluco@133
|
89 |
|
|
faluco@133
|
90 |
/* Search hash table for most frequent pair */ |
|
faluco@133
|
91 |
bestcount = THRESHOLD - 1; |
|
faluco@133
|
92 |
for (i=0; i<HASHSIZE; i++) { |
|
faluco@133
|
93 |
if (count[i] > bestcount) { |
|
faluco@133
|
94 |
bestcount = count[i]; |
|
faluco@133
|
95 |
bestindex = i; |
|
faluco@133
|
96 |
} |
|
faluco@133
|
97 |
} |
|
faluco@133
|
98 |
|
|
faluco@133
|
99 |
/* Compress if enough occurrences of pair */ |
|
faluco@133
|
100 |
if (bestcount >= THRESHOLD) { |
|
faluco@133
|
101 |
|
|
faluco@133
|
102 |
/* Add pair to table using code as index */ |
|
faluco@133
|
103 |
a = pairtable[code-128][0] = left[bestindex]; |
|
faluco@133
|
104 |
b = pairtable[code-128][1] = right[bestindex]; |
|
faluco@133
|
105 |
|
|
faluco@133
|
106 |
/* Replace all pair occurrences with unused byte */ |
|
faluco@133
|
107 |
for (i=0, j=0; i<buffersize; i++, j++) |
|
faluco@133
|
108 |
if (a == buffer[i] && b == buffer[i+1]) { |
|
faluco@133
|
109 |
buffer[j] = (unsigned char)code; |
|
faluco@133
|
110 |
++i; |
|
faluco@133
|
111 |
} |
|
faluco@133
|
112 |
else |
|
faluco@133
|
113 |
buffer[j] = buffer[i]; |
|
faluco@133
|
114 |
buffersize = j; |
|
faluco@133
|
115 |
} |
|
faluco@133
|
116 |
else |
|
faluco@133
|
117 |
break; |
|
faluco@133
|
118 |
} while (++code < 255); |
|
faluco@133
|
119 |
|
|
faluco@133
|
120 |
/* done */ |
|
faluco@133
|
121 |
free(left); free(right); free(count); |
|
faluco@133
|
122 |
return buffersize; /* return adjusted buffersize */ |
|
faluco@133
|
123 |
} |
|
faluco@133
|
124 |
|
|
faluco@133
|
125 |
static int strmatch(char *str, char *token, int *indent) |
|
faluco@133
|
126 |
{ |
|
faluco@133
|
127 |
int i = 0; |
|
faluco@133
|
128 |
|
|
faluco@133
|
129 |
/* skip whitespace */ |
|
faluco@133
|
130 |
while (*str==' ' || *str=='\t') { |
|
faluco@133
|
131 |
str++; |
|
faluco@133
|
132 |
i++; |
|
faluco@133
|
133 |
} /* while */ |
|
faluco@133
|
134 |
if (strncmp(str,token,strlen(token))!=0) |
|
faluco@133
|
135 |
return 0; |
|
faluco@133
|
136 |
if (indent != NULL) |
|
faluco@133
|
137 |
*indent = i; |
|
faluco@133
|
138 |
return 1; |
|
faluco@133
|
139 |
} |
|
faluco@133
|
140 |
|
|
faluco@133
|
141 |
static void check_if(char *str,int linenr) |
|
faluco@133
|
142 |
{ |
|
faluco@133
|
143 |
if (strmatch(str,"#if",NULL)) { |
|
faluco@133
|
144 |
printf("Error: \"#if...\" preprocessor statement should not be in SCPACK section " |
|
faluco@133
|
145 |
"(line %d)\n", linenr); |
|
faluco@133
|
146 |
exit(1); |
|
faluco@133
|
147 |
} /* if */ |
|
faluco@133
|
148 |
} |
|
faluco@133
|
149 |
|
|
faluco@133
|
150 |
static int check_tablename(char *str) |
|
faluco@133
|
151 |
{ |
|
faluco@133
|
152 |
int i; |
|
faluco@133
|
153 |
|
|
faluco@133
|
154 |
if (strmatch(str,NAME_TOKEN,NULL)) { |
|
faluco@133
|
155 |
str += strlen(NAME_TOKEN); |
|
faluco@133
|
156 |
while (*str==' ' || *str=='\t') |
|
faluco@133
|
157 |
str++; |
|
faluco@133
|
158 |
for (i=0; i<(sizeof tablename - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++) |
|
faluco@133
|
159 |
tablename[i] = *str; |
|
faluco@133
|
160 |
tablename[i] = '\0'; |
|
faluco@133
|
161 |
return 1; |
|
faluco@133
|
162 |
} /* if */ |
|
faluco@133
|
163 |
return 0; |
|
faluco@133
|
164 |
} |
|
faluco@133
|
165 |
|
|
faluco@133
|
166 |
static int check_separator(char *str) |
|
faluco@133
|
167 |
{ |
|
faluco@133
|
168 |
int i; |
|
faluco@133
|
169 |
|
|
faluco@133
|
170 |
if (strmatch(str,SEP_TOKEN,NULL)) { |
|
faluco@133
|
171 |
str += strlen(SEP_TOKEN); |
|
faluco@133
|
172 |
while (*str==' ' || *str=='\t') |
|
faluco@133
|
173 |
str++; |
|
faluco@133
|
174 |
for (i=0; i<(sizeof separator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++) |
|
faluco@133
|
175 |
separator[i] = *str; |
|
faluco@133
|
176 |
separator[i] = '\0'; |
|
faluco@133
|
177 |
return 1; |
|
faluco@133
|
178 |
} /* if */ |
|
faluco@133
|
179 |
|
|
faluco@133
|
180 |
if (strmatch(str,TERM_TOKEN,NULL)) { |
|
faluco@133
|
181 |
str += strlen(TERM_TOKEN); |
|
faluco@133
|
182 |
while (*str==' ' || *str=='\t') |
|
faluco@133
|
183 |
str++; |
|
faluco@133
|
184 |
for (i=0; i<(sizeof terminator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++) |
|
faluco@133
|
185 |
terminator[i] = *str; |
|
faluco@133
|
186 |
terminator[i] = '\0'; |
|
faluco@133
|
187 |
return 1; |
|
faluco@133
|
188 |
} /* if */ |
|
faluco@133
|
189 |
|
|
faluco@133
|
190 |
return 0; |
|
faluco@133
|
191 |
} |
|
faluco@133
|
192 |
|
|
faluco@133
|
193 |
/* readbuffer |
|
faluco@133
|
194 |
* Reads in the input file and stores all strings in the |
|
faluco@133
|
195 |
* section between "#ifdef SCPACK" and "#else" in a buffer. |
|
faluco@133
|
196 |
* Only text that is between double quotes is added to the |
|
faluco@133
|
197 |
* buffer; the \" escape code is handled. Multiple strings |
|
faluco@133
|
198 |
* on one line are handled. |
|
faluco@133
|
199 |
*/ |
|
faluco@133
|
200 |
unsigned readbuffer(FILE *input, unsigned char *buffer) |
|
faluco@133
|
201 |
{ |
|
faluco@133
|
202 |
char str[256]; |
|
faluco@133
|
203 |
unsigned buffersize; |
|
faluco@133
|
204 |
int i,linenr; |
|
faluco@133
|
205 |
|
|
faluco@133
|
206 |
linenr=0; |
|
faluco@133
|
207 |
buffersize=0; |
|
faluco@133
|
208 |
|
|
faluco@133
|
209 |
rewind(input); |
|
faluco@133
|
210 |
while (!feof(input)) { |
|
faluco@133
|
211 |
while (fgets(str,sizeof str,input)!=NULL) { |
|
faluco@133
|
212 |
linenr++; |
|
faluco@133
|
213 |
check_tablename(str); |
|
faluco@133
|
214 |
check_separator(str); |
|
faluco@133
|
215 |
if (strmatch(str,START_TOKEN,NULL)) |
|
faluco@133
|
216 |
break; |
|
faluco@133
|
217 |
} /* while */ |
|
faluco@133
|
218 |
if (!strmatch(str,START_TOKEN,NULL)) |
|
faluco@133
|
219 |
return buffersize; /* no (more) section found, quit */ |
|
faluco@133
|
220 |
|
|
faluco@133
|
221 |
while (fgets(str,sizeof str,input)!=NULL) { |
|
faluco@133
|
222 |
linenr++; |
|
faluco@133
|
223 |
check_if(str,linenr); |
|
faluco@133
|
224 |
if (check_tablename(str)) |
|
faluco@133
|
225 |
printf("Error: table name definition should not be in SCPACK section (line %d)\n", linenr); |
|
faluco@133
|
226 |
check_separator(str); |
|
faluco@133
|
227 |
if (strmatch(str,"#else",NULL)) |
|
faluco@133
|
228 |
break; /* done */ |
|
faluco@133
|
229 |
/* add to the buffer only what is between double quotes */ |
|
faluco@133
|
230 |
i=0; |
|
faluco@133
|
231 |
do { |
|
faluco@133
|
232 |
while (str[i]!='\0' && str[i]!='"') |
|
faluco@133
|
233 |
i++; |
|
faluco@133
|
234 |
if (str[i]=='"') { |
|
faluco@133
|
235 |
/* we are in a string */ |
|
faluco@133
|
236 |
i++; |
|
faluco@133
|
237 |
while (str[i]!='\0' && str[i]!='"') { |
|
faluco@133
|
238 |
/* handle escape sequences */ |
|
faluco@133
|
239 |
if (str[i]=='\\') { |
|
faluco@133
|
240 |
i++; |
|
faluco@133
|
241 |
switch (str[i]) { |
|
faluco@133
|
242 |
case 'a': /* alarm */ |
|
faluco@133
|
243 |
buffer[buffersize++]='\a'; |
|
faluco@133
|
244 |
i++; |
|
faluco@133
|
245 |
break; |
|
faluco@133
|
246 |
case 'b': /* backspace */ |
|
faluco@133
|
247 |
buffer[buffersize++]='\b'; |
|
faluco@133
|
248 |
i++; |
|
faluco@133
|
249 |
break; |
|
faluco@133
|
250 |
case 'f': /* form feed */ |
|
faluco@133
|
251 |
buffer[buffersize++]='\f'; |
|
faluco@133
|
252 |
i++; |
|
faluco@133
|
253 |
break; |
|
faluco@133
|
254 |
case 'n': /* newline */ |
|
faluco@133
|
255 |
buffer[buffersize++]='\n'; |
|
faluco@133
|
256 |
i++; |
|
faluco@133
|
257 |
break; |
|
faluco@133
|
258 |
case 'r': /* carriage return */ |
|
faluco@133
|
259 |
buffer[buffersize++]='\n'; |
|
faluco@133
|
260 |
i++; |
|
faluco@133
|
261 |
break; |
|
faluco@133
|
262 |
case 't': /* tab */ |
|
faluco@133
|
263 |
buffer[buffersize++]='\t'; |
|
faluco@133
|
264 |
i++; |
|
faluco@133
|
265 |
break; |
|
faluco@133
|
266 |
case '\'': |
|
faluco@133
|
267 |
buffer[buffersize++]='\''; |
|
faluco@133
|
268 |
i++; |
|
faluco@133
|
269 |
break; |
|
faluco@133
|
270 |
case '"': |
|
faluco@133
|
271 |
buffer[buffersize++]='"'; |
|
faluco@133
|
272 |
i++; |
|
faluco@133
|
273 |
break; |
|
faluco@133
|
274 |
default: |
|
faluco@133
|
275 |
// ??? octal character code escapes and hexadecimal escapes |
|
faluco@133
|
276 |
// not supported |
|
faluco@133
|
277 |
printf("Unknown escape sequence '\\%c' on line %d\n", |
|
faluco@133
|
278 |
str[i], linenr); |
|
faluco@133
|
279 |
} /* switch */ |
|
faluco@133
|
280 |
} else { |
|
faluco@133
|
281 |
buffer[buffersize++]=str[i++]; |
|
faluco@133
|
282 |
} /* if */ |
|
faluco@133
|
283 |
} /* while */ |
|
faluco@133
|
284 |
if (str[i]=='"') { |
|
faluco@133
|
285 |
buffer[buffersize++]='\0'; /* terminate each string */ |
|
faluco@133
|
286 |
i++; |
|
faluco@133
|
287 |
} else { |
|
faluco@133
|
288 |
printf("Error: unterminated string on line %d\n",linenr); |
|
faluco@133
|
289 |
} /* if */ |
|
faluco@133
|
290 |
} /* if */ |
|
faluco@133
|
291 |
} while (str[i]!='\0'); |
|
faluco@133
|
292 |
} /* while - in SCPACK section */ |
|
faluco@133
|
293 |
/* put in another '\0' to terminate the section */ |
|
faluco@133
|
294 |
buffer[buffersize++]='\0'; |
|
faluco@133
|
295 |
} /* while - !feof(input) */ |
|
faluco@133
|
296 |
return buffersize; |
|
faluco@133
|
297 |
} |
|
faluco@133
|
298 |
|
|
faluco@133
|
299 |
static void write_pairtable(FILE *output, unsigned char pairtable[128][2], char *tablename) |
|
faluco@133
|
300 |
{ |
|
faluco@133
|
301 |
int i; |
|
faluco@133
|
302 |
|
|
faluco@133
|
303 |
/* dump the pair table */ |
|
faluco@133
|
304 |
fprintf(output, "/*-*SCPACK start of pair table, do not change or remove this line */\n"); |
|
faluco@133
|
305 |
fprintf(output, "unsigned char %s[][2] = {", tablename); |
|
faluco@133
|
306 |
for (i=0; i<128 && pairtable[i][0]!=0 && pairtable[i][1]!=0; i++) { |
|
faluco@133
|
307 |
if ((i % 16)==0) |
|
faluco@133
|
308 |
fprintf(output, "\n "); |
|
faluco@133
|
309 |
else |
|
faluco@133
|
310 |
fprintf(output, " "); |
|
faluco@133
|
311 |
fprintf(output, "{%d,%d}", pairtable[i][0], pairtable[i][1]); |
|
faluco@133
|
312 |
/* check if something follows this pair */ |
|
faluco@133
|
313 |
if (i+1<128 && pairtable[i+1][0]!=0 && pairtable[i+1][1]!=0) |
|
faluco@133
|
314 |
fprintf(output, ","); |
|
faluco@133
|
315 |
} /* for */ |
|
faluco@133
|
316 |
fprintf(output, "\n};\n"); |
|
faluco@133
|
317 |
fprintf(output, "/*-*SCPACK end of pair table, do not change or remove this line */\n"); |
|
faluco@133
|
318 |
} |
|
faluco@133
|
319 |
|
|
faluco@133
|
320 |
void writefile(FILE *input, FILE *output, unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2]) |
|
faluco@133
|
321 |
{ |
|
faluco@133
|
322 |
char str[256]; |
|
faluco@133
|
323 |
int insection, indent, needseparator; |
|
faluco@133
|
324 |
unsigned char *bufptr; |
|
faluco@133
|
325 |
|
|
faluco@133
|
326 |
bufptr = buffer; |
|
faluco@133
|
327 |
insection = 0; |
|
faluco@133
|
328 |
|
|
faluco@133
|
329 |
rewind(input); |
|
faluco@133
|
330 |
while (!feof(input)) { |
|
faluco@133
|
331 |
while (fgets(str,sizeof str,input)!=NULL) { |
|
faluco@133
|
332 |
fprintf(output,"%s",str); |
|
faluco@133
|
333 |
if (check_tablename(str)) { |
|
faluco@133
|
334 |
write_pairtable(output, pairtable, tablename); |
|
faluco@133
|
335 |
/* strip an existing pair table from the file */ |
|
faluco@133
|
336 |
if (fgets(str,sizeof str,input)!=NULL) { |
|
faluco@133
|
337 |
if (strmatch(str,"/*-*SCPACK",NULL)) { |
|
faluco@133
|
338 |
while (fgets(str,sizeof str,input)!=NULL) |
|
faluco@133
|
339 |
if (strmatch(str,"/*-*SCPACK",NULL)) |
|
faluco@133
|
340 |
break; |
|
faluco@133
|
341 |
} else { |
|
faluco@133
|
342 |
fprintf(output,"%s",str); |
|
faluco@133
|
343 |
} /* if */ |
|
faluco@133
|
344 |
} /* if */ |
|
faluco@133
|
345 |
} /* if */ |
|
faluco@133
|
346 |
if (strmatch(str,START_TOKEN,NULL)) |
|
faluco@133
|
347 |
insection = 1; |
|
faluco@133
|
348 |
if (insection && strmatch(str,"#else",NULL)) |
|
faluco@133
|
349 |
break; |
|
faluco@133
|
350 |
} /* while */ |
|
faluco@133
|
351 |
if (!strmatch(str,"#else",&indent)) |
|
faluco@133
|
352 |
return; /* no (more) section found, quit */ |
|
faluco@133
|
353 |
insection=0; |
|
faluco@133
|
354 |
|
|
faluco@133
|
355 |
/* dump the buffer as strings, separated with commas */ |
|
faluco@133
|
356 |
needseparator = 0; |
|
faluco@133
|
357 |
while (*bufptr != '\0') { |
|
faluco@133
|
358 |
assert((unsigned)(bufptr-buffer) < buffersize); |
|
faluco@133
|
359 |
if (needseparator) |
|
faluco@133
|
360 |
fprintf(output, "%s\n",separator); |
|
faluco@133
|
361 |
fprintf(output, "%*c\"",indent+2,' '); |
|
faluco@133
|
362 |
/* loop over string */ |
|
faluco@133
|
363 |
while (*bufptr != '\0') { |
|
faluco@133
|
364 |
if (*bufptr<' ' || *bufptr >= 128 || *bufptr == '"' || *bufptr == '\\') |
|
faluco@133
|
365 |
fprintf(output, "\\%03o", *bufptr); |
|
faluco@133
|
366 |
else |
|
faluco@133
|
367 |
fprintf(output, "%c", *bufptr); |
|
faluco@133
|
368 |
bufptr++; |
|
faluco@133
|
369 |
} /* while */ |
|
faluco@133
|
370 |
fprintf(output, "\""); |
|
faluco@133
|
371 |
needseparator = 1; |
|
faluco@133
|
372 |
bufptr++; /* skip '\0' */ |
|
faluco@133
|
373 |
} /* while */ |
|
faluco@133
|
374 |
fprintf(output, "%s\n",terminator); |
|
faluco@133
|
375 |
bufptr++; |
|
faluco@133
|
376 |
|
|
faluco@133
|
377 |
/* skip the input file until the #endif section */ |
|
faluco@133
|
378 |
while (fgets(str,sizeof str,input)!=NULL) { |
|
faluco@133
|
379 |
if (strmatch(str,"#endif",NULL)) { |
|
faluco@133
|
380 |
fprintf(output,"%s",str); |
|
faluco@133
|
381 |
break; /* done */ |
|
faluco@133
|
382 |
} /* if */ |
|
faluco@133
|
383 |
} /* while */ |
|
faluco@133
|
384 |
} /* while - !feof(input) */ |
|
faluco@133
|
385 |
} |
|
faluco@133
|
386 |
|
|
faluco@133
|
387 |
static void usage(void) |
|
faluco@133
|
388 |
{ |
|
faluco@133
|
389 |
printf("Usage: scpack <filename> [output file]\n"); |
|
faluco@133
|
390 |
exit(1); |
|
faluco@133
|
391 |
} |
|
faluco@133
|
392 |
|
|
faluco@133
|
393 |
int main(int argc, char **argv) |
|
faluco@133
|
394 |
{ |
|
faluco@133
|
395 |
FILE *in, *out; |
|
faluco@133
|
396 |
unsigned char *buffer; |
|
faluco@133
|
397 |
unsigned buffersize, orgbuffersize; |
|
faluco@133
|
398 |
unsigned char pairtable[128][2]; |
|
faluco@133
|
399 |
|
|
faluco@133
|
400 |
if (argc < 2 || argc > 3) |
|
faluco@133
|
401 |
usage(); |
|
faluco@133
|
402 |
if ((in=fopen(argv[1],"rt"))==NULL) { |
|
faluco@133
|
403 |
printf("SCPACK: error opening input %s\n",argv[1]); |
|
faluco@133
|
404 |
usage(); |
|
faluco@133
|
405 |
} /* if */ |
|
faluco@133
|
406 |
if (argc == 2) { |
|
faluco@133
|
407 |
if ((out=fopen(TEMPFILE,"wt"))==NULL) { |
|
faluco@133
|
408 |
printf("SCPACK: error opening temporary file %s\n",TEMPFILE); |
|
faluco@133
|
409 |
usage(); |
|
faluco@133
|
410 |
} /* if */ |
|
faluco@133
|
411 |
} else { |
|
faluco@133
|
412 |
if ((out=fopen(argv[2],"wt"))==NULL) { |
|
faluco@133
|
413 |
printf("SCPACK: error opening output file %s\n",argv[2]); |
|
faluco@133
|
414 |
usage(); |
|
faluco@133
|
415 |
} /* if */ |
|
faluco@133
|
416 |
} /* if */ |
|
faluco@133
|
417 |
|
|
faluco@133
|
418 |
buffer = (unsigned char *)malloc(MAXSIZE); |
|
faluco@133
|
419 |
if (buffer == NULL) { |
|
faluco@133
|
420 |
printf("SCPACK: error allocating memory\n"); |
|
faluco@133
|
421 |
return 1; |
|
faluco@133
|
422 |
} /* if */ |
|
faluco@133
|
423 |
/* 1. read the buffer |
|
faluco@133
|
424 |
* 2. compress the buffer |
|
faluco@133
|
425 |
* 3. copy the file, insert the compressed buffer |
|
faluco@133
|
426 |
*/ |
|
faluco@133
|
427 |
buffersize = readbuffer(in, buffer); |
|
faluco@133
|
428 |
orgbuffersize = buffersize; |
|
faluco@133
|
429 |
if (buffersize > 0) { |
|
faluco@133
|
430 |
buffersize = compress(buffer, buffersize, pairtable); |
|
faluco@133
|
431 |
writefile(in, out, buffer, buffersize, pairtable); |
|
faluco@133
|
432 |
printf("SCPACK: compression ratio: %ld%% (%d -> %d)\n", |
|
faluco@133
|
433 |
100L-(100L*buffersize)/orgbuffersize, orgbuffersize, buffersize); |
|
faluco@133
|
434 |
} else { |
|
faluco@133
|
435 |
printf("SCPACK: no SCPACK section found, nothing to do\n"); |
|
faluco@133
|
436 |
} /* if */ |
|
faluco@133
|
437 |
fclose(out); |
|
faluco@133
|
438 |
fclose(in); |
|
faluco@133
|
439 |
/* let the new file replace the old file */ |
|
faluco@133
|
440 |
if (buffersize == 0) { |
|
faluco@133
|
441 |
if (argc == 2) |
|
faluco@133
|
442 |
remove(TEMPFILE); |
|
faluco@133
|
443 |
else |
|
faluco@133
|
444 |
remove(argv[2]); |
|
faluco@133
|
445 |
} else if (argc == 2) { |
|
faluco@133
|
446 |
remove(argv[1]); |
|
faluco@133
|
447 |
rename(TEMPFILE,argv[1]); |
|
faluco@133
|
448 |
} /* if */ |
|
faluco@133
|
449 |
return 0; |
|
faluco@133
|
450 |
} |