diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2014-02-16 22:39:58 +1100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2014-03-03 10:51:50 +1100 |
commit | e7f37606f984b3c7663624e5573da18a1d4529e0 (patch) | |
tree | 865e4b8f70e5c2a463248512bd99d3d38a7d4e01 | |
parent | 2168f9d921e1b11a9a8b3e825772e60a5930203a (diff) | |
download | device-tree-compiler-e7f37606f984b3c7663624e5573da18a1d4529e0.tar.gz |
Integrate /incbin/ with expanded expressions
Implement /incbin/ as a new type of bytestring expression operator. This
delays the evaluation of the /incbin/'s parameters until the evaluation
of the /incbin/ itself.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | dtc-parser.y | 56 | ||||
-rw-r--r-- | dtc.h | 4 | ||||
-rw-r--r-- | expression.c | 41 |
3 files changed, 60 insertions, 41 deletions
diff --git a/dtc-parser.y b/dtc-parser.y index e4df947..07cb067 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -35,7 +35,6 @@ extern struct boot_info *the_boot_info; extern bool treesource_error; static uint64_t expr_int(struct expression *expr); -static const char *expr_str(struct expression *expr); static struct data expr_bytestring(struct expression *expr); #define UNOP(loc, op, a) (expression_##op(&loc, (a))) @@ -91,6 +90,7 @@ static struct data expr_bytestring(struct expression *expr); %type <node> subnode %type <nodelist> subnodes +%type <expr> expr_incbin %type <expr> expr_prim %type <expr> expr_unary %type <expr> expr_mul @@ -224,34 +224,6 @@ propdata: { $$ = data_add_marker($1, REF_PATH, $2); } - | propdataprefix DT_INCBIN '(' expr_prim ',' expr_prim ',' expr_prim ')' - { - const char *filename = expr_str($4); - FILE *f = srcfile_relative_open(filename, NULL); - off_t offset = expr_int($6); - struct data d; - - if (offset != 0) - if (fseek(f, offset, SEEK_SET) != 0) - die("Couldn't seek to offset %llu in \"%s\": %s", - (unsigned long long)offset, filename, - strerror(errno)); - - d = data_copy_file(f, expr_int($8)); - - $$ = data_merge($1, d); - fclose(f); - } - | propdataprefix DT_INCBIN '(' DT_STRING ')' - { - FILE *f = srcfile_relative_open($4.val, NULL); - struct data d = empty_data; - - d = data_copy_file(f, -1); - - $$ = data_merge($1, d); - fclose(f); - } | propdata DT_LABEL { $$ = data_add_marker($1, LABEL, $2); @@ -336,6 +308,19 @@ arrayprefix: } ; +expr_incbin: + DT_INCBIN '(' expr_conditional ',' expr_conditional ',' expr_conditional ')' + { + $$ = expression_incbin(&@$, $3, $5, $7); + } + | DT_INCBIN '(' expr_conditional ')' + { + $$ = expression_incbin(&@$, $3, + expression_integer_constant(NULL, 0), + expression_integer_constant(NULL, -1)); + } + ; + expr_prim: DT_LITERAL { $$ = expression_integer_constant(&yylloc, $1); } | DT_CHAR_LITERAL { $$ = expression_integer_constant(&yylloc, $1); } @@ -347,6 +332,7 @@ expr_prim: { $$ = expression_bytestring_constant(&@2, $2); } + | expr_incbin | '(' expr ')' { $$ = $2; @@ -496,18 +482,6 @@ static uint64_t expr_int(struct expression *expr) return v.value.integer; } -static const char *expr_str(struct expression *expr) -{ - struct expression_value v = expression_evaluate(expr, EXPR_STRING); - - if (v.type == EXPR_VOID) { - treesource_error = true; - return ""; - } - assert(v.type == EXPR_STRING); - return v.value.d.val; -} - static struct data expr_bytestring(struct expression *expr) { struct expression_value v = expression_evaluate(expr, EXPR_BYTESTRING); @@ -305,6 +305,10 @@ struct expression *expression_conditional(struct srcpos *pos, struct expression *, struct expression *, struct expression *); +struct expression *expression_incbin(struct srcpos *loc, + struct expression *file, + struct expression *off, + struct expression *len); /* Boot info (tree plus memreserve information */ diff --git a/expression.c b/expression.c index 4ecd84a..49bc8b0 100644 --- a/expression.c +++ b/expression.c @@ -339,3 +339,44 @@ struct expression *expression_conditional(struct srcpos *loc, { return expression_build(loc, &op_conditional, arg1, arg2, arg3); } + + +static struct expression_value op_eval_incbin(struct expression *expr, + enum expr_type context) +{ + struct data filename; + uint64_t offset, len; + FILE *f; + struct expression_value v = { + .type = EXPR_BYTESTRING, + }; + + EVALUATE_STR(filename, expr->arg[0]); + EVALUATE_INT(offset, expr->arg[1]); + EVALUATE_INT(len, expr->arg[2]); + + f = srcfile_relative_open(filename.val, NULL); + + if (offset != 0) + if (fseek(f, offset, SEEK_SET) != 0) + die("Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)offset, filename.val, + strerror(errno)); + + v.value.d = data_copy_file(f, len); + + fclose(f); + return v; +} +static struct operator op_incbin = { + .name = "/incbin/", + .nargs = 3, + .evaluate = op_eval_incbin, +}; +struct expression *expression_incbin(struct srcpos *loc, + struct expression *file, + struct expression *off, + struct expression *len) +{ + return expression_build(loc, &op_incbin, file, off, len); +} |