9fans.net/go@v0.0.7/cmd/devdraw/mklatinkbd.go (about) 1 // +build ignore 2 3 /* 4 * Parse /lib/keyboard to create latin1.h table for kernel. 5 * mklatinkbd -r prints an array of integers rather than a Rune string literal. 6 */ 7 8 package main 9 10 var rflag int 11 var xflag int 12 13 const MAXLD = 2 /* latin1.c assumes this is 2 */ 14 15 var head *C.char = "" + "/*\n" + " * This is automatically generated by %s from /lib/keyboard\n" + " * Edit /lib/keyboard instead.\n" + " */\n" 16 17 /* 18 * latin1.c assumes that strlen(ld) is at most 2. 19 * It also assumes that latintab[i].ld can be a prefix of latintab[j].ld 20 * only when j < i. We ensure this by sorting the output by prefix length. 21 * The so array is indexed by the character value. 22 */ 23 24 type Trie struct { 25 n int 26 seq [MAXLD + 1 + 1]C.char 27 r [256]rune 28 link [256]*Trie 29 } 30 31 var root *Trie 32 33 func mktrie(seq []C.char) *Trie { 34 if root == nil { 35 root = malloc(sizeof(*root)) 36 memset(root, 0, sizeof(*root)) 37 } 38 39 assert(seq[0] != '\x00') 40 41 tp := &root 42 for q := (*uint8)(seq); *(q + 1) != '\x00'; q++ { 43 tp = &(*tp).link[*q] 44 if *tp == nil { 45 *tp = malloc(sizeof(**tp)) 46 assert(*tp != nil) 47 memset(*tp, 0, sizeof(**tp)) 48 strcpy((*tp).seq, seq) 49 (*tp).seq[q+1-(*uint8)(seq)] = '\x00' 50 } 51 } 52 53 assert(*tp != nil) 54 return *tp 55 } 56 57 /* add character sequence s meaning rune r */ 58 func insert(s []C.char, r rune) { 59 len := strlen(s) 60 lastc := uint8(s[len-1]) 61 62 t := mktrie(s) 63 if t.r[lastc] != 0 { 64 fprint(2, "warning: table duplicate: %s is %C and %C\n", s, t.r[lastc], r) 65 return 66 } 67 t.r[lastc] = r 68 t.n++ 69 } 70 71 func cprintchar(b *Biobuf, c int) { 72 /* print a byte c safe for a C string. */ 73 switch c { 74 case '\'', 75 '"', 76 '\\': 77 Bprint(b, "\\%c", c) 78 case '\t': 79 Bprint(b, "\\t") 80 default: 81 if isascii(c) != 0 && isprint(c) != 0 { 82 Bprint(b, "%c", c) 83 } else { 84 Bprint(b, "\\x%.2x", c) 85 } 86 } 87 } 88 89 func cprints(b *Biobuf, p *C.char) { 90 for *p != '\x00' { 91 cprintchar(b, *p) 92 p++ 93 } 94 } 95 96 func xprint(b *Biobuf, c int) { 97 } 98 99 func printtrie(b *Biobuf, t *Trie) { 100 var i int 101 for i = 0; i < 256; i++ { 102 if t.link[i] != 0 { 103 printtrie(b, t.link[i]) 104 } 105 } 106 if t.n == 0 { 107 return 108 } 109 110 if xflag != 0 { 111 for i = 0; i < 256; i++ { 112 if t.r[i] == 0 { 113 continue 114 } 115 Bprint(b, "<Multi_key>") 116 for p := t.seq; *p != 0; p++ { 117 Bprint(b, " %k", *p) 118 } 119 Bprint(b, " %k : \"%C\" U%04X\n", i, t.r[i], t.r[i]) 120 } 121 return 122 } 123 124 Bprint(b, "\t\"") 125 cprints(b, t.seq) 126 Bprint(b, "\", \"") 127 for i = 0; i < 256; i++ { 128 if t.r[i] != 0 { 129 cprintchar(b, i) 130 } 131 } 132 Bprint(b, "\",\t") 133 if rflag != 0 { 134 Bprint(b, "{") 135 for i = 0; i < 256; i++ { 136 if t.r[i] != 0 { 137 Bprint(b, " 0x%.4ux,", t.r[i]) 138 } 139 } 140 Bprint(b, " }") 141 } else { 142 Bprint(b, "L\"") 143 for i = 0; i < 256; i++ { 144 if t.r[i] != 0 { 145 Bprint(b, "%C", t.r[i]) 146 } 147 } 148 Bprint(b, "\"") 149 } 150 Bprint(b, ",\n") 151 } 152 153 func readfile(fname *C.char) { 154 b := Bopen(fname, OREAD) 155 if b == 0 { 156 fprint(2, "cannot open \"%s\": %r\n", fname) 157 exits("open") 158 } 159 160 lineno := 0 161 for { 162 line := Brdline(b, '\n') 163 if line == 0 { 164 break 165 } 166 lineno++ 167 if line[0] == '#' { 168 continue 169 } 170 171 r := strtol(line, nil, 16) 172 p := strchr(line, ' ') 173 if r == 0 || (p != line+4 && p != line+5) || p[0] != ' ' || (p == line+4 && p[1] != ' ') { 174 fprint(2, "%s:%d: cannot parse line\n", fname, lineno) 175 continue 176 } 177 178 p = line + 6 179 /* 00AE Or rO ® registered trade mark sign */ 180 inseq := 1 181 seq := p 182 for ; uint8(*p) < Runeself; p++ { 183 if *p == '\x00' || isspace(*p) != 0 { 184 if inseq != 0 && p-seq >= 2 { 185 *p = '\x00' 186 inseq = 0 187 insert(seq, r) 188 *p = ' ' 189 } 190 if *p == '\x00' { 191 break 192 } 193 } else { 194 if inseq == 0 { 195 seq = p 196 inseq = 1 197 } 198 } 199 } 200 } 201 } 202 203 func usage() { 204 fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n") 205 exits("usage") 206 } 207 208 func main(argc int, argv []*C.char) { 209 switch ARGBEGIN { 210 case 'r': /* print rune values */ 211 rflag = 1 212 case 'x': 213 xflag = 1 214 default: 215 usage() 216 } 217 218 if argc > 1 { 219 usage() 220 } 221 222 fmtinstall('k', kfmt) 223 var tmp2 unknown 224 if argc == 1 { 225 tmp2 = argv[0] 226 } else { 227 tmp2 = "/dev/stdin" 228 } 229 readfile(tmp2) 230 var bout Biobuf 231 232 Binit(&bout, 1, OWRITE) 233 if xflag != 0 { 234 Bprint(&bout, "# Generated by mklatinkbd -x; do not edit.\n") 235 for i := 0x20; i < 0x10000; i++ { 236 Bprint(&bout, "<Multi_key> <X> <%x> <%x> <%x> <%x> : \"%C\" U%04X\n", (i>>12)&0xf, (i>>8)&0xf, (i>>4)&0xf, i&0xf, i, i) 237 } 238 } 239 if root != nil { 240 printtrie(&bout, root) 241 } 242 exits(0) 243 } 244 245 // X11 key names 246 247 var xkey = [68]struct { 248 c int 249 s *C.char 250 }{ 251 ' ', "space", 252 '!', "exclam", 253 '"', "quotedbl", 254 '#', "numbersign", 255 '$', "dollar", 256 '%', "percent", 257 '&', "ampersand", 258 '\'', "apostrophe", 259 '(', "parenleft", 260 ')', "parenright", 261 '*', "asterisk", 262 '+', "plus", 263 ',', "comma", 264 '-', "minus", 265 '.', "period", 266 '/', "slash", 267 ':', "colon", 268 ';', "semicolon", 269 '<', "less", 270 '=', "equal", 271 '>', "greater", 272 '?', "question", 273 '@', "at", 274 '[', "bracketleft", 275 '\\', "backslash", 276 ',', "bracketright", 277 '^', "asciicircum", 278 '_', "underscore", 279 '`', "grave", 280 '{', "braceleft", 281 '|', "bar", 282 '}', "braceright", 283 '~', "asciitilde", 284 0, 0, 285 } 286 287 func kfmt(f *Fmt) int { 288 c := va_arg(f.args, int) 289 for i := 0; xkey[i].s != 0; i++ { 290 if xkey[i].c == c { 291 return fmtprint(f, "<%s>", xkey[i].s) 292 } 293 } 294 return fmtprint(f, "<%c>", c) 295 }