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