OSDN Git Service

4c38dda4655a2e485524351705919c4bb2d36ca3
[lha/lha.git] / src / crcio.c
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX                                                                                                                         */
3 /*                              crcio.c -- crc input / output                                                           */
4 /*                                                                                                                                                      */
5 /*              Modified                        Nobutaka Watazaki                                                       */
6 /*                                                                                                                                                      */
7 /*      Ver. 1.14       Source All chagned                              1995.01.14      N.Watazaki              */
8 /* ------------------------------------------------------------------------ */
9 #include "lha.h"
10
11 /* ------------------------------------------------------------------------ */
12 static unsigned short crctable[UCHAR_MAX + 1];
13 static unsigned char subbitbuf, bitcount;
14 #ifdef EUC
15 static int      putc_euc_cache;
16 #endif
17 static int      getc_euc_cache;
18
19 /* ------------------------------------------------------------------------ */
20 void
21 make_crctable( /* void */ )
22 {
23         unsigned int    i, j, r;
24
25         for (i = 0; i <= UCHAR_MAX; i++) {
26                 r = i;
27                 for (j = 0; j < CHAR_BIT; j++)
28                         if (r & 1)
29                                 r = (r >> 1) ^ CRCPOLY;
30                         else
31                                 r >>= 1;
32                 crctable[i] = r;
33         }
34 }
35
36 /* ------------------------------------------------------------------------ */
37 #ifdef NEED_INCREMENTAL_INDICATOR
38 static void
39 put_indicator(count)
40         long int        count;
41 {
42         if (!quiet && indicator_threshold) {
43                 while (count > indicator_count) {
44                         putchar('o');
45                         fflush(stdout);
46                         indicator_count += indicator_threshold;
47                 }
48         }
49 }
50 #endif
51
52 /* ------------------------------------------------------------------------ */
53 unsigned short
54 calccrc(p, n)
55         unsigned char  *p;
56         unsigned int    n;
57 {
58         reading_size += n;
59 #ifdef NEED_INCREMENTAL_INDICATOR
60         put_indicator(reading_size);
61 #endif
62         while (n-- > 0)
63                 UPDATE_CRC(*p++);
64         return crc;
65 }
66
67 /* ------------------------------------------------------------------------ */
68 void
69 fillbuf(n)                      /* Shift bitbuf n bits left, read n bits */
70         unsigned char   n;
71 {
72         while (n > bitcount) {
73                 n -= bitcount;
74                 bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount));
75                 if (compsize != 0) {
76                         compsize--;
77                         subbitbuf = (unsigned char) getc(infile);
78                 }
79                 else
80                         subbitbuf = 0;
81                 bitcount = CHAR_BIT;
82         }
83         bitcount -= n;
84         bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n));
85         subbitbuf <<= n;
86 }
87
88 /* ------------------------------------------------------------------------ */
89 unsigned short
90 getbits(n)
91         unsigned char   n;
92 {
93         unsigned short  x;
94
95         x = bitbuf >> (2 * CHAR_BIT - n);
96         fillbuf(n);
97         return x;
98 }
99
100 /* ------------------------------------------------------------------------ */
101 void
102 putcode(n, x)                   /* Write rightmost n bits of x */
103         unsigned char   n;
104         unsigned short  x;
105 {
106         while (n >= bitcount) {
107                 n -= bitcount;
108                 subbitbuf += x >> (USHRT_BIT - bitcount);
109                 x <<= bitcount;
110                 if (compsize < origsize) {
111             if (fwrite(&subbitbuf, 1, 1, outfile) == 0) {
112                                 /* fileerror(WTERR, outfile); */
113                             fatal_error("Write error in crcio.c(putcode)\n");
114                                 /* exit(errno); */
115                         }
116                         compsize++;
117                 }
118                 else
119                         unpackable = 1;
120                 subbitbuf = 0;
121                 bitcount = CHAR_BIT;
122         }
123         subbitbuf += x >> (USHRT_BIT - bitcount);
124         bitcount -= n;
125 }
126
127 /* ------------------------------------------------------------------------ */
128 void
129 putbits(n, x)                   /* Write rightmost n bits of x */
130         unsigned char   n;
131         unsigned short  x;
132 {
133         x <<= USHRT_BIT - n;
134         while (n >= bitcount) {
135                 n -= bitcount;
136                 subbitbuf += x >> (USHRT_BIT - bitcount);
137                 x <<= bitcount;
138                 if (compsize < origsize) {
139             if (fwrite(&subbitbuf, 1, 1, outfile) == 0) {
140                                 /* fileerror(WTERR, outfile); */
141                             fatal_error("Write error in crcio.c(putbits)\n");
142                                 /* exit(errno); */
143                         }
144                         compsize++;
145                 }
146                 else
147                         unpackable = 1;
148                 subbitbuf = 0;
149                 bitcount = CHAR_BIT;
150         }
151         subbitbuf += x >> (USHRT_BIT - bitcount);
152         bitcount -= n;
153 }
154
155 /* ------------------------------------------------------------------------ */
156 int
157 fread_crc(p, n, fp)
158         unsigned char  *p;
159         int             n;
160         FILE           *fp;
161 {
162         if (text_mode)
163                 n = fread_txt(p, n, fp);
164         else
165                 n = fread(p, 1, n, fp);
166
167         calccrc(p, n);
168         return n;
169 }
170
171 /* ------------------------------------------------------------------------ */
172 void
173 fwrite_crc(p, n, fp)
174         unsigned char  *p;
175         int             n;
176         FILE           *fp;
177 {
178         calccrc(p, n);
179         if (verify_mode)
180                 return;
181
182         if (fp) {
183                 if (text_mode) {
184                         if (fwrite_txt(p, n, fp))
185                                 fatal_error("File write error\n");
186                 }
187                 else {
188                         if (fwrite(p, 1, n, fp) < n)
189                                 fatal_error("File write error\n");
190                 }
191         }
192 }
193
194 /* ------------------------------------------------------------------------ */
195 void
196 init_code_cache( /* void */ )
197 {                               /* called from copyfile() in util.c */
198 #ifdef EUC
199         putc_euc_cache = EOF;
200 #endif
201         getc_euc_cache = EOF;
202 }
203
204 void
205 init_getbits( /* void */ )
206 {
207         bitbuf = 0;
208         subbitbuf = 0;
209         bitcount = 0;
210         fillbuf(2 * CHAR_BIT);
211 #ifdef EUC
212         putc_euc_cache = EOF;
213 #endif
214 }
215
216 /* ------------------------------------------------------------------------ */
217 void
218 init_putbits( /* void */ )
219 {
220         bitcount = CHAR_BIT;
221         subbitbuf = 0;
222         getc_euc_cache = EOF;
223 }
224
225 /* ------------------------------------------------------------------------ */
226 #ifdef EUC
227 void
228 putc_euc(c, fd)
229         int             c;
230         FILE           *fd;
231 {
232         int             d;
233
234         if (putc_euc_cache == EOF) {
235                 if (!euc_mode || c < 0x81 || c > 0xFC) {
236                         putc(c, fd);
237                         return;
238                 }
239                 if (c >= 0xA0 && c < 0xE0) {
240                         putc(0x8E, fd); /* single shift */
241                         putc(c, fd);
242                         return;
243                 }
244                 putc_euc_cache = c;     /* save first byte */
245                 return;
246         }
247         d = putc_euc_cache;
248         putc_euc_cache = EOF;
249         if (d >= 0xA0)
250                 d -= 0xE0 - 0xA0;
251         if (c > 0x9E) {
252                 c = c - 0x9F + 0x21;
253                 d = (d - 0x81) * 2 + 0x22;
254         }
255         else {
256                 if (c > 0x7E)
257                         c--;
258                 c -= 0x1F;
259                 d = (d - 0x81) * 2 + 0x21;
260         }
261         putc(0x80 | d, fd);
262         putc(0x80 | c, fd);
263 }
264 #endif
265
266 /* ------------------------------------------------------------------------ */
267 int
268 fwrite_txt(p, n, fp)
269         unsigned char  *p;
270         int             n;
271         FILE           *fp;
272 {
273         while (--n >= 0) {
274                 if (*p != '\015' && *p != '\032') {
275 #ifdef EUC
276                         putc_euc(*p, fp);
277 #else
278                         putc(*p, fp);
279 #endif
280                 }
281
282                 prev_char = *p++;
283         }
284         return (ferror(fp));
285 }
286
287 /* ------------------------------------------------------------------------ */
288 int
289 fread_txt(p, n, fp)
290         unsigned char  *p;
291         int             n;
292         FILE           *fp;
293 {
294         int             c;
295         int             cnt = 0;
296
297         while (cnt < n) {
298                 if (getc_euc_cache != EOF) {
299                         c = getc_euc_cache;
300                         getc_euc_cache = EOF;
301                 }
302                 else {
303                         if ((c = fgetc(fp)) == EOF)
304                                 break;
305                         if (c == '\n') {
306                                 getc_euc_cache = c;
307                                 ++origsize;
308                                 c = '\r';
309                         }
310 #ifdef EUC
311                         else if (euc_mode && (c == 0x8E || 0xA0 < c && c < 0xFF)) {
312                                 int             d = fgetc(fp);
313                                 if (d == EOF) {
314                                         *p++ = c;
315                                         cnt++;
316                                         break;
317                                 }
318                                 if (c == 0x8E) {        /* single shift (KANA) */
319                                         if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF))
320                                                 c = d | 0x80;
321                                         else
322                                                 getc_euc_cache = d;
323                                 }
324                                 else {
325                                         if (0xA0 < d && d < 0xFF) {     /* if GR */
326                                                 c &= 0x7F;      /* convert to MS-kanji */
327                                                 d &= 0x7F;
328                                                 if (!(c & 1)) {
329                                                         c--;
330                                                         d += 0x7F - 0x21;
331                                                 }
332                                                 if ((d += 0x40 - 0x21) > 0x7E)
333                                                         d++;
334                                                 if ((c = (c >> 1) + 0x71) >= 0xA0)
335                                                         c += 0xE0 - 0xA0;
336                                         }
337                                         getc_euc_cache = d;
338                                 }
339                         }
340 #endif
341                 }
342                 *p++ = c;
343                 cnt++;
344         }
345         return cnt;
346 }
347
348 /* ------------------------------------------------------------------------ */
349 unsigned short
350 calc_header_crc(p, n)           /* Thanks T.Okamoto */
351         unsigned char  *p;
352         unsigned int    n;
353 {
354         crc = 0;
355         while (n-- > 0)
356                 UPDATE_CRC(*p++);
357         return crc;
358 }
359 /* Local Variables: */
360 /* tab-width : 4 */
361 /* End: */