summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRan Benita <ran234@gmail.com>2012-08-12 11:40:02 +0300
committerDaniel Stone <daniel@fooishbar.org>2013-04-01 18:20:57 +0100
commita392d2682bfbf5ce6c3ee153c6a08bb456da0660 (patch)
tree154727f033a8653a2cfa0a7fd861e15e742baa45 /src
parente4bceec8809f2563af6786678442fa70d4cd728c (diff)
Replace flex scanner with a hand-written one
The scanner is very similar in structure to the one in xkbcomp/rules.c. It avoids copying and has nicer error reporting. It uses gperf to generate a hashtable for the keywords, which gives a nice speed boost (compared to the naive strcasecmp method at least). But since there's hardly a reason to regenerate it every time and require people to install gperf, the output (keywords.c) is added here as well. Here are some stats from test/rulescomp: Before: compiled 1000 keymaps in 4.052939625s ==22063== total heap usage: 101,101 allocs, 101,101 frees, 11,840,834 bytes allocated After: compiled 1000 keymaps in 3.519665434s ==26505== total heap usage: 99,945 allocs, 99,945 frees, 7,033,608 bytes allocated Signed-off-by: Ran Benita <ran234@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/keymap.c32
-rw-r--r--src/keymap.h4
-rw-r--r--src/xkbcomp/.gitignore1
-rw-r--r--src/xkbcomp/keywords.c349
-rw-r--r--src/xkbcomp/keywords.gperf79
-rw-r--r--src/xkbcomp/parser-priv.h14
-rw-r--r--src/xkbcomp/parser.y2
-rw-r--r--src/xkbcomp/scanner.c205
-rw-r--r--src/xkbcomp/scanner.l323
-rw-r--r--src/xkbcomp/xkbcomp-priv.h9
-rw-r--r--src/xkbcomp/xkbcomp.c38
11 files changed, 650 insertions, 406 deletions
diff --git a/src/keymap.c b/src/keymap.c
index 3df183a..55000f4 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -190,35 +190,7 @@ xkb_keymap_new_from_string(struct xkb_context *ctx,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags)
{
- struct xkb_keymap *keymap;
- const struct xkb_keymap_format_ops *ops;
-
- ops = get_keymap_format_ops(format);
- if (!ops || !ops->keymap_new_from_string) {
- log_err_func(ctx, "unsupported keymap format: %d\n", format);
- return NULL;
- }
-
- if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
- log_err_func(ctx, "unrecognized flags: %#x\n", flags);
- return NULL;
- }
-
- if (!string) {
- log_err_func1(ctx, "no string specified\n");
- return NULL;
- }
-
- keymap = xkb_keymap_new(ctx, format, flags);
- if (!keymap)
- return NULL;
-
- if (!ops->keymap_new_from_string(keymap, string)) {
- xkb_keymap_unref(keymap);
- return NULL;
- }
-
- return keymap;
+ return xkb_keymap_new_from_buffer(ctx, string, SIZE_MAX, format, flags);
}
XKB_EXPORT struct xkb_keymap *
@@ -250,7 +222,7 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx,
if (!keymap)
return NULL;
- if (!ops->keymap_new_from_buffer(keymap, buffer, length)) {
+ if (!ops->keymap_new_from_string(keymap, buffer, length)) {
xkb_keymap_unref(keymap);
return NULL;
}
diff --git a/src/keymap.h b/src/keymap.h
index c6b884d..7d51184 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -439,9 +439,7 @@ struct xkb_keymap_format_ops {
bool (*keymap_new_from_names)(struct xkb_keymap *keymap,
const struct xkb_rule_names *names);
bool (*keymap_new_from_string)(struct xkb_keymap *keymap,
- const char *string);
- bool (*keymap_new_from_buffer)(struct xkb_keymap *keymap,
- const char *buffer, size_t length);
+ const char *string, size_t length);
bool (*keymap_new_from_file)(struct xkb_keymap *keymap, FILE *file);
char *(*keymap_get_as_string)(struct xkb_keymap *keymap);
};
diff --git a/src/xkbcomp/.gitignore b/src/xkbcomp/.gitignore
index 2081535..d7814e4 100644
--- a/src/xkbcomp/.gitignore
+++ b/src/xkbcomp/.gitignore
@@ -1,3 +1,2 @@
parser.c
parser.h
-scanner.c
diff --git a/src/xkbcomp/keywords.c b/src/xkbcomp/keywords.c
new file mode 100644
index 0000000..dba7086
--- /dev/null
+++ b/src/xkbcomp/keywords.c
@@ -0,0 +1,349 @@
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf */
+/* Computed positions: -k'1-2,5' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+
+#include "xkbcomp-priv.h"
+#include "parser-priv.h"
+
+static unsigned int
+keyword_gperf_hash(const char *str, unsigned int len);
+
+static const struct keyword_tok *
+keyword_gperf_lookup(const char *str, unsigned int len);
+struct keyword_tok { int name; enum yytokentype tok; };
+#include <string.h>
+/* maximum key range = 70, duplicates = 0 */
+
+#ifndef GPERF_DOWNCASE
+#define GPERF_DOWNCASE 1
+static unsigned char gperf_downcase[256] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255
+ };
+#endif
+
+#ifndef GPERF_CASE_STRCMP
+#define GPERF_CASE_STRCMP 1
+static int
+gperf_case_strcmp (register const char *s1, register const char *s2)
+{
+ for (;;)
+ {
+ unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
+ unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
+ if (c1 != 0 && c1 == c2)
+ continue;
+ return (int)c1 - (int)c2;
+ }
+}
+#endif
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+keyword_gperf_hash (register const char *str, register unsigned int len)
+{
+ static const unsigned char asso_values[] =
+ {
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 0, 73, 5, 36, 0,
+ 10, 1, 15, 15, 73, 0, 10, 20, 35, 20,
+ 50, 73, 10, 10, 5, 0, 15, 73, 0, 15,
+ 73, 73, 73, 73, 73, 73, 73, 0, 73, 5,
+ 36, 0, 10, 1, 15, 15, 73, 0, 10, 20,
+ 35, 20, 50, 73, 10, 10, 5, 0, 15, 73,
+ 0, 15, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ case 3:
+ case 2:
+ hval += asso_values[(unsigned char)str[1]];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct stringpool_t
+ {
+ char stringpool_str3[sizeof("key")];
+ char stringpool_str4[sizeof("keys")];
+ char stringpool_str7[sizeof("augment")];
+ char stringpool_str9[sizeof("text")];
+ char stringpool_str10[sizeof("xkb_keymap")];
+ char stringpool_str11[sizeof("keypad_keys")];
+ char stringpool_str12[sizeof("xkb_keycodes")];
+ char stringpool_str13[sizeof("xkb_geometry")];
+ char stringpool_str14[sizeof("xkb_types")];
+ char stringpool_str15[sizeof("xkb_compat")];
+ char stringpool_str17[sizeof("replace")];
+ char stringpool_str19[sizeof("xkb_compat_map")];
+ char stringpool_str20[sizeof("xkb_layout")];
+ char stringpool_str21[sizeof("xkb_symbols")];
+ char stringpool_str22[sizeof("xkb_compatibility")];
+ char stringpool_str23[sizeof("xkb_semantics")];
+ char stringpool_str24[sizeof("type")];
+ char stringpool_str25[sizeof("alias")];
+ char stringpool_str26[sizeof("xkb_compatibility_map")];
+ char stringpool_str27[sizeof("alphanumeric_keys")];
+ char stringpool_str28[sizeof("function_keys")];
+ char stringpool_str29[sizeof("alternate")];
+ char stringpool_str30[sizeof("shape")];
+ char stringpool_str31[sizeof("action")];
+ char stringpool_str32[sizeof("section")];
+ char stringpool_str33[sizeof("row")];
+ char stringpool_str34[sizeof("logo")];
+ char stringpool_str35[sizeof("alternate_group")];
+ char stringpool_str36[sizeof("hidden")];
+ char stringpool_str37[sizeof("virtual")];
+ char stringpool_str42[sizeof("outline")];
+ char stringpool_str43[sizeof("default")];
+ char stringpool_str46[sizeof("modmap")];
+ char stringpool_str47[sizeof("virtual_modifiers")];
+ char stringpool_str52[sizeof("overlay")];
+ char stringpool_str53[sizeof("override")];
+ char stringpool_str57[sizeof("include")];
+ char stringpool_str62[sizeof("modifier_map")];
+ char stringpool_str63[sizeof("modifier_keys")];
+ char stringpool_str64[sizeof("indicator")];
+ char stringpool_str66[sizeof("group")];
+ char stringpool_str67[sizeof("mod_map")];
+ char stringpool_str69[sizeof("interpret")];
+ char stringpool_str71[sizeof("solid")];
+ char stringpool_str72[sizeof("partial")];
+ };
+static const struct stringpool_t stringpool_contents =
+ {
+ "key",
+ "keys",
+ "augment",
+ "text",
+ "xkb_keymap",
+ "keypad_keys",
+ "xkb_keycodes",
+ "xkb_geometry",
+ "xkb_types",
+ "xkb_compat",
+ "replace",
+ "xkb_compat_map",
+ "xkb_layout",
+ "xkb_symbols",
+ "xkb_compatibility",
+ "xkb_semantics",
+ "type",
+ "alias",
+ "xkb_compatibility_map",
+ "alphanumeric_keys",
+ "function_keys",
+ "alternate",
+ "shape",
+ "action",
+ "section",
+ "row",
+ "logo",
+ "alternate_group",
+ "hidden",
+ "virtual",
+ "outline",
+ "default",
+ "modmap",
+ "virtual_modifiers",
+ "overlay",
+ "override",
+ "include",
+ "modifier_map",
+ "modifier_keys",
+ "indicator",
+ "group",
+ "mod_map",
+ "interpret",
+ "solid",
+ "partial"
+ };
+#define stringpool ((const char *) &stringpool_contents)
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct keyword_tok *
+keyword_gperf_lookup (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 45,
+ MIN_WORD_LENGTH = 3,
+ MAX_WORD_LENGTH = 21,
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 72
+ };
+
+ static const struct keyword_tok wordlist[] =
+ {
+ {-1}, {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3, KEY},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4, KEYS},
+ {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, AUGMENT},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, TEXT},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, XKB_KEYMAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, KEYPAD_KEYS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, XKB_KEYCODES},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, XKB_GEOMETRY},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, XKB_TYPES},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, XKB_COMPATMAP},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, REPLACE},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, XKB_COMPATMAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, XKB_LAYOUT},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, XKB_SYMBOLS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, XKB_COMPATMAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, XKB_SEMANTICS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, TYPE},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, ALIAS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, XKB_COMPATMAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, ALPHANUMERIC_KEYS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, FUNCTION_KEYS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, ALTERNATE},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, SHAPE},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, ACTION_TOK},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, SECTION},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, ROW},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, LOGO},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, ALTERNATE_GROUP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, HIDDEN},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, VIRTUAL},
+ {-1}, {-1}, {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, OUTLINE},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, DEFAULT},
+ {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, MODIFIER_MAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, VIRTUAL_MODS},
+ {-1}, {-1}, {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str52, OVERLAY},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str53, OVERRIDE},
+ {-1}, {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str57, INCLUDE},
+ {-1}, {-1}, {-1}, {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str62, MODIFIER_MAP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str63, MODIFIER_KEYS},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str64, INDICATOR},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str66, GROUP},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str67, MODIFIER_MAP},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str69, INTERPRET},
+ {-1},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str71, SOLID},
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str72, PARTIAL}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = keyword_gperf_hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int o = wordlist[key].name;
+ if (o >= 0)
+ {
+ register const char *s = o + stringpool;
+
+ if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s))
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
+
+
+int
+keyword_to_token(const char *string)
+{
+ const struct keyword_tok *kt;
+ kt = keyword_gperf_lookup(string, strlen(string));
+ if (!kt)
+ return -1;
+ return kt->tok;
+}
diff --git a/src/xkbcomp/keywords.gperf b/src/xkbcomp/keywords.gperf
new file mode 100644
index 0000000..cfbfe8f
--- /dev/null
+++ b/src/xkbcomp/keywords.gperf
@@ -0,0 +1,79 @@
+%{
+#include "xkbcomp-priv.h"
+#include "parser-priv.h"
+
+static unsigned int
+keyword_gperf_hash(const char *str, unsigned int len);
+
+static const struct keyword_tok *
+keyword_gperf_lookup(const char *str, unsigned int len);
+%}
+
+struct keyword_tok { int name; enum yytokentype tok; };
+%language=ANSI-C
+%define hash-function-name keyword_gperf_hash
+%define lookup-function-name keyword_gperf_lookup
+%readonly-tables
+%enum
+%includes
+%struct-type
+%pic
+%ignore-case
+
+%%
+action, ACTION_TOK
+alias, ALIAS
+alphanumeric_keys, ALPHANUMERIC_KEYS
+alternate_group, ALTERNATE_GROUP
+alternate, ALTERNATE
+augment, AUGMENT
+default, DEFAULT
+function_keys, FUNCTION_KEYS
+group, GROUP
+hidden, HIDDEN
+include, INCLUDE
+indicator, INDICATOR
+interpret, INTERPRET
+keypad_keys, KEYPAD_KEYS
+key, KEY
+keys, KEYS
+logo, LOGO
+modifier_keys, MODIFIER_KEYS
+modifier_map, MODIFIER_MAP
+mod_map, MODIFIER_MAP
+modmap, MODIFIER_MAP
+outline, OUTLINE
+overlay, OVERLAY
+override, OVERRIDE
+partial, PARTIAL
+replace, REPLACE
+row, ROW
+section, SECTION
+shape, SHAPE
+solid, SOLID
+text, TEXT
+type, TYPE
+virtual_modifiers, VIRTUAL_MODS
+virtual, VIRTUAL
+xkb_compatibility_map, XKB_COMPATMAP
+xkb_compatibility, XKB_COMPATMAP
+xkb_compat_map, XKB_COMPATMAP
+xkb_compat, XKB_COMPATMAP
+xkb_geometry, XKB_GEOMETRY
+xkb_keycodes, XKB_KEYCODES
+xkb_keymap, XKB_KEYMAP
+xkb_layout, XKB_LAYOUT
+xkb_semantics, XKB_SEMANTICS
+xkb_symbols, XKB_SYMBOLS
+xkb_types, XKB_TYPES
+%%
+
+int
+keyword_to_token(const char *string)
+{
+ const struct keyword_tok *kt;
+ kt = keyword_gperf_lookup(string, strlen(string));
+ if (!kt)
+ return -1;
+ return kt->tok;
+}
diff --git a/src/xkbcomp/parser-priv.h b/src/xkbcomp/parser-priv.h
index 2e02db6..465b19d 100644
--- a/src/xkbcomp/parser-priv.h
+++ b/src/xkbcomp/parser-priv.h
@@ -27,21 +27,21 @@
#ifndef XKBCOMP_PARSER_PRIV_H
#define XKBCOMP_PARSER_PRIV_H
-struct scanner_extra;
+struct scanner;
struct parser_param;
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-#pragma GCC diagnostic push
#include "parser.h"
-#pragma GCC diagnostic pop
-void
-scanner_error(YYLTYPE *loc, void *scanner, const char *msg);
+int
+scanner_error(YYLTYPE *yylloc, struct scanner *scanner, const char *msg);
int
-_xkbcommon_lex(YYSTYPE *val, YYLTYPE *loc, void *scanner);
+_xkbcommon_lex(YYSTYPE *yylval, YYLTYPE *yylloc, struct scanner *scanner);
XkbFile *
parse(struct xkb_context *ctx, void *scanner, const char *map);
+int
+keyword_to_token(const char *string);
+
#endif
diff --git a/src/xkbcomp/parser.y b/src/xkbcomp/parser.y
index 90ac75e..aaf87db 100644
--- a/src/xkbcomp/parser.y
+++ b/src/xkbcomp/parser.y
@@ -48,7 +48,7 @@ _xkbcommon_error(struct YYLTYPE *loc, struct parser_param *param, const char *ms
%name-prefix "_xkbcommon_"
%define api.pure
%locations
-%lex-param { void *scanner }
+%lex-param { struct scanner *scanner }
%parse-param { struct parser_param *param }
%token
diff --git a/src/xkbcomp/scanner.c b/src/xkbcomp/scanner.c
new file mode 100644
index 0000000..4be2c40
--- /dev/null
+++ b/src/xkbcomp/scanner.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2012 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "xkbcomp-priv.h"
+#include "parser-priv.h"
+#include "scanner-utils.h"
+
+int
+scanner_error(YYLTYPE *yylloc, struct scanner *s, const char *msg)
+{
+ log_err(s->ctx, "%s:%d:%d: %s\n",
+ s->file_name, yylloc->first_line, yylloc->first_column, msg);
+ return ERROR_TOK;
+}
+
+static bool
+number(struct scanner *s, int64_t *out, enum yytokentype *out_tok)
+{
+ bool is_float = false, is_hex = false;
+ const char *start = s->s + s->pos;
+ char *end;
+
+ if (lit(s, "0x")) {
+ while (isxdigit(peek(s))) next(s);
+ is_hex = true;
+ }
+ else {
+ while (isdigit(peek(s))) next(s);
+ is_float = chr(s, '.');
+ while (isdigit(peek(s))) next(s);
+ }
+ if (s->s + s->pos == start)
+ return false;
+
+ errno = 0;
+ if (is_hex)
+ *out = strtoul(start, &end, 16);
+ else if (is_float)
+ *out = strtod(start, &end);
+ else
+ *out = strtoul(start, &end, 10);
+ if (errno != 0 || s->s + s->pos != end)
+ *out_tok = ERROR_TOK;
+ else
+ *out_tok = (is_float ? FLOAT : INTEGER);
+ return true;
+}
+
+int
+_xkbcommon_lex(YYSTYPE *yylval, YYLTYPE *yylloc, struct scanner *s)
+{
+ enum yytokentype tok;
+
+skip_more_whitespace_and_comments:
+ /* Skip spaces. */
+ while (isspace(peek(s))) next(s);
+
+ /* Skip comments. */
+ if (lit(s, "//") || chr(s, '#')) {
+ while (!eof(s) && !eol(s)) next(s);
+ goto skip_more_whitespace_and_comments;
+ }
+
+ /* See if we're done. */
+ if (eof(s)) return END_OF_FILE;
+
+ /* New token. */
+ yylloc->first_line = yylloc->last_line = s->line;
+ yylloc->first_column = yylloc->last_column = s->column;
+ s->buf_pos = 0;
+
+ /* String literal. */
+ if (chr(s, '\"')) {
+ while (!eof(s) && !eol(s) && peek(s) != '\"') {
+ if (chr(s, '\\')) {
+ uint8_t o;
+ if (chr(s, '\\')) buf_append(s, '\\');
+ else if (chr(s, 'n')) buf_append(s, '\n');
+ else if (chr(s, 't')) buf_append(s, '\t');
+ else if (chr(s, 'r')) buf_append(s, '\r');
+ else if (chr(s, 'b')) buf_append(s, '\b');
+ else if (chr(s, 'f')) buf_append(s, '\f');
+ else if (chr(s, 'v')) buf_append(s, '\v');
+ else if (chr(s, 'e')) buf_append(s, '\033');
+ else if (oct(s, &o)) buf_append(s, (char) o);
+ else return scanner_error(yylloc, s,
+ "illegal escape sequence in string literal");
+ } else {
+ buf_append(s, next(s));
+ }
+ }
+ if (!buf_append(s, '\0') || !chr(s, '\"'))
+ return scanner_error(yylloc, s, "unterminated string literal");
+ yylval->str = strdup(s->buf);
+ if (!yylval->str)
+ return scanner_error(yylloc, s, "scanner out of memory");
+ return STRING;
+ }
+
+ /* Key name literal. */
+ if (chr(s, '<')) {
+ while (isgraph(peek(s)) && peek(s) != '>')
+ buf_append(s, next(s));
+ if (s->buf_pos == 0)
+ return scanner_error(yylloc, s, "empty key name literal");
+ if (!buf_append(s, '\0') || !chr(s, '>'))
+ return scanner_error(yylloc, s, "unterminated key name literal");
+ yylval->sval = xkb_atom_intern(s->ctx, s->buf);
+ return KEYNAME;
+ }
+
+ /* Operators and punctuation. */
+ if (chr(s, ';')) return SEMI;
+ if (chr(s, '{')) return OBRACE;
+ if (chr(s, '}')) return CBRACE;
+ if (chr(s, '=')) return EQUALS;
+ if (chr(s, '[')) return OBRACKET;
+ if (chr(s, ']')) return CBRACKET;
+ if (chr(s, '(')) return OPAREN;
+ if (chr(s, ')')) return CPAREN;
+ if (chr(s, '.')) return DOT;
+ if (chr(s, ',')) return COMMA;
+ if (chr(s, '+')) return PLUS;
+ if (chr(s, '-')) return MINUS;
+ if (chr(s, '*')) return TIMES;
+ if (chr(s, '!')) return EXCLAM;
+ if (chr(s, '~')) return INVERT;
+
+ /* Identifier. */
+ if (isalpha(peek(s)) || peek(s) == '_') {
+ s->buf_pos = 0;
+ while (isalnum(peek(s)) || peek(s) == '_')
+ buf_append(s, next(s));
+ if (!buf_append(s, '\0'))
+ return scanner_error(yylloc, s, "identifier too long");
+
+ /* Keyword. */
+ tok = keyword_to_token(s->buf);
+ if (tok != -1) return tok;
+
+ yylval->str = strdup(s->buf);
+ if (!yylval->str)
+ return scanner_error(yylloc, s, "scanner out of memory");
+ return IDENT;
+ }
+
+ /* Number literal (hexadecimal / decimal / float). */
+ if (number(s, &yylval->num, &tok)) {
+ if (tok == ERROR_TOK)
+ return scanner_error(yylloc, s, "malformed number literal");
+ return tok;
+ }
+
+ return scanner_error(yylloc, s, "unrecognized token");
+}
+
+XkbFile *
+XkbParseString(struct xkb_context *ctx, const char *string, size_t len,
+ const char *file_name, const char *map)
+{
+ struct scanner scanner;
+ scanner_init(&scanner, ctx, string, len, file_name);
+ return parse(ctx, &scanner, map);
+}
+
+XkbFile *
+XkbParseFile(struct xkb_context *ctx, FILE *file,
+ const char *file_name, const char *map)
+{
+ bool ok;
+ XkbFile *xkb_file;
+ const char *string;
+ size_t size;
+
+ ok = map_file(file, &string, &size);
+ if (!ok) {
+ log_err(ctx, "Couldn't read XKB file %s: %s\n",
+ file_name, strerror(errno));
+ return NULL;
+ }
+
+ xkb_file = XkbParseString(ctx, string, size, file_name, map);
+ unmap_file(string, size);
+ return xkb_file;
+}
diff --git a/src/xkbcomp/scanner.l b/src/xkbcomp/scanner.l
deleted file mode 100644
index f30462d..0000000
--- a/src/xkbcomp/scanner.l
+++ /dev/null
@@ -1,323 +0,0 @@
-/************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
-
- Permission to use, copy, modify, and distribute this
- software and its documentation for any purpose and without
- fee is hereby granted, provided that the above copyright
- notice appear in all copies and that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ********************************************************/
-
-%{
-#include "xkbcomp-priv.h"
-#include "parser-priv.h"
-
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-#pragma GCC diagnostic push
-
-struct scanner_extra {
- struct xkb_context *ctx;
- const char *file_name;
- char scanBuf[1024];
- char *s;
-};
-
-static void
-scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra,
- const char *msg);
-
-#define YY_USER_ACTION { \
- yylloc->first_line = yylineno; \
- yylloc->last_line = yylineno; \
-}
-
-#define APPEND_S(ch) do { \
- if (yyextra->s - yyextra->scanBuf >= sizeof(yyextra->scanBuf) - 1) \
- return ERROR_TOK; \
- *yyextra->s++ = ch; \
-} while (0)
-%}
-
-%option prefix="_xkbcommon_"
-%option reentrant
-%option extra-type="struct scanner_extra *"
-%option bison-bridge bison-locations
-%option yylineno
-%option nounistd noyywrap noinput nounput
-%option never-interactive
-%option case-insensitive
-
-%x S_STR
-
-%%
-
-"//"[^\n]*
-"#"[^\n]*
-
-\" yyextra->s = yyextra->scanBuf; BEGIN(S_STR);
-
-<S_STR>\" {
- BEGIN(INITIAL);
- *yyextra->s = '\0';
- yylval->str = strdup(yyextra->scanBuf);
- return STRING;
- }
-
-<S_STR>\\[0-7]{1,3} {
- /* octal escape sequence */
- unsigned int result;
-
- (void) sscanf( yytext + 1, "%o", &result );
-
- if (result > 0xff) {
- scanner_error_extra(yylloc, yyextra,
- "Illegal octal escape");
- return ERROR_TOK;
- }
-
- APPEND_S(result);
- }
-
-<S_STR>\\[0-9]+ {
- scanner_error_extra(yylloc, yyextra,
- "Illegal octal escape");
- return ERROR_TOK;
- }
-
-<S_STR>\\n APPEND_S('\n');
-<S_STR>\\t APPEND_S('\t');
-<S_STR>\\r APPEND_S('\r');
-<S_STR>\\b APPEND_S('\b');
-<S_STR>\\f APPEND_S('\f');
-<S_STR>\\v APPEND_S('\v');
-<S_STR>\\e APPEND_S('\033');
-
-<S_STR>. APPEND_S(yytext[0]);
-
-\<[a-zA-Z0-9_+-]+\> {
- /* We don't want the brackets. */
- yytext[yyleng - 1] = '\0';
- yytext++;
- yylval->sval = xkb_atom_intern(yyextra->ctx, yytext);
- return KEYNAME;
- }
-
-xkb_keymap return XKB_KEYMAP;
-xkb_keycodes return XKB_KEYCODES;
-xkb_types return XKB_TYPES;
-xkb_symbols return XKB_SYMBOLS;
-xkb_compat return XKB_COMPATMAP;
-xkb_compat_map return XKB_COMPATMAP;
-xkb_compatibility return XKB_COMPATMAP;
-xkb_compatibility_map return XKB_COMPATMAP;
-xkb_geometry return XKB_GEOMETRY;
-xkb_semantics return XKB_SEMANTICS;
-xkb_layout return XKB_LAYOUT;
-include return INCLUDE;
-override return OVERRIDE;
-augment return AUGMENT;
-replace return REPLACE;
-alternate return ALTERNATE;
-partial return PARTIAL;
-default return DEFAULT;
-hidden return HIDDEN;
-virtual_modifiers return VIRTUAL_MODS;
-type return TYPE;
-interpret return INTERPRET;
-action return ACTION_TOK;
-key return KEY;
-alias return ALIAS;
-group return GROUP;
-modmap return MODIFIER_MAP;
-mod_map return MODIFIER_MAP;
-modifier_map return MODIFIER_MAP;
-indicator return INDICATOR;
-shape return SHAPE;
-row return ROW;
-keys return KEYS;
-section return SECTION;
-overlay return OVERLAY;
-text return TEXT;
-outline return OUTLINE;
-solid return SOLID;
-logo return LOGO;
-virtual return VIRTUAL;
-alphanumeric_keys return ALPHANUMERIC_KEYS;
-modifier_keys return MODIFIER_KEYS;
-keypad_keys return KEYPAD_KEYS;
-function_keys return FUNCTION_KEYS;
-alternate_group return ALTERNATE_GROUP;
-
-[a-zA-Z_][a-zA-Z_0-9]* yylval->str = strdup(yytext); return IDENT;
-
-0x[a-fA-F0-9]+ |
-[0-9]+ {
- char *end;
- yylval->num = strtoul(yytext, &end, 0);
-
- return INTEGER;
- }
-[0-9]+\.[0-9]+ {
- char *end;
- yylval->num = strtod(yytext, &end);
-
- return FLOAT;
- }
-
-"=" return EQUALS;
-"+" return PLUS;
-"-" return MINUS;
-"/" return DIVIDE;
-"*" return TIMES;
-"{" return OBRACE;
-"}" return CBRACE;
-"(" return OPAREN;
-")" return CPAREN;
-"[" return OBRACKET;
-"]" return CBRACKET;
-"." return DOT;
-"," return COMMA;
-";" return SEMI;
-"!" return EXCLAM;
-"~" return INVERT;
-
-[ \t\r\n\v]+
-
-<<EOF>> return END_OF_FILE;
-
-. return ERROR_TOK;
-
-%%
-
-#pragma GCC diagnostic pop
-
-static void
-scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra,
- const char *msg)
-{
- log_err(extra->ctx, "%s: line %d of %s\n", msg,
- loc->first_line,
- extra->file_name ? extra->file_name : "(unknown)");
-}
-
-void
-scanner_error(struct YYLTYPE *loc, void *scanner, const char *msg)
-{
- struct scanner_extra *extra = yyget_extra(scanner);
- scanner_error_extra(loc, extra, msg);
-}
-
-static bool
-init_scanner(yyscan_t *scanner, struct scanner_extra *extra,
- struct xkb_context *ctx, const char *file_name)
-{
- memset(extra, 0, sizeof(*extra));
-
- if (yylex_init_extra(extra, scanner) != 0)
- return false;
-
- extra->ctx = ctx;
- extra->file_name = file_name;
-
- return true;
-}
-
-static void
-clear_scanner(yyscan_t scanner)
-{
- yylex_destroy(scanner);
-}
-
-XkbFile *
-XkbParseString(struct xkb_context *ctx, const char *string,
- const char *file_name)
-{
- yyscan_t scanner;
- struct scanner_extra extra;
- YY_BUFFER_STATE state;
- XkbFile *xkb_file;
-
- if (!init_scanner(&scanner, &extra, ctx, file_name))
- return NULL;
-
- state = yy_scan_string(string, scanner);
-
- xkb_file = parse(ctx, scanner, NULL);
-
- yy_delete_buffer(state, scanner);
- clear_scanner(scanner);
-
- return xkb_file;
-}
-
-/*
- * yy_scan_buffer() requires the last two bytes of \buf to be 0. These two bytes
- * are not scanned. Other zero bytes in the buffer are scanned normally, though.
- * Due to these terminating zeroes, \length must be greater than 2.
- * Furthermore, the buffer must be writable and you cannot make any assumptions
- * about it after the scanner finished.
- * All this must be guaranteed by the caller of this function!
- */
-XkbFile *
-XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length,
- const char *file_name)
-{
- yyscan_t scanner;
- struct scanner_extra extra;
- YY_BUFFER_STATE state;
- XkbFile *xkb_file;
-
- if (!init_scanner(&scanner, &extra, ctx, file_name))
- return NULL;
-
- xkb_file = NULL;
- state = yy_scan_buffer(buf, length, scanner);
- if (state) {
- xkb_file = parse(ctx, scanner, NULL);
- yy_delete_buffer(state, scanner);
- }
-
- clear_scanner(scanner);
-
- return xkb_file;
-}
-
-XkbFile *
-XkbParseFile(struct xkb_context *ctx, FILE *file,
- const char *file_name, const char *map)
-{
- yyscan_t scanner;
- struct scanner_extra extra;
- YY_BUFFER_STATE state;
- XkbFile *xkb_file;
-
- if (!init_scanner(&scanner, &extra, ctx, file_name))
- return NULL;
-
- state = yy_create_buffer(file, YY_BUF_SIZE, scanner);
- yy_switch_to_buffer(state, scanner);
-
- xkb_file = parse(ctx, scanner, map);
-
- yy_delete_buffer(state, scanner);
- clear_scanner(scanner);
-
- return xkb_file;
-}
diff --git a/src/xkbcomp/xkbcomp-priv.h b/src/xkbcomp/xkbcomp-priv.h
index 4d421b5..97cc2a8 100644
--- a/src/xkbcomp/xkbcomp-priv.h
+++ b/src/xkbcomp/xkbcomp-priv.h
@@ -45,12 +45,9 @@ XkbParseFile(struct xkb_context *ctx, FILE *file,
const char *file_name, const char *map);
XkbFile *
-XkbParseString(struct xkb_context *ctx, const char *string,
- const char *file_name);
-
-XkbFile *
-XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length,
- const char *file_name);
+XkbParseString(struct xkb_context *ctx,
+ const char *string, size_t len,
+ const char *file_name, const char *map);
void
FreeXkbFile(XkbFile *file);
diff --git a/src/xkbcomp/xkbcomp.c b/src/xkbcomp/xkbcomp.c
index b9a1b5f..007e3f7 100644
--- a/src/xkbcomp/xkbcomp.c
+++ b/src/xkbcomp/xkbcomp.c
@@ -97,12 +97,13 @@ text_v1_keymap_new_from_names(struct xkb_keymap *keymap,
}
static bool
-text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string)
+text_v1_keymap_new_from_string(struct xkb_keymap *keymap,
+ const char *string, size_t len)
{
bool ok;
XkbFile *xkb_file;
- xkb_file = XkbParseString(keymap->ctx, string, "(input string)");
+ xkb_file = XkbParseString(keymap->ctx, string, len, "(input string)", NULL);
if (!xkb_file) {
log_err(keymap->ctx, "Failed to parse input xkb string\n");
return NULL;
@@ -114,38 +115,6 @@ text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string)
}
static bool
-text_v1_keymap_new_from_buffer(struct xkb_keymap *keymap,
- const char *buffer, size_t length)
-{
- bool ok;
- XkbFile *xkb_file;
- char *buf;
-
- buf = malloc(length + 2);
- if (!buf) {
- log_err(keymap->ctx, "Cannot allocate memory for keymap\n");
- return NULL;
- }
-
- /* yy_scan_buffer requires two terminating zero bytes */
- memcpy(buf, buffer, length);
- buf[length] = 0;
- buf[length + 1] = 0;
-
- xkb_file = XkbParseBuffer(keymap->ctx, buf, length + 2, "input");
- if (!xkb_file) {
- log_err(keymap->ctx, "Failed to parse input xkb file\n");
- free(buf);
- return NULL;
- }
-
- ok = compile_keymap_file(keymap, xkb_file);
- FreeXkbFile(xkb_file);
- free(buf);
- return ok;
-}
-
-static bool
text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file)
{
bool ok;
@@ -165,7 +134,6 @@ text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file)
const struct xkb_keymap_format_ops text_v1_keymap_format_ops = {
.keymap_new_from_names = text_v1_keymap_new_from_names,
.keymap_new_from_string = text_v1_keymap_new_from_string,
- .keymap_new_from_buffer = text_v1_keymap_new_from_buffer,
.keymap_new_from_file = text_v1_keymap_new_from_file,
.keymap_get_as_string = text_v1_keymap_get_as_string,
};