utils: add {un,}map_file to read an entire file
[platform/upstream/libxkbcommon.git] / src / xkbcomp / scanner.l
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25  ********************************************************/
26
27 %{
28 #include "xkbcomp-priv.h"
29 #include "parser-priv.h"
30
31 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
32 #pragma GCC diagnostic ignored "-Wredundant-decls"
33 #pragma GCC diagnostic push
34
35 struct scanner_extra {
36     struct xkb_context *ctx;
37     const char *file_name;
38     char scanBuf[1024];
39     char *s;
40 };
41
42 static void
43 scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra,
44                     const char *msg);
45
46 #define YY_USER_ACTION {                \
47         yylloc->first_line = yylineno;  \
48         yylloc->last_line = yylineno;   \
49 }
50
51 #define APPEND_S(ch) do {                                               \
52     if (yyextra->s - yyextra->scanBuf >= sizeof(yyextra->scanBuf) - 1)  \
53         return ERROR_TOK;                                               \
54     *yyextra->s++ = ch;                                                 \
55 } while (0)
56 %}
57
58 %option prefix="_xkbcommon_"
59 %option reentrant
60 %option extra-type="struct scanner_extra *"
61 %option bison-bridge bison-locations
62 %option yylineno
63 %option nounistd noyywrap noinput nounput
64 %option never-interactive
65 %option case-insensitive
66
67 %x S_STR
68
69 %%
70
71 "//"[^\n]*
72 "#"[^\n]*
73
74 \"                      yyextra->s = yyextra->scanBuf; BEGIN(S_STR);
75
76 <S_STR>\" {
77                         BEGIN(INITIAL);
78                         *yyextra->s = '\0';
79                         yylval->str = strdup(yyextra->scanBuf);
80                         return STRING;
81                     }
82
83 <S_STR>\\[0-7]{1,3} {
84                         /* octal escape sequence */
85                         unsigned int result;
86
87                         (void) sscanf( yytext + 1, "%o", &result );
88
89                         if (result > 0xff) {
90                             scanner_error_extra(yylloc, yyextra,
91                                                 "Illegal octal escape");
92                             return ERROR_TOK;
93                         }
94
95                         APPEND_S(result);
96                     }
97
98 <S_STR>\\[0-9]+ {
99                         scanner_error_extra(yylloc, yyextra,
100                                             "Illegal octal escape");
101                         return ERROR_TOK;
102                     }
103
104 <S_STR>\\n              APPEND_S('\n');
105 <S_STR>\\t              APPEND_S('\t');
106 <S_STR>\\r              APPEND_S('\r');
107 <S_STR>\\b              APPEND_S('\b');
108 <S_STR>\\f              APPEND_S('\f');
109 <S_STR>\\v              APPEND_S('\v');
110 <S_STR>\\e              APPEND_S('\033');
111
112 <S_STR>.                APPEND_S(yytext[0]);
113
114 \<[a-zA-Z0-9_+-]+\> {
115                         /* We don't want the brackets. */
116                         yytext[yyleng - 1] = '\0';
117                         yytext++;
118                         yylval->sval = xkb_atom_intern(yyextra->ctx, yytext);
119                         return KEYNAME;
120                     }
121
122 xkb_keymap              return XKB_KEYMAP;
123 xkb_keycodes            return XKB_KEYCODES;
124 xkb_types               return XKB_TYPES;
125 xkb_symbols             return XKB_SYMBOLS;
126 xkb_compat              return XKB_COMPATMAP;
127 xkb_compat_map          return XKB_COMPATMAP;
128 xkb_compatibility       return XKB_COMPATMAP;
129 xkb_compatibility_map   return XKB_COMPATMAP;
130 xkb_geometry            return XKB_GEOMETRY;
131 xkb_semantics           return XKB_SEMANTICS;
132 xkb_layout              return XKB_LAYOUT;
133 include                 return INCLUDE;
134 override                return OVERRIDE;
135 augment                 return AUGMENT;
136 replace                 return REPLACE;
137 alternate               return ALTERNATE;
138 partial                 return PARTIAL;
139 default                 return DEFAULT;
140 hidden                  return HIDDEN;
141 virtual_modifiers       return VIRTUAL_MODS;
142 type                    return TYPE;
143 interpret               return INTERPRET;
144 action                  return ACTION_TOK;
145 key                     return KEY;
146 alias                   return ALIAS;
147 group                   return GROUP;
148 modmap                  return MODIFIER_MAP;
149 mod_map                 return MODIFIER_MAP;
150 modifier_map            return MODIFIER_MAP;
151 indicator               return INDICATOR;
152 shape                   return SHAPE;
153 row                     return ROW;
154 keys                    return KEYS;
155 section                 return SECTION;
156 overlay                 return OVERLAY;
157 text                    return TEXT;
158 outline                 return OUTLINE;
159 solid                   return SOLID;
160 logo                    return LOGO;
161 virtual                 return VIRTUAL;
162 alphanumeric_keys       return ALPHANUMERIC_KEYS;
163 modifier_keys           return MODIFIER_KEYS;
164 keypad_keys             return KEYPAD_KEYS;
165 function_keys           return FUNCTION_KEYS;
166 alternate_group         return ALTERNATE_GROUP;
167
168 [a-zA-Z_][a-zA-Z_0-9]*  yylval->str = strdup(yytext); return IDENT;
169
170 0x[a-fA-F0-9]+          |
171 [0-9]+                  {
172                             char *end;
173                             yylval->num = strtoul(yytext, &end, 0);
174
175                             return INTEGER;
176                         }
177 [0-9]+\.[0-9]+ {
178                             char *end;
179                             yylval->num = strtod(yytext, &end);
180
181                             return FLOAT;
182                         }
183
184 "="                     return EQUALS;
185 "+"                     return PLUS;
186 "-"                     return MINUS;
187 "/"                     return DIVIDE;
188 "*"                     return TIMES;
189 "{"                     return OBRACE;
190 "}"                     return CBRACE;
191 "("                     return OPAREN;
192 ")"                     return CPAREN;
193 "["                     return OBRACKET;
194 "]"                     return CBRACKET;
195 "."                     return DOT;
196 ","                     return COMMA;
197 ";"                     return SEMI;
198 "!"                     return EXCLAM;
199 "~"                     return INVERT;
200
201 [ \t\r\n\v]+
202
203 <<EOF>>                 return END_OF_FILE;
204
205 .                       return ERROR_TOK;
206
207 %%
208
209 #pragma GCC diagnostic pop
210
211 static void
212 scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra,
213                     const char *msg)
214 {
215     log_err(extra->ctx, "%s: line %d of %s\n", msg,
216             loc->first_line,
217             extra->file_name ? extra->file_name : "(unknown)");
218 }
219
220 void
221 scanner_error(struct YYLTYPE *loc, void *scanner, const char *msg)
222 {
223     struct scanner_extra *extra = yyget_extra(scanner);
224     scanner_error_extra(loc, extra, msg);
225 }
226
227 static bool
228 init_scanner(yyscan_t *scanner, struct scanner_extra *extra,
229              struct xkb_context *ctx, const char *file_name)
230 {
231     memset(extra, 0, sizeof(*extra));
232
233     if (yylex_init_extra(extra, scanner) != 0)
234         return false;
235
236     extra->ctx = ctx;
237     extra->file_name = file_name;
238
239     return true;
240 }
241
242 static void
243 clear_scanner(yyscan_t scanner)
244 {
245     yylex_destroy(scanner);
246 }
247
248 XkbFile *
249 XkbParseString(struct xkb_context *ctx, const char *string,
250                const char *file_name)
251 {
252     yyscan_t scanner;
253     struct scanner_extra extra;
254     YY_BUFFER_STATE state;
255     XkbFile *xkb_file;
256
257     if (!init_scanner(&scanner, &extra, ctx, file_name))
258         return NULL;
259
260     state = yy_scan_string(string, scanner);
261
262     xkb_file = parse(ctx, scanner, NULL);
263
264     yy_delete_buffer(state, scanner);
265     clear_scanner(scanner);
266
267     return xkb_file;
268 }
269
270 /*
271  * yy_scan_buffer() requires the last two bytes of \buf to be 0. These two bytes
272  * are not scanned. Other zero bytes in the buffer are scanned normally, though.
273  * Due to these terminating zeroes, \length must be greater than 2.
274  * Furthermore, the buffer must be writable and you cannot make any assumptions
275  * about it after the scanner finished.
276  * All this must be guaranteed by the caller of this function!
277  */
278 XkbFile *
279 XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length,
280                const char *file_name)
281 {
282     yyscan_t scanner;
283     struct scanner_extra extra;
284     YY_BUFFER_STATE state;
285     XkbFile *xkb_file;
286
287     if (!init_scanner(&scanner, &extra, ctx, file_name))
288         return NULL;
289
290     xkb_file = NULL;
291     state = yy_scan_buffer(buf, length, scanner);
292     if (state) {
293         xkb_file = parse(ctx, scanner, NULL);
294         yy_delete_buffer(state, scanner);
295     }
296
297     clear_scanner(scanner);
298
299     return xkb_file;
300 }
301
302 XkbFile *
303 XkbParseFile(struct xkb_context *ctx, FILE *file,
304              const char *file_name, const char *map)
305 {
306     yyscan_t scanner;
307     struct scanner_extra extra;
308     YY_BUFFER_STATE state;
309     XkbFile *xkb_file;
310
311     if (!init_scanner(&scanner, &extra, ctx, file_name))
312         return NULL;
313
314     state = yy_create_buffer(file, YY_BUF_SIZE, scanner);
315     yy_switch_to_buffer(state, scanner);
316
317     xkb_file = parse(ctx, scanner, map);
318
319     yy_delete_buffer(state, scanner);
320     clear_scanner(scanner);
321
322     return xkb_file;
323 }