xref: /csrg-svn/old/awk/lib.c (revision 46819)
114473Ssam #ifndef lint
2*46819Sbostic static char sccsid[] = "@(#)lib.c	4.8 (Berkeley) 03/01/91";
314473Ssam #endif
46671Smckusick 
5*46819Sbostic #include <stdarg.h>
66671Smckusick #include "stdio.h"
76671Smckusick #include "awk.def"
86671Smckusick #include "awk.h"
96671Smckusick #include "ctype.h"
106671Smckusick 
1132354Sbostic extern FILE	*yyin;	/* lex input file */
1244021Sbostic extern char	*lexprog;	/* points to program argument if it exists */
136671Smckusick FILE	*infile	= NULL;
146671Smckusick char	*file;
156671Smckusick #define	RECSIZE	(5 * 512)
166671Smckusick char	record[RECSIZE];
176671Smckusick char	fields[RECSIZE];
1810794Ssam char	EMPTY[] = "";
196671Smckusick 
206671Smckusick #define	MAXFLD	100
216671Smckusick int	donefld;	/* 1 = implies rec broken into fields */
226671Smckusick int	donerec;	/* 1 = record is valid (no flds have changed) */
236671Smckusick int	mustfld;	/* 1 = NF seen, so always break*/
246671Smckusick 
2510794Ssam #define	FINIT	{EMPTY, EMPTY, 0.0, FLD|STR}
266671Smckusick cell fldtab[MAXFLD] = {	/*room for fields */
276671Smckusick 	{ "$record", record, 0.0, STR|FLD},
2831035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
2931035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3031035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3131035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3231035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3331035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3431035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3531035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
3631035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
376671Smckusick };
386671Smckusick int	maxfld	= 0;	/* last used field */
396671Smckusick 
406671Smckusick 
416671Smckusick getrec()
426671Smckusick {
436671Smckusick 	register char *rr;
446671Smckusick 	extern int svargc;
456671Smckusick 	extern char **svargv;
466671Smckusick 	register c, sep;
476671Smckusick 
486671Smckusick 	dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
496671Smckusick 	donefld = 0;
506671Smckusick 	donerec = 1;
516671Smckusick 	record[0] = 0;
526671Smckusick 	while (svargc > 0) {
536671Smckusick 		dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
546671Smckusick 		if (infile == NULL) {	/* have to open a new file */
556671Smckusick 			if (member('=', *svargv)) {	/* it's a var=value argument */
566671Smckusick 				setclvar(*svargv);
576671Smckusick 				svargv++;
586671Smckusick 				svargc--;
596671Smckusick 				continue;
606671Smckusick 			}
616671Smckusick 			*FILENAME = file = *svargv;
626671Smckusick 			dprintf("opening file %s\n", file, NULL, NULL);
6332354Sbostic 			if (*file == '-') {
6444021Sbostic 				if (yyin == stdin && ! lexprog)
6532354Sbostic 					error(FATAL, "standard input already used for reading commands");
6632354Sbostic 				else
6732354Sbostic 					infile = stdin;
6832354Sbostic 			}
696671Smckusick 			else if ((infile = fopen(file, "r")) == NULL)
706671Smckusick 				error(FATAL, "can't open %s", file);
716671Smckusick 		}
726671Smckusick 		if ((sep = **RS) == 0)
736671Smckusick 			sep = '\n';
746671Smckusick 		for (rr = record; ; ) {
756671Smckusick 			for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
766671Smckusick 				;
776671Smckusick 			if (**RS == sep || c == EOF)
786671Smckusick 				break;
796671Smckusick 			if ((c = getc(infile)) == '\n' || c == EOF)	/* 2 in a row */
806671Smckusick 				break;
816671Smckusick 			*rr++ = '\n';
826671Smckusick 			*rr++ = c;
836671Smckusick 		}
846671Smckusick 		if (rr > record+RECSIZE)
856671Smckusick 			error(FATAL, "record `%.20s...' too long", record);
866671Smckusick 		*rr = 0;
876671Smckusick 		if (mustfld)
886671Smckusick 			fldbld();
896671Smckusick 		if (c != EOF || rr > record) {	/* normal record */
906671Smckusick 			recloc->tval &= ~NUM;
916671Smckusick 			recloc->tval |= STR;
926671Smckusick 			++nrloc->fval;
936671Smckusick 			nrloc->tval &= ~STR;
946671Smckusick 			nrloc->tval |= NUM;
956671Smckusick 			return(1);
966671Smckusick 		}
976671Smckusick 		/* EOF arrived on this file; set up next */
986671Smckusick 		if (infile != stdin)
996671Smckusick 			fclose(infile);
1006671Smckusick 		infile = NULL;
1016671Smckusick 		svargc--;
1026671Smckusick 		svargv++;
1036671Smckusick 	}
1046671Smckusick 	return(0);	/* true end of file */
1056671Smckusick }
1066671Smckusick 
1076671Smckusick setclvar(s)	/* set var=value from s */
1086671Smckusick char *s;
1096671Smckusick {
1106671Smckusick 	char *p;
1116671Smckusick 	cell *q;
1126671Smckusick 
1136671Smckusick 	for (p=s; *p != '='; p++)
1146671Smckusick 		;
1156671Smckusick 	*p++ = 0;
1166671Smckusick 	q = setsymtab(s, tostring(p), 0.0, STR, symtab);
1176671Smckusick 	setsval(q, p);
1186671Smckusick 	dprintf("command line set %s to |%s|\n", s, p, NULL);
1196671Smckusick }
1206671Smckusick 
1216671Smckusick fldbld()
1226671Smckusick {
1236671Smckusick 	register char *r, *fr, sep;
1246671Smckusick 	int i, j;
1256671Smckusick 
1266671Smckusick 	r = record;
1276671Smckusick 	fr = fields;
1286671Smckusick 	i = 0;	/* number of fields accumulated here */
1296671Smckusick 	if ((sep = **FS) == ' ')
1306671Smckusick 		for (i = 0; ; ) {
1316671Smckusick 			while (*r == ' ' || *r == '\t' || *r == '\n')
1326671Smckusick 				r++;
1336671Smckusick 			if (*r == 0)
1346671Smckusick 				break;
1356671Smckusick 			i++;
1366671Smckusick 			if (i >= MAXFLD)
1376671Smckusick 				error(FATAL, "record `%.20s...' has too many fields", record);
1386671Smckusick 			if (!(fldtab[i].tval&FLD))
13910794Ssam 				strfree(fldtab[i].sval);
1406671Smckusick 			fldtab[i].sval = fr;
1416671Smckusick 			fldtab[i].tval = FLD | STR;
1426671Smckusick 			do
1436671Smckusick 				*fr++ = *r++;
1446671Smckusick 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
1456671Smckusick 			*fr++ = 0;
1466671Smckusick 		}
1476671Smckusick 	else if (*r != 0)	/* if 0, it's a null field */
1486671Smckusick 		for (;;) {
1496671Smckusick 			i++;
1506671Smckusick 			if (i >= MAXFLD)
1516671Smckusick 				error(FATAL, "record `%.20s...' has too many fields", record);
1526671Smckusick 			if (!(fldtab[i].tval&FLD))
15310794Ssam 				strfree(fldtab[i].sval);
1546671Smckusick 			fldtab[i].sval = fr;
1556671Smckusick 			fldtab[i].tval = FLD | STR;
1566671Smckusick 			while (*r != sep && *r != '\n' && *r != '\0')	/* \n always a separator */
1576671Smckusick 				*fr++ = *r++;
1586671Smckusick 			*fr++ = 0;
1596671Smckusick 			if (*r++ == 0)
1606671Smckusick 				break;
1616671Smckusick 		}
1626671Smckusick 	*fr = 0;
1636671Smckusick 	for (j=MAXFLD-1; j>i; j--) {	/* clean out junk from previous record */
1646671Smckusick 		if (!(fldtab[j].tval&FLD))
16510794Ssam 			strfree(fldtab[j].sval);
1666671Smckusick 		fldtab[j].tval = STR | FLD;
16710794Ssam 		fldtab[j].sval = EMPTY;
1686671Smckusick 	}
1696671Smckusick 	maxfld = i;
1706671Smckusick 	donefld = 1;
1716671Smckusick 	for(i=1; i<=maxfld; i++)
1726671Smckusick 		if(isnumber(fldtab[i].sval)) {
1736671Smckusick 			fldtab[i].fval = atof(fldtab[i].sval);
1746671Smckusick 			fldtab[i].tval |= NUM;
1756671Smckusick 		}
1766671Smckusick 	setfval(lookup("NF", symtab, 0), (awkfloat) maxfld);
1776671Smckusick 	if (dbg)
1786671Smckusick 		for (i = 0; i <= maxfld; i++)
1796671Smckusick 			printf("field %d: |%s|\n", i, fldtab[i].sval);
1806671Smckusick }
1816671Smckusick 
1826671Smckusick recbld()
1836671Smckusick {
1846671Smckusick 	int i;
1856671Smckusick 	register char *r, *p;
1866671Smckusick 
1876671Smckusick 	if (donefld == 0 || donerec == 1)
1886671Smckusick 		return;
1896671Smckusick 	r = record;
1906671Smckusick 	for (i = 1; i <= *NF; i++) {
1916671Smckusick 		p = getsval(&fldtab[i]);
1926671Smckusick 		while (*r++ = *p++)
1936671Smckusick 			;
1946671Smckusick 		*(r-1) = **OFS;
1956671Smckusick 	}
1966671Smckusick 	*(r-1) = '\0';
1976671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
1986671Smckusick 	recloc->tval = STR | FLD;
1996671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
2006671Smckusick 	if (r > record+RECSIZE)
2016671Smckusick 		error(FATAL, "built giant record `%.20s...'", record);
2026671Smckusick 	dprintf("recbld = |%s|\n", record, NULL, NULL);
2036671Smckusick }
2046671Smckusick 
2056671Smckusick cell *fieldadr(n)
2066671Smckusick {
2076671Smckusick 	if (n >= MAXFLD)
2086671Smckusick 		error(FATAL, "trying to access field %d", n);
2096671Smckusick 	return(&fldtab[n]);
2106671Smckusick }
2116671Smckusick 
2126671Smckusick int	errorflag	= 0;
2136671Smckusick 
2146671Smckusick yyerror(s) char *s; {
2156671Smckusick 	fprintf(stderr, "awk: %s near line %d\n", s, lineno);
2166671Smckusick 	errorflag = 2;
2176671Smckusick }
2186671Smckusick 
219*46819Sbostic error(isfatal, fmt)
220*46819Sbostic 	int isfatal;
221*46819Sbostic 	char *fmt;
222*46819Sbostic {
223*46819Sbostic 	va_list ap;
224*46819Sbostic 
225*46819Sbostic 	va_start(ap, fmt);
226*46819Sbostic 	(void)fprintf(stderr, "awk: ");
227*46819Sbostic 	(void)vfprintf(stderr, fmt, ap);
228*46819Sbostic 	va_end(ap);
229*46819Sbostic 	(void)fprintf(stderr, "\n");
23017190Sralph 	if (NR && *NR > 0)
231*46819Sbostic 		(void)fprintf(stderr, " record number %g\n", *NR);
232*46819Sbostic 	if (isfatal)
2336671Smckusick 		exit(2);
2346671Smckusick }
2356671Smckusick 
2366671Smckusick PUTS(s) char *s; {
2376671Smckusick 	dprintf("%s\n", s, NULL, NULL);
2386671Smckusick }
2396671Smckusick 
2406671Smckusick #define	MAXEXPON	38	/* maximum exponenet for fp number */
2416671Smckusick 
2426671Smckusick isnumber(s)
2436671Smckusick register char *s;
2446671Smckusick {
2456671Smckusick 	register d1, d2;
2466671Smckusick 	int point;
2476671Smckusick 	char *es;
2486671Smckusick 
24910794Ssam 	if (s == NULL)
25010794Ssam 		return (0);
2516671Smckusick 	d1 = d2 = point = 0;
2526671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
2536671Smckusick 		s++;
2546671Smckusick 	if (*s == '\0')
2556671Smckusick 		return(0);	/* empty stuff isn't number */
2566671Smckusick 	if (*s == '+' || *s == '-')
2576671Smckusick 		s++;
2586671Smckusick 	if (!isdigit(*s) && *s != '.')
2596671Smckusick 		return(0);
2606671Smckusick 	if (isdigit(*s)) {
2616671Smckusick 		do {
2626671Smckusick 			d1++;
2636671Smckusick 			s++;
2646671Smckusick 		} while (isdigit(*s));
2656671Smckusick 	}
2666671Smckusick 	if(d1 >= MAXEXPON)
2676671Smckusick 		return(0);	/* too many digits to convert */
2686671Smckusick 	if (*s == '.') {
2696671Smckusick 		point++;
2706671Smckusick 		s++;
2716671Smckusick 	}
2726671Smckusick 	if (isdigit(*s)) {
2736671Smckusick 		d2++;
2746671Smckusick 		do {
2756671Smckusick 			s++;
2766671Smckusick 		} while (isdigit(*s));
2776671Smckusick 	}
2786671Smckusick 	if (!(d1 || point && d2))
2796671Smckusick 		return(0);
2806671Smckusick 	if (*s == 'e' || *s == 'E') {
2816671Smckusick 		s++;
2826671Smckusick 		if (*s == '+' || *s == '-')
2836671Smckusick 			s++;
2846671Smckusick 		if (!isdigit(*s))
2856671Smckusick 			return(0);
2866671Smckusick 		es = s;
2876671Smckusick 		do {
2886671Smckusick 			s++;
2896671Smckusick 		} while (isdigit(*s));
2906671Smckusick 		if (s - es > 2)
2916671Smckusick 			return(0);
2926671Smckusick 		else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
2936671Smckusick 			return(0);
2946671Smckusick 	}
2956671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
2966671Smckusick 		s++;
2976671Smckusick 	if (*s == '\0')
2986671Smckusick 		return(1);
2996671Smckusick 	else
3006671Smckusick 		return(0);
3016671Smckusick }
3026671Smckusick /*
3036671Smckusick isnumber(s) char *s; {return(0);}
3046671Smckusick */
305