[comp.bugs.sys5] Fixes to S5R2 "awk"

guy%gorodish@Sun.COM (Guy Harris) (09/26/87)

These are some fixes to the S5R2 "awk" that fix some null-pointer dereferencing
problems, clean up the code slightly, and keep it from terminating without
cleaning up after programs kicked off by "| <command>" constructs (the latter
fix comes from 4.3BSD).  These fixes probably apply in a fairly straightforward
fashion to the S5R3 and S5R3.1 versions; I think they are already in the "new
awk" in S5R3.1.  If you have an "awk" that antedates the S5R2 version, you
should pick up the S5R2 version because it is significantly faster; if you
can't, just pick up the 4.3BSD version instead, it has most of these fixes in
it.

diff -c /archbeluga/s5r2/usr/src/cmd/awk/awk.def ./awk.def
*** /archbeluga/s5r2/usr/src/cmd/awk/awk.def	Mon Jul  4 11:01:04 1983
--- ./awk.def	Wed Feb  4 14:11:57 1987
***************
*** 16,22 ****
  extern awkfloat *NF;
  extern char	**FILENAME;
  
! extern char	*record;
  extern int	dbg;
  extern int	lineno;
  extern int	errorflag;
--- 16,22 ----
  extern awkfloat *NF;
  extern char	**FILENAME;
  
! extern char	record[];
  extern int	dbg;
  extern int	lineno;
  extern int	errorflag;
***************
*** 71,77 ****
  } NODE;
  
  extern NODE	*winner;
- extern NODE	*nullstat;
  
  /* ctypes */
  #define OCELL	1
--- 71,76 ----

diff -c /archbeluga/s5r2/usr/src/cmd/awk/awk.g.y ./awk.g.y
*** /archbeluga/s5r2/usr/src/cmd/awk/awk.g.y	Mon Jul  4 11:01:04 1983
--- ./awk.g.y	Wed Feb  4 14:11:29 1987
***************
*** 236,242 ****
  		{ $$ = stat3($1, $2, 0, 0); }
  	| expr	{ $$ = exptostat($1); }
  	|		{ $$ = (int)0; }
! 	| error		{ yyclearin; yyerror("illegal statement"); }
  	;
  
  statement:
--- 236,242 ----
  		{ $$ = stat3($1, $2, 0, 0); }
  	| expr	{ $$ = exptostat($1); }
  	|		{ $$ = (int)0; }
! 	| error		{ yyclearin; yyerror("illegal statement"); $$ = (int)0;  }
  	;
  
  statement:

diff -c /archbeluga/s5r2/usr/src/cmd/awk/lib.c ./lib.c
*** /archbeluga/s5r2/usr/src/cmd/awk/lib.c	Mon Jul  4 11:01:06 1983
--- ./lib.c	Wed Feb  4 14:11:06 1987
***************
*** 6,14 ****
  FILE	*infile	= NULL;
  char	*file;
  #define	RECSIZE	(5 * 512)
! char	recdata[RECSIZE];
! char	*record	= recdata;
  char	fields[RECSIZE];
  
  #define	MAXFLD	100
  int	donefld;	/* 1 = implies rec broken into fields */
--- 6,14 ----
  FILE	*infile	= NULL;
  char	*file;
  #define	RECSIZE	(5 * 512)
! char	record[RECSIZE];
  char	fields[RECSIZE];
+ static char EMPTY[] = "";
  
  #define	MAXFLD	100
  int	donefld;	/* 1 = implies rec broken into fields */
***************
*** 15,23 ****
  int	donerec;	/* 1 = record is valid (no flds have changed) */
  int	mustfld;	/* 1 = NF seen, so always break*/
  
! #define	FINIT	{ OCELL, CFLD, 0, NULL, 0.0, FLD|STR }
  CELL fldtab[MAXFLD] = {		/* room for fields */
! 	{ OCELL, CFLD, "$record", recdata, 0.0, STR|FLD},
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
--- 15,23 ----
  int	donerec;	/* 1 = record is valid (no flds have changed) */
  int	mustfld;	/* 1 = NF seen, so always break*/
  
! #define	FINIT	{ OCELL, CFLD, 0, EMPTY, 0.0, FLD|STR }
  CELL fldtab[MAXFLD] = {		/* room for fields */
! 	{ OCELL, CFLD, "$record", record, 0.0, STR|FLD},
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
  	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
***************
*** 112,118 ****
  {
  	register char *r, *fr, sep;
  	CELL *p, *q;
- 	static char *nullstat = "";
  	int i, j;
  
  	r = record;
--- 112,117 ----
***************
*** 165,171 ****
  		if (!(p->tval&FLD))
  			xfree(p->sval);
  		p->tval = STR | FLD;
! 		p->sval = nullstat;
  	}
  	maxfld = i;
  	donefld = 1;
--- 164,170 ----
  		if (!(p->tval&FLD))
  			xfree(p->sval);
  		p->tval = STR | FLD;
! 		p->sval = EMPTY;
  	}
  	maxfld = i;
  	donefld = 1;
***************
*** 221,227 ****
  	fprintf(stderr, "awk: ");
  	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
  	fprintf(stderr, "\n");
! 	if (*NR > 0)
  		fprintf(stderr, " record number %g\n", *NR);
  	if (f)
  		exit(2);
--- 220,226 ----
  	fprintf(stderr, "awk: ");
  	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
  	fprintf(stderr, "\n");
! 	if (NR && *NR > 0)
  		fprintf(stderr, " record number %g\n", *NR);
  	if (f)
  		exit(2);

diff -c /archbeluga/s5r2/usr/src/cmd/awk/run.c ./run.c
*** /archbeluga/s5r2/usr/src/cmd/awk/run.c	Mon Jul  4 11:01:08 1983
--- ./run.c	Wed Feb  4 14:09:52 1987
***************
*** 6,17 ****
  #include	"awk.h"
  #include	"stdio.h"
  
! #define RECSIZE 512
  
  #define FILENUM	10
  struct
  {
  	FILE *fp;
  	char *fname;
  } files[FILENUM];
  FILE *popen();
--- 6,18 ----
  #include	"awk.h"
  #include	"stdio.h"
  
! #define RECSIZE BUFSIZ
  
  #define FILENUM	10
  struct
  {
  	FILE *fp;
+ 	int type;
  	char *fname;
  } files[FILENUM];
  FILE *popen();
***************
*** 40,46 ****
--- 41,54 ----
  
  run(a) NODE *a;
  {
+ 	register int i;
+ 
  	execute(a);
+ 
+ 	/* Wait for children to complete if output to a pipe. */
+ 	for (i=0; i<FILENUM; i++)
+ 		if (files[i].fp && files[i].type == '|')
+ 			pclose(files[i].fp);
  }
  
  CELL *execute(u) NODE *u;
***************
*** 86,96 ****
  	}
  	while (getrec()) {
  		x = execute(a[1]);
! 		if (isexit(x))
  			break;
  		tempfree(x);
  	}
- 	tempfree(x);
  	if (a[2] != NULL) {
  		x = execute(a[2]);
  		if (isbreak(x) || isnext(x) || iscont(x))
--- 94,105 ----
  	}
  	while (getrec()) {
  		x = execute(a[1]);
! 		if (isexit(x)) {
! 			tempfree(x);
  			break;
+ 		}
  		tempfree(x);
  	}
  	if (a[2] != NULL) {
  		x = execute(a[2]);
  		if (isbreak(x) || isnext(x) || iscont(x))
***************
*** 186,191 ****
--- 195,201 ----
  	default:
  		error(FATAL, "unknown boolean operator %d", n);
  	}
+ 	/*NOTREACHED*/
  }
  
  CELL *relop(a,n) NODE **a;
***************
*** 220,225 ****
--- 230,236 ----
  	default:
  		error(FATAL, "unknown relational operator %d", n);
  	}
+ 	/*NOTREACHED*/
  }
  
  
***************
*** 329,334 ****
--- 340,347 ----
  
  	os = s;
  	p = buf = (char *)malloc(RECSIZE);
+ 	if (p == NULL)
+ 		error(FATAL, "out of space in format");
  	while (*s) {
  		if (*s != '%') {
  			*p++ = *s++;
***************
*** 378,389 ****
  			error(FATAL, "not enough arguments in printf(%s)", os);
  		x = execute(a);
  		a = a->nnext;
! 		if (flag != 4)	/* watch out for converting to numbers! */
  			xf = getfval(x);
! 		if (flag == 1) sprintf(p, fmt, xf);
! 		else if (flag == 2) sprintf(p, fmt, (long)xf);
! 		else if (flag == 3) sprintf(p, fmt, (int)xf);
! 		else if (flag == 4) sprintf(p, fmt, x->sval==NULL ? "" : getsval(x));
  		tempfree(x);
  		p += strlen(p);
  		s++;
--- 391,404 ----
  			error(FATAL, "not enough arguments in printf(%s)", os);
  		x = execute(a);
  		a = a->nnext;
! 		if (flag == 4)	/* watch out for converting to numbers! */
! 			sprintf(p, fmt, getsval(x));
! 		else {
  			xf = getfval(x);
! 			if (flag == 1) sprintf(p, fmt, xf);
! 			else if (flag == 2) sprintf(p, fmt, (long)xf);
! 			else if (flag == 3) sprintf(p, fmt, (int)xf);
! 		}
  		tempfree(x);
  		p += strlen(p);
  		s++;
***************
*** 536,542 ****
  	getsval(y);
  	n1 = strlen(x->sval);
  	n2 = strlen(y->sval);
! 	s = (char *) malloc(n1 + n2 + 1);
  	strcpy(s, x->sval);
  	strcpy(s+n1, y->sval);
  	tempfree(y);
--- 551,558 ----
  	getsval(y);
  	n1 = strlen(x->sval);
  	n2 = strlen(y->sval);
! 	if ((s = (char *) malloc(n1 + n2 + 1)) == NULL)
! 		error(FATAL, "out of space in cat");
  	strcpy(s, x->sval);
  	strcpy(s+n1, y->sval);
  	tempfree(y);
***************
*** 711,716 ****
--- 727,733 ----
  			return(x);
  		tempfree(x);
  	}
+ 	/*NOTREACHED*/
  }
  
  CELL *forstat(a,n) NODE **a;
***************
*** 763,768 ****
--- 780,786 ----
  			tempfree(x);
  		}
  	}
+ 	return (true);
  }
  
  CELL *jump(a, n) NODE **a;
***************
*** 785,790 ****
--- 803,809 ----
  	default:
  		error(FATAL, "illegal jump type %d", n);
  	}
+ 	/*NOTREACHED*/
  }
  
  CELL *fncn(a,n) NODE **a;
***************
*** 861,867 ****
  	x = execute(b);
  	getsval(x);
  	for (i=0; i<FILENUM; i++)
! 		if (strcmp(x->sval, files[i].fname) == 0)
  			goto doit;
  	for (i=0; i<FILENUM; i++)
  		if (files[i].fp == 0)
--- 880,886 ----
  	x = execute(b);
  	getsval(x);
  	for (i=0; i<FILENUM; i++)
! 		if (files[i].fp != 0 && strcmp(x->sval, files[i].fname) == 0)
  			goto doit;
  	for (i=0; i<FILENUM; i++)
  		if (files[i].fp == 0)
***************
*** 877,882 ****
--- 896,902 ----
  	if (files[i].fp == NULL)
  		error(FATAL, "can't open file %s", x->sval);
  	files[i].fname = tostring(x->sval);
+ 	files[i].type = a;
  doit:
  	fprintf(files[i].fp, "%s", s);
  #ifndef gcos
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com