Browse Source

dtc: Simplify lexing/parsing of literals vs. node/property names

The current scheme of having CELLDATA and MEMRESERVE states to
recognize hex literals instead of node or property names is
arse-backwards.  The patch switches things around so that literals are
lexed in normal states, and property/node names are only recognized in
the special PROPNODENAME state, which is only entered after a { or a
;, and is left as soon as we scan a property/node name or a keyword.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
main
David Gibson 17 years ago committed by Jon Loeliger
parent
commit
9ed27a2aac
  1. 109
      dtc-lexer.l
  2. 124
      dtc-parser.y

109
dtc-lexer.l

@ -21,9 +21,8 @@
%option noyywrap nounput yylineno %option noyywrap nounput yylineno


%x INCLUDE %x INCLUDE
%x CELLDATA
%x BYTESTRING %x BYTESTRING
%x MEMRESERVE %x PROPNODENAME


PROPCHAR [a-zA-Z0-9,._+*#?-] PROPCHAR [a-zA-Z0-9,._+*#?-]
UNITCHAR [0-9a-f,] UNITCHAR [0-9a-f,]
@ -51,7 +50,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])


%% %%


"/include/" BEGIN(INCLUDE); <*>"/include/" BEGIN(INCLUDE);


<INCLUDE>\"[^"\n]*\" { <INCLUDE>\"[^"\n]*\" {
yytext[strlen(yytext) - 1] = 0; yytext[strlen(yytext) - 1] = 0;
@ -63,13 +62,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
} }




<<EOF>> { <*><<EOF>> {
if (!pop_input_file()) { if (!pop_input_file()) {
yyterminate(); yyterminate();
} }
} }


\"([^\\"]|\\.)*\" { <*>\"([^\\"]|\\.)*\" {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("String: %s\n", yytext); DPRINT("String: %s\n", yytext);
@ -79,45 +78,24 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
return DT_STRING; return DT_STRING;
} }


"/memreserve/" { <*>"/memreserve/" {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n"); DPRINT("Keyword: /memreserve/\n");
BEGIN(MEMRESERVE);
return DT_MEMRESERVE;
}

<MEMRESERVE>[0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
if (yyleng > 2*sizeof(yylval.addr)) {
fprintf(stderr, "Address value %s too large\n",
yytext);
}
yylval.addr = (u64) strtoull(yytext, NULL, 16);
DPRINT("Addr: %llx\n",
(unsigned long long)yylval.addr);
return DT_ADDR;
}

<MEMRESERVE>";" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("/MEMRESERVE\n");
BEGIN(INITIAL); BEGIN(INITIAL);
return ';'; return DT_MEMRESERVE;
} }


<*>[a-zA-Z_][a-zA-Z0-9_]*: { <*>[a-zA-Z_][a-zA-Z0-9_]*: {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext); DPRINT("Label: %s\n", yytext);
yylval.str = strdup(yytext); yylval.labelref = strdup(yytext);
yylval.str[yyleng-1] = '\0'; yylval.labelref[yyleng-1] = '\0';
return DT_LABEL; return DT_LABEL;
} }


<CELLDATA>[bodh]# { [bodh]# {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
if (*yytext == 'b') if (*yytext == 'b')
@ -132,27 +110,19 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
return DT_BASE; return DT_BASE;
} }


<CELLDATA>[0-9a-fA-F]+ { [0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
yylval.str = strdup(yytext);
DPRINT("Cell: '%s'\n", yylval.str);
return DT_CELL;
}

<CELLDATA>">" {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("/CELLDATA\n"); yylval.literal = strdup(yytext);
BEGIN(INITIAL); DPRINT("Literal: '%s'\n", yylval.literal);
return '>'; return DT_LITERAL;
} }


<CELLDATA>\&{REFCHAR}* { \&{REFCHAR}* {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1); DPRINT("Ref: %s\n", yytext+1);
yylval.str = strdup(yytext+1); yylval.labelref = strdup(yytext+1);
return DT_REF; return DT_REF;
} }


