Blob


1 /*
2 * Parse /lib/keyboard to create latin1.h table for kernel.
3 * mklatinkbd -r prints an array of integers rather than a Rune string literal.
4 */
6 #include <u.h>
7 #include <libc.h>
8 #include <bio.h>
9 #include <ctype.h>
11 int rflag;
12 int xflag;
14 enum {
15 MAXLD = 2, /* latin1.c assumes this is 2 */
16 };
18 char *head = ""
19 "/*\n"
20 " * This is automatically generated by %s from /lib/keyboard\n"
21 " * Edit /lib/keyboard instead.\n"
22 " */\n";
24 /*
25 * latin1.c assumes that strlen(ld) is at most 2.
26 * It also assumes that latintab[i].ld can be a prefix of latintab[j].ld
27 * only when j < i. We ensure this by sorting the output by prefix length.
28 * The so array is indexed by the character value.
29 */
31 typedef struct Trie Trie;
32 struct Trie {
33 int n; /* of characters r */
34 char seq[MAXLD+1+1];
35 Rune r[256];
36 Trie *link[256];
37 };
39 Trie *root;
41 Trie*
42 mktrie(char *seq)
43 {
44 uchar *q;
45 Trie **tp;
47 if(root == nil) {
48 root = malloc(sizeof *root);
49 memset(root, 0, sizeof *root);
50 }
52 assert(seq[0] != '\0');
54 tp = &root;
55 for(q=(uchar*)seq; *(q+1) != '\0'; q++) {
56 tp = &(*tp)->link[*q];
57 if(*tp == nil) {
58 *tp = malloc(sizeof(**tp));
59 assert(*tp != nil);
60 memset(*tp, 0, sizeof(**tp));
61 strcpy((*tp)->seq, seq);
62 (*tp)->seq[q+1-(uchar*)seq] = '\0';
63 }
64 }
66 assert(*tp != nil);
67 return *tp;
68 }
70 /* add character sequence s meaning rune r */
71 void
72 insert(char *s, Rune r)
73 {
74 uchar lastc;
75 int len;
76 Trie *t;
78 len = strlen(s);
79 lastc = (uchar)s[len-1];
81 t = mktrie(s);
82 if(t->r[lastc]) {
83 fprint(2, "warning: table duplicate: %s is %C and %C\n", s, t->r[lastc], r);
84 return;
85 }
86 t->r[lastc] = r;
87 t->n++;
88 }
90 void
91 cprintchar(Biobuf *b, int c)
92 {
93 /* print a byte c safe for a C string. */
94 switch(c) {
95 case '\'':
96 case '\"':
97 case '\\':
98 Bprint(b, "\\%c", c);
99 break;
100 case '\t':
101 Bprint(b, "\\t");
102 break;
103 default:
104 if(isascii(c) && isprint(c))
105 Bprint(b, "%c", c);
106 else
107 Bprint(b, "\\x%.2x", c);
108 break;
112 void
113 cprints(Biobuf *b, char *p)
115 while(*p != '\0')
116 cprintchar(b, *p++);
119 void
120 xprint(Biobuf *b, int c)
124 void
125 printtrie(Biobuf *b, Trie *t)
127 int i;
128 char *p;
130 for(i=0; i<256; i++)
131 if(t->link[i])
132 printtrie(b, t->link[i]);
133 if(t->n == 0)
134 return;
136 if(xflag) {
137 for(i=0; i<256; i++) {
138 if(t->r[i] == 0)
139 continue;
140 Bprint(b, "<Multi_key>");
141 for(p=t->seq; *p; p++)
142 Bprint(b, " %k", *p);
143 Bprint(b, " %k : \"%C\" U%04X\n", i, t->r[i], t->r[i]);
145 return;
148 Bprint(b, "\t\"");
149 cprints(b, t->seq);
150 Bprint(b, "\", \"");
151 for(i=0; i<256; i++)
152 if(t->r[i])
153 cprintchar(b, i);
154 Bprint(b, "\",\t");
155 if(rflag) {
156 Bprint(b, "{");
157 for(i=0; i<256; i++)
158 if(t->r[i])
159 Bprint(b, " 0x%.4ux,", t->r[i]);
160 Bprint(b, " }");
161 } else {
162 Bprint(b, "L\"");
163 for(i=0; i<256; i++)
164 if(t->r[i])
165 Bprint(b, "%C", t->r[i]);
166 Bprint(b, "\"");
168 Bprint(b, ",\n");
171 void
172 readfile(char *fname)
174 Biobuf *b;
175 char *line, *p;
176 char *seq;
177 int inseq;
178 int lineno;
179 Rune r;
181 if((b = Bopen(fname, OREAD)) == 0) {
182 fprint(2, "cannot open \"%s\": %r\n", fname);
183 exits("open");
186 lineno = 0;
187 while((line = Brdline(b, '\n')) != 0) {
188 lineno++;
189 if(line[0] == '#')
190 continue;
192 r = strtol(line, nil, 16);
193 p = strchr(line, ' ');
194 if(r == 0 || (p != line+4 && p != line+5) || p[0] != ' ' || (p == line+4 && p[1] != ' ')) {
195 fprint(2, "%s:%d: cannot parse line\n", fname, lineno);
196 continue;
199 p = line+6;
200 /* 00AE Or rO ® registered trade mark sign */
201 for(inseq=1, seq=p; (uchar)*p < Runeself; p++) {
202 if(*p == '\0' || isspace(*p)) {
203 if(inseq && p-seq >= 2) {
204 *p = '\0';
205 inseq = 0;
206 insert(seq, r);
207 *p = ' ';
209 if(*p == '\0')
210 break;
211 } else {
212 if(!inseq) {
213 seq = p;
214 inseq = 1;
221 void
222 usage(void)
224 fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n");
225 exits("usage");
228 int kfmt(Fmt*);
230 void
231 main(int argc, char **argv)
233 int i;
234 Biobuf bout;
236 ARGBEGIN{
237 case 'r': /* print rune values */
238 rflag = 1;
239 break;
240 case 'x':
241 xflag = 1;
242 break;
243 default:
244 usage();
245 }ARGEND
247 if(argc > 1)
248 usage();
250 fmtinstall('k', kfmt);
251 readfile(argc == 1 ? argv[0] : "/dev/stdin");
253 Binit(&bout, 1, OWRITE);
254 if(xflag) {
255 Bprint(&bout, "# Generated by mklatinkbd -x; do not edit.\n");
256 for(i=0x20; i<0x10000; i++)
257 Bprint(&bout, "<Multi_key> <X> <%x> <%x> <%x> <%x> : \"%C\" U%04X\n",
258 (i>>12)&0xf, (i>>8)&0xf, (i>>4)&0xf, i&0xf, i, i);
260 if(root)
261 printtrie(&bout, root);
262 exits(0);
265 // X11 key names
267 struct {
268 int c;
269 char *s;
270 } xkey[] = {
271 ' ', "space",
272 '!', "exclam",
273 '"', "quotedbl",
274 '#', "numbersign",
275 '$', "dollar",
276 '%', "percent",
277 '&', "ampersand",
278 '\'', "apostrophe",
279 '(', "parenleft",
280 ')', "parenright",
281 '*', "asterisk",
282 '+', "plus",
283 ',', "comma",
284 '-', "minus",
285 '.', "period",
286 '/', "slash",
287 ':', "colon",
288 ';', "semicolon",
289 '<', "less",
290 '=', "equal",
291 '>', "greater",
292 '?', "question",
293 '@', "at",
294 '[', "bracketleft",
295 '\\', "backslash",
296 ',', "bracketright",
297 '^', "asciicircum",
298 '_', "underscore",
299 '`', "grave",
300 '{', "braceleft",
301 '|', "bar",
302 '}', "braceright",
303 '~', "asciitilde",
304 0, 0
305 };
307 int
308 kfmt(Fmt *f)
310 int i, c;
312 c = va_arg(f->args, int);
313 for(i=0; xkey[i].s; i++)
314 if(xkey[i].c == c)
315 return fmtprint(f, "<%s>", xkey[i].s);
316 return fmtprint(f, "<%c>", c);