option.c: fixed warnings
[k8jam.git] / src / unigen.c
blobe13a4b722ee5759074a2f4b1517a1500b6141b90
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
23 static char *trim (char *str) {
24 char *s;
25 if (str == NULL) return NULL;
26 for (s = str; *s && isspace(*s); ++s) ;
27 if (s > str) memmove(str, s, strlen(s)+1);
28 for (s = str+strlen(str)-1; s >= str && isspace(*s); --s) ;
29 s[1] = 0;
30 return str;
34 static int hex2num (char *s) {
35 char *end;
36 int res;
37 trim(s);
38 if (!s[0]) return -1;
39 res = strtol(s, &end, 16);
40 if (end[0] || res < 0) return -1;
41 return res;
45 typedef struct {
46 int code;
47 const char *name;
48 const char *class;
49 int upper;
50 int lower;
51 } UCInfo;
54 static char *stx = NULL;
56 static char *tok (void) {
57 char *s = stx;
58 for (; *stx && *stx != ';'; ++stx) ;
59 if (*stx) *stx++ = 0;
60 return s;
64 // <0: eof; 0: bad record; >0: good record
65 static int read_record (FILE *fi, UCInfo *ui) {
66 static char str[8192];
67 char *tk, *u, *l;
68 int f;
69 if (fgets(str, sizeof(str)-1, fi) == NULL) return -1;
70 stx = trim(str);
71 if ((tk = tok()) == NULL) return 0;
72 if ((ui->code = hex2num(tk)) < 0) return 0;
73 if (ui->code > 65535) return -1;
74 if ((ui->name = trim(tok())) == NULL) return 0;
75 if ((ui->class = trim(tok())) == NULL) return 0;
76 // skip unused fields
77 for (f = 9; f > 0; --f) if (tok() == NULL) { printf("%d\n", f); return 0; }
78 if ((u = trim(tok())) == NULL) return 0;
79 if ((l = trim(tok())) == NULL) return 0;
80 if (!u[0]) ui->upper = ui->code; else ui->upper = hex2num(u);
81 if (!l[0]) ui->lower = ui->code; else ui->lower = hex2num(l);
82 if (ui->upper < 0 || ui->lower < 0) return 0;
83 if (ui->upper > 65535 || ui->lower > 65535) abort();
84 return 1;
88 typedef struct {
89 int code, l, u;
90 } mm;
92 static mm map[65535];
95 static int mm_cmp (const void *p0, const void *p1) {
96 const mm *i0 = (const mm *)p0;
97 const mm *i1 = (const mm *)p1;
98 return (i0->code < i1->code ? -1 : (i0->code > i1->code ? 1 : 0));
102 int main (int argc, char *argv[]) {
103 UCInfo ui;
104 int rc, f, totalmap = 0;
105 FILE *fi, *fo;
106 if (argc != 3) { fprintf(stderr, "usage: %s unitable.c unitable.txt\n", argv[0]); exit(1); }
107 if ((fi = fopen(argv[2], "r")) == NULL) { fprintf(stderr, "FATAL: can't open input file: '%s'\n", argv[2]); exit(1); }
108 for (;;) {
109 rc = read_record(fi, &ui);
110 if (rc < 0) break;
111 if (rc == 0) continue;
112 if (ui.code < 128) continue;
113 if (strcmp(ui.class, "Lu") != 0 && strcmp(ui.class, "Ll") != 0) continue;
114 if (ui.upper == ui.code && ui.lower == ui.code) continue;
115 for (f = 0; f < totalmap; ++f) {
116 if (map[f].code == ui.code) { fprintf(stderr, "FATAL: duplicate entries in the map!\n"); exit(1); }
117 if (map[f].code > ui.code) { fprintf(stderr, "FATAL: invalid entry order in the map!\n"); exit(1); }
119 if (totalmap > 65535) { fprintf(stderr, "FATAL: too many entries in the map!\n"); exit(1); }
120 map[totalmap].code = ui.code;
121 map[totalmap].l = ui.lower;
122 map[totalmap].u = ui.upper;
123 ++totalmap;
125 fclose(fi);
126 qsort(map, totalmap, sizeof(map[0]), mm_cmp);
127 fo = fopen(argv[1], "w");
128 if (fo == NULL) { fprintf(stderr, "FATAL: can't create output file: '%s'\n", argv[1]); exit(1); }
129 fprintf(fo, "static const struct casemap unicode_case_mapping[%d] = {\n", totalmap);
130 for (f = 0; f < totalmap; ++f) fprintf(fo, "{0x%04x,0x%04x,0x%04x},\n", map[f].code, map[f].l, map[f].u);
131 fprintf(fo, "%s\n", "};");
132 fclose(fo);
133 return 0;