From c7eeb57210cc7104df233a243295c36ffe6a2117 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 5 Jan 2020 21:18:36 +0200 Subject: [PATCH] Fix merging of concatenated string constants. --- FIXES | 7 +++++++ lex.c | 7 +++++-- main.c | 2 +- testdir/T.concat | 29 +++++++++++++++++++++++++++++ tran.c | 9 ++++++++- 5 files changed, 50 insertions(+), 4 deletions(-) create mode 100755 testdir/T.concat diff --git a/FIXES b/FIXES index ad5585c..6889e30 100644 --- a/FIXES +++ b/FIXES @@ -25,6 +25,13 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. +January 5, 2020: + Fix a bug in the concatentation of two string constants into + one done in the grammar. Fixes GitHub issue #61. Thanks + to GitHub user awkfan77 for pointing out the direction for + the fix. New test T.concat added to the test suite. + Fix a few memory leaks reported by valgrind, as well. + December 27, 2019: Fix a bug whereby a{0,3} could match four a's. Thanks to "Anonymous AWK fan" for the report. diff --git a/lex.c b/lex.c index 2de0603..1c6a0b7 100644 --- a/lex.c +++ b/lex.c @@ -190,7 +190,9 @@ int yylex(void) if (isalpha(c) || c == '_') return word(buf); if (isdigit(c)) { - yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab); + char *cp = tostring(buf); + yylval.cp = setsymtab(buf, cp, atof(buf), CON|NUM, symtab); + free(cp); /* should this also have STR set? */ RET(NUMBER); } @@ -431,8 +433,9 @@ int string(void) } *bp = 0; s = tostring(buf); - *bp++ = ' '; *bp++ = 0; + *bp++ = ' '; *bp++ = '\0'; yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab); + free(s); RET(STRING); } diff --git a/main.c b/main.c index c8a2f32..abfa312 100644 --- a/main.c +++ b/main.c @@ -22,7 +22,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ -const char *version = "version 20191227"; +const char *version = "version 20200105"; #define DEBUG #include diff --git a/testdir/T.concat b/testdir/T.concat new file mode 100755 index 0000000..c6bd016 --- /dev/null +++ b/testdir/T.concat @@ -0,0 +1,29 @@ +echo T.concat: test constant string concatentation + +awk=${awk-../a.out} + +$awk ' +BEGIN { + $0 = "aaa" + print "abcdef" " " $0 +} +BEGIN { print "hello" "world"; print helloworld } +BEGIN { + print " " "hello" + print "hello" " " + print "hello" " " "world" + print "hello" (" " "world") +} +' > foo1 + +cat << \EOF > foo2 +abcdef aaa +helloworld + + hello +hello +hello world +hello world +EOF + +diff foo1 foo2 || echo 'BAD: T.concat (1)' diff --git a/tran.c b/tran.c index a102feb..1fca361 100644 --- a/tran.c +++ b/tran.c @@ -527,8 +527,15 @@ Cell *catstr(Cell *a, Cell *b) /* concatenate a and b */ if (p == NULL) FATAL("out of space concatenating %s and %s", sa, sb); snprintf(p, l, "%s%s", sa, sb); - c = setsymtab(p, p, 0.0, CON|STR|DONTFREE, symtab); + char *newbuf = malloc(strlen(p) + 2); + if (newbuf == NULL) + FATAL("out of space concatenating %s and %s", sa, sb); + // See string() in lex.c; a string "xx" is stored in the symbol + // table as "xx ". + sprintf(newbuf, "%s ", p); + c = setsymtab(newbuf, p, 0.0, CON|STR|DONTFREE, symtab); free(p); + free(newbuf); return c; }