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 YYLTYPE *loc, struct parser_param *param, const char *msg)
42 scanner_error(loc, param->scanner, msg);
45 #define scanner param->scanner
50 %lex-param { struct scanner *scanner }
51 %parse-param { struct parser_param *param }
130 enum xkb_file_type file_type;
133 enum merge_mode merge;
134 enum xkb_map_flags mapFlags;
143 GroupCompatDef *groupCompat;
147 KeyAliasDef *keyAlias;
152 %type <num> INTEGER FLOAT
153 %type <str> IDENT STRING
156 %type <ival> Number Integer Float SignedNumber
157 %type <merge> MergeMode OptMergeMode
158 %type <file_type> XkbCompositeType FileType
159 %type <uval> DoodadType
160 %type <mapFlags> Flag Flags OptFlags
161 %type <str> MapName OptMapName KeySym
162 %type <sval> FieldSpec Ident Element String
163 %type <any> DeclList Decl
164 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
165 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
166 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
167 %type <vmod> VModDecl VModDefList VModDef
168 %type <interp> InterpretDecl InterpretMatch
169 %type <keyType> KeyTypeDecl
170 %type <syms> SymbolsDecl
171 %type <modMask> ModMapDecl
172 %type <groupCompat> GroupCompatDecl
173 %type <ledMap> LedMapDecl
174 %type <ledName> LedNameDecl
175 %type <keyCode> KeyNameDecl
176 %type <keyAlias> KeyAliasDecl
177 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
178 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
179 %type <geom> DoodadDecl
180 %type <file> XkbFile XkbMapConfigList XkbMapConfig
181 %type <file> XkbCompositeMap
186 * An actual file may contain more than one map. However, if we do things
187 * in the normal yacc way, i.e. aggregate all of the maps into a list and
188 * let the caller find the map it wants, we end up scanning and parsing a
189 * lot of unneeded maps (in the end we always just need one).
190 * Instead of doing that, we make yyparse return one map at a time, and
191 * then call it repeatedly until we find the map we need. Once we find it,
192 * we don't need to parse everything that follows in the file.
193 * This does mean that if we e.g. always use the first map, the file may
194 * contain complete garbage after that. But it's worth it.
197 XkbFile : XkbCompositeMap
198 { $$ = param->rtrn = $1; param->more_maps = true; }
200 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
202 { $$ = param->rtrn = NULL; param->more_maps = false; }
205 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
208 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
211 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
212 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
213 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
216 XkbMapConfigList : XkbMapConfigList XkbMapConfig
221 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
227 XkbMapConfig : OptFlags FileType OptMapName OBRACE
231 if ($2 == FILE_TYPE_GEOMETRY) {
237 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
242 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
243 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
244 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
245 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
246 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
249 OptFlags : Flags { $$ = $1; }
253 Flags : Flags Flag { $$ = ($1 | $2); }
257 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
258 | DEFAULT { $$ = MAP_IS_DEFAULT; }
259 | HIDDEN { $$ = MAP_IS_HIDDEN; }
260 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
261 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
262 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
263 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
264 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
267 DeclList : DeclList Decl
268 { $$ = AppendStmt($1, $2); }
272 Decl : OptMergeMode VarDecl
277 | OptMergeMode VModDecl
282 | OptMergeMode InterpretDecl
287 | OptMergeMode KeyNameDecl
292 | OptMergeMode KeyAliasDecl
297 | OptMergeMode KeyTypeDecl
302 | OptMergeMode SymbolsDecl
307 | OptMergeMode ModMapDecl
312 | OptMergeMode GroupCompatDecl
317 | OptMergeMode LedMapDecl
322 | OptMergeMode LedNameDecl
327 | OptMergeMode ShapeDecl { $$ = NULL; }
328 | OptMergeMode SectionDecl { $$ = NULL; }
329 | OptMergeMode DoodadDecl { $$ = NULL; }
332 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
337 VarDecl : Lhs EQUALS Expr SEMI
338 { $$ = VarCreate($1, $3); }
340 { $$ = BoolVarCreate($1, 1); }
342 { $$ = BoolVarCreate($2, 0); }
345 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
346 { $$ = KeycodeCreate($1, $3); }
349 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
350 { $$ = KeyAliasCreate($2, $4); }
353 VModDecl : VIRTUAL_MODS VModDefList SEMI
357 VModDefList : VModDefList COMMA VModDef
358 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
364 { $$ = VModCreate($1, NULL); }
366 { $$ = VModCreate($1, $3); }
369 InterpretDecl : INTERPRET InterpretMatch OBRACE
372 { $2->def = $4; $$ = $2; }
375 InterpretMatch : KeySym PLUS Expr
376 { $$ = InterpCreate($1, $3); }
378 { $$ = InterpCreate($1, NULL); }
381 VarDeclList : VarDeclList VarDecl
382 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
387 KeyTypeDecl : TYPE String OBRACE
390 { $$ = KeyTypeCreate($2, $4); }
393 SymbolsDecl : KEY KEYNAME OBRACE
396 { $$ = SymbolsCreate($2, (ExprDef *)$4); }
399 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
400 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
406 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
407 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
408 | Ident { $$ = BoolVarCreate($1, 1); }
409 | EXCLAM Ident { $$ = BoolVarCreate($2, 0); }
410 | ArrayInit { $$ = VarCreate(NULL, $1); }
413 ArrayInit : OBRACKET OptKeySymList CBRACKET
415 | OBRACKET ActionList CBRACKET
416 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
419 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
420 { $$ = GroupCompatCreate($2, $4); }
423 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
424 { $$ = ModMapCreate($2, $4); }
427 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
428 { $$ = LedMapCreate($2, $4); }
431 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
432 { $$ = LedNameCreate($2, $4, false); }
433 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
434 { $$ = LedNameCreate($3, $5, true); }
437 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
439 | SHAPE String OBRACE CoordList CBRACE SEMI
443 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
447 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
448 | SectionBodyItem { $$ = NULL; }
451 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
454 { FreeStmt(&$1->common); $$ = NULL; }
458 { FreeStmt(&$1->common); $$ = NULL; }
463 RowBody : RowBody RowBodyItem { $$ = NULL;}
464 | RowBodyItem { $$ = NULL; }
467 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
469 { FreeStmt(&$1->common); $$ = NULL; }
472 Keys : Keys COMMA Key { $$ = NULL; }
478 | OBRACE ExprList CBRACE
479 { FreeStmt(&$2->common); $$ = NULL; }
482 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
486 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
487 | OverlayKey { $$ = NULL; }
490 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
493 OutlineList : OutlineList COMMA OutlineInList
499 OutlineInList : OBRACE CoordList CBRACE
501 | Ident EQUALS OBRACE CoordList CBRACE
504 { FreeStmt(&$3->common); $$ = NULL; }
507 CoordList : CoordList COMMA Coord
513 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
517 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
518 { FreeStmt(&$4->common); $$ = NULL; }
521 DoodadType : TEXT { $$ = 0; }
522 | OUTLINE { $$ = 0; }
527 FieldSpec : Ident { $$ = $1; }
528 | Element { $$ = $1; }
532 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
534 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
536 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
538 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
540 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
542 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
544 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
546 { $$ = XKB_ATOM_NONE; }
548 { $$ = XKB_ATOM_NONE; }
550 { $$ = XKB_ATOM_NONE; }
552 { $$ = XKB_ATOM_NONE; }
555 OptMergeMode : MergeMode { $$ = $1; }
556 | { $$ = MERGE_DEFAULT; }
559 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
560 | AUGMENT { $$ = MERGE_AUGMENT; }
561 | OVERRIDE { $$ = MERGE_OVERRIDE; }
562 | REPLACE { $$ = MERGE_REPLACE; }
566 * This used to be MERGE_ALT_FORM. This functionality was
567 * unused and has been removed.
573 OptExprList : ExprList { $$ = $1; }
577 ExprList : ExprList COMMA Expr
578 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
583 Expr : Expr DIVIDE Expr
584 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
586 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
588 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
590 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
592 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
598 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
600 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
602 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
604 { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
607 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
608 { $$ = ActionCreate($1, $3); }
615 ActionList : ActionList COMMA Action
616 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
621 Action : FieldSpec OPAREN OptExprList CPAREN
622 { $$ = ActionCreate($1, $3); }
628 expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
629 expr->value.str = $1;
632 | FieldSpec DOT FieldSpec
635 expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
636 expr->value.field.element = $1;
637 expr->value.field.field = $3;
640 | FieldSpec OBRACKET Expr CBRACKET
643 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
644 expr->value.array.element = XKB_ATOM_NONE;
645 expr->value.array.field = $1;
646 expr->value.array.entry = $3;
649 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
652 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
653 expr->value.array.element = $1;
654 expr->value.array.field = $3;
655 expr->value.array.entry = $5;
663 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
664 expr->value.str = $1;
670 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
671 expr->value.ival = $1;
681 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
682 expr->value.keyName = $1;
687 OptKeySymList : KeySymList { $$ = $1; }
691 KeySymList : KeySymList COMMA KeySym
692 { $$ = AppendKeysymList($1, $3); }
693 | KeySymList COMMA KeySyms
694 { $$ = AppendMultiKeysymList($1, $3); }
696 { $$ = CreateKeysymList($1); }
698 { $$ = CreateMultiKeysymList($1); }
701 KeySyms : OBRACE KeySymList CBRACE
705 KeySym : IDENT { $$ = $1; }
706 | SECTION { $$ = strdup("section"); }
709 if ($1 < 10) { /* XK_0 .. XK_9 */
716 snprintf($$, 17, "0x%x", $1);
721 SignedNumber : MINUS Number { $$ = -$2; }
722 | Number { $$ = $1; }
725 Number : FLOAT { $$ = $1; }
726 | INTEGER { $$ = $1; }
729 Float : FLOAT { $$ = 0; }
732 Integer : INTEGER { $$ = $1; }
735 KeyCode : INTEGER { $$ = $1; }
738 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
739 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
742 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
745 OptMapName : MapName { $$ = $1; }
749 MapName : STRING { $$ = $1; }
757 parse(struct xkb_context *ctx, void *scanner, const char *map)
759 struct parser_param param;
761 XkbFile *first = NULL;
763 param.scanner = scanner;
767 * If we got a specific map, we look for it exclusively and return
768 * immediately upon finding it. Otherwise, we need to get the
769 * default map. If we find a map marked as default, we return it
770 * immediately. If there are no maps marked as default, we return
771 * the first map in the file.
774 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
776 if (streq_not_null(map, param.rtrn->name))
779 FreeXkbFile(param.rtrn);
782 if (param.rtrn->flags & MAP_IS_DEFAULT) {
790 FreeXkbFile(param.rtrn);