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