URI:
       tmklatinkbd.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmklatinkbd.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 }