xref: /csrg-svn/old/awk/lib.c (revision 44021)
114473Ssam #ifndef lint
2*44021Sbostic static char sccsid[] = "@(#)lib.c	4.7 (Berkeley) 06/25/90";
314473Ssam #endif
46671Smckusick 
56671Smckusick #include "stdio.h"
66671Smckusick #include "awk.def"
76671Smckusick #include "awk.h"
86671Smckusick #include "ctype.h"
96671Smckusick 
1032354Sbostic extern FILE	*yyin;	/* lex input file */
11*44021Sbostic extern char	*lexprog;	/* points to program argument if it exists */
126671Smckusick FILE	*infile	= NULL;
136671Smckusick char	*file;
146671Smckusick #define	RECSIZE	(5 * 512)
156671Smckusick char	record[RECSIZE];
166671Smckusick char	fields[RECSIZE];
1710794Ssam char	EMPTY[] = "";
186671Smckusick 
196671Smckusick #define	MAXFLD	100
206671Smckusick int	donefld;	/* 1 = implies rec broken into fields */
216671Smckusick int	donerec;	/* 1 = record is valid (no flds have changed) */
226671Smckusick int	mustfld;	/* 1 = NF seen, so always break*/
236671Smckusick 
2410794Ssam #define	FINIT	{EMPTY, EMPTY, 0.0, FLD|STR}
256671Smckusick cell fldtab[MAXFLD] = {	/*room for fields */
266671Smckusick 	{ "$record", record, 0.0, STR|FLD},
2731035Sbostic 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
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,
366671Smckusick };
376671Smckusick int	maxfld	= 0;	/* last used field */
386671Smckusick 
396671Smckusick 
406671Smckusick getrec()
416671Smckusick {
426671Smckusick 	register char *rr;
436671Smckusick 	extern int svargc;
446671Smckusick 	extern char **svargv;
456671Smckusick 	register c, sep;
466671Smckusick 
476671Smckusick 	dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
486671Smckusick 	donefld = 0;
496671Smckusick 	donerec = 1;
506671Smckusick 	record[0] = 0;
516671Smckusick 	while (svargc > 0) {
526671Smckusick 		dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
536671Smckusick 		if (infile == NULL) {	/* have to open a new file */
546671Smckusick 			if (member('=', *svargv)) {	/* it's a var=value argument */
556671Smckusick 				setclvar(*svargv);
566671Smckusick 				svargv++;
576671Smckusick 				svargc--;
586671Smckusick 				continue;
596671Smckusick 			}
606671Smckusick 			*FILENAME = file = *svargv;
616671Smckusick 			dprintf("opening file %s\n", file, NULL, NULL);
6232354Sbostic 			if (*file == '-') {
63*44021Sbostic 				if (yyin == stdin && ! lexprog)
6432354Sbostic 					error(FATAL, "standard input already used for reading commands");
6532354Sbostic 				else
6632354Sbostic 					infile = stdin;
6732354Sbostic 			}
686671Smckusick 			else if ((infile = fopen(file, "r")) == NULL)
696671Smckusick 				error(FATAL, "can't open %s", file);
706671Smckusick 		}
716671Smckusick 		if ((sep = **RS) == 0)
726671Smckusick 			sep = '\n';
736671Smckusick 		for (rr = record; ; ) {
746671Smckusick 			for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
756671Smckusick 				;
766671Smckusick 			if (**RS == sep || c == EOF)
776671Smckusick 				break;
786671Smckusick 			if ((c = getc(infile)) == '\n' || c == EOF)	/* 2 in a row */
796671Smckusick 				break;
806671Smckusick 			*rr++ = '\n';
816671Smckusick 			*rr++ = c;
826671Smckusick 		}
836671Smckusick 		if (rr > record+RECSIZE)
846671Smckusick 			error(FATAL, "record `%.20s...' too long", record);
856671Smckusick 		*rr = 0;
866671Smckusick 		if (mustfld)
876671Smckusick 			fldbld();
886671Smckusick 		if (c != EOF || rr > record) {	/* normal record */
896671Smckusick 			recloc->tval &= ~NUM;
906671Smckusick 			recloc->tval |= STR;
916671Smckusick 			++nrloc->fval;
926671Smckusick 			nrloc->tval &= ~STR;
936671Smckusick 			nrloc->tval |= NUM;
946671Smckusick 			return(1);
956671Smckusick 		}
966671Smckusick 		/* EOF arrived on this file; set up next */
976671Smckusick 		if (infile != stdin)
986671Smckusick 			fclose(infile);
996671Smckusick 		infile = NULL;
1006671Smckusick 		svargc--;
1016671Smckusick 		svargv++;
1026671Smckusick 	}
1036671Smckusick 	return(0);	/* true end of file */
1046671Smckusick }
1056671Smckusick 
1066671Smckusick setclvar(s)	/* set var=value from s */
1076671Smckusick char *s;
1086671Smckusick {
1096671Smckusick 	char *p;
1106671Smckusick 	cell *q;
1116671Smckusick 
1126671Smckusick 	for (p=s; *p != '='; p++)
1136671Smckusick 		;
1146671Smckusick 	*p++ = 0;
1156671Smckusick 	q = setsymtab(s, tostring(p), 0.0, STR, symtab);
1166671Smckusick 	setsval(q, p);
1176671Smckusick 	dprintf("command line set %s to |%s|\n", s, p, NULL);
1186671Smckusick }
1196671Smckusick 
1206671Smckusick fldbld()
1216671Smckusick {
1226671Smckusick 	register char *r, *fr, sep;
1236671Smckusick 	int i, j;
1246671Smckusick 
1256671Smckusick 	r = record;
1266671Smckusick 	fr = fields;
1276671Smckusick 	i = 0;	/* number of fields accumulated here */
1286671Smckusick 	if ((sep = **FS) == ' ')
1296671Smckusick 		for (i = 0; ; ) {
1306671Smckusick 			while (*r == ' ' || *r == '\t' || *r == '\n')
1316671Smckusick 				r++;
1326671Smckusick 			if (*r == 0)
1336671Smckusick 				break;
1346671Smckusick 			i++;
1356671Smckusick 			if (i >= MAXFLD)
1366671Smckusick 				error(FATAL, "record `%.20s...' has too many fields", record);
1376671Smckusick 			if (!(fldtab[i].tval&FLD))
13810794Ssam 				strfree(fldtab[i].sval);
1396671Smckusick 			fldtab[i].sval = fr;
1406671Smckusick 			fldtab[i].tval = FLD | STR;
1416671Smckusick 			do
1426671Smckusick 				*fr++ = *r++;
1436671Smckusick 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
1446671Smckusick 			*fr++ = 0;
1456671Smckusick 		}
1466671Smckusick 	else if (*r != 0)	/* if 0, it's a null field */
1476671Smckusick 		for (;;) {
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 			while (*r != sep && *r != '\n' && *r != '\0')	/* \n always a separator */
1566671Smckusick 				*fr++ = *r++;
1576671Smckusick 			*fr++ = 0;
1586671Smckusick 			if (*r++ == 0)
1596671Smckusick 				break;
1606671Smckusick 		}
1616671Smckusick 	*fr = 0;
1626671Smckusick 	for (j=MAXFLD-1; j>i; j--) {	/* clean out junk from previous record */
1636671Smckusick 		if (!(fldtab[j].tval&FLD))
16410794Ssam 			strfree(fldtab[j].sval);
1656671Smckusick 		fldtab[j].tval = STR | FLD;
16610794Ssam 		fldtab[j].sval = EMPTY;
1676671Smckusick 	}
1686671Smckusick 	maxfld = i;
1696671Smckusick 	donefld = 1;
1706671Smckusick 	for(i=1; i<=maxfld; i++)
1716671Smckusick 		if(isnumber(fldtab[i].sval)) {
1726671Smckusick 			fldtab[i].fval = atof(fldtab[i].sval);
1736671Smckusick 			fldtab[i].tval |= NUM;
1746671Smckusick 		}
1756671Smckusick 	setfval(lookup("NF", symtab, 0), (awkfloat) maxfld);
1766671Smckusick 	if (dbg)
1776671Smckusick 		for (i = 0; i <= maxfld; i++)
1786671Smckusick 			printf("field %d: |%s|\n", i, fldtab[i].sval);
1796671Smckusick }
1806671Smckusick 
1816671Smckusick recbld()
1826671Smckusick {
1836671Smckusick 	int i;
1846671Smckusick 	register char *r, *p;
1856671Smckusick 
1866671Smckusick 	if (donefld == 0 || donerec == 1)
1876671Smckusick 		return;
1886671Smckusick 	r = record;
1896671Smckusick 	for (i = 1; i <= *NF; i++) {
1906671Smckusick 		p = getsval(&fldtab[i]);
1916671Smckusick 		while (*r++ = *p++)
1926671Smckusick 			;
1936671Smckusick 		*(r-1) = **OFS;
1946671Smckusick 	}
1956671Smckusick 	*(r-1) = '\0';
1966671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
1976671Smckusick 	recloc->tval = STR | FLD;
1986671Smckusick 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
1996671Smckusick 	if (r > record+RECSIZE)
2006671Smckusick 		error(FATAL, "built giant record `%.20s...'", record);
2016671Smckusick 	dprintf("recbld = |%s|\n", record, NULL, NULL);
2026671Smckusick }
2036671Smckusick 
2046671Smckusick cell *fieldadr(n)
2056671Smckusick {
2066671Smckusick 	if (n >= MAXFLD)
2076671Smckusick 		error(FATAL, "trying to access field %d", n);
2086671Smckusick 	return(&fldtab[n]);
2096671Smckusick }
2106671Smckusick 
2116671Smckusick int	errorflag	= 0;
2126671Smckusick 
2136671Smckusick yyerror(s) char *s; {
2146671Smckusick 	fprintf(stderr, "awk: %s near line %d\n", s, lineno);
2156671Smckusick 	errorflag = 2;
2166671Smckusick }
2176671Smckusick 
2186671Smckusick error(f, s, a1, a2, a3, a4, a5, a6, a7) {
2196671Smckusick 	fprintf(stderr, "awk: ");
2206671Smckusick 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
2216671Smckusick 	fprintf(stderr, "\n");
22217190Sralph 	if (NR && *NR > 0)
2236671Smckusick 		fprintf(stderr, " record number %g\n", *NR);
2246671Smckusick 	if (f)
2256671Smckusick 		exit(2);
2266671Smckusick }
2276671Smckusick 
2286671Smckusick PUTS(s) char *s; {
2296671Smckusick 	dprintf("%s\n", s, NULL, NULL);
2306671Smckusick }
2316671Smckusick 
2326671Smckusick #define	MAXEXPON	38	/* maximum exponenet for fp number */
2336671Smckusick 
2346671Smckusick isnumber(s)
2356671Smckusick register char *s;
2366671Smckusick {
2376671Smckusick 	register d1, d2;
2386671Smckusick 	int point;
2396671Smckusick 	char *es;
2406671Smckusick 
24110794Ssam 	if (s == NULL)
24210794Ssam 		return (0);
2436671Smckusick 	d1 = d2 = point = 0;
2446671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
2456671Smckusick 		s++;
2466671Smckusick 	if (*s == '\0')
2476671Smckusick 		return(0);	/* empty stuff isn't number */
2486671Smckusick 	if (*s == '+' || *s == '-')
2496671Smckusick 		s++;
2506671Smckusick 	if (!isdigit(*s) && *s != '.')
2516671Smckusick 		return(0);
2526671Smckusick 	if (isdigit(*s)) {
2536671Smckusick 		do {
2546671Smckusick 			d1++;
2556671Smckusick 			s++;
2566671Smckusick 		} while (isdigit(*s));
2576671Smckusick 	}
2586671Smckusick 	if(d1 >= MAXEXPON)
2596671Smckusick 		return(0);	/* too many digits to convert */
2606671Smckusick 	if (*s == '.') {
2616671Smckusick 		point++;
2626671Smckusick 		s++;
2636671Smckusick 	}
2646671Smckusick 	if (isdigit(*s)) {
2656671Smckusick 		d2++;
2666671Smckusick 		do {
2676671Smckusick 			s++;
2686671Smckusick 		} while (isdigit(*s));
2696671Smckusick 	}
2706671Smckusick 	if (!(d1 || point && d2))
2716671Smckusick 		return(0);
2726671Smckusick 	if (*s == 'e' || *s == 'E') {
2736671Smckusick 		s++;
2746671Smckusick 		if (*s == '+' || *s == '-')
2756671Smckusick 			s++;
2766671Smckusick 		if (!isdigit(*s))
2776671Smckusick 			return(0);
2786671Smckusick 		es = s;
2796671Smckusick 		do {
2806671Smckusick 			s++;
2816671Smckusick 		} while (isdigit(*s));
2826671Smckusick 		if (s - es > 2)
2836671Smckusick 			return(0);
2846671Smckusick 		else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
2856671Smckusick 			return(0);
2866671Smckusick 	}
2876671Smckusick 	while (*s == ' ' || *s == '\t' || *s == '\n')
2886671Smckusick 		s++;
2896671Smckusick 	if (*s == '\0')
2906671Smckusick 		return(1);
2916671Smckusick 	else
2926671Smckusick 		return(0);
2936671Smckusick }
2946671Smckusick /*
2956671Smckusick isnumber(s) char *s; {return(0);}
2966671Smckusick */
297