Browse Source

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>
main
David Gibson 11 years ago
parent
commit
b82b977614
  1. 30
      dtc-lexer.l
  2. 42
      dtc-parser.y

30
dtc-lexer.l

@ -40,6 +40,7 @@ LINECOMMENT "//".*\n
#include "dtc-parser.tab.h" #include "dtc-parser.tab.h"


YYLTYPE yylloc; YYLTYPE yylloc;
extern bool treesource_error;


/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
#define YY_USER_ACTION \ #define YY_USER_ACTION \
@ -62,6 +63,7 @@ static int dts_version = 1;


static void push_input_file(const char *filename); static void push_input_file(const char *filename);
static bool pop_input_file(void); 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)? { <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
yylval.literal = xstrdup(yytext); char *e;
DPRINT("Literal: '%s'\n", yylval.literal); 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; return DT_LITERAL;
} }


@ -248,3 +263,14 @@ static bool pop_input_file(void)


return true; 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;
}

42
dtc-parser.y

@ -33,7 +33,6 @@ extern void yyerror(char const *s);
extern struct boot_info *the_boot_info; extern struct boot_info *the_boot_info;
extern bool treesource_error; 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); 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_PROP
%token DT_DEL_NODE %token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME %token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL %token <integer> DT_LITERAL
%token <literal> DT_CHAR_LITERAL %token <literal> DT_CHAR_LITERAL
%token <cbase> DT_BASE %token <cbase> DT_BASE
%token <byte> DT_BYTE %token <byte> DT_BYTE
@ -274,18 +273,20 @@ propdataprefix:
arrayprefix: arrayprefix:
DT_BITS DT_LITERAL '<' DT_BITS DT_LITERAL '<'
{ {
$$.data = empty_data; unsigned long long bits;
$$.bits = eval_literal($2, 0, 7);
bits = $2;


if (($$.bits != 8) && if ((bits != 8) && (bits != 16) &&
($$.bits != 16) && (bits != 32) && (bits != 64))
($$.bits != 32) &&
($$.bits != 64))
{ {
print_error("Only 8, 16, 32 and 64-bit elements" print_error("Only 8, 16, 32 and 64-bit elements"
" are currently supported"); " are currently supported");
$$.bits = 32; bits = 32;
} }

$$.data = empty_data;
$$.bits = bits;
} }
| '<' | '<'
{ {
@ -334,9 +335,6 @@ arrayprefix:


integer_prim: integer_prim:
DT_LITERAL DT_LITERAL
{
$$ = eval_literal($1, 0, 64);
}
| DT_CHAR_LITERAL | DT_CHAR_LITERAL
{ {
$$ = eval_char_literal($1); $$ = eval_char_literal($1);
@ -485,26 +483,6 @@ void yyerror(char const *s) {
print_error("%s", 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) static unsigned char eval_char_literal(const char *s)
{ {
int i = 1; int i = 1;

Loading…
Cancel
Save