@ -172,30 +142,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
return ']'; return ']';
} }


, { /* Technically this is a valid property name, <PROPNODENAME>{PROPCHAR}+(@{UNITCHAR}+)? {
but we'd rather use it as punctuation, so detect it
here in preference */
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], DPRINT("PropNodeName: %s\n", yytext);
(unsigned)yytext[0]); yylval.propnodename = strdup(yytext);
return yytext[0]; BEGIN(INITIAL);
} return DT_PROPNODENAME;

{PROPCHAR}+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("PropName: %s\n", yytext);
yylval.str = strdup(yytext);
return DT_PROPNAME;
}

{PROPCHAR}+(@{UNITCHAR}+)? {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("NodeName: %s\n", yytext);
yylval.str = strdup(yytext);
return DT_NODENAME;
} }




@ -213,21 +166,17 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
<*>. { <*>. {
yylloc.filenum = srcpos_filenum; yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno; yylloc.first_line = yylineno;
switch (yytext[0]) { if (yytext[0] == '[') {
case '<': DPRINT("<BYTESTRING>\n");
DPRINT("CELLDATA\n"); BEGIN(BYTESTRING);
BEGIN(CELLDATA); }
break; if ((yytext[0] == '{')
case '[': || (yytext[0] == ';')) {
DPRINT("BYTESTRING\n"); DPRINT("<PROPNODENAME>\n");
BEGIN(BYTESTRING); BEGIN(PROPNODENAME);
break; }
default:

DPRINT("Char: %c (\\x%02x)\n", yytext[0], DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]); (unsigned)yytext[0]);
break;
}


return yytext[0]; return yytext[0];
} }

124
dtc-parser.y

@ -25,45 +25,46 @@
#include "srcpos.h" #include "srcpos.h"


int yylex(void); int yylex(void);
cell_t cell_from_string(char *s, unsigned int base); unsigned long long eval_literal(const char *s, int base, int bits);


extern struct boot_info *the_boot_info; extern struct boot_info *the_boot_info;


%} %}


%union { %union {
cell_t cval; char *propnodename;
char *literal;
char *labelref;
unsigned int cbase; unsigned int cbase;
u8 byte; u8 byte;
char *str;
struct data data; struct data data;

u64 addr;
cell_t cell;
struct property *prop; struct property *prop;
struct property *proplist; struct property *proplist;
struct node *node; struct node *node;
struct node *nodelist; struct node *nodelist;
int datalen;
int hexlen;
u64 addr;
struct reserve_info *re; struct reserve_info *re;
} }


%token DT_MEMRESERVE %token DT_MEMRESERVE
%token <addr> DT_ADDR %token <propnodename> DT_PROPNODENAME
%token <str> DT_PROPNAME %token <literal> DT_LITERAL
%token <str> DT_NODENAME
%token <cbase> DT_BASE %token <cbase> DT_BASE
%token <str> DT_CELL
%token <byte> DT_BYTE %token <byte> DT_BYTE
%token <data> DT_STRING %token <data> DT_STRING
%token <str> DT_LABEL %token <labelref> DT_LABEL
%token <str> DT_REF %token <labelref> DT_REF


%type <data> propdata %type <data> propdata
%type <data> propdataprefix %type <data> propdataprefix
%type <re> memreserve %type <re> memreserve
%type <re> memreserves %type <re> memreserves
%type <cbase> opt_cell_base %type <addr> addr
%type <data> celllist %type <data> celllist
%type <cbase> cellbase
%type <cell> cellval
%type <data> bytestring %type <data> bytestring
%type <prop> propdef %type <prop> propdef
%type <proplist> proplist %type <proplist> proplist
@ -72,8 +73,7 @@ extern struct boot_info *the_boot_info;
%type <node> nodedef %type <node> nodedef
%type <node> subnode %type <node> subnode
%type <nodelist> subnodes %type <nodelist> subnodes
%type <str> label %type <labelref> label
%type <str> nodename


