xref: /csrg-svn/old/awk/lib.c (revision 60482)
148236Sbostic /*-
248236Sbostic  * Copyright (c) 1991 The Regents of the University of California.
348236Sbostic  * All rights reserved.
448236Sbostic  *
548236Sbostic  * %sccs.include.proprietary.c%
648236Sbostic  */
748236Sbostic 
814473Ssam #ifndef lint
9*60482Sbostic static char sccsid[] = "@(#)lib.c	4.11 (Berkeley) 05/26/93";
1048236Sbostic #endif /* not lint */
116671Smckusick 
1258334Storek #ifdef __STDC__
1346819Sbostic #include <stdarg.h>
1458334Storek #else
1558334Storek #include <varargs.h>
1658334Storek #endif
176671Smckusick #include "stdio.h"
186671Smckusick #include "awk.def"
196671Smckusick #include "awk.h"
206671Smckusick #include "ctype.h"
216671Smckusick 
2258334Storek int	error __P((int, const char *, ...));
2358334Storek 
2432354Sbostic extern FILE	*yyin;	/* lex input file */
2544021Sbostic extern char	*lexprog;	/* points to program argument if it exists */
266671Smckusick FILE	*infile	= NULL;
276671Smckusick char	*file;
286671Smckusick #define	RECSIZE	(5 * 512)
296671Smckusick char	record[RECSIZE];
306671Smckusick char	fields[RECSIZE];
3110794Ssam char	EMPTY[] = "";
326671Smckusick 
336671Smckusick #define	MAXFLD	100
346671Smckusick int	donefld;	/* 1 = implies rec broken into fields */
356671Smckusick int	donerec;	/* 1 = record is valid (no flds have changed) */
366671Smckusick int	mustfld;	/* 1 = NF seen, so always break*/
376671Smckusick 
3810794Ssam #define	FINIT	{EMPTY, EMPTY, 0.0, FLD|STR}
396671Smckusick cell fldtab[MAXFLD] = {	/*room for fields */
406671Smckusick 	{ "$record", record, 0.0, STR|FLD},
4131035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4231035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4331035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4431035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4531035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4631035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4731035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4831035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4931035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
506671Smckusick };
516671Smckusick int	maxfld	= 0;	/* last used field */
526671Smckusick 
536671Smckusick 
getrec()546671Smckusick getrec()
556671Smckusick {
566671Smckusick 	register char *rr;
576671Smckusick 	extern int svargc;
586671Smckusick 	extern char **svargv;
596671Smckusick 	register c, sep;
606671Smckusick 
616671Smckusick 	dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
626671Smckusick 	donefld = 0;
636671Smckusick 	donerec = 1;
646671Smckusick 	record[0] = 0;
656671Smckusick 	while (svargc > 0) {
666671Smckusick 		dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
676671Smckusick 		if (infile == NULL) {	/* have to open a new file */
686671Smckusick 			if (member('=', *svargv)) {	/* it's a var=value argument */
696671Smckusick 				setclvar(*svargv);
706671Smckusick 				svargv++;
716671Smckusick 				svargc--;
726671Smckusick 				continue;
736671Smckusick 			}
746671Smckusick 			*FILENAME = file = *svargv;
756671Smckusick 			dprintf("opening file %s\n", file, NULL, NULL);
7632354Sbostic 			if (*file == '-') {
7744021Sbostic 				if (yyin == stdin && ! lexprog)
7832354Sbostic 					error(FATAL, "standard input already used for reading commands");
7932354Sbostic 				else
8032354Sbostic 					infile = stdin;
8132354Sbostic 			}
826671Smckusick 			else if ((infile = fopen(file, "r")) == NULL)
836671Smckusick 				error(FATAL, "can't open %s", file);
846671Smckusick 		}
856671Smckusick 		if ((sep = **RS) == 0)
866671Smckusick 			sep = '\n';
876671Smckusick 		for (rr = record; ; ) {
886671Smckusick 			for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
896671Smckusick 				;
906671Smckusick 			if (**RS == sep || c == EOF)
916671Smckusick 				break;
926671Smckusick 			if ((c = getc(infile)) == '\n' || c == EOF)	/* 2 in a row */
936671Smckusick 				break;
946671Smckusick 			*rr++ = '\n';
956671Smckusick 			*rr++ = c;
966671Smckusick 		}
976671Smckusick 		if (rr > record+RECSIZE)
986671Smckusick 			error(FATAL, "record `%.20s...' too long", record);
996671Smckusick 		*rr = 0;
1006671Smckusick 		if (mustfld)
1016671Smckusick 			fldbld();
1026671Smckusick 		if (c != EOF || rr > record) {	/* normal record */
1036671Smckusick 			recloc->tval &= ~NUM;
1046671Smckusick 			recloc->tval |= STR;
1056671Smckusick 			++nrloc->fval;
1066671Smckusick 			nrloc->tval &= ~STR;
1076671Smckusick 			nrloc->tval |= NUM;
1086671Smckusick 			return(1);
1096671Smckusick 		}
1106671Smckusick 		/* EOF arrived on this file; set up next */
1116671Smckusick 		if (infile != stdin)
1126671Smckusick 			fclose(infile);
1136671Smckusick 		infile = NULL;
1146671Smckusick 		svargc--;
1156671Smckusick 		svargv++;
1166671Smckusick 	}
1176671Smckusick 	return(0);	/* true end of file */
1186671Smckusick }
1196671Smckusick 
setclvar(s)1206671Smckusick setclvar(s)	/* set var=value from s */
1216671Smckusick char *s;
1226671Smckusick {
1236671Smckusick 	char *p;
1246671Smckusick 	cell *q;
1256671Smckusick 
1266671Smckusick 	for (p=s; *p != '='; p++)
1276671Smckusick 		;
1286671Smckusick 	*p++ = 0;
1296671Smckusick 	q = setsymtab(s, tostring(p), 0.0, STR, symtab);
1306671Smckusick 	setsval(q, p);
1316671Smckusick 	dprintf("command line set %s to |%s|\n", s, p, NULL);
1326671Smckusick }
1336671Smckusick 
fldbld()1346671Smckusick fldbld()
1356671Smckusick {
1366671Smckusick 	register char *r, *fr, sep;
1376671Smckusick 	int i, j;
1386671Smckusick 
1396671Smckusick 	r = record;
1406671Smckusick 	fr = fields;
1416671Smckusick 	i = 0;	/* number of fields accumulated here */
1426671Smckusick 	if ((sep = **FS) == ' ')
1436671Smckusick 		for (i = 0; ; ) {
1446671Smckusick 			while (*r == ' ' || *r == '\t' || *r == '\n')
1456671Smckusick 				r++;
1466671Smckusick 			if (*r == 0)
1476671Smckusick 				break;
1486671Smckusick 			i++;
1496671Smckusick 			if (i >= MAXFLD)
1506671Smckusick 				error(FATAL, "record `%.20s...' has too many fields", record);
1516671Smckusick 			if (!(fldtab[i].tval&FLD))
15210794Ssam 				strfree(fldtab[i].sval);
1536671Smckusick 			fldtab[i].sval = fr;
1546671Smckusick 			fldtab[i].tval = FLD | STR;
1556671Smckusick 			do
1566671Smckusick 				*fr++ = *r++;
1576671Smckusick 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
1586671Smckusick 			*fr++ = 0;
1596671Smckusick 		}
1606671Smckusick 	else if (*r != 0)	/* if 0, it's a null field */
1616671Smckusick 		for (;;) {
1626671Smckusick 			i++;
1636671Smckusick 			if (i >= MAXFLD)
1646671Smckusick 				error(FATAL, "record `%.20s...' has too many fields", record);
1656671Smckusick 			if (!(fldtab[i].tval&FLD))
16610794Ssam 				strfree(fldtab[i].sval);
1676671Smckusick 			fldtab[i].sval = fr;
1686671Smckusick 			fldtab[i].tval = FLD | STR;
1696671Smckusick 			while (*r != sep && *r != '\n' && *r != '\0')	/* \n always a separator */
1706671Smckusick 				*fr++ = *r++;
1716671Smckusick 			*fr++ = 0;
1726671Smckusick 			if (*r++ == 0)
1736671Smckusick 				break;
1746671Smckusick 		}
1756671Smckusick 	*fr = 0;
1766671Smckusick 	for (j=MAXFLD-1; j>i; j--) {	/* clean out junk from previous record */
1776671Smckusick 		if (!(fldtab[j].tval&FLD))
17810794Ssam 			strfree(fldtab[j].sval);
1796671Smckusick 		fldtab[j].tval = STR | FLD;
18010794Ssam 		fldtab[j].sval = EMPTY;
1816671Smckusick 	}
1826671Smckusick 	maxfld = i;
1836671Smckusick 	donefld = 1;
1846671Smckusick 	for(i=1; i<=maxfld; i++)
185*60482Sbostic 		if(isanumber(fldtab[i].sval)) {
1866671Smckusick 			fldtab[i].fval = atof(fldtab[i].sval);
1876671Smckusick 			fldtab[i].tval |= NUM;
1886671Smckusick 		}
1896671Smckusick 	setfval(lookup("NF", symtab, 0), (awkfloat) maxfld);
1906671Smckusick 	if (dbg)
1916671Smckusick 		for (i = 0; i <= maxfld; i++)
1926671Smckusick 			printf("field %d: |%s|\n", i, fldtab[i].sval);
1936671Smckusick }
1946671Smckusick 
recbld()1956671Smckusick recbld()
1966671Smckusick {
1976671Smckusick 	int i;
1986671Smckusick 	register char *r, *p;
1996671Smckusick 
2006671Smckusick 	if (donefld == 0 || donerec == 1)
2016671Smckusick 		return;
2026671Smckusick 	r = record;
2036671Smckusick 	for (i = 1; i <= *NF; i++) {
2046671Smckusick 		p = getsval(&fldtab[i]);
2056671Smckusick 		while (*r++ = *p++)
2066671Smckusick 			;
2076671Smckusick 		*(r-1) = **OFS;
2086671Smckusick 	}
2096671Smckusick 	*(r-1) = '\0';
2106671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
2116671Smckusick 	recloc->tval = STR | FLD;
2126671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
2136671Smckusick 	if (r > record+RECSIZE)
2146671Smckusick 		error(FATAL, "built giant record `%.20s...'", record);
2156671Smckusick 	dprintf("recbld = |%s|\n", record, NULL, NULL);
2166671Smckusick }
2176671Smckusick 
fieldadr(n)2186671Smckusick cell *fieldadr(n)
2196671Smckusick {
2206671Smckusick 	if (n >= MAXFLD)
2216671Smckusick 		error(FATAL, "trying to access field %d", n);
2226671Smckusick 	return(&fldtab[n]);
2236671Smckusick }
2246671Smckusick 
2256671Smckusick int	errorflag	= 0;
2266671Smckusick 
yyerror(s)2276671Smckusick yyerror(s) char *s; {
2286671Smckusick 	fprintf(stderr, "awk: %s near line %d\n", s, lineno);
2296671Smckusick 	errorflag = 2;
2306671Smckusick }
2316671Smckusick 
23258334Storek int
23358334Storek #ifdef __STDC__
error(int isfatal,const char * fmt,...)23458334Storek error(int isfatal, const char *fmt, ...)
23558334Storek #else
23658334Storek error(isfatal, fmt, va_alist)
23746819Sbostic 	int isfatal;
23846819Sbostic 	char *fmt;
23958334Storek 	va_dcl
24058334Storek #endif
24146819Sbostic {
24246819Sbostic 	va_list ap;
24346819Sbostic 
24458334Storek #ifdef __STDC__
24546819Sbostic 	va_start(ap, fmt);
24658334Storek #else
24758334Storek 	va_start(ap);
24858334Storek #endif
24946819Sbostic 	(void)fprintf(stderr, "awk: ");
25046819Sbostic 	(void)vfprintf(stderr, fmt, ap);
25146819Sbostic 	va_end(ap);
25246819Sbostic 	(void)fprintf(stderr, "\n");
25317190Sralph 	if (NR && *NR > 0)
25446819Sbostic 		(void)fprintf(stderr, " record number %g\n", *NR);
25546819Sbostic 	if (isfatal)
2566671Smckusick 		exit(2);
2576671Smckusick }
2586671Smckusick 
PUTS(s)2596671Smckusick PUTS(s) char *s; {
2606671Smckusick 	dprintf("%s\n", s, NULL, NULL);
2616671Smckusick }
2626671Smckusick 
2636671Smckusick #define	MAXEXPON	38	/* maximum exponenet for fp number */
2646671Smckusick 
isanumber(s)265*60482Sbostic isanumber(s)
2666671Smckusick register char *s;
2676671Smckusick {
2686671Smckusick 	register d1, d2;
2696671Smckusick 	int point;
2706671Smckusick 	char *es;
2716671Smckusick 
27210794Ssam 	if (s == NULL)
27310794Ssam 		return (0);
2746671Smckusick 	d1 = d2 = point = 0;
2756671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
2766671Smckusick 		s++;
2776671Smckusick 	if (*s == '\0')
2786671Smckusick 		return(0);	/* empty stuff isn't number */
2796671Smckusick 	if (*s == '+' || *s == '-')
2806671Smckusick 		s++;
2816671Smckusick 	if (!isdigit(*s) && *s != '.')
2826671Smckusick 		return(0);
2836671Smckusick 	if (isdigit(*s)) {
2846671Smckusick 		do {
2856671Smckusick 			d1++;
2866671Smckusick 			s++;
2876671Smckusick 		} while (isdigit(*s));
2886671Smckusick 	}
2896671Smckusick 	if(d1 >= MAXEXPON)
2906671Smckusick 		return(0);	/* too many digits to convert */
2916671Smckusick 	if (*s == '.') {
2926671Smckusick 		point++;
2936671Smckusick 		s++;
2946671Smckusick 	}
2956671Smckusick 	if (isdigit(*s)) {
2966671Smckusick 		d2++;
2976671Smckusick 		do {
2986671Smckusick 			s++;
2996671Smckusick 		} while (isdigit(*s));
3006671Smckusick 	}
3016671Smckusick 	if (!(d1 || point && d2))
3026671Smckusick 		return(0);
3036671Smckusick 	if (*s == 'e' || *s == 'E') {
3046671Smckusick 		s++;
3056671Smckusick 		if (*s == '+' || *s == '-')
3066671Smckusick 			s++;
3076671Smckusick 		if (!isdigit(*s))
3086671Smckusick 			return(0);
3096671Smckusick 		es = s;
3106671Smckusick 		do {
3116671Smckusick 			s++;
3126671Smckusick 		} while (isdigit(*s));
3136671Smckusick 		if (s - es > 2)
3146671Smckusick 			return(0);
3156671Smckusick 		else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
3166671Smckusick 			return(0);
3176671Smckusick 	}
3186671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
3196671Smckusick 		s++;
3206671Smckusick 	if (*s == '\0')
3216671Smckusick 		return(1);
3226671Smckusick 	else
3236671Smckusick 		return(0);
3246671Smckusick }
3256671Smckusick /*
326*60482Sbostic isanumber(s) char *s; {return(0);}
3276671Smckusick */
328