xref: /plan9/sys/src/cmd/tcs/conv_jis.c (revision ec46fab06dcae3e636b775c4eaa679036316e1d8)
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