fixed pkg-config rule
[k8jam.git] / src / unigen.c
blobe9fe1d11110c798a7472485f7c62a723360c33bd
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
8 static FILE *fi;
10 static void openFile (const char *fname) {
11 fi = fopen(fname, "r");
12 if (fi == NULL) { fprintf(stderr, "FATAL: can't open input file: '%s'\n", fname); exit(1); }
16 static char *trim (char *str) {
17 char *s;
19 if (str == NULL) return NULL;
20 for (s = str; *s && isspace(*s); ++s) ;
21 if (s > str) memmove(str, s, strlen(s)+1);
22 for (s = str+strlen(str)-1; s >= str && isspace(*s); --s) ;
23 s[1] = 0;
24 return str;
28 static int hex2num (char *s) {
29 char *end;
30 int res;
32 trim(s);
33 if (!s[0]) return -1;
34 res = strtol(s, &end, 16);
35 if (end[0] || res < 0) return -1;
36 return res;
40 typedef struct {
41 int code;
42 const char *name;
43 const char *class;
44 int upper;
45 int lower;
46 } UCInfo;
49 static char *stx = NULL;
51 static char *tok (void) {
52 char *s = stx;
53 for (; *stx && *stx != ';'; ++stx) ;
54 if (*stx) *stx++ = 0;
55 return s;
59 // <0: eof; 0: bad record; >0: good record
60 static int readRecord (UCInfo *ui) {
61 static char str[8192];
62 char *tk, *u, *l;
63 int f;
65 if (fgets(str, sizeof(str)-1, fi) == NULL) return -1;
66 stx = trim(str);
67 if ((tk = tok()) == NULL) return 0;
68 if ((ui->code = hex2num(tk)) < 0) return 0;
69 if (ui->code > 65535) return -1;
70 if ((ui->name = trim(tok())) == NULL) return 0;
71 if ((ui->class = trim(tok())) == NULL) return 0;
72 // skip unused fields
73 for (f = 9; f > 0; --f) if (tok() == NULL) { printf("%d\n", f); return 0; }
74 if ((u = trim(tok())) == NULL) return 0;
75 if ((l = trim(tok())) == NULL) return 0;
76 if (!u[0]) ui->upper = ui->code; else ui->upper = hex2num(u);
77 if (!l[0]) ui->lower = ui->code; else ui->lower = hex2num(l);
78 if (ui->upper < 0 || ui->lower < 0) return 0;
79 if (ui->upper > 65535 || ui->lower > 65535) abort();
80 return 1;
84 static struct {
85 int code, l, u;
86 } map[65535];
89 int main (int argc, char *argv[]) {
90 UCInfo ui;
91 int rc, f, totalmap = 0;
92 FILE *fo;
94 if (argc != 3) { fprintf(stderr, "usage: %s unitable.c unitable.txt\n", argv[0]); exit(1); }
96 openFile(argv[2]);
97 for (;;) {
98 rc = readRecord(&ui);
99 if (rc < 0) break;
100 if (rc == 0) continue;
101 if (ui.code < 128) continue;
102 if (strcmp(ui.class, "Lu") != 0 && strcmp(ui.class, "Ll") != 0) continue;
103 if (ui.upper == ui.code && ui.lower == ui.code) continue;
105 for (f = 0; f < totalmap; ++f) {
106 if (map[f].code == ui.code) { fprintf(stderr, "FATAL: duplicate entries in the map!\n"); exit(1); }
107 if (map[f].code > ui.code) { fprintf(stderr, "FATAL: invalid entry order in the map!\n"); exit(1); }
110 map[totalmap].code = ui.code;
111 map[totalmap].l = ui.lower;
112 map[totalmap].u = ui.upper;
113 ++totalmap;
114 if (totalmap > 65535) { fprintf(stderr, "FATAL: too many entries in the map!\n"); exit(1); }
116 fclose(fi);
118 fo = fopen(argv[1], "w");
119 if (fo == NULL) { fprintf(stderr, "FATAL: can't create output file: '%s'\n", argv[1]); exit(1); }
120 fprintf(fo, "static const struct casemap unicode_case_mapping[%d] = {\n", totalmap);
121 for (f = 0; f < totalmap; ++f) fprintf(fo, "{0x%04x,0x%04x,0x%04x},\n", map[f].code, map[f].l, map[f].u);
122 fprintf(fo, "%s\n", "};");
123 fclose(fo);
124 return 0;