[U-Boot] [PATCH V2 05/21] imximage: add expression evaluation

Stefano Babic
2012-09-23T14:56:01Z

On 22/09/2012 04:39, Troy Kisky wrote:
> Basic expressions with order precedence is
> now supported.
> ie. (----3 + ((1+2*3)/--2 + --5 *(8/4))) is 16.
>
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---

Hi Troy,

> tools/imximage.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 162 insertions(+), 10 deletions(-)
>
> diff --git a/tools/imximage.c b/tools/imximage.c
> index 1e120354..2c5a622 100644

I have some general considerations. First, if you plan to add support
for expression evaluation, this feature should be available generally
for mkimage, that means also other processors / architecture can profit
of it. It should be moved away from imximage.c code.

Then, you want also let that the preprocesso can parse the imximage
code. I can imagine that in such terms it could be then possible to
define in imximage.cfg something like:

#define DDR_VAL (1 <<17 | 3 << 7)
#define ADDRESS 0x0x53something

DATA 4 ADDRESS DDR_VAL

Else, why do we need the power of C preprocessor ?

If this is true, can you explain us which is the use case using the C
preprocessor and which is the one for the expression evaluator ? And why
do we need both ?

> --- a/tools/imximage.c
> +++ b/tools/imximage.c
> @@ -380,20 +380,172 @@ char *grab_token(char *dest, int size, char *src)
> return src;
> }
>
> +char precedence[] = {
> + /* ( + - * / & ^ | ) */
> + 0, 2, 2, 1, 1, 3, 4, 5, 6
> +};
> +char unary_operations[] = "(+-";
> +char binary_operations[] = " +-*/&^|)";
> +
> +uint32_t do_func(uint32_t val1, uint32_t val2, int op)
> +{
> + switch (op) {
> + case 1:
> + return val1 + val2;
> + case 2:
> + return val1 - val2;
> + case 3:
> + return val1 * val2;
> + case 4:
> + return val1 / val2;
> + case 5:
> + return val1 & val2;
> + case 6:
> + return val1 ^ val2;
> + case 7:
> + return val1 | val2;
> + }
> + fprintf(stderr, "Error: in func %s: val1=%d val2=%d op = %d\n",
> + __func__, val1, val2, op);
> + exit(EXIT_FAILURE);
> +}
> +
> +int find_op(char c, char *p)
> +{
> + int i;
> + for (i = 0; ; i++) {
> + if (c == p[i])
> + return i;
> + if (!p[i])
> + break;
> + }
> + return -1;
> +}
> +
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +
> static uint32_t get_cfg_value(struct data_src *ds, uint32_t *pval)
> {
> char *endptr;
> - uint32_t value;
> + int op_i = 0;
> + int val_i = 0;
> + unsigned char op[16];
> + uint32_t val[16];
> + int unary = 1;
> + char *p;
>
> - if (skip_separators(ds))
> - return -1;
> - errno = 0;
> - value = strtoul(ds->p, &endptr, 16);
> - if (errno || (ds->p == endptr))
> - return -1;
> - *pval = value;
> - ds->p = endptr;
> - return 0;
> + p = ds->p;
> + for (;;) {
> + char c;
> + int i, j;
> + char *ops = unary ? unary_operations : binary_operations;
> +
> + if (unary) {
> + ds->p = p;
> + if (skip_separators(ds))
> + return -1;
> + p = ds->p;
> + c = *p;
> + } else {
> + for (;;) {
> + c = *p;
> + if ((c != ' ') && (c != '\t'))
> + break;
> + p++;
> + }
> + }
> + i = find_op(c, ops);
> + debug("%d,%c,%d:%s\n", i, c, unary, p);
> + if ((i < 0) && unary) {
> + if (val_i >= ARRAY_SIZE(val))
> + return -1;
> + errno = 0;
> + val[val_i++] = strtoul(p, &endptr, 16);
> + if (errno || (p == endptr)) {
> + ds->p = p;
> + return -1;
> + }
> + p = endptr;
> + unary = 0;
> + debug("val[%d]=%x,%d,%d\n", val_i - 1, val[val_i - 1],
> + op_i, val_i);
> +do_unary:
> + while (op_i) {
> + j = op[op_i - 1];
> + if (!(j & 0x80))
> + break;
> + op_i--;
> + val[val_i - 1] = do_func(0,
> + val[val_i - 1], j & 0x7f);
> + debug("un:%d,%x,%d,%d\n", val[val_i - 1], j,
> + op_i, val_i);
> + }
> + continue;
> + }
> + if (i < 0) {
> + c = 0;
> + i = 8;
> + } else {
> + p++;
> + }
> + if (c == '(') {
> + if (op_i >= ARRAY_SIZE(op))
> + return -1;
> + op[op_i++] = i;
> + debug("op[%d]=%x,%d,%d\n", op_i - 1, op[op_i - 1],
> + op_i, val_i);
> + unary = 1;
> + continue;
> + }
> + for (;;) {
> + if (!op_i || unary)
> + break;
> + j = op[op_i - 1];
> + if (j == 0) {
> + if (c == ')') {
> + op_i--;
> + goto do_unary;
> + }
> + break;
> + }
> + if ((j & 0x80)) {
> + op_i--;
> + val[val_i - 1] = do_func(0,
> + val[val_i - 1], j & 0x7f);
> + debug("unary:%d,%x\n", val[val_i - 1], j);
> + continue;
> + }
> + if (precedence[i] < precedence[j])
> + break;
> + if (val_i < 2)
> + return -1;
> + op_i--;
> + val[val_i - 2] = do_func(val[val_i - 2],
> + val[val_i - 1], j);
> + val_i--;
> + debug("binary:%d,%x,%d,%d\n", val[val_i - 1], j,
> + op_i, val_i);
> + }
> + if (c == ')') {
> + fprintf(stderr, "Error: unmatched parenthesis\n");
> + return -1;
> + }
> + if (i == 8) {
> + if ((op_i != 0) || (val_i != 1)) {
> + fprintf(stderr, "Error: syntax %d %d\n",
> + op_i, val_i);
> + return -1;
> + }
> + ds->p = p;
> + *pval = val[0];
> + return 0;
> + }
> + if (op_i >= ARRAY_SIZE(op))
> + return -1;
> + op[op_i++] = i | (unary << 7);
> + debug("op[%d]=%x,%d,%d\n", op_i - 1, op[op_i - 1], op_i, val_i);
> + unary = 1;
> + }
> }

Best regards,
Stefano Babic

--
=====================================================================
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================