diff options
-rw-r--r-- | data.c | 21 | ||||
-rw-r--r-- | dtc-lexer.l | 21 | ||||
-rw-r--r-- | dtc-parser.y | 16 | ||||
-rw-r--r-- | dtc.h | 1 |
4 files changed, 51 insertions, 8 deletions
@@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "dtc-parser.tab.h" void fixup_free(struct fixup *f) { @@ -224,6 +225,26 @@ struct data data_merge(struct data d1, struct data d2) return d; } +/* + * Convert a string representation of a numberic cell + * in the given base into a cell. + */ +cell_t data_convert_cell(char *s, unsigned int base) +{ + cell_t c; + extern YYLTYPE yylloc; + + c = strtoul(s, NULL, base); + if (errno == EINVAL || errno == ERANGE) { + fprintf(stderr, + "Line %d: Invalid cell value '%s'; %d assumed\n", + yylloc.first_line, s, c); + } + + return c; +} + + struct data data_append_cell(struct data d, cell_t word) { cell_t beword = cpu_to_be32(word); diff --git a/dtc-lexer.l b/dtc-lexer.l index 6146bad..93f3268 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -83,15 +83,24 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) BEGIN(INITIAL); return ';'; } +<CELLDATA>[bodh]# { + yylloc.first_line = yylineno; + if (*yytext == 'b') + yylval.cbase = 2; + else if (*yytext == 'o') + yylval.cbase = 8; + else if (*yytext == 'd') + yylval.cbase = 10; + else + yylval.cbase = 16; + DPRINT("Base: %d\n", yylval.cbase); + return DT_BASE; + } <CELLDATA>[0-9a-fA-F]+ { yylloc.first_line = yylineno; - if (yyleng > 2*sizeof(yylval.cval)) { - fprintf(stderr, - "Cell value %s too long\n", yytext); - } - yylval.cval = strtoul(yytext, NULL, 16); - DPRINT("Cell: %x\n", yylval.cval); + yylval.str = strdup(yytext); + DPRINT("Cell: '%s'\n", yylval.str); return DT_CELL; } diff --git a/dtc-parser.y b/dtc-parser.y index bd725fe..992fdb1 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -33,6 +33,7 @@ extern struct boot_info *the_boot_info; %union { cell_t cval; + unsigned int cbase; u8 byte; char *str; struct data data; @@ -50,7 +51,8 @@ extern struct boot_info *the_boot_info; %token <addr> DT_ADDR %token <str> DT_PROPNAME %token <str> DT_NODENAME -%token <cval> DT_CELL +%token <cbase> DT_BASE +%token <str> DT_CELL %token <byte> DT_BYTE %token <data> DT_STRING %token <str> DT_UNIT @@ -61,6 +63,7 @@ extern struct boot_info *the_boot_info; %type <data> propdataprefix %type <re> memreserve %type <re> memreserves +%type <cbase> opt_cell_base %type <data> celllist %type <data> bytestring %type <prop> propdef @@ -133,7 +136,16 @@ propdataprefix: propdata ',' { $$ = $1; } | /* empty */ { $$ = empty_data; } ; -celllist: celllist DT_CELL { $$ = data_append_cell($1, $2); } +opt_cell_base: + /* empty */ + { $$ = 16; } + | DT_BASE + ; + +celllist: celllist opt_cell_base DT_CELL { + $$ = data_append_cell($1, + data_convert_cell($3, $2)); + } | celllist DT_REF { $$ = data_append_cell(data_add_fixup($1, $2), -1); } @@ -118,6 +118,7 @@ struct data data_copy_mem(char *mem, int len); struct data data_copy_escape_string(char *s, int len); struct data data_copy_file(FILE *f, size_t len); +cell_t data_convert_cell(char *s, unsigned int base); struct data data_append_data(struct data d, void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); |