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