mklatinkbd.c (5299B)
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 int xflag; 13 14 enum { 15 MAXLD = 2, /* latin1.c assumes this is 2 */ 16 }; 17 18 char *head = "" 19 "/*\n" 20 " * This is automatically generated by %s from /lib/keyboard\n" 21 " * Edit /lib/keyboard instead.\n" 22 " */\n"; 23 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 */ 30 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 }; 38 39 Trie *root; 40 41 Trie* 42 mktrie(char *seq) 43 { 44 uchar *q; 45 Trie **tp; 46 47 if(root == nil) { 48 root = malloc(sizeof *root); 49 memset(root, 0, sizeof *root); 50 } 51 52 assert(seq[0] != '\0'); 53 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 } 65 66 assert(*tp != nil); 67 return *tp; 68 } 69 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; 77 78 len = strlen(s); 79 lastc = (uchar)s[len-1]; 80 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 } 89 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; 109 } 110 } 111 112 void 113 cprints(Biobuf *b, char *p) 114 { 115 while(*p != '\0') 116 cprintchar(b, *p++); 117 } 118 119 void 120 xprint(Biobuf *b, int c) 121 { 122 } 123 124 void 125 printtrie(Biobuf *b, Trie *t) 126 { 127 int i; 128 char *p; 129 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; 135 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]); 144 } 145 return; 146 } 147 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, "\""); 167 } 168 Bprint(b, ",\n"); 169 } 170 171 void 172 readfile(char *fname) 173 { 174 Biobuf *b; 175 char *line, *p; 176 char *seq; 177 int inseq; 178 int lineno; 179 Rune r; 180 181 if((b = Bopen(fname, OREAD)) == 0) { 182 fprint(2, "cannot open \"%s\": %r\n", fname); 183 exits("open"); 184 } 185 186 lineno = 0; 187 while((line = Brdline(b, '\n')) != 0) { 188 lineno++; 189 if(line[0] == '#') 190 continue; 191 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; 197 } 198 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 = ' '; 208 } 209 if(*p == '\0') 210 break; 211 } else { 212 if(!inseq) { 213 seq = p; 214 inseq = 1; 215 } 216 } 217 } 218 } 219 } 220 221 void 222 usage(void) 223 { 224 fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n"); 225 exits("usage"); 226 } 227 228 int kfmt(Fmt*); 229 230 void 231 main(int argc, char **argv) 232 { 233 int i; 234 Biobuf bout; 235 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 246 247 if(argc > 1) 248 usage(); 249 250 fmtinstall('k', kfmt); 251 readfile(argc == 1 ? argv[0] : "/dev/stdin"); 252 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); 259 } 260 if(root) 261 printtrie(&bout, root); 262 exits(0); 263 } 264 265 // X11 key names 266 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 }; 306 307 int 308 kfmt(Fmt *f) 309 { 310 int i, c; 311 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); 317 }