tmklatinkbd.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
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 
     7 #include 
     8 #include 
     9 #include 
    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, "");
   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, "  <%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 }