xref: /csrg-svn/old/awk/lib.c (revision 31035)
1 #ifndef lint
2 static char sccsid[] = "@(#)lib.c	4.4 9/17/84";
3 #endif
4 
5 #include "stdio.h"
6 #include "awk.def"
7 #include "awk.h"
8 #include "ctype.h"
9 
10 FILE	*infile	= NULL;
11 char	*file;
12 #define	RECSIZE	(5 * 512)
13 char	record[RECSIZE];
14 char	fields[RECSIZE];
15 char	EMPTY[] = "";
16 
17 #define	MAXFLD	100
18 int	donefld;	/* 1 = implies rec broken into fields */
19 int	donerec;	/* 1 = record is valid (no flds have changed) */
20 int	mustfld;	/* 1 = NF seen, so always break*/
21 
22 #define	FINIT	{EMPTY, EMPTY, 0.0, FLD|STR}
23 cell fldtab[MAXFLD] = {	/*room for fields */
24 	{ "$record", record, 0.0, STR|FLD},
25 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
26 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
27 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
28 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
29 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
30 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
31 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
32 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
33 	FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
34 };
35 int	maxfld	= 0;	/* last used field */
36 
37 
38 getrec()
39 {
40 	register char *rr;
41 	extern int svargc;
42 	extern char **svargv;
43 	register c, sep;
44 
45 	dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
46 	donefld = 0;
47 	donerec = 1;
48 	record[0] = 0;
49 	while (svargc > 0) {
50 		dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
51 		if (infile == NULL) {	/* have to open a new file */
52 			if (member('=', *svargv)) {	/* it's a var=value argument */
53 				setclvar(*svargv);
54 				svargv++;
55 				svargc--;
56 				continue;
57 			}
58 			*FILENAME = file = *svargv;
59 			dprintf("opening file %s\n", file, NULL, NULL);
60 			if (*file == '-')
61 				infile = stdin;
62 			else if ((infile = fopen(file, "r")) == NULL)
63 				error(FATAL, "can't open %s", file);
64 		}
65 		if ((sep = **RS) == 0)
66 			sep = '\n';
67 		for (rr = record; ; ) {
68 			for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
69 				;
70 			if (**RS == sep || c == EOF)
71 				break;
72 			if ((c = getc(infile)) == '\n' || c == EOF)	/* 2 in a row */
73 				break;
74 			*rr++ = '\n';
75 			*rr++ = c;
76 		}
77 		if (rr > record+RECSIZE)
78 			error(FATAL, "record `%.20s...' too long", record);
79 		*rr = 0;
80 		if (mustfld)
81 			fldbld();
82 		if (c != EOF || rr > record) {	/* normal record */
83 			recloc->tval &= ~NUM;
84 			recloc->tval |= STR;
85 			++nrloc->fval;
86 			nrloc->tval &= ~STR;
87 			nrloc->tval |= NUM;
88 			return(1);
89 		}
90 		/* EOF arrived on this file; set up next */
91 		if (infile != stdin)
92 			fclose(infile);
93 		infile = NULL;
94 		svargc--;
95 		svargv++;
96 	}
97 	return(0);	/* true end of file */
98 }
99 
100 setclvar(s)	/* set var=value from s */
101 char *s;
102 {
103 	char *p;
104 	cell *q;
105 
106 	for (p=s; *p != '='; p++)
107 		;
108 	*p++ = 0;
109 	q = setsymtab(s, tostring(p), 0.0, STR, symtab);
110 	setsval(q, p);
111 	dprintf("command line set %s to |%s|\n", s, p, NULL);
112 }
113 
114 fldbld()
115 {
116 	register char *r, *fr, sep;
117 	int i, j;
118 
119 	r = record;
120 	fr = fields;
121 	i = 0;	/* number of fields accumulated here */
122 	if ((sep = **FS) == ' ')
123 		for (i = 0; ; ) {
124 			while (*r == ' ' || *r == '\t' || *r == '\n')
125 				r++;
126 			if (*r == 0)
127 				break;
128 			i++;
129 			if (i >= MAXFLD)
130 				error(FATAL, "record `%.20s...' has too many fields", record);
131 			if (!(fldtab[i].tval&FLD))
132 				strfree(fldtab[i].sval);
133 			fldtab[i].sval = fr;
134 			fldtab[i].tval = FLD | STR;
135 			do
136 				*fr++ = *r++;
137 			while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
138 			*fr++ = 0;
139 		}
140 	else if (*r != 0)	/* if 0, it's a null field */
141 		for (;;) {
142 			i++;
143 			if (i >= MAXFLD)
144 				error(FATAL, "record `%.20s...' has too many fields", record);
145 			if (!(fldtab[i].tval&FLD))
146 				strfree(fldtab[i].sval);
147 			fldtab[i].sval = fr;
148 			fldtab[i].tval = FLD | STR;
149 			while (*r != sep && *r != '\n' && *r != '\0')	/* \n always a separator */
150 				*fr++ = *r++;
151 			*fr++ = 0;
152 			if (*r++ == 0)
153 				break;
154 		}
155 	*fr = 0;
156 	for (j=MAXFLD-1; j>i; j--) {	/* clean out junk from previous record */
157 		if (!(fldtab[j].tval&FLD))
158 			strfree(fldtab[j].sval);
159 		fldtab[j].tval = STR | FLD;
160 		fldtab[j].sval = EMPTY;
161 	}
162 	maxfld = i;
163 	donefld = 1;
164 	for(i=1; i<=maxfld; i++)
165 		if(isnumber(fldtab[i].sval)) {
166 			fldtab[i].fval = atof(fldtab[i].sval);
167 			fldtab[i].tval |= NUM;
168 		}
169 	setfval(lookup("NF", symtab, 0), (awkfloat) maxfld);
170 	if (dbg)
171 		for (i = 0; i <= maxfld; i++)
172 			printf("field %d: |%s|\n", i, fldtab[i].sval);
173 }
174 
175 recbld()
176 {
177 	int i;
178 	register char *r, *p;
179 
180 	if (donefld == 0 || donerec == 1)
181 		return;
182 	r = record;
183 	for (i = 1; i <= *NF; i++) {
184 		p = getsval(&fldtab[i]);
185 		while (*r++ = *p++)
186 			;
187 		*(r-1) = **OFS;
188 	}
189 	*(r-1) = '\0';
190 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
191 	recloc->tval = STR | FLD;
192 	dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
193 	if (r > record+RECSIZE)
194 		error(FATAL, "built giant record `%.20s...'", record);
195 	dprintf("recbld = |%s|\n", record, NULL, NULL);
196 }
197 
198 cell *fieldadr(n)
199 {
200 	if (n >= MAXFLD)
201 		error(FATAL, "trying to access field %d", n);
202 	return(&fldtab[n]);
203 }
204 
205 int	errorflag	= 0;
206 
207 yyerror(s) char *s; {
208 	fprintf(stderr, "awk: %s near line %d\n", s, lineno);
209 	errorflag = 2;
210 }
211 
212 error(f, s, a1, a2, a3, a4, a5, a6, a7) {
213 	fprintf(stderr, "awk: ");
214 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
215 	fprintf(stderr, "\n");
216 	if (NR && *NR > 0)
217 		fprintf(stderr, " record number %g\n", *NR);
218 	if (f)
219 		exit(2);
220 }
221 
222 PUTS(s) char *s; {
223 	dprintf("%s\n", s, NULL, NULL);
224 }
225 
226 #define	MAXEXPON	38	/* maximum exponenet for fp number */
227 
228 isnumber(s)
229 register char *s;
230 {
231 	register d1, d2;
232 	int point;
233 	char *es;
234 
235 	if (s == NULL)
236 		return (0);
237 	d1 = d2 = point = 0;
238 	while (*s == ' ' || *s == '\t' || *s == '\n')
239 		s++;
240 	if (*s == '\0')
241 		return(0);	/* empty stuff isn't number */
242 	if (*s == '+' || *s == '-')
243 		s++;
244 	if (!isdigit(*s) && *s != '.')
245 		return(0);
246 	if (isdigit(*s)) {
247 		do {
248 			d1++;
249 			s++;
250 		} while (isdigit(*s));
251 	}
252 	if(d1 >= MAXEXPON)
253 		return(0);	/* too many digits to convert */
254 	if (*s == '.') {
255 		point++;
256 		s++;
257 	}
258 	if (isdigit(*s)) {
259 		d2++;
260 		do {
261 			s++;
262 		} while (isdigit(*s));
263 	}
264 	if (!(d1 || point && d2))
265 		return(0);
266 	if (*s == 'e' || *s == 'E') {
267 		s++;
268 		if (*s == '+' || *s == '-')
269 			s++;
270 		if (!isdigit(*s))
271 			return(0);
272 		es = s;
273 		do {
274 			s++;
275 		} while (isdigit(*s));
276 		if (s - es > 2)
277 			return(0);
278 		else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
279 			return(0);
280 	}
281 	while (*s == ' ' || *s == '\t' || *s == '\n')
282 		s++;
283 	if (*s == '\0')
284 		return(1);
285 	else
286 		return(0);
287 }
288 /*
289 isnumber(s) char *s; {return(0);}
290 */
291