This commit was generated by cvs2svn to compensate for changes in r146299,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Ruslan Ermilov 2005-05-16 19:11:36 +00:00
commit e53d81968a
11 changed files with 189 additions and 130 deletions

View File

@ -25,6 +25,37 @@ THIS SOFTWARE.
This file lists all bug fixes, changes, etc., made since the AWK book
was sent to the printers in August, 1987.
Apr 24, 2005:
modified lib.c so that values of $0 et al are preserved in the END
block, apparently as required by posix. thanks to havard eidnes
for the report and code.
Jan 14, 2005:
fixed infinite loop in parsing, originally found by brian tsang.
thanks to arnold robbins for a suggestion that started me
rethinking it.
Dec 31, 2004:
prevent overflow of -f array in main, head off potential error in
call of SYNTAX(), test malloc return in lib.c, all with thanks to
todd miller.
Dec 22, 2004:
cranked up size of NCHARS; coverity thinks it can be overrun with
smaller size, and i think that's right. added some assertions to b.c
to catch places where it might overrun. the RE code is still fragile.
Dec 5, 2004:
fixed a couple of overflow problems with ridiculous field numbers:
e.g., print $(2^32-1). thanks to ruslan ermilov, giorgos keramidas
and david o'brien at freebsd.org for patches. this really should
be re-done from scratch.
Nov 21, 2004:
fixed another 25-year-old RE bug, in split. it's another failure
to (re-)initialize. thanks to steve fisher for spotting this and
providing a good test case.
Nov 22, 2003:
fixed a bug in regular expressions that dates (so help me) from 1977;
it's been there from the beginning. an anchored longest match that
@ -222,7 +253,7 @@ Apr 21, 2000:
jon bentley for the test case that found it.
added test in envinit to catch environment "variables" with
names begining with '='; thanks to Berend Hasselman.
names beginning with '='; thanks to Berend Hasselman.
Jul 28, 1999:
added test in defn() to catch function foo(foo), which
@ -459,7 +490,7 @@ May 2, 1996:
some awful behaviors.)
Apr 29, 1996:
replaced uchar by uschar everwhere; apparently some compilers
replaced uchar by uschar everywhere; apparently some compilers
usurp this name and this causes conflicts.
fixed call to time in run.c (bltin); arg is time_t *.

View File

