]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/mklatinkbd.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / cmd / aux / mklatinkbd.c
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  */
5
6 #include <u.h>
7 #include <libc.h>
8 #include <bio.h>
9 #include <ctype.h>
10
11 int rflag;
12
13 enum {
14         MAXLD = 2,      /* latin1.c assumes this is 2 */
15 };
16
17 char *head = ""
18 "/*\n"
19 " * This is automatically generated by %s from /lib/keyboard\n"
20 " * Edit /lib/keyboard instead.\n"
21 " */\n";
22
23 /*
24  * latin1.c assumes that strlen(ld) is at most 2.
25  * It also assumes that latintab[i].ld can be a prefix of latintab[j].ld
26  * only when j < i.  We ensure this by sorting the output by prefix length.
27  * The so array is indexed by the character value.
28  */
29
30 typedef struct Trie     Trie;
31 struct Trie {
32         int n; /* of characters r */
33         char seq[MAXLD+1];
34         Rune r[256];
35         Trie *link[256];
36 };
37
38 Trie *root;
39
40 Trie*
41 mktrie(char *seq)
42 {
43         uchar *q;
44         Trie **tp;
45
46         if(root == nil) {
47                 root = malloc(sizeof *root);
48                 memset(root, 0, sizeof *root);
49         }
50
51         assert(seq[0] != '\0');
52
53         tp = &root;
54         for(q=(uchar*)seq; *(q+1) != '\0'; q++) {
55                 tp = &(*tp)->link[*q];
56                 if(*tp == nil) {
57                         *tp = malloc(sizeof(**tp));
58                         assert(*tp != nil);
59                         memset(*tp, 0, sizeof(**tp));
60                         strcpy((*tp)->seq, seq);
61                         (*tp)->seq[q+1-(uchar*)seq] = '\0';
62                 }
63         }
64
65         assert(*tp != nil);
66         return *tp;
67 }
68
69 /* add character sequence s meaning rune r */
70 void
71 insert(char *s, Rune r)
72 {
73         uchar lastc;
74         int len;
75         Trie *t;
76
77         len = strlen(s);
78         lastc = (uchar)s[len-1];
79
80         t = mktrie(s);
81         if(t->r[lastc]) {
82                 fprint(2, "warning: table duplicate: %s is %C and %C\n", s, t->r[lastc], r);
83                 return;
84         }
85         t->r[lastc] = r;
86         t->n++;
87 }
88
89 void
90 cprintchar(Biobuf *b, int c)
91 {
92         /* print a byte c safe for a C string. */
93         switch(c) {
94         case '\'':
95         case '\"':
96         case '\\':
97                 Bprint(b, "\\%c", c);
98                 break;
99         case '\t':
100                 Bprint(b, "\\t");
101                 break;
102         default:
103                 if(isascii(c) && isprint(c))
104                         Bprint(b, "%c", c);
105                 else
106                         Bprint(b, "\\x%.2x", c);
107                 break;
108         }
109 }
110
111 void
112 cprints(Biobuf *b, char *p)
113 {
114         while(*p != '\0')
115                 cprintchar(b, *p++);
116 }
117
118
119 void
120 printtrie(Biobuf *b, Trie *t)
121 {
122         int i;
123
124         for(i=0; i<256; i++)
125                 if(t->link[i])
126                         printtrie(b, t->link[i]);
127
128         if(t->n > 0) {
129                 Bprint(b, "\t\"");
130                 cprints(b, t->seq);
131                 Bprint(b, "\", \"");
132                 for(i=0; i<256; i++)
133                         if(t->r[i])
134                                 cprintchar(b, i);
135                 Bprint(b, "\",\t");
136                 if(rflag) {
137                         Bprint(b, "{");
138                         for(i=0; i<256; i++)
139                                 if(t->r[i])
140                                         Bprint(b, " 0x%.4ux,", t->r[i]);
141                         Bprint(b, " }");
142                 } else {
143                         Bprint(b, "L\"");
144                         for(i=0; i<256; i++)
145                                 if(t->r[i])
146                                         Bprint(b, "%C", t->r[i]);
147                         Bprint(b, "\"");
148                 }
149                 Bprint(b, ",\n");
150         }       
151 }
152
153 void
154 readfile(char *fname)
155 {
156         Biobuf *b;
157         char *line, *p;
158         char *seq;
159         int inseq;
160         int lineno;
161         Rune r;
162
163         if((b = Bopen(fname, OREAD)) == 0) {
164                 fprint(2, "cannot open \"%s\": %r\n", fname);
165                 exits("open");
166         }
167
168         lineno = 0;
169         while((line = Brdline(b, '\n')) != 0) {
170                 lineno++;
171                 if(line[0] == '#')
172                         continue;
173
174                 r = strtol(line, nil, 16);
175                 p = strchr(line, ' ');
176                 if(r == 0 || p != line+4 || p[0] != ' ' || p[1] != ' ') {
177                         fprint(2, "%s:%d: cannot parse line\n", fname, lineno);
178                         continue;
179                 }
180
181                 p = line+6;
182 /*      00AE  Or rO       ®    registered trade mark sign      */
183                 for(inseq=1, seq=p; (uchar)*p < Runeself; p++) {
184                         if(*p == '\0' || isspace(*p)) {
185                                 if(inseq && p-seq >= 2) {
186                                         *p = '\0';
187                                         inseq = 0;
188                                         insert(seq, r);
189                                         *p = ' ';
190                                 }
191                                 if(*p == '\0')
192                                         break;
193                         } else {
194                                 if(!inseq) {
195                                         seq = p;
196                                         inseq = 1;
197                                 }
198                         }
199                 }
200         }
201 }
202
203 void
204 usage(void)
205 {
206         fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n");
207         exits("usage");
208 }
209
210 void
211 main(int argc, char **argv)
212 {
213         Biobuf bout;
214
215         ARGBEGIN{
216         case 'r':       /* print rune values */
217                 rflag = 1;
218                 break;
219         default:
220                 usage();
221         }ARGEND
222
223         if(argc > 1)
224                 usage();
225
226         readfile(argc == 1 ? argv[0] : "/fd/0");
227
228         Binit(&bout, 1, OWRITE);
229         if(root)
230                 printtrie(&bout, root);
231         exits(0);
232 }