%% %%


@ -96,16 +96,23 @@ memreserves:
; ;


memreserve: memreserve:
label DT_MEMRESERVE DT_ADDR DT_ADDR ';' label DT_MEMRESERVE addr addr ';'
{ {
$$ = build_reserve_entry($3, $4, $1); $$ = build_reserve_entry($3, $4, $1);
} }
| label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' | label DT_MEMRESERVE addr '-' addr ';'
{ {
$$ = build_reserve_entry($3, $5 - $3 + 1, $1); $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
} }
; ;


addr:
DT_LITERAL
{
$$ = eval_literal($1, 16, 64);
}
;

devicetree: devicetree:
'/' nodedef '/' nodedef
{ {
@ -132,11 +139,11 @@ proplist:
; ;


propdef: propdef:
label DT_PROPNAME '=' propdata ';' label DT_PROPNODENAME '=' propdata ';'
{ {
$$ = build_property($2, $4, $1); $$ = build_property($2, $4, $1);
} }
| label DT_PROPNAME ';' | label DT_PROPNODENAME ';'
{ {
$$ = build_property($2, empty_data, $1); $$ = build_property($2, empty_data, $1);
} }
@ -176,23 +183,14 @@ propdataprefix:
} }
; ;


opt_cell_base:
/* empty */
{
$$ = 16;
}
| DT_BASE
;

celllist: celllist:
/* empty */ /* empty */
{ {
$$ = empty_data; $$ = empty_data;
} }
| celllist opt_cell_base DT_CELL | celllist cellval
{ {
$$ = data_append_cell($1, $$ = data_append_cell($1, $2);
cell_from_string($3, $2));
} }
| celllist DT_REF | celllist DT_REF
{ {
@ -204,6 +202,21 @@ celllist:
} }
; ;


cellbase:
/* empty */
{
$$ = 16;
}
| DT_BASE
;

cellval:
cellbase DT_LITERAL
{
$$ = eval_literal($2, $1, 32);
}
;

bytestring: bytestring:
/* empty */ /* empty */
{ {
@ -231,23 +244,12 @@ subnodes:
; ;


subnode: subnode:
label nodename nodedef label DT_PROPNODENAME nodedef
{ {
$$ = name_node($3, $2, $1); $$ = name_node($3, $2, $1);
} }
; ;


nodename:
DT_NODENAME
{
$$ = $1;
}
| DT_PROPNAME
{
$$ = $1;
}
;

label: label:
/* empty */ /* empty */
{ {
@ -272,33 +274,19 @@ void yyerror (char const *s)
fname, yylloc.first_line, s); fname, yylloc.first_line, s);
} }



unsigned long long eval_literal(const char *s, int base, int bits)
/*
* Convert a string representation of a numeric cell
* in the given base into a cell.
*
* FIXME: should these specification errors be fatal instead?
*/

cell_t cell_from_string(char *s, unsigned int base)
{ {
cell_t c; unsigned long long val;
char *e; char *e;


c = strtoul(s, &e, base); errno = 0;
if (*e) { val = strtoull(s, &e, base);
fprintf(stderr, if (*e)
"Line %d: Invalid cell value '%s' : " yyerror("bad characters in literal");
"%c is not a base %d digit; %d assumed\n", else if ((errno == ERANGE)
yylloc.first_line, s, *e, base, c); || ((bits < 64) && (val >= (1ULL << bits))))
} yyerror("literal out of range");

else if (errno != 0)
if (errno == EINVAL || errno == ERANGE) { yyerror("bad literal");
fprintf(stderr, return val;
"Line %d: Invalid cell value '%s'; %d assumed\n",
yylloc.first_line, s, c);
errno = 0;
}

return c;
} }

Loading…
Cancel
Save