4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / old / awk / lib.c
CommitLineData
2791ff57
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
b803c326 8#ifndef lint
89616477 9static char sccsid[] = "@(#)lib.c 4.11 (Berkeley) %G%";
2791ff57 10#endif /* not lint */
b9bbf539 11
66d1b859 12#ifdef __STDC__
2404822a 13#include <stdarg.h>
66d1b859
CT
14#else
15#include <varargs.h>
16#endif
b9bbf539
KM
17#include "stdio.h"
18#include "awk.def"
19#include "awk.h"
20#include "ctype.h"
21
66d1b859
CT
22int error __P((int, const char *, ...));
23
26758489 24extern FILE *yyin; /* lex input file */
e068ed21 25extern char *lexprog; /* points to program argument if it exists */
b9bbf539
KM
26FILE *infile = NULL;
27char *file;
28#define RECSIZE (5 * 512)
29char record[RECSIZE];
30char fields[RECSIZE];
c48090b0 31char EMPTY[] = "";
b9bbf539
KM
32
33#define MAXFLD 100
34int donefld; /* 1 = implies rec broken into fields */
35int donerec; /* 1 = record is valid (no flds have changed) */
36int mustfld; /* 1 = NF seen, so always break*/
37
c48090b0 38#define FINIT {EMPTY, EMPTY, 0.0, FLD|STR}
b9bbf539
KM
39cell fldtab[MAXFLD] = { /*room for fields */
40 { "$record", record, 0.0, STR|FLD},
83b07d63
KB
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,
b9bbf539
KM
50};
51int maxfld = 0; /* last used field */
52
53
54getrec()
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);
26758489 76 if (*file == '-') {
e068ed21 77 if (yyin == stdin && ! lexprog)
26758489
KB
78 error(FATAL, "standard input already used for reading commands");
79 else
80 infile = stdin;
81 }
b9bbf539
KM
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
120setclvar(s) /* set var=value from s */
121char *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
134fldbld()
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))
c48090b0 152 strfree(fldtab[i].sval);
b9bbf539
KM
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))
c48090b0 166 strfree(fldtab[i].sval);
b9bbf539
KM
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))
c48090b0 178 strfree(fldtab[j].sval);
b9bbf539 179 fldtab[j].tval = STR | FLD;
c48090b0 180 fldtab[j].sval = EMPTY;
b9bbf539
KM
181 }
182 maxfld = i;
183 donefld = 1;
184 for(i=1; i<=maxfld; i++)
89616477 185 if(isanumber(fldtab[i].sval)) {
b9bbf539
KM
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
195recbld()
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
218cell *fieldadr(n)
219{
220 if (n >= MAXFLD)
221 error(FATAL, "trying to access field %d", n);
222 return(&fldtab[n]);
223}
224
225int errorflag = 0;
226
227yyerror(s) char *s; {
228 fprintf(stderr, "awk: %s near line %d\n", s, lineno);
229 errorflag = 2;
230}
231
66d1b859
CT
232int
233#ifdef __STDC__
234error(int isfatal, const char *fmt, ...)
235#else
236error(isfatal, fmt, va_alist)
2404822a
KB
237 int isfatal;
238 char *fmt;
66d1b859
CT
239 va_dcl
240#endif
2404822a
KB
241{
242 va_list ap;
243
66d1b859 244#ifdef __STDC__
2404822a 245 va_start(ap, fmt);
66d1b859
CT
246#else
247 va_start(ap);
248#endif
2404822a
KB
249 (void)fprintf(stderr, "awk: ");
250 (void)vfprintf(stderr, fmt, ap);
251 va_end(ap);
252 (void)fprintf(stderr, "\n");
8820cba9 253 if (NR && *NR > 0)
2404822a
KB
254 (void)fprintf(stderr, " record number %g\n", *NR);
255 if (isfatal)
b9bbf539
KM
256 exit(2);
257}
258
259PUTS(s) char *s; {
260 dprintf("%s\n", s, NULL, NULL);
261}
262
263#define MAXEXPON 38 /* maximum exponenet for fp number */
264
89616477 265isanumber(s)
b9bbf539
KM
266register char *s;
267{
268 register d1, d2;
269 int point;
270 char *es;
271
c48090b0
SL
272 if (s == NULL)
273 return (0);
b9bbf539
KM
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/*
89616477 326isanumber(s) char *s; {return(0);}
b9bbf539 327*/