fbeab1e75c2d3142cf6c3c57c15fc1f0f0ee7b4c
[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
196                                 /* Unicode: The first 256 code points were made
197                                    identical to the content of ISO 8859-1 */
198                                 if (kmap->prefer_unicode &&
199                                     !strcasecmp((char *) $2.data, "iso-8859-1"))
200                                         kmap->prefer_unicode = 0;
201                         }
202                 ;
203 altismetaline   : ALT_IS_META EOL
204                         {
205                                 kmap->alt_is_meta = 1;
206                         }
207                 ;
208 usualstringsline: STRINGS AS USUAL EOL
209                         {
210                                 if (strings_as_usual(kmap) == -1)
211                                         YYERROR;
212                         }
213                 ;
214 usualcomposeline: COMPOSE AS USUAL FOR STRLITERAL EOL
215                         {
216                                 if (compose_as_usual(kmap, (char *) $5.data) == -1)
217                                         YYERROR;
218                         }
219                   | COMPOSE AS USUAL EOL
220                         {
221                                 if (compose_as_usual(kmap, 0) == -1)
222                                         YYERROR;
223                         }
224                 ;
225 keymapline      : KEYMAPS range EOL
226                         {
227                                 kmap->keymaps_line_seen = 1;
228                         }
229                 ;
230 range           : range COMMA range0
231                 | range0
232                 ;
233 range0          : NUMBER DASH NUMBER
234                         {
235                                 int i;
236                                 for (i = $1; i <= $3; i++) {
237                                         if (lk_add_map(kmap, i, 1) == -1)
238                                                 YYERROR;
239                                 }
240                         }
241                 | NUMBER
242                         {
243                                 if (lk_add_map(kmap, $1, 1) == -1)
244                                         YYERROR;
245                         }
246                 ;
247 strline         : STRING LITERAL EQUALS STRLITERAL EOL
248                         {
249                                 struct kbsentry ke;
250
251                                 if (KTYP($2) != KT_FN) {
252                                         ERR(kmap, _("'%s' is not a function key symbol"),
253                                                 syms[KTYP($2)].table[KVAL($2)]);
254                                         YYERROR;
255                                 }
256
257                                 ke.kb_func = KVAL($2);
258                                 strncpy((char *) ke.kb_string,
259                                         (char *) $4.data,
260                                         sizeof(ke.kb_string));
261                                 ke.kb_string[sizeof(ke.kb_string) - 1] = 0;
262
263                                 if (lk_add_func(kmap, ke) == -1)
264                                         YYERROR;
265                         }
266                 ;
267 compline        : COMPOSE compsym compsym TO compsym EOL
268                         {
269                                 if (lk_add_compose(kmap, $2, $3, $5) == -1)
270                                         YYERROR;
271                         }
272                  | COMPOSE compsym compsym TO rvalue EOL
273                         {
274                                 if (lk_add_compose(kmap, $2, $3, $5) == -1)
275                                         YYERROR;
276                         }
277                 ;
278 compsym         : CCHAR         {       $$ = $1;                }
279                 | UNUMBER       {       $$ = $1 ^ 0xf000;       }
280                 ;
281 singleline      :       {
282                                 kmap->mod = 0;
283                         }
284                   modifiers KEYCODE NUMBER EQUALS rvalue EOL
285                         {
286                                 if (lk_add_key(kmap, $4, kmap->mod, $6) == -1)
287                                         YYERROR;
288                         }
289                 | PLAIN KEYCODE NUMBER EQUALS rvalue EOL
290                         {
291                                 if (lk_add_key(kmap, $3, 0, $5) == -1)
292                                         YYERROR;
293                         }
294                 ;
295 modifiers       : modifiers modifier
296                 | modifier
297                 ;
298 modifier        : SHIFT         { kmap->mod |= M_SHIFT; }
299                 | CONTROL       { kmap->mod |= M_CTRL;  }
300                 | ALT           { kmap->mod |= M_ALT;           }
301                 | ALTGR         { kmap->mod |= M_ALTGR; }
302                 | SHIFTL        { kmap->mod |= M_SHIFTL;        }
303                 | SHIFTR        { kmap->mod |= M_SHIFTR;        }
304                 | CTRLL         { kmap->mod |= M_CTRLL; }
305                 | CTRLR         { kmap->mod |= M_CTRLR; }
306                 | CAPSSHIFT     { kmap->mod |= M_CAPSSHIFT;     }
307                 ;
308 fullline        : KEYCODE NUMBER EQUALS rvalue0 EOL
309                         {
310                                 int i, j, keycode;
311
312                                 if (kmap->rvalct == 1) {
313                                         /* Some files do not have a keymaps line, and
314                                          * we have to wait until all input has been read
315                                          * before we know which maps to fill. */
316                                         kmap->key_is_constant[$2] = 1;
317
318                                         /* On the other hand, we now have include files,
319                                          * and it should be possible to override lines
320                                          * from an include file. So, kill old defs. */
321                                         for (j = 0; j < kmap->max_keymap; j++) {
322                                                 if (!(kmap->defining[j]))
323                                                         continue;
324
325                                                 if (lk_remove_key(kmap, $2, j) == -1)
326                                                         YYERROR;
327                                         }
328                                 }
329
330                                 if (kmap->keymaps_line_seen) {
331                                         i = 0;
332
333                                         for (j = 0; j < kmap->max_keymap; j++) {
334                                                 if (!(kmap->defining[j]))
335                                                         continue;
336
337                                                 if (kmap->rvalct != 1 || i == 0) {
338                                                         keycode = (i < kmap->rvalct)
339                                                                 ? kmap->key_buf[i]
340                                                                 : K_HOLE;
341
342                                                         if (lk_add_key(kmap, $2, j, keycode) == -1)
343                                                                 YYERROR;
344                                                 }
345                                                 i++;
346                                         }
347
348                                         if (i < kmap->rvalct) {
349                                                 ERR(kmap, _("too many (%d) entries on one line"),
350                                                         kmap->rvalct);
351                                                 YYERROR;
352                                         }
353                                 } else {
354                                         for (i = 0; i < kmap->rvalct; i++) {
355                                                 if (lk_add_key(kmap, $2, i, kmap->key_buf[i]) == -1)
356                                                         YYERROR;
357                                         }
358                                 }
359                         }
360                 ;
361
362 rvalue0         :
363                 | rvalue1 rvalue0
364                 ;
365 rvalue1         : rvalue
366                         {
367                                 if (kmap->rvalct >= MAX_NR_KEYMAPS) {
368                                         ERR(kmap, _("too many key definitions on one line"));
369                                         YYERROR;
370                                 }
371                                 kmap->key_buf[kmap->rvalct++] = $1;
372                         }
373                 ;
374 rvalue          : NUMBER        { $$ = convert_code(kmap, $1, TO_AUTO);         }
375                 | PLUS NUMBER   { $$ = add_capslock(kmap, $2);                  }
376                 | UNUMBER       { $$ = convert_code(kmap, $1^0xf000, TO_AUTO);  }
377                 | PLUS UNUMBER  { $$ = add_capslock(kmap, $2^0xf000);           }
378                 | LITERAL       { $$ = $1;                                      }
379                 | PLUS LITERAL  { $$ = add_capslock(kmap, $2);                  }
380                 ;
381 %%
382
383 int
384 lk_parse_keymap(struct keymap *kmap, lkfile_t *f)
385 {
386         yyscan_t scanner;
387         int rc = -1;
388
389         yylex_init(&scanner);
390         yylex_init_extra(kmap, &scanner);
391
392         INFO(kmap, _("Loading %s"), f->pathname);
393
394         if (stack_push(kmap, f, scanner) == -1)
395                 goto fail;
396
397         if (yyparse(scanner, kmap))
398                 goto fail;
399
400         rc = 0;
401
402         stack_pop(kmap, scanner);
403
404  fail:  yylex_destroy(scanner);
405         return rc;
406 }