1 /* $NetBSD: chrtbl.c,v 1.11 2009/04/15 00:43:29 lukem Exp $ */
4 * Copyright (c) 1997 Christos Zoulas. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 unsigned short *uptab
;
41 unsigned short *lotab
;
42 char *numericfilename
;
43 unsigned char decimal_point
;
44 unsigned char thousands_sep
;
47 static void usage
__P((void));
48 static int numeric
__P((struct chartbl
*, const char *, int, char *, size_t));
49 static int cswidth
__P((struct chartbl
*, const char *, int, char *, size_t));
50 static int setfilename
__P((struct chartbl
*, const char *, int, char *,
52 static int addattr
__P((struct chartbl
*, const char *, int, char *, size_t));
53 static int uplow
__P((struct chartbl
*, const char *, int, char *, size_t));
54 static void printctype
__P((FILE *, unsigned int));
55 static int output_ascii
__P((const char *, const struct chartbl
*));
56 static int output_binary
__P((const struct chartbl
*));
58 int main
__P((int, char *[]));
60 static const struct toklist
{
62 int (*func
) __P((struct chartbl
*, const char *, int arg
,
66 { "LC_CTYPE", setfilename
, 0 },
67 { "isupper", addattr
, _U
},
68 { "islower", addattr
, _L
},
69 { "isdigit", addattr
, _N
},
70 { "isspace", addattr
, _S
},
71 { "ispunct", addattr
, _P
},
72 { "iscntrl", addattr
, _C
},
73 { "isblank", addattr
, _B
},
74 { "isxdigit", addattr
, _X
},
76 { "cswidth", cswidth
, 0 },
77 { "LC_NUMERIC", setfilename
, 1 },
78 { "decimal_point", numeric
, 0 },
79 { "thousands_sep", numeric
, 0 },
84 * Print a usage message and exit
90 (void) fprintf(stderr
, "usage: %s [-o <filename>] <description>\n",
97 * Parse a decimal_point or thousands_sep line
100 numeric(cs
, token
, arg
, line
, lnum
)
112 * Parse a cswidth line. This is of the form:
113 * cswidth: <n1>:<s1>,<n2>:<s2>,<n3>:<s3>
115 * n1,n2,n3: byte widths of the supplementary codes 1,2,3
116 * s1,s2,s3: screen widths " " "
119 cswidth(cs
, token
, arg
, line
, lnum
)
130 * Set the output file name for LC_CTYPE or LC_NUMERIC
133 setfilename(cs
, token
, arg
, line
, lnum
)
140 char *p
= strtok(line
, " \t");
142 if (p
== NULL
|| *p
== '\0')
145 if ((p
= strdup(p
)) == NULL
)
146 err(1, "Out of memory at line %lu", (u_long
)lnum
);
150 cs
->ctypefilename
= p
;
153 cs
->numericfilename
= p
;
156 warn("%s: Bad filename argument %d at line %lu", token
, arg
,
165 * Parse a character attribute line
166 * The line is of the form <attribute>: <char> | <char> - <char>
169 addattr(cs
, token
, arg
, line
, lnum
)
176 static const char sep
[] = "\t ";
177 size_t b
= 0, e
= 0, n
;
181 for (ptr
= strtok(line
, sep
); ptr
; ptr
= strtok(NULL
, sep
)) {
182 if (strcmp(ptr
, "-") == 0) {
188 n
= (size_t) strtoul(ptr
, &ep
, 0);
189 if (ptr
== ep
|| *ep
) {
190 warnx("%s: Bad number `%s' at line %lu", token
,
199 if (b
> cs
->maxchar
) {
203 cs
->ctype
[b
+1] |= arg
;
209 if (e
> cs
->maxchar
) {
213 for (n
= b
; n
<= e
; n
++)
214 cs
->ctype
[n
+1] |= arg
;
225 if (b
> cs
->maxchar
) {
229 cs
->ctype
[b
+1] |= arg
;
238 warnx("%s: Character %lu out of range at line %lu", token
, (u_long
)n
,
242 warnx("%s: Unexpected state %d at line %lu", token
, st
,
246 warnx("%s: Missing %s range at line %lu", token
,
247 st
== 1 ? "begin" : "end", (u_long
)lnum
);
253 * Parse an upper<->lower case transformation. The format of the line
254 * is ul <upper lower> ...
257 uplow(cs
, token
, arg
, line
, lnum
)
268 while (*p
&& isspace((u_char
) *p
))
279 while (*p
&& isspace((u_char
) *p
))
283 lo
= (size_t) strtol(p
, &ep
, 0);
284 if (p
== ep
|| !isspace((u_char
) *ep
))
287 while (*p
&& isspace((u_char
) *p
))
289 up
= (size_t) strtol(p
, &ep
, 0);
292 if (lo
> cs
->maxchar
)
294 if (up
> cs
->maxchar
) {
298 cs
->lotab
[up
+ 1] = lo
;
299 cs
->uptab
[lo
+ 1] = up
;
315 warnx("%s: Bad token `%s' at line %lu", token
, p
, (u_long
)lnum
);
318 warnx("%s: Out of range character %lx at line %lu", token
, (u_long
)lo
,
325 * Symbolically print an ascii character.
334 #define DO(a) if (__CONCAT(_,a) & ct) { \
336 (void) fputc('|', fp); \
338 (void) fputc('_', fp); \
339 (void) fputs(__STRING(a), fp); \
350 (void) fputc('0', fp
);
355 * Print a `c' symbolic description of the character set
360 const struct chartbl
*ct
;
365 if ((fp
= fopen(fn
, "w")) == NULL
) {
366 warn("Cannot open `%s'", fn
);
370 (void) fprintf(fp
, "/* Automatically generated file; do not edit */\n");
371 (void) fprintf(fp
, "#include <ctype.h>\n");
372 (void) fprintf(fp
, "unsigned char _ctype_[] = { 0");
373 for (i
= 1; i
<= ct
->maxchar
; i
++) {
374 if (((i
- 1) & 7) == 0)
375 (void) fputs(",\n\t", fp
);
376 printctype(fp
, ct
->ctype
[i
]);
378 (void) fputs(",\t", fp
);
380 (void) fprintf(fp
, "\n};\n");
382 (void) fprintf(fp
, "short _tolower_tab_[] = { -1");
383 for (i
= 1; i
<= ct
->maxchar
; i
++) {
384 if (((i
- 1) & 7) == 0)
385 (void) fputs(",\n\t", fp
);
386 (void) fprintf(fp
, "0x%x", ct
->lotab
[i
]);
388 (void) fputs(",\t", fp
);
390 (void) fprintf(fp
, "\n};\n");
392 (void) fprintf(fp
, "short _toupper_tab_[] = { -1");
393 for (i
= 1; i
<= ct
->maxchar
; i
++) {
394 if (((i
- 1) & 7) == 0)
395 (void) fputs(",\n\t", fp
);
396 (void) fprintf(fp
, "0x%x", ct
->uptab
[i
]);
398 (void) fputs(",\t", fp
);
400 (void) fprintf(fp
, "\n};\n");
407 * Print a binary description of the requested character set.
411 const struct chartbl
*ct
;
415 if (ct
->ctypefilename
!= NULL
) {
416 if (!__savectype(ct
->ctypefilename
, ct
->ctype
, ct
->lotab
,
418 err(1, "Cannot creating/writing `%s'",
422 warnx("No output file for LC_CTYPE specified");
436 char *line
, *token
, *p
;
437 const struct toklist
*t
;
441 char *ifname
, *ofname
= NULL
;
444 while ((c
= getopt(argc
, argv
, "o:")) != -1)
454 if (argc
- 1 != optind
)
457 ifname
= argv
[optind
];
459 if ((fp
= fopen(ifname
, "r")) == NULL
)
460 err(1, "Cannot open `%s'", ifname
);
463 ct
.ctype
= malloc(sizeof(ct
.ctype
[0]) * (ct
.maxchar
+ 1));
464 ct
.uptab
= malloc(sizeof(ct
.uptab
[0]) * (ct
.maxchar
+ 1));
465 ct
.lotab
= malloc(sizeof(ct
.lotab
[0]) * (ct
.maxchar
+ 1));
466 ct
.ctypefilename
= NULL
;
467 ct
.numericfilename
= NULL
;
468 ct
.decimal_point
= '.';
469 ct
.thousands_sep
= ',';
471 if (ct
.ctype
== NULL
|| ct
.uptab
== NULL
|| ct
.lotab
== NULL
)
472 err(1, "Out of memory");
474 (void) memset(ct
.ctype
, 0, sizeof(ct
.ctype
[0]) * (ct
.maxchar
* 1));
475 (void) memset(ct
.uptab
, 0, sizeof(ct
.uptab
[0]) * (ct
.maxchar
* 1));
476 (void) memset(ct
.lotab
, 0, sizeof(ct
.lotab
[0]) * (ct
.maxchar
* 1));
478 for (lnum
= 1; (line
= fparseln(fp
, &size
, &lnum
, NULL
, 0)) != NULL
;
480 for (token
= line
; *token
&& isspace((u_char
) *token
); token
++)
484 for (p
= token
; *p
&& !isspace((u_char
) *p
); p
++)
489 for (p
++; *p
&& isspace((u_char
) *p
); p
++)
491 for (t
= tokens
; t
->name
!= NULL
; t
++)
492 if (strcmp(t
->name
, token
) == 0)
494 if (t
->name
== NULL
) {
495 warnx("Unknown token %s at line %lu", token
,
500 error
|= (*t
->func
)(&ct
, token
, t
->arg
, p
, lnum
);
504 for (i
= 1; i
<= ct
.maxchar
; i
++) {
505 if (ct
.uptab
[i
] == 0)
507 if (ct
.lotab
[i
] == 0)
512 error
|= output_ascii(ofname
, &ct
);
513 error
|= output_binary(&ct
);