From 65e63e746120a03b54de51f1db148a7fa1aa27e2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 18 Sep 2019 10:59:35 -0400 Subject: [PATCH] annotate_ifdef_directives: remove some cases of double negation This change should reduce the number of cases where we say "/* !(!defined(foo)) */" . This only does cases where we can use a regex to make sure that the simplification is guaranteed to be correct. Full boolean simplification would require this script to parse C, and nobody wants that. --- scripts/maint/annotate_ifdef_directives | 44 +++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/scripts/maint/annotate_ifdef_directives b/scripts/maint/annotate_ifdef_directives index b784ca71ba..4463d83828 100755 --- a/scripts/maint/annotate_ifdef_directives +++ b/scripts/maint/annotate_ifdef_directives @@ -54,6 +54,46 @@ def commented_line(fmt, argument, maxwidth=LINE_WIDTH): assert len(result) <= maxwidth return result +def negate(expr): + """Return a negated version of expr; try to avoid double-negation. + + We usually wrap expressions in parentheses and add a "!". + >>> negate("A && B") + '!(A && B)' + + But if we recognize the expression as negated, we can restore it. + >>> negate(negate("A && B")) + 'A && B' + + The same applies for defined(FOO). + >>> negate("defined(FOO)") + '!defined(FOO)' + >>> negate(negate("defined(FOO)")) + 'defined(FOO)' + + Internal parentheses don't confuse us: + >>> negate("!(FOO) && !(BAR)") + '!(!(FOO) && !(BAR))' + + """ + expr = expr.strip() + # See whether we match !(...), with no intervening close-parens. + m = re.match(r'^!\s*\(([^\)]*)\)$', expr) + if m: + return m.group(1) + + + # See whether we match !?defined(...), with no intervening close-parens. + m = re.match(r'^(!?)\s*(defined\([^\)]*\))$', expr) + if m: + if m.group(1) == "!": + prefix = "" + else: + prefix = "!" + return prefix + m.group(2) + + return "!(%s)" % expr + def uncomment(s): """ Remove existing trailing comments from an #else or #endif line. @@ -108,8 +148,8 @@ def translate(f_in, f_out): raise Problem("Unexpected #%s on %d"% (command,lineno)) if (len(cur_level) == 1 and command == 'else' and lineno > cur_level[0][2] + LINE_OBVIOUSNESS_LIMIT): - f_out.write(commented_line("#else /* !(%s) */\n", - cur_level[0][1])) + f_out.write(commented_line("#else /* %s */\n", + negate(cur_level[0][1]))) else: f_out.write(line) cur_level.append((command, rest, lineno))