1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
28 #include "xkbcomp-priv.h"
29 #include "ast-build.h"
30 #include "parser-priv.h"
33 struct xkb_context *ctx;
40 _xkbcommon_error(struct parser_param *param, const char *msg)
42 scanner_error(param->scanner, msg);
45 #define scanner param->scanner
49 %lex-param { struct scanner *scanner }
50 %parse-param { struct parser_param *param }
129 enum xkb_file_type file_type;
132 enum merge_mode merge;
133 enum xkb_map_flags mapFlags;
142 GroupCompatDef *groupCompat;
146 KeyAliasDef *keyAlias;
151 %type <num> INTEGER FLOAT
152 %type <str> IDENT STRING
155 %type <ival> Number Integer Float SignedNumber
156 %type <merge> MergeMode OptMergeMode
157 %type <file_type> XkbCompositeType FileType
158 %type <uval> DoodadType
159 %type <mapFlags> Flag Flags OptFlags
160 %type <str> MapName OptMapName KeySym
161 %type <sval> FieldSpec Ident Element String
162 %type <any> DeclList Decl
163 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
164 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
165 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
166 %type <vmod> VModDecl VModDefList VModDef
167 %type <interp> InterpretDecl InterpretMatch
168 %type <keyType> KeyTypeDecl
169 %type <syms> SymbolsDecl
170 %type <modMask> ModMapDecl
171 %type <groupCompat> GroupCompatDecl
172 %type <ledMap> LedMapDecl
173 %type <ledName> LedNameDecl
174 %type <keyCode> KeyNameDecl
175 %type <keyAlias> KeyAliasDecl
176 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
177 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
178 %type <geom> DoodadDecl
179 %type <file> XkbFile XkbMapConfigList XkbMapConfig
180 %type <file> XkbCompositeMap
185 * An actual file may contain more than one map. However, if we do things
186 * in the normal yacc way, i.e. aggregate all of the maps into a list and
187 * let the caller find the map it wants, we end up scanning and parsing a
188 * lot of unneeded maps (in the end we always just need one).
189 * Instead of doing that, we make yyparse return one map at a time, and
190 * then call it repeatedly until we find the map we need. Once we find it,
191 * we don't need to parse everything that follows in the file.
192 * This does mean that if we e.g. always use the first map, the file may
193 * contain complete garbage after that. But it's worth it.
196 XkbFile : XkbCompositeMap
197 { $$ = param->rtrn = $1; param->more_maps = true; }
199 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
201 { $$ = param->rtrn = NULL; param->more_maps = false; }
204 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
207 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
210 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
211 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
212 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
215 XkbMapConfigList : XkbMapConfigList XkbMapConfig
220 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
226 XkbMapConfig : OptFlags FileType OptMapName OBRACE
230 if ($2 == FILE_TYPE_GEOMETRY) {
236 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
241 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
242 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
243 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
244 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
245 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
248 OptFlags : Flags { $$ = $1; }
252 Flags : Flags Flag { $$ = ($1 | $2); }
256 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
257 | DEFAULT { $$ = MAP_IS_DEFAULT; }
258 | HIDDEN { $$ = MAP_IS_HIDDEN; }
259 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
260 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
261 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
262 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
263 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
266 DeclList : DeclList Decl
267 { $$ = AppendStmt($1, $2); }
271 Decl : OptMergeMode VarDecl
276 | OptMergeMode VModDecl
281 | OptMergeMode InterpretDecl
286 | OptMergeMode KeyNameDecl
291 | OptMergeMode KeyAliasDecl
296 | OptMergeMode KeyTypeDecl
301 | OptMergeMode SymbolsDecl
306 | OptMergeMode ModMapDecl
311 | OptMergeMode GroupCompatDecl
316 | OptMergeMode LedMapDecl
321 | OptMergeMode LedNameDecl
326 | OptMergeMode ShapeDecl { $$ = NULL; }
327 | OptMergeMode SectionDecl { $$ = NULL; }
328 | OptMergeMode DoodadDecl { $$ = NULL; }
331 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
336 VarDecl : Lhs EQUALS Expr SEMI
337 { $$ = VarCreate($1, $3); }
339 { $$ = BoolVarCreate($1, 1); }
341 { $$ = BoolVarCreate($2, 0); }
344 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
345 { $$ = KeycodeCreate($1, $3); }
348 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
349 { $$ = KeyAliasCreate($2, $4); }
352 VModDecl : VIRTUAL_MODS VModDefList SEMI
356 VModDefList : VModDefList COMMA VModDef
357 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
363 { $$ = VModCreate($1, NULL); }
365 { $$ = VModCreate($1, $3); }
368 InterpretDecl : INTERPRET InterpretMatch OBRACE
371 { $2->def = $4; $$ = $2; }
374 InterpretMatch : KeySym PLUS Expr
375 { $$ = InterpCreate($1, $3); }
377 { $$ = InterpCreate($1, NULL); }
380 VarDeclList : VarDeclList VarDecl
381 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
386 KeyTypeDecl : TYPE String OBRACE
389 { $$ = KeyTypeCreate($2, $4); }
392 SymbolsDecl : KEY KEYNAME OBRACE
395 { $$ = SymbolsCreate($2, (ExprDef *)$4); }
398 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
399 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
405 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
406 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
407 | Ident { $$ = BoolVarCreate($1, 1); }
408 | EXCLAM Ident { $$ = BoolVarCreate($2, 0); }
409 | ArrayInit { $$ = VarCreate(NULL, $1); }
412 ArrayInit : OBRACKET OptKeySymList CBRACKET
414 | OBRACKET ActionList CBRACKET
415 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
418 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
419 { $$ = GroupCompatCreate($2, $4); }
422 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
423 { $$ = ModMapCreate($2, $4); }
426 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
427 { $$ = LedMapCreate($2, $4); }
430 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
431 { $$ = LedNameCreate($2, $4, false); }
432 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
433 { $$ = LedNameCreate($3, $5, true); }
436 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
438 | SHAPE String OBRACE CoordList CBRACE SEMI
442 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
446 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
447 | SectionBodyItem { $$ = NULL; }
450 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
453 { FreeStmt(&$1->common); $$ = NULL; }
457 { FreeStmt(&$1->common); $$ = NULL; }
462 RowBody : RowBody RowBodyItem { $$ = NULL;}
463 | RowBodyItem { $$ = NULL; }
466 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
468 { FreeStmt(&$1->common); $$ = NULL; }
471 Keys : Keys COMMA Key { $$ = NULL; }
477 | OBRACE ExprList CBRACE
478 { FreeStmt(&$2->common); $$ = NULL; }
481 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
485 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
486 | OverlayKey { $$ = NULL; }
489 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
492 OutlineList : OutlineList COMMA OutlineInList
498 OutlineInList : OBRACE CoordList CBRACE
500 | Ident EQUALS OBRACE CoordList CBRACE
503 { FreeStmt(&$3->common); $$ = NULL; }
506 CoordList : CoordList COMMA Coord
512 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
516 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
517 { FreeStmt(&$4->common); $$ = NULL; }
520 DoodadType : TEXT { $$ = 0; }
521 | OUTLINE { $$ = 0; }
526 FieldSpec : Ident { $$ = $1; }
527 | Element { $$ = $1; }
531 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
533 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
535 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
537 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
539 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
541 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
543 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
545 { $$ = XKB_ATOM_NONE; }
547 { $$ = XKB_ATOM_NONE; }
549 { $$ = XKB_ATOM_NONE; }
551 { $$ = XKB_ATOM_NONE; }
554 OptMergeMode : MergeMode { $$ = $1; }
555 | { $$ = MERGE_DEFAULT; }
558 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
559 | AUGMENT { $$ = MERGE_AUGMENT; }
560 | OVERRIDE { $$ = MERGE_OVERRIDE; }
561 | REPLACE { $$ = MERGE_REPLACE; }
565 * This used to be MERGE_ALT_FORM. This functionality was
566 * unused and has been removed.
572 OptExprList : ExprList { $$ = $1; }
576 ExprList : ExprList COMMA Expr
577 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
582 Expr : Expr DIVIDE Expr
583 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
585 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
587 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
589 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
591 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
597 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
599 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
601 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
603 { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
606 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
607 { $$ = ActionCreate($1, $3); }
614 ActionList : ActionList COMMA Action
615 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
620 Action : FieldSpec OPAREN OptExprList CPAREN
621 { $$ = ActionCreate($1, $3); }
627 expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
628 expr->value.str = $1;
631 | FieldSpec DOT FieldSpec
634 expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
635 expr->value.field.element = $1;
636 expr->value.field.field = $3;
639 | FieldSpec OBRACKET Expr CBRACKET
642 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
643 expr->value.array.element = XKB_ATOM_NONE;
644 expr->value.array.field = $1;
645 expr->value.array.entry = $3;
648 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
651 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
652 expr->value.array.element = $1;
653 expr->value.array.field = $3;
654 expr->value.array.entry = $5;
662 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
663 expr->value.str = $1;
669 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
670 expr->value.ival = $1;
680 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
681 expr->value.keyName = $1;
686 OptKeySymList : KeySymList { $$ = $1; }
690 KeySymList : KeySymList COMMA KeySym
691 { $$ = AppendKeysymList($1, $3); }
692 | KeySymList COMMA KeySyms
693 { $$ = AppendMultiKeysymList($1, $3); }
695 { $$ = CreateKeysymList($1); }
697 { $$ = CreateMultiKeysymList($1); }
700 KeySyms : OBRACE KeySymList CBRACE
704 KeySym : IDENT { $$ = $1; }
705 | SECTION { $$ = strdup("section"); }
708 if ($1 < 10) { /* XK_0 .. XK_9 */
715 snprintf($$, 17, "0x%x", $1);
720 SignedNumber : MINUS Number { $$ = -$2; }
721 | Number { $$ = $1; }
724 Number : FLOAT { $$ = $1; }
725 | INTEGER { $$ = $1; }
728 Float : FLOAT { $$ = 0; }
731 Integer : INTEGER { $$ = $1; }
734 KeyCode : INTEGER { $$ = $1; }
737 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
738 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
741 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
744 OptMapName : MapName { $$ = $1; }
748 MapName : STRING { $$ = $1; }
756 parse(struct xkb_context *ctx, void *scanner, const char *map)
758 struct parser_param param;
760 XkbFile *first = NULL;
762 param.scanner = scanner;
766 * If we got a specific map, we look for it exclusively and return
767 * immediately upon finding it. Otherwise, we need to get the
768 * default map. If we find a map marked as default, we return it
769 * immediately. If there are no maps marked as default, we return
770 * the first map in the file.
773 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
775 if (streq_not_null(map, param.rtrn->name))
778 FreeXkbFile(param.rtrn);
781 if (param.rtrn->flags & MAP_IS_DEFAULT) {
789 FreeXkbFile(param.rtrn);