OSDN Git Service

* src/header.c (skip_bytes): newly added.
[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                             fatal_error("Write error in crcio.c(putcode)");
113                         }
114                         compsize++;
115                 }
116                 else
117                         unpackable = 1;
118                 subbitbuf = 0;
119                 bitcount = CHAR_BIT;
120         }
121         subbitbuf += x >> (USHRT_BIT - bitcount);
122         bitcount -= n;
123 }
124
125 /* ------------------------------------------------------------------------ */
126 void
127 putbits(n, x)                   /* Write rightmost n bits of x */
128         unsigned char   n;
129         unsigned short  x;
130 {
131         x <<= USHRT_BIT - n;
132         while (n >= bitcount) {
133                 n -= bitcount;
134                 subbitbuf += x >> (USHRT_BIT - bitcount);
135                 x <<= bitcount;
136                 if (compsize < origsize) {
137                         if (fwrite(&subbitbuf, 1, 1, outfile) == 0) {
138                             fatal_error("Write error in crcio.c(putbits)");
139                         }
140                         compsize++;
141                 }
142                 else
143                         unpackable = 1;
144                 subbitbuf = 0;
145                 bitcount = CHAR_BIT;
146         }
147         subbitbuf += x >> (USHRT_BIT - bitcount);
148         bitcount -= n;
149 }
150
151 /* ------------------------------------------------------------------------ */
152 int
153 fread_crc(p, n, fp)
154         unsigned char  *p;
155         int             n;
156         FILE           *fp;
157 {
158         if (text_mode)
159                 n = fread_txt(p, n, fp);
160         else
161                 n = fread(p, 1, n, fp);
162
163         calccrc(p, n);
164         return n;
165 }
166
167 /* ------------------------------------------------------------------------ */
168 void
169 fwrite_crc(p, n, fp)
170         unsigned char  *p;
171         int             n;
172         FILE           *fp;
173 {
174         calccrc(p, n);
175         if (verify_mode)
176                 return;
177
178         if (fp) {
179                 if (text_mode) {
180                         if (fwrite_txt(p, n, fp))
181                                 fatal_error("File write error");
182                 }
183                 else {
184                         if (fwrite(p, 1, n, fp) < n)
185                                 fatal_error("File write error");
186                 }
187         }
188 }
189
190 /* ------------------------------------------------------------------------ */
191 void
192 init_code_cache( /* void */ )
193 {                               /* called from copyfile() in util.c */
194 #ifdef EUC
195         putc_euc_cache = EOF;
196 #endif
197         getc_euc_cache = EOF;
198 }
199
200 void
201 init_getbits( /* void */ )
202 {
203         bitbuf = 0;
204         subbitbuf = 0;
205         bitcount = 0;
206         fillbuf(2 * CHAR_BIT);
207 #ifdef EUC
208         putc_euc_cache = EOF;
209 #endif
210 }
211
212 /* ------------------------------------------------------------------------ */
213 void
214 init_putbits( /* void */ )
215 {
216         bitcount = CHAR_BIT;
217         subbitbuf = 0;
218         getc_euc_cache = EOF;
219 }
220
221 /* ------------------------------------------------------------------------ */
222 #ifdef EUC
223 int
224 putc_euc(c, fd)
225         int             c;
226         FILE           *fd;
227 {
228         int             d;
229
230         if (putc_euc_cache == EOF) {
231                 if (!euc_mode || c < 0x81 || c > 0xFC) {
232                         return putc(c, fd);
233                 }
234                 if (c >= 0xA0 && c < 0xE0) {
235                         if (putc(0x8E, fd) == EOF) return EOF;  /* single shift */
236                         return putc(c, fd);
237                 }
238                 putc_euc_cache = c;     /* save first byte */
239                 return c;
240         }
241         d = putc_euc_cache;
242         putc_euc_cache = EOF;
243         if (d >= 0xA0)
244                 d -= 0xE0 - 0xA0;
245         if (c > 0x9E) {
246                 c = c - 0x9F + 0x21;
247                 d = (d - 0x81) * 2 + 0x22;
248         }
249         else {
250                 if (c > 0x7E)
251                         c--;
252                 c -= 0x1F;
253                 d = (d - 0x81) * 2 + 0x21;
254         }
255         if (putc(0x80 | d, fd) == EOF) return EOF;
256         return putc(0x80 | c, fd);
257 }
258 #endif
259
260 /* ------------------------------------------------------------------------ */
261 int
262 fwrite_txt(p, n, fp)
263         unsigned char  *p;
264         int             n;
265         FILE           *fp;
266 {
267         while (--n >= 0) {
268                 if (*p != '\015' && *p != '\032') {
269 #ifdef EUC
270                         if (putc_euc(*p, fp) == EOF)
271                 break;
272 #else
273                         if (putc(*p, fp) == EOF)
274                 break;
275 #endif
276                 }
277
278                 prev_char = *p++;
279         }
280         return (ferror(fp));
281 }
282
283 /* ------------------------------------------------------------------------ */
284 int
285 fread_txt(p, n, fp)
286         unsigned char  *p;
287         int             n;
288         FILE           *fp;
289 {
290         int             c;
291         int             cnt = 0;
292
293         while (cnt < n) {
294                 if (getc_euc_cache != EOF) {
295                         c = getc_euc_cache;
296                         getc_euc_cache = EOF;
297                 }
298                 else {
299                         if ((c = fgetc(fp)) == EOF)
300                                 break;
301                         if (c == '\n') {
302                                 getc_euc_cache = c;
303                                 ++origsize;
304                                 c = '\r';
305                         }
306 #ifdef EUC
307                         else if (euc_mode && (c == 0x8E || (0xA0 < c && c < 0xFF))) {
308                                 int             d = fgetc(fp);
309                                 if (d == EOF) {
310                                         *p++ = c;
311                                         cnt++;
312                                         break;
313                                 }
314                                 if (c == 0x8E) {        /* single shift (KANA) */
315                                         if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF))
316                                                 c = d | 0x80;
317                                         else
318                                                 getc_euc_cache = d;
319                                 }
320                                 else {
321                                         if (0xA0 < d && d < 0xFF) {     /* if GR */
322                                                 c &= 0x7F;      /* convert to MS-kanji */
323                                                 d &= 0x7F;
324                                                 if (!(c & 1)) {
325                                                         c--;
326                                                         d += 0x7F - 0x21;
327                                                 }
328                                                 if ((d += 0x40 - 0x21) > 0x7E)
329                                                         d++;
330                                                 if ((c = (c >> 1) + 0x71) >= 0xA0)
331                                                         c += 0xE0 - 0xA0;
332                                         }
333                                         getc_euc_cache = d;
334                                 }
335                         }
336 #endif
337                 }
338                 *p++ = c;
339                 cnt++;
340         }
341         return cnt;
342 }
343
344 /* ------------------------------------------------------------------------ */
345 unsigned short
346 calc_header_crc(p, n)           /* Thanks T.Okamoto */
347         unsigned char  *p;
348         unsigned int    n;
349 {
350         crc = 0;
351         while (n-- > 0)
352                 UPDATE_CRC(*p++);
353         return crc;
354 }
355 /* Local Variables: */
356 /* tab-width : 4 */
357 /* End: */
358 /* vi: set tabstop=4: */