@ -56,7 +56,7 @@ conflicts: 43 shift/reduce, 85 reduce/reduce
This produces an executable a.out; you will eventually want to
move this to some place like /usr/bin/awk.
If your system is does not have yacc or bison (the GNU
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

View File

@ -22,6 +22,8 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
#include <assert.h>
typedef double Awkfloat;
/* unsigned char is more trouble than it's worth */
@ -40,8 +42,6 @@ typedef unsigned char uschar;
# define dprintf(x)
#endif
extern char errbuf[];
extern int compile_time; /* 1 if compiling, 0 if running */
extern int safe; /* 0 => unsafe, 1 => safe */
@ -201,7 +201,7 @@ extern int pairstack[], paircnt;
/* structures used by regular expression matching machinery, mostly b.c: */
#define NCHARS (256+1) /* 256 handles 8-bit chars; 128 does 7-bit */
#define NCHARS (256+3) /* 256 handles 8-bit chars; 128 does 7-bit */
/* watch out in match(), etc. */
#define NSTATES 32

View File

@ -465,6 +465,7 @@ int match(fa *f, const char *p0) /* shortest match ? */
if (f->out[s])
return(1);
do {
assert(*p < NCHARS);
if ((ns = f->gototab[s][*p]) != 0)
s = ns;
else
@ -495,6 +496,7 @@ int pmatch(fa *f, const char *p0) /* longest match, for sub */
do {
if (f->out[s]) /* final state */
patlen = q-p;
assert(*q < NCHARS);
if ((ns = f->gototab[s][*q]) != 0)
s = ns;
else
@ -552,6 +554,7 @@ int nematch(fa *f, const char *p0) /* non-empty match, for sub */
do {
if (f->out[s]) /* final state */
patlen = q-p;
assert(*q < NCHARS);
if ((ns = f->gototab[s][*q]) != 0)
s = ns;
else
@ -834,6 +837,7 @@ int cgoto(fa *f, int s, int c)
int i, j, k;
int *p, *q;
assert(c == HAT || c < NCHARS);
while (f->accept >= maxsetvec) { /* guessing here! */
maxsetvec *= 4;
setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));

View File

@ -134,7 +134,7 @@ int gettok(char **pbuf, int *psz) /* get next input token */
}
*bp = 0;
retc = 'a'; /* alphanumeric */
} else { /* it's a number */
} else { /* maybe it's a number, but could be . */
char *rem;
/* read input until can't be a number */
for ( ; (c = input()) != 0; ) {
@ -151,13 +151,14 @@ int gettok(char **pbuf, int *psz) /* get next input token */
}
*bp = 0;
strtod(buf, &rem); /* parse the number */
unputstr(rem); /* put rest back for later */
if (rem == buf) { /* it wasn't a valid number at all */
buf[1] = 0; /* so return one character as token */
buf[1] = 0; /* return one character as token */
retc = buf[0]; /* character is its own type */
unputstr(rem+1); /* put rest back for later */
} else { /* some prefix was a number */
rem[0] = 0; /* so truncate where failure started */
retc = '0'; /* number */
unputstr(rem); /* put rest back for later */
rem[0] = 0; /* truncate buf after number part */
retc = '0'; /* type is number */
}
}
*pbuf = buf;
@ -187,8 +188,10 @@ int yylex(void)
reg = 0;
return regexpr();
}
/* printf("top\n"); */
for (;;) {
c = gettok(&buf, &bufsize);
/* printf("gettok [%s]\n", buf); */
if (c == 0)
return 0;
if (isalpha(c) || c == '_')

View File

@ -57,13 +57,11 @@ static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
void recinit(unsigned int n)
{
record = (char *) malloc(n);
fields = (char *) malloc(n);
fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *));
if (record == NULL || fields == NULL || fldtab == NULL)
if ( (record = (char *) malloc(n)) == NULL
|| (fields = (char *) malloc(n)) == NULL
|| (fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *))) == NULL
|| (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL )
FATAL("out of space for $0 and fields");
fldtab[0] = (Cell *) malloc(sizeof (Cell));
*fldtab[0] = dollar0;
fldtab[0]->sval = record;
fldtab[0]->nval = tostring("0");
@ -101,12 +99,14 @@ void initgetrec(void)
infile = stdin; /* no filenames, so use stdin */
}
static int firsttime = 1;
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
{ /* note: cares whether buf == record */
int c;
static int firsttime = 1;
char *buf = *pbuf;
int bufsize = *pbufsize;
uschar saveb0;
int bufsize = *pbufsize, savebufsize = bufsize;
if (firsttime) {
firsttime = 0;
@ -118,6 +118,7 @@ int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
donefld = 0;
donerec = 1;
}
saveb0 = buf[0];
buf[0] = 0;
while (argno < *ARGC || infile == stdin) {
dprintf( ("argno=%d, file=|%s|\n", argno, file) );
@ -164,8 +165,9 @@ int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
infile = NULL;
argno++;
}
buf[0] = saveb0;
*pbuf = buf;
*pbufsize = bufsize;
*pbufsize = savebufsize;
return 0; /* true end of file */
}
@ -378,7 +380,7 @@ void newfld(int n) /* add field n after end of existing lastfld */
Cell *fieldadr(int n) /* get nth field */
{
if (n < 0)
FATAL("trying to access field %d", n);
FATAL("trying to access out of range field %d", n);
if (n > nfields) /* fields after NF are empty */
growfldtab(n); /* but does not increase NF */
return(fldtab[n]);
@ -387,10 +389,15 @@ Cell *fieldadr(int n) /* get nth field */
void growfldtab(int n) /* make new fields up to at least $n */
{
int nf = 2 * nfields;
size_t s;
if (n > nf)
nf = n;
fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *)));
s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */
if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */
fldtab = (Cell **) realloc(fldtab, s);
else /* overflow sizeof int */
xfree(fldtab); /* make it null */
if (fldtab == NULL)
FATAL("out of space creating %d fields", nf);
makefields(nfields+1, nf);
@ -484,7 +491,7 @@ int errorflag = 0;
void yyerror(const char *s)
{
SYNTAX(s);
SYNTAX("%s", s);
}
void SYNTAX(const char *fmt, ...)

View File

@ -22,7 +22,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
const char *version = "version 20040207";
const char *version = "version 20050424";
#define DEBUG
#include <stdio.h>
@ -45,7 +45,9 @@ extern int errorflag; /* non-zero if any syntax errors; set by yyerror */
int compile_time = 2; /* for error printing: */
/* 2 = cmdline, 1 = compile, 0 = running */
char *pfile[20]; /* program filenames from -f's */
#define MAX_PFILE 20 /* max number of -f's */
char *pfile[MAX_PFILE]; /* program filenames from -f's */
int npfile = 0; /* number of filenames */
int curpfile = 0; /* current filename */
@ -81,6 +83,8 @@ int main(int argc, char *argv[])
argv++;
if (argc <= 1)
FATAL("no program filename");
if (npfile >= MAX_PFILE - 1)
FATAL("too many -f options");
pfile[npfile++] = argv[1];
break;
case 'F': /* set field separator */

View File

@ -27,9 +27,9 @@ CFLAGS = -O2
CFLAGS =
CC = gcc -Wall -g -Wwrite-strings
CC = gcc -fprofile-arcs -ftest-coverage
# followed by gcov onefile.c; cat onefile.c.gcov
CC = gcc -Wall -g
CC = /opt/SUNWspro/bin/cc
CC = /opt/pure/purify/purify cc
CC = cc
YACC = bison -y
@ -83,4 +83,4 @@ names:
@echo $(LISTING)
clean:
rm -f a.out *.o *.obj maketab maketab.exe # proctab.c
rm -f a.out *.o *.obj maketab maketab.exe *.bb *.bbg *.da *.gcov # proctab.c

View File

