diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2014-01-03 20:00:01 +1100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2014-01-03 20:00:01 +1100 |
commit | b82b9776140a077db723f13832afd7e279a45184 (patch) | |
tree | 5d7f9a3ba5b9f17af44be6a4893a0dcbade48086 | |
parent | 0e2d3992258ff4129a8c0f79b660e92994411684 (diff) | |
download | device-tree-compiler-b82b9776140a077db723f13832afd7e279a45184.tar.gz |
Move integer literal processing back to the lexer
At the moment integer literals are passed from the lexer to the parser as
a string, where it's evaluated into an integer by eval_literal(). That
strange approach happened because we needed to know whether we were
processing dts-v0 or dts-v1 - only known at the parser level - to know
how to interpret the literal properly.
dts-v0 support has been gone for some time now, and the base and bits
parameters to eval_literal() are essentially useless.
So, clean things up by moving the literal interpretation back to the lexer.
This also introduces a new lexical_error() function to report malformed
literals and set the treesource_error flag so that they'll cause a parse
failure at the top level.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | dtc-lexer.l | 30 | ||||
-rw-r--r-- | dtc-parser.y | 42 |
2 files changed, 38 insertions, 34 deletions
diff --git a/dtc-lexer.l b/dtc-lexer.l index 0cd7e67..ba5d150 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -40,6 +40,7 @@ LINECOMMENT "//".*\n #include "dtc-parser.tab.h" YYLTYPE yylloc; +extern bool treesource_error; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ #define YY_USER_ACTION \ @@ -62,6 +63,7 @@ static int dts_version = 1; static void push_input_file(const char *filename); static bool pop_input_file(void); +static void lexical_error(const char *fmt, ...); %} %% @@ -146,8 +148,21 @@ static bool pop_input_file(void); } <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { - yylval.literal = xstrdup(yytext); - DPRINT("Literal: '%s'\n", yylval.literal); + char *e; + DPRINT("Integer Literal: '%s'\n", yytext); + + errno = 0; + yylval.integer = strtoull(yytext, &e, 0); + + assert(!(*e) || !e[strspn(e, "UL")]); + + if (errno == ERANGE) + lexical_error("Integer literal '%s' out of range", + yytext); + else + /* ERANGE is the only strtoull error triggerable + * by strings matching the pattern */ + assert(errno == 0); return DT_LITERAL; } @@ -248,3 +263,14 @@ static bool pop_input_file(void) return true; } + +static void lexical_error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + srcpos_verror(&yylloc, "Lexical error", fmt, ap); + va_end(ap); + + treesource_error = true; +} diff --git a/dtc-parser.y b/dtc-parser.y index 2bcef1b..0ce0815 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -33,7 +33,6 @@ extern void yyerror(char const *s); extern struct boot_info *the_boot_info; extern bool treesource_error; -static unsigned long long eval_literal(const char *s, int base, int bits); static unsigned char eval_char_literal(const char *s); %} @@ -65,7 +64,7 @@ static unsigned char eval_char_literal(const char *s); %token DT_DEL_PROP %token DT_DEL_NODE %token <propnodename> DT_PROPNODENAME -%token <literal> DT_LITERAL +%token <integer> DT_LITERAL %token <literal> DT_CHAR_LITERAL %token <cbase> DT_BASE %token <byte> DT_BYTE @@ -274,18 +273,20 @@ propdataprefix: arrayprefix: DT_BITS DT_LITERAL '<' { - $$.data = empty_data; - $$.bits = eval_literal($2, 0, 7); + unsigned long long bits; + + bits = $2; - if (($$.bits != 8) && - ($$.bits != 16) && - ($$.bits != 32) && - ($$.bits != 64)) + if ((bits != 8) && (bits != 16) && + (bits != 32) && (bits != 64)) { print_error("Only 8, 16, 32 and 64-bit elements" " are currently supported"); - $$.bits = 32; + bits = 32; } + + $$.data = empty_data; + $$.bits = bits; } | '<' { @@ -334,9 +335,6 @@ arrayprefix: integer_prim: DT_LITERAL - { - $$ = eval_literal($1, 0, 64); - } | DT_CHAR_LITERAL { $$ = eval_char_literal($1); @@ -485,26 +483,6 @@ void yyerror(char const *s) { print_error("%s", s); } -static unsigned long long eval_literal(const char *s, int base, int bits) -{ - unsigned long long val; - char *e; - - errno = 0; - val = strtoull(s, &e, base); - if (*e) { - size_t uls = strspn(e, "UL"); - if (e[uls]) - print_error("bad characters in literal"); - } - if ((errno == ERANGE) - || ((bits < 64) && (val >= (1ULL << bits)))) - print_error("literal out of range"); - else if (errno != 0) - print_error("bad literal"); - return val; -} - static unsigned char eval_char_literal(const char *s) { int i = 1; |