aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-01-09 17:31:45 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-01-09 17:31:45 +0000
commitc55d3b6808ee724814e54ec00ab2faba04519855 (patch)
treed9f8db750df527ca8061b6196d5ae1eac77f5edd
parentbc266eabe3d1b136ef93d5366210db9560d7f317 (diff)
parent7be0794073f08277c25000415f5d66ac1a645c61 (diff)
downloadone-true-awk-c55d3b6808ee724814e54ec00ab2faba04519855.tar.gz
Upgrade one-true-awk to 944989bf683d30f306d8f29a3eb8c68c7c603fb4 am: 2b2ca9f3fb am: 78cb1093df am: 7be0794073
Change-Id: I31b2a71bd29660973c47448599812f37d575c9a6
-rw-r--r--ChangeLog26
-rw-r--r--FIXES15
-rw-r--r--METADATA8
-rw-r--r--README90
-rw-r--r--README.md96
-rw-r--r--b.c33
-rw-r--r--lex.c9
-rw-r--r--main.c2
-rw-r--r--run.c20
-rwxr-xr-xtestdir/T.concat29
-rwxr-xr-xtestdir/T.expr18
-rwxr-xr-xtestdir/T.int-expr82
-rw-r--r--tran.c14
13 files changed, 308 insertions, 134 deletions
diff --git a/ChangeLog b/ChangeLog
index 0ecc656..1afd9de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2020-01-06 Arnold D. Robbins <arnold@skeeve.com>
+
+ Minor fixes.
+ * b.c (replace_repeat): Turn init_q back into an int.
+ * lex.c (string): Use \a instead of \007.
+ * tran.c (catstr): Use snprintf instead of sprintf.
+
+2020-01-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * tran.c (syminit, arginit, envinit): Free sval member before
+ setting it. Thanks to valgrind.
+ * b.c: Small formatting cleanups in several routines.
+
+2019-12-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * b.c (replace_repeat): Fix a bug whereby a{0,3} could match
+ four a's. Thanks to Anonymous AWK fan <awkfan77@mailfence.com>
+ for the report. Also, minor code formatting cleanups.
+ * testdir/T.int-expr: New file.
+
+2019-12-11 Arnold D. Robbins <arnold@skeeve.com>
+
+ * README: Renamed to ...
+ * README.md: ... this. Cleaned up some as well,
+ including moving to Markdown.
+
2019-11-08 Arnold D. Robbins <arnold@skeeve.com>
* test/T.chem: Use $oldawk instead of hardwiring 'awk'.
diff --git a/FIXES b/FIXES
index 722739e..6889e30 100644
--- a/FIXES
+++ b/FIXES
@@ -25,6 +25,21 @@ 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.
+
+December 11, 2019:
+ Further printf-related fixes for 32 bit systems.
+ Thanks again to Christos Zoulas.
+
December 8, 2019:
Fix the return value of sprintf("%d") on 32 bit systems.
Thanks to Jim Lowe for the report and to Christos Zoulas
diff --git a/METADATA b/METADATA
index c99366c..a4d2203 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@ third_party {
type: GIT
value: "https://github.com/onetrueawk/awk.git"
}
- version: "af86dacfad85857b2ea9fa95150ddd8c671695ed"
+ version: "944989bf683d30f306d8f29a3eb8c68c7c603fb4"
license_type: NOTICE
last_upgrade_date {
- year: 2019
- month: 12
- day: 9
+ year: 2020
+ month: 1
+ day: 8
}
}
diff --git a/README b/README
deleted file mode 100644
index 5d89359..0000000
--- a/README
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************
-Copyright (C) Lucent Technologies 1997
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name Lucent Technologies or any of
-its entities not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-****************************************************************/
-
-This is the version of awk described in "The AWK Programming Language",
-by Al Aho, Brian Kernighan, and Peter Weinberger
-(Addison-Wesley, 1988, ISBN 0-201-07981-X).
-
-Changes, mostly bug fixes and occasional enhancements, are listed
-in FIXES. If you distribute this code further, please please please
-distribute FIXES with it. If you find errors, please report them
-to bwk@cs.princeton.edu. Thanks.
-
-The program itself is created by
- make
-which should produce a sequence of messages roughly like this:
-
- yacc -d awkgram.y
-
-conflicts: 43 shift/reduce, 85 reduce/reduce
- mv y.tab.c ytab.c
- mv y.tab.h ytab.h
- cc -c ytab.c
- cc -c b.c
- cc -c main.c
- cc -c parse.c
- cc maketab.c -o maketab
- ./maketab >proctab.c
- cc -c proctab.c
- cc -c tran.c
- cc -c lib.c
- cc -c run.c
- cc -c lex.c
- cc ytab.o b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -lm
-
-This produces an executable a.out; you will eventually want to
-move this to some place like /usr/bin/awk.
-
-If your system does not have yacc or bison (the GNU
-equivalent), you must compile the pieces manually. We have
-included yacc output in ytab.c and ytab.h, and backup copies in
-case you overwrite them. We have also included a copy of
-proctab.c so you do not need to run maketab.
-
-NOTE: This version uses ANSI C, as you should also. We have
-compiled this without any changes using gcc -Wall and/or local C
-compilers on a variety of systems, but new systems or compilers
-may raise some new complaint; reports of difficulties are
-welcome.
-
-This also compiles with Visual C++ on all flavors of Windows,
-*if* you provide versions of popen and pclose. The file
-missing95.c contains versions that can be used to get started
-with, though the underlying support has mysterious properties,
-the symptom of which can be truncated pipe output. Beware. The
-file makefile.win gives hints on how to proceed; if you run
-vcvars32.bat, it will set up necessary paths and parameters so
-you can subsequently run nmake -f makefile.win. Beware also that
-when running on Windows under command.com, various quoting
-conventions are different from Unix systems: single quotes won't
-work around arguments, and various characters like % are
-interpreted within double quotes.
-
-This compiles without change on Macintosh OS X using gcc and
-the standard developer tools.
-
-The version of malloc that comes with some systems is sometimes
-astonishly slow. If awk seems slow, you might try fixing that.
-More generally, turning on optimization can significantly improve
-awk's speed, perhaps by 1/3 for highest levels.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..77701d7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+# The One True Awk
+
+This is the version of `awk` described in _The AWK Programming Language_,
+by Al Aho, Brian Kernighan, and Peter Weinberger
+(Addison-Wesley, 1988, ISBN 0-201-07981-X).
+
+## Copyright
+
+Copyright (C) Lucent Technologies 1997<br/>
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+## Distribution and Reporting Problems
+
+Changes, mostly bug fixes and occasional enhancements, are listed
+in `FIXES`. If you distribute this code further, please please please
+distribute `FIXES` with it.
+
+If you find errors, please report them
+to bwk@cs.princeton.edu.
+Please _also_ open an issue in the GitHub issue tracker, to make
+it easy to track issues.
+Thanks.
+
+## Submitting Pull Requests
+
+Pull requests are welcome. However, please create them with a request
+to merge into the `staging` branch instead of into the `master` branch.
+This allows us to do testing, and to make any additional edits or changes
+after the merge but before merging to `master`.
+
+## Building
+
+The program itself is created by
+
+ make
+
+which should produce a sequence of messages roughly like this:
+
+ yacc -d awkgram.y
+ conflicts: 43 shift/reduce, 85 reduce/reduce
+ mv y.tab.c ytab.c
+ mv y.tab.h ytab.h
+ cc -c ytab.c
+ cc -c b.c
+ cc -c main.c
+ cc -c parse.c
+ cc maketab.c -o maketab
+ ./maketab >proctab.c
+ cc -c proctab.c
+ cc -c tran.c
+ cc -c lib.c
+ cc -c run.c
+ cc -c lex.c
+ cc ytab.o b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -lm
+
+This produces an executable `a.out`; you will eventually want to
+move this to some place like `/usr/bin/awk`.
+
+If your system does not have `yacc` or `bison` (the GNU
+equivalent), you need to install one of them first.
+
+NOTE: This version uses ANSI C (C 99), as you should also. We have
+compiled this without any changes using `gcc -Wall` and/or local C
+compilers on a variety of systems, but new systems or compilers
+may raise some new complaint; reports of difficulties are
+welcome.
+
+This compiles without change on Macintosh OS X using `gcc` and
+the standard developer tools.
+
+The version of `malloc` that comes with some systems is sometimes
+astonishly slow. If `awk` seems slow, you might try fixing that.
+More generally, turning on optimization can significantly improve
+`awk`'s speed, perhaps by 1/3 for highest levels.
+
+#### Last Updated
+Wed Jan 1 22:44:38 IST 2020
diff --git a/b.c b/b.c
index 1e53652..5671796 100644
--- a/b.c
+++ b/b.c
@@ -180,7 +180,7 @@ fa *makedfa(const char *s, bool anchor) /* returns dfa for reg expr s */
}
fa *mkdfa(const char *s, bool anchor) /* does the real work of making a dfa */
- /* anchor = 1 for anchored matches, else 0 */
+ /* anchor = true for anchored matches, else false */
{
Node *p, *p1;
fa *f;
@@ -223,17 +223,17 @@ int makeinit(fa *f, bool anchor)
k = *(f->re[0].lfollow);
xfree(f->posns[2]);
f->posns[2] = intalloc(k + 1, __func__);
- for (i=0; i <= k; i++) {
+ for (i = 0; i <= k; i++) {
(f->posns[2])[i] = (f->re[0].lfollow)[i];
}
if ((f->posns[2])[1] == f->accept)
f->out[2] = 1;
- for (i=0; i < NCHARS; i++)
+ for (i = 0; i < NCHARS; i++)
f->gototab[2][i] = 0;
f->curstat = cgoto(f, 2, HAT);
if (anchor) {
*f->posns[2] = k-1; /* leave out position 0 */
- for (i=0; i < k; i++) {
+ for (i = 0; i < k; i++) {
(f->posns[0])[i] = (f->posns[2])[i];
}
@@ -463,9 +463,10 @@ int first(Node *p) /* collects initially active leaves of p into setvec */
}
if (type(p) == CCL && (*(char *) right(p)) == '\0')
return(0); /* empty CCL */
- else return(1);
+ return(1);
case PLUS:
- if (first(left(p)) == 0) return(0);
+ if (first(left(p)) == 0)
+ return(0);
return(1);
case STAR:
case QUEST:
@@ -714,7 +715,7 @@ bool fnematch(fa *pfa, FILE *f, char **pbuf, int *pbufsize, int quantum)
if (buf[--k] && ungetc(buf[k], f) == EOF)
FATAL("unable to ungetc '%c'", buf[k]);
while (k > i + patlen);
- buf[k] = 0;
+ buf[k] = '\0';
return true;
}
else
@@ -935,7 +936,7 @@ replace_repeat(const uschar *reptok, int reptoklen, const uschar *atom,
buf[j++] = '(';
buf[j++] = ')';
}
- for (i=1; i < firstnum; i++) { /* copy x reps */
+ for (i = 1; i < firstnum; i++) { /* copy x reps */
memcpy(&buf[j], atom, atomlen);
j += atomlen;
}
@@ -944,7 +945,7 @@ replace_repeat(const uschar *reptok, int reptoklen, const uschar *atom,
} else if (special_case == REPEAT_WITH_Q) {
if (init_q)
buf[j++] = '?';
- for (i = 0; i < n_q_reps; i++) { /* copy x? reps */
+ for (i = init_q; i < n_q_reps; i++) { /* copy x? reps */
memcpy(&buf[j], atom, atomlen);
j += atomlen;
buf[j++] = '?';
@@ -1166,15 +1167,17 @@ rescan:
if (commafound) {
if (digitfound) { /* {n,m} */
m = num;
- if (m<n)
+ if (m < n)
FATAL("illegal repetition expression: class %.20s",
lastre);
- if ((n==0) && (m==1)) {
+ if (n == 0 && m == 1) {
return QUEST;
}
} else { /* {n,} */
- if (n==0) return STAR;
- if (n==1) return PLUS;
+ if (n == 0)
+ return STAR;
+ else if (n == 1)
+ return PLUS;
}
} else {
if (digitfound) { /* {n} same as {n,n} */
@@ -1187,7 +1190,7 @@ rescan:
}
if (repeat(starttok, prestr-starttok, lastatom,
startreptok - lastatom, n, m) > 0) {
- if ((n==0) && (m==0)) {
+ if (n == 0 && m == 0) {
return EMPTYRE;
}
/* must rescan input for next token */
@@ -1313,7 +1316,7 @@ void freefa(fa *f) /* free a finite automaton */
for (i = 0; i <= f->accept; i++) {
xfree(f->re[i].lfollow);
if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL)
- xfree((f->re[i].lval.np));
+ xfree(f->re[i].lval.np);
}
xfree(f->restr);
xfree(f->out);
diff --git a/lex.c b/lex.c
index 2de0603..d729516 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);
}
@@ -388,7 +390,7 @@ int string(void)
case 'r': *bp++ = '\r'; break;
case 'b': *bp++ = '\b'; break;
case 'v': *bp++ = '\v'; break;
- case 'a': *bp++ = '\007'; break;
+ case 'a': *bp++ = '\a'; break;
case '\\': *bp++ = '\\'; break;
case '0': case '1': case '2': /* octal: \d \dd \ddd */
@@ -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 e3648d0..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 20191208";
+const char *version = "version 20200105";
#define DEBUG
#include <stdio.h>
diff --git a/run.c b/run.c
index 4069f59..a331449 100644
--- a/run.c
+++ b/run.c
@@ -855,8 +855,13 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
for (t = fmt; (*t++ = *s) != '\0'; s++) {
if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
FATAL("format item %.30s... ran format() out of memory", os);
- if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
- break; /* the ansi panoply */
+ /* Ignore size specifiers */
+ if (strchr("hjLlqtz", *s) != NULL) { /* the ansi panoply */
+ t--;
+ continue;
+ }
+ if (isalpha((uschar)*s))
+ break;
if (*s == '$') {
FATAL("'$' not permitted in awk formats");
}
@@ -889,15 +894,8 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
case 'f': case 'e': case 'g': case 'E': case 'G':
flag = 'f';
break;
- case 'd': case 'i':
- flag = 'd';
- if(*(s-1) == 'l') break;
- *(t-1) = 'j';
- *t = 'd';
- *++t = '\0';
- break;
- case 'o': case 'x': case 'X': case 'u':
- flag = *(s-1) == 'l' ? 'd' : 'u';
+ case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
+ flag = (*s == 'd' || *s == 'i') ? 'd' : 'u';
*(t-1) = 'j';
*t = *s;
*++t = '\0';
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/testdir/T.expr b/testdir/T.expr
index 7390e8b..304b3d0 100755
--- a/testdir/T.expr
+++ b/testdir/T.expr
@@ -167,15 +167,15 @@ try { printf("a%-*.*sb\n", $1, $2, "hello") }
2 1 ah b
3 1 ah b
-try { printf("%d %ld\n", $1, $1) }
-1 1 1
-10 10 10
-10000 10000 10000
-
-try { printf("%x %lx\n", $1, $1) }
-1 1 1
-10 a a
-10000 2710 2710
+try { printf("%d %ld %lld %zd %jd %hd %hhd\n", $1, $1, $1, $1, $1, $1, $1) }
+1 1 1 1 1 1 1 1
+10 10 10 10 10 10 10 10
+10000 10000 10000 10000 10000 10000 10000 10000
+
+try { printf("%x %lx %llx %zx %jx %hx %hhx\n", $1, $1, $1, $1, $1, $1, $1) }
+1 1 1 1 1 1 1 1
+10 a a a a a a a
+10000 2710 2710 2710 2710 2710 2710 2710
try { if ($1 ~ $2) print 1; else print 0 }
a \141 1
diff --git a/testdir/T.int-expr b/testdir/T.int-expr
new file mode 100755
index 0000000..e71a075
--- /dev/null
+++ b/testdir/T.int-expr
@@ -0,0 +1,82 @@
+echo T.int-expr: test interval expressions
+
+awk=${awk-../a.out}
+
+rm -f foo
+
+cat << \EOF > prog
+NF == 0 { next }
+$1 == "pat" { pattern = $2; next }
+{
+ check = ($1 ~ pattern)
+ printf("%s ~ /%s/ -> should be %d, is %d\n", $1, pattern, $2, check)
+}
+EOF
+
+cat << \EOF > foo.in
+pat ab{0}c
+ac 1
+abc 0
+
+pat ab{1}c
+ac 0
+abc 1
+abbc 0
+
+pat ab{1,}c
+ac 0
+abc 1
+abbc 1
+abbbc 1
+abbbbc 1
+
+pat ab{0,1}c
+ac 1
+abc 1
+abbc 0
+
+pat ab{0,3}c
+ac 1
+abc 1
+abbc 1
+abbbc 1
+abbbbc 0
+
+pat ab{1,3}c
+ac 0
+abc 1
+abbc 1
+abbbc 1
+abbbbc 0
+EOF
+
+cat << \EOF > foo1
+ac ~ /ab{0}c/ -> should be 1, is 1
+abc ~ /ab{0}c/ -> should be 0, is 0
+ac ~ /ab{1}c/ -> should be 0, is 0
+abc ~ /ab{1}c/ -> should be 1, is 1
+abbc ~ /ab{1}c/ -> should be 0, is 0
+ac ~ /ab{1,}c/ -> should be 0, is 0
+abc ~ /ab{1,}c/ -> should be 1, is 1
+abbc ~ /ab{1,}c/ -> should be 1, is 1
+abbbc ~ /ab{1,}c/ -> should be 1, is 1
+abbbbc ~ /ab{1,}c/ -> should be 1, is 1
+ac ~ /ab{0,1}c/ -> should be 1, is 1
+abc ~ /ab{0,1}c/ -> should be 1, is 1
+abbc ~ /ab{0,1}c/ -> should be 0, is 0
+ac ~ /ab{0,3}c/ -> should be 1, is 1
+abc ~ /ab{0,3}c/ -> should be 1, is 1
+abbc ~ /ab{0,3}c/ -> should be 1, is 1
+abbbc ~ /ab{0,3}c/ -> should be 1, is 1
+abbbbc ~ /ab{0,3}c/ -> should be 0, is 0
+ac ~ /ab{1,3}c/ -> should be 0, is 0
+abc ~ /ab{1,3}c/ -> should be 1, is 1
+abbc ~ /ab{1,3}c/ -> should be 1, is 1
+abbbc ~ /ab{1,3}c/ -> should be 1, is 1
+abbbbc ~ /ab{1,3}c/ -> should be 0, is 0
+EOF
+
+
+$awk -f prog foo.in > foo2
+diff foo1 foo2 || echo 'BAD: T.int-expr (1)'
+rm -f prog
diff --git a/tran.c b/tran.c
index 20125e3..d659cfa 100644
--- a/tran.c
+++ b/tran.c
@@ -114,6 +114,7 @@ void syminit(void) /* initialize symbol table with builtin vars */
rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
RLENGTH = &rlengthloc->fval;
symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
+ free(symtabloc->sval);
symtabloc->sval = (char *) symtab;
}
@@ -126,6 +127,7 @@ void arginit(int ac, char **av) /* set up ARGV and ARGC */
ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
+ free(cp->sval);
cp->sval = (char *) ARGVtab;
for (i = 0; i < ac; i++) {
sprintf(temp, "%d", i);
@@ -144,6 +146,7 @@ void envinit(char **envp) /* set up ENVIRON variable */
cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
ENVtab = makesymtab(NSYMTAB);
+ free(cp->sval);
cp->sval = (char *) ENVtab;
for ( ; *envp; envp++) {
if ((p = strchr(*envp, '=')) == NULL)
@@ -524,8 +527,17 @@ 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);
+
+ l++; // add room for ' '
+ char *newbuf = malloc(l);
+ 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 ".
+ snprintf(newbuf, l, "%s ", p);
+ c = setsymtab(newbuf, p, 0.0, CON|STR|DONTFREE, symtab);
free(p);
+ free(newbuf);
return c;
}