@ -3,98 +3,98 @@
#include "ytab.h"
static char *printname[92] = {
(char *) "FIRSTTOKEN", /* 57346 */
(char *) "PROGRAM", /* 57347 */
(char *) "PASTAT", /* 57348 */
(char *) "PASTAT2", /* 57349 */
(char *) "XBEGIN", /* 57350 */
(char *) "XEND", /* 57351 */
(char *) "NL", /* 57352 */
(char *) "ARRAY", /* 57353 */
(char *) "MATCH", /* 57354 */
(char *) "NOTMATCH", /* 57355 */
(char *) "MATCHOP", /* 57356 */
(char *) "FINAL", /* 57357 */
(char *) "DOT", /* 57358 */
(char *) "ALL", /* 57359 */
(char *) "CCL", /* 57360 */
(char *) "NCCL", /* 57361 */
(char *) "CHAR", /* 57362 */
(char *) "OR", /* 57363 */
(char *) "STAR", /* 57364 */
(char *) "QUEST", /* 57365 */
(char *) "PLUS", /* 57366 */
(char *) "AND", /* 57367 */
(char *) "BOR", /* 57368 */
(char *) "APPEND", /* 57369 */
(char *) "EQ", /* 57370 */
(char *) "GE", /* 57371 */
(char *) "GT", /* 57372 */
(char *) "LE", /* 57373 */
(char *) "LT", /* 57374 */
(char *) "NE", /* 57375 */
(char *) "IN", /* 57376 */
(char *) "ARG", /* 57377 */
(char *) "BLTIN", /* 57378 */
(char *) "BREAK", /* 57379 */
(char *) "CLOSE", /* 57380 */
(char *) "CONTINUE", /* 57381 */
(char *) "DELETE", /* 57382 */
(char *) "DO", /* 57383 */
(char *) "EXIT", /* 57384 */
(char *) "FOR", /* 57385 */
(char *) "FUNC", /* 57386 */
(char *) "SUB", /* 57387 */
(char *) "GSUB", /* 57388 */
(char *) "IF", /* 57389 */
(char *) "INDEX", /* 57390 */
(char *) "LSUBSTR", /* 57391 */
(char *) "MATCHFCN", /* 57392 */
(char *) "NEXT", /* 57393 */
(char *) "NEXTFILE", /* 57394 */
(char *) "ADD", /* 57395 */
(char *) "MINUS", /* 57396 */
(char *) "MULT", /* 57397 */
(char *) "DIVIDE", /* 57398 */
(char *) "MOD", /* 57399 */
(char *) "ASSIGN", /* 57400 */
(char *) "ASGNOP", /* 57401 */
(char *) "ADDEQ", /* 57402 */
(char *) "SUBEQ", /* 57403 */
(char *) "MULTEQ", /* 57404 */
(char *) "DIVEQ", /* 57405 */
(char *) "MODEQ", /* 57406 */
(char *) "POWEQ", /* 57407 */
(char *) "PRINT", /* 57408 */
(char *) "PRINTF", /* 57409 */
(char *) "SPRINTF", /* 57410 */
(char *) "ELSE", /* 57411 */
(char *) "INTEST", /* 57412 */
(char *) "CONDEXPR", /* 57413 */
(char *) "POSTINCR", /* 57414 */
(char *) "PREINCR", /* 57415 */
(char *) "POSTDECR", /* 57416 */
(char *) "PREDECR", /* 57417 */
(char *) "VAR", /* 57418 */
(char *) "IVAR", /* 57419 */
(char *) "VARNF", /* 57420 */
(char *) "CALL", /* 57421 */
(char *) "NUMBER", /* 57422 */
(char *) "STRING", /* 57423 */
(char *) "REGEXPR", /* 57424 */
(char *) "GETLINE", /* 57425 */
(char *) "RETURN", /* 57426 */
(char *) "SPLIT", /* 57427 */
(char *) "SUBSTR", /* 57428 */
(char *) "WHILE", /* 57429 */
(char *) "CAT", /* 57430 */
(char *) "NOT", /* 57431 */
(char *) "UMINUS", /* 57432 */
(char *) "POWER", /* 57433 */
(char *) "DECR", /* 57434 */
(char *) "INCR", /* 57435 */
(char *) "INDIRECT", /* 57436 */
(char *) "LASTTOKEN", /* 57437 */
(char *) "FIRSTTOKEN", /* 258 */
(char *) "PROGRAM", /* 259 */
(char *) "PASTAT", /* 260 */
(char *) "PASTAT2", /* 261 */
(char *) "XBEGIN", /* 262 */
(char *) "XEND", /* 263 */
(char *) "NL", /* 264 */
(char *) "ARRAY", /* 265 */
(char *) "MATCH", /* 266 */
(char *) "NOTMATCH", /* 267 */
(char *) "MATCHOP", /* 268 */
(char *) "FINAL", /* 269 */
(char *) "DOT", /* 270 */
(char *) "ALL", /* 271 */
(char *) "CCL", /* 272 */
(char *) "NCCL", /* 273 */
(char *) "CHAR", /* 274 */
(char *) "OR", /* 275 */
(char *) "STAR", /* 276 */
(char *) "QUEST", /* 277 */
(char *) "PLUS", /* 278 */
(char *) "AND", /* 279 */
(char *) "BOR", /* 280 */
(char *) "APPEND", /* 281 */
(char *) "EQ", /* 282 */
(char *) "GE", /* 283 */
(char *) "GT", /* 284 */
(char *) "LE", /* 285 */
(char *) "LT", /* 286 */
(char *) "NE", /* 287 */
(char *) "IN", /* 288 */
(char *) "ARG", /* 289 */
(char *) "BLTIN", /* 290 */
(char *) "BREAK", /* 291 */
(char *) "CLOSE", /* 292 */
(char *) "CONTINUE", /* 293 */
(char *) "DELETE", /* 294 */
(char *) "DO", /* 295 */
(char *) "EXIT", /* 296 */
(char *) "FOR", /* 297 */
(char *) "FUNC", /* 298 */
(char *) "SUB", /* 299 */
(char *) "GSUB", /* 300 */
(char *) "IF", /* 301 */
(char *) "INDEX", /* 302 */
(char *) "LSUBSTR", /* 303 */
(char *) "MATCHFCN", /* 304 */
(char *) "NEXT", /* 305 */
(char *) "NEXTFILE", /* 306 */
(char *) "ADD", /* 307 */
(char *) "MINUS", /* 308 */
(char *) "MULT", /* 309 */
(char *) "DIVIDE", /* 310 */
(char *) "MOD", /* 311 */
(char *) "ASSIGN", /* 312 */
(char *) "ASGNOP", /* 313 */
(char *) "ADDEQ", /* 314 */
(char *) "SUBEQ", /* 315 */
(char *) "MULTEQ", /* 316 */
(char *) "DIVEQ", /* 317 */
(char *) "MODEQ", /* 318 */
(char *) "POWEQ", /* 319 */
(char *) "PRINT", /* 320 */
(char *) "PRINTF", /* 321 */
(char *) "SPRINTF", /* 322 */
(char *) "ELSE", /* 323 */
(char *) "INTEST", /* 324 */
(char *) "CONDEXPR", /* 325 */
(char *) "POSTINCR", /* 326 */
(char *) "PREINCR", /* 327 */
(char *) "POSTDECR", /* 328 */
(char *) "PREDECR", /* 329 */
(char *) "VAR", /* 330 */
(char *) "IVAR", /* 331 */
(char *) "VARNF", /* 332 */
(char *) "CALL", /* 333 */
(char *) "NUMBER", /* 334 */
(char *) "STRING", /* 335 */
(char *) "REGEXPR", /* 336 */
(char *) "GETLINE", /* 337 */
(char *) "SUBSTR", /* 338 */
(char *) "SPLIT", /* 339 */
(char *) "RETURN", /* 340 */
(char *) "WHILE", /* 341 */
(char *) "CAT", /* 342 */
(char *) "UMINUS", /* 343 */
(char *) "NOT", /* 344 */
(char *) "POWER", /* 345 */
(char *) "INCR", /* 346 */
(char *) "DECR", /* 347 */
(char *) "INDIRECT", /* 348 */
(char *) "LASTTOKEN", /* 349 */
};
@ -179,16 +179,16 @@ Cell *(*proctab[92])(Node **, int) = {
nullproc, /* STRING */
nullproc, /* REGEXPR */
getline, /* GETLINE */
jump, /* RETURN */
split, /* SPLIT */
substr, /* SUBSTR */
split, /* SPLIT */
jump, /* RETURN */
whilestat, /* WHILE */
cat, /* CAT */
boolop, /* NOT */
arith, /* UMINUS */
boolop, /* NOT */
arith, /* POWER */
nullproc, /* DECR */
nullproc, /* INCR */
nullproc, /* DECR */
indirect, /* INDIRECT */
nullproc, /* LASTTOKEN */
};

