[git commit] awk: fix parsing of expressions such as "v (a)"

Denys Vlasenko vda.linux at googlemail.com
Tue Jun 29 10:16:36 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=6872c193a935df47facf717c15a32f93b43c6bcf
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
next_token                                           812     825     +13

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/awk.c       | 22 ++++++++++++++++++----
 testsuite/awk.tests | 11 +++++++++++
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/editors/awk.c b/editors/awk.c
index 34bcc1798..ce860dc04 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -1231,11 +1231,24 @@ static uint32_t next_token(uint32_t expected)
 			while (isalnum_(*p))
 				p++;
 			end_of_name = p;
-			tc = TC_VARIABLE;
-			/* also consume whitespace between functionname and bracket */
-			if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY))
-//TODO: why if variable can be here (but not array ref), skipping is not allowed? Example where it matters?
+
+			if (last_token_class == TC_FUNCDECL)
+				/* eat space in "function FUNC (...) {...}" declaration */
 				p = skip_spaces(p);
+			else if (expected & TC_ARRAY) {
+				/* eat space between array name and [ */
+				char *s = skip_spaces(p);
+				if (*s == '[') /* array ref, not just a name? */
+					p = s;
+			}
+			/* else: do NOT consume whitespace after variable name!
+			 * gawk allows definition "function FUNC (p) {...}" - note space,
+			 * but disallows the call "FUNC (p)" because it isn't one -
+			 * expression "v (a)" should NOT be parsed as TC_FUNCTION:
+			 * it is a valid concatenation if "v" is a variable,
+			 * not a function name (and type of name is not known at parse time).
+			 */
+
 			if (*p == '(') {
 				p++;
 				tc = TC_FUNCTION;
@@ -1245,6 +1258,7 @@ static uint32_t next_token(uint32_t expected)
 				tc = TC_ARRAY;
 				debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string);
 			} else {
+				tc = TC_VARIABLE;
 				debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string);
 				if (end_of_name == p) {
 					/* there is no space for trailing NUL in t_string!
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index cf9b722dc..6e35d33dd 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -71,6 +71,17 @@ testing "awk properly handles undefined function" \
 	"L1\n\nawk: cmd. line:5: Call to undefined function\n" \
 	"" ""
 
+prg='
+BEGIN {
+  v=1
+  a=2
+  print v (a)
+}'
+testing "'v (a)' is not a function call, it is a concatenation" \
+	"awk '$prg' 2>&1" \
+	"12\n" \
+	"" ""
+
 
 optional DESKTOP
 testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"


More information about the busybox-cvs mailing list