xref: /minix3/external/historical/nawk/dist/lib.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
15ea9e707SThomas Veerman /****************************************************************
25ea9e707SThomas Veerman Copyright (C) Lucent Technologies 1997
35ea9e707SThomas Veerman All Rights Reserved
45ea9e707SThomas Veerman 
55ea9e707SThomas Veerman Permission to use, copy, modify, and distribute this software and
65ea9e707SThomas Veerman its documentation for any purpose and without fee is hereby
75ea9e707SThomas Veerman granted, provided that the above copyright notice appear in all
85ea9e707SThomas Veerman copies and that both that the copyright notice and this
95ea9e707SThomas Veerman permission notice and warranty disclaimer appear in supporting
105ea9e707SThomas Veerman documentation, and that the name Lucent Technologies or any of
115ea9e707SThomas Veerman its entities not be used in advertising or publicity pertaining
125ea9e707SThomas Veerman to distribution of the software without specific, written prior
135ea9e707SThomas Veerman permission.
145ea9e707SThomas Veerman 
155ea9e707SThomas Veerman LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
165ea9e707SThomas Veerman INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
175ea9e707SThomas Veerman IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
185ea9e707SThomas Veerman SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
195ea9e707SThomas Veerman WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
205ea9e707SThomas Veerman IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
215ea9e707SThomas Veerman ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
225ea9e707SThomas Veerman THIS SOFTWARE.
235ea9e707SThomas Veerman ****************************************************************/
245ea9e707SThomas Veerman 
255ea9e707SThomas Veerman #if HAVE_NBTOOL_CONFIG_H
265ea9e707SThomas Veerman #include "nbtool_config.h"
275ea9e707SThomas Veerman #endif
285ea9e707SThomas Veerman 
295ea9e707SThomas Veerman #define DEBUG
305ea9e707SThomas Veerman #include <stdio.h>
315ea9e707SThomas Veerman #include <string.h>
325ea9e707SThomas Veerman #include <ctype.h>
335ea9e707SThomas Veerman #include <errno.h>
345ea9e707SThomas Veerman #include <stdlib.h>
355ea9e707SThomas Veerman #include <stdarg.h>
365ea9e707SThomas Veerman #include "awk.h"
375ea9e707SThomas Veerman #include "awkgram.h"
385ea9e707SThomas Veerman 
395ea9e707SThomas Veerman char	EMPTY[] = { '\0' };
405ea9e707SThomas Veerman FILE	*infile	= NULL;
415ea9e707SThomas Veerman int	innew;		/* 1 = infile has not been read by readrec */
425ea9e707SThomas Veerman char	*file	= EMPTY;
435ea9e707SThomas Veerman uschar	*record;
445ea9e707SThomas Veerman int	recsize	= RECSIZE;
455ea9e707SThomas Veerman char	*fields;
465ea9e707SThomas Veerman int	fieldssize = RECSIZE;
475ea9e707SThomas Veerman 
485ea9e707SThomas Veerman Cell	**fldtab;	/* pointers to Cells */
495ea9e707SThomas Veerman 
505ea9e707SThomas Veerman static size_t	len_inputFS = 0;
515ea9e707SThomas Veerman static char	*inputFS = NULL;
525ea9e707SThomas Veerman 
535ea9e707SThomas Veerman #define	MAXFLD	2
545ea9e707SThomas Veerman int	nfields	= MAXFLD;	/* last allocated slot for $i */
555ea9e707SThomas Veerman 
565ea9e707SThomas Veerman int	donefld;	/* 1 = implies rec broken into fields */
575ea9e707SThomas Veerman int	donerec;	/* 1 = record is valid (no flds have changed) */
585ea9e707SThomas Veerman 
595ea9e707SThomas Veerman int	lastfld	= 0;	/* last used field */
605ea9e707SThomas Veerman int	argno	= 1;	/* current input argument number */
615ea9e707SThomas Veerman extern	Awkfloat *ARGC;
625ea9e707SThomas Veerman 
635ea9e707SThomas Veerman static Cell dollar0 = { OCELL, CFLD, NULL, EMPTY, 0.0, REC|STR|DONTFREE, NULL };
645ea9e707SThomas Veerman static Cell dollar1 = { OCELL, CFLD, NULL, EMPTY, 0.0, FLD|STR|DONTFREE, NULL };
655ea9e707SThomas Veerman 
recinit(unsigned int n)665ea9e707SThomas Veerman void recinit(unsigned int n)
675ea9e707SThomas Veerman {
685ea9e707SThomas Veerman 	if ( (record = malloc(n)) == NULL
695ea9e707SThomas Veerman 	  || (fields = malloc(n+1)) == NULL
705ea9e707SThomas Veerman 	  || (fldtab = malloc((nfields+1) * sizeof(*fldtab))) == NULL
715ea9e707SThomas Veerman 	  || (fldtab[0] = malloc(sizeof(**fldtab))) == NULL )
725ea9e707SThomas Veerman 		FATAL("out of space for $0 and fields");
735ea9e707SThomas Veerman 	*fldtab[0] = dollar0;
745ea9e707SThomas Veerman 	fldtab[0]->sval = record;
755ea9e707SThomas Veerman 	fldtab[0]->nval = tostring("0");
765ea9e707SThomas Veerman 	makefields(1, nfields);
775ea9e707SThomas Veerman }
785ea9e707SThomas Veerman 
makefields(int n1,int n2)795ea9e707SThomas Veerman void makefields(int n1, int n2)		/* create $n1..$n2 inclusive */
805ea9e707SThomas Veerman {
815ea9e707SThomas Veerman 	char temp[50];
825ea9e707SThomas Veerman 	int i;
835ea9e707SThomas Veerman 
845ea9e707SThomas Veerman 	for (i = n1; i <= n2; i++) {
855ea9e707SThomas Veerman 		fldtab[i] = malloc(sizeof(**fldtab));
865ea9e707SThomas Veerman 		if (fldtab[i] == NULL)
875ea9e707SThomas Veerman 			FATAL("out of space in makefields %d", i);
885ea9e707SThomas Veerman 		*fldtab[i] = dollar1;
895ea9e707SThomas Veerman 		snprintf(temp, sizeof(temp), "%d", i);
905ea9e707SThomas Veerman 		fldtab[i]->nval = tostring(temp);
915ea9e707SThomas Veerman 	}
925ea9e707SThomas Veerman }
935ea9e707SThomas Veerman 
initgetrec(void)945ea9e707SThomas Veerman void initgetrec(void)
955ea9e707SThomas Veerman {
965ea9e707SThomas Veerman 	int i;
975ea9e707SThomas Veerman 	char *p;
985ea9e707SThomas Veerman 
995ea9e707SThomas Veerman 	for (i = 1; i < *ARGC; i++) {
100*84d9c625SLionel Sambuc 		p = getargv(i); /* find 1st real filename */
101*84d9c625SLionel Sambuc 		if (p == NULL || *p == '\0') {  /* deleted or zapped */
102*84d9c625SLionel Sambuc 			argno++;
103*84d9c625SLionel Sambuc 			continue;
104*84d9c625SLionel Sambuc 		}
105*84d9c625SLionel Sambuc 		if (!isclvar(p)) {
106*84d9c625SLionel Sambuc 			setsval(lookup("FILENAME", symtab), p);
1075ea9e707SThomas Veerman 			return;
1085ea9e707SThomas Veerman 		}
1095ea9e707SThomas Veerman 		setclvar(p);	/* a commandline assignment before filename */
1105ea9e707SThomas Veerman 		argno++;
1115ea9e707SThomas Veerman 	}
1125ea9e707SThomas Veerman 	infile = stdin;		/* no filenames, so use stdin */
1135ea9e707SThomas Veerman 	innew = 1;
1145ea9e707SThomas Veerman }
1155ea9e707SThomas Veerman 
1165ea9e707SThomas Veerman static int firsttime = 1;
1175ea9e707SThomas Veerman 
getrec(uschar ** pbuf,int * pbufsize,int isrecord)1185ea9e707SThomas Veerman int getrec(uschar **pbuf, int *pbufsize, int isrecord)	/* get next input record */
1195ea9e707SThomas Veerman {			/* note: cares whether buf == record */
1205ea9e707SThomas Veerman 	int c;
1215ea9e707SThomas Veerman 	uschar *buf = *pbuf;
1225ea9e707SThomas Veerman 	uschar saveb0;
1235ea9e707SThomas Veerman 	int bufsize = *pbufsize, savebufsize = bufsize;
1245ea9e707SThomas Veerman 
1255ea9e707SThomas Veerman 	if (firsttime) {
1265ea9e707SThomas Veerman 		firsttime = 0;
1275ea9e707SThomas Veerman 		initgetrec();
1285ea9e707SThomas Veerman 	}
1295ea9e707SThomas Veerman 	   dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
1305ea9e707SThomas Veerman 		*RS, *FS, *ARGC, *FILENAME) );
1315ea9e707SThomas Veerman 	if (isrecord) {
1325ea9e707SThomas Veerman 		donefld = 0;
1335ea9e707SThomas Veerman 		donerec = 1;
1345ea9e707SThomas Veerman 	}
1355ea9e707SThomas Veerman 	saveb0 = buf[0];
1365ea9e707SThomas Veerman 	buf[0] = 0;
1375ea9e707SThomas Veerman 	while (argno < *ARGC || infile == stdin) {
1385ea9e707SThomas Veerman 		   dprintf( ("argno=%d, file=|%s|\n", argno, file) );
1395ea9e707SThomas Veerman 		if (infile == NULL) {	/* have to open a new file */
1405ea9e707SThomas Veerman 			file = getargv(argno);
141*84d9c625SLionel Sambuc 			if (file == NULL || *file == '\0') {	/* deleted or zapped */
1425ea9e707SThomas Veerman 				argno++;
1435ea9e707SThomas Veerman 				continue;
1445ea9e707SThomas Veerman 			}
1455ea9e707SThomas Veerman 			if (isclvar(file)) {	/* a var=value arg */
1465ea9e707SThomas Veerman 				setclvar(file);
1475ea9e707SThomas Veerman 				argno++;
1485ea9e707SThomas Veerman 				continue;
1495ea9e707SThomas Veerman 			}
1505ea9e707SThomas Veerman 			*FILENAME = file;
1515ea9e707SThomas Veerman 			   dprintf( ("opening file %s\n", file) );
1525ea9e707SThomas Veerman 			if (*file == '-' && *(file+1) == '\0')
1535ea9e707SThomas Veerman 				infile = stdin;
1545ea9e707SThomas Veerman 			else if ((infile = fopen(file, "r")) == NULL)
1555ea9e707SThomas Veerman 				FATAL("can't open file %s", file);
1565ea9e707SThomas Veerman 			innew = 1;
1575ea9e707SThomas Veerman 			setfval(fnrloc, 0.0);
1585ea9e707SThomas Veerman 		}
1595ea9e707SThomas Veerman 		c = readrec(&buf, &bufsize, infile, innew);
1605ea9e707SThomas Veerman 		if (innew)
1615ea9e707SThomas Veerman 			innew = 0;
1625ea9e707SThomas Veerman 		if (c != 0 || buf[0] != '\0') {	/* normal record */
1635ea9e707SThomas Veerman 			if (isrecord) {
1645ea9e707SThomas Veerman 				if (freeable(fldtab[0]))
1655ea9e707SThomas Veerman 					xfree(fldtab[0]->sval);
1665ea9e707SThomas Veerman 				fldtab[0]->sval = buf;	/* buf == record */
1675ea9e707SThomas Veerman 				fldtab[0]->tval = REC | STR | DONTFREE;
1685ea9e707SThomas Veerman 				if (is_number(fldtab[0]->sval)) {
1695ea9e707SThomas Veerman 					fldtab[0]->fval = atof(fldtab[0]->sval);
1705ea9e707SThomas Veerman 					fldtab[0]->tval |= NUM;
1715ea9e707SThomas Veerman 				}
1725ea9e707SThomas Veerman 			}
1735ea9e707SThomas Veerman 			setfval(nrloc, nrloc->fval+1);
1745ea9e707SThomas Veerman 			setfval(fnrloc, fnrloc->fval+1);
1755ea9e707SThomas Veerman 			*pbuf = buf;
1765ea9e707SThomas Veerman 			*pbufsize = bufsize;
1775ea9e707SThomas Veerman 			return 1;
1785ea9e707SThomas Veerman 		}
1795ea9e707SThomas Veerman 		/* EOF arrived on this file; set up next */
1805ea9e707SThomas Veerman 		if (infile != stdin)
1815ea9e707SThomas Veerman 			fclose(infile);
1825ea9e707SThomas Veerman 		infile = NULL;
1835ea9e707SThomas Veerman 		argno++;
1845ea9e707SThomas Veerman 	}
1855ea9e707SThomas Veerman 	buf[0] = saveb0;
1865ea9e707SThomas Veerman 	*pbuf = buf;
1875ea9e707SThomas Veerman 	*pbufsize = savebufsize;
1885ea9e707SThomas Veerman 	return 0;	/* true end of file */
1895ea9e707SThomas Veerman }
1905ea9e707SThomas Veerman 
nextfile(void)1915ea9e707SThomas Veerman void nextfile(void)
1925ea9e707SThomas Veerman {
1935ea9e707SThomas Veerman 	if (infile != NULL && infile != stdin)
1945ea9e707SThomas Veerman 		fclose(infile);
1955ea9e707SThomas Veerman 	infile = NULL;
1965ea9e707SThomas Veerman 	argno++;
1975ea9e707SThomas Veerman }
1985ea9e707SThomas Veerman 
readrec(uschar ** pbuf,int * pbufsize,FILE * inf,int newflag)1995ea9e707SThomas Veerman int readrec(uschar **pbuf, int *pbufsize, FILE *inf, int newflag)	/* read one record into buf */
2005ea9e707SThomas Veerman {
2015ea9e707SThomas Veerman 	int sep, c, isrec, found, tempstat;
2025ea9e707SThomas Veerman 	uschar *rr, *buf = *pbuf;
2035ea9e707SThomas Veerman 	int bufsize = *pbufsize;
2045ea9e707SThomas Veerman 	size_t len;
2055ea9e707SThomas Veerman 
2065ea9e707SThomas Veerman 	if ((len = strlen(*FS)) < len_inputFS) {
2075ea9e707SThomas Veerman 		strcpy(inputFS, *FS);	/* for subsequent field splitting */
2085ea9e707SThomas Veerman 	} else {
2095ea9e707SThomas Veerman 		len_inputFS = len + 1;
2105ea9e707SThomas Veerman 		inputFS = realloc(inputFS, len_inputFS);
2115ea9e707SThomas Veerman 		if (inputFS == NULL)
2125ea9e707SThomas Veerman 			FATAL("field separator %.10s... is too long", *FS);
2135ea9e707SThomas Veerman 		memcpy(inputFS, *FS, len_inputFS);
2145ea9e707SThomas Veerman 	}
215*84d9c625SLionel Sambuc 	/*fflush(stdout); avoids some buffering problem but makes it 25% slower*/
2165ea9e707SThomas Veerman 	if (**RS && (*RS)[1]) {
2175ea9e707SThomas Veerman 		fa *pfa = makedfa(*RS, 1);
2185ea9e707SThomas Veerman 		if (newflag)
2195ea9e707SThomas Veerman 			found = fnematch(pfa, inf, &buf, &bufsize, recsize);
2205ea9e707SThomas Veerman 		else {
2215ea9e707SThomas Veerman 			tempstat = pfa->initstat;
2225ea9e707SThomas Veerman 			pfa->initstat = 2;
2235ea9e707SThomas Veerman 			found = fnematch(pfa, inf, &buf, &bufsize, recsize);
2245ea9e707SThomas Veerman 			pfa->initstat = tempstat;
2255ea9e707SThomas Veerman 		}
2265ea9e707SThomas Veerman 		if (found)
2275ea9e707SThomas Veerman 			*patbeg = 0;
2285ea9e707SThomas Veerman 	} else {
2295ea9e707SThomas Veerman 		if ((sep = **RS) == 0) {
2305ea9e707SThomas Veerman 			sep = '\n';
2315ea9e707SThomas Veerman 			while ((c=getc(inf)) == '\n' && c != EOF)	/* skip leading \n's */
2325ea9e707SThomas Veerman 				;
2335ea9e707SThomas Veerman 			if (c != EOF)
2345ea9e707SThomas Veerman 				ungetc(c, inf);
2355ea9e707SThomas Veerman 		}
2365ea9e707SThomas Veerman 		for (rr = buf; ; ) {
2375ea9e707SThomas Veerman 			for (; (c=getc(inf)) != sep && c != EOF; ) {
2385ea9e707SThomas Veerman 				if (rr-buf+1 > bufsize)
2395ea9e707SThomas Veerman 					if (!adjbuf(&buf, &bufsize, 1+rr-buf,
2405ea9e707SThomas Veerman 					    recsize, &rr, "readrec 1"))
2415ea9e707SThomas Veerman 						FATAL("input record `%.30s...'"
2425ea9e707SThomas Veerman 						    " too long", buf);
2435ea9e707SThomas Veerman 				*rr++ = c;
2445ea9e707SThomas Veerman 			}
2455ea9e707SThomas Veerman 			if (**RS == sep || c == EOF)
2465ea9e707SThomas Veerman 				break;
2475ea9e707SThomas Veerman 			if ((c = getc(inf)) == '\n' || c == EOF)
2485ea9e707SThomas Veerman 				/* 2 in a row */
2495ea9e707SThomas Veerman 				break;
2505ea9e707SThomas Veerman 			if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr,
2515ea9e707SThomas Veerman 			    "readrec 2"))
2525ea9e707SThomas Veerman 				FATAL("input record `%.30s...' too long", buf);
2535ea9e707SThomas Veerman 			*rr++ = '\n';
2545ea9e707SThomas Veerman 			*rr++ = c;
2555ea9e707SThomas Veerman 		}
2565ea9e707SThomas Veerman 		if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
2575ea9e707SThomas Veerman 			FATAL("input record `%.30s...' too long", buf);
2585ea9e707SThomas Veerman 		*rr = 0;
2595ea9e707SThomas Veerman 	}
2605ea9e707SThomas Veerman 	*pbuf = buf;
2615ea9e707SThomas Veerman 	*pbufsize = bufsize;
2625ea9e707SThomas Veerman 	isrec = *buf || !feof(inf);
2635ea9e707SThomas Veerman 	   dprintf( ("readrec saw <%s>, returns %d\n", buf, isrec) );
2645ea9e707SThomas Veerman 	return isrec;
2655ea9e707SThomas Veerman }
2665ea9e707SThomas Veerman 
getargv(int n)2675ea9e707SThomas Veerman char *getargv(int n)	/* get ARGV[n] */
2685ea9e707SThomas Veerman {
2695ea9e707SThomas Veerman 	Cell *x;
2705ea9e707SThomas Veerman 	char *s, temp[50];
2715ea9e707SThomas Veerman 	extern Array *ARGVtab;
2725ea9e707SThomas Veerman 
2735ea9e707SThomas Veerman 	snprintf(temp, sizeof(temp), "%d", n);
274*84d9c625SLionel Sambuc 	if (lookup(temp, ARGVtab) == NULL)
275*84d9c625SLionel Sambuc 		return NULL;
2765ea9e707SThomas Veerman 	x = setsymtab(temp, "", 0.0, STR, ARGVtab);
2775ea9e707SThomas Veerman 	s = getsval(x);
2785ea9e707SThomas Veerman 	   dprintf( ("getargv(%d) returns |%s|\n", n, s) );
2795ea9e707SThomas Veerman 	return s;
2805ea9e707SThomas Veerman }
2815ea9e707SThomas Veerman 
setclvar(char * s)2825ea9e707SThomas Veerman void setclvar(char *s)	/* set var=value from s */
2835ea9e707SThomas Veerman {
2845ea9e707SThomas Veerman 	char *p;
2855ea9e707SThomas Veerman 	Cell *q;
2865ea9e707SThomas Veerman 
2875ea9e707SThomas Veerman 	for (p=s; *p != '='; p++)
2885ea9e707SThomas Veerman 		;
2895ea9e707SThomas Veerman 	*p++ = 0;
2905ea9e707SThomas Veerman 	p = qstring(p, '\0');
2915ea9e707SThomas Veerman 	q = setsymtab(s, p, 0.0, STR, symtab);
2925ea9e707SThomas Veerman 	setsval(q, p);
2935ea9e707SThomas Veerman 	if (is_number(q->sval)) {
2945ea9e707SThomas Veerman 		q->fval = atof(q->sval);
2955ea9e707SThomas Veerman 		q->tval |= NUM;
2965ea9e707SThomas Veerman 	}
2975ea9e707SThomas Veerman 	   dprintf( ("command line set %s to |%s|\n", s, p) );
2985ea9e707SThomas Veerman }
2995ea9e707SThomas Veerman 
3005ea9e707SThomas Veerman 
fldbld(void)3015ea9e707SThomas Veerman void fldbld(void)	/* create fields from current record */
3025ea9e707SThomas Veerman {
3035ea9e707SThomas Veerman 	/* this relies on having fields[] the same length as $0 */
3045ea9e707SThomas Veerman 	/* the fields are all stored in this one array with \0's */
305*84d9c625SLionel Sambuc 	/* possibly with a final trailing \0 not associated with any field */
3065ea9e707SThomas Veerman 	char *r, *fr, sep;
3075ea9e707SThomas Veerman 	Cell *p;
3085ea9e707SThomas Veerman 	int i, j, n;
3095ea9e707SThomas Veerman 
3105ea9e707SThomas Veerman 	if (donefld)
3115ea9e707SThomas Veerman 		return;
3125ea9e707SThomas Veerman 	if (!isstr(fldtab[0]))
3135ea9e707SThomas Veerman 		getsval(fldtab[0]);
3145ea9e707SThomas Veerman 	r = fldtab[0]->sval;
3155ea9e707SThomas Veerman 	n = strlen(r);
3165ea9e707SThomas Veerman 	if (n > fieldssize) {
3175ea9e707SThomas Veerman 		xfree(fields);
318*84d9c625SLionel Sambuc 		if ((fields = malloc(n+2)) == NULL) /* possibly 2 final \0s */
3195ea9e707SThomas Veerman 			FATAL("out of space for fields in fldbld %d", n);
3205ea9e707SThomas Veerman 		fieldssize = n;
3215ea9e707SThomas Veerman 	}
3225ea9e707SThomas Veerman 	fr = fields;
3235ea9e707SThomas Veerman 	i = 0;	/* number of fields accumulated here */
3245ea9e707SThomas Veerman 	if (!inputFS) {
3255ea9e707SThomas Veerman 		/* do nothing */
3265ea9e707SThomas Veerman 	} else if (inputFS[0] && inputFS[1]) {	/* it's a regular expression */
3275ea9e707SThomas Veerman 		i = refldbld(r, inputFS);
3285ea9e707SThomas Veerman 	} else if ((sep = *inputFS) == ' ') {	/* default whitespace */
3295ea9e707SThomas Veerman 		for (i = 0; ; ) {
3305ea9e707SThomas Veerman 			while (*r == ' ' || *r == '\t' || *r == '\n')
3315ea9e707SThomas Veerman 				r++;
3325ea9e707SThomas Veerman 			if (*r == 0)
3335ea9e707SThomas Veerman 				break;
3345ea9e707SThomas Veerman 			i++;
3355ea9e707SThomas Veerman 			if (i > nfields)
3365ea9e707SThomas Veerman 				growfldtab(i);
3375ea9e707SThomas Veerman 			if (freeable(fldtab[i]))
3385ea9e707SThomas Veerman 				xfree(fldtab[i]->sval);
3395ea9e707SThomas Veerman 			fldtab[i]->sval = fr;
3405ea9e707SThomas Veerman 			fldtab[i]->tval = FLD | STR | DONTFREE;
3415ea9e707SThomas Veerman 			do
3425ea9e707SThomas Veerman 				*fr++ = *r++;
3435ea9e707SThomas Veerman 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
3445ea9e707SThomas Veerman 			*fr++ = 0;
3455ea9e707SThomas Veerman 		}
3465ea9e707SThomas Veerman 		*fr = 0;
3475ea9e707SThomas Veerman 	} else if ((sep = *inputFS) == 0) {		/* new: FS="" => 1 char/field */
3485ea9e707SThomas Veerman 		for (i = 0; *r != 0; r++) {
3495ea9e707SThomas Veerman 			char buf[2];
3505ea9e707SThomas Veerman 			i++;
3515ea9e707SThomas Veerman 			if (i > nfields)
3525ea9e707SThomas Veerman 				growfldtab(i);
3535ea9e707SThomas Veerman 			if (freeable(fldtab[i]))
3545ea9e707SThomas Veerman 				xfree(fldtab[i]->sval);
3555ea9e707SThomas Veerman 			buf[0] = *r;
3565ea9e707SThomas Veerman 			buf[1] = 0;
3575ea9e707SThomas Veerman 			fldtab[i]->sval = tostring(buf);
3585ea9e707SThomas Veerman 			fldtab[i]->tval = FLD | STR;
3595ea9e707SThomas Veerman 		}
3605ea9e707SThomas Veerman 		*fr = 0;
3615ea9e707SThomas Veerman 	} else if (*r != 0) {	/* if 0, it's a null field */
3625ea9e707SThomas Veerman 		/* subtlecase : if length(FS) == 1 && length(RS > 0)
3635ea9e707SThomas Veerman 		 * \n is NOT a field separator (cf awk book 61,84).
3645ea9e707SThomas Veerman 		 * this variable is tested in the inner while loop.
3655ea9e707SThomas Veerman 		 */
3665ea9e707SThomas Veerman 		int rtest = '\n';  /* normal case */
3675ea9e707SThomas Veerman 		if (strlen(*RS) > 0)
3685ea9e707SThomas Veerman 			rtest = '\0';
3695ea9e707SThomas Veerman 		for (;;) {
3705ea9e707SThomas Veerman 			i++;
3715ea9e707SThomas Veerman 			if (i > nfields)
3725ea9e707SThomas Veerman 				growfldtab(i);
3735ea9e707SThomas Veerman 			if (freeable(fldtab[i]))
3745ea9e707SThomas Veerman 				xfree(fldtab[i]->sval);
3755ea9e707SThomas Veerman 			fldtab[i]->sval = fr;
3765ea9e707SThomas Veerman 			fldtab[i]->tval = FLD | STR | DONTFREE;
3775ea9e707SThomas Veerman 			while (*r != sep && *r != rtest && *r != '\0')	/* \n is always a separator */
3785ea9e707SThomas Veerman 				*fr++ = *r++;
3795ea9e707SThomas Veerman 			*fr++ = 0;
3805ea9e707SThomas Veerman 			if (*r++ == 0)
3815ea9e707SThomas Veerman 				break;
3825ea9e707SThomas Veerman 		}
3835ea9e707SThomas Veerman 		*fr = 0;
3845ea9e707SThomas Veerman 	}
3855ea9e707SThomas Veerman 	if (i > nfields)
3865ea9e707SThomas Veerman 		FATAL("record `%.30s...' has too many fields; can't happen", r);
3875ea9e707SThomas Veerman 	cleanfld(i+1, lastfld);	/* clean out junk from previous record */
3885ea9e707SThomas Veerman 	lastfld = i;
3895ea9e707SThomas Veerman 	donefld = 1;
3905ea9e707SThomas Veerman 	for (j = 1; j <= lastfld; j++) {
3915ea9e707SThomas Veerman 		p = fldtab[j];
3925ea9e707SThomas Veerman 		if(is_number(p->sval)) {
3935ea9e707SThomas Veerman 			p->fval = atof(p->sval);
3945ea9e707SThomas Veerman 			p->tval |= NUM;
3955ea9e707SThomas Veerman 		}
3965ea9e707SThomas Veerman 	}
3975ea9e707SThomas Veerman 	setfval(nfloc, (Awkfloat) lastfld);
3985ea9e707SThomas Veerman 	donerec = 1; /* restore */
3995ea9e707SThomas Veerman 	if (dbg) {
4005ea9e707SThomas Veerman 		for (j = 0; j <= lastfld; j++) {
4015ea9e707SThomas Veerman 			p = fldtab[j];
4025ea9e707SThomas Veerman 			printf("field %d (%s): |%s|\n", j, p->nval, p->sval);
4035ea9e707SThomas Veerman 		}
4045ea9e707SThomas Veerman 	}
4055ea9e707SThomas Veerman }
4065ea9e707SThomas Veerman 
cleanfld(int n1,int n2)4075ea9e707SThomas Veerman void cleanfld(int n1, int n2)	/* clean out fields n1 .. n2 inclusive */
4085ea9e707SThomas Veerman {				/* nvals remain intact */
4095ea9e707SThomas Veerman 	Cell *p;
4105ea9e707SThomas Veerman 	int i;
4115ea9e707SThomas Veerman 
4125ea9e707SThomas Veerman 	for (i = n1; i <= n2; i++) {
4135ea9e707SThomas Veerman 		p = fldtab[i];
4145ea9e707SThomas Veerman 		if (freeable(p))
4155ea9e707SThomas Veerman 			xfree(p->sval);
4165ea9e707SThomas Veerman 		p->sval = EMPTY;
4175ea9e707SThomas Veerman 		p->tval = FLD | STR | DONTFREE;
4185ea9e707SThomas Veerman 	}
4195ea9e707SThomas Veerman }
4205ea9e707SThomas Veerman 
newfld(int n)4215ea9e707SThomas Veerman void newfld(int n)	/* add field n after end of existing lastfld */
4225ea9e707SThomas Veerman {
4235ea9e707SThomas Veerman 	if (n > nfields)
4245ea9e707SThomas Veerman 		growfldtab(n);
4255ea9e707SThomas Veerman 	cleanfld(lastfld+1, n);
4265ea9e707SThomas Veerman 	lastfld = n;
4275ea9e707SThomas Veerman 	setfval(nfloc, (Awkfloat) n);
4285ea9e707SThomas Veerman }
4295ea9e707SThomas Veerman 
setlastfld(int n)4305ea9e707SThomas Veerman void setlastfld(int n)	/* set lastfld cleaning fldtab cells if necessary */
4315ea9e707SThomas Veerman {
4325ea9e707SThomas Veerman 	if (n > nfields)
4335ea9e707SThomas Veerman 		growfldtab(n);
4345ea9e707SThomas Veerman 
4355ea9e707SThomas Veerman 	if (lastfld < n)
4365ea9e707SThomas Veerman 	    cleanfld(lastfld+1, n);
4375ea9e707SThomas Veerman 	else
4385ea9e707SThomas Veerman 	    cleanfld(n+1, lastfld);
4395ea9e707SThomas Veerman 
4405ea9e707SThomas Veerman 	lastfld = n;
4415ea9e707SThomas Veerman }
4425ea9e707SThomas Veerman 
fieldadr(int n)4435ea9e707SThomas Veerman Cell *fieldadr(int n)	/* get nth field */
4445ea9e707SThomas Veerman {
4455ea9e707SThomas Veerman 	if (n < 0)
4465ea9e707SThomas Veerman 		FATAL("trying to access out of range field %d", n);
4475ea9e707SThomas Veerman 	if (n > nfields)	/* fields after NF are empty */
4485ea9e707SThomas Veerman 		growfldtab(n);	/* but does not increase NF */
4495ea9e707SThomas Veerman 	return(fldtab[n]);
4505ea9e707SThomas Veerman }
4515ea9e707SThomas Veerman 
growfldtab(int n)4525ea9e707SThomas Veerman void growfldtab(int n)	/* make new fields up to at least $n */
4535ea9e707SThomas Veerman {
4545ea9e707SThomas Veerman 	int nf = 2 * nfields;
4555ea9e707SThomas Veerman 	size_t s;
4565ea9e707SThomas Veerman 
4575ea9e707SThomas Veerman 	if (n > nf)
4585ea9e707SThomas Veerman 		nf = n;
4595ea9e707SThomas Veerman 	s = (nf+1) * (sizeof (struct Cell *));  /* freebsd: how much do we need? */
4605ea9e707SThomas Veerman 	if (s / sizeof(struct Cell *) - 1 == (size_t)nf) /* didn't overflow */
4615ea9e707SThomas Veerman 		fldtab = realloc(fldtab, s);
4625ea9e707SThomas Veerman 	else					/* overflow sizeof int */
4635ea9e707SThomas Veerman 		xfree(fldtab);	/* make it null */
4645ea9e707SThomas Veerman 	if (fldtab == NULL)
4655ea9e707SThomas Veerman 		FATAL("out of space creating %d fields", nf);
4665ea9e707SThomas Veerman 	makefields(nfields+1, nf);
4675ea9e707SThomas Veerman 	nfields = nf;
4685ea9e707SThomas Veerman }
4695ea9e707SThomas Veerman 
refldbld(const char * rec,const char * fs)4705ea9e707SThomas Veerman int refldbld(const char *rec, const char *fs)	/* build fields from reg expr in FS */
4715ea9e707SThomas Veerman {
4725ea9e707SThomas Veerman 	/* this relies on having fields[] the same length as $0 */
4735ea9e707SThomas Veerman 	/* the fields are all stored in this one array with \0's */
4745ea9e707SThomas Veerman 	char *fr;
4755ea9e707SThomas Veerman 	int i, tempstat, n;
4765ea9e707SThomas Veerman 	fa *pfa;
4775ea9e707SThomas Veerman 
4785ea9e707SThomas Veerman 	n = strlen(rec);
4795ea9e707SThomas Veerman 	if (n > fieldssize) {
4805ea9e707SThomas Veerman 		xfree(fields);
4815ea9e707SThomas Veerman 		if ((fields = malloc(n+1)) == NULL)
4825ea9e707SThomas Veerman 			FATAL("out of space for fields in refldbld %d", n);
4835ea9e707SThomas Veerman 		fieldssize = n;
4845ea9e707SThomas Veerman 	}
4855ea9e707SThomas Veerman 	fr = fields;
4865ea9e707SThomas Veerman 	*fr = '\0';
4875ea9e707SThomas Veerman 	if (*rec == '\0')
4885ea9e707SThomas Veerman 		return 0;
4895ea9e707SThomas Veerman 	pfa = makedfa(fs, 1);
4905ea9e707SThomas Veerman 	   dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
4915ea9e707SThomas Veerman 	tempstat = pfa->initstat;
4925ea9e707SThomas Veerman 	for (i = 1; ; i++) {
4935ea9e707SThomas Veerman 		if (i > nfields)
4945ea9e707SThomas Veerman 			growfldtab(i);
4955ea9e707SThomas Veerman 		if (freeable(fldtab[i]))
4965ea9e707SThomas Veerman 			xfree(fldtab[i]->sval);
4975ea9e707SThomas Veerman 		fldtab[i]->tval = FLD | STR | DONTFREE;
4985ea9e707SThomas Veerman 		fldtab[i]->sval = fr;
4995ea9e707SThomas Veerman 		   dprintf( ("refldbld: i=%d\n", i) );
5005ea9e707SThomas Veerman 		if (nematch(pfa, rec)) {
5015ea9e707SThomas Veerman 			pfa->initstat = 2;	/* horrible coupling to b.c */
5025ea9e707SThomas Veerman 			   dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
5035ea9e707SThomas Veerman 			strncpy(fr, rec, ((const char*)patbeg)-rec);
5045ea9e707SThomas Veerman 			fr += ((const char*)patbeg) - rec + 1;
5055ea9e707SThomas Veerman 			*(fr-1) = '\0';
5065ea9e707SThomas Veerman 			rec = patbeg + patlen;
5075ea9e707SThomas Veerman 		} else {
5085ea9e707SThomas Veerman 			   dprintf( ("no match %s\n", rec) );
5095ea9e707SThomas Veerman 			strcpy(fr, rec);
5105ea9e707SThomas Veerman 			pfa->initstat = tempstat;
5115ea9e707SThomas Veerman 			break;
5125ea9e707SThomas Veerman 		}
5135ea9e707SThomas Veerman 	}
5145ea9e707SThomas Veerman 	return i;
5155ea9e707SThomas Veerman }
5165ea9e707SThomas Veerman 
recbld(void)5175ea9e707SThomas Veerman void recbld(void)	/* create $0 from $1..$NF if necessary */
5185ea9e707SThomas Veerman {
5195ea9e707SThomas Veerman 	int i;
5205ea9e707SThomas Veerman 	uschar *r;
5215ea9e707SThomas Veerman 	char *p;
5225ea9e707SThomas Veerman 
5235ea9e707SThomas Veerman 	if (donerec == 1)
5245ea9e707SThomas Veerman 		return;
5255ea9e707SThomas Veerman 	r = record;
5265ea9e707SThomas Veerman 	for (i = 1; i <= *NF; i++) {
5275ea9e707SThomas Veerman 		p = getsval(fldtab[i]);
5285ea9e707SThomas Veerman 		if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1"))
5295ea9e707SThomas Veerman 			FATAL("created $0 `%.30s...' too long", record);
5305ea9e707SThomas Veerman 		while ((*r = *p++) != 0)
5315ea9e707SThomas Veerman 			r++;
5325ea9e707SThomas Veerman 		if (i < *NF) {
5335ea9e707SThomas Veerman 			if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
5345ea9e707SThomas Veerman 				FATAL("created $0 `%.30s...' too long", record);
5355ea9e707SThomas Veerman 			for (p = *OFS; (*r = *p++) != 0; )
5365ea9e707SThomas Veerman 				r++;
5375ea9e707SThomas Veerman 		}
5385ea9e707SThomas Veerman 	}
5395ea9e707SThomas Veerman 	if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
5405ea9e707SThomas Veerman 		FATAL("built giant record `%.30s...'", record);
5415ea9e707SThomas Veerman 	*r = '\0';
5425ea9e707SThomas Veerman 	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
5435ea9e707SThomas Veerman 
5445ea9e707SThomas Veerman 	if (freeable(fldtab[0]))
5455ea9e707SThomas Veerman 		xfree(fldtab[0]->sval);
5465ea9e707SThomas Veerman 	fldtab[0]->tval = REC | STR | DONTFREE;
5475ea9e707SThomas Veerman 	fldtab[0]->sval = record;
5485ea9e707SThomas Veerman 
5495ea9e707SThomas Veerman 	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
5505ea9e707SThomas Veerman 	   dprintf( ("recbld = |%s|\n", record) );
5515ea9e707SThomas Veerman 	donerec = 1;
5525ea9e707SThomas Veerman }
5535ea9e707SThomas Veerman 
5545ea9e707SThomas Veerman int	errorflag	= 0;
5555ea9e707SThomas Veerman 
yyerror(const char * s)5565ea9e707SThomas Veerman void yyerror(const char *s)
5575ea9e707SThomas Veerman {
5585ea9e707SThomas Veerman 	SYNTAX("%s", s);
5595ea9e707SThomas Veerman }
5605ea9e707SThomas Veerman 
SYNTAX(const char * fmt,...)5615ea9e707SThomas Veerman void SYNTAX(const char *fmt, ...)
5625ea9e707SThomas Veerman {
5635ea9e707SThomas Veerman 	extern char *cmdname, *curfname;
5645ea9e707SThomas Veerman 	static int been_here = 0;
5655ea9e707SThomas Veerman 	va_list varg;
5665ea9e707SThomas Veerman 
5675ea9e707SThomas Veerman 	if (been_here++ > 2)
5685ea9e707SThomas Veerman 		return;
5695ea9e707SThomas Veerman 	fprintf(stderr, "%s: ", cmdname);
5705ea9e707SThomas Veerman 	va_start(varg, fmt);
5715ea9e707SThomas Veerman 	vfprintf(stderr, fmt, varg);
5725ea9e707SThomas Veerman 	va_end(varg);
5735ea9e707SThomas Veerman 	fprintf(stderr, " at source line %d", lineno);
5745ea9e707SThomas Veerman 	if (curfname != NULL)
5755ea9e707SThomas Veerman 		fprintf(stderr, " in function %s", curfname);
5765ea9e707SThomas Veerman 	if (compile_time == 1 && cursource() != NULL)
5775ea9e707SThomas Veerman 		fprintf(stderr, " source file %s", cursource());
5785ea9e707SThomas Veerman 	fprintf(stderr, "\n");
5795ea9e707SThomas Veerman 	errorflag = 2;
5805ea9e707SThomas Veerman 	eprint();
5815ea9e707SThomas Veerman }
5825ea9e707SThomas Veerman 
5835ea9e707SThomas Veerman extern int bracecnt, brackcnt, parencnt;
5845ea9e707SThomas Veerman 
bracecheck(void)5855ea9e707SThomas Veerman void bracecheck(void)
5865ea9e707SThomas Veerman {
5875ea9e707SThomas Veerman 	int c;
5885ea9e707SThomas Veerman 	static int beenhere = 0;
5895ea9e707SThomas Veerman 
5905ea9e707SThomas Veerman 	if (beenhere++)
5915ea9e707SThomas Veerman 		return;
5925ea9e707SThomas Veerman 	while ((c = input()) != EOF && c != '\0')
5935ea9e707SThomas Veerman 		bclass(c);
5945ea9e707SThomas Veerman 	bcheck2(bracecnt, '{', '}');
5955ea9e707SThomas Veerman 	bcheck2(brackcnt, '[', ']');
5965ea9e707SThomas Veerman 	bcheck2(parencnt, '(', ')');
5975ea9e707SThomas Veerman }
5985ea9e707SThomas Veerman 
bcheck2(int n,int c1,int c2)5995ea9e707SThomas Veerman void bcheck2(int n, int c1, int c2)
6005ea9e707SThomas Veerman {
6015ea9e707SThomas Veerman 	if (n == 1)
6025ea9e707SThomas Veerman 		fprintf(stderr, "\tmissing %c\n", c2);
6035ea9e707SThomas Veerman 	else if (n > 1)
6045ea9e707SThomas Veerman 		fprintf(stderr, "\t%d missing %c's\n", n, c2);
6055ea9e707SThomas Veerman 	else if (n == -1)
6065ea9e707SThomas Veerman 		fprintf(stderr, "\textra %c\n", c2);
6075ea9e707SThomas Veerman 	else if (n < -1)
6085ea9e707SThomas Veerman 		fprintf(stderr, "\t%d extra %c's\n", -n, c2);
6095ea9e707SThomas Veerman }
6105ea9e707SThomas Veerman 
FATAL(const char * fmt,...)6115ea9e707SThomas Veerman void FATAL(const char *fmt, ...)
6125ea9e707SThomas Veerman {
6135ea9e707SThomas Veerman 	extern char *cmdname;
6145ea9e707SThomas Veerman 	va_list varg;
6155ea9e707SThomas Veerman 
6165ea9e707SThomas Veerman 	fflush(stdout);
6175ea9e707SThomas Veerman 	fprintf(stderr, "%s: ", cmdname);
6185ea9e707SThomas Veerman 	va_start(varg, fmt);
6195ea9e707SThomas Veerman 	vfprintf(stderr, fmt, varg);
6205ea9e707SThomas Veerman 	va_end(varg);
6215ea9e707SThomas Veerman 	error();
6225ea9e707SThomas Veerman 	if (dbg > 1)		/* core dump if serious debugging on */
6235ea9e707SThomas Veerman 		abort();
6245ea9e707SThomas Veerman 	exit(2);
6255ea9e707SThomas Veerman }
6265ea9e707SThomas Veerman 
WARNING(const char * fmt,...)6275ea9e707SThomas Veerman void WARNING(const char *fmt, ...)
6285ea9e707SThomas Veerman {
6295ea9e707SThomas Veerman 	extern char *cmdname;
6305ea9e707SThomas Veerman 	va_list varg;
6315ea9e707SThomas Veerman 
6325ea9e707SThomas Veerman 	fflush(stdout);
6335ea9e707SThomas Veerman 	fprintf(stderr, "%s: ", cmdname);
6345ea9e707SThomas Veerman 	va_start(varg, fmt);
6355ea9e707SThomas Veerman 	vfprintf(stderr, fmt, varg);
6365ea9e707SThomas Veerman 	va_end(varg);
6375ea9e707SThomas Veerman 	error();
6385ea9e707SThomas Veerman }
6395ea9e707SThomas Veerman 
error()6405ea9e707SThomas Veerman void error()
6415ea9e707SThomas Veerman {
6425ea9e707SThomas Veerman 	extern Node *curnode;
6435ea9e707SThomas Veerman 
6445ea9e707SThomas Veerman 	fprintf(stderr, "\n");
6455ea9e707SThomas Veerman 	if (compile_time != 2 && NR && *NR > 0) {
6465ea9e707SThomas Veerman 		fprintf(stderr, " input record number %d", (int) (*FNR));
6475ea9e707SThomas Veerman 		if (strcmp(*FILENAME, "-") != 0)
6485ea9e707SThomas Veerman 			fprintf(stderr, ", file %s", *FILENAME);
6495ea9e707SThomas Veerman 		fprintf(stderr, "\n");
6505ea9e707SThomas Veerman 	}
6515ea9e707SThomas Veerman 	if (compile_time != 2 && curnode)
6525ea9e707SThomas Veerman 		fprintf(stderr, " source line number %d", curnode->lineno);
6535ea9e707SThomas Veerman 	else if (compile_time != 2 && lineno)
6545ea9e707SThomas Veerman 		fprintf(stderr, " source line number %d", lineno);
6555ea9e707SThomas Veerman 	if (compile_time == 1 && cursource() != NULL)
6565ea9e707SThomas Veerman 		fprintf(stderr, " source file %s", cursource());
6575ea9e707SThomas Veerman 	fprintf(stderr, "\n");
6585ea9e707SThomas Veerman 	eprint();
6595ea9e707SThomas Veerman }
6605ea9e707SThomas Veerman 
eprint(void)6615ea9e707SThomas Veerman void eprint(void)	/* try to print context around error */
6625ea9e707SThomas Veerman {
6635ea9e707SThomas Veerman 	char *p, *q;
6645ea9e707SThomas Veerman 	static int been_here = 0;
6655ea9e707SThomas Veerman 	extern char ebuf[], *ep;
6665ea9e707SThomas Veerman 
6675ea9e707SThomas Veerman 	if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
6685ea9e707SThomas Veerman 		return;
6695ea9e707SThomas Veerman 	p = ep - 1;
6705ea9e707SThomas Veerman 	if (p > ebuf && *p == '\n')
6715ea9e707SThomas Veerman 		p--;
6725ea9e707SThomas Veerman 	for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
6735ea9e707SThomas Veerman 		;
6745ea9e707SThomas Veerman 	while (*p == '\n')
6755ea9e707SThomas Veerman 		p++;
6765ea9e707SThomas Veerman 	fprintf(stderr, " context is\n\t");
6775ea9e707SThomas Veerman 	for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
6785ea9e707SThomas Veerman 		;
6795ea9e707SThomas Veerman 	for ( ; p < q; p++)
6805ea9e707SThomas Veerman 		if (*p)
6815ea9e707SThomas Veerman 			putc(*p, stderr);
6825ea9e707SThomas Veerman 	fprintf(stderr, " >>> ");
6835ea9e707SThomas Veerman 	for ( ; p < ep; p++)
6845ea9e707SThomas Veerman 		if (*p)
6855ea9e707SThomas Veerman 			putc(*p, stderr);
6865ea9e707SThomas Veerman 	fprintf(stderr, " <<< ");
6875ea9e707SThomas Veerman #if 0
6885ea9e707SThomas Veerman 	/*
6895ea9e707SThomas Veerman 	 * The following code was used to print the rest of the line of
6905ea9e707SThomas Veerman 	 * error context. It naively counts brackets, parens and braces in
6915ea9e707SThomas Veerman 	 * order to minimize the parsing effect of dropping the rest of the
6925ea9e707SThomas Veerman 	 * line but it does not work in all the cases. It is too much work
6935ea9e707SThomas Veerman 	 * to save the current program input point and restore it in all the
6945ea9e707SThomas Veerman 	 * cases just for the benefit of error printing so for now this
6955ea9e707SThomas Veerman 	 * code is disabled. In particular this code is confused if the
6965ea9e707SThomas Veerman 	 * [ { ( ) } ] is inside a quoted string or a pattern.
6975ea9e707SThomas Veerman 	 */
6985ea9e707SThomas Veerman 	if (*ep) {
6995ea9e707SThomas Veerman 		int c;
7005ea9e707SThomas Veerman 		while ((c = input()) != '\n' && c != '\0' && c != EOF) {
7015ea9e707SThomas Veerman 			putc(c, stderr);
7025ea9e707SThomas Veerman 			bclass(c);
7035ea9e707SThomas Veerman 		}
7045ea9e707SThomas Veerman 	}
7055ea9e707SThomas Veerman #endif
7065ea9e707SThomas Veerman 	putc('\n', stderr);
7075ea9e707SThomas Veerman 	ep = ebuf;
7085ea9e707SThomas Veerman }
7095ea9e707SThomas Veerman 
bclass(int c)7105ea9e707SThomas Veerman void bclass(int c)
7115ea9e707SThomas Veerman {
7125ea9e707SThomas Veerman 	switch (c) {
7135ea9e707SThomas Veerman 	case '{': bracecnt++; break;
7145ea9e707SThomas Veerman 	case '}': bracecnt--; break;
7155ea9e707SThomas Veerman 	case '[': brackcnt++; break;
7165ea9e707SThomas Veerman 	case ']': brackcnt--; break;
7175ea9e707SThomas Veerman 	case '(': parencnt++; break;
7185ea9e707SThomas Veerman 	case ')': parencnt--; break;
7195ea9e707SThomas Veerman 	}
7205ea9e707SThomas Veerman }
7215ea9e707SThomas Veerman 
errcheck(double x,const char * s)7225ea9e707SThomas Veerman double errcheck(double x, const char *s)
7235ea9e707SThomas Veerman {
7245ea9e707SThomas Veerman 
7255ea9e707SThomas Veerman 	if (errno == EDOM) {
7265ea9e707SThomas Veerman 		errno = 0;
7275ea9e707SThomas Veerman 		WARNING("%s argument out of domain", s);
7285ea9e707SThomas Veerman 		x = 1;
7295ea9e707SThomas Veerman 	} else if (errno == ERANGE) {
7305ea9e707SThomas Veerman 		errno = 0;
7315ea9e707SThomas Veerman 		WARNING("%s result out of range", s);
7325ea9e707SThomas Veerman 		x = 1;
7335ea9e707SThomas Veerman 	}
7345ea9e707SThomas Veerman 	return x;
7355ea9e707SThomas Veerman }
7365ea9e707SThomas Veerman 
isclvar(const char * s)7375ea9e707SThomas Veerman int isclvar(const char *s)	/* is s of form var=something ? */
7385ea9e707SThomas Veerman {
7395ea9e707SThomas Veerman 	const char *os = s;
7405ea9e707SThomas Veerman 
7415ea9e707SThomas Veerman 	if (!isalpha((uschar) *s) && *s != '_')
7425ea9e707SThomas Veerman 		return 0;
7435ea9e707SThomas Veerman 	for ( ; *s; s++)
7445ea9e707SThomas Veerman 		if (!(isalnum((uschar) *s) || *s == '_'))
7455ea9e707SThomas Veerman 			break;
7465ea9e707SThomas Veerman 	return *s == '=' && s > os && *(s+1) != '=';
7475ea9e707SThomas Veerman }
7485ea9e707SThomas Veerman 
7495ea9e707SThomas Veerman /* strtod is supposed to be a proper test of what's a valid number */
7505ea9e707SThomas Veerman /* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
7515ea9e707SThomas Veerman /* wrong: violates 4.10.1.4 of ansi C standard */
7525ea9e707SThomas Veerman 
7535ea9e707SThomas Veerman #include <math.h>
is_number(const char * s)7545ea9e707SThomas Veerman int is_number(const char *s)
7555ea9e707SThomas Veerman {
7565ea9e707SThomas Veerman 	char *ep;
7575ea9e707SThomas Veerman 	errno = 0;
758*84d9c625SLionel Sambuc 	(void)strtod(s, &ep);
7595ea9e707SThomas Veerman 	if (ep == s || errno == ERANGE)
7605ea9e707SThomas Veerman 		return 0;
7615ea9e707SThomas Veerman 	if (ep - s >= 3 && strncasecmp(ep - 3, "nan", 3) == 0)
7625ea9e707SThomas Veerman 		return 0;
7635ea9e707SThomas Veerman 	while (*ep == ' ' || *ep == '\t' || *ep == '\n')
7645ea9e707SThomas Veerman 		ep++;
7655ea9e707SThomas Veerman 	if (*ep == '\0')
7665ea9e707SThomas Veerman 		return 1;
7675ea9e707SThomas Veerman 	else
7685ea9e707SThomas Veerman 		return 0;
7695ea9e707SThomas Veerman }
770