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