xref: /csrg-svn/contrib/awk.research/lib.c (revision 65396)
165390Sbostic /****************************************************************
265390Sbostic Copyright (C) AT&T 1993
365390Sbostic All Rights Reserved
465390Sbostic 
565390Sbostic Permission to use, copy, modify, and distribute this software and
665390Sbostic its documentation for any purpose and without fee is hereby
765390Sbostic granted, provided that the above copyright notice appear in all
865390Sbostic copies and that both that the copyright notice and this
965390Sbostic permission notice and warranty disclaimer appear in supporting
1065390Sbostic documentation, and that the name of AT&T or any of its entities
1165390Sbostic not be used in advertising or publicity pertaining to
1265390Sbostic distribution of the software without specific, written prior
1365390Sbostic permission.
1465390Sbostic 
1565390Sbostic AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1665390Sbostic INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1765390Sbostic IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
1865390Sbostic SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1965390Sbostic WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
2065390Sbostic IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2165390Sbostic ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2265390Sbostic THIS SOFTWARE.
2365390Sbostic ****************************************************************/
2465390Sbostic 
2565390Sbostic #define DEBUG
2665390Sbostic #include <stdio.h>
2765390Sbostic #include <string.h>
2865390Sbostic #include <ctype.h>
2965390Sbostic #include <errno.h>
3065390Sbostic #include <stdlib.h>
3165390Sbostic #include "awk.h"
3265390Sbostic #include "y.tab.h"
3365390Sbostic 
3465390Sbostic #define	getfval(p)	(((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
3565390Sbostic #define	getsval(p)	(((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
3665390Sbostic 
3765390Sbostic FILE	*infile	= NULL;
3865390Sbostic uchar	*file	= (uchar*) "";
3965390Sbostic int	recsize	= RECSIZE;
4065390Sbostic uchar	*recdata;
4165390Sbostic uchar	*record;
4265390Sbostic uchar	*fields;
4365390Sbostic Cell	*fldtab;
4465390Sbostic 
4565390Sbostic #define	MAXFLD	200
4665390Sbostic int	nfields	= MAXFLD;	/* can be set from commandline in main */
4765390Sbostic 
4865390Sbostic int	donefld;	/* 1 = implies rec broken into fields */
4965390Sbostic int	donerec;	/* 1 = record is valid (no flds have changed) */
5065390Sbostic 
5165390Sbostic int	maxfld	= 0;	/* last used field */
5265390Sbostic int	argno	= 1;	/* current input argument number */
5365390Sbostic extern	Awkfloat *ARGC;
5465390Sbostic 
recinit(unsigned int n)5565390Sbostic void recinit(unsigned int n)
5665390Sbostic {
5765390Sbostic 	static Cell dollar0 = {
5865390Sbostic 	    OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE };
5965390Sbostic 	static Cell dollar1 = {
6065390Sbostic 	    OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE };
6165390Sbostic 	int i;
6265390Sbostic 
6365390Sbostic 	record = recdata = (uchar *) malloc(n);
6465390Sbostic 	fields = (uchar *) malloc(n);
6565390Sbostic 	fldtab = (Cell *) malloc(nfields * sizeof(Cell));
6665390Sbostic 	if (recdata == NULL || fields == NULL || fldtab == NULL)
6765390Sbostic 		ERROR "out of space for $0 and fields" FATAL;
6865390Sbostic 	fldtab[0] = dollar0;
6965390Sbostic 	fldtab[0].sval = recdata;
7065390Sbostic 	for (i = 1; i < nfields; i++)
7165390Sbostic 		fldtab[i] = dollar1;
7265390Sbostic }
7365390Sbostic 
initgetrec(void)7465390Sbostic void initgetrec(void)
7565390Sbostic {
7665390Sbostic 	int i;
7765390Sbostic 	uchar *p;
7865390Sbostic 
7965390Sbostic 	for (i = 1; i < *ARGC; i++) {
8065390Sbostic 		if (!isclvar(p = getargv(i))) {	/* find 1st real filename */
8165390Sbostic 			setsval(lookup("FILENAME", symtab), getargv(i));
8265390Sbostic 			return;
8365390Sbostic 		}
8465390Sbostic 		setclvar(p);	/* a commandline assignment before filename */
8565390Sbostic 		argno++;
8665390Sbostic 	}
8765390Sbostic 	infile = stdin;		/* no filenames, so use stdin */
8865390Sbostic }
8965390Sbostic 
getrec(uchar * buf)9065390Sbostic getrec(uchar *buf)	/* get next input record from whatever source */
9165390Sbostic {			/* note: tests whether buf == record */
9265390Sbostic 	int c;
9365390Sbostic 	static int firsttime = 1;
9465390Sbostic 
9565390Sbostic 	if (firsttime) {
9665390Sbostic 		firsttime = 0;
9765390Sbostic 		initgetrec();
9865390Sbostic 	}
9965390Sbostic 	dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
10065390Sbostic 		*RS, *FS, *ARGC, *FILENAME) );
10165390Sbostic 	donefld = 0;
10265390Sbostic 	donerec = 1;
10365390Sbostic 	buf[0] = 0;
10465390Sbostic 	while (argno < *ARGC || infile == stdin) {
10565390Sbostic 		dprintf( ("argno=%d, file=|%s|\n", argno, file) );
10665390Sbostic 		if (infile == NULL) {	/* have to open a new file */
10765390Sbostic 			file = getargv(argno);
10865390Sbostic 			if (*file == '\0') {	/* it's been zapped */
10965390Sbostic 				argno++;
11065390Sbostic 				continue;
11165390Sbostic 			}
11265390Sbostic 			if (isclvar(file)) {	/* a var=value arg */
11365390Sbostic 				setclvar(file);
11465390Sbostic 				argno++;
11565390Sbostic 				continue;
11665390Sbostic 			}
11765390Sbostic 			*FILENAME = file;
11865390Sbostic 			dprintf( ("opening file %s\n", file) );
11965390Sbostic 			if (*file == '-' && *(file+1) == '\0')
12065390Sbostic 				infile = stdin;
12165390Sbostic 			else if ((infile = fopen((char *)file, "r")) == NULL)
12265390Sbostic 				ERROR "can't open file %s", file FATAL;
12365390Sbostic 			setfval(fnrloc, 0.0);
12465390Sbostic 		}
12565390Sbostic 		c = readrec(buf, recsize, infile);
12665390Sbostic 		if (c != 0 || buf[0] != '\0') {	/* normal record */
12765390Sbostic 			if (buf == record) {
12865390Sbostic 				if (!(recloc->tval & DONTFREE))
12965390Sbostic 					xfree(recloc->sval);
13065390Sbostic 				recloc->sval = record;
13165390Sbostic 				recloc->tval = REC | STR | DONTFREE;
132*65396Sbostic 				if (is_a_number(recloc->sval)) {
13365390Sbostic 					recloc->fval = atof(recloc->sval);
13465390Sbostic 					recloc->tval |= NUM;
13565390Sbostic 				}
13665390Sbostic 			}
13765390Sbostic 			setfval(nrloc, nrloc->fval+1);
13865390Sbostic 			setfval(fnrloc, fnrloc->fval+1);
13965390Sbostic 			return 1;
14065390Sbostic 		}
14165390Sbostic 		/* EOF arrived on this file; set up next */
14265390Sbostic 		if (infile != stdin)
14365390Sbostic 			fclose(infile);
14465390Sbostic 		infile = NULL;
14565390Sbostic 		argno++;
14665390Sbostic 	}
14765390Sbostic 	return 0;	/* true end of file */
14865390Sbostic }
14965390Sbostic 
readrec(uchar * buf,int bufsize,FILE * inf)15065390Sbostic readrec(uchar *buf, int bufsize, FILE *inf)	/* read one record into buf */
15165390Sbostic {
15265390Sbostic 	register int sep, c;
15365390Sbostic 	register uchar *rr;
15465390Sbostic 	register int nrr;
15565390Sbostic 
15665390Sbostic 	if ((sep = **RS) == 0) {
15765390Sbostic 		sep = '\n';
15865390Sbostic 		while ((c=getc(inf)) == '\n' && c != EOF)	/* skip leading \n's */
15965390Sbostic 			;
16065390Sbostic 		if (c != EOF)
16165390Sbostic 			ungetc(c, inf);
16265390Sbostic 	}
16365390Sbostic 	for (rr = buf, nrr = bufsize; ; ) {
16465390Sbostic 		for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c)
16565390Sbostic 			if (--nrr < 0)
16665390Sbostic 				ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
16765390Sbostic 		if (**RS == sep || c == EOF)
16865390Sbostic 			break;
16965390Sbostic 		if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
17065390Sbostic 			break;
17165390Sbostic 		*rr++ = '\n';
17265390Sbostic 		*rr++ = c;
17365390Sbostic 	}
17465390Sbostic 	if (rr > buf + bufsize)
17565390Sbostic 		ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
17665390Sbostic 	*rr = 0;
17765390Sbostic 	dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
17865390Sbostic 	return c == EOF && rr == buf ? 0 : 1;
17965390Sbostic }
18065390Sbostic 
getargv(int n)18165390Sbostic uchar *getargv(int n)	/* get ARGV[n] */
18265390Sbostic {
18365390Sbostic 	Cell *x;
18465390Sbostic 	uchar *s, temp[10];
18565390Sbostic 	extern Array *ARGVtab;
18665390Sbostic 
18765390Sbostic 	sprintf((char *)temp, "%d", n);
18865390Sbostic 	x = setsymtab(temp, "", 0.0, STR, ARGVtab);
18965390Sbostic 	s = getsval(x);
19065390Sbostic 	dprintf( ("getargv(%d) returns |%s|\n", n, s) );
19165390Sbostic 	return s;
19265390Sbostic }
19365390Sbostic 
setclvar(uchar * s)19465390Sbostic void setclvar(uchar *s)	/* set var=value from s */
19565390Sbostic {
19665390Sbostic 	uchar *p;
19765390Sbostic 	Cell *q;
19865390Sbostic 
19965390Sbostic 	for (p=s; *p != '='; p++)
20065390Sbostic 		;
20165390Sbostic 	*p++ = 0;
20265390Sbostic 	p = qstring(p, '\0');
20365390Sbostic 	q = setsymtab(s, p, 0.0, STR, symtab);
20465390Sbostic 	setsval(q, p);
205*65396Sbostic 	if (is_a_number(q->sval)) {
20665390Sbostic 		q->fval = atof(q->sval);
20765390Sbostic 		q->tval |= NUM;
20865390Sbostic 	}
20965390Sbostic 	dprintf( ("command line set %s to |%s|\n", s, p) );
21065390Sbostic }
21165390Sbostic 
21265390Sbostic 
fldbld(void)21365390Sbostic void fldbld(void)	/* create fields from current record */
21465390Sbostic {
21565390Sbostic 	register uchar *r, *fr, sep;
21665390Sbostic 	Cell *p;
21765390Sbostic 	int i;
21865390Sbostic 
21965390Sbostic 	if (donefld)
22065390Sbostic 		return;
22165390Sbostic 	if (!(recloc->tval & STR))
22265390Sbostic 		getsval(recloc);
22365390Sbostic 	r = recloc->sval;
22465390Sbostic 	fr = fields;
22565390Sbostic 	i = 0;	/* number of fields accumulated here */
22665390Sbostic 	if (strlen(*FS) > 1) {	/* it's a regular expression */
22765390Sbostic 		i = refldbld(r, *FS);
22865390Sbostic 	} else if ((sep = **FS) == ' ') {	/* default whitespace */
22965390Sbostic 		for (i = 0; ; ) {
23065390Sbostic 			while (*r == ' ' || *r == '\t' || *r == '\n')
23165390Sbostic 				r++;
23265390Sbostic 			if (*r == 0)
23365390Sbostic 				break;
23465390Sbostic 			i++;
23565390Sbostic 			if (i >= nfields)
23665390Sbostic 				break;
23765390Sbostic 			if (!(fldtab[i].tval & DONTFREE))
23865390Sbostic 				xfree(fldtab[i].sval);
23965390Sbostic 			fldtab[i].sval = fr;
24065390Sbostic 			fldtab[i].tval = FLD | STR | DONTFREE;
24165390Sbostic 			do
24265390Sbostic 				*fr++ = *r++;
24365390Sbostic 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
24465390Sbostic 			*fr++ = 0;
24565390Sbostic 		}
24665390Sbostic 		*fr = 0;
24765390Sbostic 	} else if (*r != 0) {	/* if 0, it's a null field */
24865390Sbostic 		for (;;) {
24965390Sbostic 			i++;
25065390Sbostic 			if (i >= nfields)
25165390Sbostic 				break;
25265390Sbostic 			if (!(fldtab[i].tval & DONTFREE))
25365390Sbostic 				xfree(fldtab[i].sval);
25465390Sbostic 			fldtab[i].sval = fr;
25565390Sbostic 			fldtab[i].tval = FLD | STR | DONTFREE;
25665390Sbostic 			while (*r != sep && *r != '\n' && *r != '\0')	/* \n is always a separator */
25765390Sbostic 				*fr++ = *r++;
25865390Sbostic 			*fr++ = 0;
25965390Sbostic 			if (*r++ == 0)
26065390Sbostic 				break;
26165390Sbostic 		}
26265390Sbostic 		*fr = 0;
26365390Sbostic 	}
26465390Sbostic 	if (i >= nfields)
26565390Sbostic 		ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL;
26665390Sbostic 	/* clean out junk from previous record */
26765390Sbostic 	cleanfld(i, maxfld);
26865390Sbostic 	maxfld = i;
26965390Sbostic 	donefld = 1;
27065390Sbostic 	for (p = fldtab+1; p <= fldtab+maxfld; p++) {
271*65396Sbostic 		if(is_a_number(p->sval)) {
27265390Sbostic 			p->fval = atof(p->sval);
27365390Sbostic 			p->tval |= NUM;
27465390Sbostic 		}
27565390Sbostic 	}
27665390Sbostic 	setfval(nfloc, (Awkfloat) maxfld);
27765390Sbostic 	if (dbg)
27865390Sbostic 		for (p = fldtab; p <= fldtab+maxfld; p++)
27965390Sbostic 			printf("field %d: |%s|\n", p-fldtab, p->sval);
28065390Sbostic }
28165390Sbostic 
cleanfld(int n1,int n2)28265390Sbostic void cleanfld(int n1, int n2)	/* clean out fields n1..n2 inclusive */
28365390Sbostic {
28465390Sbostic 	static uchar *nullstat = (uchar *) "";
28565390Sbostic 	register Cell *p, *q;
28665390Sbostic 
28765390Sbostic 	for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
28865390Sbostic 		if (!(p->tval & DONTFREE))
28965390Sbostic 			xfree(p->sval);
29065390Sbostic 		p->tval = FLD | STR | DONTFREE;
29165390Sbostic 		p->sval = nullstat;
29265390Sbostic 	}
29365390Sbostic }
29465390Sbostic 
newfld(int n)29565390Sbostic void newfld(int n)	/* add field n (after end) */
29665390Sbostic {
29765390Sbostic 	if (n >= nfields)
29865390Sbostic 		ERROR "creating too many fields (%d); try -mf n", n, record FATAL;
29965390Sbostic 	cleanfld(maxfld, n);
30065390Sbostic 	maxfld = n;
30165390Sbostic 	setfval(nfloc, (Awkfloat) n);
30265390Sbostic }
30365390Sbostic 
refldbld(uchar * rec,uchar * fs)30465390Sbostic refldbld(uchar *rec, uchar *fs)	/* build fields from reg expr in FS */
30565390Sbostic {
30665390Sbostic 	uchar *fr;
30765390Sbostic 	int i, tempstat;
30865390Sbostic 	fa *pfa;
30965390Sbostic 
31065390Sbostic 	fr = fields;
31165390Sbostic 	*fr = '\0';
31265390Sbostic 	if (*rec == '\0')
31365390Sbostic 		return 0;
31465390Sbostic 	pfa = makedfa(fs, 1);
31565390Sbostic 	dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
31665390Sbostic 	tempstat = pfa->initstat;
31765390Sbostic 	for (i = 1; i < nfields; i++) {
31865390Sbostic 		if (!(fldtab[i].tval & DONTFREE))
31965390Sbostic 			xfree(fldtab[i].sval);
32065390Sbostic 		fldtab[i].tval = FLD | STR | DONTFREE;
32165390Sbostic 		fldtab[i].sval = fr;
32265390Sbostic 		dprintf( ("refldbld: i=%d\n", i) );
32365390Sbostic 		if (nematch(pfa, rec)) {
32465390Sbostic 			pfa->initstat = 2;	/* horrible coupling */
32565390Sbostic 			dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
32665390Sbostic 			strncpy(fr, rec, patbeg-rec);
32765390Sbostic 			fr += patbeg - rec + 1;
32865390Sbostic 			*(fr-1) = '\0';
32965390Sbostic 			rec = patbeg + patlen;
33065390Sbostic 		} else {
33165390Sbostic 			dprintf( ("no match %s\n", rec) );
33265390Sbostic 			strcpy(fr, rec);
33365390Sbostic 			pfa->initstat = tempstat;
33465390Sbostic 			break;
33565390Sbostic 		}
33665390Sbostic 	}
33765390Sbostic 	return i;
33865390Sbostic }
33965390Sbostic 
recbld(void)34065390Sbostic void recbld(void)	/* create $0 from $1..$NF if necessary */
34165390Sbostic {
34265390Sbostic 	register int i;
34365390Sbostic 	register uchar *r, *p;
34465390Sbostic 	static uchar *rec = 0;
34565390Sbostic 
34665390Sbostic 	if (donerec == 1)
34765390Sbostic 		return;
34865390Sbostic 	if (rec == 0) {
34965390Sbostic 		rec = (uchar *) malloc(recsize);
35065390Sbostic 		if (rec == 0)
35165390Sbostic 			ERROR "out of space building $0, record size %d", recsize FATAL;
35265390Sbostic 	}
35365390Sbostic 	r = rec;
35465390Sbostic 	for (i = 1; i <= *NF; i++) {
35565390Sbostic 		p = getsval(&fldtab[i]);
35665390Sbostic 		while (r < rec+recsize-1 && (*r = *p++))
35765390Sbostic 			r++;
35865390Sbostic 		if (i < *NF)
35965390Sbostic 			for (p = *OFS; r < rec+recsize-1 && (*r = *p++); )
36065390Sbostic 				r++;
36165390Sbostic 	}
36265390Sbostic 	if (r > rec + recsize - 1)
36365390Sbostic 		ERROR "built giant record `%.30s...'; try -mr n", record FATAL;
36465390Sbostic 	*r = '\0';
36565390Sbostic 	dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
36665390Sbostic 	recloc->tval = REC | STR | DONTFREE;
36765390Sbostic 	recloc->sval = record = rec;
36865390Sbostic 	dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
36965390Sbostic 	dprintf( ("recbld = |%s|\n", record) );
37065390Sbostic 	donerec = 1;
37165390Sbostic }
37265390Sbostic 
fieldadr(int n)37365390Sbostic Cell *fieldadr(int n)
37465390Sbostic {
37565390Sbostic 	if (n < 0 || n >= nfields)
37665390Sbostic 		ERROR "trying to access field %d; try -mf n", n FATAL;
37765390Sbostic 	return(&fldtab[n]);
37865390Sbostic }
37965390Sbostic 
38065390Sbostic int	errorflag	= 0;
38165390Sbostic char	errbuf[200];
38265390Sbostic 
yyerror(uchar * s)38365390Sbostic void yyerror(uchar *s)
38465390Sbostic {
38565390Sbostic 	extern uchar *cmdname, *curfname;
38665390Sbostic 	static int been_here = 0;
38765390Sbostic 
38865390Sbostic 	if (been_here++ > 2)
38965390Sbostic 		return;
39065390Sbostic 	fprintf(stderr, "%s: %s", cmdname, s);
39165390Sbostic 	fprintf(stderr, " at source line %d", lineno);
39265390Sbostic 	if (curfname != NULL)
39365390Sbostic 		fprintf(stderr, " in function %s", curfname);
39465390Sbostic 	fprintf(stderr, "\n");
39565390Sbostic 	errorflag = 2;
39665390Sbostic 	eprint();
39765390Sbostic }
39865390Sbostic 
fpecatch(int n)39965390Sbostic void fpecatch(int n)
40065390Sbostic {
40165390Sbostic 	ERROR "floating point exception %d", n FATAL;
40265390Sbostic }
40365390Sbostic 
40465390Sbostic extern int bracecnt, brackcnt, parencnt;
40565390Sbostic 
bracecheck(void)40665390Sbostic void bracecheck(void)
40765390Sbostic {
40865390Sbostic 	int c;
40965390Sbostic 	static int beenhere = 0;
41065390Sbostic 
41165390Sbostic 	if (beenhere++)
41265390Sbostic 		return;
413*65396Sbostic 	while ((c = lex_input()) != EOF && c != '\0')
41465390Sbostic 		bclass(c);
41565390Sbostic 	bcheck2(bracecnt, '{', '}');
41665390Sbostic 	bcheck2(brackcnt, '[', ']');
41765390Sbostic 	bcheck2(parencnt, '(', ')');
41865390Sbostic }
41965390Sbostic 
bcheck2(int n,int c1,int c2)42065390Sbostic void bcheck2(int n, int c1, int c2)
42165390Sbostic {
42265390Sbostic 	if (n == 1)
42365390Sbostic 		fprintf(stderr, "\tmissing %c\n", c2);
42465390Sbostic 	else if (n > 1)
42565390Sbostic 		fprintf(stderr, "\t%d missing %c's\n", n, c2);
42665390Sbostic 	else if (n == -1)
42765390Sbostic 		fprintf(stderr, "\textra %c\n", c2);
42865390Sbostic 	else if (n < -1)
42965390Sbostic 		fprintf(stderr, "\t%d extra %c's\n", -n, c2);
43065390Sbostic }
43165390Sbostic 
error(int f,char * s)43265390Sbostic void error(int f, char *s)
43365390Sbostic {
43465390Sbostic 	extern Node *curnode;
43565390Sbostic 	extern uchar *cmdname;
43665390Sbostic 
43765390Sbostic 	fflush(stdout);
43865390Sbostic 	fprintf(stderr, "%s: ", cmdname);
43965390Sbostic 	fprintf(stderr, "%s", s);
44065390Sbostic 	fprintf(stderr, "\n");
44165390Sbostic 	if (compile_time != 2 && NR && *NR > 0) {
44265390Sbostic 		fprintf(stderr, " input record number %g", *FNR);
44365390Sbostic 		if (strcmp(*FILENAME, "-") != 0)
44465390Sbostic 			fprintf(stderr, ", file %s", *FILENAME);
44565390Sbostic 		fprintf(stderr, "\n");
44665390Sbostic 	}
44765390Sbostic 	if (compile_time != 2 && curnode)
44865390Sbostic 		fprintf(stderr, " source line number %d\n", curnode->lineno);
44965390Sbostic 	else if (compile_time != 2 && lineno)
45065390Sbostic 		fprintf(stderr, " source line number %d\n", lineno);
45165390Sbostic 	eprint();
45265390Sbostic 	if (f) {
45365390Sbostic 		if (dbg > 1)		/* core dump if serious debugging on */
45465390Sbostic 			abort();
45565390Sbostic 		exit(2);
45665390Sbostic 	}
45765390Sbostic }
45865390Sbostic 
eprint(void)45965390Sbostic void eprint(void)	/* try to print context around error */
46065390Sbostic {
461*65396Sbostic #if 0
46265390Sbostic 	uchar *p, *q;
46365390Sbostic 	int c;
46465390Sbostic 	static int been_here = 0;
46565390Sbostic 	extern uchar ebuf[], *ep;
46665390Sbostic 
46765390Sbostic 	if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
46865390Sbostic 		return;
46965390Sbostic 	p = ep - 1;
47065390Sbostic 	if (p > ebuf && *p == '\n')
47165390Sbostic 		p--;
47265390Sbostic 	for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
47365390Sbostic 		;
47465390Sbostic 	while (*p == '\n')
47565390Sbostic 		p++;
47665390Sbostic 	fprintf(stderr, " context is\n\t");
47765390Sbostic 	for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
47865390Sbostic 		;
47965390Sbostic 	for ( ; p < q; p++)
48065390Sbostic 		if (*p)
48165390Sbostic 			putc(*p, stderr);
48265390Sbostic 	fprintf(stderr, " >>> ");
48365390Sbostic 	for ( ; p < ep; p++)
48465390Sbostic 		if (*p)
48565390Sbostic 			putc(*p, stderr);
48665390Sbostic 	fprintf(stderr, " <<< ");
48765390Sbostic 	if (*ep)
48865390Sbostic 		while ((c = input()) != '\n' && c != '\0' && c != EOF) {
48965390Sbostic 			putc(c, stderr);
49065390Sbostic 			bclass(c);
49165390Sbostic 		}
49265390Sbostic 	putc('\n', stderr);
49365390Sbostic 	ep = ebuf;
494*65396Sbostic #endif
49565390Sbostic }
49665390Sbostic 
bclass(int c)49765390Sbostic void bclass(int c)
49865390Sbostic {
49965390Sbostic 	switch (c) {
50065390Sbostic 	case '{': bracecnt++; break;
50165390Sbostic 	case '}': bracecnt--; break;
50265390Sbostic 	case '[': brackcnt++; break;
50365390Sbostic 	case ']': brackcnt--; break;
50465390Sbostic 	case '(': parencnt++; break;
50565390Sbostic 	case ')': parencnt--; break;
50665390Sbostic 	}
50765390Sbostic }
50865390Sbostic 
errcheck(double x,uchar * s)50965390Sbostic double errcheck(double x, uchar *s)
51065390Sbostic {
51165390Sbostic 	extern int errno;
51265390Sbostic 
51365390Sbostic 	if (errno == EDOM) {
51465390Sbostic 		errno = 0;
51565390Sbostic 		ERROR "%s argument out of domain", s WARNING;
51665390Sbostic 		x = 1;
51765390Sbostic 	} else if (errno == ERANGE) {
51865390Sbostic 		errno = 0;
51965390Sbostic 		ERROR "%s result out of range", s WARNING;
52065390Sbostic 		x = 1;
52165390Sbostic 	}
52265390Sbostic 	return x;
52365390Sbostic }
52465390Sbostic 
isclvar(uchar * s)52565390Sbostic isclvar(uchar *s)	/* is s of form var=something ? */
52665390Sbostic {
52765390Sbostic 	uchar *os = s;
52865390Sbostic 
52965390Sbostic 	if (!isalpha(*s) && *s != '_')
53065390Sbostic 		return 0;
53165390Sbostic 	for ( ; *s; s++)
53265390Sbostic 		if (!(isalnum(*s) || *s == '_'))
53365390Sbostic 			break;
53465390Sbostic 	return *s == '=' && s > os && *(s+1) != '=';
53565390Sbostic }
53665390Sbostic 
53765390Sbostic #define	MAXEXPON	38	/* maximum exponent for fp number. should be IEEE */
53865390Sbostic 
is_a_number(uchar * s)539*65396Sbostic is_a_number(uchar *s)	/* probably should be done by a library function */
54065390Sbostic {
54165390Sbostic 	register int d1, d2;
54265390Sbostic 	int point;
54365390Sbostic 	uchar *es;
54465390Sbostic 
54565390Sbostic 	d1 = d2 = point = 0;
54665390Sbostic 	while (*s == ' ' || *s == '\t' || *s == '\n')
54765390Sbostic 		s++;
54865390Sbostic 	if (*s == '\0')
54965390Sbostic 		return(0);	/* empty stuff isn't number */
55065390Sbostic 	if (*s == '+' || *s == '-')
55165390Sbostic 		s++;
55265390Sbostic 	if (!isdigit(*s) && *s != '.')
55365390Sbostic 		return(0);
55465390Sbostic 	if (isdigit(*s)) {
55565390Sbostic 		do {
55665390Sbostic 			d1++;
55765390Sbostic 			s++;
55865390Sbostic 		} while (isdigit(*s));
55965390Sbostic 	}
56065390Sbostic 	if (*s == '.') {
56165390Sbostic 		point++;
56265390Sbostic 		s++;
56365390Sbostic 	}
56465390Sbostic 	if (isdigit(*s)) {
56565390Sbostic 		d2++;
56665390Sbostic 		do {
56765390Sbostic 			s++;
56865390Sbostic 		} while (isdigit(*s));
56965390Sbostic 	}
57065390Sbostic 	if (!(d1 || point && d2))
57165390Sbostic 		return(0);
57265390Sbostic 	if (*s == 'e' || *s == 'E') {
57365390Sbostic 		s++;
57465390Sbostic 		if (*s == '+' || *s == '-')
57565390Sbostic 			s++;
57665390Sbostic 		if (!isdigit(*s))
57765390Sbostic 			return(0);
57865390Sbostic 		es = s;
57965390Sbostic 		do {
58065390Sbostic 			s++;
58165390Sbostic 		} while (isdigit(*s));
58265390Sbostic 		if (s - es > 2)
58365390Sbostic 			return(0);
58465390Sbostic 		else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
58565390Sbostic 			return(0);
58665390Sbostic 	}
58765390Sbostic 	while (*s == ' ' || *s == '\t' || *s == '\n')
58865390Sbostic 		s++;
58965390Sbostic 	if (*s == '\0')
59065390Sbostic 		return(1);
59165390Sbostic 	else
59265390Sbostic 		return(0);
59365390Sbostic }
594