Home | History | Annotate | Download | only in android
      1 /* Copyright (C) 2007-2008 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 #include "qemu-common.h"
     13 #include "android/utils/path.h"
     14 #include "android/utils/misc.h"
     15 #include "android/utils/debug.h"
     16 #include "android/charmap.h"
     17 
     18 /* Parses .kcm file producing key characters map.
     19  * .kcm file parsed by this module is expected to contain 4 types of
     20  * lines:
     21  * 1. An empty line (containing no characters, or only space or tab
     22  *    characters).
     23  * 2. A comment line (begins with '#')
     24  * 3. A type section line (begins with '[')
     25  * 4. Character map line, formatted as such:
     26  * Key code value, followed by one or more space or tab characters.
     27  * Display value, followed by one or more space or tab characters.
     28  * Number value, followed by one or more space or tab characters.
     29  * Base value, followed by one or more space or tab characters.
     30  * Caps value, followed by one or more space or tab characters.
     31  * Fn value, followed by one or more space or tab characters.
     32  * Caps_fn value, followed by one or more space or tab characters.
     33  * All values, except for the key code value must be either in character
     34  * form ('X', where X is the value), or in hexadecimal form (0xXXXX, where
     35  * XXXX is hexadecimal representation of the value). Note that if value is
     36  * in hexadecimal form, it must not exceed value that can be contained in
     37  * variable of 'unsigned short' type.
     38  * Bellow are a couple of examples of valid .kcm file lines:
     39  * # keycode       display number  base    caps    fn      caps_fn
     40  * A               'A'     '2'     'a'     'A'     '#'     0x00
     41  * PERIOD          '.'     '.'     '.'     ':'     ':'     0x2026
     42  * SPACE           0x20    0x20    0x20    0x20    0xEF01  0xEF01
     43 */
     44 
     45 /* Maximum length of a line expected in .kcm file. */
     46 #define KCM_MAX_LINE_LEN    1024
     47 
     48 /* Maximum length of a token in a key map line. */
     49 #define KCM_MAX_TOKEN_LEN   512
     50 
     51 /* Maps symbol name from .kcm file to a keycode value. */
     52 typedef struct AKeycodeMapEntry {
     53     /* Symbol name from .kcm file. */
     54     const char* key_name;
     55 
     56     /* Key code value for the symbol. */
     57     int         key_code;
     58 } AKeycodeMapEntry;
     59 
     60 /* Result of parsing a line in a .kcm file. */
     61 typedef enum {
     62     /* Line format was bad. */
     63     BAD_FORMAT,
     64 
     65     /* Line had been skipped (an empty line, or a comment, etc.). */
     66     SKIP_LINE,
     67 
     68     /* Line represents an entry in the key map. */
     69     KEY_ENTRY,
     70 } ParseStatus;
     71 
     72 static const AKeycodeMapEntry keycode_map[] = {
     73     /*  Symbol           Key code */
     74 
     75       { "A",             kKeyCodeA },
     76       { "B",             kKeyCodeB },
     77       { "C",             kKeyCodeC },
     78       { "D",             kKeyCodeD },
     79       { "E",             kKeyCodeE },
     80       { "F",             kKeyCodeF },
     81       { "G",             kKeyCodeG },
     82       { "H",             kKeyCodeH },
     83       { "I",             kKeyCodeI },
     84       { "J",             kKeyCodeJ },
     85       { "K",             kKeyCodeK },
     86       { "L",             kKeyCodeL },
     87       { "M",             kKeyCodeM },
     88       { "N",             kKeyCodeN },
     89       { "O",             kKeyCodeO },
     90       { "P",             kKeyCodeP },
     91       { "Q",             kKeyCodeQ },
     92       { "R",             kKeyCodeR },
     93       { "S",             kKeyCodeS },
     94       { "T",             kKeyCodeT },
     95       { "U",             kKeyCodeU },
     96       { "V",             kKeyCodeV },
     97       { "W",             kKeyCodeW },
     98       { "X",             kKeyCodeX },
     99       { "Y",             kKeyCodeY },
    100       { "Z",             kKeyCodeZ },
    101       { "0",             kKeyCode0 },
    102       { "1",             kKeyCode1 },
    103       { "2",             kKeyCode2 },
    104       { "3",             kKeyCode3 },
    105       { "4",             kKeyCode4 },
    106       { "5",             kKeyCode5 },
    107       { "6",             kKeyCode6 },
    108       { "7",             kKeyCode7 },
    109       { "8",             kKeyCode8 },
    110       { "9",             kKeyCode9 },
    111       { "COMMA",         kKeyCodeComma },
    112       { "PERIOD",        kKeyCodePeriod },
    113       { "AT",            kKeyCodeAt },
    114       { "SLASH",         kKeyCodeSlash },
    115       { "SPACE",         kKeyCodeSpace },
    116       { "ENTER",         kKeyCodeNewline },
    117       { "TAB",           kKeyCodeTab },
    118       { "GRAVE",         kKeyCodeGrave },
    119       { "MINUS",         kKeyCodeMinus },
    120       { "EQUALS",        kKeyCodeEquals },
    121       { "LEFT_BRACKET",  kKeyCodeLeftBracket },
    122       { "RIGHT_BRACKET", kKeyCodeRightBracket },
    123       { "BACKSLASH",     kKeyCodeBackslash },
    124       { "SEMICOLON",     kKeyCodeSemicolon },
    125       { "APOSTROPHE",    kKeyCodeApostrophe },
    126       { "STAR",          kKeyCodeStar },
    127       { "POUND",         kKeyCodePound },
    128       { "PLUS",          kKeyCodePlus },
    129       { "DEL",           kKeyCodeDel },
    130 };
    131 
    132 /* the following is automatically generated by the 'gen-charmap.py' script
    133  * do not touch. the generation command was:
    134  *   gen-charmap.py qwerty.kcm qwerty2.kcm
    135  */
    136 
    137 static const AKeyEntry  _qwerty_keys[] =
    138 {
    139    /* keycode                   base   caps    fn  caps+fn   number */
    140 
    141     { kKeyCodeA             ,   'a',   'A',   '#',   0x00,   '#' },
    142     { kKeyCodeB             ,   'b',   'B',   '<',   0x00,   '<' },
    143     { kKeyCodeC             ,   'c',   'C',   '9', 0x00E7,   '9' },
    144     { kKeyCodeD             ,   'd',   'D',   '5',   0x00,   '5' },
    145     { kKeyCodeE             ,   'e',   'E',   '2', 0x0301,   '2' },
    146     { kKeyCodeF             ,   'f',   'F',   '6', 0x00A5,   '6' },
    147     { kKeyCodeG             ,   'g',   'G',   '-',    '_',   '-' },
    148     { kKeyCodeH             ,   'h',   'H',   '[',    '{',   '[' },
    149     { kKeyCodeI             ,   'i',   'I',   '$', 0x0302,   '$' },
    150     { kKeyCodeJ             ,   'j',   'J',   ']',    '}',   ']' },
    151     { kKeyCodeK             ,   'k',   'K',   '"',    '~',   '"' },
    152     { kKeyCodeL             ,   'l',   'L',  '\'',    '`',  '\'' },
    153     { kKeyCodeM             ,   'm',   'M',   '!',   0x00,   '!' },
    154     { kKeyCodeN             ,   'n',   'N',   '>', 0x0303,   '>' },
    155     { kKeyCodeO             ,   'o',   'O',   '(',   0x00,   '(' },
    156     { kKeyCodeP             ,   'p',   'P',   ')',   0x00,   ')' },
    157     { kKeyCodeQ             ,   'q',   'Q',   '*', 0x0300,   '*' },
    158     { kKeyCodeR             ,   'r',   'R',   '3', 0x20AC,   '3' },
    159     { kKeyCodeS             ,   's',   'S',   '4', 0x00DF,   '4' },
    160     { kKeyCodeT             ,   't',   'T',   '+', 0x00A3,   '+' },
    161     { kKeyCodeU             ,   'u',   'U',   '&', 0x0308,   '&' },
    162     { kKeyCodeV             ,   'v',   'V',   '=',    '^',   '=' },
    163     { kKeyCodeW             ,   'w',   'W',   '1',   0x00,   '1' },
    164     { kKeyCodeX             ,   'x',   'X',   '8',   0x00,   '8' },
    165     { kKeyCodeY             ,   'y',   'Y',   '%', 0x00A1,   '%' },
    166     { kKeyCodeZ             ,   'z',   'Z',   '7',   0x00,   '7' },
    167     { kKeyCodeComma         ,   ',',   ';',   ';',    '|',   ',' },
    168     { kKeyCodePeriod        ,   '.',   ':',   ':', 0x2026,   '.' },
    169     { kKeyCodeAt            ,   '@',   '0',   '0', 0x2022,   '0' },
    170     { kKeyCodeSlash         ,   '/',   '?',   '?',   '\\',   '/' },
    171     { kKeyCodeSpace         ,  0x20,  0x20,   0x9,    0x9,  0x20 },
    172     { kKeyCodeNewline       ,   0xa,   0xa,   0xa,    0xa,   0xa },
    173     { kKeyCodeTab           ,   0x9,   0x9,   0x9,    0x9,   0x9 },
    174     { kKeyCode0             ,   '0',   ')',   '0',    ')',   '0' },
    175     { kKeyCode1             ,   '1',   '!',   '1',    '!',   '1' },
    176     { kKeyCode2             ,   '2',   '@',   '2',    '@',   '2' },
    177     { kKeyCode3             ,   '3',   '#',   '3',    '#',   '3' },
    178     { kKeyCode4             ,   '4',   '$',   '4',    '$',   '4' },
    179     { kKeyCode5             ,   '5',   '%',   '5',    '%',   '5' },
    180     { kKeyCode6             ,   '6',   '^',   '6',    '^',   '6' },
    181     { kKeyCode7             ,   '7',   '&',   '7',    '&',   '7' },
    182     { kKeyCode8             ,   '8',   '*',   '8',    '*',   '8' },
    183     { kKeyCode9             ,   '9',   '(',   '9',    '(',   '9' },
    184     { kKeyCodeGrave         ,   '`',   '~',   '`',    '~',   '`' },
    185     { kKeyCodeMinus         ,   '-',   '_',   '-',    '_',   '-' },
    186     { kKeyCodeEquals        ,   '=',   '+',   '=',    '+',   '=' },
    187     { kKeyCodeLeftBracket   ,   '[',   '{',   '[',    '{',   '[' },
    188     { kKeyCodeRightBracket  ,   ']',   '}',   ']',    '}',   ']' },
    189     { kKeyCodeBackslash     ,  '\\',   '|',  '\\',    '|',  '\\' },
    190     { kKeyCodeSemicolon     ,   ';',   ':',   ';',    ':',   ';' },
    191     { kKeyCodeApostrophe    ,  '\'',   '"',  '\'',    '"',  '\'' },
    192 };
    193 
    194 static const AKeyCharmap  _qwerty_charmap =
    195 {
    196     _qwerty_keys,
    197     51,
    198     "qwerty"
    199 };
    200 
    201 static const AKeyEntry  _qwerty2_keys[] =
    202 {
    203    /* keycode                   base   caps    fn  caps+fn   number */
    204 
    205     { kKeyCodeA             ,   'a',   'A',   'a',    'A',   'a' },
    206     { kKeyCodeB             ,   'b',   'B',   'b',    'B',   'b' },
    207     { kKeyCodeC             ,   'c',   'C', 0x00e7, 0x00E7,   'c' },
    208     { kKeyCodeD             ,   'd',   'D',  '\'',   '\'',  '\'' },
    209     { kKeyCodeE             ,   'e',   'E',   '"', 0x0301,   '"' },
    210     { kKeyCodeF             ,   'f',   'F',   '[',    '[',   '[' },
    211     { kKeyCodeG             ,   'g',   'G',   ']',    ']',   ']' },
    212     { kKeyCodeH             ,   'h',   'H',   '<',    '<',   '<' },
    213     { kKeyCodeI             ,   'i',   'I',   '-', 0x0302,   '-' },
    214     { kKeyCodeJ             ,   'j',   'J',   '>',    '>',   '>' },
    215     { kKeyCodeK             ,   'k',   'K',   ';',    '~',   ';' },
    216     { kKeyCodeL             ,   'l',   'L',   ':',    '`',   ':' },
    217     { kKeyCodeM             ,   'm',   'M',   '%',   0x00,   '%' },
    218     { kKeyCodeN             ,   'n',   'N',  0x00, 0x0303,   'n' },
    219     { kKeyCodeO             ,   'o',   'O',   '+',    '+',   '+' },
    220     { kKeyCodeP             ,   'p',   'P',   '=', 0x00A5,   '=' },
    221     { kKeyCodeQ             ,   'q',   'Q',   '|', 0x0300,   '|' },
    222     { kKeyCodeR             ,   'r',   'R',   '`', 0x20AC,   '`' },
    223     { kKeyCodeS             ,   's',   'S',  '\\', 0x00DF,  '\\' },
    224     { kKeyCodeT             ,   't',   'T',   '{', 0x00A3,   '}' },
    225     { kKeyCodeU             ,   'u',   'U',   '_', 0x0308,   '_' },
    226     { kKeyCodeV             ,   'v',   'V',   'v',    'V',   'v' },
    227     { kKeyCodeW             ,   'w',   'W',   '~',    '~',   '~' },
    228     { kKeyCodeX             ,   'x',   'X',   'x',    'X',   'x' },
    229     { kKeyCodeY             ,   'y',   'Y',   '}', 0x00A1,   '}' },
    230     { kKeyCodeZ             ,   'z',   'Z',   'z',    'Z',   'z' },
    231     { kKeyCodeComma         ,   ',',   '<',   ',',    ',',   ',' },
    232     { kKeyCodePeriod        ,   '.',   '>',   '.', 0x2026,   '.' },
    233     { kKeyCodeAt            ,   '@',   '@',   '@', 0x2022,   '@' },
    234     { kKeyCodeSlash         ,   '/',   '?',   '?',    '?',   '/' },
    235     { kKeyCodeSpace         ,  0x20,  0x20,   0x9,    0x9,  0x20 },
    236     { kKeyCodeNewline       ,   0xa,   0xa,   0xa,    0xa,   0xa },
    237     { kKeyCode0             ,   '0',   ')',   ')',    ')',   '0' },
    238     { kKeyCode1             ,   '1',   '!',   '!',    '!',   '1' },
    239     { kKeyCode2             ,   '2',   '@',   '@',    '@',   '2' },
    240     { kKeyCode3             ,   '3',   '#',   '#',    '#',   '3' },
    241     { kKeyCode4             ,   '4',   '$',   '$',    '$',   '4' },
    242     { kKeyCode5             ,   '5',   '%',   '%',    '%',   '5' },
    243     { kKeyCode6             ,   '6',   '^',   '^',    '^',   '6' },
    244     { kKeyCode7             ,   '7',   '&',   '&',    '&',   '7' },
    245     { kKeyCode8             ,   '8',   '*',   '*',    '*',   '8' },
    246     { kKeyCode9             ,   '9',   '(',   '(',    '(',   '9' },
    247     { kKeyCodeTab           ,   0x9,   0x9,   0x9,    0x9,   0x9 },
    248     { kKeyCodeGrave         ,   '`',   '~',   '`',    '~',   '`' },
    249     { kKeyCodeMinus         ,   '-',   '_',   '-',    '_',   '-' },
    250     { kKeyCodeEquals        ,   '=',   '+',   '=',    '+',   '=' },
    251     { kKeyCodeLeftBracket   ,   '[',   '{',   '[',    '{',   '[' },
    252     { kKeyCodeRightBracket  ,   ']',   '}',   ']',    '}',   ']' },
    253     { kKeyCodeBackslash     ,  '\\',   '|',  '\\',    '|',  '\\' },
    254     { kKeyCodeSemicolon     ,   ';',   ':',   ';',    ':',   ';' },
    255     { kKeyCodeApostrophe    ,  '\'',   '"',  '\'',    '"',  '\'' },
    256 };
    257 
    258 static const AKeyCharmap  _qwerty2_charmap =
    259 {
    260     _qwerty2_keys,
    261     51,
    262     "qwerty2"
    263 };
    264 
    265 /* Custom character map created with -charmap option. */
    266 static AKeyCharmap android_custom_charmap = { 0 };
    267 
    268 const AKeyCharmap** android_charmaps = 0;
    269 int                 android_charmap_count = 0;
    270 
    271 /* Checks if a character represents an end of the line.
    272  * Returns a non-zero value if ch is an EOL character. Returns
    273  * zero value if ch is not an EOL character.
    274 */
    275 static int
    276 kcm_is_eol(char ch) {
    277     // EOLs are 0, \r and \n chars.
    278     return ('\0' == ch) || ('\n' == ch) || ('\r' == ch);
    279 }
    280 
    281 /* Checks if a character represents a token separator.
    282  * Returns a non-zero value if ch is a token separator.
    283  * Returns zero value if ch is not a token separator.
    284 */
    285 static int
    286 kcm_is_token_separator(char ch) {
    287     // Spaces and tabs are the only separators allowed
    288     // between tokens in .kcm files.
    289     return (' ' == ch) || ('\t' == ch);
    290 }
    291 
    292 /* Checks if a character represents a path separator.
    293  * Returns a non-zero value if ch is a path separator.
    294  * Returns zero value if ch is not a path separator.
    295 */
    296 static int
    297 kcm_is_path_separator(char ch) {
    298 #ifdef _WIN32
    299     return '/' == ch || '\\' == ch;
    300 #else
    301     return '/' == ch;
    302 #endif  // _WIN32
    303 }
    304 
    305 /* Skips space separators in a string.
    306  * str - string to advance past space separators.
    307  * Returns pointer to the first character in the string, that is
    308  * not a space separator. Note that this routine may return
    309  * pointer to EOL in case if all characters in the string were
    310  * space separators.
    311 */
    312 static const char*
    313 kcm_skip_spaces(const char* str) {
    314     while (!kcm_is_eol(*str) && kcm_is_token_separator(*str)) {
    315         str++;
    316     }
    317     return str;
    318 }
    319 
    320 /* Advances string to the first space separator character.
    321  * str - string to advance.
    322  * Returns pointer to the first space separator character in the string.
    323  * Note that this routine may return pointer to EOL in case if all
    324  * characters in the string were not space separators.
    325 */
    326 static const char*
    327 kcm_skip_non_spaces(const char* str) {
    328     while (!kcm_is_eol(*str) && !kcm_is_token_separator(*str)) {
    329         str++;
    330     }
    331     return str;
    332 }
    333 
    334 /* Gets first token from a string.
    335  * line - String to get token from. End of the string should be
    336  * determined using kcm_is_eol() routine.
    337  * token - String where to copy token. Token, copied to this
    338  * string will be zero-terminated. Note that buffer for the
    339  * token string must be large enough to fit token of any size.
    340  * max_token_len - character size of the buffer addressed by
    341  * the 'token' parameter.
    342  * Returns NULL if there were no tokens found in the string, or
    343  * a pointer to the line string, advanced past the found token.
    344 */
    345 static const char*
    346 kcm_get_token(const char* line, char* token, size_t max_token_len) {
    347     // Pass spaces and tabs.
    348     const char* token_starts = kcm_skip_spaces(line);
    349     // Advance to next space.
    350     const char* token_ends = kcm_skip_non_spaces(token_starts);
    351     // Calc token length
    352     size_t token_len = token_ends - token_starts;
    353     if ((0 == token_len) || (token_len >= max_token_len)) {
    354       return NULL;
    355     }
    356     memcpy(token, token_starts, token_len);
    357     token[token_len] = '\0';
    358     return token_ends;
    359 }
    360 
    361 /* Checks if token represents a comment.
    362  * Returns non-zero value if token represents a comment, or zero otherwise.
    363 */
    364 static int
    365 kcm_is_token_comment(const char* token) {
    366     return '#' == *token;
    367 }
    368 
    369 /* Converts a key name to a key code as defined by AndroidKeyCode enum.
    370  * key_name - Key name to convert.
    371  * key_code - Upon success contains key code value for the key_name.
    372  * Returns a zero value on success, or -1 if key code was not found
    373  * for the given key_name.
    374 */
    375 static int
    376 kcm_get_key_code(const char* key_name, unsigned short* key_code) {
    377     int n;
    378     // Iterate through the key code map, matching key names.
    379     for (n = 0; n < sizeof(keycode_map) / sizeof(keycode_map[0]); n++) {
    380         if (0 == strcmp(key_name, keycode_map[n].key_name)) {
    381             *key_code = keycode_map[n].key_code;
    382             return 0;
    383         }
    384     }
    385     return -1;
    386 }
    387 
    388 /* Gets unsigned short hexadecimal value for a token.
    389  * token - Token to get hexadecimal value for. Note that this
    390  * routine expects a "clean" (i.e. no "0x" prefix) hex number
    391  * represented by the token string.
    392  * val - Upon success contains hexadecimal value for the token.
    393  * Returns a zero value on success, or -1 on error.
    394 */
    395 static int
    396 kcm_get_ushort_hex_val(const char* token, unsigned short* val) {
    397     int hex_val = hex2int(token, strlen(token));
    398     // Make sure token format was ok and value doesn't exceed unsigned short.
    399     if (-1 == hex_val || 0 != (hex_val & ~0xFFFF)) {
    400       return -1;
    401     }
    402 
    403     *val = (unsigned short)hex_val;
    404 
    405     return 0;
    406 }
    407 
    408 /* Gets a character or hexadecimal value represented by a token.
    409  * token - Token to get value from.
    410  * val - Upon success will contain a character or hexadecimal
    411  * value represented by a token.
    412  * Returns a zero value on success, or -1 on error.
    413 */
    414 static int
    415 kcm_get_char_or_hex_val(const char* token, unsigned short* val) {
    416     // For chars token must begin with ' followed by character followed by '
    417     if ('\'' == *token) {
    418         if ('\0' == token[1] || '\'' != token[2] || '\0' != token[3]) {
    419             return 0;
    420         }
    421         *val = token[1];
    422         return 0;
    423     } else {
    424         // Make sure that hex token is prefixed with "0x"
    425         if (('0' != *token) || ('x' != token[1])) {
    426             return -1;
    427         }
    428         // Past 0x
    429         return kcm_get_ushort_hex_val(token + 2, val);
    430     }
    431 }
    432 
    433 /* Gets first token for the line and calculates its value.
    434  * line - Line to get token's value from.
    435  * val - Upon success will contain a character or hexadecimal
    436  * value represented by the first token in the line.
    437  * returns NULL on error, or a pointer to the line string,
    438  * advanced past the found token.
    439 */
    440 static const char*
    441 kcm_get_char_or_hex_token_value(const char* line, unsigned short* val) {
    442     char token[KCM_MAX_TOKEN_LEN];
    443     line = kcm_get_token(line, token, KCM_MAX_TOKEN_LEN);
    444     if (NULL != line) {
    445         // Token must be a char, or a hex number.
    446         if (kcm_get_char_or_hex_val(token, val)) {
    447             return NULL;
    448         }
    449     }
    450 
    451     return line;
    452 }
    453 
    454 /* Parses a line in .kcm file extracting key information.
    455  * line - Line in .kcm file to parse.
    456  * line_index - Index of the parsing line in .kcm file.
    457  * key_entry - Upon success contains key information extracted from
    458  * the line.
    459  * kcm_file_path - Path to the charmap file, where paresed line was taken from.
    460  * returns BAD_FORMAT if line format was not recognized, SKIP_LINE if line
    461  * format was ok, but it didn't contain key information, or KEY_ENTRY
    462  * if key information was successfuly extracted from the line.
    463 */
    464 static ParseStatus
    465 kcm_parse_line(const char* line,
    466                int line_index,
    467                AKeyEntry* key_entry,
    468                const char* kcm_file_path) {
    469       char token[KCM_MAX_TOKEN_LEN];
    470       unsigned short disp;
    471 
    472       // Get first token, and see if it's an empty, or a comment line.
    473       line = kcm_get_token(line, token, KCM_MAX_TOKEN_LEN);
    474       if ((NULL == line) || kcm_is_token_comment(token)) {
    475           // Empty line, or a comment.
    476           return SKIP_LINE;
    477       }
    478 
    479       // Here we expect either [type=XXXX], or a key string.
    480       if ('[' == token[0]) {
    481           return SKIP_LINE;
    482       }
    483 
    484       // It must be a key string.
    485       // First token is key code.
    486       if (kcm_get_key_code(token, &key_entry->code)) {
    487           derror("Invalid format of charmap file %s. Unknown key %s in line %d",
    488                  kcm_file_path, token, line_index);
    489           return BAD_FORMAT;
    490       }
    491 
    492       // 2-nd token is display character, which is ignored.
    493       line = kcm_get_char_or_hex_token_value(line, &disp);
    494       if (NULL == line) {
    495           derror("Invalid format of charmap file %s. Invalid display value in line %d",
    496                  kcm_file_path, line_index);
    497           return BAD_FORMAT;
    498       }
    499 
    500       // 3-rd token is number.
    501       line = kcm_get_char_or_hex_token_value(line, &key_entry->number);
    502       if (NULL == line) {
    503           derror("Invalid format of charmap file %s. Invalid number value in line %d",
    504                  kcm_file_path, line_index);
    505           return BAD_FORMAT;
    506       }
    507 
    508       // 4-th token is base.
    509       line = kcm_get_char_or_hex_token_value(line, &key_entry->base);
    510       if (NULL == line) {
    511           derror("Invalid format of charmap file %s. Invalid base value in line %d",
    512                  kcm_file_path, line_index);
    513           return BAD_FORMAT;
    514       }
    515 
    516       // 5-th token is caps.
    517       line = kcm_get_char_or_hex_token_value(line, &key_entry->caps);
    518       if (NULL == line) {
    519           derror("Invalid format of charmap file %s. Invalid caps value in line %d",
    520                  kcm_file_path, line_index);
    521           return BAD_FORMAT;
    522       }
    523 
    524       // 6-th token is fn.
    525       line = kcm_get_char_or_hex_token_value(line, &key_entry->fn);
    526       if (NULL == line) {
    527           derror("Invalid format of charmap file %s. Invalid fn value in line %d",
    528                  kcm_file_path, line_index);
    529           return BAD_FORMAT;
    530       }
    531 
    532       // 7-th token is caps_fn.
    533       line = kcm_get_char_or_hex_token_value(line, &key_entry->caps_fn);
    534       if (NULL == line) {
    535           derror("Invalid format of charmap file %s. Invalid caps_fn value in line %d",
    536                  kcm_file_path, line_index);
    537           return BAD_FORMAT;
    538       }
    539 
    540       // Make sure that line doesn't contain anything else,
    541       // except (may be) a comment token.
    542       line = kcm_get_token(line, token, KCM_MAX_TOKEN_LEN);
    543       if ((NULL == line) || kcm_is_token_comment(token)) {
    544           return KEY_ENTRY;
    545       } else {
    546           derror("Invalid format of charmap file %s in line %d",
    547                  kcm_file_path, line_index);
    548           return BAD_FORMAT;
    549       }
    550 }
    551 
    552 void
    553 kcm_extract_charmap_name(const char* kcm_file_path,
    554                          char* charmap_name,
    555                          int max_len) {
    556     const char* ext_separator;
    557     size_t to_copy;
    558 
    559     // Initialize charmap name with name of .kcm file.
    560     // First, get file name from the full path to .kcm file.
    561     const char* file_name = kcm_file_path + strlen(kcm_file_path);
    562     while (!kcm_is_path_separator(*file_name) &&
    563            (file_name != kcm_file_path)) {
    564         file_name--;
    565     }
    566     if (kcm_is_path_separator(*file_name)) {
    567         file_name++;
    568     }
    569 
    570     // Cut off file name extension.
    571     ext_separator = strrchr(file_name, '.');
    572     if (NULL == ext_separator) {
    573       // "filename" is legal name.
    574       ext_separator = file_name + strlen(file_name);
    575     } else if (ext_separator == file_name) {
    576       // ".filename" is legal name too. In this case we will use
    577       // "filename" as our custom charmap name.
    578       file_name++;
    579       ext_separator = file_name + strlen(file_name);
    580     }
    581 
    582     // Copy file name to charmap name.
    583     to_copy = ext_separator - file_name;
    584     if (to_copy > (max_len - 1)) {
    585         to_copy = max_len - 1;
    586     }
    587     memcpy(charmap_name, file_name, to_copy);
    588     charmap_name[to_copy] = '\0';
    589 }
    590 
    591 /* Extracts charmap name from .kcm file name,
    592  * and saves it into char_map as its name.
    593 */
    594 static void
    595 kcm_get_charmap_name(const char* kcm_file_path, AKeyCharmap* char_map) {
    596     kcm_extract_charmap_name(kcm_file_path, char_map->name,
    597                              sizeof(char_map->name));
    598 }
    599 
    600 /* Parses .kcm file producing key characters map.
    601  * See comments to this module for .kcm file format information.
    602  * This routine checks format only for character map lines. It will not check
    603  * format for empty lines, comments, and type section lines.
    604  * Note that line length in .kcm file should not exceed 1024 characters,
    605  * including newline character.
    606  *
    607  * Parameters:
    608  * kcm_file_path - Full path to the .kcm file to parse.
    609  * char_map - Upon success will contain initialized characters map.
    610  * Returns a zero value on success, or -1 on failure.
    611 */
    612 static int
    613 parse_kcm_file(const char* kcm_file_path, AKeyCharmap* char_map) {
    614     // A line read from .kcm file.
    615     char line[KCM_MAX_LINE_LEN];
    616     // Return code.
    617     int err = 0;
    618     // Number of the currently parsed line.
    619     int cur_line = 1;
    620     // Initial size of the charmap's array of keys.
    621     int map_size = 52;
    622     FILE* kcm_file;
    623 
    624     char_map->num_entries = 0;
    625     char_map->entries = 0;
    626 
    627     kcm_file = fopen(kcm_file_path, "r");
    628     if (NULL == kcm_file) {
    629         derror("Unable to open charmap file %s : %s",
    630                kcm_file_path, strerror(errno));
    631         return -1;
    632     }
    633 
    634     // Calculate charmap name.
    635     kcm_get_charmap_name(kcm_file_path, char_map);
    636 
    637     // Preallocate map.
    638     char_map->num_entries = 0;
    639     char_map->entries = qemu_malloc(sizeof(AKeyEntry) * map_size);
    640 
    641     // Line by line parse the file.
    642     for (; 0 != fgets(line, sizeof(line), kcm_file); cur_line++) {
    643         AKeyEntry key_entry;
    644         ParseStatus parse_res =
    645             kcm_parse_line(line, cur_line, &key_entry, kcm_file_path);
    646         if (BAD_FORMAT == parse_res) {
    647             err = -1;
    648             break;
    649         } else if (KEY_ENTRY == parse_res) {
    650             AKeyEntry* entries;
    651             // Key information has been extracted. Add it to the map.
    652             // Lets see if we need to reallocate map.
    653             if (map_size == char_map->num_entries) {
    654                 void* new_map;
    655                 map_size += 10;
    656                 new_map = qemu_malloc(sizeof(AKeyEntry) * map_size);
    657                 memcpy(new_map, char_map->entries,
    658                        char_map->num_entries * sizeof(AKeyEntry));
    659                 qemu_free((void*)char_map->entries);
    660                 char_map->entries = new_map;
    661             }
    662             entries = (AKeyEntry*)char_map->entries;
    663             entries[char_map->num_entries] = key_entry;
    664             char_map->num_entries++;
    665         }
    666     }
    667 
    668     if (!err) {
    669         // Make sure we exited the loop on EOF condition. Any other
    670         // condition is an error.
    671         if (0 == feof(kcm_file)) {
    672             err = -1;
    673         }
    674         if (err) {
    675           derror("Error reading charmap file %s : %s",
    676                   kcm_file_path, strerror(errno));
    677         }
    678     }
    679 
    680     fclose(kcm_file);
    681 
    682     if (err) {
    683         // Cleanup on failure.
    684         if (0 != char_map->entries) {
    685             qemu_free((void*)char_map->entries);
    686             char_map->entries = 0;
    687         }
    688         char_map->num_entries = 0;
    689     }
    690 
    691     return err;
    692 }
    693 
    694 int
    695 android_charmap_setup(const char* kcm_file_path) {
    696     if (NULL != kcm_file_path) {
    697         if (!parse_kcm_file(kcm_file_path, &android_custom_charmap)) {
    698             // Here we have two default charmaps and the custom one.
    699             android_charmap_count = 3;
    700             android_charmaps = qemu_malloc(sizeof(AKeyCharmap*) *
    701                                            android_charmap_count);
    702             android_charmaps[0] = &android_custom_charmap;
    703             android_charmaps[1] = &_qwerty_charmap;
    704             android_charmaps[2] = &_qwerty2_charmap;
    705         } else {
    706             derror("Unable to parse kcm file.");
    707             return -1;
    708         }
    709     } else {
    710         // Here we have only two default charmaps.
    711         android_charmap_count = 2;
    712         android_charmaps = qemu_malloc(sizeof(AKeyCharmap*) *
    713                            android_charmap_count);
    714         android_charmaps[0] = &_qwerty_charmap;
    715         android_charmaps[1] = &_qwerty2_charmap;
    716     }
    717 
    718     return 0;
    719 }
    720 
    721 void
    722 android_charmap_done(void) {
    723   if (NULL != android_charmaps) {
    724       int n;
    725       for (n = 0; n < android_charmap_count; n++) {
    726           // Entries for qwerty and qwerty2 character maps are
    727           // static entries defined in charmap.c
    728           if ((_qwerty_charmap.entries != android_charmaps[n]->entries) &&
    729               (_qwerty2_charmap.entries != android_charmaps[n]->entries)) {
    730               qemu_free((void*)android_charmaps[n]->entries);
    731           }
    732       }
    733       qemu_free(android_charmaps);
    734   }
    735 }
    736