kbuild: fix headers_exports with boolean expression

When we had code like this in a header unifdef failed to
deduct that the expression was always false - and we had code exported
that was not intended for userspace.

#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
  int a;
#endif

This commit implment support in unidef which allows it to work out if
an #if expression always evaluates true or false for symbols which
are being undefined/always defined.

The patch is slightly more complicated than I'd hoped because unifdef
needs to see lines fully evaluated - doing otherwise causes it to
mark the line as "dirty" and copy it over no matter what.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
Russell King 2009-06-06 22:47:11 +01:00 committed by Sam Ravnborg
parent 67b7ebe091
commit eedc9d83ea

View file

@ -678,8 +678,10 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp)
if (*cp == '!') {
debug("eval%d !", ops - eval_ops);
cp++;
if (eval_unary(ops, valp, &cp) == LT_IF)
if (eval_unary(ops, valp, &cp) == LT_IF) {
*cpp = cp;
return (LT_IF);
}
*valp = !*valp;
} else if (*cp == '(') {
cp++;
@ -700,13 +702,16 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp)
return (LT_IF);
cp = skipcomment(cp);
sym = findsym(cp);
if (sym < 0)
return (LT_IF);
*valp = (value[sym] != NULL);
cp = skipsym(cp);
cp = skipcomment(cp);
if (*cp++ != ')')
return (LT_IF);
if (sym >= 0)
*valp = (value[sym] != NULL);
else {
*cpp = cp;
return (LT_IF);
}
keepthis = false;
} else if (!endsym(*cp)) {
debug("eval%d symbol", ops - eval_ops);
@ -741,11 +746,11 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
const struct op *op;
const char *cp;
int val;
Linetype lhs, rhs;
debug("eval%d", ops - eval_ops);
cp = *cpp;
if (ops->inner(ops+1, valp, &cp) == LT_IF)
return (LT_IF);
lhs = ops->inner(ops+1, valp, &cp);
for (;;) {
cp = skipcomment(cp);
for (op = ops->op; op->str != NULL; op++)
@ -755,14 +760,32 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
break;
cp += strlen(op->str);
debug("eval%d %s", ops - eval_ops, op->str);
if (ops->inner(ops+1, &val, &cp) == LT_IF)
return (LT_IF);
*valp = op->fn(*valp, val);
rhs = ops->inner(ops+1, &val, &cp);
if (op->fn == op_and && (lhs == LT_FALSE || rhs == LT_FALSE)) {
debug("eval%d: and always false", ops - eval_ops);
if (lhs == LT_IF)
*valp = val;
lhs = LT_FALSE;
continue;
}
if (op->fn == op_or && (lhs == LT_TRUE || rhs == LT_TRUE)) {
debug("eval%d: or always true", ops - eval_ops);
if (lhs == LT_IF)
*valp = val;
lhs = LT_TRUE;
continue;
}
if (rhs == LT_IF)
lhs = LT_IF;
if (lhs != LT_IF)
*valp = op->fn(*valp, val);
}
*cpp = cp;
debug("eval%d = %d", ops - eval_ops, *valp);
return (*valp ? LT_TRUE : LT_FALSE);
if (lhs != LT_IF)
lhs = (*valp ? LT_TRUE : LT_FALSE);
return lhs;
}
/*
@ -773,12 +796,15 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
static Linetype
ifeval(const char **cpp)
{
const char *cp = *cpp;
int ret;
int val;
debug("eval %s", *cpp);
keepthis = killconsts ? false : true;
ret = eval_table(eval_ops, &val, cpp);
ret = eval_table(eval_ops, &val, &cp);
if (ret != LT_IF)
*cpp = cp;
debug("eval = %d", val);
return (keepthis ? LT_IF : ret);
}