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