Structured log messages with a message registry
[platform/upstream/libxkbcommon.git] / src / xkbcomp / parser.y
index 1c212bb..1beb30b 100644 (file)
  */
 
 %{
-#include "xkbcomp-priv.h"
-#include "ast-build.h"
-#include "parser-priv.h"
+#include "config.h"
+
+#include "xkbcomp/xkbcomp-priv.h"
+#include "xkbcomp/ast-build.h"
+#include "xkbcomp/parser-priv.h"
 #include "scanner-utils.h"
+#include "keysym.h"
 
 struct parser_param {
     struct xkb_context *ctx;
@@ -43,16 +46,16 @@ struct parser_param {
     bool more_maps;
 };
 
-#define parser_err(param, fmt, ...) \
-    scanner_err((param)->scanner, fmt, ##__VA_ARGS__)
+#define parser_err(param, error_id, fmt, ...) \
+    scanner_err_with_code((param)->scanner, error_id, fmt, ##__VA_ARGS__)
 
-#define parser_warn(param, fmt, ...) \
-    scanner_warn((param)->scanner, fmt, ##__VA_ARGS__)
+#define parser_warn(param, warning_id, fmt, ...) \
+    scanner_warn_with_code((param)->scanner, warning_id, fmt, ##__VA_ARGS__)
 
 static void
 _xkbcommon_error(struct parser_param *param, const char *msg)
 {
-    parser_err(param, "%s", msg);
+    parser_err(param, XKB_ERROR_INVALID_SYNTAX, "%s", msg);
 }
 
 static bool
@@ -82,7 +85,7 @@ resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
 #define param_scanner param->scanner
 %}
 
-%pure-parser
+%define api.pure
 %lex-param      { struct scanner *param_scanner }
 %parse-param    { struct parser_param *param }
 
@@ -160,18 +163,21 @@ resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
 %start  XkbFile
 
 %union  {
-        int              ival;
         int64_t          num;
         enum xkb_file_type file_type;
         char            *str;
-        xkb_atom_t      sval;
+        xkb_atom_t      atom;
         enum merge_mode merge;
         enum xkb_map_flags mapFlags;
         xkb_keysym_t    keysym;
         ParseCommon     *any;
+        struct { ParseCommon *head; ParseCommon *last; } anyList;
         ExprDef         *expr;
+        struct { ExprDef *head; ExprDef *last; } exprList;
         VarDef          *var;
+        struct { VarDef *head; VarDef *last; } varList;
         VModDef         *vmod;
+        struct { VModDef *head; VModDef *last; } vmodList;
         InterpDef       *interp;
         KeyTypeDef      *keyType;
         SymbolsDef      *syms;
@@ -183,24 +189,28 @@ resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
         KeyAliasDef     *keyAlias;
         void            *geom;
         XkbFile         *file;
+        struct { XkbFile *head; XkbFile *last; } fileList;
 }
 
 %type <num>     INTEGER FLOAT
 %type <str>     IDENT STRING
-%type <sval>    KEYNAME
-%type <num>     KeyCode
-%type <ival>    Number Integer Float SignedNumber DoodadType
+%type <atom>    KEYNAME
+%type <num>     KeyCode Number Integer Float SignedNumber DoodadType
 %type <merge>   MergeMode OptMergeMode
 %type <file_type> XkbCompositeType FileType
 %type <mapFlags> Flag Flags OptFlags
 %type <str>     MapName OptMapName
-%type <sval>    FieldSpec Ident Element String
+%type <atom>    FieldSpec Ident Element String
 %type <keysym>  KeySym
-%type <any>     DeclList Decl
-%type <expr>    OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
-%type <expr>    OptKeySymList KeySymList Action ActionList Coord CoordList
-%type <var>     VarDecl VarDeclList SymbolsBody SymbolsVarDecl
-%type <vmod>    VModDecl VModDefList VModDef
+%type <any>     Decl
+%type <anyList> DeclList
+%type <expr>    Expr Term Lhs Terminal ArrayInit KeySyms
+%type <expr>    OptKeySymList KeySymList Action Coord CoordList
+%type <exprList> OptExprList ExprList ActionList
+%type <var>     VarDecl SymbolsVarDecl
+%type <varList> VarDeclList SymbolsBody
+%type <vmod>    VModDef
+%type <vmodList> VModDefList VModDecl
 %type <interp>  InterpretDecl InterpretMatch
 %type <keyType> KeyTypeDecl
 %type <syms>    SymbolsDecl
@@ -213,15 +223,19 @@ resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
 %type <geom>    ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
 %type <geom>    Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
 %type <geom>    DoodadDecl
-%type <file>    XkbFile XkbMapConfigList XkbMapConfig
+%type <file>    XkbFile XkbMapConfig
+%type <fileList> XkbMapConfigList
 %type <file>    XkbCompositeMap
 
 %destructor { FreeStmt((ParseCommon *) $$); }
     <any> <expr> <var> <vmod> <interp> <keyType> <syms> <modMask> <groupCompat>
     <ledMap> <ledName> <keyCode> <keyAlias>
+%destructor { FreeStmt((ParseCommon *) $$.head); }
+    <anyList> <exprList> <varList> <vmodList>
 /* The destructor also runs on the start symbol when the parser *succeeds*.
  * The `if` here catches this case. */
 %destructor { if (!param->rtrn) FreeXkbFile($$); } <file>
+%destructor { FreeXkbFile($$.head); } <fileList>
 %destructor { free($$); } <str>
 
 %%
@@ -239,9 +253,9 @@ resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
  */
 
 XkbFile         :       XkbCompositeMap
-                        { $$ = param->rtrn = $1; param->more_maps = true; }
+                        { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; }
                 |       XkbMapConfig
-                        { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
+                        { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; YYACCEPT; }
                 |       END_OF_FILE
                         { $$ = param->rtrn = NULL; param->more_maps = false; }
                 ;
@@ -249,7 +263,7 @@ XkbFile         :       XkbCompositeMap
 XkbCompositeMap :       OptFlags XkbCompositeType OptMapName OBRACE
                             XkbMapConfigList
                         CBRACE SEMI
-                        { $$ = XkbFileCreate($2, $3, (ParseCommon *) $5, $1); }
+                        { $$ = XkbFileCreate($2, $3, (ParseCommon *) $5.head, $1); }
                 ;
 
 XkbCompositeType:       XKB_KEYMAP      { $$ = FILE_TYPE_KEYMAP; }
@@ -258,29 +272,16 @@ XkbCompositeType:       XKB_KEYMAP      { $$ = FILE_TYPE_KEYMAP; }
                 ;
 
 XkbMapConfigList :      XkbMapConfigList XkbMapConfig
-                        {
-                            if (!$2)
-                                $$ = $1;
-                            else
-                                $$ = (XkbFile *) AppendStmt((ParseCommon *) $1,
-                                                            (ParseCommon *) $2);
-                        }
+                        { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; }
                 |       XkbMapConfig
-                        { $$ = $1; }
+                        { $$.head = $$.last = $1; }
                 ;
 
 XkbMapConfig    :       OptFlags FileType OptMapName OBRACE
                             DeclList
                         CBRACE SEMI
                         {
-                            if ($2 == FILE_TYPE_GEOMETRY) {
-                                free($3);
-                                FreeStmt($5);
-                                $$ = NULL;
-                            }
-                            else {
-                                $$ = XkbFileCreate($2, $3, $5, $1);
-                            }
+                            $$ = XkbFileCreate($2, $3, $5.head, $1);
                         }
                 ;
 
@@ -310,8 +311,31 @@ Flag            :       PARTIAL                 { $$ = MAP_IS_PARTIAL; }
                 ;
 
 DeclList        :       DeclList Decl
-                        { $$ = AppendStmt($1, $2); }
-                |       { $$ = NULL; }
+                        {
+                            if ($2) {
+                                if ($1.head) {
+                                    $$.head = $1.head; $1.last->next = $2; $$.last = $2;
+                                } else {
+                                    $$.head = $$.last = $2;
+                                }
+                            }
+                        }
+                        /*
+                         * VModDecl is "inlined" directly into DeclList, i.e.
+                         * each VModDef in the VModDecl is a separate Decl in
+                         * the File.
+                         */
+                |       DeclList OptMergeMode VModDecl
+                        {
+                            for (VModDef *vmod = $3.head; vmod; vmod = (VModDef *) vmod->common.next)
+                                vmod->merge = $2;
+                            if ($1.head) {
+                                $$.head = $1.head; $1.last->next = &$3.head->common; $$.last = &$3.last->common;
+                            } else {
+                                $$.head = &$3.head->common; $$.last = &$3.last->common;
+                            }
+                        }
+                |       { $$.head = $$.last = NULL; }
                 ;
 
 Decl            :       OptMergeMode VarDecl
@@ -319,11 +343,7 @@ Decl            :       OptMergeMode VarDecl
                             $2->merge = $1;
                             $$ = (ParseCommon *) $2;
                         }
-                |       OptMergeMode VModDecl
-                        {
-                            $2->merge = $1;
-                            $$ = (ParseCommon *) $2;
-                        }
+                /*      OptMergeMode VModDecl - see above. */
                 |       OptMergeMode InterpretDecl
                         {
                             $2->merge = $1;
@@ -400,10 +420,9 @@ VModDecl        :       VIRTUAL_MODS VModDefList SEMI
                 ;
 
 VModDefList     :       VModDefList COMMA VModDef
-                        { $$ = (VModDef *) AppendStmt((ParseCommon *) $1,
-                                                      (ParseCommon *) $3); }
+                        { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; }
                 |       VModDef
-                        { $$ = $1; }
+                        { $$.head = $$.last = $1; }
                 ;
 
 VModDef         :       Ident
@@ -415,7 +434,7 @@ VModDef         :       Ident
 InterpretDecl   :       INTERPRET InterpretMatch OBRACE
                             VarDeclList
                         CBRACE SEMI
-                        { $2->def = $4; $$ = $2; }
+                        { $2->def = $4.head; $$ = $2; }
                 ;
 
 InterpretMatch  :       KeySym PLUS Expr
@@ -425,30 +444,28 @@ InterpretMatch  :       KeySym PLUS Expr
                 ;
 
 VarDeclList     :       VarDeclList VarDecl
-                        { $$ = (VarDef *) AppendStmt((ParseCommon *) $1,
-                                                     (ParseCommon *) $2); }
+                        { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; }
                 |       VarDecl
-                        { $$ = $1; }
+                        { $$.head = $$.last = $1; }
                 ;
 
 KeyTypeDecl     :       TYPE String OBRACE
                             VarDeclList
                         CBRACE SEMI
-                        { $$ = KeyTypeCreate($2, $4); }
+                        { $$ = KeyTypeCreate($2, $4.head); }
                 ;
 
 SymbolsDecl     :       KEY KEYNAME OBRACE
                             SymbolsBody
                         CBRACE SEMI
-                        { $$ = SymbolsCreate($2, $4); }
+                        { $$ = SymbolsCreate($2, $4.head); }
                 ;
 
 SymbolsBody     :       SymbolsBody COMMA SymbolsVarDecl
-                        { $$ = (VarDef *) AppendStmt((ParseCommon *) $1,
-                                                     (ParseCommon *) $3); }
+                        { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; }
                 |       SymbolsVarDecl
-                        { $$ = $1; }
-                |       { $$ = NULL; }
+                        { $$.head = $$.last = $1; }
+                |       { $$.head = $$.last = NULL; }
                 ;
 
 SymbolsVarDecl  :       Lhs EQUALS Expr         { $$ = VarCreate($1, $3); }
@@ -461,7 +478,7 @@ SymbolsVarDecl  :       Lhs EQUALS Expr         { $$ = VarCreate($1, $3); }
 ArrayInit       :       OBRACKET OptKeySymList CBRACKET
                         { $$ = $2; }
                 |       OBRACKET ActionList CBRACKET
-                        { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
+                        { $$ = ExprCreateActionList($2.head); }
                 ;
 
 GroupCompatDecl :       GROUP Integer EQUALS Expr SEMI
@@ -469,11 +486,11 @@ GroupCompatDecl :       GROUP Integer EQUALS Expr SEMI
                 ;
 
 ModMapDecl      :       MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
-                        { $$ = ModMapCreate($2, $4); }
+                        { $$ = ModMapCreate($2, $4.head); }
                 ;
 
 LedMapDecl:             INDICATOR String OBRACE VarDeclList CBRACE SEMI
-                        { $$ = LedMapCreate($2, $4); }
+                        { $$ = LedMapCreate($2, $4.head); }
                 ;
 
 LedNameDecl:            INDICATOR Integer EQUALS Expr SEMI
@@ -485,7 +502,7 @@ LedNameDecl:            INDICATOR Integer EQUALS Expr SEMI
 ShapeDecl       :       SHAPE String OBRACE OutlineList CBRACE SEMI
                         { $$ = NULL; }
                 |       SHAPE String OBRACE CoordList CBRACE SEMI
-                        { $$ = NULL; }
+                        { (void) $4; $$ = NULL; }
                 ;
 
 SectionDecl     :       SECTION String OBRACE SectionBody CBRACE SEMI
@@ -524,7 +541,7 @@ Keys            :       Keys COMMA Key          { $$ = NULL; }
 Key             :       KEYNAME
                         { $$ = NULL; }
                 |       OBRACE ExprList CBRACE
-                        { FreeStmt((ParseCommon *) $2); $$ = NULL; }
+                        { FreeStmt((ParseCommon *) $2.head); $$ = NULL; }
                 ;
 
 OverlayDecl     :       OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
@@ -545,17 +562,17 @@ OutlineList     :       OutlineList COMMA OutlineInList
                 ;
 
 OutlineInList   :       OBRACE CoordList CBRACE
-                        { $$ = NULL; }
+                        { (void) $2; $$ = NULL; }
                 |       Ident EQUALS OBRACE CoordList CBRACE
-                        { $$ = NULL; }
+                        { (void) $4; $$ = NULL; }
                 |       Ident EQUALS Expr
                         { FreeStmt((ParseCommon *) $3); $$ = NULL; }
                 ;
 
 CoordList       :       CoordList COMMA Coord
-                        { $$ = NULL; }
+                        { (void) $1; (void) $3; $$ = NULL; }
                 |       Coord
-                        { $$ = NULL; }
+                        { (void) $1; $$ = NULL; }
                 ;
 
 Coord           :       OBRACKET SignedNumber COMMA SignedNumber CBRACKET
@@ -563,7 +580,7 @@ Coord           :       OBRACKET SignedNumber COMMA SignedNumber CBRACKET
                 ;
 
 DoodadDecl      :       DoodadType String OBRACE VarDeclList CBRACE SEMI
-                        { FreeStmt((ParseCommon *) $4); $$ = NULL; }
+                        { FreeStmt((ParseCommon *) $4.head); $$ = NULL; }
                 ;
 
 DoodadType      :       TEXT    { $$ = 0; }
@@ -591,13 +608,13 @@ Element         :       ACTION_TOK
                 |       INDICATOR
                         { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
                 |       SHAPE
-                        { $$ = XKB_ATOM_NONE; }
+                        { $$ = xkb_atom_intern_literal(param->ctx, "shape"); }
                 |       ROW
-                        { $$ = XKB_ATOM_NONE; }
+                        { $$ = xkb_atom_intern_literal(param->ctx, "row"); }
                 |       SECTION
-                        { $$ = XKB_ATOM_NONE; }
+                        { $$ = xkb_atom_intern_literal(param->ctx, "section"); }
                 |       TEXT
-                        { $$ = XKB_ATOM_NONE; }
+                        { $$ = xkb_atom_intern_literal(param->ctx, "text"); }
                 ;
 
 OptMergeMode    :       MergeMode       { $$ = $1; }
@@ -619,14 +636,13 @@ MergeMode       :       INCLUDE         { $$ = MERGE_DEFAULT; }
                 ;
 
 OptExprList     :       ExprList        { $$ = $1; }
-                |                       { $$ = NULL; }
+                |                       { $$.head = $$.last = NULL; }
                 ;
 
 ExprList        :       ExprList COMMA Expr
-                        { $$ = (ExprDef *) AppendStmt((ParseCommon *) $1,
-                                                      (ParseCommon *) $3); }
+                        { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; }
                 |       Expr
-                        { $$ = $1; }
+                        { $$.head = $$.last = $1; }
                 ;
 
 Expr            :       Expr DIVIDE Expr
@@ -654,7 +670,7 @@ Term            :       MINUS Term
                 |       Lhs
                         { $$ = $1;  }
                 |       FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
-                        { $$ = ExprCreateAction($1, $3); }
+                        { $$ = ExprCreateAction($1, $3.head); }
                 |       Terminal
                         { $$ = $1;  }
                 |       OPAREN Expr CPAREN
@@ -662,14 +678,13 @@ Term            :       MINUS Term
                 ;
 
 ActionList      :       ActionList COMMA Action
-                        { $$ = (ExprDef *) AppendStmt((ParseCommon *) $1,
-                                                      (ParseCommon *) $3); }
+                        { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; }
                 |       Action
-                        { $$ = $1; }
+                        { $$.head = $$.last = $1; }
                 ;
 
 Action          :       FieldSpec OPAREN OptExprList CPAREN
-                        { $$ = ExprCreateAction($1, $3); }
+                        { $$ = ExprCreateAction($1, $3.head); }
                 ;
 
 Lhs             :       FieldSpec
@@ -687,7 +702,7 @@ Terminal        :       String
                 |       Integer
                         { $$ = ExprCreateInteger($1); }
                 |       Float
-                        { $$ = NULL; }
+                        { $$ = ExprCreateFloat(/* Discard $1 */); }
                 |       KEYNAME
                         { $$ = ExprCreateKeyName($1); }
                 ;
@@ -712,25 +727,42 @@ KeySyms         :       OBRACE KeySymList CBRACE
 
 KeySym          :       IDENT
                         {
-                            if (!resolve_keysym($1, &$$))
-                                parser_warn(param, "unrecognized keysym \"%s\"", $1);
+                            if (!resolve_keysym($1, &$$)) {
+                                parser_warn(
+                                    param,
+                                    XKB_WARNING_UNRECOGNIZED_KEYSYM,
+                                    "unrecognized keysym \"%s\"",
+                                    $1
+                                );
+                                $$ = XKB_KEY_NoSymbol;
+                            }
                             free($1);
                         }
                 |       SECTION { $$ = XKB_KEY_section; }
                 |       Integer
                         {
-                            if ($1 < 0) {
-                                parser_warn(param, "unrecognized keysym \"%d\"", $1);
+                            if ($1 < XKB_KEYSYM_MIN) {
+                                parser_warn(
+                                    param,
+                                    XKB_WARNING_UNRECOGNIZED_KEYSYM,
+                                    "unrecognized keysym \"%"PRId64"\"",
+                                    $1
+                                );
                                 $$ = XKB_KEY_NoSymbol;
                             }
+                            /* Special case for digits 0..9 */
                             else if ($1 < 10) {      /* XKB_KEY_0 .. XKB_KEY_9 */
                                 $$ = XKB_KEY_0 + (xkb_keysym_t) $1;
                             }
                             else {
-                                char buf[17];
-                                snprintf(buf, sizeof(buf), "0x%x", $1);
-                                if (!resolve_keysym(buf, &$$)) {
-                                    parser_warn(param, "unrecognized keysym \"%s\"", buf);
+                                if ($1 <= XKB_KEYSYM_MAX) {
+                                    $$ = (xkb_keysym_t) $1;
+                                } else {
+                                    parser_warn(
+                                        param, XKB_WARNING_UNRECOGNIZED_KEYSYM,
+                                        "unrecognized keysym \"0x%"PRIx64"\" "
+                                        "(%"PRId64")", $1, $1
+                                    );
                                     $$ = XKB_KEY_NoSymbol;
                                 }
                             }
@@ -754,11 +786,11 @@ Integer         :       INTEGER { $$ = $1; }
 KeyCode         :       INTEGER { $$ = $1; }
                 ;
 
-Ident           :       IDENT   { $$ = xkb_atom_steal(param->ctx, $1); }
+Ident           :       IDENT   { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); }
                 |       DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
                 ;
 
-String          :       STRING  { $$ = xkb_atom_steal(param->ctx, $1); }
+String          :       STRING  { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); }
                 ;
 
 OptMapName      :       MapName { $$ = $1; }
@@ -779,6 +811,7 @@ parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
         .scanner = scanner,
         .ctx = ctx,
         .rtrn = NULL,
+        .more_maps = false,
     };
 
     /*
@@ -816,5 +849,11 @@ parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
         return NULL;
     }
 
+    if (first)
+        log_vrb(ctx, 5,
+                "No map in include statement, but \"%s\" contains several; "
+                "Using first defined map, \"%s\"\n",
+                scanner->file_name, first->name);
+
     return first;
 }