plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }