GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: lib.c,v 1.24 2017/10/09 14:51:31 deraadt Exp $ */ |
||
2 |
/**************************************************************** |
||
3 |
Copyright (C) Lucent Technologies 1997 |
||
4 |
All Rights Reserved |
||
5 |
|||
6 |
Permission to use, copy, modify, and distribute this software and |
||
7 |
its documentation for any purpose and without fee is hereby |
||
8 |
granted, provided that the above copyright notice appear in all |
||
9 |
copies and that both that the copyright notice and this |
||
10 |
permission notice and warranty disclaimer appear in supporting |
||
11 |
documentation, and that the name Lucent Technologies or any of |
||
12 |
its entities not be used in advertising or publicity pertaining |
||
13 |
to distribution of the software without specific, written prior |
||
14 |
permission. |
||
15 |
|||
16 |
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
||
17 |
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. |
||
18 |
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY |
||
19 |
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
20 |
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER |
||
21 |
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
||
22 |
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF |
||
23 |
THIS SOFTWARE. |
||
24 |
****************************************************************/ |
||
25 |
|||
26 |
#define DEBUG |
||
27 |
#include <stdio.h> |
||
28 |
#include <string.h> |
||
29 |
#include <ctype.h> |
||
30 |
#include <errno.h> |
||
31 |
#include <stdlib.h> |
||
32 |
#include <unistd.h> |
||
33 |
#include <stdarg.h> |
||
34 |
#include "awk.h" |
||
35 |
#include "ytab.h" |
||
36 |
|||
37 |
FILE *infile = NULL; |
||
38 |
char *file = ""; |
||
39 |
char *record; |
||
40 |
int recsize = RECSIZE; |
||
41 |
char *fields; |
||
42 |
int fieldssize = RECSIZE; |
||
43 |
|||
44 |
Cell **fldtab; /* pointers to Cells */ |
||
45 |
char inputFS[100] = " "; |
||
46 |
|||
47 |
#define MAXFLD 2 |
||
48 |
int nfields = MAXFLD; /* last allocated slot for $i */ |
||
49 |
|||
50 |
int donefld; /* 1 = implies rec broken into fields */ |
||
51 |
int donerec; /* 1 = record is valid (no flds have changed) */ |
||
52 |
|||
53 |
int lastfld = 0; /* last used field */ |
||
54 |
int argno = 1; /* current input argument number */ |
||
55 |
extern Awkfloat *ARGC; |
||
56 |
|||
57 |
static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; |
||
58 |
static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; |
||
59 |
|||
60 |
void recinit(unsigned int n) |
||
61 |
{ |
||
62 |
✗✓ | 1461 |
if ( (record = (char *) malloc(n)) == NULL |
63 |
✓✗ | 974 |
|| (fields = (char *) malloc(n+1)) == NULL |
64 |
✓✗ | 974 |
|| (fldtab = (Cell **) calloc(nfields+1, sizeof(Cell *))) == NULL |
65 |
✓✗ | 974 |
|| (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL ) |
66 |
FATAL("out of space for $0 and fields"); |
||
67 |
487 |
*record = '\0'; |
|
68 |
487 |
*fldtab[0] = dollar0; |
|
69 |
487 |
fldtab[0]->sval = record; |
|
70 |
487 |
fldtab[0]->nval = tostring("0"); |
|
71 |
487 |
makefields(1, nfields); |
|
72 |
487 |
} |
|
73 |
|||
74 |
void makefields(int n1, int n2) /* create $n1..$n2 inclusive */ |
||
75 |
{ |
||
76 |
1618 |
char temp[50]; |
|
77 |
int i; |
||
78 |
|||
79 |
✓✓ | 6474 |
for (i = n1; i <= n2; i++) { |
80 |
2428 |
fldtab[i] = (Cell *) malloc(sizeof (struct Cell)); |
|
81 |
✗✓ | 2428 |
if (fldtab[i] == NULL) |
82 |
FATAL("out of space in makefields %d", i); |
||
83 |
2428 |
*fldtab[i] = dollar1; |
|
84 |
2428 |
snprintf(temp, sizeof temp, "%d", i); |
|
85 |
2428 |
fldtab[i]->nval = tostring(temp); |
|
86 |
} |
||
87 |
809 |
} |
|
88 |
|||
89 |
void initgetrec(void) |
||
90 |
{ |
||
91 |
int i; |
||
92 |
char *p; |
||
93 |
|||
94 |
✓✓ | 1352 |
for (i = 1; i < *ARGC; i++) { |
95 |
88 |
p = getargv(i); /* find 1st real filename */ |
|
96 |
✓✗✓✗ |
176 |
if (p == NULL || *p == '\0') { /* deleted or zapped */ |
97 |
argno++; |
||
98 |
continue; |
||
99 |
} |
||
100 |
✓✓ | 88 |
if (!isclvar(p)) { |
101 |
72 |
setsval(lookup("FILENAME", symtab), p); |
|
102 |
72 |
return; |
|
103 |
} |
||
104 |
16 |
setclvar(p); /* a commandline assignment before filename */ |
|
105 |
argno++; |
||
106 |
16 |
} |
|
107 |
368 |
infile = stdin; /* no filenames, so use stdin */ |
|
108 |
808 |
} |
|
109 |
|||
110 |
static int firsttime = 1; |
||
111 |
|||
112 |
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ |
||
113 |
{ /* note: cares whether buf == record */ |
||
114 |
int c; |
||
115 |
1197718 |
char *buf = *pbuf; |
|
116 |
uschar saveb0; |
||
117 |
598859 |
int bufsize = *pbufsize, savebufsize = bufsize; |
|
118 |
|||
119 |
✓✓ | 598859 |
if (firsttime) { |
120 |
440 |
firsttime = 0; |
|
121 |
440 |
initgetrec(); |
|
122 |
440 |
} |
|
123 |
✗✓ | 598859 |
DPRINTF( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", |
124 |
*RS, *FS, *ARGC, *FILENAME) ); |
||
125 |
✓✗ | 598859 |
if (isrecord) { |
126 |
598859 |
donefld = 0; |
|
127 |
598859 |
donerec = 1; |
|
128 |
598859 |
} |
|
129 |
598859 |
saveb0 = buf[0]; |
|
130 |
598859 |
buf[0] = 0; |
|
131 |
✓✓ | 1198494 |
while (argno < *ARGC || infile == stdin) { |
132 |
✗✓ | 598859 |
DPRINTF( ("argno=%d, file=|%s|\n", argno, file) ); |
133 |
✓✓ | 598859 |
if (infile == NULL) { /* have to open a new file */ |
134 |
72 |
file = getargv(argno); |
|
135 |
✓✗✗✓ |
144 |
if (file == NULL || *file == '\0') { /* deleted or zapped */ |
136 |
argno++; |
||
137 |
continue; |
||
138 |
} |
||
139 |
✗✓ | 72 |
if (isclvar(file)) { /* a var=value arg */ |
140 |
setclvar(file); |
||
141 |
argno++; |
||
142 |
continue; |
||
143 |
} |
||
144 |
72 |
*FILENAME = file; |
|
145 |
✗✓ | 72 |
DPRINTF( ("opening file %s\n", file) ); |
146 |
✗✓✗✗ |
72 |
if (*file == '-' && *(file+1) == '\0') |
147 |
infile = stdin; |
||
148 |
✗✓ | 72 |
else if ((infile = fopen(file, "r")) == NULL) |
149 |
FATAL("can't open file %s", file); |
||
150 |
72 |
setfval(fnrloc, 0.0); |
|
151 |
72 |
} |
|
152 |
598859 |
c = readrec(&buf, &bufsize, infile); |
|
153 |
✓✓✗✓ |
599247 |
if (c != 0 || buf[0] != '\0') { /* normal record */ |
154 |
✓✗ | 598471 |
if (isrecord) { |
155 |
✗✓ | 598471 |
if (freeable(fldtab[0])) |
156 |
xfree(fldtab[0]->sval); |
||
157 |
598471 |
fldtab[0]->sval = buf; /* buf == record */ |
|
158 |
598471 |
fldtab[0]->tval = REC | STR | DONTFREE; |
|
159 |
✓✓ | 598471 |
if (is_number(fldtab[0]->sval)) { |
160 |
481583 |
fldtab[0]->fval = atof(fldtab[0]->sval); |
|
161 |
481583 |
fldtab[0]->tval |= NUM; |
|
162 |
481583 |
} |
|
163 |
} |
||
164 |
598471 |
setfval(nrloc, nrloc->fval+1); |
|
165 |
598471 |
setfval(fnrloc, fnrloc->fval+1); |
|
166 |
598471 |
*pbuf = buf; |
|
167 |
598471 |
*pbufsize = bufsize; |
|
168 |
598471 |
return 1; |
|
169 |
} |
||
170 |
/* EOF arrived on this file; set up next */ |
||
171 |
✓✓ | 388 |
if (infile != stdin) |
172 |
72 |
fclose(infile); |
|
173 |
388 |
infile = NULL; |
|
174 |
388 |
argno++; |
|
175 |
} |
||
176 |
388 |
buf[0] = saveb0; |
|
177 |
388 |
*pbuf = buf; |
|
178 |
388 |
*pbufsize = savebufsize; |
|
179 |
388 |
return 0; /* true end of file */ |
|
180 |
598859 |
} |
|
181 |
|||
182 |
void nextfile(void) |
||
183 |
{ |
||
184 |
if (infile != NULL && infile != stdin) |
||
185 |
fclose(infile); |
||
186 |
infile = NULL; |
||
187 |
argno++; |
||
188 |
} |
||
189 |
|||
190 |
int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */ |
||
191 |
{ |
||
192 |
int sep, c; |
||
193 |
1197718 |
char *rr, *buf = *pbuf; |
|
194 |
598859 |
int bufsize = *pbufsize; |
|
195 |
|||
196 |
✗✓ | 598859 |
if (strlen(*FS) >= sizeof(inputFS)) |
197 |
FATAL("field separator %.10s... is too long", *FS); |
||
198 |
/*fflush(stdout); avoids some buffering problem but makes it 25% slower*/ |
||
199 |
598859 |
strlcpy(inputFS, *FS, sizeof inputFS); /* for subsequent field splitting */ |
|
200 |
✗✓ | 598859 |
if ((sep = **RS) == 0) { |
201 |
sep = '\n'; |
||
202 |
while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */ |
||
203 |
; |
||
204 |
if (c != EOF) |
||
205 |
ungetc(c, inf); |
||
206 |
} |
||
207 |
598859 |
for (rr = buf; ; ) { |
|
208 |
✓✗✓✓ ✓✓ |
33922880 |
for (; (c=getc(inf)) != sep && c != EOF; ) { |
209 |
✗✓ | 6185717 |
if (rr-buf+1 > bufsize) |
210 |
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1")) |
||
211 |
FATAL("input record `%.30s...' too long", buf); |
||
212 |
6185717 |
*rr++ = c; |
|
213 |
} |
||
214 |
✗✓ | 598859 |
if (**RS == sep || c == EOF) |
215 |
break; |
||
216 |
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ |
||
217 |
break; |
||
218 |
if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2")) |
||
219 |
FATAL("input record `%.30s...' too long", buf); |
||
220 |
*rr++ = '\n'; |
||
221 |
*rr++ = c; |
||
222 |
} |
||
223 |
✗✓ | 598859 |
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3")) |
224 |
FATAL("input record `%.30s...' too long", buf); |
||
225 |
598859 |
*rr = 0; |
|
226 |
✗✓✗✗ |
598859 |
DPRINTF( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); |
227 |
598859 |
*pbuf = buf; |
|
228 |
598859 |
*pbufsize = bufsize; |
|
229 |
✓✓ | 1796965 |
return c == EOF && rr == buf ? 0 : 1; |
230 |
598859 |
} |
|
231 |
|||
232 |
char *getargv(int n) /* get ARGV[n] */ |
||
233 |
{ |
||
234 |
Cell *x; |
||
235 |
320 |
char *s, temp[50]; |
|
236 |
extern Array *ARGVtab; |
||
237 |
|||
238 |
160 |
snprintf(temp, sizeof temp, "%d", n); |
|
239 |
✗✓ | 160 |
if (lookup(temp, ARGVtab) == NULL) |
240 |
return NULL; |
||
241 |
160 |
x = setsymtab(temp, "", 0.0, STR, ARGVtab); |
|
242 |
160 |
s = getsval(x); |
|
243 |
✗✓ | 160 |
DPRINTF( ("getargv(%d) returns |%s|\n", n, s) ); |
244 |
160 |
return s; |
|
245 |
160 |
} |
|
246 |
|||
247 |
void setclvar(char *s) /* set var=value from s */ |
||
248 |
{ |
||
249 |
char *p; |
||
250 |
Cell *q; |
||
251 |
|||
252 |
✓✓ | 340 |
for (p=s; *p != '='; p++) |
253 |
; |
||
254 |
16 |
*p++ = 0; |
|
255 |
16 |
p = qstring(p, '\0'); |
|
256 |
16 |
q = setsymtab(s, p, 0.0, STR, symtab); |
|
257 |
16 |
setsval(q, p); |
|
258 |
✓✓ | 16 |
if (is_number(q->sval)) { |
259 |
10 |
q->fval = atof(q->sval); |
|
260 |
10 |
q->tval |= NUM; |
|
261 |
10 |
} |
|
262 |
✗✓ | 16 |
DPRINTF( ("command line set %s to |%s|\n", s, p) ); |
263 |
16 |
} |
|
264 |
|||
265 |
|||
266 |
void fldbld(void) /* create fields from current record */ |
||
267 |
{ |
||
268 |
/* this relies on having fields[] the same length as $0 */ |
||
269 |
/* the fields are all stored in this one array with \0's */ |
||
270 |
/* possibly with a final trailing \0 not associated with any field */ |
||
271 |
char *r, *fr, sep; |
||
272 |
Cell *p; |
||
273 |
int i, j, n; |
||
274 |
|||
275 |
✗✓ | 42530 |
if (donefld) |
276 |
return; |
||
277 |
✗✓ | 21265 |
if (!isstr(fldtab[0])) |
278 |
getsval(fldtab[0]); |
||
279 |
21265 |
r = fldtab[0]->sval; |
|
280 |
21265 |
n = strlen(r); |
|
281 |
✗✓ | 21265 |
if (n > fieldssize) { |
282 |
xfree(fields); |
||
283 |
if ((fields = (char *) malloc(n+2)) == NULL) /* possibly 2 final \0s */ |
||
284 |
FATAL("out of space for fields in fldbld %d", n); |
||
285 |
fieldssize = n; |
||
286 |
} |
||
287 |
21265 |
fr = fields; |
|
288 |
i = 0; /* number of fields accumulated here */ |
||
289 |
21265 |
strlcpy(inputFS, *FS, sizeof(inputFS)); |
|
290 |
✗✓ | 21265 |
if (strlen(inputFS) > 1) { /* it's a regular expression */ |
291 |
i = refldbld(r, inputFS); |
||
292 |
✓✓ | 21265 |
} else if ((sep = *inputFS) == ' ') { /* default whitespace */ |
293 |
133035 |
for (i = 0; ; ) { |
|
294 |
✓✓✓✓ ✓✓ |
1047415 |
while (*r == ' ' || *r == '\t' || *r == '\n') |
295 |
109271 |
r++; |
|
296 |
✓✓ | 133035 |
if (*r == 0) |
297 |
break; |
||
298 |
111946 |
i++; |
|
299 |
✓✓ | 111946 |
if (i > nfields) |
300 |
272 |
growfldtab(i); |
|
301 |
✗✓ | 111946 |
if (freeable(fldtab[i])) |
302 |
xfree(fldtab[i]->sval); |
||
303 |
111946 |
fldtab[i]->sval = fr; |
|
304 |
111946 |
fldtab[i]->tval = FLD | STR | DONTFREE; |
|
305 |
111946 |
do |
|
306 |
✓✓ | 849551 |
*fr++ = *r++; |
307 |
✓✓✓✓ ✓✗ |
1650446 |
while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); |
308 |
111946 |
*fr++ = 0; |
|
309 |
} |
||
310 |
21089 |
*fr = 0; |
|
311 |
✗✓ | 21265 |
} else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ |
312 |
for (i = 0; *r != 0; r++) { |
||
313 |
char buf[2]; |
||
314 |
i++; |
||
315 |
if (i > nfields) |
||
316 |
growfldtab(i); |
||
317 |
if (freeable(fldtab[i])) |
||
318 |
xfree(fldtab[i]->sval); |
||
319 |
buf[0] = *r; |
||
320 |
buf[1] = 0; |
||
321 |
fldtab[i]->sval = tostring(buf); |
||
322 |
fldtab[i]->tval = FLD | STR; |
||
323 |
} |
||
324 |
*fr = 0; |
||
325 |
✓✗ | 176 |
} else if (*r != 0) { /* if 0, it's a null field */ |
326 |
/* subtlecase : if length(FS) == 1 && length(RS > 0) |
||
327 |
* \n is NOT a field separator (cf awk book 61,84). |
||
328 |
* this variable is tested in the inner while loop. |
||
329 |
*/ |
||
330 |
int rtest = '\n'; /* normal case */ |
||
331 |
✓✗ | 176 |
if (strlen(*RS) > 0) |
332 |
176 |
rtest = '\0'; |
|
333 |
352 |
for (;;) { |
|
334 |
352 |
i++; |
|
335 |
✗✓ | 352 |
if (i > nfields) |
336 |
growfldtab(i); |
||
337 |
✗✓ | 352 |
if (freeable(fldtab[i])) |
338 |
xfree(fldtab[i]->sval); |
||
339 |
352 |
fldtab[i]->sval = fr; |
|
340 |
352 |
fldtab[i]->tval = FLD | STR | DONTFREE; |
|
341 |
✓✓✓✓ ✓✗ |
7392 |
while (*r != sep && *r != rtest && *r != '\0') /* \n is always a separator */ |
342 |
1628 |
*fr++ = *r++; |
|
343 |
352 |
*fr++ = 0; |
|
344 |
✓✓ | 352 |
if (*r++ == 0) |
345 |
break; |
||
346 |
} |
||
347 |
176 |
*fr = 0; |
|
348 |
176 |
} |
|
349 |
✗✓ | 21265 |
if (i > nfields) |
350 |
FATAL("record `%.30s...' has too many fields; can't happen", r); |
||
351 |
21265 |
cleanfld(i+1, lastfld); /* clean out junk from previous record */ |
|
352 |
21265 |
lastfld = i; |
|
353 |
21265 |
donefld = 1; |
|
354 |
✓✓ | 267126 |
for (j = 1; j <= lastfld; j++) { |
355 |
112298 |
p = fldtab[j]; |
|
356 |
✓✓ | 112298 |
if(is_number(p->sval)) { |
357 |
21300 |
p->fval = atof(p->sval); |
|
358 |
21300 |
p->tval |= NUM; |
|
359 |
21300 |
} |
|
360 |
} |
||
361 |
21265 |
setfval(nfloc, (Awkfloat) lastfld); |
|
362 |
✗✓ | 21265 |
if (dbg) { |
363 |
for (j = 0; j <= lastfld; j++) { |
||
364 |
p = fldtab[j]; |
||
365 |
printf("field %d (%s): |%s|\n", j, p->nval, p->sval); |
||
366 |
} |
||
367 |
} |
||
368 |
42530 |
} |
|
369 |
|||
370 |
void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */ |
||
371 |
{ /* nvals remain intact */ |
||
372 |
Cell *p; |
||
373 |
int i; |
||
374 |
|||
375 |
✓✓ | 84199 |
for (i = n1; i <= n2; i++) { |
376 |
10202 |
p = fldtab[i]; |
|
377 |
✗✓ | 10202 |
if (freeable(p)) |
378 |
xfree(p->sval); |
||
379 |
10202 |
p->sval = ""; |
|
380 |
10202 |
p->tval = FLD | STR | DONTFREE; |
|
381 |
} |
||
382 |
21265 |
} |
|
383 |
|||
384 |
void newfld(int n) /* add field n after end of existing lastfld */ |
||
385 |
{ |
||
386 |
if (n > nfields) |
||
387 |
growfldtab(n); |
||
388 |
cleanfld(lastfld+1, n); |
||
389 |
lastfld = n; |
||
390 |
setfval(nfloc, (Awkfloat) n); |
||
391 |
} |
||
392 |
|||
393 |
Cell *fieldadr(int n) /* get nth field */ |
||
394 |
{ |
||
395 |
✗✓ | 5197454 |
if (n < 0) |
396 |
FATAL("trying to access out of range field %d", n); |
||
397 |
✓✓ | 2598727 |
if (n > nfields) /* fields after NF are empty */ |
398 |
50 |
growfldtab(n); /* but does not increase NF */ |
|
399 |
2598727 |
return(fldtab[n]); |
|
400 |
} |
||
401 |
|||
402 |
void growfldtab(int n) /* make new fields up to at least $n */ |
||
403 |
{ |
||
404 |
644 |
int nf = 2 * nfields; |
|
405 |
size_t s; |
||
406 |
|||
407 |
✓✓ | 322 |
if (n > nf) |
408 |
32 |
nf = n; |
|
409 |
322 |
s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */ |
|
410 |
✓✗ | 322 |
if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */ |
411 |
322 |
fldtab = (Cell **) realloc(fldtab, s); |
|
412 |
else /* overflow sizeof int */ |
||
413 |
xfree(fldtab); /* make it null */ |
||
414 |
✗✓ | 644 |
if (fldtab == NULL) |
415 |
FATAL("out of space creating %d fields", nf); |
||
416 |
322 |
makefields(nfields+1, nf); |
|
417 |
322 |
nfields = nf; |
|
418 |
322 |
} |
|
419 |
|||
420 |
int refldbld(const char *rec, const char *fs) /* build fields from reg expr in FS */ |
||
421 |
{ |
||
422 |
/* this relies on having fields[] the same length as $0 */ |
||
423 |
/* the fields are all stored in this one array with \0's */ |
||
424 |
char *fr; |
||
425 |
int i, tempstat, n; |
||
426 |
fa *pfa; |
||
427 |
|||
428 |
n = strlen(rec); |
||
429 |
if (n > fieldssize) { |
||
430 |
xfree(fields); |
||
431 |
if ((fields = (char *) malloc(n+1)) == NULL) |
||
432 |
FATAL("out of space for fields in refldbld %d", n); |
||
433 |
fieldssize = n; |
||
434 |
} |
||
435 |
fr = fields; |
||
436 |
*fr = '\0'; |
||
437 |
if (*rec == '\0') |
||
438 |
return 0; |
||
439 |
pfa = makedfa(fs, 1); |
||
440 |
DPRINTF( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); |
||
441 |
tempstat = pfa->initstat; |
||
442 |
for (i = 1; ; i++) { |
||
443 |
if (i > nfields) |
||
444 |
growfldtab(i); |
||
445 |
if (freeable(fldtab[i])) |
||
446 |
xfree(fldtab[i]->sval); |
||
447 |
fldtab[i]->tval = FLD | STR | DONTFREE; |
||
448 |
fldtab[i]->sval = fr; |
||
449 |
DPRINTF( ("refldbld: i=%d\n", i) ); |
||
450 |
if (nematch(pfa, rec)) { |
||
451 |
pfa->initstat = 2; /* horrible coupling to b.c */ |
||
452 |
DPRINTF( ("match %s (%d chars)\n", patbeg, patlen) ); |
||
453 |
strncpy(fr, rec, patbeg-rec); |
||
454 |
fr += patbeg - rec + 1; |
||
455 |
*(fr-1) = '\0'; |
||
456 |
rec = patbeg + patlen; |
||
457 |
} else { |
||
458 |
DPRINTF( ("no match %s\n", rec) ); |
||
459 |
strlcpy(fr, rec, fields + fieldssize - fr); |
||
460 |
pfa->initstat = tempstat; |
||
461 |
break; |
||
462 |
} |
||
463 |
} |
||
464 |
return i; |
||
465 |
} |
||
466 |
|||
467 |
void recbld(void) /* create $0 from $1..$NF if necessary */ |
||
468 |
{ |
||
469 |
int i; |
||
470 |
16 |
char *r, *p; |
|
471 |
|||
472 |
✗✓ | 8 |
if (donerec == 1) |
473 |
return; |
||
474 |
8 |
r = record; |
|
475 |
✗✓ | 16 |
for (i = 1; i <= *NF; i++) { |
476 |
p = getsval(fldtab[i]); |
||
477 |
if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1")) |
||
478 |
FATAL("created $0 `%.30s...' too long", record); |
||
479 |
while ((*r = *p++) != 0) |
||
480 |
r++; |
||
481 |
if (i < *NF) { |
||
482 |
if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2")) |
||
483 |
FATAL("created $0 `%.30s...' too long", record); |
||
484 |
for (p = *OFS; (*r = *p++) != 0; ) |
||
485 |
r++; |
||
486 |
} |
||
487 |
} |
||
488 |
✗✓ | 8 |
if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3")) |
489 |
FATAL("built giant record `%.30s...'", record); |
||
490 |
8 |
*r = '\0'; |
|
491 |
✗✓ | 8 |
DPRINTF( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, (void*)fldtab[0]) ); |
492 |
|||
493 |
✗✓ | 8 |
if (freeable(fldtab[0])) |
494 |
xfree(fldtab[0]->sval); |
||
495 |
8 |
fldtab[0]->tval = REC | STR | DONTFREE; |
|
496 |
8 |
fldtab[0]->sval = record; |
|
497 |
|||
498 |
✗✓ | 8 |
DPRINTF( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, (void*)fldtab[0]) ); |
499 |
✗✓ | 8 |
DPRINTF( ("recbld = |%s|\n", record) ); |
500 |
8 |
donerec = 1; |
|
501 |
16 |
} |
|
502 |
|||
503 |
int errorflag = 0; |
||
504 |
|||
505 |
void yyerror(const char *s) |
||
506 |
{ |
||
507 |
SYNTAX("%s", s); |
||
508 |
} |
||
509 |
|||
510 |
void SYNTAX(const char *fmt, ...) |
||
511 |
{ |
||
512 |
extern char *cmdname, *curfname; |
||
513 |
static int been_here = 0; |
||
514 |
va_list varg; |
||
515 |
|||
516 |
if (been_here++ > 2) |
||
517 |
return; |
||
518 |
fprintf(stderr, "%s: ", cmdname); |
||
519 |
va_start(varg, fmt); |
||
520 |
vfprintf(stderr, fmt, varg); |
||
521 |
va_end(varg); |
||
522 |
fprintf(stderr, " at source line %d", lineno); |
||
523 |
if (curfname != NULL) |
||
524 |
fprintf(stderr, " in function %s", curfname); |
||
525 |
if (compile_time == 1 && cursource() != NULL) |
||
526 |
fprintf(stderr, " source file %s", cursource()); |
||
527 |
fprintf(stderr, "\n"); |
||
528 |
errorflag = 2; |
||
529 |
eprint(); |
||
530 |
} |
||
531 |
|||
532 |
void fpecatch(int sig) |
||
533 |
{ |
||
534 |
extern Node *curnode; |
||
535 |
char buf[1024]; |
||
536 |
|||
537 |
snprintf(buf, sizeof buf, "floating point exception\n"); |
||
538 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
539 |
|||
540 |
if (compile_time != 2 && NR && *NR > 0) { |
||
541 |
snprintf(buf, sizeof buf, " input record number %d", (int) (*FNR)); |
||
542 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
543 |
|||
544 |
if (strcmp(*FILENAME, "-") != 0) { |
||
545 |
snprintf(buf, sizeof buf, ", file %s", *FILENAME); |
||
546 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
547 |
} |
||
548 |
write(STDERR_FILENO, "\n", 1); |
||
549 |
} |
||
550 |
if (compile_time != 2 && curnode) { |
||
551 |
snprintf(buf, sizeof buf, " source line number %d", curnode->lineno); |
||
552 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
553 |
} else if (compile_time != 2 && lineno) { |
||
554 |
snprintf(buf, sizeof buf, " source line number %d", lineno); |
||
555 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
556 |
} |
||
557 |
if (compile_time == 1 && cursource() != NULL) { |
||
558 |
snprintf(buf, sizeof buf, " source file %s", cursource()); |
||
559 |
write(STDERR_FILENO, buf, strlen(buf)); |
||
560 |
} |
||
561 |
write(STDERR_FILENO, "\n", 1); |
||
562 |
if (dbg > 1) /* core dump if serious debugging on */ |
||
563 |
abort(); |
||
564 |
_exit(1); |
||
565 |
} |
||
566 |
|||
567 |
extern int bracecnt, brackcnt, parencnt; |
||
568 |
|||
569 |
void bracecheck(void) |
||
570 |
{ |
||
571 |
int c; |
||
572 |
static int beenhere = 0; |
||
573 |
|||
574 |
if (beenhere++) |
||
575 |
return; |
||
576 |
while ((c = input()) != EOF && c != '\0') |
||
577 |
bclass(c); |
||
578 |
bcheck2(bracecnt, '{', '}'); |
||
579 |
bcheck2(brackcnt, '[', ']'); |
||
580 |
bcheck2(parencnt, '(', ')'); |
||
581 |
} |
||
582 |
|||
583 |
void bcheck2(int n, int c1, int c2) |
||
584 |
{ |
||
585 |
if (n == 1) |
||
586 |
fprintf(stderr, "\tmissing %c\n", c2); |
||
587 |
else if (n > 1) |
||
588 |
fprintf(stderr, "\t%d missing %c's\n", n, c2); |
||
589 |
else if (n == -1) |
||
590 |
fprintf(stderr, "\textra %c\n", c2); |
||
591 |
else if (n < -1) |
||
592 |
fprintf(stderr, "\t%d extra %c's\n", -n, c2); |
||
593 |
} |
||
594 |
|||
595 |
__dead void FATAL(const char *fmt, ...) |
||
596 |
{ |
||
597 |
extern char *cmdname; |
||
598 |
va_list varg; |
||
599 |
|||
600 |
fflush(stdout); |
||
601 |
fprintf(stderr, "%s: ", cmdname); |
||
602 |
va_start(varg, fmt); |
||
603 |
vfprintf(stderr, fmt, varg); |
||
604 |
va_end(varg); |
||
605 |
error(); |
||
606 |
if (dbg > 1) /* core dump if serious debugging on */ |
||
607 |
abort(); |
||
608 |
exit(2); |
||
609 |
} |
||
610 |
|||
611 |
void WARNING(const char *fmt, ...) |
||
612 |
{ |
||
613 |
extern char *cmdname; |
||
614 |
va_list varg; |
||
615 |
|||
616 |
fflush(stdout); |
||
617 |
fprintf(stderr, "%s: ", cmdname); |
||
618 |
va_start(varg, fmt); |
||
619 |
vfprintf(stderr, fmt, varg); |
||
620 |
va_end(varg); |
||
621 |
error(); |
||
622 |
} |
||
623 |
|||
624 |
void error() |
||
625 |
{ |
||
626 |
extern Node *curnode; |
||
627 |
|||
628 |
fprintf(stderr, "\n"); |
||
629 |
if (compile_time != 2 && NR && *NR > 0) { |
||
630 |
fprintf(stderr, " input record number %d", (int) (*FNR)); |
||
631 |
if (strcmp(*FILENAME, "-") != 0) |
||
632 |
fprintf(stderr, ", file %s", *FILENAME); |
||
633 |
fprintf(stderr, "\n"); |
||
634 |
} |
||
635 |
if (compile_time != 2 && curnode) |
||
636 |
fprintf(stderr, " source line number %d", curnode->lineno); |
||
637 |
else if (compile_time != 2 && lineno) |
||
638 |
fprintf(stderr, " source line number %d", lineno); |
||
639 |
if (compile_time == 1 && cursource() != NULL) |
||
640 |
fprintf(stderr, " source file %s", cursource()); |
||
641 |
fprintf(stderr, "\n"); |
||
642 |
eprint(); |
||
643 |
} |
||
644 |
|||
645 |
void eprint(void) /* try to print context around error */ |
||
646 |
{ |
||
647 |
char *p, *q; |
||
648 |
int c; |
||
649 |
static int been_here = 0; |
||
650 |
extern char ebuf[], *ep; |
||
651 |
|||
652 |
if (compile_time == 2 || compile_time == 0 || been_here++ > 0 || |
||
653 |
ebuf == ep) |
||
654 |
return; |
||
655 |
p = ep - 1; |
||
656 |
if (p > ebuf && *p == '\n') |
||
657 |
p--; |
||
658 |
for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--) |
||
659 |
; |
||
660 |
while (*p == '\n') |
||
661 |
p++; |
||
662 |
fprintf(stderr, " context is\n\t"); |
||
663 |
for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) |
||
664 |
; |
||
665 |
for ( ; p < q; p++) |
||
666 |
if (*p) |
||
667 |
putc(*p, stderr); |
||
668 |
fprintf(stderr, " >>> "); |
||
669 |
for ( ; p < ep; p++) |
||
670 |
if (*p) |
||
671 |
putc(*p, stderr); |
||
672 |
fprintf(stderr, " <<< "); |
||
673 |
if (*ep) |
||
674 |
while ((c = input()) != '\n' && c != '\0' && c != EOF) { |
||
675 |
putc(c, stderr); |
||
676 |
bclass(c); |
||
677 |
} |
||
678 |
putc('\n', stderr); |
||
679 |
ep = ebuf; |
||
680 |
} |
||
681 |
|||
682 |
void bclass(int c) |
||
683 |
{ |
||
684 |
switch (c) { |
||
685 |
case '{': bracecnt++; break; |
||
686 |
case '}': bracecnt--; break; |
||
687 |
case '[': brackcnt++; break; |
||
688 |
case ']': brackcnt--; break; |
||
689 |
case '(': parencnt++; break; |
||
690 |
case ')': parencnt--; break; |
||
691 |
} |
||
692 |
} |
||
693 |
|||
694 |
double errcheck(double x, const char *s) |
||
695 |
{ |
||
696 |
|||
697 |
if (errno == EDOM) { |
||
698 |
errno = 0; |
||
699 |
WARNING("%s argument out of domain", s); |
||
700 |
x = 1; |
||
701 |
} else if (errno == ERANGE) { |
||
702 |
errno = 0; |
||
703 |
WARNING("%s result out of range", s); |
||
704 |
x = 1; |
||
705 |
} |
||
706 |
return x; |
||
707 |
} |
||
708 |
|||
709 |
int isclvar(const char *s) /* is s of form var=something ? */ |
||
710 |
{ |
||
711 |
const char *os = s; |
||
712 |
|||
713 |
✓✓✓✗ |
396 |
if (!isalpha((uschar) *s) && *s != '_') |
714 |
76 |
return 0; |
|
715 |
✓✓ | 764 |
for ( ; *s; s++) |
716 |
✓✓✗✓ |
338 |
if (!(isalnum((uschar) *s) || *s == '_')) |
717 |
break; |
||
718 |
✓✓✓✗ |
200 |
return *s == '=' && s > os && *(s+1) != '='; |
719 |
160 |
} |
|
720 |
|||
721 |
/* strtod is supposed to be a proper test of what's a valid number */ |
||
722 |
/* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */ |
||
723 |
/* wrong: violates 4.10.1.4 of ansi C standard */ |
||
724 |
|||
725 |
#include <math.h> |
||
726 |
int is_number(const char *s) |
||
727 |
{ |
||
728 |
double r; |
||
729 |
6448474 |
char *ep; |
|
730 |
3224237 |
errno = 0; |
|
731 |
3224237 |
r = strtod(s, &ep); |
|
732 |
✓✓✗✓ |
6246297 |
if (ep == s || r == HUGE_VAL || errno == ERANGE) |
733 |
202177 |
return 0; |
|
734 |
✓✓✓✓ ✓✓ |
15147156 |
while (*ep == ' ' || *ep == '\t' || *ep == '\n') |
735 |
11664 |
ep++; |
|
736 |
✓✓ | 3022060 |
if (*ep == '\0') |
737 |
3004253 |
return 1; |
|
738 |
else |
||
739 |
17807 |
return 0; |
|
740 |
3224237 |
} |
Generated by: GCOVR (Version 3.3) |