Merge branch 'master' into cc_func-avoid-undefined-behaviour
This commit is contained in:
commit
031aac816d
@ -1,3 +1,9 @@
|
||||
2018-08-29 Arnold D. Robbins <arnold@skeeve.com>
|
||||
|
||||
* REGRESS: Check for existence of a.out. If not there, run
|
||||
make. Enable core dumps for T.arnold system status test
|
||||
to work on MacOS X.
|
||||
|
||||
2018-08-22 Arnold D. Robbins <arnold@skeeve.com>
|
||||
|
||||
* awktest.tar (testdir/T.expr): Fix test for unary plus.
|
||||
|
5
FIXES
5
FIXES
@ -25,6 +25,11 @@ THIS SOFTWARE.
|
||||
This file lists all bug fixes, changes, etc., made since the AWK book
|
||||
was sent to the printers in August, 1987.
|
||||
|
||||
Oct 25, 2018:
|
||||
Added test in maketab.c to prevent generating a proctab entry
|
||||
for YYSTYPE_IS_DEFINED. It was harmless but some gcc settings
|
||||
generated a warning message. Thanks to Nan Xiao for report.
|
||||
|
||||
Aug 27, 2018:
|
||||
Disallow '$' in printf formats; arguments evaluated in order
|
||||
and printed in order.
|
||||
|
15
REGRESS
15
REGRESS
@ -1,5 +1,15 @@
|
||||
#! /bin/sh
|
||||
|
||||
case `uname` in
|
||||
CYGWIN) EXE=a.exe ;;
|
||||
*) EXE=a.out ;;
|
||||
esac
|
||||
|
||||
if [ ! -f $EXE ]
|
||||
then
|
||||
make || exit 1
|
||||
fi
|
||||
|
||||
if [ -d testdir ]
|
||||
then
|
||||
true # do nothing
|
||||
@ -16,5 +26,10 @@ cd testdir
|
||||
pwd
|
||||
PATH=.:$PATH
|
||||
export PATH
|
||||
if (ulimit -c unlimited > /dev/null 2>&1)
|
||||
then
|
||||
# Workaround broken default on MacOS X
|
||||
ulimit -c unlimited
|
||||
fi
|
||||
|
||||
REGRESS
|
||||
|
5
awk.h
5
awk.h
@ -97,9 +97,14 @@ extern Array *symtab;
|
||||
|
||||
extern Cell *nrloc; /* NR */
|
||||
extern Cell *fnrloc; /* FNR */
|
||||
extern Cell *fsloc; /* FS */
|
||||
extern Cell *nfloc; /* NF */
|
||||
extern Cell *ofsloc; /* OFS */
|
||||
extern Cell *orsloc; /* ORS */
|
||||
extern Cell *rsloc; /* RS */
|
||||
extern Cell *rstartloc; /* RSTART */
|
||||
extern Cell *rlengthloc; /* RLENGTH */
|
||||
extern Cell *subseploc; /* SUBSEP */
|
||||
|
||||
/* Cell.tval values: */
|
||||
#define NUM 01 /* number value is valid */
|
||||
|
10
b.c
10
b.c
@ -824,7 +824,15 @@ int relex(void) /* lexical analyzer for reparse */
|
||||
if (cc->cc_name != NULL && prestr[1 + cc->cc_namelen] == ':' &&
|
||||
prestr[2 + cc->cc_namelen] == ']') {
|
||||
prestr += cc->cc_namelen + 3;
|
||||
for (i = 0; i <= UCHAR_MAX; i++) {
|
||||
/*
|
||||
* BUG: We begin at 1, instead of 0, since we
|
||||
* would otherwise prematurely terminate the
|
||||
* string for classes like [[:cntrl:]]. This
|
||||
* means that we can't match the NUL character,
|
||||
* not without first adapting the entire
|
||||
* program to track each string's length.
|
||||
*/
|
||||
for (i = 1; i <= UCHAR_MAX; i++) {
|
||||
if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, "relex2"))
|
||||
FATAL("out of space for reg expr %.10s...", lastre);
|
||||
if (cc->cc_func(i)) {
|
||||
|
@ -23,3 +23,32 @@ and also if CONVFMT changed.
|
||||
|
||||
7. unary-plus: Unary plus on a string constant returned the string.
|
||||
Instead, it should convert the value to numeric and give that value.
|
||||
|
||||
8. concat-assign-same: Concatenation previously evaluated both sides of the
|
||||
expression before doing its work, which, since assign() evaluates to the cell
|
||||
being assigned to, meant that expressions like "print (a = 1) (a = 2)" would
|
||||
print "22" rather than "12".
|
||||
|
||||
9. missing-precision: When using the format string "%*s", the precision
|
||||
argument was used without checking if it was present first.
|
||||
|
||||
10. missing-precision: When using the format string "%*s", the precision
|
||||
argument was used without checking if it was present first.
|
||||
|
||||
11. fmt-overflow: The buffer used for OFMT/CONVFMT conversions was written
|
||||
to with sprintf(), which meant that some conversions could write past the
|
||||
end.
|
||||
|
||||
12. numeric-subsep, numeric-fs, numeric-output-seps, numerics-rs: If SUBSEP,
|
||||
FS, RS, OFS, or ORS were set to a numeric value, then their string values
|
||||
wouldn't always be generated before being needed.
|
||||
|
||||
13. subsep-overflow: The length of SUBSEP needs to be rechecked after
|
||||
calling execute(), in case SUBSEP itself has been changed.
|
||||
|
||||
14. split-fs-from-array: If the third argument to split() comes from the
|
||||
array passed as the second argument, then split() would previously read
|
||||
from the freed memory and possibly produce incorrect results (depending
|
||||
on the system's malloc()/free() behaviour.)
|
||||
|
||||
|
||||
|
4
bugs-fixed/concat-assign-same.awk
Normal file
4
bugs-fixed/concat-assign-same.awk
Normal file
@ -0,0 +1,4 @@
|
||||
BEGIN {
|
||||
print (a = 1) (a = 2) (a = 3) (a = 4) (a = 5);
|
||||
print (a = 1), (a = 2), (a = 3), (a = 4), (a = 5);
|
||||
}
|
2
bugs-fixed/concat-assign-same.bad
Normal file
2
bugs-fixed/concat-assign-same.bad
Normal file
@ -0,0 +1,2 @@
|
||||
22345
|
||||
1 2 3 4 5
|
2
bugs-fixed/concat-assign-same.ok
Normal file
2
bugs-fixed/concat-assign-same.ok
Normal file
@ -0,0 +1,2 @@
|
||||
12345
|
||||
1 2 3 4 5
|
1
bugs-fixed/fmt-overflow.awk
Normal file
1
bugs-fixed/fmt-overflow.awk
Normal file
@ -0,0 +1 @@
|
||||
BEGIN { OFMT = "%.1000f"; print 1.25; }
|
1
bugs-fixed/fmt-overflow.ok
Normal file
1
bugs-fixed/fmt-overflow.ok
Normal file
@ -0,0 +1 @@
|
||||
1.2500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
13
bugs-fixed/fs-overflow.awk
Normal file
13
bugs-fixed/fs-overflow.awk
Normal file
@ -0,0 +1,13 @@
|
||||
function foo() {
|
||||
a = "";
|
||||
for (i = 0; i < 10000; i++) {
|
||||
a = a "c";
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
FS = foo();
|
||||
$0="foo";
|
||||
print $1;
|
||||
}
|
1
bugs-fixed/missing-precision.awk
Normal file
1
bugs-fixed/missing-precision.awk
Normal file
@ -0,0 +1 @@
|
||||
BEGIN { printf("%*s"); }
|
2
bugs-fixed/missing-precision.ok
Normal file
2
bugs-fixed/missing-precision.ok
Normal file
@ -0,0 +1,2 @@
|
||||
./a.out: not enough args in printf(%*s)
|
||||
source line number 1
|
1
bugs-fixed/negative-nf.awk
Normal file
1
bugs-fixed/negative-nf.awk
Normal file
@ -0,0 +1 @@
|
||||
BEGIN { NF = -5; }
|
2
bugs-fixed/negative-nf.ok
Normal file
2
bugs-fixed/negative-nf.ok
Normal file
@ -0,0 +1,2 @@
|
||||
./a.out: cannot set NF to a negative value
|
||||
source line number 1
|
6
bugs-fixed/nf-self-assign.awk
Normal file
6
bugs-fixed/nf-self-assign.awk
Normal file
@ -0,0 +1,6 @@
|
||||
BEGIN {
|
||||
$0="a b c";
|
||||
OFS=",";
|
||||
NF = NF;
|
||||
print;
|
||||
}
|
1
bugs-fixed/nf-self-assign.bad
Normal file
1
bugs-fixed/nf-self-assign.bad
Normal file
@ -0,0 +1 @@
|
||||
a b c
|
1
bugs-fixed/nf-self-assign.ok
Normal file
1
bugs-fixed/nf-self-assign.ok
Normal file
@ -0,0 +1 @@
|
||||
a,b,c
|
5
bugs-fixed/numeric-fs.awk
Normal file
5
bugs-fixed/numeric-fs.awk
Normal file
@ -0,0 +1,5 @@
|
||||
BEGIN {
|
||||
FS = 0; split("20202", a); print a[1];
|
||||
FS = 1; $0="31313"; print $1;
|
||||
FS = 2; "echo 42424" | getline; print $1;
|
||||
}
|
3
bugs-fixed/numeric-fs.ok
Normal file
3
bugs-fixed/numeric-fs.ok
Normal file
@ -0,0 +1,3 @@
|
||||
2
|
||||
3
|
||||
4
|
8
bugs-fixed/numeric-output-seps.awk
Normal file
8
bugs-fixed/numeric-output-seps.awk
Normal file
@ -0,0 +1,8 @@
|
||||
BEGIN {
|
||||
$0 = "a b c";
|
||||
OFS = 1;
|
||||
ORS = 2;
|
||||
NF = 2;
|
||||
print;
|
||||
print "d", "e";
|
||||
}
|
2
bugs-fixed/numeric-output-seps.bad
Normal file
2
bugs-fixed/numeric-output-seps.bad
Normal file
@ -0,0 +1,2 @@
|
||||
a b
|
||||
d e
|
1
bugs-fixed/numeric-output-seps.ok
Normal file
1
bugs-fixed/numeric-output-seps.ok
Normal file
@ -0,0 +1 @@
|
||||
a1b2d1e2
|
6
bugs-fixed/numeric-rs.awk
Normal file
6
bugs-fixed/numeric-rs.awk
Normal file
@ -0,0 +1,6 @@
|
||||
BEGIN {
|
||||
RS = 1;
|
||||
while ("echo a1b1c1d" | getline > 0) {
|
||||
print $1;
|
||||
}
|
||||
}
|
1
bugs-fixed/numeric-rs.bad
Normal file
1
bugs-fixed/numeric-rs.bad
Normal file
@ -0,0 +1 @@
|
||||
a1b1c1d
|
4
bugs-fixed/numeric-rs.ok
Normal file
4
bugs-fixed/numeric-rs.ok
Normal file
@ -0,0 +1,4 @@
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
5
bugs-fixed/numeric-subsep.awk
Normal file
5
bugs-fixed/numeric-subsep.awk
Normal file
@ -0,0 +1,5 @@
|
||||
BEGIN {
|
||||
SUBSEP = 123.456;
|
||||
a["hello", "world"] = "foo";
|
||||
print a["hello" SUBSEP "world"];
|
||||
}
|
1
bugs-fixed/numeric-subsep.bad
Normal file
1
bugs-fixed/numeric-subsep.bad
Normal file
@ -0,0 +1 @@
|
||||
|
1
bugs-fixed/numeric-subsep.ok
Normal file
1
bugs-fixed/numeric-subsep.ok
Normal file
@ -0,0 +1 @@
|
||||
foo
|
5
bugs-fixed/split-fs-from-array.awk
Normal file
5
bugs-fixed/split-fs-from-array.awk
Normal file
@ -0,0 +1,5 @@
|
||||
BEGIN {
|
||||
a[1] = "elephantie"
|
||||
a[2] = "e"
|
||||
print split(a[1],a,a[2]), a[2], a[3], split(a[2],a,a[2])
|
||||
}
|
1
bugs-fixed/split-fs-from-array.ok
Normal file
1
bugs-fixed/split-fs-from-array.ok
Normal file
@ -0,0 +1 @@
|
||||
4 l phanti 2
|
24
bugs-fixed/subsep-overflow.awk
Normal file
24
bugs-fixed/subsep-overflow.awk
Normal file
@ -0,0 +1,24 @@
|
||||
function foo(c, n) {
|
||||
s = "";
|
||||
for (i = 0; i < n; i++) {
|
||||
s = s c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
str1 = foo("a", 4500);
|
||||
str2 = foo("b", 9000);
|
||||
|
||||
a[(SUBSEP = str1), (SUBSEP = str2), "c"] = 1;
|
||||
|
||||
for (k in a) {
|
||||
print length(k);
|
||||
}
|
||||
|
||||
print (((SUBSEP = str1), (SUBSEP = str2), "c") in a);
|
||||
print (((SUBSEP = str1) SUBSEP (SUBSEP = str2) SUBSEP "c") in a);
|
||||
delete a[(SUBSEP = str1), (SUBSEP = str2), "c"];
|
||||
print (((SUBSEP = str1), (SUBSEP = str2), "c") in a);
|
||||
print (((SUBSEP = str1) SUBSEP (SUBSEP = str2) SUBSEP "c") in a);
|
||||
}
|
5
bugs-fixed/subsep-overflow.ok
Normal file
5
bugs-fixed/subsep-overflow.ok
Normal file
@ -0,0 +1,5 @@
|
||||
27001
|
||||
1
|
||||
1
|
||||
0
|
||||
0
|
18
lex.c
18
lex.c
@ -198,6 +198,7 @@ int yylex(void)
|
||||
yylval.i = c;
|
||||
switch (c) {
|
||||
case '\n': /* {EOL} */
|
||||
lineno++;
|
||||
RET(NL);
|
||||
case '\r': /* assume \n is coming */
|
||||
case ' ': /* {WS}+ */
|
||||
@ -213,6 +214,7 @@ int yylex(void)
|
||||
case '\\':
|
||||
if (peek() == '\n') {
|
||||
input();
|
||||
lineno++;
|
||||
} else if (peek() == '\r') {
|
||||
input(); input(); /* \n */
|
||||
lineno++;
|
||||
@ -370,10 +372,11 @@ int string(void)
|
||||
case '\n':
|
||||
case '\r':
|
||||
case 0:
|
||||
*bp = '\0';
|
||||
SYNTAX( "non-terminated string %.10s...", buf );
|
||||
lineno++;
|
||||
if (c == 0) /* hopeless */
|
||||
FATAL( "giving up" );
|
||||
lineno++;
|
||||
break;
|
||||
case '\\':
|
||||
c = input();
|
||||
@ -515,6 +518,7 @@ int regexpr(void)
|
||||
if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
|
||||
FATAL("out of space for reg expr %.10s...", buf);
|
||||
if (c == '\n') {
|
||||
*bp = '\0';
|
||||
SYNTAX( "newline in regular expression %.10s...", buf );
|
||||
unput('\n');
|
||||
break;
|
||||
@ -553,19 +557,19 @@ int input(void) /* get next lexical input character */
|
||||
lexprog++;
|
||||
} else /* awk -f ... */
|
||||
c = pgetc();
|
||||
if (c == '\n')
|
||||
lineno++;
|
||||
else if (c == EOF)
|
||||
if (c == EOF)
|
||||
c = 0;
|
||||
if (ep >= ebuf + sizeof ebuf)
|
||||
ep = ebuf;
|
||||
return *ep++ = c;
|
||||
*ep = c;
|
||||
if (c != 0) {
|
||||
ep++;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
void unput(int c) /* put lexical character back on input */
|
||||
{
|
||||
if (c == '\n')
|
||||
lineno--;
|
||||
if (yysptr >= yysbuf + sizeof(yysbuf))
|
||||
FATAL("pushed back too much: %.20s...", yysbuf);
|
||||
*yysptr++ = c;
|
||||
|
18
lib.c
18
lib.c
@ -59,7 +59,7 @@ void recinit(unsigned int n)
|
||||
{
|
||||
if ( (record = (char *) malloc(n)) == NULL
|
||||
|| (fields = (char *) malloc(n+1)) == NULL
|
||||
|| (fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *))) == NULL
|
||||
|| (fldtab = (Cell **) malloc((nfields+2) * sizeof(Cell *))) == NULL
|
||||
|| (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL )
|
||||
FATAL("out of space for $0 and fields");
|
||||
*fldtab[0] = dollar0;
|
||||
@ -189,12 +189,13 @@ int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf *
|
||||
int sep, c;
|
||||
char *rr, *buf = *pbuf;
|
||||
int bufsize = *pbufsize;
|
||||
char *rs = getsval(rsloc);
|
||||
|
||||
if (strlen(*FS) >= sizeof(inputFS))
|
||||
if (strlen(getsval(fsloc)) >= sizeof (inputFS))
|
||||
FATAL("field separator %.10s... is too long", *FS);
|
||||
/*fflush(stdout); avoids some buffering problem but makes it 25% slower*/
|
||||
strcpy(inputFS, *FS); /* for subsequent field splitting */
|
||||
if ((sep = **RS) == 0) {
|
||||
if ((sep = *rs) == 0) {
|
||||
sep = '\n';
|
||||
while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
|
||||
;
|
||||
@ -208,7 +209,7 @@ int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf *
|
||||
FATAL("input record `%.30s...' too long", buf);
|
||||
*rr++ = c;
|
||||
}
|
||||
if (**RS == sep || c == EOF)
|
||||
if (*rs == sep || c == EOF)
|
||||
break;
|
||||
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
|
||||
break;
|
||||
@ -283,6 +284,8 @@ void fldbld(void) /* create fields from current record */
|
||||
}
|
||||
fr = fields;
|
||||
i = 0; /* number of fields accumulated here */
|
||||
if (strlen(getsval(fsloc)) >= sizeof (inputFS))
|
||||
FATAL("field separator %.10s... is too long", *FS);
|
||||
strcpy(inputFS, *FS);
|
||||
if (strlen(inputFS) > 1) { /* it's a regular expression */
|
||||
i = refldbld(r, inputFS);
|
||||
@ -390,6 +393,8 @@ void newfld(int n) /* add field n after end of existing lastfld */
|
||||
|
||||
void setlastfld(int n) /* set lastfld cleaning fldtab cells if necessary */
|
||||
{
|
||||
if (n < 0)
|
||||
FATAL("cannot set NF to a negative value");
|
||||
if (n > nfields)
|
||||
growfldtab(n);
|
||||
|
||||
@ -479,6 +484,7 @@ void recbld(void) /* create $0 from $1..$NF if necessary */
|
||||
{
|
||||
int i;
|
||||
char *r, *p;
|
||||
char *sep = getsval(ofsloc);
|
||||
|
||||
if (donerec == 1)
|
||||
return;
|
||||
@ -490,9 +496,9 @@ void recbld(void) /* create $0 from $1..$NF if necessary */
|
||||
while ((*r = *p++) != 0)
|
||||
r++;
|
||||
if (i < *NF) {
|
||||
if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
|
||||
if (!adjbuf(&record, &recsize, 2+strlen(sep)+r-record, recsize, &r, "recbld 2"))
|
||||
FATAL("created $0 `%.30s...' too long", record);
|
||||
for (p = *OFS; (*r = *p++) != 0; )
|
||||
for (p = sep; (*r = *p++) != 0; )
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
2
main.c
2
main.c
@ -88,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
if (strncmp(argv[1], "--", 2) == 0) { /* explicit end of args */
|
||||
if (strcmp(argv[1], "--") == 0) { /* explicit end of args */
|
||||
argc--;
|
||||
argv++;
|
||||
break;
|
||||
|
15
makefile
15
makefile
@ -34,8 +34,8 @@ CC = gcc -g -Wall -pedantic
|
||||
|
||||
# yacc options. pick one; this varies a lot by system.
|
||||
#YFLAGS = -d -S
|
||||
#YACC = bison -d -y
|
||||
YACC = yacc -d
|
||||
YACC = bison -d -y
|
||||
#YACC = yacc -d
|
||||
# -S uses sprintf in yacc parser instead of sprint
|
||||
|
||||
OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o
|
||||
@ -54,10 +54,15 @@ a.out: ytab.o $(OFILES)
|
||||
|
||||
$(OFILES): awk.h ytab.h proto.h
|
||||
|
||||
ytab.c: awk.h proto.h awkgram.y
|
||||
#Clear dependency for parallel build: (make -j)
|
||||
#YACC generated y.tab.c and y.tab.h at the same time
|
||||
#this needs to be a static pattern rules otherwise multiple target
|
||||
#are mapped onto multiple executions of yacc, which overwrite
|
||||
#each others outputs.
|
||||
y%.c y%.h: awk.h proto.h awkgram.y
|
||||
$(YACC) $(YFLAGS) awkgram.y
|
||||
mv y.tab.c ytab.c
|
||||
mv y.tab.h ytab.h
|
||||
mv y.$*.c y$*.c
|
||||
mv y.$*.h y$*.h
|
||||
|
||||
ytab.h: ytab.c
|
||||
|
||||
|
@ -135,6 +135,8 @@ int main(int argc, char *argv[])
|
||||
n = sscanf(buf, "%1c %s %s %d", &c, def, name, &tok);
|
||||
if (c != '#' || (n != 4 && strcmp(def,"define") != 0)) /* not a valid #define */
|
||||
continue;
|
||||
if (strcmp(name, "YYSTYPE_IS_DECLARED") == 0)
|
||||
continue;
|
||||
if (tok < FIRSTTOKEN || tok > LASTTOKEN) {
|
||||
/* fprintf(stderr, "maketab funny token %d %s ignored\n", tok, buf); */
|
||||
continue;
|
||||
|
57
run.c
57
run.c
@ -462,7 +462,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
|
||||
Node *np;
|
||||
char *buf;
|
||||
int bufsz = recsize;
|
||||
int nsub = strlen(*SUBSEP);
|
||||
int nsub;
|
||||
|
||||
if ((buf = (char *) malloc(bufsz)) == NULL)
|
||||
FATAL("out of memory in array");
|
||||
@ -472,6 +472,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
|
||||
for (np = a[1]; np; np = np->nnext) {
|
||||
y = execute(np); /* subscript */
|
||||
s = getsval(y);
|
||||
nsub = strlen(getsval(subseploc));
|
||||
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
|
||||
FATAL("out of memory for %s[%s...]", x->nval, buf);
|
||||
strcat(buf, s);
|
||||
@ -500,7 +501,7 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts *
|
||||
Cell *x, *y;
|
||||
Node *np;
|
||||
char *s;
|
||||
int nsub = strlen(*SUBSEP);
|
||||
int nsub;
|
||||
|
||||
x = execute(a[0]); /* Cell* for symbol table */
|
||||
if (!isarr(x))
|
||||
@ -519,9 +520,10 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts *
|
||||
for (np = a[1]; np; np = np->nnext) {
|
||||
y = execute(np); /* subscript */
|
||||
s = getsval(y);
|
||||
nsub = strlen(getsval(subseploc));
|
||||
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
|
||||
FATAL("out of memory deleting %s[%s...]", x->nval, buf);
|
||||
strcat(buf, s);
|
||||
strcat(buf, s);
|
||||
if (np->nnext)
|
||||
strcat(buf, *SUBSEP);
|
||||
tempfree(y);
|
||||
@ -540,7 +542,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
|
||||
char *buf;
|
||||
char *s;
|
||||
int bufsz = recsize;
|
||||
int nsub = strlen(*SUBSEP);
|
||||
int nsub;
|
||||
|
||||
ap = execute(a[1]); /* array name */
|
||||
if (!isarr(ap)) {
|
||||
@ -558,6 +560,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
|
||||
for (p = a[0]; p; p = p->nnext) {
|
||||
x = execute(p); /* expr */
|
||||
s = getsval(x);
|
||||
nsub = strlen(getsval(subseploc));
|
||||
if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
|
||||
FATAL("out of memory deleting %s[%s...]", x->nval, buf);
|
||||
strcat(buf, s);
|
||||
@ -863,6 +866,9 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
|
||||
FATAL("'$' not permitted in awk formats");
|
||||
}
|
||||
if (*s == '*') {
|
||||
if (a == NULL) {
|
||||
FATAL("not enough args in printf(%s)", os);
|
||||
}
|
||||
x = execute(a);
|
||||
a = a->nnext;
|
||||
sprintf(t-1, "%d", fmtwd=(int) getfval(x));
|
||||
@ -1117,8 +1123,8 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
|
||||
y = execute(a[1]);
|
||||
x = execute(a[0]);
|
||||
if (n == ASSIGN) { /* ordinary assignment */
|
||||
if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
|
||||
; /* leave alone unless it's a field */
|
||||
if (x == y && !(x->tval & (FLD|REC)) && x != nfloc)
|
||||
; /* self-assignment: leave alone unless it's a field or NF */
|
||||
else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
|
||||
setsval(x, getsval(y));
|
||||
x->fval = getfval(y);
|
||||
@ -1175,25 +1181,26 @@ Cell *cat(Node **a, int q) /* a[0] cat a[1] */
|
||||
{
|
||||
Cell *x, *y, *z;
|
||||
int n1, n2;
|
||||
char *s;
|
||||
char *s = NULL;
|
||||
int ssz = 0;
|
||||
|
||||
x = execute(a[0]);
|
||||
n1 = strlen(getsval(x));
|
||||
adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1");
|
||||
(void) strncpy(s, x->sval, ssz);
|
||||
|
||||
y = execute(a[1]);
|
||||
getsval(x);
|
||||
getsval(y);
|
||||
n1 = strlen(x->sval);
|
||||
n2 = strlen(y->sval);
|
||||
s = (char *) malloc(n1 + n2 + 1);
|
||||
if (s == NULL)
|
||||
FATAL("out of space concatenating %.15s... and %.15s...",
|
||||
x->sval, y->sval);
|
||||
strcpy(s, x->sval);
|
||||
strcpy(s+n1, y->sval);
|
||||
n2 = strlen(getsval(y));
|
||||
adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2");
|
||||
(void) strncpy(s + n1, y->sval, ssz - n1);
|
||||
|
||||
tempfree(x);
|
||||
tempfree(y);
|
||||
|
||||
z = gettemp();
|
||||
z->sval = s;
|
||||
z->tval = STR;
|
||||
|
||||
return(z);
|
||||
}
|
||||
|
||||
@ -1240,18 +1247,20 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
|
||||
{
|
||||
Cell *x = 0, *y, *ap;
|
||||
char *s, *origs;
|
||||
char *fs, *origfs = NULL;
|
||||
int sep;
|
||||
char *t, temp, num[50], *fs = 0;
|
||||
char *t, temp, num[50];
|
||||
int n, tempstat, arg3type;
|
||||
|
||||
y = execute(a[0]); /* source string */
|
||||
origs = s = strdup(getsval(y));
|
||||
arg3type = ptoi(a[3]);
|
||||
if (a[2] == 0) /* fs string */
|
||||
fs = *FS;
|
||||
fs = getsval(fsloc);
|
||||
else if (arg3type == STRING) { /* split(str,arr,"string") */
|
||||
x = execute(a[2]);
|
||||
fs = getsval(x);
|
||||
origfs = fs = strdup(getsval(x));
|
||||
tempfree(x);
|
||||
} else if (arg3type == REGEXPR)
|
||||
fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
|
||||
else
|
||||
@ -1366,9 +1375,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
|
||||
tempfree(ap);
|
||||
tempfree(y);
|
||||
free(origs);
|
||||
if (a[2] != 0 && arg3type == STRING) {
|
||||
tempfree(x);
|
||||
}
|
||||
free(origfs);
|
||||
x = gettemp();
|
||||
x->tval = NUM;
|
||||
x->fval = n;
|
||||
@ -1630,9 +1637,9 @@ Cell *printstat(Node **a, int n) /* print a[0] */
|
||||
fputs(getpssval(y), fp);
|
||||
tempfree(y);
|
||||
if (x->nnext == NULL)
|
||||
fputs(*ORS, fp);
|
||||
fputs(getsval(orsloc), fp);
|
||||
else
|
||||
fputs(*OFS, fp);
|
||||
fputs(getsval(ofsloc), fp);
|
||||
}
|
||||
if (a[1] != 0)
|
||||
fflush(fp);
|
||||
|
27
tran.c
27
tran.c
@ -55,10 +55,14 @@ Cell *fsloc; /* FS */
|
||||
Cell *nrloc; /* NR */
|
||||
Cell *nfloc; /* NF */
|
||||
Cell *fnrloc; /* FNR */
|
||||
Cell *ofsloc; /* OFS */
|
||||
Cell *orsloc; /* ORS */
|
||||
Cell *rsloc; /* RS */
|
||||
Array *ARGVtab; /* symbol table containing ARGV[...] */
|
||||
Array *ENVtab; /* symbol table containing ENVIRON[...] */
|
||||
Cell *rstartloc; /* RSTART */
|
||||
Cell *rlengthloc; /* RLENGTH */
|
||||
Cell *subseploc; /* SUBSEP */
|
||||
Cell *symtabloc; /* SYMTAB */
|
||||
|
||||
Cell *nullloc; /* a guaranteed empty cell */
|
||||
@ -88,9 +92,12 @@ void syminit(void) /* initialize symbol table with builtin vars */
|
||||
|
||||
fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
|
||||
FS = &fsloc->sval;
|
||||
RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
rsloc = setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab);
|
||||
RS = &rsloc->sval;
|
||||
ofsloc = setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab);
|
||||
OFS = &ofsloc->sval;
|
||||
orsloc = setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab);
|
||||
ORS = &orsloc->sval;
|
||||
OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
@ -100,7 +107,8 @@ void syminit(void) /* initialize symbol table with builtin vars */
|
||||
NR = &nrloc->fval;
|
||||
fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
|
||||
FNR = &fnrloc->fval;
|
||||
SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
|
||||
subseploc = setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab);
|
||||
SUBSEP = &subseploc->sval;
|
||||
rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
|
||||
RSTART = &rstartloc->fval;
|
||||
rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
|
||||
@ -310,6 +318,9 @@ Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
|
||||
} else if (isrec(vp)) {
|
||||
donefld = 0; /* mark $1... invalid */
|
||||
donerec = 1;
|
||||
} else if (vp == ofsloc) {
|
||||
if (donerec == 0)
|
||||
recbld();
|
||||
}
|
||||
if (freeable(vp))
|
||||
xfree(vp->sval); /* free any previous string */
|
||||
@ -351,7 +362,7 @@ char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
|
||||
} else if (isrec(vp)) {
|
||||
donefld = 0; /* mark $1... invalid */
|
||||
donerec = 1;
|
||||
} else if (&vp->sval == OFS) {
|
||||
} else if (vp == ofsloc) {
|
||||
if (donerec == 0)
|
||||
recbld();
|
||||
}
|
||||
@ -395,7 +406,7 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */
|
||||
|
||||
static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
|
||||
{
|
||||
char s[100]; /* BUG: unchecked */
|
||||
char s[256];
|
||||
double dtemp;
|
||||
|
||||
if ((vp->tval & (NUM | STR)) == 0)
|
||||
@ -434,9 +445,9 @@ static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cel
|
||||
if (freeable(vp)) \
|
||||
xfree(vp->sval); \
|
||||
if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \
|
||||
sprintf(s, "%.30g", vp->fval); \
|
||||
snprintf(s, sizeof (s), "%.30g", vp->fval); \
|
||||
else \
|
||||
sprintf(s, *fmt, vp->fval); \
|
||||
snprintf(s, sizeof (s), *fmt, vp->fval); \
|
||||
vp->sval = tostring(s); \
|
||||
vp->tval &= ~DONTFREE; \
|
||||
vp->tval |= STR; \
|
||||
|
Loading…
Reference in New Issue
Block a user