]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/tcs/tcs.c
ip/cifsd: dont return garbage in upper 32 bit of unix extension stat fields
[plan9front.git] / sys / src / cmd / tcs / tcs.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        <bio.h>
4 #include        "cyrillic.h"
5 #include        "misc.h"
6 #include        "ms.h"
7 #include        "8859.h"
8 #include        "big5.h"
9 #include        "gb.h"
10 #include        "hdr.h"
11 #include        "conv.h"
12
13 void usage(void);
14 void list(void);
15 int squawk = 1;
16 int clean = 0;
17 int verbose = 0;
18 long ninput, noutput, nrunes, nerrors;
19 char *file = "stdin";
20 char *argv0;
21 Rune runes[N];
22 char obuf[UTFmax*N];    /* maximum bloat from N runes */
23 long tab[NRUNE];
24
25 void intable(int, long *, struct convert *);
26 void unicode_in(int, long *, struct convert *);
27 void unicode_out(Rune *, int, long *);
28
29 void
30 main(int argc, char **argv)
31 {
32         char *from = "utf";
33         char *to = "utf";
34         int fd;
35         int listem = 0;
36         struct convert *t, *f;
37
38         ARGBEGIN {
39         case 'c':
40                 clean = 1;
41                 break;
42         case 'f':
43                 from = EARGF(usage());
44                 break;  
45         case 'l':
46                 listem = 1;
47                 break;
48         case 's':
49                 squawk = 0;
50                 break;
51         case 't':
52                 to = EARGF(usage());
53                 break;
54         case 'v':
55                 verbose = 1;
56                 break;
57         default:
58                 usage();
59                 break;
60         } ARGEND
61
62         if(verbose)
63                 squawk = 1;
64         if(listem){
65                 list();
66                 exits(nil);
67         }
68         if(!from || !to)
69                 usage();
70         f = conv(from, 1);
71         t = conv(to, 0);
72 #define PROC    {if(f->flags&Table)\
73                         intable(fd, (long *)f->data, t);\
74                 else\
75                         ((Infn)(f->fn))(fd, (long *)0, t);}
76         if(*argv){
77                 while(*argv){
78                         file = *argv;
79                         if((fd = open(*argv, OREAD)) < 0){
80                                 sysfatal("%s: %r", *argv);
81                         }
82                         PROC
83                         close(fd);
84                         argv++;
85                 }
86         } else {
87                 fd = 0;
88                 PROC
89         }
90         if(verbose)
91                 warn("%ld input bytes, %ld runes, %ld output bytes (%ld errors)",
92                         ninput, nrunes, noutput, nerrors);
93         exits((nerrors && squawk)? "conversion error":nil);
94 }
95
96 void
97 usage(void)
98 {
99         fprint(2, "Usage: %s [-slv] [-f cs] [-t cs] [file ...]\n", argv0);
100         verbose = 1;
101         list();
102         exits("usage");
103 }
104
105 void
106 list(void)
107 {
108         struct convert *c;
109         char ch = verbose?'\t':' ';
110
111         if(verbose)
112                 fprint(2, "character sets:\n");
113         else
114                 fprint(2, "cs:");
115         for(c = convert; c->name; c++){
116                 if((c->flags&From) && c[1].name && (strcmp(c[1].name, c->name) == 0)){
117                         fprint(2, "%c%s", ch, c->name);
118                         c++;
119                 } else if(c->flags&Table)
120                         fprint(2, "%c%s", ch, c->name);
121                 else if(c->flags&From)
122                         fprint(2, "%c%s(from)", ch, c->name);
123                 else
124                         fprint(2, "%c%s(to)", ch, c->name);
125                 if(verbose)
126                         fprint(2, "\t%s\n", c->chatter);
127         }
128         if(!verbose)
129                 fprint(2, "\n");
130 }
131
132 void
133 warn(char *fmt, ...)
134 {
135         va_list arg;
136         char buf[1024]; /* arbitrary */
137         int n;
138
139         if((n = snprint(buf, sizeof(buf), "%s: ", argv0)) < 0)
140                 sysfatal("snprint: %r");
141         va_start(arg, fmt);
142         vseprint(buf+n, buf+sizeof(buf), fmt, arg);
143         va_end(arg);
144
145         fprint(2, "%s\n", buf);
146 }
147
148 char*
149 aliasname(char *name)
150 {
151         static struct {
152                 char *alias;
153                 char *name;
154         } tab[] = {
155 #include "alias.h"
156                 /* not generated by the script */
157                 "utf8", "utf",
158                 "euc_jp", "jis",
159                 "euc_kr", "euc-k",
160                 "windows-874", "tis",
161         };
162         int i;
163         for(i=0; i<nelem(tab); i++)
164                 if(cistrcmp(tab[i].alias, name) == 0)
165                         return tab[i].name;
166         return name;
167 }
168
169 struct convert *
170 conv(char *name, int from)
171 {
172         struct convert *c;
173
174         name = aliasname(name);
175         for(c = convert; c->name; c++){
176                 if(cistrcmp(c->name, name) != 0)
177                         continue;
178                 if(c->flags&Table)
179                         return(c);
180                 if(((c->flags&From) == 0) == (from == 0))
181                         return(c);
182         }
183         sysfatal("charset `%s' unknown", name);
184         return(0);      /* just shut the compiler up */
185 }
186
187 static int
188 cread(int fd, void *buf, int len, int mod)
189 {
190         char *off = buf;
191
192         len -= (len % mod);
193 Again:
194         len = read(fd, off, len);
195         if(len <= 0)
196                 return len;
197         off += len;
198         len = off - (char*)buf;
199         if((len % mod) != 0){
200                 len = mod - (len % mod);
201                 goto Again;
202         }
203         return len;
204 }
205
206 void
207 unicode_in_be(int fd, long *, struct convert *out)
208 {
209         uchar buf[2*N], *p, *e;
210         Rune *r, r2;
211         int n;
212
213         r2 = 0;
214         while((n = cread(fd, (char*)buf, 2*N, 2)) > 0){
215                 ninput += n;
216                 p = buf;
217                 e = buf + n;
218                 r = runes;
219                 while(p < e){
220                         *r = *p++ << 8;
221                         *r |= *p++;
222                         if(fixsurrogate(r, r2)){
223                                 r2 = *r;
224                                 continue;
225                         }
226                         r2 = 0;
227                         r++;
228                 }
229                 if(r > runes){
230                         OUT(out, runes, r-runes);
231                 }
232         }
233         OUT(out, runes, 0);
234 }
235
236 void
237 unicode_in_le(int fd, long *, struct convert *out)
238 {
239         uchar buf[2*N], *p, *e;
240         Rune *r, r2;
241         int n;
242
243         r2 = 0;
244         while((n = cread(fd, (char*)buf, 2*N, 2)) > 0){
245                 ninput += n;
246                 p = buf;
247                 e = buf + n;
248                 r = runes;
249                 while(p < e){
250                         *r = *p++;
251                         *r |= *p++ << 8;
252                         if(fixsurrogate(r, r2)){
253                                 r2 = *r;
254                                 continue;
255                         }
256                         r2 = 0;
257                         r++;
258                 }
259                 if(r > runes){
260                         OUT(out, runes, r-runes);
261                 }
262         }
263         OUT(out, runes, 0);
264 }
265
266 void
267 unicode_in(int fd, long *notused, struct convert *out)
268 {
269         uchar bom[2];
270         Rune r;
271
272         if(cread(fd, (char *)bom, 2, 2) != 2)
273                 return;
274         ninput += 2;
275         r = bom[0];
276         r |= bom[1]<<8;
277         switch(r)
278         {
279         default:
280                 OUT(out, &r, 1);
281         case 0xFEFF:
282                 unicode_in_le(fd, notused, out);
283                 break;
284         case 0xFFFE:
285                 unicode_in_be(fd, notused, out);
286                 break;
287         }
288 }
289
290 void
291 unicode_out_be(Rune *base, int n, long *)
292 {
293         int i;
294         uchar *p;
295         unsigned long r;
296
297         p = (uchar*)base;
298         for(i=0; i<n; i++){
299                 r = base[i];
300                 if(r > 0xFFFF){
301                         r -= 0x10000;
302                         *p++ = ((r>>18)&3) + 0xD8;
303                         *p++ = r>>10;
304                         *p++ = ((r>>8)&3) + 0xDC;
305                         *p++ = r;
306                 } else {
307                         *p++ = r>>8;
308                         *p++ = r;
309                 }
310         }
311         nrunes += n;
312         n = p - (uchar*)base;
313         noutput += n;
314         if(n > 0)
315                 write(1, base, n);
316 }
317
318 void
319 unicode_out_le(Rune *base, int n, long *)
320 {
321         int i;
322         uchar *p;
323         unsigned long r;
324
325         p = (uchar*)base;
326         for(i=0; i<n; i++){
327                 r = base[i];
328                 if(r > 0xFFFF){
329                         r -= 0x10000;
330                         *p++ = r>>10;
331                         *p++ = ((r>>18)&3) + 0xD8;
332                         *p++ = r;
333                         *p++ = ((r>>8)&3) + 0xDC;
334                 } else {
335                         *p++ = r;
336                         *p++ = r>>8;
337                 }
338         }
339         nrunes += n;
340         n = p - (uchar*)base;
341         noutput += n;
342         if(n > 0)
343                 write(1, (char *)base, n);
344 }
345
346 void
347 unicode_out(Rune *base, int n, long *notused)
348 {
349         static Rune first = 0xFEFF;
350
351         if(first){
352                 unicode_out_le(&first, 1, notused);
353                 first = 0;
354         }
355         unicode_out_le(base, n, notused);
356 }
357
358 void
359 intable(int fd, long *table, struct convert *out)
360 {
361         uchar buf[N];
362         uchar *p, *e;
363         Rune *r;
364         int n;
365         long c;
366
367         while((n = read(fd, (char *)buf, N)) > 0){
368                 ninput += n;
369                 r = runes;
370                 for(p = buf, e = buf+n; p < e; p++){
371                         c = table[*p];
372                         if(c < 0){
373                                 if(squawk)
374                                         warn("bad char 0x%x near byte %zd in %s", *p, ninput+(p-e), file);
375                                 nerrors++;
376                                 if(clean)
377                                         continue;
378                                 c = BADMAP;
379                         }
380                         *r++ = c;
381                 }
382                 OUT(out, runes, r-runes);
383         }
384         OUT(out, runes, 0);
385         if(n < 0)
386                 sysfatal("input read: %r");
387 }
388
389 void
390 outtable(Rune *base, int n, long *map)
391 {
392         long c;
393         char *p;
394         int i;
395
396         nrunes += n;
397         for(i = 0; i < NRUNE; i++)
398                 tab[i] = -1;
399         for(i = 0; i < 256; i++)
400                 if(map[i] >= 0)
401                         tab[map[i]] = i;
402         for(i = 0, p = obuf; i < n; i++){
403                 c = base[i];
404                 if(c < NRUNE)
405                         c = tab[c];
406                 else
407                         c = -1;
408                 if(c < 0){
409                         if(squawk)
410                                 warn("rune 0x%x not in output cs", base[i]);
411                         nerrors++;
412                         if(clean)
413                                 continue;
414                         c = BADMAP;
415                 }
416                 *p++ = c;
417         }
418         noutput += p-obuf;
419         if(p > obuf)
420                 write(1, obuf, p-obuf);
421 }
422
423 int
424 fixsurrogate(Rune *rp, Rune r2)
425 {
426         Rune r1;
427
428         r1 = *rp;
429         if(r1 >= 0xD800 && r1 <= 0xDBFF){
430                 if(r2 >= 0xDC00 && r2 <= 0xDFFF){
431                         *rp = 0x10000 + (((r1 - 0xD800)<<10) | (r2 - 0xDC00));
432                         return 0;
433                 }
434                 return 1;
435         } else
436         if(r1 >= 0xDC00 && r1 <= 0xDFFF){
437                 if(r2 >= 0xD800 && r2 <= 0xDBFF){
438                         *rp = 0x10000 + (((r2 - 0xD800)<<10) | (r1 - 0xDC00));
439                         return 0;
440                 }
441                 return 1;
442         }
443         return 0;
444 }
445
446 long tabascii[256] =
447 {
448 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
449 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
450 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
451 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
452 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
453 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
454 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
455 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
456   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
457   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
458   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
459   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
460   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
461   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
462   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
463   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
464 };
465
466 long tabmsdos[256] =    /* from jhelling@cs.ruu.nl (Jeroen Hellingman) */
467 {
468 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
469 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
470 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
471 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
472 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
473 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
474 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
475 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
476 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, /* latin */
477 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
478 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
479 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
480 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
481 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
482 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, /* forms */
483 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
484 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
485 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
486 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 
487 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
488 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, /* greek */
489 0x03a6, 0x0398, 0x2126, 0x03b4, 0x221e, 0x2205, 0x2208, 0x2229,
490 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, /* math */
491 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0,
492 };
493 long tabmsdos2[256] =   /* from jhelling@cs.ruu.nl (Jeroen Hellingman) */
494 {
495 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
496 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
497 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x2043, 0x21a8,
498 0x2191, 0x2193, 0x2192, 0x2190, 0x2319, 0x2194, 0x25b2, 0x25bc,
499 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
500 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
501 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
502 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
503 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
504 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
505 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, /* latin */
506 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
507 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
508 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
509 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
510 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
511 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, /* forms */
512 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
513 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
514 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
515 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 
516 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
517 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, /* greek */
518 0x03a6, 0x0398, 0x2126, 0x03b4, 0x221e, 0x2205, 0x2208, 0x2229,
519 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, /* math */
520 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0,
521 };
522 struct convert convert[] =
523 {       /* if two entries have the same name, put the from one first */
524         { "8859-1", "Latin-1 (Western and Northern Europe including Italian)", Table, (void *)tab8859_1 },
525         { "8859-2", "Latin-2 (Eastern Europe except Turkey and the Baltic countries)", Table, (void *)tab8859_2 },
526         { "8859-3", "Latin-3 (Mediterranean, South Africa, Esperanto)", Table, (void *)tab8859_3 },
527         { "8859-4", "Latin-4 (Scandinavia and the Baltic countries; obsolete)", Table, (void *)tab8859_4 },
528         { "8859-5", "Part 5 (Cyrillic)", Table, (void *)tab8859_5 },
529         { "8859-6", "Part 6 (Arabic)", Table, (void *)tab8859_6 },
530         { "8859-7", "Part 7 (Greek)", Table, (void *)tab8859_7 },
531         { "8859-8", "Part 8 (Hebrew)", Table, (void *)tab8859_8 },
532         { "8859-9", "Latin-5 (Turkey, Western Europe except Icelandic and Faroese)", Table, (void *)tab8859_9 },
533         { "8859-10", "Latin-6 (Northern Europe)", Table, (void *)tab8859_10 },
534         { "8859-15", "Latin-9 (Western Europe)", Table, (void *)tab8859_15 },
535         { "ascii", "7-bit ASCII", Table, (void *)tabascii },
536         { "atari", "ATARI-ST character set", Table, (void *)tabatari },
537         { "av", "Alternativnyj Variant", Table, (void *)tabav },
538         { "big5", "Big 5 (HKU)", From|Func, 0, (Fnptr)big5_in },
539         { "big5", "Big 5 (HKU)", Func, 0, (Fnptr)big5_out },
540         { "ebcdic", "EBCDIC", Table, (void *)tabebcdic },       /* 6f is recommended bad map */
541         { "euc-k", "Korean EUC: ASCII+KS C 5601 1987", From|Func, 0, (Fnptr)uksc_in },
542         { "euc-k", "Korean EUC: ASCII+KS C 5601 1987", Func, 0, (Fnptr)uksc_out },
543         { "gb2312", "GB2312-80 (Chinese)", From|Func, 0, (Fnptr)gb_in },
544         { "gb2312", "GB2312-80 (Chinese)", Func, 0, (Fnptr)gb_out },
545         { "gbk", "GBK (Chinese)", From|Func, 0, (Fnptr)gbk_in },
546         { "gbk", "GBK (Chinese)", Func, 0, (Fnptr)gbk_out },
547         { "html", "HTML", From|Func, 0, (Fnptr)html_in },
548         { "html", "HTML", Func, 0, (Fnptr)html_out },
549         { "ibm437", "IBM Code Page 437 (US)", Table, (void*)tabcp437 },
550         { "ibm720", "IBM Code Page 720 (Arabic)", Table, (void*)tabcp720 },
551         { "ibm737", "IBM Code Page 737 (Greek)", Table, (void*)tabcp737 },
552         { "ibm775", "IBM Code Page 775 (Baltic)", Table, (void*)tabcp775 },
553         { "ibm850", "IBM Code Page 850 (Multilingual Latin I)", Table, (void*)tabcp850 },
554         { "ibm852", "IBM Code Page 852 (Latin II)", Table, (void*)tabcp852 },
555         { "ibm855", "IBM Code Page 855 (Cyrillic)", Table, (void*)tabcp855 },
556         { "ibm857", "IBM Code Page 857 (Turkish)", Table, (void*)tabcp857 },
557         { "ibm858", "IBM Code Page 858 (Multilingual Latin I+Euro)", Table, (void*)tabcp858 },
558         { "ibm862", "IBM Code Page 862 (Hebrew)", Table, (void*)tabcp862 },
559         { "ibm866", "IBM Code Page 866 (Russian)", Table, (void*)tabcp866 },
560         { "ibm874", "IBM Code Page 874 (Thai)", Table, (void*)tabcp874 },
561         { "iso-2022-jp", "alias for jis-kanji (MIME)", From|Func, 0, (Fnptr)jisjis_in },
562         { "iso-2022-jp", "alias for jis-kanji (MIME)", Func, 0, (Fnptr)jisjis_out },
563         { "iso-8859-1", "alias for 8859-1 (MIME)", Table, (void *)tab8859_1 },
564         { "iso-8859-2", "alias for 8859-2 (MIME)", Table, (void *)tab8859_2 },
565         { "iso-8859-3", "alias for 8859-3 (MIME)", Table, (void *)tab8859_3 },
566         { "iso-8859-4", "alias for 8859-4 (MIME)", Table, (void *)tab8859_4 },
567         { "iso-8859-5", "alias for 8859-5 (MIME)", Table, (void *)tab8859_5 },
568         { "iso-8859-6", "alias for 8859-6 (MIME)", Table, (void *)tab8859_6 },
569         { "iso-8859-7", "alias for 8859-7 (MIME)", Table, (void *)tab8859_7 },
570         { "iso-8859-8", "alias for 8859-8 (MIME)", Table, (void *)tab8859_8 },
571         { "iso-8859-9", "alias for 8859-9 (MIME)", Table, (void *)tab8859_9 },
572         { "iso-8859-10", "alias for 8859-10 (MIME)", Table, (void *)tab8859_10 },
573         { "iso-8859-15", "alias for 8859-15 (MIME)", Table, (void *)tab8859_15 },
574         { "jis", "guesses at the JIS encoding", From|Func, 0, (Fnptr)jis_in },
575         { "jis-kanji", "ISO 2022-JP (Japanese)", From|Func, 0, (Fnptr)jisjis_in },
576         { "jis-kanji", "ISO 2022-JP (Japanese)", Func, 0, (Fnptr)jisjis_out },
577         { "koi8", "KOI-8 (GOST 19769-74)", Table, (void *)tabkoi8 },
578         { "koi8-r", "alias for koi8 (MIME)", Table, (void *)tabkoi8 },
579         { "latin1", "alias for 8859-1", Table, (void *)tab8859_1 },
580         { "macrom", "Macintosh Standard Roman character set", Table, (void *)tabmacroman },
581         { "microsoft", "alias for windows1252", Table, (void *)tabcp1252 },
582         { "ms-kanji", "Microsoft, or Shift-JIS", From|Func, 0, (Fnptr)msjis_in },
583         { "ms-kanji", "Microsoft, or Shift-JIS", Func, 0, (Fnptr)msjis_out },
584         { "msdos", "IBM PC (alias for ibm437)", Table, (void *)tabcp437 },
585         { "msdos2", "IBM PC (ibm437 with graphics in C0)", Table, (void *)tabmsdos2 },
586         { "next", "NEXTSTEP character set", Table, (void *)tabnextstep },
587         { "ov", "Osnovnoj Variant", Table, (void *)tabov },
588         { "ps2", "IBM PS/2: (alias for ibm850)", Table, (void *)tabcp850 },
589         { "sf1", "ISO-646: Finnish/Swedish SF-1 variant", Table, (void *)tabsf1 },
590         { "sf2", "ISO-646: Finnish/Swedish SF-2 variant (recommended)", Table, (void *)tabsf2 },
591         { "tis-620", "Thai+ASCII (TIS 620-1986)", Table, (void *)tabtis620 },
592         { "tune", "TUNE (Tamil)", From|Func, 0, (Fnptr)tune_in },
593         { "tune", "TUNE (Tamil)", Func, 0, (Fnptr)tune_out },
594         { "ucode", "Russian U-code", Table, (void *)tabucode },
595         { "ujis", "EUC-JX: JIS 0208", From|Func, 0, (Fnptr)ujis_in },
596         { "ujis", "EUC-JX: JIS 0208", Func, 0, (Fnptr)ujis_out },
597         { "unicode", "Unicode 1.1", From|Func, 0, (Fnptr)unicode_in },
598         { "unicode", "Unicode 1.1", Func, 0, (Fnptr)unicode_out },
599         { "unicode-be", "Unicode 1.1 big-endian", From|Func, 0, (Fnptr)unicode_in_be },
600         { "unicode-be", "Unicode 1.1 big-endian", Func, 0, (Fnptr)unicode_out_be },
601         { "unicode-le", "Unicode 1.1 little-endian", From|Func, 0, (Fnptr)unicode_in_le },
602         { "unicode-le", "Unicode 1.1 little-endian", Func, 0, (Fnptr)unicode_out_le },
603         { "us-ascii", "alias for ascii (MIME)", Table, (void *)tabascii },
604         { "utf", "FSS-UTF a.k.a. UTF-8", From|Func, 0, (Fnptr)utf_in },
605         { "utf", "FSS-UTF a.k.a. UTF-8", Func, 0, (Fnptr)utf_out },
606         { "utf1", "UTF-1 (ISO 10646 Annex A)", From|Func, 0, (Fnptr)isoutf_in },
607         { "utf1", "UTF-1 (ISO 10646 Annex A)", Func, 0, (Fnptr)isoutf_out },
608         { "utf-8", "alias for utf (MIME)", From|Func, 0, (Fnptr)utf_in },
609         { "utf-8", "alias for utf (MIME)", Func, 0, (Fnptr)utf_out },
610         { "utf-16", "alias for unicode (MIME)", From|Func, 0, (Fnptr)unicode_in },
611         { "utf-16", "alias for unicode (MIME)", Func, 0, (Fnptr)unicode_out },
612         { "utf-16be", "alias for unicode-be (MIME)", From|Func, 0, (Fnptr)unicode_in_be },
613         { "utf-16be", "alias for unicode-be (MIME)", Func, 0, (Fnptr)unicode_out_be },
614         { "utf-16le", "alias for unicode-le (MIME)", From|Func, 0, (Fnptr)unicode_in_le },
615         { "utf-16le", "alias for unicode-le (MIME)", Func, 0, (Fnptr)unicode_out_le },
616         { "viet1", "Vietnamese VSCII-1 (1993)", Table, (void *)tabviet1 },
617         { "viet2", "Vietnamese VSCII-2 (1993)", Table, (void *)tabviet2 },
618         { "vscii", "Vietnamese VISCII 1.1 (1992)", Table, (void *)tabviscii },
619         { "windows-1250", "Windows Code Page 1250 (Central Europe)", Table, (void *)tabcp1250 },
620         { "windows-1251", "Windows Code Page 1251 (Cyrillic)", Table, (void *)tabcp1251 },
621         { "windows-1252", "Windows Code Page 1252 (Latin I)", Table, (void *)tabcp1252 },
622         { "windows-1253", "Windows Code Page 1253 (Greek)", Table, (void *)tabcp1253 },
623         { "windows-1254", "Windows Code Page 1254 (Turkish)", Table, (void *)tabcp1254 },
624         { "windows-1255", "Windows Code Page 1255 (Hebrew)", Table, (void *)tabcp1255 },
625         { "windows-1256", "Windows Code Page 1256 (Arabic)", Table, (void *)tabcp1256 },
626         { "windows-1257", "Windows Code Page 1257 (Baltic)", Table, (void *)tabcp1257 },
627         { "windows-1258", "Windows Code Page 1258 (Vietnam)", Table, (void *)tabcp1258 },
628         { 0 },
629 };