new copyright; att/bsd/shared
[unix-history] / usr / src / old / awk / lib.c
CommitLineData
b803c326 1#ifndef lint
2404822a 2static char sccsid[] = "@(#)lib.c 4.8 (Berkeley) %G%";
b803c326 3#endif
b9bbf539 4
2404822a 5#include <stdarg.h>
b9bbf539
KM
6#include "stdio.h"
7#include "awk.def"
8#include "awk.h"
9#include "ctype.h"
10
26758489 11extern FILE *yyin; /* lex input file */
e068ed21 12extern char *lexprog; /* points to program argument if it exists */
b9bbf539
KM
13FILE *infile = NULL;
14char *file;
15#define RECSIZE (5 * 512)
16char record[RECSIZE];
17char fields[RECSIZE];
c48090b0 18char EMPTY[] = "";
b9bbf539
KM
19
20#define MAXFLD 100
21int donefld; /* 1 = implies rec broken into fields */
22int donerec; /* 1 = record is valid (no flds have changed) */
23int mustfld; /* 1 = NF seen, so always break*/
24
c48090b0 25#define FINIT {EMPTY, EMPTY, 0.0, FLD|STR}
b9bbf539
KM
26cell fldtab[MAXFLD] = { /*room for fields */
27 { "$record", record, 0.0, STR|FLD},
83b07d63
KB
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,
b9bbf539
KM
37};
38int maxfld = 0; /* last used field */
39
40
41getrec()
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);
26758489 63 if (*file == '-') {
e068ed21 64 if (yyin == stdin && ! lexprog)
26758489
KB
65 error(FATAL, "standard input already used for reading commands");
66 else
67 infile = stdin;
68 }
b9bbf539
KM
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
107setclvar(s) /* set var=value from s */
108char *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
121fldbld()
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))
c48090b0 139 strfree(fldtab[i].sval);
b9bbf539
KM
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))
c48090b0 153 strfree(fldtab[i].sval);
b9bbf539
KM
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))
c48090b0 165 strfree(fldtab[j].sval);
b9bbf539 166 fldtab[j].tval = STR | FLD;
c48090b0 167 fldtab[j].sval = EMPTY;
b9bbf539
KM
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
182recbld()
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
205cell *fieldadr(n)
206{
207 if (n >= MAXFLD)
208 error(FATAL, "trying to access field %d", n);
209 return(&fldtab[n]);
210}
211
212int errorflag = 0;
213
214yyerror(s) char *s; {
215 fprintf(stderr, "awk: %s near line %d\n", s, lineno);
216 errorflag = 2;
217}
218
2404822a
KB
219error(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");
8820cba9 230 if (NR && *NR > 0)
2404822a
KB
231 (void)fprintf(stderr, " record number %g\n", *NR);
232 if (isfatal)
b9bbf539
KM
233 exit(2);
234}
235
236PUTS(s) char *s; {
237 dprintf("%s\n", s, NULL, NULL);
238}
239
240#define MAXEXPON 38 /* maximum exponenet for fp number */
241
242isnumber(s)
243register char *s;
244{
245 register d1, d2;
246 int point;
247 char *es;
248
c48090b0
SL
249 if (s == NULL)
250 return (0);
b9bbf539
KM
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/*
303isnumber(s) char *s; {return(0);}
304*/