*/
%{
+#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;
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
#define param_scanner param->scanner
%}
-%pure-parser
+%define api.pure
%lex-param { struct scanner *param_scanner }
%parse-param { struct parser_param *param }
%start XkbFile
%union {
- int ival;
int64_t num;
enum xkb_file_type file_type;
char *str;
%type <num> INTEGER FLOAT
%type <str> IDENT STRING
%type <atom> KEYNAME
-%type <num> KeyCode
-%type <ival> Number Integer Float SignedNumber DoodadType
+%type <num> KeyCode Number Integer Float SignedNumber DoodadType
%type <merge> MergeMode OptMergeMode
%type <file_type> XkbCompositeType FileType
%type <mapFlags> Flag Flags OptFlags
DeclList : DeclList Decl
{
- /*
- * TODO: This is needed because of VModDecl, which
- * is a list and is "inlined" into the DeclList.
- * Should change to avoid the O(N)-append behavior,
- * like we do in the other lists.
- */
if ($2) {
- if (!$1.head)
- $$.head = $2;
- else
- $$.head = $1.head;
- if (!$1.last)
- $$.last = $2;
- else
- $$.last = $1.last->next = $2;
- while ($$.last->next)
- $$.last = $$.last->next;
+ 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; }
$2->merge = $1;
$$ = (ParseCommon *) $2;
}
- | OptMergeMode VModDecl
- {
- for (VModDef *vmod = $2.head; vmod; vmod = (VModDef *) vmod->common.next)
- vmod->merge = $1;
- $$ = (ParseCommon *) $2.head;
- }
+ /* OptMergeMode VModDecl - see above. */
| OptMergeMode InterpretDecl
{
$2->merge = $1;
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;
}
}