Remove static arrays for keymaps and keys
[platform/upstream/kbd.git] / src / libkeymap / parser.y
1 /* parser.y
2  *
3  * This file is part of kbd project.
4  * Copyright (C) 1993  Risto Kankkunen.
5  * Copyright (C) 1993  Eugene G. Crosser.
6  * Copyright (C) 1994-2007  Andries E. Brouwer.
7  * Copyright (C) 2007-2013  Alexey Gladkov <gladkov.alexey@gmail.com>
8  *
9  * This file is covered by the GNU General Public License,
10  * which should be included with kbd as the file COPYING.
11  */
12 %{
13 #define YY_HEADER_EXPORT_START_CONDITIONS 1
14
15 #include "nls.h"
16 #include "kbd.h"
17
18 #include "ksyms.h"
19 #include "modifiers.h"
20
21 #include "parser.h"
22 #include "analyze.h"
23 %}
24
25 %code requires {
26 #include "keymap.h"
27
28 #ifndef STRDATA_STRUCT
29 #define STRDATA_STRUCT
30 #define MAX_PARSER_STRING 512
31 struct strdata {
32         unsigned int len;
33         unsigned char data[MAX_PARSER_STRING];
34 };
35 #endif
36 }
37
38 %language "C"
39 %yacc
40 %defines
41 %debug
42 %error-verbose
43
44 /* Pure yylex.  */
45 %define api.pure
46 %lex-param { yyscan_t scanner }
47
48 /* Pure yyparse.  */
49 %parse-param { void *scanner }
50 %parse-param { struct keymap *kmap }
51
52 %token EOL NUMBER LITERAL CHARSET KEYMAPS KEYCODE EQUALS
53 %token PLAIN SHIFT CONTROL ALT ALTGR SHIFTL SHIFTR CTRLL CTRLR CAPSSHIFT
54 %token COMMA DASH STRING STRLITERAL COMPOSE TO CCHAR ERROR PLUS
55 %token UNUMBER ALT_IS_META STRINGS AS USUAL ON FOR
56
57 %union {
58         long long int num;
59         struct strdata str;
60 }
61
62 %type <str>  STRLITERAL
63 %type <num>  CCHAR
64 %type <num>  LITERAL
65 %type <num>  NUMBER
66 %type <num>  UNUMBER
67 %type <num>  compsym
68 %type <num>  rvalue
69
70 %{
71 static int
72 yyerror(yyscan_t scanner __attribute__ ((unused)),
73         struct keymap *kmap, const char *s)
74 {
75         ERR(kmap, "%s", s);
76         return 0;
77 }
78
79 static int
80 strings_as_usual(struct keymap *kmap)
81 {
82         /*
83          * 26 strings, mostly inspired by the VT100 family
84          */
85         char *stringvalues[30] = {
86                 /* F1 .. F20 */
87                 "\033[[A",  "\033[[B",  "\033[[C",  "\033[[D",  "\033[[E",
88                 "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~",
89                 "\033[23~", "\033[24~", "\033[25~", "\033[26~",
90                 "\033[28~", "\033[29~",
91                 "\033[31~", "\033[32~", "\033[33~", "\033[34~",
92                 /* Find,    Insert,     Remove,     Select,     Prior */
93                 "\033[1~",  "\033[2~",  "\033[3~",  "\033[4~",  "\033[5~",
94                 /* Next,    Macro,      Help,       Do,         Pause */
95                 "\033[6~",  0,          0,          0,          0
96         };
97         int i;
98
99         for (i = 0; i < 30; i++) {
100                 if (stringvalues[i]) {
101                         struct kbsentry ke;
102                         ke.kb_func = i;
103                         strncpy((char *)ke.kb_string, stringvalues[i],
104                                 sizeof(ke.kb_string));
105                         ke.kb_string[sizeof(ke.kb_string) - 1] = 0;
106
107                         if (lk_add_func(kmap, ke) == -1)
108                                 return -1;
109                 }
110         }
111         return 0;
112 }
113
114 static int
115 compose_as_usual(struct keymap *kmap, char *charset)
116 {
117         if (charset && strcmp(charset, "iso-8859-1")) {
118                 ERR(kmap, _("loadkeys: don't know how to compose for %s"), charset);
119                 return -1;
120
121         } else {
122                 struct ccc {
123                         unsigned char c1, c2, c3;
124                 } def_latin1_composes[68] = {
125                         { '`', 'A', 0300 }, { '`', 'a', 0340 },
126                         { '\'', 'A', 0301 }, { '\'', 'a', 0341 },
127                         { '^', 'A', 0302 }, { '^', 'a', 0342 },
128                         { '~', 'A', 0303 }, { '~', 'a', 0343 },
129                         { '"', 'A', 0304 }, { '"', 'a', 0344 },
130                         { 'O', 'A', 0305 }, { 'o', 'a', 0345 },
131                         { '0', 'A', 0305 }, { '0', 'a', 0345 },
132                         { 'A', 'A', 0305 }, { 'a', 'a', 0345 },
133                         { 'A', 'E', 0306 }, { 'a', 'e', 0346 },
134                         { ',', 'C', 0307 }, { ',', 'c', 0347 },
135                         { '`', 'E', 0310 }, { '`', 'e', 0350 },
136                         { '\'', 'E', 0311 }, { '\'', 'e', 0351 },
137                         { '^', 'E', 0312 }, { '^', 'e', 0352 },
138                         { '"', 'E', 0313 }, { '"', 'e', 0353 },
139                         { '`', 'I', 0314 }, { '`', 'i', 0354 },
140                         { '\'', 'I', 0315 }, { '\'', 'i', 0355 },
141                         { '^', 'I', 0316 }, { '^', 'i', 0356 },
142                         { '"', 'I', 0317 }, { '"', 'i', 0357 },
143                         { '-', 'D', 0320 }, { '-', 'd', 0360 },
144                         { '~', 'N', 0321 }, { '~', 'n', 0361 },
145                         { '`', 'O', 0322 }, { '`', 'o', 0362 },
146                         { '\'', 'O', 0323 }, { '\'', 'o', 0363 },
147                         { '^', 'O', 0324 }, { '^', 'o', 0364 },
148                         { '~', 'O', 0325 }, { '~', 'o', 0365 },
149                         { '"', 'O', 0326 }, { '"', 'o', 0366 },
150                         { '/', 'O', 0330 }, { '/', 'o', 0370 },
151                         { '`', 'U', 0331 }, { '`', 'u', 0371 },
152                         { '\'', 'U', 0332 }, { '\'', 'u', 0372 },
153                         { '^', 'U', 0333 }, { '^', 'u', 0373 },
154                         { '"', 'U', 0334 }, { '"', 'u', 0374 },
155                         { '\'', 'Y', 0335 }, { '\'', 'y', 0375 },
156                         { 'T', 'H', 0336 }, { 't', 'h', 0376 },
157                         { 's', 's', 0337 }, { '"', 'y', 0377 },
158                         { 's', 'z', 0337 }, { 'i', 'j', 0377 }
159                 };
160                 int i;
161                 for (i = 0; i < 68; i++) {
162                         struct ccc ptr = def_latin1_composes[i];
163                         if (lk_add_compose(kmap, ptr.c1, ptr.c2, ptr.c3) == -1)
164                                 return -1;
165                 }
166         }
167         return 0;
168 }
169
170 %}
171
172 %%
173 keytable        :
174                 | keytable line
175                 ;
176 line            : EOL
177                 | charsetline
178                 | altismetaline
179                 | usualstringsline
180                 | usualcomposeline
181                 | keymapline
182                 | fullline
183                 | singleline
184                 | strline
185                 | compline
186                 ;
187 charsetline     : CHARSET STRLITERAL EOL
188                         {
189                                 if (lk_set_charset(kmap, (char *) $2.data)) {
190                                         ERR(kmap,
191                                                 _("unknown charset %s - ignoring charset request\n"),
192                                                 (char *) $2.data);
193                                         YYERROR;
194                                 }
195                                 kmap->keywords |= LK_KEYWORD_CHARSET;
196
197                                 /* Unicode: The first 256 code points were made
198                                    identical to the content of ISO 8859-1 */
199                                 if (kmap->flags & LK_FLAG_PREFER_UNICODE &&
200                                     !strcasecmp((char *) $2.data, "iso-8859-1"))
201                                         kmap->flags ^= LK_FLAG_PREFER_UNICODE;
202                         }
203                 ;
204 altismetaline   : ALT_IS_META EOL
205                         {
206                                 kmap->keywords |= LK_KEYWORD_ALTISMETA;
207                         }
208                 ;
209 usualstringsline: STRINGS AS USUAL EOL
210                         {
211                                 if (strings_as_usual(kmap) == -1)
212                                         YYERROR;
213                                 kmap->keywords |= LK_KEYWORD_STRASUSUAL;
214                         }
215                 ;
216 usualcomposeline: COMPOSE AS USUAL FOR STRLITERAL EOL
217                         {
218                                 if (compose_as_usual(kmap, (char *) $5.data) == -1)
219                                         YYERROR;
220                         }
221                   | COMPOSE AS USUAL EOL
222                         {
223                                 if (compose_as_usual(kmap, 0) == -1)
224                                         YYERROR;
225                         }
226                 ;
227 keymapline      : KEYMAPS range EOL
228                         {
229                                 kmap->keywords |= LK_KEYWORD_KEYMAPS;
230                         }
231                 ;
232 range           : range COMMA range0
233                 | range0
234                 ;
235 range0          : NUMBER DASH NUMBER
236                         {
237                                 int i;
238                                 for (i = $1; i <= $3; i++) {
239                                         if (lk_add_map(kmap, i) == -1)
240                                                 YYERROR;
241                                 }
242                         }
243                 | NUMBER
244                         {
245                                 if (lk_add_map(kmap, $1) == -1)
246                                         YYERROR;
247                         }
248                 ;
249 strline         : STRING LITERAL EQUALS STRLITERAL EOL
250                         {
251                                 struct kbsentry ke;
252
253                                 if (KTYP($2) != KT_FN) {
254                                         ERR(kmap, _("'%s' is not a function key symbol"),
255                                                 syms[KTYP($2)].table[KVAL($2)]);
256                                         YYERROR;
257                                 }
258
259                                 ke.kb_func = KVAL($2);
260                                 strncpy((char *) ke.kb_string,
261                                         (char *) $4.data,
262                                         sizeof(ke.kb_string));
263                                 ke.kb_string[sizeof(ke.kb_string) - 1] = 0;
264
265                                 if (lk_add_func(kmap, ke) == -1)
266                                         YYERROR;
267                         }
268                 ;
269 compline        : COMPOSE compsym compsym TO compsym EOL
270                         {
271                                 if (lk_add_compose(kmap, $2, $3, $5) == -1)
272                                         YYERROR;
273                         }
274                  | COMPOSE compsym compsym TO rvalue EOL
275                         {
276                                 if (lk_add_compose(kmap, $2, $3, $5) == -1)
277                                         YYERROR;
278                         }
279                 ;
280 compsym         : CCHAR         {       $$ = $1;                }
281                 | UNUMBER       {       $$ = $1 ^ 0xf000;       }
282                 ;
283 singleline      :       {
284                                 kmap->mod = 0;
285                         }
286                   modifiers KEYCODE NUMBER EQUALS rvalue EOL
287                         {
288                                 if (lk_add_key(kmap, kmap->mod, $4, $6) < 0)
289                                         YYERROR;
290                         }
291                 | PLAIN KEYCODE NUMBER EQUALS rvalue EOL
292                         {
293                                 if (lk_add_key(kmap, 0, $3, $5) < 0)
294                                         YYERROR;
295                         }
296                 ;
297 modifiers       : modifiers modifier
298                 | modifier
299                 ;
300 modifier        : SHIFT         { kmap->mod |= M_SHIFT; }
301                 | CONTROL       { kmap->mod |= M_CTRL;  }
302                 | ALT           { kmap->mod |= M_ALT;           }
303                 | ALTGR         { kmap->mod |= M_ALTGR; }
304                 | SHIFTL        { kmap->mod |= M_SHIFTL;        }
305                 | SHIFTR        { kmap->mod |= M_SHIFTR;        }
306                 | CTRLL         { kmap->mod |= M_CTRLL; }
307                 | CTRLR         { kmap->mod |= M_CTRLR; }
308                 | CAPSSHIFT     { kmap->mod |= M_CAPSSHIFT;     }
309                 ;
310 fullline        : KEYCODE NUMBER EQUALS rvalue0 EOL
311                         {
312                                 unsigned int j;
313                                 int i, keycode;
314
315                                 if (kmap->rvalct == 1) {
316                                         /* Some files do not have a keymaps line, and
317                                          * we have to wait until all input has been read
318                                          * before we know which maps to fill. */
319                                         kmap->key_is_constant[$2] = 1;
320
321                                         /* On the other hand, we now have include files,
322                                          * and it should be possible to override lines
323                                          * from an include file. So, kill old defs. */
324                                         for (j = 0; j < kmap->keymap->total; j++) {
325                                                 if (!lk_map_exist(kmap, j))
326                                                         continue;
327
328                                                 if (lk_del_key(kmap, j, $2) < 0)
329                                                         YYERROR;
330                                         }
331                                 }
332
333                                 if (kmap->keywords & LK_KEYWORD_KEYMAPS) {
334                                         i = 0;
335
336                                         for (j = 0; j < kmap->keymap->total; j++) {
337                                                 if (!lk_map_exist(kmap, j))
338                                                         continue;
339
340                                                 if (kmap->rvalct != 1 || i == 0) {
341                                                         keycode = (i < kmap->rvalct)
342                                                                 ? kmap->key_buf[i]
343                                                                 : K_HOLE;
344
345                                                         if (lk_add_key(kmap, j, $2, keycode) < 0)
346                                                                 YYERROR;
347                                                 }
348                                                 i++;
349                                         }
350
351                                         if (i < kmap->rvalct) {
352                                                 ERR(kmap, _("too many (%d) entries on one line"),
353                                                         kmap->rvalct);
354                                                 YYERROR;
355                                         }
356                                 } else {
357                                         for (i = 0; i < kmap->rvalct; i++) {
358                                                 if (lk_add_key(kmap, i, $2, kmap->key_buf[i]) < 0)
359                                                         YYERROR;
360                                         }
361                                 }
362                         }
363                 ;
364
365 rvalue0         :
366                 | rvalue1 rvalue0
367                 ;
368 rvalue1         : rvalue
369                         {
370                                 if (kmap->rvalct >= MAX_NR_KEYMAPS) {
371                                         ERR(kmap, _("too many key definitions on one line"));
372                                         YYERROR;
373                                 }
374                                 kmap->key_buf[kmap->rvalct++] = $1;
375                         }
376                 ;
377 rvalue          : NUMBER        { $$ = convert_code(kmap, $1, TO_AUTO);         }
378                 | PLUS NUMBER   { $$ = add_capslock(kmap, $2);                  }
379                 | UNUMBER       { $$ = convert_code(kmap, $1^0xf000, TO_AUTO);  }
380                 | PLUS UNUMBER  { $$ = add_capslock(kmap, $2^0xf000);           }
381                 | LITERAL       { $$ = $1;                                      }
382                 | PLUS LITERAL  { $$ = add_capslock(kmap, $2);                  }
383                 ;
384 %%
385
386 int
387 lk_parse_keymap(struct keymap *kmap, lkfile_t *f)
388 {
389         yyscan_t scanner;
390         int rc = -1;
391
392         yylex_init(&scanner);
393         yylex_init_extra(kmap, &scanner);
394
395         INFO(kmap, _("Loading %s"), f->pathname);
396
397         if (stack_push(kmap, f, scanner) == -1)
398                 goto fail;
399
400         if (yyparse(scanner, kmap))
401                 goto fail;
402
403         rc = 0;
404
405         stack_pop(kmap, scanner);
406
407  fail:  yylex_destroy(scanner);
408         return rc;
409 }