diff options
author | Michael Teichgräber <mt@ib.wmipf.de> | 2009-07-08 08:34:42 -0700 |
---|---|---|
committer | Michael Teichgräber <mt@ib.wmipf.de> | 2009-07-08 08:34:42 -0700 |
commit | bb7ff349fb314edffabb01c418e146d563548058 (patch) | |
tree | 5e8162588bcf9d9348fb62ad46091b2ca48659f2 /src/cmd/devdraw/mklatinkbd.c | |
parent | 342866f89cff5d35bc5e8fc7990767ad5d080a3c (diff) | |
download | plan9port-bb7ff349fb314edffabb01c418e146d563548058.tar.gz plan9port-bb7ff349fb314edffabb01c418e146d563548058.tar.bz2 plan9port-bb7ff349fb314edffabb01c418e146d563548058.zip |
devdraw: generate Latin-1 table from lib/keyboard
Diffstat (limited to 'src/cmd/devdraw/mklatinkbd.c')
-rw-r--r-- | src/cmd/devdraw/mklatinkbd.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/cmd/devdraw/mklatinkbd.c b/src/cmd/devdraw/mklatinkbd.c new file mode 100644 index 00000000..64787f00 --- /dev/null +++ b/src/cmd/devdraw/mklatinkbd.c @@ -0,0 +1,232 @@ +/* + * Parse /lib/keyboard to create latin1.h table for kernel. + * mklatinkbd -r prints an array of integers rather than a Rune string literal. + */ + +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ctype.h> + +int rflag; + +enum { + MAXLD = 2, /* latin1.c assumes this is 2 */ +}; + +char *head = "" +"/*\n" +" * This is automatically generated by %s from /lib/keyboard\n" +" * Edit /lib/keyboard instead.\n" +" */\n"; + +/* + * latin1.c assumes that strlen(ld) is at most 2. + * It also assumes that latintab[i].ld can be a prefix of latintab[j].ld + * only when j < i. We ensure this by sorting the output by prefix length. + * The so array is indexed by the character value. + */ + +typedef struct Trie Trie; +struct Trie { + int n; /* of characters r */ + char seq[MAXLD+1]; + Rune r[256]; + Trie *link[256]; +}; + +Trie *root; + +Trie* +mktrie(char *seq) +{ + uchar *q; + Trie **tp; + + if(root == nil) { + root = malloc(sizeof *root); + memset(root, 0, sizeof *root); + } + + assert(seq[0] != '\0'); + + tp = &root; + for(q=(uchar*)seq; *(q+1) != '\0'; q++) { + tp = &(*tp)->link[*q]; + if(*tp == nil) { + *tp = malloc(sizeof(**tp)); + assert(*tp != nil); + memset(*tp, 0, sizeof(**tp)); + strcpy((*tp)->seq, seq); + (*tp)->seq[q+1-(uchar*)seq] = '\0'; + } + } + + assert(*tp != nil); + return *tp; +} + +/* add character sequence s meaning rune r */ +void +insert(char *s, Rune r) +{ + uchar lastc; + int len; + Trie *t; + + len = strlen(s); + lastc = (uchar)s[len-1]; + + t = mktrie(s); + if(t->r[lastc]) { + fprint(2, "warning: table duplicate: %s is %C and %C\n", s, t->r[lastc], r); + return; + } + t->r[lastc] = r; + t->n++; +} + +void +cprintchar(Biobuf *b, int c) +{ + /* print a byte c safe for a C string. */ + switch(c) { + case '\'': + case '\"': + case '\\': + Bprint(b, "\\%c", c); + break; + case '\t': + Bprint(b, "\\t"); + break; + default: + if(isascii(c) && isprint(c)) + Bprint(b, "%c", c); + else + Bprint(b, "\\x%.2x", c); + break; + } +} + +void +cprints(Biobuf *b, char *p) +{ + while(*p != '\0') + cprintchar(b, *p++); +} + + +void +printtrie(Biobuf *b, Trie *t) +{ + int i; + + for(i=0; i<256; i++) + if(t->link[i]) + printtrie(b, t->link[i]); + + if(t->n > 0) { + Bprint(b, "\t\""); + cprints(b, t->seq); + Bprint(b, "\", \""); + for(i=0; i<256; i++) + if(t->r[i]) + cprintchar(b, i); + Bprint(b, "\",\t"); + if(rflag) { + Bprint(b, "{"); + for(i=0; i<256; i++) + if(t->r[i]) + Bprint(b, " 0x%.4ux,", t->r[i]); + Bprint(b, " }"); + } else { + Bprint(b, "L\""); + for(i=0; i<256; i++) + if(t->r[i]) + Bprint(b, "%C", t->r[i]); + Bprint(b, "\""); + } + Bprint(b, ",\n"); + } +} + +void +readfile(char *fname) +{ + Biobuf *b; + char *line, *p; + char *seq; + int inseq; + int lineno; + Rune r; + + if((b = Bopen(fname, OREAD)) == 0) { + fprint(2, "cannot open \"%s\": %r\n", fname); + exits("open"); + } + + lineno = 0; + while((line = Brdline(b, '\n')) != 0) { + lineno++; + if(line[0] == '#') + continue; + + r = strtol(line, nil, 16); + p = strchr(line, ' '); + if(r == 0 || p != line+4 || p[0] != ' ' || p[1] != ' ') { + fprint(2, "%s:%d: cannot parse line\n", fname, lineno); + continue; + } + + p = line+6; +/* 00AE Or rO ® registered trade mark sign */ + for(inseq=1, seq=p; (uchar)*p < Runeself; p++) { + if(*p == '\0' || isspace(*p)) { + if(inseq && p-seq >= 2) { + *p = '\0'; + inseq = 0; + insert(seq, r); + *p = ' '; + } + if(*p == '\0') + break; + } else { + if(!inseq) { + seq = p; + inseq = 1; + } + } + } + } +} + +void +usage(void) +{ + fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Biobuf bout; + + ARGBEGIN{ + case 'r': /* print rune values */ + rflag = 1; + break; + default: + usage(); + }ARGEND + + if(argc > 1) + usage(); + + readfile(argc == 1 ? argv[0] : "/fd/0"); + + Binit(&bout, 1, OWRITE); + if(root) + printtrie(&bout, root); + exits(0); +} |