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