diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2019-09-25 20:25:06 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2019-09-26 11:52:22 +0200 |
| commit | 720ce88a839cc9966d4b5dfbcdbe868c33cb5965 (patch) | |
| tree | 501e70c5a3a21c48dec091832971fde91d666b64 | |
| parent | f2ce282eca6537210d83f9f0d2c753c2b280943c (diff) | |
Fix handling of parentheses in macro argument values
As an oversight, there was no check for nested parentheses in macro
arguments, making the preprocessor think the call ended after 'void)' in
def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
This broke the latest linux-next kernels, starting with commit
eb111869301e1 ("compiler-types.h: add asm_inline definition").
I remember seeing this when going through the C code, but somehow forgot
to put it in. Fix it, and clean up _expand_macro() a bit at the same
time.
Fixes: #76
| -rw-r--r-- | kconfiglib.py | 40 | ||||
| -rw-r--r-- | tests/Kpreprocess | 6 | ||||
| -rw-r--r-- | testsuite.py | 17 |
3 files changed, 40 insertions, 23 deletions
diff --git a/kconfiglib.py b/kconfiglib.py index 3908985..6c42ca2 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -2649,14 +2649,12 @@ class Kconfig(object): # Returns the expanded 's' (including the part before the macro) and # the index of the first character after the expanded macro in 's'. - start = i + res = s[:i] i += 2 # Skip over "$(" - # Start of current macro argument - arg_start = i - - # Arguments of this macro call - new_args = [] + arg_start = i # Start of current macro argument + new_args = [] # Arguments of this macro call + nesting = 0 # Current parentheses nesting level while 1: match = _macro_special_search(s, i) @@ -2664,32 +2662,42 @@ class Kconfig(object): self._parse_error("missing end parenthesis in macro expansion") - if match.group() == ")": + if match.group() == "(": + nesting += 1 + i = match.end() + + elif match.group() == ")": + if nesting: + nesting -= 1 + i = match.end() + continue + # Found the end of the macro new_args.append(s[arg_start:match.start()]) - prefix = s[:start] - # $(1) is replaced by the first argument to the function, etc., # provided at least that many arguments were passed try: # Does the macro look like an integer, with a corresponding # argument? If so, expand it to the value of the argument. - prefix += args[int(new_args[0])] + res += args[int(new_args[0])] except (ValueError, IndexError): # Regular variables are just functions without arguments, # and also go through the function value path - prefix += self._fn_val(new_args) + res += self._fn_val(new_args) - return (prefix + s[match.end():], - len(prefix)) + return (res + s[match.end():], len(res)) elif match.group() == ",": + i = match.end() + if nesting: + continue + # Found the end of a macro argument new_args.append(s[arg_start:match.start()]) - arg_start = i = match.end() + arg_start = i else: # match.group() == "$(" # A nested macro call within the macro @@ -7015,8 +7023,8 @@ _assignment_lhs_fragment_match = _re_match("[A-Za-z0-9_-]*") # variable assignment _assignment_rhs_match = _re_match(r"\s*(=|:=|\+=)\s*(.*)") -# Special characters/strings while expanding a macro (')', ',', and '$(') -_macro_special_search = _re_search(r"\)|,|\$\(") +# Special characters/strings while expanding a macro ('(', ')', ',', and '$(') +_macro_special_search = _re_search(r"\(|\)|,|\$\(") # Special characters/strings while expanding a string (quotes, '\', and '$(') _string_special_search = _re_search(r'"|\'|\\|\$\(') diff --git a/tests/Kpreprocess b/tests/Kpreprocess index e30b389..f9aca10 100644 --- a/tests/Kpreprocess +++ b/tests/Kpreprocess @@ -51,7 +51,7 @@ surround-rev-quote = $(0) $(rev-quote,$(1),$(2)) $(0) surround-rev-quote-unused-arg = $(surround-rev-quote,$(1),$(2)) $(3) # No value is passed for $(3), so it expands to nothing fn-indir = surround-rev-quote -messy-fn-res = $($(fn-indir)-unused-arg, a b , c d ) +messy-fn-res = $($(fn-indir)-unused-arg, a b (,) , c d ) # Special characters in function call comma = , @@ -121,6 +121,10 @@ shell-res = $(shell,false && echo foo bar || echo baz qaz) # Warns about output on stderr, expands to nothing shell-stderr-res := $(shell,echo message on stderr >&2) +# Nested parens in macro call. Should give a single argument. Test it with +# $(shell) to get a free argument number check. +parens-res = pre-$(shell,echo '(a,b,(c,d),e)')-post + # Expands to the current location location-res := $(filename):$(lineno) diff --git a/testsuite.py b/testsuite.py index 93e85d6..a29f815 100644 --- a/testsuite.py +++ b/testsuite.py @@ -2478,8 +2478,8 @@ config J verify_variable("immediate", "foofoo", "foofoo", False) verify_variable("messy-fn-res", - "$($(fn-indir)-unused-arg, a b , c d )", - 'surround-rev-quote " c d " " a b " surround-rev-quote ', + "$($(fn-indir)-unused-arg, a b (,) , c d )", + 'surround-rev-quote " c d " " a b (,) " surround-rev-quote ', True) verify_variable("special-chars-fn-res", @@ -2516,7 +2516,7 @@ config PRINT_ME_TOO verify_repr( "messy-fn-res", - "<variable messy-fn-res, recursive, value '$($(fn-indir)-unused-arg, a b , c d )'>") + "<variable messy-fn-res, recursive, value '$($(fn-indir)-unused-arg, a b (,) , c d )'>") def verify_recursive(name): try: @@ -2546,9 +2546,14 @@ config PRINT_ME_TOO verify_variable("shell-stderr-res", "", "", False) + verify_variable("parens-res", + "pre-$(shell,echo '(a,b,(c,d),e)')-post", + "pre-(a,b,(c,d),e)-post", + True) + verify_variable("location-res", - "Kconfiglib/tests/Kpreprocess:125", - "Kconfiglib/tests/Kpreprocess:125", + "Kconfiglib/tests/Kpreprocess:129", + "Kconfiglib/tests/Kpreprocess:129", False) verify_variable("warning-res", "", "", False) @@ -2568,7 +2573,7 @@ config PRINT_ME_TOO # Check that the expected warnings were generated verify_equal(c.warnings, [ "Kconfiglib/tests/Kpreprocess:122: warning: 'echo message on stderr >&2' wrote to stderr: message on stderr", - "Kconfiglib/tests/Kpreprocess:130: warning: a warning" + "Kconfiglib/tests/Kpreprocess:134: warning: a warning" ]) |
