18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#!/usr/bin/python
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# a python script used to generate some C constant tables from a key charmap file
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# usage:
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    progname file.kcm > charmap-tab.h
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectimport sys, os, string, re
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectheader = """\
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android_charmap.h"
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* the following is automatically generated by the 'gen-charmap.py' script
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * do not touch. the generation command was:
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *   gen-charmap.py\
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project"""
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectheader2 = """
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project"""
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectkmap_header = """\
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const AKeyEntry  _%(name)s_keys[] =
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* keycode                   base   caps    fn  caps+fn   number */
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project"""
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectkmap_footer = """\
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const AKeyCharmap  _%(name)s_charmap =
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _%(name)s_keys,
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    %(count)d,
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "%(name)s"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project"""
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectre_mapname = re.compile( r".*/(\w+).kcm" )
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectre_start = re.compile( r"(\w+)\s*(.*)" )
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectre_char  = re.compile( r"('.')\s*(.*)" )
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectre_hex   = re.compile( r"(0x\w+)\s*(.*)" )
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectspecials = { 'COMMA': 'Comma',
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'PERIOD': 'Period',
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'AT': 'At',
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'LEFT_BRACKET': 'LeftBracket',
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'RIGHT_BRACKET': 'RightBracket',
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'SLASH': 'Slash',
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'BACKSLASH': 'Backslash',
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'GRAVE': 'Grave',
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'MINUS': 'Minus',
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'EQUALS': 'Equals',
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'SEMICOLON': 'Semicolon',
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'APOSTROPHE': 'Apostrophe',
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             'SPACE': 'Space',
599085a28c14f369d231dbae099a690689179f428avchtchetkine             'ENTER': 'Newline',
609085a28c14f369d231dbae099a690689179f428avchtchetkine             'TAB': 'Tab',
619085a28c14f369d231dbae099a690689179f428avchtchetkine             'STAR': 'Star',
629085a28c14f369d231dbae099a690689179f428avchtchetkine             'POUND': 'Pound',
639085a28c14f369d231dbae099a690689179f428avchtchetkine             'PLUS': 'Plus',
649085a28c14f369d231dbae099a690689179f428avchtchetkine             'DEL': 'Del'
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           }
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectentries = []
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdef match_char_or_hex(line):
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = re_char.match(line)
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        m = re_hex.match(line)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return m
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdef quote(s):
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if s == "'''":
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s = "'\\''"
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    elif s == "'\\'":
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s = "'\\\\'"
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdef process_line(line,result):
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = re_start.match(line)
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "bad bad line: " + line
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    keycode = m.group(1)
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line    = m.group(2)
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = match_char_or_hex(line)
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "character expected in: " + line
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
939085a28c14f369d231dbae099a690689179f428avchtchetkine    disp = quote(m.group(1))
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line = m.group(2)
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = match_char_or_hex(line)
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "character expected in: " + line
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
999085a28c14f369d231dbae099a690689179f428avchtchetkine    number = quote(m.group(1))
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line = m.group(2)
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = match_char_or_hex(line)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "character expected in: " + line
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
1059085a28c14f369d231dbae099a690689179f428avchtchetkine    base = quote(m.group(1))
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line = m.group(2)
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = match_char_or_hex(line)
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "character expected in: " + line
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
1119085a28c14f369d231dbae099a690689179f428avchtchetkine    caps = quote(m.group(1))
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line = m.group(2)
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = match_char_or_hex(line)
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if not m:
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "character expected in: " + line
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1
1179085a28c14f369d231dbae099a690689179f428avchtchetkine    fn = quote(m.group(1))
1189085a28c14f369d231dbae099a690689179f428avchtchetkine    line = m.group(2)
1199085a28c14f369d231dbae099a690689179f428avchtchetkine    m = match_char_or_hex(line)
1209085a28c14f369d231dbae099a690689179f428avchtchetkine    if not m:
1219085a28c14f369d231dbae099a690689179f428avchtchetkine        print "character expected in: " + line
1229085a28c14f369d231dbae099a690689179f428avchtchetkine        return -1
1239085a28c14f369d231dbae099a690689179f428avchtchetkine    caps_fn = quote(m.group(1))
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if specials.has_key(keycode):
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        keycode = specials[keycode]
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    keycode = "kKeyCode" + keycode
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result.append( (keycode,base,caps,fn,caps_fn,number) )
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdef process_file( file ):
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = []
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fp = open(file,"rb")
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for line in fp.xreadlines():
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line = line.strip()
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if not line:   # skip empty lines
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if line[0] == '#' or line[0] == '[':  # skip
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if process_line(line,result) < 0:
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fp.close()
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclass KMap:
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    def __init__(self,name,results):
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        self.name    = name
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        self.results = results
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    def dump(self):
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        t = { 'name': self.name, 'count':len(self.results) }
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print kmap_header % t
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for item in self.results:
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            print "    { %-22s, %5s, %5s, %5s, %6s, %5s }," % item
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print kmap_footer % t
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectkmaps = []
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectif len(sys.argv) < 2:
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print "usage: progname  charmap.kcm [charmap2.kcm ...] > charmap-tab.h"
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectelse:
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    genline = ""
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for filepath in sys.argv[1:]:
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        m = re_mapname.match(filepath)
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if not m:
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            print "%s is not a keyboard charmap name" % filepath
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            os.exit(1)
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mapname = m.group(1)
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        genline = genline + " " + mapname + ".kcm"
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for filepath in sys.argv[1:]:
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        m = re_mapname.match(filepath)
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mapname = m.group(1)
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = process_file( filepath )
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        kmap = KMap(mapname,result)
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        kmaps.append(kmap)
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print header + genline + header2
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for kmap in kmaps:
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        kmap.dump()
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print "const AKeyCharmap*  android_charmaps[%d] = {" % len(kmaps),
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    comma = ""
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for kmap in kmaps:
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        print "%s&_%s_charmap" % (comma, kmap.name),
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        comma = ", "
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print "};"
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print "const int           android_charmap_count = %d;" % len(kmaps)
191