aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/devdraw/mklatinkbd.c
diff options
context:
space:
mode:
authorMichael Teichgräber <mt@ib.wmipf.de>2009-07-08 08:34:42 -0700
committerMichael Teichgräber <mt@ib.wmipf.de>2009-07-08 08:34:42 -0700
commitbb7ff349fb314edffabb01c418e146d563548058 (patch)
tree5e8162588bcf9d9348fb62ad46091b2ca48659f2 /src/cmd/devdraw/mklatinkbd.c
parent342866f89cff5d35bc5e8fc7990767ad5d080a3c (diff)
downloadplan9port-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.c232
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);
+}