xref: /titanic_44/usr/src/cmd/awk/lib.c (revision 8ef4c21a581c38a44ac18b7363c4928cb3222303)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*8ef4c21aSnakanon  * Common Development and Distribution License (the "License").
6*8ef4c21aSnakanon  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
211ee2e5faSnakanon 
221ee2e5faSnakanon /*
23*8ef4c21aSnakanon  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
241ee2e5faSnakanon  * Use is subject to license terms.
251ee2e5faSnakanon  */
261ee2e5faSnakanon 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
301ee2e5faSnakanon #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <errno.h>
337c478bd9Sstevel@tonic-gate #include "awk.h"
347c478bd9Sstevel@tonic-gate #include "y.tab.h"
357c478bd9Sstevel@tonic-gate 
361ee2e5faSnakanon uchar	*record;
371ee2e5faSnakanon size_t	record_size;
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate int	donefld;	/* 1 = implies rec broken into fields */
407c478bd9Sstevel@tonic-gate int	donerec;	/* 1 = record is valid (no flds have changed) */
417c478bd9Sstevel@tonic-gate 
421ee2e5faSnakanon static struct fldtab_chunk {
431ee2e5faSnakanon 	struct fldtab_chunk	*next;
441ee2e5faSnakanon 	Cell			fields[FLD_INCR];
451ee2e5faSnakanon } *fldtab_head, *fldtab_tail;
467c478bd9Sstevel@tonic-gate 
471ee2e5faSnakanon static	size_t	fldtab_maxidx;
487c478bd9Sstevel@tonic-gate 
491ee2e5faSnakanon static FILE	*infile	= NULL;
501ee2e5faSnakanon static uchar	*file	= (uchar*) "";
511ee2e5faSnakanon static uchar	*fields;
521ee2e5faSnakanon static size_t	fields_size = LINE_INCR;
531ee2e5faSnakanon 
541ee2e5faSnakanon static int	maxfld	= 0;	/* last used field */
551ee2e5faSnakanon static int	argno	= 1;	/* current input argument number */
561ee2e5faSnakanon 
571ee2e5faSnakanon static	uchar	*getargv(int);
581ee2e5faSnakanon static	void	cleanfld(int, int);
591ee2e5faSnakanon static	int	refldbld(uchar *, uchar *);
601ee2e5faSnakanon static	void	bcheck2(int, int, int);
611ee2e5faSnakanon static	void	eprint(void);
621ee2e5faSnakanon static	void	bclass(int);
631ee2e5faSnakanon 
641ee2e5faSnakanon static void
initgetrec(void)651ee2e5faSnakanon initgetrec(void)
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate 	int i;
687c478bd9Sstevel@tonic-gate 	uchar *p;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	for (i = 1; i < *ARGC; i++) {
717c478bd9Sstevel@tonic-gate 		if (!isclvar(p = getargv(i)))	/* find 1st real filename */
727c478bd9Sstevel@tonic-gate 			return;
737c478bd9Sstevel@tonic-gate 		setclvar(p);	/* a commandline assignment before filename */
747c478bd9Sstevel@tonic-gate 		argno++;
757c478bd9Sstevel@tonic-gate 	}
767c478bd9Sstevel@tonic-gate 	infile = stdin;		/* no filenames, so use stdin */
777c478bd9Sstevel@tonic-gate 	/* *FILENAME = file = (uchar*) "-"; */
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
801ee2e5faSnakanon int
getrec(uchar ** bufp,size_t * bufsizep)811ee2e5faSnakanon getrec(uchar **bufp, size_t *bufsizep)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	int c;
847c478bd9Sstevel@tonic-gate 	static int firsttime = 1;
851ee2e5faSnakanon 	uchar_t	*buf, *nbuf;
861ee2e5faSnakanon 	size_t	len;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	if (firsttime) {
897c478bd9Sstevel@tonic-gate 		firsttime = 0;
907c478bd9Sstevel@tonic-gate 		initgetrec();
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 	dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
937c478bd9Sstevel@tonic-gate 	    *RS, *FS, *ARGC, *FILENAME));
947c478bd9Sstevel@tonic-gate 	donefld = 0;
957c478bd9Sstevel@tonic-gate 	donerec = 1;
967c478bd9Sstevel@tonic-gate 	while (argno < *ARGC || infile == stdin) {
977c478bd9Sstevel@tonic-gate 		dprintf(("argno=%d, file=|%s|\n", argno, file));
987c478bd9Sstevel@tonic-gate 		if (infile == NULL) {	/* have to open a new file */
997c478bd9Sstevel@tonic-gate 			file = getargv(argno);
1007c478bd9Sstevel@tonic-gate 			if (*file == '\0') {	/* it's been zapped */
1017c478bd9Sstevel@tonic-gate 				argno++;
1027c478bd9Sstevel@tonic-gate 				continue;
1037c478bd9Sstevel@tonic-gate 			}
1047c478bd9Sstevel@tonic-gate 			if (isclvar(file)) {	/* a var=value arg */
1057c478bd9Sstevel@tonic-gate 				setclvar(file);
1067c478bd9Sstevel@tonic-gate 				argno++;
1077c478bd9Sstevel@tonic-gate 				continue;
1087c478bd9Sstevel@tonic-gate 			}
1097c478bd9Sstevel@tonic-gate 			*FILENAME = file;
1107c478bd9Sstevel@tonic-gate 			dprintf(("opening file %s\n", file));
1117c478bd9Sstevel@tonic-gate 			if (*file == '-' && *(file+1) == '\0')
1127c478bd9Sstevel@tonic-gate 				infile = stdin;
1137c478bd9Sstevel@tonic-gate 			else if ((infile = fopen((char *)file, "r")) == NULL)
1147c478bd9Sstevel@tonic-gate 				ERROR "can't open file %s", file FATAL;
1151ee2e5faSnakanon 			(void) setfval(fnrloc, 0.0);
1167c478bd9Sstevel@tonic-gate 		}
1171ee2e5faSnakanon 		c = readrec(&nbuf, &len, infile);
1181ee2e5faSnakanon 		expand_buf(bufp, bufsizep, len);
1191ee2e5faSnakanon 		buf = *bufp;
1201ee2e5faSnakanon 		(void) memcpy(buf, nbuf, len);
1211ee2e5faSnakanon 		buf[len] = '\0';
1221ee2e5faSnakanon 		free(nbuf);
1231ee2e5faSnakanon 
1247c478bd9Sstevel@tonic-gate 		if (c != 0 || buf[0] != '\0') {	/* normal record */
125*8ef4c21aSnakanon 			if (bufp == &record) {
1267c478bd9Sstevel@tonic-gate 				if (!(recloc->tval & DONTFREE))
1277c478bd9Sstevel@tonic-gate 					xfree(recloc->sval);
1287c478bd9Sstevel@tonic-gate 				recloc->sval = record;
1297c478bd9Sstevel@tonic-gate 				recloc->tval = REC | STR | DONTFREE;
1301ee2e5faSnakanon 				if (is_number(recloc->sval)) {
1311ee2e5faSnakanon 					recloc->fval =
1321ee2e5faSnakanon 					    atof((const char *)recloc->sval);
1337c478bd9Sstevel@tonic-gate 					recloc->tval |= NUM;
1347c478bd9Sstevel@tonic-gate 				}
1357c478bd9Sstevel@tonic-gate 			}
1361ee2e5faSnakanon 			(void) setfval(nrloc, nrloc->fval+1);
1371ee2e5faSnakanon 			(void) setfval(fnrloc, fnrloc->fval+1);
1387c478bd9Sstevel@tonic-gate 			return (1);
1397c478bd9Sstevel@tonic-gate 		}
1407c478bd9Sstevel@tonic-gate 		/* EOF arrived on this file; set up next */
1417c478bd9Sstevel@tonic-gate 		if (infile != stdin)
1421ee2e5faSnakanon 			(void) fclose(infile);
1437c478bd9Sstevel@tonic-gate 		infile = NULL;
1447c478bd9Sstevel@tonic-gate 		argno++;
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	return (0);	/* true end of file */
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1491ee2e5faSnakanon int
readrec(uchar ** bufp,size_t * sizep,FILE * inf)1501ee2e5faSnakanon readrec(uchar **bufp, size_t *sizep, FILE *inf)	/* read one record into buf */
1517c478bd9Sstevel@tonic-gate {
152cb4658fbSceastha 	int sep, c;
1531ee2e5faSnakanon 	uchar	*buf;
1547c478bd9Sstevel@tonic-gate 	int	count;
1551ee2e5faSnakanon 	size_t	bufsize;
1567c478bd9Sstevel@tonic-gate 
1571ee2e5faSnakanon 	init_buf(&buf, &bufsize, LINE_INCR);
1587c478bd9Sstevel@tonic-gate 	if ((sep = **RS) == 0) {
1597c478bd9Sstevel@tonic-gate 		sep = '\n';
1607c478bd9Sstevel@tonic-gate 		/* skip leading \n's */
1617c478bd9Sstevel@tonic-gate 		while ((c = getc(inf)) == '\n' && c != EOF)
1627c478bd9Sstevel@tonic-gate 			;
1637c478bd9Sstevel@tonic-gate 		if (c != EOF)
1641ee2e5faSnakanon 			(void) ungetc(c, inf);
1657c478bd9Sstevel@tonic-gate 	}
1661ee2e5faSnakanon 	count = 0;
1671ee2e5faSnakanon 	for (;;) {
1687c478bd9Sstevel@tonic-gate 		while ((c = getc(inf)) != sep && c != EOF) {
1691ee2e5faSnakanon 			expand_buf(&buf, &bufsize, count);
1701ee2e5faSnakanon 			buf[count++] = c;
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 		if (**RS == sep || c == EOF)
1737c478bd9Sstevel@tonic-gate 			break;
1747c478bd9Sstevel@tonic-gate 		if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
1757c478bd9Sstevel@tonic-gate 			break;
1761ee2e5faSnakanon 		expand_buf(&buf, &bufsize, count + 1);
1771ee2e5faSnakanon 		buf[count++] = '\n';
1781ee2e5faSnakanon 		buf[count++] = c;
1797c478bd9Sstevel@tonic-gate 	}
1801ee2e5faSnakanon 	buf[count] = '\0';
1817c478bd9Sstevel@tonic-gate 	dprintf(("readrec saw <%s>, returns %d\n",
1821ee2e5faSnakanon 	    buf, c == EOF && count == 0 ? 0 : 1));
1831ee2e5faSnakanon 	*bufp = buf;
1841ee2e5faSnakanon 	*sizep = count;
1851ee2e5faSnakanon 	return (c == EOF && count == 0 ? 0 : 1);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate /* get ARGV[n] */
1891ee2e5faSnakanon static uchar *
getargv(int n)1901ee2e5faSnakanon getargv(int n)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	Cell *x;
1931ee2e5faSnakanon 	uchar *s, temp[11];
1947c478bd9Sstevel@tonic-gate 	extern Array *ARGVtab;
1957c478bd9Sstevel@tonic-gate 
1961ee2e5faSnakanon 	(void) sprintf((char *)temp, "%d", n);
1971ee2e5faSnakanon 	x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab);
1987c478bd9Sstevel@tonic-gate 	s = getsval(x);
1997c478bd9Sstevel@tonic-gate 	dprintf(("getargv(%d) returns |%s|\n", n, s));
2007c478bd9Sstevel@tonic-gate 	return (s);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2031ee2e5faSnakanon void
setclvar(uchar * s)2041ee2e5faSnakanon setclvar(uchar *s)	/* set var=value from s */
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	uchar *p;
2077c478bd9Sstevel@tonic-gate 	Cell *q;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	for (p = s; *p != '='; p++)
2107c478bd9Sstevel@tonic-gate 		;
2117c478bd9Sstevel@tonic-gate 	*p++ = 0;
2127c478bd9Sstevel@tonic-gate 	p = qstring(p, '\0');
2137c478bd9Sstevel@tonic-gate 	q = setsymtab(s, p, 0.0, STR, symtab);
2141ee2e5faSnakanon 	(void) setsval(q, p);
2151ee2e5faSnakanon 	if (is_number(q->sval)) {
2161ee2e5faSnakanon 		q->fval = atof((const char *)q->sval);
2177c478bd9Sstevel@tonic-gate 		q->tval |= NUM;
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 	dprintf(("command line set %s to |%s|\n", s, p));
2201ee2e5faSnakanon 	free(p);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2231ee2e5faSnakanon void
fldbld(void)2241ee2e5faSnakanon fldbld(void)
2257c478bd9Sstevel@tonic-gate {
226cb4658fbSceastha 	uchar *r, *fr, sep;
2277c478bd9Sstevel@tonic-gate 	Cell *p;
2287c478bd9Sstevel@tonic-gate 	int i;
2291ee2e5faSnakanon 	size_t	len;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (donefld)
2327c478bd9Sstevel@tonic-gate 		return;
2337c478bd9Sstevel@tonic-gate 	if (!(recloc->tval & STR))
2341ee2e5faSnakanon 		(void) getsval(recloc);
2357c478bd9Sstevel@tonic-gate 	r = recloc->sval;	/* was record! */
2361ee2e5faSnakanon 
2371ee2e5faSnakanon 	/* make sure fields is always allocated */
2381ee2e5faSnakanon 	adjust_buf(&fields, fields_size);
2391ee2e5faSnakanon 
2401ee2e5faSnakanon 	/*
2411ee2e5faSnakanon 	 * make sure fields has enough size. We don't expand the buffer
2421ee2e5faSnakanon 	 * in the middle of the loop, since p->sval has already pointed
2431ee2e5faSnakanon 	 * the address in the fields.
2441ee2e5faSnakanon 	 */
2451ee2e5faSnakanon 	len = strlen((char *)r) + 1;
2461ee2e5faSnakanon 	expand_buf(&fields, &fields_size, len);
2477c478bd9Sstevel@tonic-gate 	fr = fields;
2481ee2e5faSnakanon 
2497c478bd9Sstevel@tonic-gate 	i = 0;	/* number of fields accumulated here */
2501ee2e5faSnakanon 	if (strlen((char *)*FS) > 1) {	/* it's a regular expression */
2517c478bd9Sstevel@tonic-gate 		i = refldbld(r, *FS);
2527c478bd9Sstevel@tonic-gate 	} else if ((sep = **FS) == ' ') {
2537c478bd9Sstevel@tonic-gate 		for (i = 0; ; ) {
2547c478bd9Sstevel@tonic-gate 			while (*r == ' ' || *r == '\t' || *r == '\n')
2557c478bd9Sstevel@tonic-gate 				r++;
2567c478bd9Sstevel@tonic-gate 			if (*r == 0)
2577c478bd9Sstevel@tonic-gate 				break;
2587c478bd9Sstevel@tonic-gate 			i++;
2591ee2e5faSnakanon 			p = getfld(i);
2601ee2e5faSnakanon 			if (!(p->tval & DONTFREE))
2611ee2e5faSnakanon 				xfree(p->sval);
2621ee2e5faSnakanon 			p->sval = fr;
2631ee2e5faSnakanon 			p->tval = FLD | STR | DONTFREE;
2647c478bd9Sstevel@tonic-gate 			do
2657c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
2667c478bd9Sstevel@tonic-gate 			while (*r != ' ' && *r != '\t' && *r != '\n' &&
2671ee2e5faSnakanon 			    *r != '\0')
2681ee2e5faSnakanon 				;
2697c478bd9Sstevel@tonic-gate 			*fr++ = 0;
2707c478bd9Sstevel@tonic-gate 		}
2717c478bd9Sstevel@tonic-gate 		*fr = 0;
2727c478bd9Sstevel@tonic-gate 	} else if (*r != 0) {	/* if 0, it's a null field */
2737c478bd9Sstevel@tonic-gate 		for (;;) {
2747c478bd9Sstevel@tonic-gate 			i++;
2751ee2e5faSnakanon 			p = getfld(i);
2761ee2e5faSnakanon 			if (!(p->tval & DONTFREE))
2771ee2e5faSnakanon 				xfree(p->sval);
2781ee2e5faSnakanon 			p->sval = fr;
2791ee2e5faSnakanon 			p->tval = FLD | STR | DONTFREE;
2807c478bd9Sstevel@tonic-gate 			/* \n always a separator */
2817c478bd9Sstevel@tonic-gate 			while (*r != sep && *r != '\n' && *r != '\0')
2827c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
2837c478bd9Sstevel@tonic-gate 			*fr++ = 0;
2847c478bd9Sstevel@tonic-gate 			if (*r++ == 0)
2857c478bd9Sstevel@tonic-gate 				break;
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		*fr = 0;
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	/* clean out junk from previous record */
2907c478bd9Sstevel@tonic-gate 	cleanfld(i, maxfld);
2917c478bd9Sstevel@tonic-gate 	maxfld = i;
2927c478bd9Sstevel@tonic-gate 	donefld = 1;
2931ee2e5faSnakanon 	for (i = 1; i <= maxfld; i++) {
2941ee2e5faSnakanon 		p = getfld(i);
2951ee2e5faSnakanon 		if (is_number(p->sval)) {
2961ee2e5faSnakanon 			p->fval = atof((const char *)p->sval);
2977c478bd9Sstevel@tonic-gate 			p->tval |= NUM;
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 	}
3001ee2e5faSnakanon 
3011ee2e5faSnakanon 	(void) setfval(nfloc, (Awkfloat) maxfld);
3021ee2e5faSnakanon 	if (dbg) {
3031ee2e5faSnakanon 		for (i = 0; i <= maxfld; i++) {
3041ee2e5faSnakanon 			p = getfld(i);
3051ee2e5faSnakanon 			(void) printf("field %d: |%s|\n", i, p->sval);
3061ee2e5faSnakanon 		}
3071ee2e5faSnakanon 	}
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate 
3101ee2e5faSnakanon static void
cleanfld(int n1,int n2)3111ee2e5faSnakanon cleanfld(int n1, int n2)	/* clean out fields n1..n2 inclusive */
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	static uchar *nullstat = (uchar *) "";
314cb4658fbSceastha 	Cell *p;
3151ee2e5faSnakanon 	int	i;
3167c478bd9Sstevel@tonic-gate 
3171ee2e5faSnakanon 	for (i = n2; i > n1; i--) {
3181ee2e5faSnakanon 		p = getfld(i);
3197c478bd9Sstevel@tonic-gate 		if (!(p->tval & DONTFREE))
3207c478bd9Sstevel@tonic-gate 			xfree(p->sval);
3217c478bd9Sstevel@tonic-gate 		p->tval = FLD | STR | DONTFREE;
3227c478bd9Sstevel@tonic-gate 		p->sval = nullstat;
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3261ee2e5faSnakanon void
newfld(int n)3271ee2e5faSnakanon newfld(int n)	/* add field n (after end) */
3287c478bd9Sstevel@tonic-gate {
3291ee2e5faSnakanon 	if (n < 0)
3301ee2e5faSnakanon 		ERROR "accessing invalid field", record FATAL;
3311ee2e5faSnakanon 	(void) getfld(n);
3327c478bd9Sstevel@tonic-gate 	cleanfld(maxfld, n);
3337c478bd9Sstevel@tonic-gate 	maxfld = n;
3341ee2e5faSnakanon 	(void) setfval(nfloc, (Awkfloat) n);
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3371ee2e5faSnakanon /*
3381ee2e5faSnakanon  * allocate field table. We don't reallocate the table since there
3391ee2e5faSnakanon  * might be somewhere recording the address of the table.
3401ee2e5faSnakanon  */
3411ee2e5faSnakanon static void
morefld(void)3421ee2e5faSnakanon morefld(void)
3437c478bd9Sstevel@tonic-gate {
3441ee2e5faSnakanon 	int	i;
3451ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
3461ee2e5faSnakanon 	Cell	*newfld;
3471ee2e5faSnakanon 
3481ee2e5faSnakanon 	if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL)
3491ee2e5faSnakanon 		ERROR "out of space in morefld" FATAL;
3501ee2e5faSnakanon 
3511ee2e5faSnakanon 	newfld = &fldcp->fields[0];
3521ee2e5faSnakanon 	for (i = 0; i < FLD_INCR; i++) {
3531ee2e5faSnakanon 		newfld[i].ctype = OCELL;
3541ee2e5faSnakanon 		newfld[i].csub = CFLD;
3551ee2e5faSnakanon 		newfld[i].nval = NULL;
3561ee2e5faSnakanon 		newfld[i].sval = (uchar *)"";
3571ee2e5faSnakanon 		newfld[i].fval = 0.0;
3581ee2e5faSnakanon 		newfld[i].tval = FLD|STR|DONTFREE;
3591ee2e5faSnakanon 		newfld[i].cnext = NULL;
3601ee2e5faSnakanon 	}
3611ee2e5faSnakanon 	/*
3621ee2e5faSnakanon 	 * link this field chunk
3631ee2e5faSnakanon 	 */
3641ee2e5faSnakanon 	if (fldtab_head == NULL)
3651ee2e5faSnakanon 		fldtab_head = fldcp;
3661ee2e5faSnakanon 	else
3671ee2e5faSnakanon 		fldtab_tail->next = fldcp;
3681ee2e5faSnakanon 	fldtab_tail = fldcp;
3691ee2e5faSnakanon 	fldcp->next = NULL;
3701ee2e5faSnakanon 
3711ee2e5faSnakanon 	fldtab_maxidx += FLD_INCR;
3721ee2e5faSnakanon }
3731ee2e5faSnakanon 
3741ee2e5faSnakanon Cell *
getfld(int idx)3751ee2e5faSnakanon getfld(int idx)
3761ee2e5faSnakanon {
3771ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
3781ee2e5faSnakanon 	int	cbase;
3791ee2e5faSnakanon 
3801ee2e5faSnakanon 	if (idx < 0)
3811ee2e5faSnakanon 		ERROR "trying to access field %d", idx FATAL;
3821ee2e5faSnakanon 	while (idx >= fldtab_maxidx)
3831ee2e5faSnakanon 		morefld();
3841ee2e5faSnakanon 	cbase = 0;
3851ee2e5faSnakanon 	for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
3861ee2e5faSnakanon 		if (idx < (cbase + FLD_INCR))
3871ee2e5faSnakanon 			return (&fldcp->fields[idx - cbase]);
3881ee2e5faSnakanon 		cbase += FLD_INCR;
3891ee2e5faSnakanon 	}
3901ee2e5faSnakanon 	/* should never happen */
3911ee2e5faSnakanon 	ERROR "trying to access invalid field %d", idx FATAL;
3921ee2e5faSnakanon 	return (NULL);
3931ee2e5faSnakanon }
3941ee2e5faSnakanon 
3951ee2e5faSnakanon int
fldidx(Cell * vp)3961ee2e5faSnakanon fldidx(Cell *vp)
3971ee2e5faSnakanon {
3981ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
3991ee2e5faSnakanon 	Cell	*tbl;
4001ee2e5faSnakanon 	int	cbase;
4011ee2e5faSnakanon 
4021ee2e5faSnakanon 	cbase = 0;
4031ee2e5faSnakanon 	for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
4041ee2e5faSnakanon 		tbl = &fldcp->fields[0];
4051ee2e5faSnakanon 		if (vp >= tbl && vp < (tbl + FLD_INCR))
4061ee2e5faSnakanon 			return (cbase + (vp - tbl));
4071ee2e5faSnakanon 		cbase += FLD_INCR;
4081ee2e5faSnakanon 	}
4091ee2e5faSnakanon 	/* should never happen */
4101ee2e5faSnakanon 	ERROR "trying to access unknown field" FATAL;
4111ee2e5faSnakanon 	return (0);
4121ee2e5faSnakanon }
4131ee2e5faSnakanon 
4141ee2e5faSnakanon static int
refldbld(uchar * rec,uchar * fs)4151ee2e5faSnakanon refldbld(uchar *rec, uchar *fs)	/* build fields from reg expr in FS */
4161ee2e5faSnakanon {
4177c478bd9Sstevel@tonic-gate 	uchar *fr;
4187c478bd9Sstevel@tonic-gate 	int i, tempstat;
4197c478bd9Sstevel@tonic-gate 	fa *pfa;
4201ee2e5faSnakanon 	Cell	*p;
4211ee2e5faSnakanon 	size_t	len;
4227c478bd9Sstevel@tonic-gate 
4231ee2e5faSnakanon 	/* make sure fields is allocated */
4241ee2e5faSnakanon 	adjust_buf(&fields, fields_size);
4257c478bd9Sstevel@tonic-gate 	fr = fields;
4267c478bd9Sstevel@tonic-gate 	*fr = '\0';
4277c478bd9Sstevel@tonic-gate 	if (*rec == '\0')
4287c478bd9Sstevel@tonic-gate 		return (0);
4291ee2e5faSnakanon 
4301ee2e5faSnakanon 	len = strlen((char *)rec) + 1;
4311ee2e5faSnakanon 	expand_buf(&fields, &fields_size, len);
4321ee2e5faSnakanon 	fr = fields;
4331ee2e5faSnakanon 
4347c478bd9Sstevel@tonic-gate 	pfa = makedfa(fs, 1);
4357c478bd9Sstevel@tonic-gate 	dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
4367c478bd9Sstevel@tonic-gate 	tempstat = pfa->initstat;
4371ee2e5faSnakanon 	for (i = 1; ; i++) {
4381ee2e5faSnakanon 		p = getfld(i);
4391ee2e5faSnakanon 		if (!(p->tval & DONTFREE))
4401ee2e5faSnakanon 			xfree(p->sval);
4411ee2e5faSnakanon 		p->tval = FLD | STR | DONTFREE;
4421ee2e5faSnakanon 		p->sval = fr;
4437c478bd9Sstevel@tonic-gate 		dprintf(("refldbld: i=%d\n", i));
4447c478bd9Sstevel@tonic-gate 		if (nematch(pfa, rec)) {
4457c478bd9Sstevel@tonic-gate 			pfa->initstat = 2;
4467c478bd9Sstevel@tonic-gate 			dprintf(("match %s (%d chars)\n", patbeg, patlen));
4471ee2e5faSnakanon 			(void) strncpy((char *)fr, (char *)rec, patbeg-rec);
4487c478bd9Sstevel@tonic-gate 			fr += patbeg - rec + 1;
4497c478bd9Sstevel@tonic-gate 			*(fr-1) = '\0';
4507c478bd9Sstevel@tonic-gate 			rec = patbeg + patlen;
4517c478bd9Sstevel@tonic-gate 		} else {
4527c478bd9Sstevel@tonic-gate 			dprintf(("no match %s\n", rec));
4531ee2e5faSnakanon 			(void) strcpy((char *)fr, (char *)rec);
4547c478bd9Sstevel@tonic-gate 			pfa->initstat = tempstat;
4557c478bd9Sstevel@tonic-gate 			break;
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	return (i);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4611ee2e5faSnakanon void
recbld(void)4621ee2e5faSnakanon recbld(void)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	int i;
465cb4658fbSceastha 	uchar *p;
4661ee2e5faSnakanon 	size_t cnt, len, olen;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	if (donerec == 1)
4697c478bd9Sstevel@tonic-gate 		return;
4701ee2e5faSnakanon 	cnt = 0;
4711ee2e5faSnakanon 	olen = strlen((char *)*OFS);
4727c478bd9Sstevel@tonic-gate 	for (i = 1; i <= *NF; i++) {
4731ee2e5faSnakanon 		p = getsval(getfld(i));
4741ee2e5faSnakanon 		len = strlen((char *)p);
475*8ef4c21aSnakanon 		expand_buf(&record, &record_size, cnt + len + olen);
476*8ef4c21aSnakanon 		(void) memcpy(&record[cnt], p, len);
4771ee2e5faSnakanon 		cnt += len;
4781ee2e5faSnakanon 		if (i < *NF) {
479*8ef4c21aSnakanon 			(void) memcpy(&record[cnt], *OFS, olen);
4801ee2e5faSnakanon 			cnt += olen;
4817c478bd9Sstevel@tonic-gate 		}
4821ee2e5faSnakanon 	}
483*8ef4c21aSnakanon 	record[cnt] = '\0';
4841ee2e5faSnakanon 	dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
485*8ef4c21aSnakanon 	if (!(recloc->tval & DONTFREE))
486*8ef4c21aSnakanon 		xfree(recloc->sval);
4877c478bd9Sstevel@tonic-gate 	recloc->tval = REC | STR | DONTFREE;
488*8ef4c21aSnakanon 	recloc->sval = record;
4891ee2e5faSnakanon 	dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
4907c478bd9Sstevel@tonic-gate 	dprintf(("recbld = |%s|\n", record));
4917c478bd9Sstevel@tonic-gate 	donerec = 1;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate Cell *
fieldadr(int n)4951ee2e5faSnakanon fieldadr(int n)
4967c478bd9Sstevel@tonic-gate {
4971ee2e5faSnakanon 	if (n < 0)
4987c478bd9Sstevel@tonic-gate 		ERROR "trying to access field %d", n FATAL;
4991ee2e5faSnakanon 	return (getfld(n));
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate int	errorflag	= 0;
5037c478bd9Sstevel@tonic-gate char	errbuf[200];
5047c478bd9Sstevel@tonic-gate 
5051ee2e5faSnakanon void
yyerror(char * s)5061ee2e5faSnakanon yyerror(char *s)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	extern uchar *cmdname, *curfname;
5097c478bd9Sstevel@tonic-gate 	static int been_here = 0;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	if (been_here++ > 2)
5127c478bd9Sstevel@tonic-gate 		return;
5131ee2e5faSnakanon 	(void) fprintf(stderr, "%s: %s", cmdname, s);
5141ee2e5faSnakanon 	(void) fprintf(stderr, gettext(" at source line %lld"), lineno);
5157c478bd9Sstevel@tonic-gate 	if (curfname != NULL)
5161ee2e5faSnakanon 		(void) fprintf(stderr, gettext(" in function %s"), curfname);
5171ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
5187c478bd9Sstevel@tonic-gate 	errorflag = 2;
5197c478bd9Sstevel@tonic-gate 	eprint();
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5221ee2e5faSnakanon /*ARGSUSED*/
5231ee2e5faSnakanon void
fpecatch(int sig)5241ee2e5faSnakanon fpecatch(int sig)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	ERROR "floating point exception" FATAL;
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate extern int bracecnt, brackcnt, parencnt;
5307c478bd9Sstevel@tonic-gate 
5311ee2e5faSnakanon void
bracecheck(void)5321ee2e5faSnakanon bracecheck(void)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate 	int c;
5357c478bd9Sstevel@tonic-gate 	static int beenhere = 0;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (beenhere++)
5387c478bd9Sstevel@tonic-gate 		return;
5397c478bd9Sstevel@tonic-gate 	while ((c = input()) != EOF && c != '\0')
5407c478bd9Sstevel@tonic-gate 		bclass(c);
5417c478bd9Sstevel@tonic-gate 	bcheck2(bracecnt, '{', '}');
5427c478bd9Sstevel@tonic-gate 	bcheck2(brackcnt, '[', ']');
5437c478bd9Sstevel@tonic-gate 	bcheck2(parencnt, '(', ')');
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate 
5461ee2e5faSnakanon /*ARGSUSED*/
5471ee2e5faSnakanon static void
bcheck2(int n,int c1,int c2)5481ee2e5faSnakanon bcheck2(int n, int c1, int c2)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate 	if (n == 1)
5511ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
5527c478bd9Sstevel@tonic-gate 	else if (n > 1)
5531ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
5547c478bd9Sstevel@tonic-gate 	else if (n == -1)
5551ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\textra %c\n"), c2);
5567c478bd9Sstevel@tonic-gate 	else if (n < -1)
5571ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5601ee2e5faSnakanon void
error(int f,char * s)5611ee2e5faSnakanon error(int f, char *s)
5627c478bd9Sstevel@tonic-gate {
5637c478bd9Sstevel@tonic-gate 	extern Node *curnode;
5647c478bd9Sstevel@tonic-gate 	extern uchar *cmdname;
5657c478bd9Sstevel@tonic-gate 
5661ee2e5faSnakanon 	(void) fflush(stdout);
5671ee2e5faSnakanon 	(void) fprintf(stderr, "%s: ", cmdname);
5681ee2e5faSnakanon 	(void) fprintf(stderr, "%s", s);
5691ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
5707c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && NR && *NR > 0) {
5711ee2e5faSnakanon 		(void) fprintf(stderr,
5721ee2e5faSnakanon 		    gettext(" input record number %g"), *FNR);
5731ee2e5faSnakanon 		if (strcmp((char *)*FILENAME, "-") != 0)
5741ee2e5faSnakanon 			(void) fprintf(stderr, gettext(", file %s"), *FILENAME);
5751ee2e5faSnakanon 		(void) fprintf(stderr, "\n");
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && curnode)
5781ee2e5faSnakanon 		(void) fprintf(stderr, gettext(" source line number %lld\n"),
5797c478bd9Sstevel@tonic-gate 		    curnode->lineno);
5801ee2e5faSnakanon 	else if (compile_time != 2 && lineno) {
5811ee2e5faSnakanon 		(void) fprintf(stderr,
5821ee2e5faSnakanon 		    gettext(" source line number %lld\n"), lineno);
5831ee2e5faSnakanon 	}
5847c478bd9Sstevel@tonic-gate 	eprint();
5857c478bd9Sstevel@tonic-gate 	if (f) {
5867c478bd9Sstevel@tonic-gate 		if (dbg)
5877c478bd9Sstevel@tonic-gate 			abort();
5887c478bd9Sstevel@tonic-gate 		exit(2);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
5921ee2e5faSnakanon static void
eprint(void)5931ee2e5faSnakanon eprint(void)	/* try to print context around error */
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	uchar *p, *q;
5967c478bd9Sstevel@tonic-gate 	int c;
5977c478bd9Sstevel@tonic-gate 	static int been_here = 0;
5987c478bd9Sstevel@tonic-gate 	extern uchar ebuf[300], *ep;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
6017c478bd9Sstevel@tonic-gate 		return;
6027c478bd9Sstevel@tonic-gate 	p = ep - 1;
6037c478bd9Sstevel@tonic-gate 	if (p > ebuf && *p == '\n')
6047c478bd9Sstevel@tonic-gate 		p--;
6057c478bd9Sstevel@tonic-gate 	for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
6067c478bd9Sstevel@tonic-gate 		;
6077c478bd9Sstevel@tonic-gate 	while (*p == '\n')
6087c478bd9Sstevel@tonic-gate 		p++;
6091ee2e5faSnakanon 	(void) fprintf(stderr, gettext(" context is\n\t"));
6101ee2e5faSnakanon 	for (q = ep-1; q >= p && *q != ' ' && *q != '\t' && *q != '\n'; q--)
6117c478bd9Sstevel@tonic-gate 		;
6127c478bd9Sstevel@tonic-gate 	for (; p < q; p++)
6137c478bd9Sstevel@tonic-gate 		if (*p)
6141ee2e5faSnakanon 			(void) putc(*p, stderr);
6151ee2e5faSnakanon 	(void) fprintf(stderr, " >>> ");
6167c478bd9Sstevel@tonic-gate 	for (; p < ep; p++)
6177c478bd9Sstevel@tonic-gate 		if (*p)
6181ee2e5faSnakanon 			(void) putc(*p, stderr);
6191ee2e5faSnakanon 	(void) fprintf(stderr, " <<< ");
6207c478bd9Sstevel@tonic-gate 	if (*ep)
6217c478bd9Sstevel@tonic-gate 		while ((c = input()) != '\n' && c != '\0' && c != EOF) {
6221ee2e5faSnakanon 			(void) putc(c, stderr);
6237c478bd9Sstevel@tonic-gate 			bclass(c);
6247c478bd9Sstevel@tonic-gate 		}
6251ee2e5faSnakanon 	(void) putc('\n', stderr);
6267c478bd9Sstevel@tonic-gate 	ep = ebuf;
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate 
6291ee2e5faSnakanon static void
bclass(int c)6301ee2e5faSnakanon bclass(int c)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate 	switch (c) {
6337c478bd9Sstevel@tonic-gate 	case '{': bracecnt++; break;
6347c478bd9Sstevel@tonic-gate 	case '}': bracecnt--; break;
6357c478bd9Sstevel@tonic-gate 	case '[': brackcnt++; break;
6367c478bd9Sstevel@tonic-gate 	case ']': brackcnt--; break;
6377c478bd9Sstevel@tonic-gate 	case '(': parencnt++; break;
6387c478bd9Sstevel@tonic-gate 	case ')': parencnt--; break;
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate double
errcheck(double x,char * s)6431ee2e5faSnakanon errcheck(double x, char *s)
6447c478bd9Sstevel@tonic-gate {
6457c478bd9Sstevel@tonic-gate 	extern int errno;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if (errno == EDOM) {
6487c478bd9Sstevel@tonic-gate 		errno = 0;
6497c478bd9Sstevel@tonic-gate 		ERROR "%s argument out of domain", s WARNING;
6507c478bd9Sstevel@tonic-gate 		x = 1;
6517c478bd9Sstevel@tonic-gate 	} else if (errno == ERANGE) {
6527c478bd9Sstevel@tonic-gate 		errno = 0;
6537c478bd9Sstevel@tonic-gate 		ERROR "%s result out of range", s WARNING;
6547c478bd9Sstevel@tonic-gate 		x = 1;
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 	return (x);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate 
6591ee2e5faSnakanon void
PUTS(uchar * s)6601ee2e5faSnakanon PUTS(uchar *s)
6611ee2e5faSnakanon {
6627c478bd9Sstevel@tonic-gate 	dprintf(("%s\n", s));
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6651ee2e5faSnakanon int
isclvar(uchar * s)6661ee2e5faSnakanon isclvar(uchar *s)	/* is s of form var=something? */
6677c478bd9Sstevel@tonic-gate {
668cb4658fbSceastha 	if (s != NULL) {
6697c478bd9Sstevel@tonic-gate 
670cb4658fbSceastha 		/* Must begin with an underscore or alphabetic character */
671cb4658fbSceastha 		if (isalpha(*s) || (*s == '_')) {
672cb4658fbSceastha 
673cb4658fbSceastha 			for (s++; *s; s++) {
674cb4658fbSceastha 				/*
675cb4658fbSceastha 				 * followed by a sequence of underscores,
676cb4658fbSceastha 				 * digits, and alphabetics
677cb4658fbSceastha 				 */
678cb4658fbSceastha 				if (!(isalnum(*s) || *s == '_')) {
6797c478bd9Sstevel@tonic-gate 					break;
680cb4658fbSceastha 				}
681cb4658fbSceastha 			}
682cb4658fbSceastha 			return (*s == '=' && *(s + 1) != '=');
683cb4658fbSceastha 		}
684cb4658fbSceastha 	}
685cb4658fbSceastha 
686cb4658fbSceastha 	return (0);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate #define	MAXEXPON	38	/* maximum exponent for fp number */
6907c478bd9Sstevel@tonic-gate 
6911ee2e5faSnakanon int
is_number(uchar * s)6921ee2e5faSnakanon is_number(uchar *s)
6937c478bd9Sstevel@tonic-gate {
694cb4658fbSceastha 	int d1, d2;
6957c478bd9Sstevel@tonic-gate 	int point;
6967c478bd9Sstevel@tonic-gate 	uchar *es;
6977c478bd9Sstevel@tonic-gate 	extern char	radixpoint;
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	d1 = d2 = point = 0;
7007c478bd9Sstevel@tonic-gate 	while (*s == ' ' || *s == '\t' || *s == '\n')
7017c478bd9Sstevel@tonic-gate 		s++;
7027c478bd9Sstevel@tonic-gate 	if (*s == '\0')
7037c478bd9Sstevel@tonic-gate 		return (0);	/* empty stuff isn't number */
7047c478bd9Sstevel@tonic-gate 	if (*s == '+' || *s == '-')
7057c478bd9Sstevel@tonic-gate 		s++;
7067c478bd9Sstevel@tonic-gate 	if (!isdigit(*s) && *s != radixpoint)
7077c478bd9Sstevel@tonic-gate 		return (0);
7087c478bd9Sstevel@tonic-gate 	if (isdigit(*s)) {
7097c478bd9Sstevel@tonic-gate 		do {
7107c478bd9Sstevel@tonic-gate 			d1++;
7117c478bd9Sstevel@tonic-gate 			s++;
7127c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7137c478bd9Sstevel@tonic-gate 	}
7147c478bd9Sstevel@tonic-gate 	if (d1 >= MAXEXPON)
7157c478bd9Sstevel@tonic-gate 		return (0);	/* too many digits to convert */
7167c478bd9Sstevel@tonic-gate 	if (*s == radixpoint) {
7177c478bd9Sstevel@tonic-gate 		point++;
7187c478bd9Sstevel@tonic-gate 		s++;
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 	if (isdigit(*s)) {
7217c478bd9Sstevel@tonic-gate 		d2++;
7227c478bd9Sstevel@tonic-gate 		do {
7237c478bd9Sstevel@tonic-gate 			s++;
7247c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate 	if (!(d1 || point && d2))
7277c478bd9Sstevel@tonic-gate 		return (0);
7287c478bd9Sstevel@tonic-gate 	if (*s == 'e' || *s == 'E') {
7297c478bd9Sstevel@tonic-gate 		s++;
7307c478bd9Sstevel@tonic-gate 		if (*s == '+' || *s == '-')
7317c478bd9Sstevel@tonic-gate 			s++;
7327c478bd9Sstevel@tonic-gate 		if (!isdigit(*s))
7337c478bd9Sstevel@tonic-gate 			return (0);
7347c478bd9Sstevel@tonic-gate 		es = s;
7357c478bd9Sstevel@tonic-gate 		do {
7367c478bd9Sstevel@tonic-gate 			s++;
7377c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7381ee2e5faSnakanon 		if (s - es > 2) {
7397c478bd9Sstevel@tonic-gate 			return (0);
7401ee2e5faSnakanon 		} else if (s - es == 2 &&
7411ee2e5faSnakanon 		    (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) {
7427c478bd9Sstevel@tonic-gate 			return (0);
7437c478bd9Sstevel@tonic-gate 		}
7441ee2e5faSnakanon 	}
7457c478bd9Sstevel@tonic-gate 	while (*s == ' ' || *s == '\t' || *s == '\n')
7467c478bd9Sstevel@tonic-gate 		s++;
7477c478bd9Sstevel@tonic-gate 	if (*s == '\0')
7487c478bd9Sstevel@tonic-gate 		return (1);
7497c478bd9Sstevel@tonic-gate 	else
7507c478bd9Sstevel@tonic-gate 		return (0);
7517c478bd9Sstevel@tonic-gate }
7521ee2e5faSnakanon 
7531ee2e5faSnakanon void
init_buf(uchar ** optr,size_t * sizep,size_t amt)7541ee2e5faSnakanon init_buf(uchar **optr, size_t *sizep, size_t amt)
7551ee2e5faSnakanon {
7561ee2e5faSnakanon 	uchar	*nptr = NULL;
7571ee2e5faSnakanon 
7581ee2e5faSnakanon 	if ((nptr = malloc(amt)) == NULL)
7591ee2e5faSnakanon 		ERROR "out of space in init_buf" FATAL;
7601ee2e5faSnakanon 	/* initial buffer should have NULL terminated */
7611ee2e5faSnakanon 	*nptr = '\0';
7621ee2e5faSnakanon 	if (sizep != NULL)
7631ee2e5faSnakanon 		*sizep = amt;
7641ee2e5faSnakanon 	*optr = nptr;
7651ee2e5faSnakanon }
7661ee2e5faSnakanon 
7671ee2e5faSnakanon void
r_expand_buf(uchar ** optr,size_t * sizep,size_t req)7681ee2e5faSnakanon r_expand_buf(uchar **optr, size_t *sizep, size_t req)
7691ee2e5faSnakanon {
7701ee2e5faSnakanon 	uchar	*nptr;
7711ee2e5faSnakanon 	size_t	amt, size = *sizep;
7721ee2e5faSnakanon 
7731ee2e5faSnakanon 	if (size != 0 && req < (size - 1))
7741ee2e5faSnakanon 		return;
7751ee2e5faSnakanon 	amt = req + 1 - size;
7761ee2e5faSnakanon 	amt = (amt / LINE_INCR + 1) * LINE_INCR;
7771ee2e5faSnakanon 
7781ee2e5faSnakanon 	if ((nptr = realloc(*optr, size + amt)) == NULL)
7791ee2e5faSnakanon 		ERROR "out of space in expand_buf" FATAL;
7801ee2e5faSnakanon 	/* initial buffer should have NULL terminated */
7811ee2e5faSnakanon 	if (size == 0)
7821ee2e5faSnakanon 		*nptr = '\0';
7831ee2e5faSnakanon 	*sizep += amt;
7841ee2e5faSnakanon 	*optr = nptr;
7851ee2e5faSnakanon }
7861ee2e5faSnakanon 
7871ee2e5faSnakanon void
adjust_buf(uchar ** optr,size_t size)7881ee2e5faSnakanon adjust_buf(uchar **optr, size_t size)
7891ee2e5faSnakanon {
7901ee2e5faSnakanon 	uchar	*nptr;
7911ee2e5faSnakanon 
7921ee2e5faSnakanon 	if ((nptr = realloc(*optr, size)) == NULL)
7931ee2e5faSnakanon 		ERROR "out of space in adjust_buf" FATAL;
7941ee2e5faSnakanon 	*optr = nptr;
7951ee2e5faSnakanon }
796