OSDN Git Service

Merge branch 'master' of github.com:jca02266/lha
[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 #ifdef EUC
13 static int      putc_euc_cache;
14 #endif
15 static int      getc_euc_cache;
16
17 /* ------------------------------------------------------------------------ */
18 void
19 make_crctable( /* void */ )
20 {
21     unsigned int    i, j, r;
22
23     for (i = 0; i <= UCHAR_MAX; i++) {
24         r = i;
25         for (j = 0; j < CHAR_BIT; j++)
26             if (r & 1)
27                 r = (r >> 1) ^ CRCPOLY;
28             else
29                 r >>= 1;
30         crctable[i] = r;
31     }
32 }
33
34 /* ------------------------------------------------------------------------ */
35 unsigned int
36 calccrc(crc, p, n)
37     unsigned int crc;
38     char  *p;
39     unsigned int    n;
40 {
41     while (n-- > 0)
42         crc = UPDATE_CRC(crc, *p++);
43     return crc;
44 }
45
46 /* ------------------------------------------------------------------------ */
47 int
48 fread_crc(crcp, p, n, fp)
49     unsigned int *crcp;
50     void *p;
51     int  n;
52     FILE *fp;
53 {
54     if (text_mode)
55         n = fread_txt(p, n, fp);
56     else
57         n = fread(p, 1, n, fp);
58
59     *crcp = calccrc(*crcp, p, n);
60 #ifdef NEED_INCREMENTAL_INDICATOR
61     put_indicator(n);
62 #endif
63     return n;
64 }
65
66 /* ------------------------------------------------------------------------ */
67 void
68 fwrite_crc(crcp, p, n, fp)
69     unsigned int *crcp;
70     void *p;
71     int  n;
72     FILE *fp;
73 {
74     *crcp = calccrc(*crcp, p, n);
75 #ifdef NEED_INCREMENTAL_INDICATOR
76     put_indicator(n);
77 #endif
78     if (verify_mode)
79         return;
80
81     if (fp) {
82         if (text_mode) {
83             if (fwrite_txt(p, n, fp))
84                 fatal_error("File write error");
85         }
86         else {
87             if (fwrite(p, 1, n, fp) < n)
88                 fatal_error("File write error");
89         }
90     }
91 }
92
93 /* ------------------------------------------------------------------------ */
94 void
95 init_code_cache( /* void */ )
96 {               /* called from copyfile() in util.c */
97 #ifdef EUC
98     putc_euc_cache = EOF;
99 #endif
100     getc_euc_cache = EOF;
101 }
102
103 /* ------------------------------------------------------------------------ */
104 #ifdef EUC
105 int
106 putc_euc(c, fd)
107     int             c;
108     FILE           *fd;
109 {
110     int             d;
111
112     if (putc_euc_cache == EOF) {
113         if (!euc_mode || c < 0x81 || c > 0xFC) {
114             return putc(c, fd);
115         }
116         if (c >= 0xA0 && c < 0xE0) {
117             if (putc(0x8E, fd) == EOF) return EOF;  /* single shift */
118             return putc(c, fd);
119         }
120         putc_euc_cache = c; /* save first byte */
121         return c;
122     }
123     d = putc_euc_cache;
124     putc_euc_cache = EOF;
125     if (d >= 0xA0)
126         d -= 0xE0 - 0xA0;
127     if (c > 0x9E) {
128         c = c - 0x9F + 0x21;
129         d = (d - 0x81) * 2 + 0x22;
130     }
131     else {
132         if (c > 0x7E)
133             c--;
134         c -= 0x1F;
135         d = (d - 0x81) * 2 + 0x21;
136     }
137     if (putc(0x80 | d, fd) == EOF) return EOF;
138     return putc(0x80 | c, fd);
139 }
140 #endif
141
142 /* ------------------------------------------------------------------------ */
143 int
144 fwrite_txt(vp, n, fp)
145     void *vp;
146     int  n;
147     FILE *fp;
148 {
149     unsigned char *p = vp;
150
151     while (--n >= 0) {
152         if (*p != '\015' && *p != '\032') {
153 #ifdef EUC
154             if (putc_euc(*p, fp) == EOF)
155                 break;
156 #else
157             if (putc(*p, fp) == EOF)
158                 break;
159 #endif
160         }
161         p++;
162     }
163     return (ferror(fp));
164 }
165
166 /* ------------------------------------------------------------------------ */
167 int
168 fread_txt(vp, n, fp)
169     void *vp;
170     int  n;
171     FILE *fp;
172 {
173     int             c;
174     int             cnt = 0;
175     unsigned char *p;
176
177     p = vp;
178
179     while (cnt < n) {
180         if (getc_euc_cache != EOF) {
181             c = getc_euc_cache;
182             getc_euc_cache = EOF;
183         }
184         else {
185             if ((c = fgetc(fp)) == EOF)
186                 break;
187             if (c == '\n') {
188                 getc_euc_cache = c;
189                 ++origsize;
190                 c = '\r';
191             }
192 #ifdef EUC
193             else if (euc_mode && (c == 0x8E || (0xA0 < c && c < 0xFF))) {
194                 int             d = fgetc(fp);
195                 if (d == EOF) {
196                     *p++ = c;
197                     cnt++;
198                     break;
199                 }
200                 if (c == 0x8E) {    /* single shift (KANA) */
201                     if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF))
202                         c = d | 0x80;
203                     else
204                         getc_euc_cache = d;
205                 }
206                 else {
207                     if (0xA0 < d && d < 0xFF) { /* if GR */
208                         c &= 0x7F;  /* convert to MS-kanji */
209                         d &= 0x7F;
210                         if (!(c & 1)) {
211                             c--;
212                             d += 0x7F - 0x21;
213                         }
214                         if ((d += 0x40 - 0x21) > 0x7E)
215                             d++;
216                         if ((c = (c >> 1) + 0x71) >= 0xA0)
217                             c += 0xE0 - 0xA0;
218                     }
219                     getc_euc_cache = d;
220                 }
221             }
222 #endif
223         }
224         *p++ = c;
225         cnt++;
226     }
227     return cnt;
228 }