mklatinkbd.c 3.7 KB

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