mklatinkbd.c 4.1 KB

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