xref: /titanic_51/usr/src/cmd/awk/lib.c (revision cb4658fbb85e4290093c4fea0eb396a7d98de1fb)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
221ee2e5faSnakanon 
231ee2e5faSnakanon /*
241ee2e5faSnakanon  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
251ee2e5faSnakanon  * Use is subject to license terms.
261ee2e5faSnakanon  */
271ee2e5faSnakanon 
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
307c478bd9Sstevel@tonic-gate 
311ee2e5faSnakanon #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include "awk.h"
357c478bd9Sstevel@tonic-gate #include "y.tab.h"
367c478bd9Sstevel@tonic-gate 
371ee2e5faSnakanon uchar	*recdata;
381ee2e5faSnakanon uchar	*record;
391ee2e5faSnakanon size_t	record_size;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate int	donefld;	/* 1 = implies rec broken into fields */
427c478bd9Sstevel@tonic-gate int	donerec;	/* 1 = record is valid (no flds have changed) */
437c478bd9Sstevel@tonic-gate 
441ee2e5faSnakanon static struct fldtab_chunk {
451ee2e5faSnakanon 	struct fldtab_chunk	*next;
461ee2e5faSnakanon 	Cell			fields[FLD_INCR];
471ee2e5faSnakanon } *fldtab_head, *fldtab_tail;
487c478bd9Sstevel@tonic-gate 
491ee2e5faSnakanon static	size_t	fldtab_maxidx;
507c478bd9Sstevel@tonic-gate 
511ee2e5faSnakanon static FILE	*infile	= NULL;
521ee2e5faSnakanon static uchar	*file	= (uchar*) "";
531ee2e5faSnakanon static uchar	*fields;
541ee2e5faSnakanon static size_t	fields_size = LINE_INCR;
551ee2e5faSnakanon 
561ee2e5faSnakanon static int	maxfld	= 0;	/* last used field */
571ee2e5faSnakanon static int	argno	= 1;	/* current input argument number */
581ee2e5faSnakanon 
591ee2e5faSnakanon static	uchar	*getargv(int);
601ee2e5faSnakanon static	void	cleanfld(int, int);
611ee2e5faSnakanon static	int	refldbld(uchar *, uchar *);
621ee2e5faSnakanon static	void	bcheck2(int, int, int);
631ee2e5faSnakanon static	void	eprint(void);
641ee2e5faSnakanon static	void	bclass(int);
651ee2e5faSnakanon 
661ee2e5faSnakanon static void
671ee2e5faSnakanon initgetrec(void)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	int i;
707c478bd9Sstevel@tonic-gate 	uchar *p;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	for (i = 1; i < *ARGC; i++) {
737c478bd9Sstevel@tonic-gate 		if (!isclvar(p = getargv(i)))	/* find 1st real filename */
747c478bd9Sstevel@tonic-gate 			return;
757c478bd9Sstevel@tonic-gate 		setclvar(p);	/* a commandline assignment before filename */
767c478bd9Sstevel@tonic-gate 		argno++;
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 	infile = stdin;		/* no filenames, so use stdin */
797c478bd9Sstevel@tonic-gate 	/* *FILENAME = file = (uchar*) "-"; */
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate 
821ee2e5faSnakanon int
831ee2e5faSnakanon getrec(uchar **bufp, size_t *bufsizep)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	int c;
867c478bd9Sstevel@tonic-gate 	static int firsttime = 1;
871ee2e5faSnakanon 	uchar_t	*buf, *nbuf;
881ee2e5faSnakanon 	size_t	len;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	if (firsttime) {
917c478bd9Sstevel@tonic-gate 		firsttime = 0;
927c478bd9Sstevel@tonic-gate 		initgetrec();
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 	dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
957c478bd9Sstevel@tonic-gate 	    *RS, *FS, *ARGC, *FILENAME));
967c478bd9Sstevel@tonic-gate 	donefld = 0;
977c478bd9Sstevel@tonic-gate 	donerec = 1;
987c478bd9Sstevel@tonic-gate 	while (argno < *ARGC || infile == stdin) {
997c478bd9Sstevel@tonic-gate 		dprintf(("argno=%d, file=|%s|\n", argno, file));
1007c478bd9Sstevel@tonic-gate 		if (infile == NULL) {	/* have to open a new file */
1017c478bd9Sstevel@tonic-gate 			file = getargv(argno);
1027c478bd9Sstevel@tonic-gate 			if (*file == '\0') {	/* it's been zapped */
1037c478bd9Sstevel@tonic-gate 				argno++;
1047c478bd9Sstevel@tonic-gate 				continue;
1057c478bd9Sstevel@tonic-gate 			}
1067c478bd9Sstevel@tonic-gate 			if (isclvar(file)) {	/* a var=value arg */
1077c478bd9Sstevel@tonic-gate 				setclvar(file);
1087c478bd9Sstevel@tonic-gate 				argno++;
1097c478bd9Sstevel@tonic-gate 				continue;
1107c478bd9Sstevel@tonic-gate 			}
1117c478bd9Sstevel@tonic-gate 			*FILENAME = file;
1127c478bd9Sstevel@tonic-gate 			dprintf(("opening file %s\n", file));
1137c478bd9Sstevel@tonic-gate 			if (*file == '-' && *(file+1) == '\0')
1147c478bd9Sstevel@tonic-gate 				infile = stdin;
1157c478bd9Sstevel@tonic-gate 			else if ((infile = fopen((char *)file, "r")) == NULL)
1167c478bd9Sstevel@tonic-gate 				ERROR "can't open file %s", file FATAL;
1171ee2e5faSnakanon 			(void) setfval(fnrloc, 0.0);
1187c478bd9Sstevel@tonic-gate 		}
1191ee2e5faSnakanon 		c = readrec(&nbuf, &len, infile);
1201ee2e5faSnakanon 		expand_buf(bufp, bufsizep, len);
1211ee2e5faSnakanon 		buf = *bufp;
1221ee2e5faSnakanon 		(void) memcpy(buf, nbuf, len);
1231ee2e5faSnakanon 		buf[len] = '\0';
1241ee2e5faSnakanon 		free(nbuf);
1251ee2e5faSnakanon 
1267c478bd9Sstevel@tonic-gate 		if (c != 0 || buf[0] != '\0') {	/* normal record */
1277c478bd9Sstevel@tonic-gate 			if (buf == record) {
1287c478bd9Sstevel@tonic-gate 				if (!(recloc->tval & DONTFREE))
1297c478bd9Sstevel@tonic-gate 					xfree(recloc->sval);
1307c478bd9Sstevel@tonic-gate 				recloc->sval = record;
1317c478bd9Sstevel@tonic-gate 				recloc->tval = REC | STR | DONTFREE;
1321ee2e5faSnakanon 				if (is_number(recloc->sval)) {
1331ee2e5faSnakanon 					recloc->fval =
1341ee2e5faSnakanon 					    atof((const char *)recloc->sval);
1357c478bd9Sstevel@tonic-gate 					recloc->tval |= NUM;
1367c478bd9Sstevel@tonic-gate 				}
1377c478bd9Sstevel@tonic-gate 			}
1381ee2e5faSnakanon 			(void) setfval(nrloc, nrloc->fval+1);
1391ee2e5faSnakanon 			(void) setfval(fnrloc, fnrloc->fval+1);
1407c478bd9Sstevel@tonic-gate 			return (1);
1417c478bd9Sstevel@tonic-gate 		}
1427c478bd9Sstevel@tonic-gate 		/* EOF arrived on this file; set up next */
1437c478bd9Sstevel@tonic-gate 		if (infile != stdin)
1441ee2e5faSnakanon 			(void) fclose(infile);
1457c478bd9Sstevel@tonic-gate 		infile = NULL;
1467c478bd9Sstevel@tonic-gate 		argno++;
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	return (0);	/* true end of file */
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1511ee2e5faSnakanon int
1521ee2e5faSnakanon readrec(uchar **bufp, size_t *sizep, FILE *inf)	/* read one record into buf */
1537c478bd9Sstevel@tonic-gate {
154*cb4658fbSceastha 	int sep, c;
1551ee2e5faSnakanon 	uchar	*buf;
1567c478bd9Sstevel@tonic-gate 	int	count;
1571ee2e5faSnakanon 	size_t	bufsize;
1587c478bd9Sstevel@tonic-gate 
1591ee2e5faSnakanon 	init_buf(&buf, &bufsize, LINE_INCR);
1607c478bd9Sstevel@tonic-gate 	if ((sep = **RS) == 0) {
1617c478bd9Sstevel@tonic-gate 		sep = '\n';
1627c478bd9Sstevel@tonic-gate 		/* skip leading \n's */
1637c478bd9Sstevel@tonic-gate 		while ((c = getc(inf)) == '\n' && c != EOF)
1647c478bd9Sstevel@tonic-gate 			;
1657c478bd9Sstevel@tonic-gate 		if (c != EOF)
1661ee2e5faSnakanon 			(void) ungetc(c, inf);
1677c478bd9Sstevel@tonic-gate 	}
1681ee2e5faSnakanon 	count = 0;
1691ee2e5faSnakanon 	for (;;) {
1707c478bd9Sstevel@tonic-gate 		while ((c = getc(inf)) != sep && c != EOF) {
1711ee2e5faSnakanon 			expand_buf(&buf, &bufsize, count);
1721ee2e5faSnakanon 			buf[count++] = c;
1737c478bd9Sstevel@tonic-gate 		}
1747c478bd9Sstevel@tonic-gate 		if (**RS == sep || c == EOF)
1757c478bd9Sstevel@tonic-gate 			break;
1767c478bd9Sstevel@tonic-gate 		if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
1777c478bd9Sstevel@tonic-gate 			break;
1781ee2e5faSnakanon 		expand_buf(&buf, &bufsize, count + 1);
1791ee2e5faSnakanon 		buf[count++] = '\n';
1801ee2e5faSnakanon 		buf[count++] = c;
1817c478bd9Sstevel@tonic-gate 	}
1821ee2e5faSnakanon 	buf[count] = '\0';
1837c478bd9Sstevel@tonic-gate 	dprintf(("readrec saw <%s>, returns %d\n",
1841ee2e5faSnakanon 	    buf, c == EOF && count == 0 ? 0 : 1));
1851ee2e5faSnakanon 	*bufp = buf;
1861ee2e5faSnakanon 	*sizep = count;
1871ee2e5faSnakanon 	return (c == EOF && count == 0 ? 0 : 1);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate /* get ARGV[n] */
1911ee2e5faSnakanon static uchar *
1921ee2e5faSnakanon getargv(int n)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	Cell *x;
1951ee2e5faSnakanon 	uchar *s, temp[11];
1967c478bd9Sstevel@tonic-gate 	extern Array *ARGVtab;
1977c478bd9Sstevel@tonic-gate 
1981ee2e5faSnakanon 	(void) sprintf((char *)temp, "%d", n);
1991ee2e5faSnakanon 	x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab);
2007c478bd9Sstevel@tonic-gate 	s = getsval(x);
2017c478bd9Sstevel@tonic-gate 	dprintf(("getargv(%d) returns |%s|\n", n, s));
2027c478bd9Sstevel@tonic-gate 	return (s);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
2051ee2e5faSnakanon void
2061ee2e5faSnakanon setclvar(uchar *s)	/* set var=value from s */
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate 	uchar *p;
2097c478bd9Sstevel@tonic-gate 	Cell *q;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	for (p = s; *p != '='; p++)
2127c478bd9Sstevel@tonic-gate 		;
2137c478bd9Sstevel@tonic-gate 	*p++ = 0;
2147c478bd9Sstevel@tonic-gate 	p = qstring(p, '\0');
2157c478bd9Sstevel@tonic-gate 	q = setsymtab(s, p, 0.0, STR, symtab);
2161ee2e5faSnakanon 	(void) setsval(q, p);
2171ee2e5faSnakanon 	if (is_number(q->sval)) {
2181ee2e5faSnakanon 		q->fval = atof((const char *)q->sval);
2197c478bd9Sstevel@tonic-gate 		q->tval |= NUM;
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 	dprintf(("command line set %s to |%s|\n", s, p));
2221ee2e5faSnakanon 	free(p);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2251ee2e5faSnakanon void
2261ee2e5faSnakanon fldbld(void)
2277c478bd9Sstevel@tonic-gate {
228*cb4658fbSceastha 	uchar *r, *fr, sep;
2297c478bd9Sstevel@tonic-gate 	Cell *p;
2307c478bd9Sstevel@tonic-gate 	int i;
2311ee2e5faSnakanon 	size_t	len;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (donefld)
2347c478bd9Sstevel@tonic-gate 		return;
2357c478bd9Sstevel@tonic-gate 	if (!(recloc->tval & STR))
2361ee2e5faSnakanon 		(void) getsval(recloc);
2377c478bd9Sstevel@tonic-gate 	r = recloc->sval;	/* was record! */
2381ee2e5faSnakanon 
2391ee2e5faSnakanon 	/* make sure fields is always allocated */
2401ee2e5faSnakanon 	adjust_buf(&fields, fields_size);
2411ee2e5faSnakanon 
2421ee2e5faSnakanon 	/*
2431ee2e5faSnakanon 	 * make sure fields has enough size. We don't expand the buffer
2441ee2e5faSnakanon 	 * in the middle of the loop, since p->sval has already pointed
2451ee2e5faSnakanon 	 * the address in the fields.
2461ee2e5faSnakanon 	 */
2471ee2e5faSnakanon 	len = strlen((char *)r) + 1;
2481ee2e5faSnakanon 	expand_buf(&fields, &fields_size, len);
2497c478bd9Sstevel@tonic-gate 	fr = fields;
2501ee2e5faSnakanon 
2517c478bd9Sstevel@tonic-gate 	i = 0;	/* number of fields accumulated here */
2521ee2e5faSnakanon 	if (strlen((char *)*FS) > 1) {	/* it's a regular expression */
2537c478bd9Sstevel@tonic-gate 		i = refldbld(r, *FS);
2547c478bd9Sstevel@tonic-gate 	} else if ((sep = **FS) == ' ') {
2557c478bd9Sstevel@tonic-gate 		for (i = 0; ; ) {
2567c478bd9Sstevel@tonic-gate 			while (*r == ' ' || *r == '\t' || *r == '\n')
2577c478bd9Sstevel@tonic-gate 				r++;
2587c478bd9Sstevel@tonic-gate 			if (*r == 0)
2597c478bd9Sstevel@tonic-gate 				break;
2607c478bd9Sstevel@tonic-gate 			i++;
2611ee2e5faSnakanon 			p = getfld(i);
2621ee2e5faSnakanon 			if (!(p->tval & DONTFREE))
2631ee2e5faSnakanon 				xfree(p->sval);
2641ee2e5faSnakanon 			p->sval = fr;
2651ee2e5faSnakanon 			p->tval = FLD | STR | DONTFREE;
2667c478bd9Sstevel@tonic-gate 			do
2677c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
2687c478bd9Sstevel@tonic-gate 			while (*r != ' ' && *r != '\t' && *r != '\n' &&
2691ee2e5faSnakanon 			    *r != '\0')
2701ee2e5faSnakanon 				;
2717c478bd9Sstevel@tonic-gate 			*fr++ = 0;
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 		*fr = 0;
2747c478bd9Sstevel@tonic-gate 	} else if (*r != 0) {	/* if 0, it's a null field */
2757c478bd9Sstevel@tonic-gate 		for (;;) {
2767c478bd9Sstevel@tonic-gate 			i++;
2771ee2e5faSnakanon 			p = getfld(i);
2781ee2e5faSnakanon 			if (!(p->tval & DONTFREE))
2791ee2e5faSnakanon 				xfree(p->sval);
2801ee2e5faSnakanon 			p->sval = fr;
2811ee2e5faSnakanon 			p->tval = FLD | STR | DONTFREE;
2827c478bd9Sstevel@tonic-gate 			/* \n always a separator */
2837c478bd9Sstevel@tonic-gate 			while (*r != sep && *r != '\n' && *r != '\0')
2847c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
2857c478bd9Sstevel@tonic-gate 			*fr++ = 0;
2867c478bd9Sstevel@tonic-gate 			if (*r++ == 0)
2877c478bd9Sstevel@tonic-gate 				break;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		*fr = 0;
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 	/* clean out junk from previous record */
2927c478bd9Sstevel@tonic-gate 	cleanfld(i, maxfld);
2937c478bd9Sstevel@tonic-gate 	maxfld = i;
2947c478bd9Sstevel@tonic-gate 	donefld = 1;
2951ee2e5faSnakanon 	for (i = 1; i <= maxfld; i++) {
2961ee2e5faSnakanon 		p = getfld(i);
2971ee2e5faSnakanon 		if (is_number(p->sval)) {
2981ee2e5faSnakanon 			p->fval = atof((const char *)p->sval);
2997c478bd9Sstevel@tonic-gate 			p->tval |= NUM;
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 	}
3021ee2e5faSnakanon 
3031ee2e5faSnakanon 	(void) setfval(nfloc, (Awkfloat) maxfld);
3041ee2e5faSnakanon 	if (dbg) {
3051ee2e5faSnakanon 		for (i = 0; i <= maxfld; i++) {
3061ee2e5faSnakanon 			p = getfld(i);
3071ee2e5faSnakanon 			(void) printf("field %d: |%s|\n", i, p->sval);
3081ee2e5faSnakanon 		}
3091ee2e5faSnakanon 	}
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3121ee2e5faSnakanon static void
3131ee2e5faSnakanon cleanfld(int n1, int n2)	/* clean out fields n1..n2 inclusive */
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate 	static uchar *nullstat = (uchar *) "";
316*cb4658fbSceastha 	Cell *p;
3171ee2e5faSnakanon 	int	i;
3187c478bd9Sstevel@tonic-gate 
3191ee2e5faSnakanon 	for (i = n2; i > n1; i--) {
3201ee2e5faSnakanon 		p = getfld(i);
3217c478bd9Sstevel@tonic-gate 		if (!(p->tval & DONTFREE))
3227c478bd9Sstevel@tonic-gate 			xfree(p->sval);
3237c478bd9Sstevel@tonic-gate 		p->tval = FLD | STR | DONTFREE;
3247c478bd9Sstevel@tonic-gate 		p->sval = nullstat;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3281ee2e5faSnakanon void
3291ee2e5faSnakanon newfld(int n)	/* add field n (after end) */
3307c478bd9Sstevel@tonic-gate {
3311ee2e5faSnakanon 	if (n < 0)
3321ee2e5faSnakanon 		ERROR "accessing invalid field", record FATAL;
3331ee2e5faSnakanon 	(void) getfld(n);
3347c478bd9Sstevel@tonic-gate 	cleanfld(maxfld, n);
3357c478bd9Sstevel@tonic-gate 	maxfld = n;
3361ee2e5faSnakanon 	(void) setfval(nfloc, (Awkfloat) n);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate 
3391ee2e5faSnakanon /*
3401ee2e5faSnakanon  * allocate field table. We don't reallocate the table since there
3411ee2e5faSnakanon  * might be somewhere recording the address of the table.
3421ee2e5faSnakanon  */
3431ee2e5faSnakanon static void
3441ee2e5faSnakanon morefld(void)
3457c478bd9Sstevel@tonic-gate {
3461ee2e5faSnakanon 	int	i;
3471ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
3481ee2e5faSnakanon 	Cell	*newfld;
3491ee2e5faSnakanon 
3501ee2e5faSnakanon 	if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL)
3511ee2e5faSnakanon 		ERROR "out of space in morefld" FATAL;
3521ee2e5faSnakanon 
3531ee2e5faSnakanon 	newfld = &fldcp->fields[0];
3541ee2e5faSnakanon 	for (i = 0; i < FLD_INCR; i++) {
3551ee2e5faSnakanon 		newfld[i].ctype = OCELL;
3561ee2e5faSnakanon 		newfld[i].csub = CFLD;
3571ee2e5faSnakanon 		newfld[i].nval = NULL;
3581ee2e5faSnakanon 		newfld[i].sval = (uchar *)"";
3591ee2e5faSnakanon 		newfld[i].fval = 0.0;
3601ee2e5faSnakanon 		newfld[i].tval = FLD|STR|DONTFREE;
3611ee2e5faSnakanon 		newfld[i].cnext = NULL;
3621ee2e5faSnakanon 	}
3631ee2e5faSnakanon 	/*
3641ee2e5faSnakanon 	 * link this field chunk
3651ee2e5faSnakanon 	 */
3661ee2e5faSnakanon 	if (fldtab_head == NULL)
3671ee2e5faSnakanon 		fldtab_head = fldcp;
3681ee2e5faSnakanon 	else
3691ee2e5faSnakanon 		fldtab_tail->next = fldcp;
3701ee2e5faSnakanon 	fldtab_tail = fldcp;
3711ee2e5faSnakanon 	fldcp->next = NULL;
3721ee2e5faSnakanon 
3731ee2e5faSnakanon 	fldtab_maxidx += FLD_INCR;
3741ee2e5faSnakanon }
3751ee2e5faSnakanon 
3761ee2e5faSnakanon Cell *
3771ee2e5faSnakanon getfld(int idx)
3781ee2e5faSnakanon {
3791ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
3801ee2e5faSnakanon 	int	cbase;
3811ee2e5faSnakanon 
3821ee2e5faSnakanon 	if (idx < 0)
3831ee2e5faSnakanon 		ERROR "trying to access field %d", idx FATAL;
3841ee2e5faSnakanon 	while (idx >= fldtab_maxidx)
3851ee2e5faSnakanon 		morefld();
3861ee2e5faSnakanon 	cbase = 0;
3871ee2e5faSnakanon 	for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
3881ee2e5faSnakanon 		if (idx < (cbase + FLD_INCR))
3891ee2e5faSnakanon 			return (&fldcp->fields[idx - cbase]);
3901ee2e5faSnakanon 		cbase += FLD_INCR;
3911ee2e5faSnakanon 	}
3921ee2e5faSnakanon 	/* should never happen */
3931ee2e5faSnakanon 	ERROR "trying to access invalid field %d", idx FATAL;
3941ee2e5faSnakanon 	return (NULL);
3951ee2e5faSnakanon }
3961ee2e5faSnakanon 
3971ee2e5faSnakanon int
3981ee2e5faSnakanon fldidx(Cell *vp)
3991ee2e5faSnakanon {
4001ee2e5faSnakanon 	struct fldtab_chunk *fldcp;
4011ee2e5faSnakanon 	Cell	*tbl;
4021ee2e5faSnakanon 	int	cbase;
4031ee2e5faSnakanon 
4041ee2e5faSnakanon 	cbase = 0;
4051ee2e5faSnakanon 	for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
4061ee2e5faSnakanon 		tbl = &fldcp->fields[0];
4071ee2e5faSnakanon 		if (vp >= tbl && vp < (tbl + FLD_INCR))
4081ee2e5faSnakanon 			return (cbase + (vp - tbl));
4091ee2e5faSnakanon 		cbase += FLD_INCR;
4101ee2e5faSnakanon 	}
4111ee2e5faSnakanon 	/* should never happen */
4121ee2e5faSnakanon 	ERROR "trying to access unknown field" FATAL;
4131ee2e5faSnakanon 	return (0);
4141ee2e5faSnakanon }
4151ee2e5faSnakanon 
4161ee2e5faSnakanon static int
4171ee2e5faSnakanon refldbld(uchar *rec, uchar *fs)	/* build fields from reg expr in FS */
4181ee2e5faSnakanon {
4197c478bd9Sstevel@tonic-gate 	uchar *fr;
4207c478bd9Sstevel@tonic-gate 	int i, tempstat;
4217c478bd9Sstevel@tonic-gate 	fa *pfa;
4221ee2e5faSnakanon 	Cell	*p;
4231ee2e5faSnakanon 	size_t	len;
4247c478bd9Sstevel@tonic-gate 
4251ee2e5faSnakanon 	/* make sure fields is allocated */
4261ee2e5faSnakanon 	adjust_buf(&fields, fields_size);
4277c478bd9Sstevel@tonic-gate 	fr = fields;
4287c478bd9Sstevel@tonic-gate 	*fr = '\0';
4297c478bd9Sstevel@tonic-gate 	if (*rec == '\0')
4307c478bd9Sstevel@tonic-gate 		return (0);
4311ee2e5faSnakanon 
4321ee2e5faSnakanon 	len = strlen((char *)rec) + 1;
4331ee2e5faSnakanon 	expand_buf(&fields, &fields_size, len);
4341ee2e5faSnakanon 	fr = fields;
4351ee2e5faSnakanon 
4367c478bd9Sstevel@tonic-gate 	pfa = makedfa(fs, 1);
4377c478bd9Sstevel@tonic-gate 	dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
4387c478bd9Sstevel@tonic-gate 	tempstat = pfa->initstat;
4391ee2e5faSnakanon 	for (i = 1; ; i++) {
4401ee2e5faSnakanon 		p = getfld(i);
4411ee2e5faSnakanon 		if (!(p->tval & DONTFREE))
4421ee2e5faSnakanon 			xfree(p->sval);
4431ee2e5faSnakanon 		p->tval = FLD | STR | DONTFREE;
4441ee2e5faSnakanon 		p->sval = fr;
4457c478bd9Sstevel@tonic-gate 		dprintf(("refldbld: i=%d\n", i));
4467c478bd9Sstevel@tonic-gate 		if (nematch(pfa, rec)) {
4477c478bd9Sstevel@tonic-gate 			pfa->initstat = 2;
4487c478bd9Sstevel@tonic-gate 			dprintf(("match %s (%d chars)\n", patbeg, patlen));
4491ee2e5faSnakanon 			(void) strncpy((char *)fr, (char *)rec, patbeg-rec);
4507c478bd9Sstevel@tonic-gate 			fr += patbeg - rec + 1;
4517c478bd9Sstevel@tonic-gate 			*(fr-1) = '\0';
4527c478bd9Sstevel@tonic-gate 			rec = patbeg + patlen;
4537c478bd9Sstevel@tonic-gate 		} else {
4547c478bd9Sstevel@tonic-gate 			dprintf(("no match %s\n", rec));
4551ee2e5faSnakanon 			(void) strcpy((char *)fr, (char *)rec);
4567c478bd9Sstevel@tonic-gate 			pfa->initstat = tempstat;
4577c478bd9Sstevel@tonic-gate 			break;
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 	return (i);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4631ee2e5faSnakanon void
4641ee2e5faSnakanon recbld(void)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	int i;
467*cb4658fbSceastha 	uchar *p;
4681ee2e5faSnakanon 	size_t cnt, len, olen;
4691ee2e5faSnakanon 	static uchar *rec;
4701ee2e5faSnakanon 	size_t osize, nsize;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	if (donerec == 1)
4737c478bd9Sstevel@tonic-gate 		return;
4741ee2e5faSnakanon 	/* sync up rec size */
4751ee2e5faSnakanon 	adjust_buf(&rec, record_size);
4761ee2e5faSnakanon 	cnt = 0;
4771ee2e5faSnakanon 	olen = strlen((char *)*OFS);
4787c478bd9Sstevel@tonic-gate 	for (i = 1; i <= *NF; i++) {
4791ee2e5faSnakanon 		p = getsval(getfld(i));
4801ee2e5faSnakanon 		len = strlen((char *)p);
4811ee2e5faSnakanon 		osize = record_size;
4821ee2e5faSnakanon 		nsize = cnt + len + olen;
4831ee2e5faSnakanon 		expand_buf(&rec, &record_size, nsize);
4841ee2e5faSnakanon 		if (osize != record_size)
4851ee2e5faSnakanon 			adjust_buf(&recdata, record_size);
4861ee2e5faSnakanon 		(void) memcpy(&rec[cnt], p, len);
4871ee2e5faSnakanon 		cnt += len;
4881ee2e5faSnakanon 		if (i < *NF) {
4891ee2e5faSnakanon 			(void) memcpy(&rec[cnt], *OFS, olen);
4901ee2e5faSnakanon 			cnt += olen;
4917c478bd9Sstevel@tonic-gate 		}
4921ee2e5faSnakanon 	}
4931ee2e5faSnakanon 	rec[cnt] = '\0';
4941ee2e5faSnakanon 	dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
4957c478bd9Sstevel@tonic-gate 	recloc->tval = REC | STR | DONTFREE;
4967c478bd9Sstevel@tonic-gate 	recloc->sval = record = rec;
4971ee2e5faSnakanon 	dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
4987c478bd9Sstevel@tonic-gate 	dprintf(("recbld = |%s|\n", record));
4997c478bd9Sstevel@tonic-gate 	donerec = 1;
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate Cell *
5031ee2e5faSnakanon fieldadr(int n)
5047c478bd9Sstevel@tonic-gate {
5051ee2e5faSnakanon 	if (n < 0)
5067c478bd9Sstevel@tonic-gate 		ERROR "trying to access field %d", n FATAL;
5071ee2e5faSnakanon 	return (getfld(n));
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate int	errorflag	= 0;
5117c478bd9Sstevel@tonic-gate char	errbuf[200];
5127c478bd9Sstevel@tonic-gate 
5131ee2e5faSnakanon void
5141ee2e5faSnakanon yyerror(char *s)
5157c478bd9Sstevel@tonic-gate {
5167c478bd9Sstevel@tonic-gate 	extern uchar *cmdname, *curfname;
5177c478bd9Sstevel@tonic-gate 	static int been_here = 0;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (been_here++ > 2)
5207c478bd9Sstevel@tonic-gate 		return;
5211ee2e5faSnakanon 	(void) fprintf(stderr, "%s: %s", cmdname, s);
5221ee2e5faSnakanon 	(void) fprintf(stderr, gettext(" at source line %lld"), lineno);
5237c478bd9Sstevel@tonic-gate 	if (curfname != NULL)
5241ee2e5faSnakanon 		(void) fprintf(stderr, gettext(" in function %s"), curfname);
5251ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
5267c478bd9Sstevel@tonic-gate 	errorflag = 2;
5277c478bd9Sstevel@tonic-gate 	eprint();
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
5301ee2e5faSnakanon /*ARGSUSED*/
5311ee2e5faSnakanon void
5321ee2e5faSnakanon fpecatch(int sig)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate 	ERROR "floating point exception" FATAL;
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate extern int bracecnt, brackcnt, parencnt;
5387c478bd9Sstevel@tonic-gate 
5391ee2e5faSnakanon void
5401ee2e5faSnakanon bracecheck(void)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	int c;
5437c478bd9Sstevel@tonic-gate 	static int beenhere = 0;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	if (beenhere++)
5467c478bd9Sstevel@tonic-gate 		return;
5477c478bd9Sstevel@tonic-gate 	while ((c = input()) != EOF && c != '\0')
5487c478bd9Sstevel@tonic-gate 		bclass(c);
5497c478bd9Sstevel@tonic-gate 	bcheck2(bracecnt, '{', '}');
5507c478bd9Sstevel@tonic-gate 	bcheck2(brackcnt, '[', ']');
5517c478bd9Sstevel@tonic-gate 	bcheck2(parencnt, '(', ')');
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
5541ee2e5faSnakanon /*ARGSUSED*/
5551ee2e5faSnakanon static void
5561ee2e5faSnakanon bcheck2(int n, int c1, int c2)
5577c478bd9Sstevel@tonic-gate {
5587c478bd9Sstevel@tonic-gate 	if (n == 1)
5591ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
5607c478bd9Sstevel@tonic-gate 	else if (n > 1)
5611ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
5627c478bd9Sstevel@tonic-gate 	else if (n == -1)
5631ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\textra %c\n"), c2);
5647c478bd9Sstevel@tonic-gate 	else if (n < -1)
5651ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5681ee2e5faSnakanon void
5691ee2e5faSnakanon error(int f, char *s)
5707c478bd9Sstevel@tonic-gate {
5717c478bd9Sstevel@tonic-gate 	extern Node *curnode;
5727c478bd9Sstevel@tonic-gate 	extern uchar *cmdname;
5737c478bd9Sstevel@tonic-gate 
5741ee2e5faSnakanon 	(void) fflush(stdout);
5751ee2e5faSnakanon 	(void) fprintf(stderr, "%s: ", cmdname);
5761ee2e5faSnakanon 	(void) fprintf(stderr, "%s", s);
5771ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
5787c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && NR && *NR > 0) {
5791ee2e5faSnakanon 		(void) fprintf(stderr,
5801ee2e5faSnakanon 		    gettext(" input record number %g"), *FNR);
5811ee2e5faSnakanon 		if (strcmp((char *)*FILENAME, "-") != 0)
5821ee2e5faSnakanon 			(void) fprintf(stderr, gettext(", file %s"), *FILENAME);
5831ee2e5faSnakanon 		(void) fprintf(stderr, "\n");
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && curnode)
5861ee2e5faSnakanon 		(void) fprintf(stderr, gettext(" source line number %lld\n"),
5877c478bd9Sstevel@tonic-gate 		    curnode->lineno);
5881ee2e5faSnakanon 	else if (compile_time != 2 && lineno) {
5891ee2e5faSnakanon 		(void) fprintf(stderr,
5901ee2e5faSnakanon 		    gettext(" source line number %lld\n"), lineno);
5911ee2e5faSnakanon 	}
5927c478bd9Sstevel@tonic-gate 	eprint();
5937c478bd9Sstevel@tonic-gate 	if (f) {
5947c478bd9Sstevel@tonic-gate 		if (dbg)
5957c478bd9Sstevel@tonic-gate 			abort();
5967c478bd9Sstevel@tonic-gate 		exit(2);
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6001ee2e5faSnakanon static void
6011ee2e5faSnakanon eprint(void)	/* try to print context around error */
6027c478bd9Sstevel@tonic-gate {
6037c478bd9Sstevel@tonic-gate 	uchar *p, *q;
6047c478bd9Sstevel@tonic-gate 	int c;
6057c478bd9Sstevel@tonic-gate 	static int been_here = 0;
6067c478bd9Sstevel@tonic-gate 	extern uchar ebuf[300], *ep;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
6097c478bd9Sstevel@tonic-gate 		return;
6107c478bd9Sstevel@tonic-gate 	p = ep - 1;
6117c478bd9Sstevel@tonic-gate 	if (p > ebuf && *p == '\n')
6127c478bd9Sstevel@tonic-gate 		p--;
6137c478bd9Sstevel@tonic-gate 	for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
6147c478bd9Sstevel@tonic-gate 		;
6157c478bd9Sstevel@tonic-gate 	while (*p == '\n')
6167c478bd9Sstevel@tonic-gate 		p++;
6171ee2e5faSnakanon 	(void) fprintf(stderr, gettext(" context is\n\t"));
6181ee2e5faSnakanon 	for (q = ep-1; q >= p && *q != ' ' && *q != '\t' && *q != '\n'; q--)
6197c478bd9Sstevel@tonic-gate 		;
6207c478bd9Sstevel@tonic-gate 	for (; p < q; p++)
6217c478bd9Sstevel@tonic-gate 		if (*p)
6221ee2e5faSnakanon 			(void) putc(*p, stderr);
6231ee2e5faSnakanon 	(void) fprintf(stderr, " >>> ");
6247c478bd9Sstevel@tonic-gate 	for (; p < ep; p++)
6257c478bd9Sstevel@tonic-gate 		if (*p)
6261ee2e5faSnakanon 			(void) putc(*p, stderr);
6271ee2e5faSnakanon 	(void) fprintf(stderr, " <<< ");
6287c478bd9Sstevel@tonic-gate 	if (*ep)
6297c478bd9Sstevel@tonic-gate 		while ((c = input()) != '\n' && c != '\0' && c != EOF) {
6301ee2e5faSnakanon 			(void) putc(c, stderr);
6317c478bd9Sstevel@tonic-gate 			bclass(c);
6327c478bd9Sstevel@tonic-gate 		}
6331ee2e5faSnakanon 	(void) putc('\n', stderr);
6347c478bd9Sstevel@tonic-gate 	ep = ebuf;
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6371ee2e5faSnakanon static void
6381ee2e5faSnakanon bclass(int c)
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	switch (c) {
6417c478bd9Sstevel@tonic-gate 	case '{': bracecnt++; break;
6427c478bd9Sstevel@tonic-gate 	case '}': bracecnt--; break;
6437c478bd9Sstevel@tonic-gate 	case '[': brackcnt++; break;
6447c478bd9Sstevel@tonic-gate 	case ']': brackcnt--; break;
6457c478bd9Sstevel@tonic-gate 	case '(': parencnt++; break;
6467c478bd9Sstevel@tonic-gate 	case ')': parencnt--; break;
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate double
6511ee2e5faSnakanon errcheck(double x, char *s)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate 	extern int errno;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	if (errno == EDOM) {
6567c478bd9Sstevel@tonic-gate 		errno = 0;
6577c478bd9Sstevel@tonic-gate 		ERROR "%s argument out of domain", s WARNING;
6587c478bd9Sstevel@tonic-gate 		x = 1;
6597c478bd9Sstevel@tonic-gate 	} else if (errno == ERANGE) {
6607c478bd9Sstevel@tonic-gate 		errno = 0;
6617c478bd9Sstevel@tonic-gate 		ERROR "%s result out of range", s WARNING;
6627c478bd9Sstevel@tonic-gate 		x = 1;
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 	return (x);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6671ee2e5faSnakanon void
6681ee2e5faSnakanon PUTS(uchar *s)
6691ee2e5faSnakanon {
6707c478bd9Sstevel@tonic-gate 	dprintf(("%s\n", s));
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate 
6731ee2e5faSnakanon int
6741ee2e5faSnakanon isclvar(uchar *s)	/* is s of form var=something? */
6757c478bd9Sstevel@tonic-gate {
676*cb4658fbSceastha 	if (s != NULL) {
6777c478bd9Sstevel@tonic-gate 
678*cb4658fbSceastha 		/* Must begin with an underscore or alphabetic character */
679*cb4658fbSceastha 		if (isalpha(*s) || (*s == '_')) {
680*cb4658fbSceastha 
681*cb4658fbSceastha 			for (s++; *s; s++) {
682*cb4658fbSceastha 				/*
683*cb4658fbSceastha 				 * followed by a sequence of underscores,
684*cb4658fbSceastha 				 * digits, and alphabetics
685*cb4658fbSceastha 				 */
686*cb4658fbSceastha 				if (!(isalnum(*s) || *s == '_')) {
6877c478bd9Sstevel@tonic-gate 					break;
688*cb4658fbSceastha 				}
689*cb4658fbSceastha 			}
690*cb4658fbSceastha 			return (*s == '=' && *(s + 1) != '=');
691*cb4658fbSceastha 		}
692*cb4658fbSceastha 	}
693*cb4658fbSceastha 
694*cb4658fbSceastha 	return (0);
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate #define	MAXEXPON	38	/* maximum exponent for fp number */
6987c478bd9Sstevel@tonic-gate 
6991ee2e5faSnakanon int
7001ee2e5faSnakanon is_number(uchar *s)
7017c478bd9Sstevel@tonic-gate {
702*cb4658fbSceastha 	int d1, d2;
7037c478bd9Sstevel@tonic-gate 	int point;
7047c478bd9Sstevel@tonic-gate 	uchar *es;
7057c478bd9Sstevel@tonic-gate 	extern char	radixpoint;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	d1 = d2 = point = 0;
7087c478bd9Sstevel@tonic-gate 	while (*s == ' ' || *s == '\t' || *s == '\n')
7097c478bd9Sstevel@tonic-gate 		s++;
7107c478bd9Sstevel@tonic-gate 	if (*s == '\0')
7117c478bd9Sstevel@tonic-gate 		return (0);	/* empty stuff isn't number */
7127c478bd9Sstevel@tonic-gate 	if (*s == '+' || *s == '-')
7137c478bd9Sstevel@tonic-gate 		s++;
7147c478bd9Sstevel@tonic-gate 	if (!isdigit(*s) && *s != radixpoint)
7157c478bd9Sstevel@tonic-gate 		return (0);
7167c478bd9Sstevel@tonic-gate 	if (isdigit(*s)) {
7177c478bd9Sstevel@tonic-gate 		do {
7187c478bd9Sstevel@tonic-gate 			d1++;
7197c478bd9Sstevel@tonic-gate 			s++;
7207c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7217c478bd9Sstevel@tonic-gate 	}
7227c478bd9Sstevel@tonic-gate 	if (d1 >= MAXEXPON)
7237c478bd9Sstevel@tonic-gate 		return (0);	/* too many digits to convert */
7247c478bd9Sstevel@tonic-gate 	if (*s == radixpoint) {
7257c478bd9Sstevel@tonic-gate 		point++;
7267c478bd9Sstevel@tonic-gate 		s++;
7277c478bd9Sstevel@tonic-gate 	}
7287c478bd9Sstevel@tonic-gate 	if (isdigit(*s)) {
7297c478bd9Sstevel@tonic-gate 		d2++;
7307c478bd9Sstevel@tonic-gate 		do {
7317c478bd9Sstevel@tonic-gate 			s++;
7327c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7337c478bd9Sstevel@tonic-gate 	}
7347c478bd9Sstevel@tonic-gate 	if (!(d1 || point && d2))
7357c478bd9Sstevel@tonic-gate 		return (0);
7367c478bd9Sstevel@tonic-gate 	if (*s == 'e' || *s == 'E') {
7377c478bd9Sstevel@tonic-gate 		s++;
7387c478bd9Sstevel@tonic-gate 		if (*s == '+' || *s == '-')
7397c478bd9Sstevel@tonic-gate 			s++;
7407c478bd9Sstevel@tonic-gate 		if (!isdigit(*s))
7417c478bd9Sstevel@tonic-gate 			return (0);
7427c478bd9Sstevel@tonic-gate 		es = s;
7437c478bd9Sstevel@tonic-gate 		do {
7447c478bd9Sstevel@tonic-gate 			s++;
7457c478bd9Sstevel@tonic-gate 		} while (isdigit(*s));
7461ee2e5faSnakanon 		if (s - es > 2) {
7477c478bd9Sstevel@tonic-gate 			return (0);
7481ee2e5faSnakanon 		} else if (s - es == 2 &&
7491ee2e5faSnakanon 		    (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) {
7507c478bd9Sstevel@tonic-gate 			return (0);
7517c478bd9Sstevel@tonic-gate 		}
7521ee2e5faSnakanon 	}
7537c478bd9Sstevel@tonic-gate 	while (*s == ' ' || *s == '\t' || *s == '\n')
7547c478bd9Sstevel@tonic-gate 		s++;
7557c478bd9Sstevel@tonic-gate 	if (*s == '\0')
7567c478bd9Sstevel@tonic-gate 		return (1);
7577c478bd9Sstevel@tonic-gate 	else
7587c478bd9Sstevel@tonic-gate 		return (0);
7597c478bd9Sstevel@tonic-gate }
7601ee2e5faSnakanon 
7611ee2e5faSnakanon void
7621ee2e5faSnakanon init_buf(uchar **optr, size_t *sizep, size_t amt)
7631ee2e5faSnakanon {
7641ee2e5faSnakanon 	uchar	*nptr = NULL;
7651ee2e5faSnakanon 
7661ee2e5faSnakanon 	if ((nptr = malloc(amt)) == NULL)
7671ee2e5faSnakanon 		ERROR "out of space in init_buf" FATAL;
7681ee2e5faSnakanon 	/* initial buffer should have NULL terminated */
7691ee2e5faSnakanon 	*nptr = '\0';
7701ee2e5faSnakanon 	if (sizep != NULL)
7711ee2e5faSnakanon 		*sizep = amt;
7721ee2e5faSnakanon 	*optr = nptr;
7731ee2e5faSnakanon }
7741ee2e5faSnakanon 
7751ee2e5faSnakanon void
7761ee2e5faSnakanon r_expand_buf(uchar **optr, size_t *sizep, size_t req)
7771ee2e5faSnakanon {
7781ee2e5faSnakanon 	uchar	*nptr;
7791ee2e5faSnakanon 	size_t	amt, size = *sizep;
7801ee2e5faSnakanon 
7811ee2e5faSnakanon 	if (size != 0 && req < (size - 1))
7821ee2e5faSnakanon 		return;
7831ee2e5faSnakanon 	amt = req + 1 - size;
7841ee2e5faSnakanon 	amt = (amt / LINE_INCR + 1) * LINE_INCR;
7851ee2e5faSnakanon 
7861ee2e5faSnakanon 	if ((nptr = realloc(*optr, size + amt)) == NULL)
7871ee2e5faSnakanon 		ERROR "out of space in expand_buf" FATAL;
7881ee2e5faSnakanon 	/* initial buffer should have NULL terminated */
7891ee2e5faSnakanon 	if (size == 0)
7901ee2e5faSnakanon 		*nptr = '\0';
7911ee2e5faSnakanon 	*sizep += amt;
7921ee2e5faSnakanon 	*optr = nptr;
7931ee2e5faSnakanon }
7941ee2e5faSnakanon 
7951ee2e5faSnakanon void
7961ee2e5faSnakanon adjust_buf(uchar **optr, size_t size)
7971ee2e5faSnakanon {
7981ee2e5faSnakanon 	uchar	*nptr;
7991ee2e5faSnakanon 
8001ee2e5faSnakanon 	if ((nptr = realloc(*optr, size)) == NULL)
8011ee2e5faSnakanon 		ERROR "out of space in adjust_buf" FATAL;
8021ee2e5faSnakanon 	*optr = nptr;
8031ee2e5faSnakanon }
804