Replace flex scanner with a hand-written one
authorRan Benita <ran234@gmail.com>
Sun, 12 Aug 2012 08:40:02 +0000 (11:40 +0300)
committerDaniel Stone <daniel@fooishbar.org>
Mon, 1 Apr 2013 17:20:57 +0000 (18:20 +0100)
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>
13 files changed:
Makefile.am
configure.ac
src/keymap.c
src/keymap.h
src/xkbcomp/.gitignore
src/xkbcomp/keywords.c [new file with mode: 0644]
src/xkbcomp/keywords.gperf [new file with mode: 0644]
src/xkbcomp/parser-priv.h
src/xkbcomp/parser.y
src/xkbcomp/scanner.c [new file with mode: 0644]
src/xkbcomp/scanner.l [deleted file]
src/xkbcomp/xkbcomp-priv.h
src/xkbcomp/xkbcomp.c

index 0d43f39..98cabc1 100644 (file)
@@ -38,11 +38,12 @@ libxkbcommon_la_SOURCES = \
        src/xkbcomp/keycodes.c \
        src/xkbcomp/keymap.c \
        src/xkbcomp/keymap-dump.c \
+       src/xkbcomp/keywords.c \
        src/xkbcomp/parser.y \
        src/xkbcomp/parser-priv.h \
        src/xkbcomp/rules.c \
        src/xkbcomp/rules.h \
-       src/xkbcomp/scanner.l \
+       src/xkbcomp/scanner.c \
        src/xkbcomp/scanner-utils.h \
        src/xkbcomp/symbols.c \
        src/xkbcomp/types.c \
@@ -70,13 +71,11 @@ libxkbcommon_la_SOURCES = \
 
 BUILT_SOURCES = \
        src/xkbcomp/parser.c \
-       src/xkbcomp/parser.h \
-       src/xkbcomp/scanner.c
+       src/xkbcomp/parser.h
 CLEANFILES = $(BUILT_SOURCES)
 
 src/xkbcomp/parser.c: $(top_builddir)/src/$(am__dirstamp) $(top_builddir)/src/xkbcomp/$(am__dirstamp)
 src/xkbcomp/parser.h: $(top_builddir)/src/$(am__dirstamp) $(top_builddir)/src/xkbcomp/$(am__dirstamp)
-src/xkbcomp/scanner.c: $(top_builddir)/src/$(am__dirstamp) $(top_builddir)/src/xkbcomp/$(am__dirstamp)
 
 # Documentation
 
@@ -171,7 +170,6 @@ EXTRA_DIST = \
 # removes #define _OSF_Keysyms and such.  The XK_Ydiaeresis case is to
 # handle a duplicate definition in HPkeysyms.h which kicks in if it's
 # not already defined.
-
 X11_INCLUDEDIR = /usr/include/X11
 KEYSYMDEFS = \
         $(X11_INCLUDEDIR)/keysymdef.h \
@@ -191,6 +189,11 @@ update-keysyms:
        echo -en '/* This file is autogenerated from Makefile.am; please do not commit directly. */\n\n' > $(top_srcdir)/src/ks_tables.h
        LC_CTYPE=C python $(top_srcdir)/makekeys.py $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h >> $(top_srcdir)/src/ks_tables.h
 
+# Run this if you add/remove a new keyword to the xkbcomp scanner,
+# or just want to regenerate the gperf file.
+update-keywords:
+       $(AM_V_GEN)gperf < $(top_srcdir)/src/xkbcomp/keywords.gperf > $(top_srcdir)/src/xkbcomp/keywords.c
+
 # Android stuff
 
 Android_build.mk: Makefile $(BUILT_SOURCES)
index ec829cd..2806a2c 100644 (file)
@@ -54,7 +54,7 @@ AC_C_INLINE
 # Check for programs
 AC_PROG_MKDIR_P
 PKG_PROG_PKG_CONFIG
-AC_PROG_LEX
+
 AC_PROG_YACC
 AC_PATH_PROG([YACC_INST], $YACC)
 if test ! -f "src/xkbcomp/parser.c"; then
index 3df183a..55000f4 100644 (file)
@@ -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;
     }
index c6b884d..7d51184 100644 (file)
@@ -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);
 };
index 2081535..d7814e4 100644 (file)
@@ -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 (file)
index 0000000..dba7086
--- /dev/null
@@ -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 (file)
index 0000000..cfbfe8f
--- /dev/null
@@ -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;
+}
index 2e02db6..465b19d 100644 (file)
 #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
index 90ac75e..aaf87db 100644 (file)
@@ -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 (file)
index 0000000..4be2c40
--- /dev/null
@@ -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 (file)
index f30462d..0000000
+++ /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;
-}
index 4d421b5..97cc2a8 100644 (file)
@@ -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);
index b9a1b5f..007e3f7 100644 (file)
@@ -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,
 };