diff --git a/dtc-lexer.l b/dtc-lexer.l index 278a96e..677abe4 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -21,9 +21,8 @@ %option noyywrap nounput yylineno %x INCLUDE -%x CELLDATA %x BYTESTRING -%x MEMRESERVE +%x PROPNODENAME PROPCHAR [a-zA-Z0-9,._+*#?-] UNITCHAR [0-9a-f,] @@ -51,7 +50,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %% -"/include/" BEGIN(INCLUDE); +<*>"/include/" BEGIN(INCLUDE); \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; @@ -63,13 +62,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } -<> { +<*><> { if (!pop_input_file()) { yyterminate(); } } -\"([^\\"]|\\.)*\" { +<*>\"([^\\"]|\\.)*\" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); @@ -79,45 +78,24 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_STRING; } -"/memreserve/" { +<*>"/memreserve/" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); - BEGIN(MEMRESERVE); - return DT_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; - } - -";" { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("/MEMRESERVE\n"); BEGIN(INITIAL); - return ';'; + return DT_MEMRESERVE; } <*>[a-zA-Z_][a-zA-Z0-9_]*: { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); - yylval.str = strdup(yytext); - yylval.str[yyleng-1] = '\0'; + yylval.labelref = strdup(yytext); + yylval.labelref[yyleng-1] = '\0'; return DT_LABEL; } -[bodh]# { +[bodh]# { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (*yytext == 'b') @@ -132,27 +110,19 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_BASE; } -[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; - } - -">" { +[0-9a-fA-F]+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - DPRINT("/CELLDATA\n"); - BEGIN(INITIAL); - return '>'; + yylval.literal = strdup(yytext); + DPRINT("Literal: '%s'\n", yylval.literal); + return DT_LITERAL; } -\&{REFCHAR}* { +\&{REFCHAR}* { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); - yylval.str = strdup(yytext+1); + yylval.labelref = strdup(yytext+1); return DT_REF; } @@ -172,30 +142,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return ']'; } -, { /* Technically this is a valid property name, - but we'd rather use it as punctuation, so detect it - here in preference */ +{PROPCHAR}+(@{UNITCHAR}+)? { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], - (unsigned)yytext[0]); - return yytext[0]; - } - -{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; + DPRINT("PropNodeName: %s\n", yytext); + yylval.propnodename = strdup(yytext); + BEGIN(INITIAL); + return DT_PROPNODENAME; } @@ -213,21 +166,17 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) <*>. { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - switch (yytext[0]) { - case '<': - DPRINT("CELLDATA\n"); - BEGIN(CELLDATA); - break; - case '[': - DPRINT("BYTESTRING\n"); - BEGIN(BYTESTRING); - break; - default: - + if (yytext[0] == '[') { + DPRINT("\n"); + BEGIN(BYTESTRING); + } + if ((yytext[0] == '{') + || (yytext[0] == ';')) { + DPRINT("\n"); + BEGIN(PROPNODENAME); + } DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); - break; - } return yytext[0]; } diff --git a/dtc-parser.y b/dtc-parser.y index 4853794..5ac3db7 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -25,45 +25,46 @@ #include "srcpos.h" 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; %} %union { - cell_t cval; + char *propnodename; + char *literal; + char *labelref; unsigned int cbase; u8 byte; - char *str; struct data data; + + u64 addr; + cell_t cell; struct property *prop; struct property *proplist; struct node *node; struct node *nodelist; - int datalen; - int hexlen; - u64 addr; struct reserve_info *re; } %token DT_MEMRESERVE -%token DT_ADDR -%token DT_PROPNAME -%token DT_NODENAME +%token DT_PROPNODENAME +%token DT_LITERAL %token DT_BASE -%token DT_CELL %token DT_BYTE %token DT_STRING -%token DT_LABEL -%token DT_REF +%token DT_LABEL +%token DT_REF %type propdata %type propdataprefix %type memreserve %type memreserves -%type opt_cell_base +%type addr %type celllist +%type cellbase +%type cellval %type bytestring %type propdef %type proplist @@ -72,8 +73,7 @@ extern struct boot_info *the_boot_info; %type nodedef %type subnode %type subnodes -%type label -%type nodename +%type label %% @@ -96,16 +96,23 @@ memreserves: ; memreserve: - label DT_MEMRESERVE DT_ADDR DT_ADDR ';' + label DT_MEMRESERVE addr addr ';' { $$ = 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); } ; +addr: + DT_LITERAL + { + $$ = eval_literal($1, 16, 64); + } + ; + devicetree: '/' nodedef { @@ -132,11 +139,11 @@ proplist: ; propdef: - label DT_PROPNAME '=' propdata ';' + label DT_PROPNODENAME '=' propdata ';' { $$ = build_property($2, $4, $1); } - | label DT_PROPNAME ';' + | label DT_PROPNODENAME ';' { $$ = build_property($2, empty_data, $1); } @@ -176,23 +183,14 @@ propdataprefix: } ; -opt_cell_base: - /* empty */ - { - $$ = 16; - } - | DT_BASE - ; - celllist: /* empty */ { $$ = empty_data; } - | celllist opt_cell_base DT_CELL + | celllist cellval { - $$ = data_append_cell($1, - cell_from_string($3, $2)); + $$ = data_append_cell($1, $2); } | celllist DT_REF { @@ -204,6 +202,21 @@ celllist: } ; +cellbase: + /* empty */ + { + $$ = 16; + } + | DT_BASE + ; + +cellval: + cellbase DT_LITERAL + { + $$ = eval_literal($2, $1, 32); + } + ; + bytestring: /* empty */ { @@ -231,23 +244,12 @@ subnodes: ; subnode: - label nodename nodedef + label DT_PROPNODENAME nodedef { $$ = name_node($3, $2, $1); } ; -nodename: - DT_NODENAME - { - $$ = $1; - } - | DT_PROPNAME - { - $$ = $1; - } - ; - label: /* empty */ { @@ -272,33 +274,19 @@ void yyerror (char const *s) fname, yylloc.first_line, s); } - -/* - * 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) +unsigned long long eval_literal(const char *s, int base, int bits) { - cell_t c; + unsigned long long val; char *e; - c = strtoul(s, &e, base); - if (*e) { - fprintf(stderr, - "Line %d: Invalid cell value '%s' : " - "%c is not a base %d digit; %d assumed\n", - yylloc.first_line, s, *e, base, c); - } - - if (errno == EINVAL || errno == ERANGE) { - fprintf(stderr, - "Line %d: Invalid cell value '%s'; %d assumed\n", - yylloc.first_line, s, c); - errno = 0; - } - - return c; + errno = 0; + val = strtoull(s, &e, base); + if (*e) + yyerror("bad characters in literal"); + else if ((errno == ERANGE) + || ((bits < 64) && (val >= (1ULL << bits)))) + yyerror("literal out of range"); + else if (errno != 0) + yyerror("bad literal"); + return val; }