]>
Commit | Line | Data |
---|---|---|
6838f038 WB |
1 | #!/usr/bin/python |
2 | # -*- python -*- | |
3 | # | |
4 | # Keycode Map Generator | |
5 | # | |
6 | # Copyright (C) 2009-2017 Red Hat, Inc. | |
7 | # | |
8 | # This file is dual license under the terms of the GPLv2 or later | |
9 | # and 3-clause BSD licenses. | |
10 | # | |
11 | ||
12 | # Requires >= 2.6 | |
13 | from __future__ import print_function | |
14 | ||
15 | import csv | |
16 | try: | |
17 | import argparse | |
18 | except: | |
19 | import os, sys | |
20 | sys.path.append(os.path.join(os.path.dirname(__file__), "../thirdparty")) | |
21 | import argparse | |
22 | import hashlib | |
23 | import time | |
24 | import sys | |
25 | ||
26 | class Database: | |
27 | ||
28 | # Linux: linux/input.h | |
29 | MAP_LINUX = "linux" | |
30 | ||
31 | # OS-X: Carbon/HIToolbox/Events.h | |
32 | MAP_OSX = "osx" | |
33 | ||
34 | # AT Set 1: linux/drivers/input/keyboard/atkbd.c | |
35 | # (atkbd_set2_keycode + atkbd_unxlate_table) | |
36 | MAP_ATSET1 = "atset1" | |
37 | ||
38 | # AT Set 2: linux/drivers/input/keyboard/atkbd.c | |
39 | # (atkbd_set2_keycode) | |
40 | MAP_ATSET2 = "atset2" | |
41 | ||
42 | # AT Set 3: linux/drivers/input/keyboard/atkbd.c | |
43 | # (atkbd_set3_keycode) | |
44 | MAP_ATSET3 = "atset3" | |
45 | ||
46 | # Linux RAW: linux/drivers/char/keyboard.c (x86_keycodes) | |
47 | MAP_XTKBD = "xtkbd" | |
48 | ||
49 | # USB HID: linux/drivers/hid/usbhid/usbkbd.c (usb_kbd_keycode) | |
50 | MAP_USB = "usb" | |
51 | ||
52 | # Win32: mingw32/winuser.h | |
53 | MAP_WIN32 = "win32" | |
54 | ||
55 | # XWin XT: xorg-server/hw/xwin/{winkeybd.c,winkeynames.h} | |
56 | # (xt + manually transcribed) | |
57 | MAP_XWINXT = "xwinxt" | |
58 | ||
59 | # X11: http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h | |
60 | MAP_X11 = "x11" | |
61 | ||
62 | # XKBD XT: xf86-input-keyboard/src/at_scancode.c | |
63 | # (xt + manually transcribed) | |
64 | MAP_XKBDXT = "xkbdxt" | |
65 | ||
66 | # Xorg with evdev: linux + an offset | |
67 | MAP_XORGEVDEV = "xorgevdev" | |
68 | ||
69 | # Xorg with kbd: xkbdxt + an offset | |
70 | MAP_XORGKBD = "xorgkbd" | |
71 | ||
72 | # Xorg with OS-X: osx + an offset | |
73 | MAP_XORGXQUARTZ = "xorgxquartz" | |
74 | ||
75 | # Xorg + Cygwin: xwinxt + an offset | |
76 | MAP_XORGXWIN = "xorgxwin" | |
77 | ||
78 | # QEMU key numbers: xtkbd + special re-encoding of high bit | |
79 | MAP_QNUM = "qnum" | |
80 | ||
81 | # HTML codes | |
82 | MAP_HTML = "html" | |
83 | ||
84 | # XKB key names | |
85 | MAP_XKB = "xkb" | |
86 | ||
87 | # QEMU keycodes | |
88 | MAP_QCODE = "qcode" | |
89 | ||
90 | # Sun / Sparc scan codes | |
91 | # Reference: "SPARC International Keyboard Spec 1", page 7 "US scan set" | |
92 | MAP_SUN = "sun" | |
93 | ||
94 | # Apple Desktop Bus | |
95 | # Reference: http://www.archive.org/stream/apple-guide-macintosh-family-hardware/Apple_Guide_to_the_Macintosh_Family_Hardware_2e#page/n345/mode/2up | |
96 | MAP_ADB = "adb" | |
97 | ||
98 | MAP_LIST = ( | |
99 | MAP_LINUX, | |
100 | MAP_OSX, | |
101 | MAP_ATSET1, | |
102 | MAP_ATSET2, | |
103 | MAP_ATSET3, | |
104 | MAP_USB, | |
105 | MAP_WIN32, | |
106 | MAP_XWINXT, | |
107 | MAP_XKBDXT, | |
108 | MAP_X11, | |
109 | MAP_HTML, | |
110 | MAP_XKB, | |
111 | MAP_QCODE, | |
112 | MAP_SUN, | |
113 | MAP_ADB, | |
114 | ||
115 | # These are derived from maps above | |
116 | MAP_XTKBD, | |
117 | MAP_XORGEVDEV, | |
118 | MAP_XORGKBD, | |
119 | MAP_XORGXQUARTZ, | |
120 | MAP_XORGXWIN, | |
121 | MAP_QNUM, | |
122 | ) | |
123 | ||
124 | CODE_COLUMNS = { | |
125 | MAP_LINUX: 1, | |
126 | MAP_OSX: 3, | |
127 | MAP_ATSET1: 4, | |
128 | MAP_ATSET2: 5, | |
129 | MAP_ATSET3: 6, | |
130 | MAP_USB: 7, | |
131 | MAP_WIN32: 9, | |
132 | MAP_XWINXT: 10, | |
133 | MAP_XKBDXT: 11, | |
134 | MAP_X11: 13, | |
135 | MAP_HTML: 14, | |
136 | MAP_XKB: 15, | |
137 | MAP_SUN: 17, | |
138 | MAP_ADB: 18, | |
139 | } | |
140 | ||
141 | ENUM_COLUMNS = { | |
142 | MAP_QCODE: 14, | |
143 | } | |
144 | ||
145 | NAME_COLUMNS = { | |
146 | MAP_LINUX: 0, | |
147 | MAP_OSX: 2, | |
148 | MAP_WIN32: 8, | |
149 | MAP_X11: 12, | |
150 | MAP_HTML: 14, | |
151 | MAP_XKB: 15, | |
152 | MAP_QCODE: 16, | |
153 | } | |
154 | ||
155 | ENUM_BOUND = { | |
156 | MAP_QCODE: "Q_KEY_CODE__MAX", | |
157 | } | |
158 | ||
159 | def __init__(self): | |
160 | ||
161 | self.mapto = {} | |
162 | self.mapfrom = {} | |
163 | self.mapname = {} | |
164 | self.mapchecksum = None | |
165 | ||
166 | for name in self.MAP_LIST: | |
167 | # Key is a MAP_LINUX, value is a MAP_XXX | |
168 | self.mapto[name] = {} | |
169 | # key is a MAP_XXX, value is a MAP_LINUX | |
170 | self.mapfrom[name] = {} | |
171 | ||
172 | for name in self.NAME_COLUMNS.keys(): | |
173 | # key is a MAP_LINUX, value is a string | |
174 | self.mapname[name] = {} | |
175 | ||
176 | def _generate_checksum(self, filename): | |
177 | hash = hashlib.sha256() | |
178 | with open(filename, "rb") as f: | |
179 | for chunk in iter(lambda: f.read(4096), b""): | |
180 | hash.update(chunk) | |
181 | self.mapchecksum = hash.hexdigest() | |
182 | ||
183 | def load(self, filename): | |
184 | self._generate_checksum(filename) | |
185 | ||
186 | with open(filename, 'r') as f: | |
187 | reader = csv.reader(f) | |
188 | ||
189 | first = True | |
190 | ||
191 | for row in reader: | |
192 | # Discard column headings | |
193 | if first: | |
194 | first = False | |
195 | continue | |
196 | ||
197 | # We special case MAP_LINUX since that is out | |
198 | # master via which all other mappings are done | |
199 | linux = self.load_linux(row) | |
200 | ||
201 | # Now load all the remaining master data values | |
202 | self.load_data(row, linux) | |
203 | ||
204 | # Then load all the keycode names | |
205 | self.load_names(row, linux) | |
206 | ||
207 | # Finally calculate derived key maps | |
208 | self.derive_data(row, linux) | |
209 | ||
210 | def load_linux(self, row): | |
211 | col = self.CODE_COLUMNS[self.MAP_LINUX] | |
212 | linux = row[col] | |
213 | ||
214 | if linux.startswith("0x"): | |
215 | linux = int(linux, 16) | |
216 | else: | |
217 | linux = int(linux, 10) | |
218 | ||
219 | self.mapto[self.MAP_LINUX][linux] = linux | |
220 | self.mapfrom[self.MAP_LINUX][linux] = linux | |
221 | ||
222 | return linux | |
223 | ||
224 | ||
225 | def load_data(self, row, linux): | |
226 | for mapname in self.CODE_COLUMNS: | |
227 | if mapname == self.MAP_LINUX: | |
228 | continue | |
229 | ||
230 | col = self.CODE_COLUMNS[mapname] | |
231 | val = row[col] | |
232 | ||
233 | if val == "": | |
234 | continue | |
235 | ||
236 | if val.startswith("0x"): | |
237 | val = int(val, 16) | |
238 | elif val.isdigit(): | |
239 | val = int(val, 10) | |
240 | ||
241 | self.mapto[mapname][linux] = val | |
242 | self.mapfrom[mapname][val] = linux | |
243 | ||
244 | def load_names(self, row, linux): | |
245 | for mapname in self.NAME_COLUMNS: | |
246 | col = self.NAME_COLUMNS[mapname] | |
247 | val = row[col] | |
248 | ||
249 | if val == "": | |
250 | continue | |
251 | ||
252 | self.mapname[mapname][linux] = val | |
253 | ||
254 | ||
255 | def derive_data(self, row, linux): | |
256 | # Linux RAW is XT scan codes with special encoding of the | |
257 | # 0xe0 scan codes | |
258 | if linux in self.mapto[self.MAP_ATSET1]: | |
259 | at1 = self.mapto[self.MAP_ATSET1][linux] | |
260 | if at1 > 0x7f: | |
261 | assert((at1 & ~0x7f) == 0xe000) | |
262 | xtkbd = 0x100 | (at1 & 0x7f) | |
263 | else: | |
264 | xtkbd = at1 | |
265 | self.mapto[self.MAP_XTKBD][linux] = xtkbd | |
266 | self.mapfrom[self.MAP_XTKBD][xtkbd] = linux | |
267 | ||
268 | # Xorg KBD is XKBD XT offset by 8 | |
269 | if linux in self.mapto[self.MAP_XKBDXT]: | |
270 | xorgkbd = self.mapto[self.MAP_XKBDXT][linux] + 8 | |
271 | self.mapto[self.MAP_XORGKBD][linux] = xorgkbd | |
272 | self.mapfrom[self.MAP_XORGKBD][xorgkbd] = linux | |
273 | ||
274 | # Xorg evdev is Linux offset by 8 | |
275 | self.mapto[self.MAP_XORGEVDEV][linux] = linux + 8 | |
276 | self.mapfrom[self.MAP_XORGEVDEV][linux + 8] = linux | |
277 | ||
278 | # Xorg XQuartx is OS-X offset by 8 | |
279 | if linux in self.mapto[self.MAP_OSX]: | |
280 | xorgxquartz = self.mapto[self.MAP_OSX][linux] + 8 | |
281 | self.mapto[self.MAP_XORGXQUARTZ][linux] = xorgxquartz | |
282 | self.mapfrom[self.MAP_XORGXQUARTZ][xorgxquartz] = linux | |
283 | ||
284 | # Xorg Xwin (aka Cygwin) is XWin XT offset by 8 | |
285 | if linux in self.mapto[self.MAP_XWINXT]: | |
286 | xorgxwin = self.mapto[self.MAP_XWINXT][linux] + 8 | |
287 | self.mapto[self.MAP_XORGXWIN][linux] = xorgxwin | |
288 | self.mapfrom[self.MAP_XORGXWIN][xorgxwin] = linux | |
289 | ||
290 | # QNUM keycodes are XT scan codes with a slightly | |
291 | # different encoding of 0xe0 scan codes | |
292 | if linux in self.mapto[self.MAP_ATSET1]: | |
293 | at1 = self.mapto[self.MAP_ATSET1][linux] | |
294 | if at1 > 0x7f: | |
295 | assert((at1 & ~0x7f) == 0xe000) | |
296 | qnum = 0x80 | (at1 & 0x7f) | |
297 | else: | |
298 | qnum = at1 | |
299 | self.mapto[self.MAP_QNUM][linux] = qnum | |
300 | self.mapfrom[self.MAP_QNUM][qnum] = linux | |
301 | ||
302 | # Hack for compatibility with previous mistakes in handling | |
303 | # Print/SysRq. The preferred qnum for Print/SysRq is 0x54, | |
304 | # but QEMU previously allowed 0xb7 too | |
305 | if qnum == 0x54: | |
306 | self.mapfrom[self.MAP_QNUM][0xb7] = self.mapfrom[self.MAP_QNUM][0x54] | |
307 | ||
308 | if linux in self.mapname[self.MAP_QCODE]: | |
309 | qcodeenum = self.mapname[self.MAP_QCODE][linux] | |
310 | qcodeenum = "Q_KEY_CODE_" + qcodeenum.upper() | |
311 | self.mapto[self.MAP_QCODE][linux] = qcodeenum | |
312 | self.mapfrom[self.MAP_QCODE][qcodeenum] = linux | |
313 | ||
314 | class LanguageGenerator(object): | |
315 | ||
316 | def _boilerplate(self, lines): | |
317 | raise NotImplementedError() | |
318 | ||
319 | def generate_header(self, database, args): | |
6838f038 | 320 | self._boilerplate([ |
263fef5b | 321 | "This file is auto-generated from keymaps.csv", |
6838f038 WB |
322 | "Database checksum sha256(%s)" % database.mapchecksum, |
323 | "To re-generate, run:", | |
324 | " %s" % args, | |
325 | ]) | |
326 | ||
327 | class LanguageSrcGenerator(LanguageGenerator): | |
328 | ||
329 | TYPE_INT = "integer" | |
330 | TYPE_STRING = "string" | |
331 | TYPE_ENUM = "enum" | |
332 | ||
333 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
334 | raise NotImplementedError() | |
335 | ||
336 | def _array_end(self, fromtype, totype): | |
337 | raise NotImplementedError() | |
338 | ||
339 | def _array_entry(self, index, value, comment, fromtype, totype): | |
340 | raise NotImplementedError() | |
341 | ||
342 | def generate_code_map(self, varname, database, frommapname, tomapname): | |
343 | if frommapname not in database.mapfrom: | |
344 | raise Exception("Unknown map %s, expected one of %s" % ( | |
345 | frommapname, ", ".join(database.mapfrom.keys()))) | |
346 | if tomapname not in database.mapto: | |
347 | raise Exception("Unknown map %s, expected one of %s" % ( | |
348 | tomapname, ", ".join(database.mapto.keys()))) | |
349 | ||
350 | tolinux = database.mapfrom[frommapname] | |
351 | fromlinux = database.mapto[tomapname] | |
352 | ||
353 | if varname is None: | |
354 | varname = "code_map_%s_to_%s" % (frommapname, tomapname) | |
355 | ||
356 | if frommapname in database.ENUM_COLUMNS: | |
357 | fromtype = self.TYPE_ENUM | |
53e83913 | 358 | elif type(list(tolinux.keys())[0]) == str: |
6838f038 WB |
359 | fromtype = self.TYPE_STRING |
360 | else: | |
361 | fromtype = self.TYPE_INT | |
362 | ||
363 | if tomapname in database.ENUM_COLUMNS: | |
364 | totype = self.TYPE_ENUM | |
53e83913 | 365 | elif type(list(fromlinux.values())[0]) == str: |
6838f038 WB |
366 | totype = self.TYPE_STRING |
367 | else: | |
368 | totype = self.TYPE_INT | |
369 | ||
53e83913 | 370 | keys = list(tolinux.keys()) |
6838f038 WB |
371 | keys.sort() |
372 | if fromtype == self.TYPE_INT: | |
373 | keys = range(keys[-1] + 1) | |
374 | ||
375 | if fromtype == self.TYPE_ENUM: | |
376 | keymax = database.ENUM_BOUND[frommapname] | |
377 | else: | |
378 | keymax = len(keys) | |
379 | ||
380 | defvalue = fromlinux.get(0, None) | |
381 | if fromtype == self.TYPE_ENUM: | |
382 | self._array_start(varname, keymax, defvalue, fromtype, totype) | |
383 | else: | |
384 | self._array_start(varname, keymax, None, fromtype, totype) | |
385 | ||
386 | for src in keys: | |
387 | linux = tolinux.get(src, None) | |
388 | if linux is None: | |
389 | dst = None | |
390 | else: | |
391 | dst = fromlinux.get(linux, defvalue) | |
392 | ||
393 | comment = "%s -> %s -> %s" % (self._label(database, frommapname, src, linux), | |
394 | self._label(database, Database.MAP_LINUX, linux, linux), | |
395 | self._label(database, tomapname, dst, linux)) | |
396 | self._array_entry(src, dst, comment, fromtype, totype) | |
397 | self._array_end(fromtype, totype) | |
398 | ||
399 | def generate_code_table(self, varname, database, mapname): | |
400 | if mapname not in database.mapto: | |
401 | raise Exception("Unknown map %s, expected one of %s" % ( | |
402 | mapname, ", ".join(database.mapto.keys()))) | |
403 | ||
53e83913 | 404 | keys = list(database.mapto[Database.MAP_LINUX].keys()) |
6838f038 WB |
405 | keys.sort() |
406 | names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
407 | ||
408 | if varname is None: | |
409 | varname = "code_table_%s" % mapname | |
410 | ||
411 | if mapname in database.ENUM_COLUMNS: | |
412 | totype = self.TYPE_ENUM | |
53e83913 | 413 | elif type(list(database.mapto[mapname].values())[0]) == str: |
6838f038 WB |
414 | totype = self.TYPE_STRING |
415 | else: | |
416 | totype = self.TYPE_INT | |
417 | ||
418 | self._array_start(varname, len(keys), None, self.TYPE_INT, totype) | |
419 | ||
420 | defvalue = database.mapto[mapname].get(0, None) | |
421 | for i in range(len(keys)): | |
422 | key = keys[i] | |
423 | dst = database.mapto[mapname].get(key, defvalue) | |
424 | self._array_entry(i, dst, names[i], self.TYPE_INT, totype) | |
425 | ||
426 | self._array_end(self.TYPE_INT, totype) | |
427 | ||
428 | def generate_name_map(self, varname, database, frommapname, tomapname): | |
429 | if frommapname not in database.mapfrom: | |
430 | raise Exception("Unknown map %s, expected one of %s" % ( | |
431 | frommapname, ", ".join(database.mapfrom.keys()))) | |
432 | if tomapname not in database.mapname: | |
433 | raise Exception("Unknown map %s, expected one of %s" % ( | |
434 | tomapname, ", ".join(database.mapname.keys()))) | |
435 | ||
436 | tolinux = database.mapfrom[frommapname] | |
437 | fromlinux = database.mapname[tomapname] | |
438 | ||
439 | if varname is None: | |
440 | varname = "name_map_%s_to_%s" % (frommapname, tomapname) | |
441 | ||
53e83913 | 442 | keys = list(tolinux.keys()) |
6838f038 WB |
443 | keys.sort() |
444 | if type(keys[0]) == int: | |
445 | keys = range(keys[-1] + 1) | |
446 | ||
447 | if type(keys[0]) == int: | |
448 | fromtype = self.TYPE_INT | |
449 | else: | |
450 | fromtype = self.TYPE_STRING | |
451 | ||
452 | self._array_start(varname, len(keys), None, fromtype, self.TYPE_STRING) | |
453 | ||
454 | for src in keys: | |
455 | linux = tolinux.get(src, None) | |
456 | if linux is None: | |
457 | dst = None | |
458 | else: | |
459 | dst = fromlinux.get(linux, None) | |
460 | ||
461 | comment = "%s -> %s -> %s" % (self._label(database, frommapname, src, linux), | |
462 | self._label(database, Database.MAP_LINUX, linux, linux), | |
463 | self._label(database, tomapname, dst, linux)) | |
464 | self._array_entry(src, dst, comment, fromtype, self.TYPE_STRING) | |
465 | self._array_end(fromtype, self.TYPE_STRING) | |
466 | ||
467 | def generate_name_table(self, varname, database, mapname): | |
468 | if mapname not in database.mapname: | |
469 | raise Exception("Unknown map %s, expected one of %s" % ( | |
470 | mapname, ", ".join(database.mapname.keys()))) | |
471 | ||
53e83913 | 472 | keys = list(database.mapto[Database.MAP_LINUX].keys()) |
6838f038 WB |
473 | keys.sort() |
474 | names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
475 | ||
476 | if varname is None: | |
477 | varname = "name_table_%s" % mapname | |
478 | ||
479 | self._array_start(varname, len(keys), None, self.TYPE_INT, self.TYPE_STRING) | |
480 | ||
481 | for i in range(len(keys)): | |
482 | key = keys[i] | |
483 | dst = database.mapname[mapname].get(key, None) | |
484 | self._array_entry(i, dst, names[i], self.TYPE_INT, self.TYPE_STRING) | |
485 | ||
486 | self._array_end(self.TYPE_INT, self.TYPE_STRING) | |
487 | ||
488 | def _label(self, database, mapname, val, linux): | |
489 | if mapname in database.mapname: | |
490 | return "%s:%s (%s)" % (mapname, val, database.mapname[mapname].get(linux, "unnamed")) | |
491 | else: | |
492 | return "%s:%s" % (mapname, val) | |
493 | ||
494 | class LanguageDocGenerator(LanguageGenerator): | |
495 | ||
496 | def _array_start_name_doc(self, varname, namemap): | |
497 | raise NotImplementedError() | |
498 | ||
499 | def _array_start_code_doc(self, varname, namemap, codemap): | |
500 | raise NotImplementedError() | |
501 | ||
502 | def _array_end(self): | |
503 | raise NotImplementedError() | |
504 | ||
505 | def _array_name_entry(self, value, name): | |
506 | raise NotImplementedError() | |
507 | ||
508 | def _array_code_entry(self, value, name): | |
509 | raise NotImplementedError() | |
510 | ||
263fef5b | 511 | def generate_name_docs(self, title, subtitle, database, mapname): |
6838f038 WB |
512 | if mapname not in database.mapname: |
513 | raise Exception("Unknown map %s, expected one of %s" % ( | |
514 | mapname, ", ".join(database.mapname.keys()))) | |
515 | ||
53e83913 | 516 | keys = list(database.mapto[Database.MAP_LINUX].keys()) |
6838f038 WB |
517 | keys.sort() |
518 | names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
519 | ||
263fef5b SR |
520 | if title is None: |
521 | title = mapname | |
522 | if subtitle is None: | |
523 | subtitle = "Docs for %s" % mapname | |
6838f038 | 524 | |
263fef5b | 525 | self._array_start_name_doc(title, subtitle, mapname) |
6838f038 WB |
526 | |
527 | for i in range(len(keys)): | |
528 | key = keys[i] | |
529 | dst = database.mapname[mapname].get(key, None) | |
530 | self._array_name_entry(key, dst) | |
531 | ||
532 | self._array_end() | |
533 | ||
534 | ||
263fef5b | 535 | def generate_code_docs(self, title, subtitle, database, mapname): |
6838f038 WB |
536 | if mapname not in database.mapfrom: |
537 | raise Exception("Unknown map %s, expected one of %s" % ( | |
538 | mapname, ", ".join(database.mapfrom.keys()))) | |
539 | ||
540 | tolinux = database.mapfrom[mapname] | |
53e83913 | 541 | keys = list(tolinux.keys()) |
6838f038 WB |
542 | keys.sort() |
543 | if mapname in database.mapname: | |
544 | names = database.mapname[mapname] | |
545 | namemap = mapname | |
546 | else: | |
547 | names = database.mapname[Database.MAP_LINUX] | |
548 | namemap = Database.MAP_LINUX | |
549 | ||
263fef5b SR |
550 | if title is None: |
551 | title = mapname | |
552 | if subtitle is None: | |
553 | subtitle = "Docs for %s" % mapname | |
6838f038 | 554 | |
263fef5b | 555 | self._array_start_code_doc(title, subtitle, mapname, namemap) |
6838f038 WB |
556 | |
557 | for i in range(len(keys)): | |
558 | key = keys[i] | |
559 | self._array_code_entry(key, names.get(tolinux[key], "unnamed")) | |
560 | ||
561 | self._array_end() | |
562 | ||
563 | class CLanguageGenerator(LanguageSrcGenerator): | |
564 | ||
565 | def __init__(self, inttypename, strtypename, lentypename): | |
566 | self.inttypename = inttypename | |
567 | self.strtypename = strtypename | |
568 | self.lentypename = lentypename | |
569 | ||
570 | def _boilerplate(self, lines): | |
571 | print("/*") | |
572 | for line in lines: | |
573 | print(" * %s" % line) | |
574 | print("*/") | |
575 | ||
576 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
577 | self._varname = varname; | |
578 | totypename = self.strtypename if totype == self.TYPE_STRING else self.inttypename | |
579 | if fromtype in (self.TYPE_INT, self.TYPE_ENUM): | |
580 | if type(length) == str: | |
581 | print("const %s %s[%s] = {" % (totypename, varname, length)) | |
582 | else: | |
583 | print("const %s %s[%d] = {" % (totypename, varname, length)) | |
584 | else: | |
585 | print("const struct _%s {" % varname) | |
586 | print(" const %s from;" % self.strtypename) | |
587 | print(" const %s to;" % totypename) | |
588 | print("} %s[] = {" % varname) | |
589 | ||
590 | if defvalue != None: | |
591 | if totype == self.TYPE_ENUM: | |
592 | if type(length) == str: | |
593 | print(" [0 ... %s-1] = %s," % (length, defvalue)) | |
594 | else: | |
595 | print(" [0 ... 0x%x-1] = %s," % (length, defvalue)) | |
596 | else: | |
597 | if type(length) == str: | |
598 | print(" [0 ... %s-1] = 0x%x," % (length, defvalue)) | |
599 | else: | |
600 | print(" [0 ... 0x%x-1] = 0x%x," % (length, defvalue)) | |
601 | ||
602 | def _array_end(self, fromtype, totype): | |
603 | print("};") | |
604 | print("const %s %s_len = sizeof(%s)/sizeof(%s[0]);" % | |
605 | (self.lentypename, self._varname, self._varname, self._varname)) | |
606 | ||
607 | def _array_entry(self, index, value, comment, fromtype, totype): | |
608 | if value is None: | |
609 | return | |
610 | if fromtype == self.TYPE_INT: | |
611 | indexfmt = "0x%x" | |
612 | elif fromtype == self.TYPE_ENUM: | |
613 | indexfmt = "%s" | |
614 | else: | |
615 | indexfmt = "\"%s\"" | |
616 | ||
617 | if totype == self.TYPE_INT: | |
618 | valuefmt = "0x%x" | |
619 | elif totype == self.TYPE_ENUM: | |
620 | valuefmt = "%s" | |
621 | else: | |
622 | valuefmt = "\"%s\"" | |
623 | ||
624 | if fromtype != self.TYPE_STRING: | |
625 | print((" [" + indexfmt + "] = " + valuefmt + ", /* %s */") % (index, value, comment)) | |
626 | else: | |
627 | print((" {" + indexfmt + ", " + valuefmt + "}, /* %s */") % (index, value, comment)) | |
628 | ||
263fef5b SR |
629 | class StdCLanguageGenerator(CLanguageGenerator): |
630 | ||
631 | def __init__(self): | |
632 | super(StdCLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int") | |
633 | ||
634 | class GLib2LanguageGenerator(CLanguageGenerator): | |
635 | ||
636 | def __init__(self): | |
637 | super(GLib2LanguageGenerator, self).__init__("guint16", "gchar *", "guint") | |
638 | ||
639 | class CHeaderLanguageGenerator(LanguageSrcGenerator): | |
640 | ||
641 | def __init__(self, inttypename, strtypename, lentypename): | |
642 | self.inttypename = inttypename | |
643 | self.strtypename = strtypename | |
644 | self.lentypename = lentypename | |
645 | ||
646 | def _boilerplate(self, lines): | |
647 | print("/*") | |
648 | for line in lines: | |
649 | print(" * %s" % line) | |
650 | print("*/") | |
651 | ||
652 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
653 | self._varname = varname | |
654 | if fromtype == self.TYPE_STRING: | |
655 | self._length = 0 | |
656 | else: | |
657 | self._length = length | |
658 | ||
659 | def _array_end(self, fromtype, totype): | |
660 | totypename = self.strtypename if totype == self.TYPE_STRING else self.inttypename | |
661 | if fromtype == self.TYPE_STRING: | |
662 | vartypename = "struct _%s" % self._varname | |
663 | print("%s {" % vartypename) | |
664 | print(" const %s from;" % self.strtypename) | |
665 | print(" const %s to;" % totypename) | |
666 | print("};") | |
667 | else: | |
668 | vartypename = totypename | |
669 | if type(self._length) == str: | |
670 | print("extern const %s %s[%s];" % (vartypename, self._varname, self._length)) | |
671 | else: | |
672 | print("extern const %s %s[%d];" % (vartypename, self._varname, self._length)) | |
673 | print("extern const %s %s_len;" % (self.lentypename, self._varname)) | |
674 | ||
675 | def _array_entry(self, index, value, comment, fromtype, totype): | |
676 | if value is None: | |
677 | return | |
678 | if fromtype == self.TYPE_STRING: | |
679 | self._length += 1 | |
680 | ||
681 | class StdCHeaderLanguageGenerator(CHeaderLanguageGenerator): | |
682 | ||
683 | def __init__(self): | |
684 | super(StdCHeaderLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int") | |
685 | ||
686 | class GLib2HeaderLanguageGenerator(CHeaderLanguageGenerator): | |
687 | ||
688 | def __init__(self): | |
689 | super(GLib2HeaderLanguageGenerator, self).__init__("guint16", "gchar *", "guint") | |
690 | ||
6838f038 WB |
691 | class CppLanguageGenerator(CLanguageGenerator): |
692 | ||
693 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
694 | if fromtype == self.TYPE_ENUM: | |
695 | raise NotImplementedError("Enums not supported as source in C++ generator") | |
696 | totypename = "const " + self.strtypename if totype == self.TYPE_STRING else self.inttypename | |
697 | if fromtype == self.TYPE_INT: | |
698 | print("#include <vector>") | |
263fef5b | 699 | print("extern const std::vector<%s> %s;" % (totypename, varname)); |
6838f038 WB |
700 | print("const std::vector<%s> %s = {" % (totypename, varname)) |
701 | else: | |
702 | print("#include <map>") | |
703 | print("#include <string>") | |
263fef5b | 704 | print("extern const std::map<const std::string, %s> %s;" % (totypename, varname)) |
6838f038 WB |
705 | print("const std::map<const std::string, %s> %s = {" % (totypename, varname)) |
706 | ||
707 | def _array_end(self, fromtype, totype): | |
708 | print("};") | |
709 | ||
710 | # designated initializers not available in C++ | |
711 | def _array_entry(self, index, value, comment, fromtype, totype): | |
712 | if fromtype == self.TYPE_STRING: | |
713 | return super(CppLanguageGenerator, self)._array_entry(index, value, comment, fromtype, totype) | |
714 | ||
715 | if value is None: | |
716 | print(" 0, /* %s */" % comment) | |
717 | elif totype == self.TYPE_INT: | |
718 | print(" 0x%x, /* %s */" % (value, comment)) | |
719 | elif totype == self.TYPE_ENUM: | |
720 | print(" %s, /* %s */" % (value, comment)) | |
721 | else: | |
722 | print(" \"%s\", /* %s */" % (value, comment)) | |
723 | ||
6838f038 WB |
724 | class StdCppLanguageGenerator(CppLanguageGenerator): |
725 | ||
726 | def __init__(self): | |
727 | super(StdCppLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int") | |
728 | ||
263fef5b SR |
729 | class CppHeaderLanguageGenerator(CHeaderLanguageGenerator): |
730 | ||
731 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
732 | if fromtype == self.TYPE_ENUM: | |
733 | raise NotImplementedError("Enums not supported as source in C++ generator") | |
734 | totypename = "const " + self.strtypename if totype == self.TYPE_STRING else self.inttypename | |
735 | if fromtype == self.TYPE_INT: | |
736 | print("#include <vector>") | |
737 | print("extern const std::vector<%s> %s;" % (totypename, varname)); | |
738 | else: | |
739 | print("#include <map>") | |
740 | print("#include <string>") | |
741 | print("extern const std::map<const std::string, %s> %s;" % (totypename, varname)) | |
742 | ||
743 | def _array_end(self, fromtype, totype): | |
744 | pass | |
745 | ||
746 | # designated initializers not available in C++ | |
747 | def _array_entry(self, index, value, comment, fromtype, totype): | |
748 | pass | |
749 | ||
750 | class StdCppHeaderLanguageGenerator(CppHeaderLanguageGenerator): | |
6838f038 WB |
751 | |
752 | def __init__(self): | |
263fef5b | 753 | super(StdCppHeaderLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int") |
6838f038 WB |
754 | |
755 | class PythonLanguageGenerator(LanguageSrcGenerator): | |
756 | ||
757 | def _boilerplate(self, lines): | |
758 | print("#") | |
759 | for line in lines: | |
760 | print("# %s" % line) | |
761 | print("#") | |
762 | ||
763 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
764 | if fromtype == self.TYPE_ENUM: | |
765 | raise NotImplementedError("Enums not supported as source in Python generator") | |
766 | ||
767 | if fromtype != self.TYPE_STRING: | |
768 | print("%s = [" % varname) | |
769 | else: | |
770 | print("%s = {" % varname) | |
771 | ||
772 | def _array_end(self, fromtype, totype): | |
773 | if fromtype != self.TYPE_STRING: | |
774 | print("]") | |
775 | else: | |
776 | print("}") | |
777 | ||
778 | def _array_entry(self, index, value, comment, fromtype, totype): | |
779 | if fromtype == self.TYPE_INT: | |
780 | if value is None: | |
781 | print(" None, # %s" % (comment)) | |
782 | elif totype == self.TYPE_INT: | |
783 | print(" 0x%x, # %s" % (value, comment)) | |
784 | elif totype == self.TYPE_ENUM: | |
785 | print(" %s, # %s" % (value, comment)) | |
786 | else: | |
787 | print(" \"%s\", # %s" % (value, comment)) | |
788 | else: | |
789 | if value is None: | |
790 | print(" \"%s\": None, # %s" % (index, comment)) | |
791 | elif totype == self.TYPE_INT: | |
792 | print(" \"%s\": 0x%x, # %s" % (index, value, comment)) | |
793 | elif totype == self.TYPE_ENUM: | |
794 | print(" \"%s\": %s, # %s" % (index, value, comment)) | |
795 | else: | |
796 | print(" \"%s\": \"%s\", # %s" % (index, value, comment)) | |
797 | ||
798 | class PerlLanguageGenerator(LanguageSrcGenerator): | |
799 | ||
800 | def _boilerplate(self, lines): | |
801 | print("#") | |
802 | for line in lines: | |
803 | print("# %s" % line) | |
804 | print("#") | |
805 | ||
806 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
807 | if fromtype == self.TYPE_ENUN: | |
808 | raise NotImplementedError("Enums not supported as source in Python generator") | |
809 | if fromtype == self.TYPE_INT: | |
810 | print("my @%s = (" % varname) | |
811 | else: | |
812 | print("my %%%s = (" % varname) | |
813 | ||
814 | def _array_end(self, fromtype, totype): | |
815 | print(");") | |
816 | ||
817 | def _array_entry(self, index, value, comment, fromtype, totype): | |
818 | if fromtype == self.TYPE_INT: | |
819 | if value is None: | |
820 | print(" undef, # %s" % (comment)) | |
821 | elif totype == self.TYPE_INT: | |
822 | print(" 0x%x, # %s" % (value, comment)) | |
823 | elif totype == self.TYPE_ENUM: | |
824 | print(" %s, # %s" % (value, comment)) | |
825 | else: | |
826 | print(" \"%s\", # %s" % (value, comment)) | |
827 | else: | |
828 | if value is None: | |
829 | print(" \"%s\", undef, # %s" % (index, comment)) | |
830 | elif totype == self.TYPE_INT: | |
831 | print(" \"%s\", 0x%x, # %s" % (index, value, comment)) | |
832 | elif totype == self.TYPE_ENUM: | |
833 | print(" \"%s\", 0x%x, # %s" % (index, value, comment)) | |
834 | else: | |
835 | print(" \"%s\", \"%s\", # %s" % (index, value, comment)) | |
836 | ||
837 | class JavaScriptLanguageGenerator(LanguageSrcGenerator): | |
838 | ||
839 | def _boilerplate(self, lines): | |
840 | print("/*") | |
841 | for line in lines: | |
842 | print(" * %s" % line) | |
843 | print("*/") | |
844 | ||
845 | def _array_start(self, varname, length, defvalue, fromtype, totype): | |
846 | print("export default {") | |
847 | ||
848 | def _array_end(self, fromtype, totype): | |
849 | print("};") | |
850 | ||
851 | def _array_entry(self, index, value, comment, fromtype, totype): | |
852 | if value is None: | |
853 | return | |
854 | ||
855 | if fromtype == self.TYPE_INT: | |
856 | fromfmt = "0x%x" | |
857 | elif fromtype == self.TYPE_ENUM: | |
858 | fromfmt = "%s" | |
859 | else: | |
860 | fromfmt = "\"%s\"" | |
861 | ||
862 | if totype == self.TYPE_INT: | |
863 | tofmt = "0x%x" | |
864 | elif totype == self.TYPE_ENUM: | |
865 | tofmt = "%s" | |
866 | else: | |
867 | tofmt = "\"%s\"" | |
868 | ||
869 | print((" " + fromfmt + ": " + tofmt + ", /* %s */") % (index, value, comment)) | |
870 | ||
871 | class PodLanguageGenerator(LanguageDocGenerator): | |
872 | ||
873 | def _boilerplate(self, lines): | |
874 | print("#") | |
875 | for line in lines: | |
876 | print("# %s" % line) | |
877 | print("#") | |
878 | ||
263fef5b SR |
879 | def _array_start_name_doc(self, title, subtitle, namemap): |
880 | print("=head1 NAME") | |
881 | print("") | |
882 | print("%s - %s" % (title, subtitle)) | |
883 | print("") | |
884 | print("=head1 DESCRIPTION") | |
6838f038 WB |
885 | print("") |
886 | print("List of %s key code names, with corresponding key code values" % namemap) | |
887 | print("") | |
888 | print("=over 4") | |
889 | print("") | |
890 | ||
263fef5b SR |
891 | def _array_start_code_doc(self, title, subtitle, codemap, namemap): |
892 | print("=head1 NAME") | |
893 | print("") | |
894 | print("%s - %s" % (title, subtitle)) | |
895 | print("") | |
896 | print("=head1 DESCRIPTION") | |
6838f038 WB |
897 | print("") |
898 | print("List of %s key code values, with corresponding %s key code names" % (codemap, namemap)) | |
899 | print("") | |
900 | print("=over 4") | |
901 | print("") | |
902 | ||
903 | def _array_end(self): | |
904 | print("=back") | |
905 | print("") | |
906 | ||
907 | def _array_name_entry(self, value, name): | |
908 | print("=item %s" % name) | |
909 | print("") | |
910 | print("Key value %d (0x%x)" % (value, value)) | |
911 | print("") | |
912 | ||
913 | def _array_code_entry(self, value, name): | |
914 | print("=item %d (0x%x)" % (value, value)) | |
915 | print("") | |
916 | print("Key name %s" % name) | |
917 | print("") | |
918 | ||
263fef5b SR |
919 | class RSTLanguageGenerator(LanguageDocGenerator): |
920 | ||
921 | def _boilerplate(self, lines): | |
922 | print("..") | |
923 | for line in lines: | |
924 | print(" %s" % line) | |
925 | print("") | |
926 | ||
927 | def _array_start_name_doc(self, title, subtitle, namemap): | |
928 | print("=" * len(title)) | |
929 | print(title) | |
930 | print("=" * len(title)) | |
931 | print("") | |
932 | print("-" * len(subtitle)) | |
933 | print(subtitle) | |
934 | print("-" * len(subtitle)) | |
935 | print("") | |
936 | print(":Manual section: 7") | |
937 | print(":Manual group: Virtualization Support") | |
938 | print("") | |
939 | print("DESCRIPTION") | |
940 | print("===========") | |
941 | print("List of %s key code names, with corresponding key code values" % namemap) | |
942 | print("") | |
943 | ||
944 | def _array_start_code_doc(self, title, subtitle, codemap, namemap): | |
945 | print("=" * len(title)) | |
946 | print(title) | |
947 | print("=" * len(title)) | |
948 | print("") | |
949 | print("-" * len(subtitle)) | |
950 | print(subtitle) | |
951 | print("-" * len(subtitle)) | |
952 | print("") | |
953 | print(":Manual section: 7") | |
954 | print(":Manual group: Virtualization Support") | |
955 | print("") | |
956 | print("DESCRIPTION") | |
957 | print("===========") | |
958 | print("List of %s key code values, with corresponding %s key code names" % (codemap, namemap)) | |
959 | print("") | |
960 | ||
961 | def _array_end(self): | |
962 | print("") | |
963 | ||
964 | def _array_name_entry(self, value, name): | |
965 | print("* %s" % name) | |
966 | print("") | |
967 | print(" Key value %d (0x%x)" % (value, value)) | |
968 | print("") | |
969 | ||
970 | def _array_code_entry(self, value, name): | |
971 | print("* %d (0x%x)" % (value, value)) | |
972 | print("") | |
973 | print(" Key name %s" % name) | |
974 | print("") | |
975 | ||
6838f038 WB |
976 | SRC_GENERATORS = { |
977 | "stdc": StdCLanguageGenerator(), | |
263fef5b | 978 | "stdc-header": StdCHeaderLanguageGenerator(), |
6838f038 | 979 | "stdc++": StdCppLanguageGenerator(), |
263fef5b | 980 | "stdc++-header": StdCppHeaderLanguageGenerator(), |
6838f038 | 981 | "glib2": GLib2LanguageGenerator(), |
263fef5b | 982 | "glib2-header": GLib2HeaderLanguageGenerator(), |
6838f038 WB |
983 | "python2": PythonLanguageGenerator(), |
984 | "python3": PythonLanguageGenerator(), | |
985 | "perl": PerlLanguageGenerator(), | |
986 | "js": JavaScriptLanguageGenerator(), | |
987 | } | |
988 | DOC_GENERATORS = { | |
989 | "pod": PodLanguageGenerator(), | |
263fef5b | 990 | "rst": RSTLanguageGenerator(), |
6838f038 WB |
991 | } |
992 | ||
993 | def code_map(args): | |
994 | database = Database() | |
995 | database.load(args.keymaps) | |
996 | ||
263fef5b | 997 | cliargs = ["keymap-gen", "code-map", "--lang=%s" % args.lang] |
6838f038 WB |
998 | if args.varname is not None: |
999 | cliargs.append("--varname=%s" % args.varname) | |
263fef5b | 1000 | cliargs.extend(["keymaps.csv", args.frommapname, args.tomapname]) |
6838f038 WB |
1001 | SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1002 | ||
1003 | SRC_GENERATORS[args.lang].generate_code_map(args.varname, database, args.frommapname, args.tomapname) | |
1004 | ||
1005 | def code_table(args): | |
1006 | database = Database() | |
1007 | database.load(args.keymaps) | |
1008 | ||
263fef5b | 1009 | cliargs = ["keymap-gen", "code-table", "--lang=%s" % args.lang] |
6838f038 WB |
1010 | if args.varname is not None: |
1011 | cliargs.append("--varname=%s" % args.varname) | |
263fef5b | 1012 | cliargs.extend(["keymaps.csv", args.mapname]) |
6838f038 WB |
1013 | SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1014 | ||
1015 | SRC_GENERATORS[args.lang].generate_code_table(args.varname, database, args.mapname) | |
1016 | ||
1017 | def name_map(args): | |
1018 | database = Database() | |
1019 | database.load(args.keymaps) | |
1020 | ||
263fef5b | 1021 | cliargs = ["keymap-gen", "name-map", "--lang=%s" % args.lang] |
6838f038 WB |
1022 | if args.varname is not None: |
1023 | cliargs.append("--varname=%s" % args.varname) | |
263fef5b | 1024 | cliargs.extend(["keymaps.csv", args.frommapname, args.tomapname]) |
6838f038 WB |
1025 | SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1026 | ||
1027 | SRC_GENERATORS[args.lang].generate_name_map(args.varname, database, args.frommapname, args.tomapname) | |
1028 | ||
1029 | def name_table(args): | |
1030 | database = Database() | |
1031 | database.load(args.keymaps) | |
1032 | ||
1033 | ||
263fef5b | 1034 | cliargs = ["keymap-gen", "name-table", "--lang=%s" % args.lang] |
6838f038 WB |
1035 | if args.varname is not None: |
1036 | cliargs.append("--varname=%s" % args.varname) | |
263fef5b | 1037 | cliargs.extend(["keymaps.csv", args.mapname]) |
6838f038 WB |
1038 | SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1039 | ||
1040 | SRC_GENERATORS[args.lang].generate_name_table(args.varname, database, args.mapname) | |
1041 | ||
1042 | def code_docs(args): | |
1043 | database = Database() | |
1044 | database.load(args.keymaps) | |
1045 | ||
1046 | ||
263fef5b SR |
1047 | cliargs = ["keymap-gen", "code-docs", "--lang=%s" % args.lang] |
1048 | if args.title is not None: | |
1049 | cliargs.append("--title=%s" % args.title) | |
1050 | if args.subtitle is not None: | |
1051 | cliargs.append("--subtitle=%s" % args.subtitle) | |
1052 | cliargs.extend(["keymaps.csv", args.mapname]) | |
6838f038 WB |
1053 | DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1054 | ||
263fef5b | 1055 | DOC_GENERATORS[args.lang].generate_code_docs(args.title, args.subtitle, database, args.mapname) |
6838f038 WB |
1056 | |
1057 | def name_docs(args): | |
1058 | database = Database() | |
1059 | database.load(args.keymaps) | |
1060 | ||
1061 | ||
263fef5b SR |
1062 | cliargs = ["keymap-gen", "name-docs", "--lang=%s" % args.lang] |
1063 | if args.title is not None: | |
1064 | cliargs.append("--title=%s" % args.title) | |
1065 | if args.subtitle is not None: | |
1066 | cliargs.append("--subtitle=%s" % args.subtitle) | |
1067 | cliargs.extend(["keymaps.csv", args.mapname]) | |
6838f038 WB |
1068 | DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) |
1069 | ||
263fef5b | 1070 | DOC_GENERATORS[args.lang].generate_name_docs(args.title, args.subtitle, database, args.mapname) |
6838f038 WB |
1071 | |
1072 | def usage(): | |
1073 | print ("Please select a command:") | |
1074 | print (" 'code-map', 'code-table', 'name-map', 'name-table', 'docs'") | |
1075 | sys.exit(1) | |
1076 | ||
1077 | def main(): | |
1078 | parser = argparse.ArgumentParser() | |
1079 | ||
6838f038 WB |
1080 | subparsers = parser.add_subparsers(help="sub-command help") |
1081 | ||
1082 | codemapparser = subparsers.add_parser("code-map", help="Generate a mapping between code tables") | |
263fef5b SR |
1083 | codemapparser.add_argument("--varname", default=None, help="Data variable name") |
1084 | codemapparser.add_argument("--lang", default="stdc", | |
1085 | help="Output language (%s)" % ( | |
1086 | ",".join(SRC_GENERATORS.keys()))) | |
6838f038 WB |
1087 | codemapparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1088 | codemapparser.add_argument("frommapname", help="Source code table name") | |
1089 | codemapparser.add_argument("tomapname", help="Target code table name") | |
1090 | codemapparser.set_defaults(func=code_map) | |
1091 | ||
1092 | codetableparser = subparsers.add_parser("code-table", help="Generate a flat code table") | |
263fef5b SR |
1093 | codetableparser.add_argument("--lang", default="stdc", |
1094 | help="Output language (%s)" % ( | |
1095 | ",".join(SRC_GENERATORS.keys()))) | |
1096 | codetableparser.add_argument("--varname", default=None, help="Data variable name") | |
6838f038 WB |
1097 | codetableparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1098 | codetableparser.add_argument("mapname", help="Code table name") | |
1099 | codetableparser.set_defaults(func=code_table) | |
1100 | ||
1101 | namemapparser = subparsers.add_parser("name-map", help="Generate a mapping to names") | |
263fef5b SR |
1102 | namemapparser.add_argument("--lang", default="stdc", |
1103 | help="Output language (%s)" % ( | |
1104 | ",".join(SRC_GENERATORS.keys()))) | |
1105 | namemapparser.add_argument("--varname", default=None, help="Data variable name") | |
6838f038 WB |
1106 | namemapparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1107 | namemapparser.add_argument("frommapname", help="Source code table name") | |
1108 | namemapparser.add_argument("tomapname", help="Target name table name") | |
1109 | namemapparser.set_defaults(func=name_map) | |
1110 | ||
1111 | nametableparser = subparsers.add_parser("name-table", help="Generate a flat name table") | |
263fef5b SR |
1112 | nametableparser.add_argument("--lang", default="stdc", |
1113 | help="Output language, (%s)" % ( | |
1114 | ",".join(SRC_GENERATORS.keys()))) | |
1115 | nametableparser.add_argument("--varname", default=None, help="Data variable name") | |
6838f038 WB |
1116 | nametableparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1117 | nametableparser.add_argument("mapname", help="Name table name") | |
1118 | nametableparser.set_defaults(func=name_table) | |
1119 | ||
1120 | codedocsparser = subparsers.add_parser("code-docs", help="Generate code documentation") | |
263fef5b SR |
1121 | codedocsparser.add_argument("--lang", default="pod", |
1122 | help="Output language (%s)" % ( | |
1123 | ",".join(DOC_GENERATORS.keys()))) | |
1124 | codedocsparser.add_argument("--title", default=None, help="Document title") | |
1125 | codedocsparser.add_argument("--subtitle", default=None, help="Document subtitle") | |
6838f038 WB |
1126 | codedocsparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1127 | codedocsparser.add_argument("mapname", help="Code table name") | |
1128 | codedocsparser.set_defaults(func=code_docs) | |
1129 | ||
1130 | namedocsparser = subparsers.add_parser("name-docs", help="Generate name documentation") | |
263fef5b SR |
1131 | namedocsparser.add_argument("--lang", default="pod", |
1132 | help="Output language (%s)" % ( | |
1133 | ",".join(DOC_GENERATORS.keys()))) | |
1134 | namedocsparser.add_argument("--title", default=None, help="Document title") | |
1135 | namedocsparser.add_argument("--subtitle", default=None, help="Document subtitle") | |
6838f038 WB |
1136 | namedocsparser.add_argument("keymaps", help="Path to keymap CSV data file") |
1137 | namedocsparser.add_argument("mapname", help="Name table name") | |
1138 | namedocsparser.set_defaults(func=name_docs) | |
1139 | ||
1140 | args = parser.parse_args() | |
1141 | if hasattr(args, "func"): | |
1142 | args.func(args) | |
1143 | else: | |
1144 | usage() | |
1145 | ||
1146 | ||
1147 | main() |