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