View File

@ -26,6 +26,7 @@ THIS SOFTWARE.
#include <stdio.h>
#include <ctype.h>
#include <setjmp.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
@ -705,12 +706,16 @@ Cell *gettemp(void) /* get a tempcell */
Cell *indirect(Node **a, int n) /* $( a[0] ) */
{
Awkfloat val;
Cell *x;
int m;
char *s;
x = execute(a[0]);
m = (int) getfval(x);
val = getfval(x); /* freebsd: defend against super large field numbers */
if ((Awkfloat)INT_MAX < val)
FATAL("trying to access out of range field %s", x->nval);
m = (int) val;
if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
/* BUG: can x->nval ever be null??? */
@ -1257,6 +1262,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
goto spdone;
}
} while (nematch(pfa,s));
pfa->initstat = tempstat; /* bwk: has to be here to reset */
/* cf gsub and refldbld */
}
n++;
sprintf(num, "%d", n);

View File

@ -51,6 +51,7 @@ char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
Awkfloat *RLENGTH; /* length of same */
Cell *fsloc; /* FS */
Cell *nrloc; /* NR */
Cell *nfloc; /* NF */
Cell *fnrloc; /* FNR */
@ -73,7 +74,8 @@ void syminit(void) /* initialize symbol table with builtin vars */
nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
nullnode = celltonode(nullloc, CCON);
FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
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;
@ -315,7 +317,8 @@ char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
char *t;
int fldno;
dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, NN(vp->nval), s, vp->tval) );
dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, "assign to");
if (isfld(vp)) {
@ -334,7 +337,8 @@ char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
if (freeable(vp))
xfree(vp->sval);
vp->tval &= ~DONTFREE;
dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), t,t, vp->tval) );
dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
return(vp->sval = t);
}
@ -355,8 +359,7 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */
return(vp->fval);
}
static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
{
char s[100]; /* BUG: unchecked */
double dtemp;