kbuild: fix headers_exports with boolean expression
Russell King [Sat, 6 Jun 2009 21:47:11 +0000 (22:47 +0100)]
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>

scripts/unifdef.c

index 05a31a6..30d459f 100644 (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);
 }