1219b2ee8SDavid du Colombier #ifdef PLAN9
2bd389b36SDavid du Colombier #include <u.h>
3bd389b36SDavid du Colombier #include <libc.h>
4bd389b36SDavid du Colombier #include <bio.h>
5219b2ee8SDavid du Colombier #else
6219b2ee8SDavid du Colombier #include <stdio.h>
7219b2ee8SDavid du Colombier #include <unistd.h>
8219b2ee8SDavid du Colombier #include "plan9.h"
9219b2ee8SDavid du Colombier #endif
10bd389b36SDavid du Colombier #include "hdr.h"
11219b2ee8SDavid du Colombier #include "conv.h"
12219b2ee8SDavid du Colombier #include "kuten208.h"
13219b2ee8SDavid du Colombier #include "jis.h"
14bd389b36SDavid du Colombier
15bd389b36SDavid du Colombier /*
16219b2ee8SDavid du Colombier a state machine for interpreting all sorts of encodings
17bd389b36SDavid du Colombier */
18219b2ee8SDavid du Colombier static void
alljis(int c,Rune ** r,long input_loc)19219b2ee8SDavid du Colombier alljis(int c, Rune **r, long input_loc)
20219b2ee8SDavid du Colombier {
21219b2ee8SDavid du Colombier static enum { state0, state1, state2, state3, state4 } state = state0;
22219b2ee8SDavid du Colombier static int set8 = 0;
23219b2ee8SDavid du Colombier static int japan646 = 0;
24219b2ee8SDavid du Colombier static int lastc;
25219b2ee8SDavid du Colombier int n;
26219b2ee8SDavid du Colombier long l;
27219b2ee8SDavid du Colombier
28219b2ee8SDavid du Colombier again:
29219b2ee8SDavid du Colombier switch(state)
30219b2ee8SDavid du Colombier {
31219b2ee8SDavid du Colombier case state0: /* idle state */
32219b2ee8SDavid du Colombier if(c == ESC){ state = state1; return; }
33219b2ee8SDavid du Colombier if(c < 0) return;
34219b2ee8SDavid du Colombier if(!set8 && (c < 128)){
35219b2ee8SDavid du Colombier if(japan646){
36219b2ee8SDavid du Colombier switch(c)
37219b2ee8SDavid du Colombier {
38219b2ee8SDavid du Colombier case '\\': emit(0xA5); return; /* yen */
39219b2ee8SDavid du Colombier case '~': emit(0xAF); return; /* spacing macron */
40219b2ee8SDavid du Colombier default: emit(c); return;
41219b2ee8SDavid du Colombier }
42219b2ee8SDavid du Colombier } else {
43219b2ee8SDavid du Colombier emit(c);
44219b2ee8SDavid du Colombier return;
45219b2ee8SDavid du Colombier }
46219b2ee8SDavid du Colombier }
47219b2ee8SDavid du Colombier if(c < 0x21){ /* guard against bogus characters in JIS mode */
48219b2ee8SDavid du Colombier if(squawk)
497dd7cddfSDavid du Colombier EPR "%s: non-JIS character %02x in %s near byte %ld\n", argv0, c, file, input_loc);
50219b2ee8SDavid du Colombier emit(c);
51219b2ee8SDavid du Colombier return;
52219b2ee8SDavid du Colombier }
53219b2ee8SDavid du Colombier lastc = c; state = state4; return;
54219b2ee8SDavid du Colombier
55219b2ee8SDavid du Colombier case state1: /* seen an escape */
56219b2ee8SDavid du Colombier if(c == '$'){ state = state2; return; }
57219b2ee8SDavid du Colombier if(c == '('){ state = state3; return; }
58219b2ee8SDavid du Colombier emit(ESC); state = state0; goto again;
59219b2ee8SDavid du Colombier
60219b2ee8SDavid du Colombier case state2: /* may be shifting into JIS */
61219b2ee8SDavid du Colombier if((c == '@') || (c == 'B')){
62219b2ee8SDavid du Colombier set8 = 1; state = state0; return;
63219b2ee8SDavid du Colombier }
64219b2ee8SDavid du Colombier emit(ESC); emit('$'); state = state0; goto again;
65219b2ee8SDavid du Colombier
66219b2ee8SDavid du Colombier case state3: /* may be shifting out of JIS */
67219b2ee8SDavid du Colombier if((c == 'J') || (c == 'H') || (c == 'B')){
68219b2ee8SDavid du Colombier japan646 = (c == 'J');
69219b2ee8SDavid du Colombier set8 = 0; state = state0; return;
70219b2ee8SDavid du Colombier }
71219b2ee8SDavid du Colombier emit(ESC); emit('('); state = state0; goto again;
72219b2ee8SDavid du Colombier
73219b2ee8SDavid du Colombier case state4: /* two part char */
74219b2ee8SDavid du Colombier if(c < 0){
75219b2ee8SDavid du Colombier if(squawk)
76219b2ee8SDavid du Colombier EPR "%s: unexpected EOF in %s\n", argv0, file);
77219b2ee8SDavid du Colombier c = 0x21 | (lastc&0x80);
78219b2ee8SDavid du Colombier }
79219b2ee8SDavid du Colombier if(CANS2J(lastc, c)){ /* ms dos sjis */
80219b2ee8SDavid du Colombier int hi = lastc, lo = c;
81219b2ee8SDavid du Colombier S2J(hi, lo); /* convert to 208 */
82219b2ee8SDavid du Colombier n = hi*100 + lo - 3232; /* convert to kuten208 */
83219b2ee8SDavid du Colombier } else
84219b2ee8SDavid du Colombier n = (lastc&0x7F)*100 + (c&0x7f) - 3232; /* kuten208 */
85219b2ee8SDavid du Colombier if((n >= KUTEN208MAX) || ((l = tabkuten208[n]) == -1)){
86219b2ee8SDavid du Colombier nerrors++;
87219b2ee8SDavid du Colombier if(squawk)
88219b2ee8SDavid du Colombier EPR "%s: unknown kuten208 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
89219b2ee8SDavid du Colombier if(!clean)
90219b2ee8SDavid du Colombier emit(BADMAP);
91219b2ee8SDavid du Colombier } else {
92219b2ee8SDavid du Colombier if(l < 0){
93219b2ee8SDavid du Colombier l = -l;
94219b2ee8SDavid du Colombier if(squawk)
957dd7cddfSDavid du Colombier EPR "%s: ambiguous kuten208 %d (mapped to 0x%lx) near byte %ld in %s\n", argv0, n, l, input_loc, file);
96219b2ee8SDavid du Colombier }
97219b2ee8SDavid du Colombier emit(l);
98219b2ee8SDavid du Colombier }
99219b2ee8SDavid du Colombier state = state0;
100219b2ee8SDavid du Colombier }
101219b2ee8SDavid du Colombier }
102219b2ee8SDavid du Colombier
103219b2ee8SDavid du Colombier /*
104219b2ee8SDavid du Colombier a state machine for interpreting ms-kanji == shift-jis.
105219b2ee8SDavid du Colombier */
106219b2ee8SDavid du Colombier static void
ms(int c,Rune ** r,long input_loc)107219b2ee8SDavid du Colombier ms(int c, Rune **r, long input_loc)
108bd389b36SDavid du Colombier {
109bd389b36SDavid du Colombier static enum { state0, state1, state2, state3, state4 } state = state0;
110bd389b36SDavid du Colombier static int set8 = 0;
111bd389b36SDavid du Colombier static int japan646 = 0;
112bd389b36SDavid du Colombier static int lastc;
113bd389b36SDavid du Colombier int n;
114bd389b36SDavid du Colombier long l;
115bd389b36SDavid du Colombier
116bd389b36SDavid du Colombier again:
117bd389b36SDavid du Colombier switch(state)
118bd389b36SDavid du Colombier {
119bd389b36SDavid du Colombier case state0: /* idle state */
120bd389b36SDavid du Colombier if(c == ESC){ state = state1; return; }
121bd389b36SDavid du Colombier if(c < 0) return;
122bd389b36SDavid du Colombier if(!set8 && (c < 128)){
123bd389b36SDavid du Colombier if(japan646){
124bd389b36SDavid du Colombier switch(c)
125bd389b36SDavid du Colombier {
126bd389b36SDavid du Colombier case '\\': emit(0xA5); return; /* yen */
127bd389b36SDavid du Colombier case '~': emit(0xAF); return; /* spacing macron */
128bd389b36SDavid du Colombier default: emit(c); return;
129bd389b36SDavid du Colombier }
130bd389b36SDavid du Colombier } else {
131bd389b36SDavid du Colombier emit(c);
132bd389b36SDavid du Colombier return;
133bd389b36SDavid du Colombier }
134bd389b36SDavid du Colombier }
135bd389b36SDavid du Colombier lastc = c; state = state4; return;
136bd389b36SDavid du Colombier
137bd389b36SDavid du Colombier case state1: /* seen an escape */
138bd389b36SDavid du Colombier if(c == '$'){ state = state2; return; }
139bd389b36SDavid du Colombier if(c == '('){ state = state3; return; }
140bd389b36SDavid du Colombier emit(ESC); state = state0; goto again;
141bd389b36SDavid du Colombier
142bd389b36SDavid du Colombier case state2: /* may be shifting into JIS */
143bd389b36SDavid du Colombier if((c == '@') || (c == 'B')){
144bd389b36SDavid du Colombier set8 = 1; state = state0; return;
145bd389b36SDavid du Colombier }
146bd389b36SDavid du Colombier emit(ESC); emit('$'); state = state0; goto again;
147bd389b36SDavid du Colombier
148bd389b36SDavid du Colombier case state3: /* may be shifting out of JIS */
149bd389b36SDavid du Colombier if((c == 'J') || (c == 'H') || (c == 'B')){
150bd389b36SDavid du Colombier japan646 = (c == 'J');
151bd389b36SDavid du Colombier set8 = 0; state = state0; return;
152bd389b36SDavid du Colombier }
153bd389b36SDavid du Colombier emit(ESC); emit('('); state = state0; goto again;
154bd389b36SDavid du Colombier
155bd389b36SDavid du Colombier case state4: /* two part char */
156bd389b36SDavid du Colombier if(c < 0){
157bd389b36SDavid du Colombier if(squawk)
158219b2ee8SDavid du Colombier EPR "%s: unexpected EOF in %s\n", argv0, file);
159bd389b36SDavid du Colombier c = 0x21 | (lastc&0x80);
160bd389b36SDavid du Colombier }
161bd389b36SDavid du Colombier if(CANS2J(lastc, c)){ /* ms dos sjis */
162219b2ee8SDavid du Colombier int hi = lastc, lo = c;
163219b2ee8SDavid du Colombier S2J(hi, lo); /* convert to 208 */
164219b2ee8SDavid du Colombier n = hi*100 + lo - 3232; /* convert to kuten208 */
165219b2ee8SDavid du Colombier } else {
166bd389b36SDavid du Colombier nerrors++;
167bd389b36SDavid du Colombier if(squawk)
168219b2ee8SDavid du Colombier EPR "%s: illegal byte pair (0x%x,0x%x) near byte %ld in %s\n", argv0, lastc, c, input_loc, file);
169219b2ee8SDavid du Colombier if(!clean)
170219b2ee8SDavid du Colombier emit(BADMAP);
171219b2ee8SDavid du Colombier state = state0;
172219b2ee8SDavid du Colombier goto again;
173219b2ee8SDavid du Colombier }
174219b2ee8SDavid du Colombier if((n >= KUTEN208MAX) || ((l = tabkuten208[n]) == -1)){
175219b2ee8SDavid du Colombier nerrors++;
176219b2ee8SDavid du Colombier if(squawk)
177219b2ee8SDavid du Colombier EPR "%s: unknown kuten208 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
178bd389b36SDavid du Colombier if(!clean)
179bd389b36SDavid du Colombier emit(BADMAP);
180bd389b36SDavid du Colombier } else {
181bd389b36SDavid du Colombier if(l < 0){
182bd389b36SDavid du Colombier l = -l;
183bd389b36SDavid du Colombier if(squawk)
1847dd7cddfSDavid du Colombier EPR "%s: ambiguous kuten208 %d (mapped to 0x%lx) near byte %ld in %s\n", argv0, n, l, input_loc, file);
185bd389b36SDavid du Colombier }
186bd389b36SDavid du Colombier emit(l);
187bd389b36SDavid du Colombier }
188bd389b36SDavid du Colombier state = state0;
189bd389b36SDavid du Colombier }
190bd389b36SDavid du Colombier }
191bd389b36SDavid du Colombier
192219b2ee8SDavid du Colombier /*
193219b2ee8SDavid du Colombier a state machine for interpreting ujis == EUC
194219b2ee8SDavid du Colombier */
195219b2ee8SDavid du Colombier static void
ujis(int c,Rune ** r,long input_loc)196219b2ee8SDavid du Colombier ujis(int c, Rune **r, long input_loc)
197bd389b36SDavid du Colombier {
198219b2ee8SDavid du Colombier static enum { state0, state1 } state = state0;
199219b2ee8SDavid du Colombier static int lastc;
200219b2ee8SDavid du Colombier int n;
201219b2ee8SDavid du Colombier long l;
202219b2ee8SDavid du Colombier
203219b2ee8SDavid du Colombier switch(state)
204219b2ee8SDavid du Colombier {
205219b2ee8SDavid du Colombier case state0: /* idle state */
206219b2ee8SDavid du Colombier if(c < 0) return;
207219b2ee8SDavid du Colombier if(c < 128){
208219b2ee8SDavid du Colombier emit(c);
209219b2ee8SDavid du Colombier return;
210219b2ee8SDavid du Colombier }
211219b2ee8SDavid du Colombier if(c == 0x8e){ /* codeset 2 */
212219b2ee8SDavid du Colombier nerrors++;
213219b2ee8SDavid du Colombier if(squawk)
214219b2ee8SDavid du Colombier EPR "%s: unknown codeset 2 near byte %ld in %s\n", argv0, input_loc, file);
215219b2ee8SDavid du Colombier if(!clean)
216219b2ee8SDavid du Colombier emit(BADMAP);
217219b2ee8SDavid du Colombier return;
218219b2ee8SDavid du Colombier }
219219b2ee8SDavid du Colombier if(c == 0x8f){ /* codeset 3 */
220219b2ee8SDavid du Colombier nerrors++;
221219b2ee8SDavid du Colombier if(squawk)
222219b2ee8SDavid du Colombier EPR "%s: unknown codeset 3 near byte %ld in %s\n", argv0, input_loc, file);
223219b2ee8SDavid du Colombier if(!clean)
224219b2ee8SDavid du Colombier emit(BADMAP);
225219b2ee8SDavid du Colombier return;
226219b2ee8SDavid du Colombier }
227219b2ee8SDavid du Colombier lastc = c;
228219b2ee8SDavid du Colombier state = state1;
229219b2ee8SDavid du Colombier return;
230219b2ee8SDavid du Colombier
231219b2ee8SDavid du Colombier case state1: /* two part char */
232219b2ee8SDavid du Colombier if(c < 0){
233219b2ee8SDavid du Colombier if(squawk)
234219b2ee8SDavid du Colombier EPR "%s: unexpected EOF in %s\n", argv0, file);
235219b2ee8SDavid du Colombier c = 0xA1;
236219b2ee8SDavid du Colombier }
237219b2ee8SDavid du Colombier n = (lastc&0x7F)*100 + (c&0x7F) - 3232; /* kuten208 */
238219b2ee8SDavid du Colombier if((n >= KUTEN208MAX) || ((l = tabkuten208[n]) == -1)){
239219b2ee8SDavid du Colombier nerrors++;
240219b2ee8SDavid du Colombier if(squawk)
241219b2ee8SDavid du Colombier EPR "%s: unknown kuten208 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
242219b2ee8SDavid du Colombier if(!clean)
243219b2ee8SDavid du Colombier emit(BADMAP);
244219b2ee8SDavid du Colombier } else {
245219b2ee8SDavid du Colombier if(l < 0){
246219b2ee8SDavid du Colombier l = -l;
247219b2ee8SDavid du Colombier if(squawk)
2487dd7cddfSDavid du Colombier EPR "%s: ambiguous kuten208 %d (mapped to 0x%lx) near byte %ld in %s\n", argv0, n, l, input_loc, file);
249219b2ee8SDavid du Colombier }
250219b2ee8SDavid du Colombier emit(l);
251219b2ee8SDavid du Colombier }
252219b2ee8SDavid du Colombier state = state0;
253219b2ee8SDavid du Colombier }
254219b2ee8SDavid du Colombier }
255219b2ee8SDavid du Colombier
256219b2ee8SDavid du Colombier /*
257219b2ee8SDavid du Colombier a state machine for interpreting jis-kanji == 2022-JP
258219b2ee8SDavid du Colombier */
259219b2ee8SDavid du Colombier static void
jis(int c,Rune ** r,long input_loc)260219b2ee8SDavid du Colombier jis(int c, Rune **r, long input_loc)
261219b2ee8SDavid du Colombier {
262219b2ee8SDavid du Colombier static enum { state0, state1, state2, state3, state4 } state = state0;
263219b2ee8SDavid du Colombier static int set8 = 0;
264219b2ee8SDavid du Colombier static int japan646 = 0;
265219b2ee8SDavid du Colombier static int lastc;
266219b2ee8SDavid du Colombier int n;
267219b2ee8SDavid du Colombier long l;
268219b2ee8SDavid du Colombier
269219b2ee8SDavid du Colombier again:
270219b2ee8SDavid du Colombier switch(state)
271219b2ee8SDavid du Colombier {
272219b2ee8SDavid du Colombier case state0: /* idle state */
273219b2ee8SDavid du Colombier if(c == ESC){ state = state1; return; }
274219b2ee8SDavid du Colombier if(c < 0) return;
275219b2ee8SDavid du Colombier if(!set8 && (c < 128)){
276219b2ee8SDavid du Colombier if(japan646){
277219b2ee8SDavid du Colombier switch(c)
278219b2ee8SDavid du Colombier {
279219b2ee8SDavid du Colombier case '\\': emit(0xA5); return; /* yen */
280219b2ee8SDavid du Colombier case '~': emit(0xAF); return; /* spacing macron */
281219b2ee8SDavid du Colombier default: emit(c); return;
282219b2ee8SDavid du Colombier }
283219b2ee8SDavid du Colombier } else {
284219b2ee8SDavid du Colombier emit(c);
285219b2ee8SDavid du Colombier return;
286219b2ee8SDavid du Colombier }
287219b2ee8SDavid du Colombier }
288219b2ee8SDavid du Colombier lastc = c; state = state4; return;
289219b2ee8SDavid du Colombier
290219b2ee8SDavid du Colombier case state1: /* seen an escape */
291219b2ee8SDavid du Colombier if(c == '$'){ state = state2; return; }
292219b2ee8SDavid du Colombier if(c == '('){ state = state3; return; }
293219b2ee8SDavid du Colombier emit(ESC); state = state0; goto again;
294219b2ee8SDavid du Colombier
295219b2ee8SDavid du Colombier case state2: /* may be shifting into JIS */
296219b2ee8SDavid du Colombier if((c == '@') || (c == 'B')){
297219b2ee8SDavid du Colombier set8 = 1; state = state0; return;
298219b2ee8SDavid du Colombier }
299219b2ee8SDavid du Colombier emit(ESC); emit('$'); state = state0; goto again;
300219b2ee8SDavid du Colombier
301219b2ee8SDavid du Colombier case state3: /* may be shifting out of JIS */
302219b2ee8SDavid du Colombier if((c == 'J') || (c == 'H') || (c == 'B')){
303219b2ee8SDavid du Colombier japan646 = (c == 'J');
304219b2ee8SDavid du Colombier set8 = 0; state = state0; return;
305219b2ee8SDavid du Colombier }
306219b2ee8SDavid du Colombier emit(ESC); emit('('); state = state0; goto again;
307219b2ee8SDavid du Colombier
308219b2ee8SDavid du Colombier case state4: /* two part char */
309219b2ee8SDavid du Colombier if(c < 0){
310219b2ee8SDavid du Colombier if(squawk)
311219b2ee8SDavid du Colombier EPR "%s: unexpected EOF in %s\n", argv0, file);
312219b2ee8SDavid du Colombier c = 0x21 | (lastc&0x80);
313219b2ee8SDavid du Colombier }
314219b2ee8SDavid du Colombier if((lastc&0x80) != (c&0x80)){ /* guard against latin1 in jis */
315219b2ee8SDavid du Colombier emit(lastc);
316219b2ee8SDavid du Colombier state = state0;
317219b2ee8SDavid du Colombier goto again;
318219b2ee8SDavid du Colombier }
319219b2ee8SDavid du Colombier n = (lastc&0x7F)*100 + (c&0x7f) - 3232; /* kuten208 */
320219b2ee8SDavid du Colombier if((n >= KUTEN208MAX) || ((l = tabkuten208[n]) == -1)){
321219b2ee8SDavid du Colombier nerrors++;
322219b2ee8SDavid du Colombier if(squawk)
323219b2ee8SDavid du Colombier EPR "%s: unknown kuten208 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
324219b2ee8SDavid du Colombier if(!clean)
325219b2ee8SDavid du Colombier emit(BADMAP);
326219b2ee8SDavid du Colombier } else {
327219b2ee8SDavid du Colombier if(l < 0){
328219b2ee8SDavid du Colombier l = -l;
329219b2ee8SDavid du Colombier if(squawk)
3307dd7cddfSDavid du Colombier EPR "%s: ambiguous kuten208 %d (mapped to 0x%lx) near byte %ld in %s\n", argv0, n, l, input_loc, file);
331219b2ee8SDavid du Colombier }
332219b2ee8SDavid du Colombier emit(l);
333219b2ee8SDavid du Colombier }
334219b2ee8SDavid du Colombier state = state0;
335219b2ee8SDavid du Colombier }
336219b2ee8SDavid du Colombier }
337219b2ee8SDavid du Colombier
338219b2ee8SDavid du Colombier static void
do_in(int fd,void (* procfn)(int,Rune **,long),struct convert * out)339219b2ee8SDavid du Colombier do_in(int fd, void (*procfn)(int, Rune **, long), struct convert *out)
340219b2ee8SDavid du Colombier {
341219b2ee8SDavid du Colombier Rune ob[N];
342bd389b36SDavid du Colombier Rune *r, *re;
343bd389b36SDavid du Colombier uchar ibuf[N];
344bd389b36SDavid du Colombier int n, i;
345bd389b36SDavid du Colombier long nin;
346bd389b36SDavid du Colombier
347219b2ee8SDavid du Colombier r = ob;
348219b2ee8SDavid du Colombier re = ob+N-3;
349bd389b36SDavid du Colombier nin = 0;
350bd389b36SDavid du Colombier while((n = read(fd, ibuf, sizeof ibuf)) > 0){
351bd389b36SDavid du Colombier for(i = 0; i < n; i++){
352219b2ee8SDavid du Colombier (*procfn)(ibuf[i], &r, nin++);
353bd389b36SDavid du Colombier if(r >= re){
354219b2ee8SDavid du Colombier OUT(out, ob, r-ob);
355219b2ee8SDavid du Colombier r = ob;
356bd389b36SDavid du Colombier }
357bd389b36SDavid du Colombier }
358219b2ee8SDavid du Colombier if(r > ob){
359219b2ee8SDavid du Colombier OUT(out, ob, r-ob);
360219b2ee8SDavid du Colombier r = ob;
361bd389b36SDavid du Colombier }
362bd389b36SDavid du Colombier }
363219b2ee8SDavid du Colombier (*procfn)(-1, &r, nin);
364219b2ee8SDavid du Colombier if(r > ob)
365219b2ee8SDavid du Colombier OUT(out, ob, r-ob);
366*ec46fab0SDavid du Colombier OUT(out, ob, 0);
367bd389b36SDavid du Colombier }
368bd389b36SDavid du Colombier
369bd389b36SDavid du Colombier void
jis_in(int fd,long * notused,struct convert * out)370219b2ee8SDavid du Colombier jis_in(int fd, long *notused, struct convert *out)
371bd389b36SDavid du Colombier {
372219b2ee8SDavid du Colombier USED(notused);
373219b2ee8SDavid du Colombier do_in(fd, alljis, out);
374219b2ee8SDavid du Colombier }
375219b2ee8SDavid du Colombier
376219b2ee8SDavid du Colombier void
ujis_in(int fd,long * notused,struct convert * out)377219b2ee8SDavid du Colombier ujis_in(int fd, long *notused, struct convert *out)
378219b2ee8SDavid du Colombier {
379219b2ee8SDavid du Colombier USED(notused);
380219b2ee8SDavid du Colombier do_in(fd, ujis, out);
381219b2ee8SDavid du Colombier }
382219b2ee8SDavid du Colombier
383219b2ee8SDavid du Colombier void
msjis_in(int fd,long * notused,struct convert * out)384219b2ee8SDavid du Colombier msjis_in(int fd, long *notused, struct convert *out)
385219b2ee8SDavid du Colombier {
386219b2ee8SDavid du Colombier USED(notused);
387219b2ee8SDavid du Colombier do_in(fd, ms, out);
388219b2ee8SDavid du Colombier }
389219b2ee8SDavid du Colombier
390219b2ee8SDavid du Colombier void
jisjis_in(int fd,long * notused,struct convert * out)391219b2ee8SDavid du Colombier jisjis_in(int fd, long *notused, struct convert *out)
392219b2ee8SDavid du Colombier {
393219b2ee8SDavid du Colombier USED(notused);
394219b2ee8SDavid du Colombier do_in(fd, jis, out);
395219b2ee8SDavid du Colombier }
396219b2ee8SDavid du Colombier
397bd389b36SDavid du Colombier static int first = 1;
398219b2ee8SDavid du Colombier
399219b2ee8SDavid du Colombier static void
tab_init(void)400219b2ee8SDavid du Colombier tab_init(void)
401219b2ee8SDavid du Colombier {
402219b2ee8SDavid du Colombier int i;
403bd389b36SDavid du Colombier long l;
404bd389b36SDavid du Colombier
405bd389b36SDavid du Colombier first = 0;
406bd389b36SDavid du Colombier for(i = 0; i < NRUNE; i++)
407bd389b36SDavid du Colombier tab[i] = -1;
408219b2ee8SDavid du Colombier for(i = 0; i < KUTEN208MAX; i++)
409219b2ee8SDavid du Colombier if((l = tabkuten208[i]) != -1){
410bd389b36SDavid du Colombier if(l < 0)
411bd389b36SDavid du Colombier tab[-l] = i;
412bd389b36SDavid du Colombier else
413bd389b36SDavid du Colombier tab[l] = i;
414bd389b36SDavid du Colombier }
415bd389b36SDavid du Colombier }
416219b2ee8SDavid du Colombier
417219b2ee8SDavid du Colombier
418219b2ee8SDavid du Colombier /* jis-kanji, or ISO 2022-JP */
419219b2ee8SDavid du Colombier void
jisjis_out(Rune * base,int n,long * notused)420219b2ee8SDavid du Colombier jisjis_out(Rune *base, int n, long *notused)
421219b2ee8SDavid du Colombier {
422219b2ee8SDavid du Colombier char *p;
423219b2ee8SDavid du Colombier int i;
424219b2ee8SDavid du Colombier Rune r;
425219b2ee8SDavid du Colombier static enum { ascii, japan646, jp2022 } state = ascii;
426219b2ee8SDavid du Colombier
427219b2ee8SDavid du Colombier USED(notused);
428219b2ee8SDavid du Colombier if(first)
429219b2ee8SDavid du Colombier tab_init();
430219b2ee8SDavid du Colombier nrunes += n;
431219b2ee8SDavid du Colombier p = obuf;
432219b2ee8SDavid du Colombier for(i = 0; i < n; i++){
433219b2ee8SDavid du Colombier r = base[i];
434219b2ee8SDavid du Colombier if(r < 128){
435219b2ee8SDavid du Colombier if(state == jp2022){
4367dd7cddfSDavid du Colombier *p++ = ESC; *p++ = '('; *p++ = 'B';
437219b2ee8SDavid du Colombier state = ascii;
438219b2ee8SDavid du Colombier }
439219b2ee8SDavid du Colombier *p++ = r;
440219b2ee8SDavid du Colombier } else {
441219b2ee8SDavid du Colombier if(tab[r] != -1){
442219b2ee8SDavid du Colombier if(state != jp2022){
443219b2ee8SDavid du Colombier *p++ = ESC; *p++ = '$'; *p++ = 'B';
444219b2ee8SDavid du Colombier state = jp2022;
445219b2ee8SDavid du Colombier }
446219b2ee8SDavid du Colombier *p++ = tab[r]/100 + ' ';
447219b2ee8SDavid du Colombier *p++ = tab[r]%100 + ' ';
448219b2ee8SDavid du Colombier continue;
449219b2ee8SDavid du Colombier }
450219b2ee8SDavid du Colombier if(squawk)
451219b2ee8SDavid du Colombier EPR "%s: rune 0x%x not in output cs\n", argv0, r);
452219b2ee8SDavid du Colombier nerrors++;
453219b2ee8SDavid du Colombier if(clean)
454219b2ee8SDavid du Colombier continue;
455219b2ee8SDavid du Colombier *p++ = BYTEBADMAP;
456219b2ee8SDavid du Colombier }
457219b2ee8SDavid du Colombier }
458219b2ee8SDavid du Colombier noutput += p-obuf;
459219b2ee8SDavid du Colombier if(p > obuf)
460219b2ee8SDavid du Colombier write(1, obuf, p-obuf);
461219b2ee8SDavid du Colombier }
462219b2ee8SDavid du Colombier
463219b2ee8SDavid du Colombier /* ms-kanji, or Shift-JIS */
464219b2ee8SDavid du Colombier void
msjis_out(Rune * base,int n,long * notused)465219b2ee8SDavid du Colombier msjis_out(Rune *base, int n, long *notused)
466219b2ee8SDavid du Colombier {
467219b2ee8SDavid du Colombier char *p;
468219b2ee8SDavid du Colombier int i, hi, lo;
469219b2ee8SDavid du Colombier Rune r;
470219b2ee8SDavid du Colombier
471219b2ee8SDavid du Colombier USED(notused);
472219b2ee8SDavid du Colombier if(first)
473219b2ee8SDavid du Colombier tab_init();
474219b2ee8SDavid du Colombier nrunes += n;
475219b2ee8SDavid du Colombier p = obuf;
476219b2ee8SDavid du Colombier for(i = 0; i < n; i++){
477219b2ee8SDavid du Colombier r = base[i];
478219b2ee8SDavid du Colombier if(r < 128)
479219b2ee8SDavid du Colombier *p++ = r;
480219b2ee8SDavid du Colombier else {
481219b2ee8SDavid du Colombier if(tab[r] != -1){
482219b2ee8SDavid du Colombier hi = tab[r]/100 + ' ';
483219b2ee8SDavid du Colombier lo = tab[r]%100 + ' ';
484219b2ee8SDavid du Colombier J2S(hi, lo);
485219b2ee8SDavid du Colombier *p++ = hi;
486219b2ee8SDavid du Colombier *p++ = lo;
487219b2ee8SDavid du Colombier continue;
488219b2ee8SDavid du Colombier }
489219b2ee8SDavid du Colombier if(squawk)
490219b2ee8SDavid du Colombier EPR "%s: rune 0x%x not in output cs\n", argv0, r);
491219b2ee8SDavid du Colombier nerrors++;
492219b2ee8SDavid du Colombier if(clean)
493219b2ee8SDavid du Colombier continue;
494219b2ee8SDavid du Colombier *p++ = BYTEBADMAP;
495219b2ee8SDavid du Colombier }
496219b2ee8SDavid du Colombier }
497219b2ee8SDavid du Colombier noutput += p-obuf;
498219b2ee8SDavid du Colombier if(p > obuf)
499219b2ee8SDavid du Colombier write(1, obuf, p-obuf);
500219b2ee8SDavid du Colombier }
501219b2ee8SDavid du Colombier
502219b2ee8SDavid du Colombier /* ujis, or EUC */
503219b2ee8SDavid du Colombier void
ujis_out(Rune * base,int n,long * notused)504219b2ee8SDavid du Colombier ujis_out(Rune *base, int n, long *notused)
505219b2ee8SDavid du Colombier {
506219b2ee8SDavid du Colombier char *p;
507219b2ee8SDavid du Colombier int i;
508219b2ee8SDavid du Colombier Rune r;
509219b2ee8SDavid du Colombier
510219b2ee8SDavid du Colombier USED(notused);
511219b2ee8SDavid du Colombier if(first)
512219b2ee8SDavid du Colombier tab_init();
513bd389b36SDavid du Colombier nrunes += n;
514bd389b36SDavid du Colombier p = obuf;
515bd389b36SDavid du Colombier for(i = 0; i < n; i++){
516bd389b36SDavid du Colombier r = base[i];
517bd389b36SDavid du Colombier if(r < 128)
518bd389b36SDavid du Colombier *p++ = r;
519bd389b36SDavid du Colombier else {
520bd389b36SDavid du Colombier if(tab[r] != -1){
521bd389b36SDavid du Colombier *p++ = 0x80 | (tab[r]/100 + ' ');
522bd389b36SDavid du Colombier *p++ = 0x80 | (tab[r]%100 + ' ');
523bd389b36SDavid du Colombier continue;
524bd389b36SDavid du Colombier }
525bd389b36SDavid du Colombier if(squawk)
526219b2ee8SDavid du Colombier EPR "%s: rune 0x%x not in output cs\n", argv0, r);
527bd389b36SDavid du Colombier nerrors++;
528bd389b36SDavid du Colombier if(clean)
529bd389b36SDavid du Colombier continue;
530219b2ee8SDavid du Colombier *p++ = BYTEBADMAP;
531bd389b36SDavid du Colombier }
532bd389b36SDavid du Colombier }
533bd389b36SDavid du Colombier noutput += p-obuf;
534bd389b36SDavid du Colombier if(p > obuf)
535bd389b36SDavid du Colombier write(1, obuf, p-obuf);
536bd389b36SDavid du Colombier }
537