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

Stefano Babic sbabic at denx.de
Sun Sep 23 16:56:01 CEST 2012


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 at 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
=====================================================================


More information about the U-Boot mailing list