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