GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: lex.c,v 1.12 2011/09/28 19:27:18 millert 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 |
#include <stdio.h> |
||
27 |
#include <stdlib.h> |
||
28 |
#include <string.h> |
||
29 |
#include <ctype.h> |
||
30 |
#include "awk.h" |
||
31 |
#include "ytab.h" |
||
32 |
|||
33 |
extern YYSTYPE yylval; |
||
34 |
extern int infunc; |
||
35 |
|||
36 |
int lineno = 1; |
||
37 |
int bracecnt = 0; |
||
38 |
int brackcnt = 0; |
||
39 |
int parencnt = 0; |
||
40 |
|||
41 |
typedef struct Keyword { |
||
42 |
const char *word; |
||
43 |
int sub; |
||
44 |
int type; |
||
45 |
} Keyword; |
||
46 |
|||
47 |
Keyword keywords[] ={ /* keep sorted: binary searched */ |
||
48 |
{ "BEGIN", XBEGIN, XBEGIN }, |
||
49 |
{ "END", XEND, XEND }, |
||
50 |
{ "NF", VARNF, VARNF }, |
||
51 |
{ "and", FAND, BLTIN }, |
||
52 |
{ "atan2", FATAN, BLTIN }, |
||
53 |
{ "break", BREAK, BREAK }, |
||
54 |
{ "close", CLOSE, CLOSE }, |
||
55 |
{ "compl", FCOMPL, BLTIN }, |
||
56 |
{ "continue", CONTINUE, CONTINUE }, |
||
57 |
{ "cos", FCOS, BLTIN }, |
||
58 |
{ "delete", DELETE, DELETE }, |
||
59 |
{ "do", DO, DO }, |
||
60 |
{ "else", ELSE, ELSE }, |
||
61 |
{ "exit", EXIT, EXIT }, |
||
62 |
{ "exp", FEXP, BLTIN }, |
||
63 |
{ "fflush", FFLUSH, BLTIN }, |
||
64 |
{ "for", FOR, FOR }, |
||
65 |
{ "func", FUNC, FUNC }, |
||
66 |
{ "function", FUNC, FUNC }, |
||
67 |
{ "getline", GETLINE, GETLINE }, |
||
68 |
{ "gsub", GSUB, GSUB }, |
||
69 |
{ "if", IF, IF }, |
||
70 |
{ "in", IN, IN }, |
||
71 |
{ "index", INDEX, INDEX }, |
||
72 |
{ "int", FINT, BLTIN }, |
||
73 |
{ "length", FLENGTH, BLTIN }, |
||
74 |
{ "log", FLOG, BLTIN }, |
||
75 |
{ "lshift", FLSHIFT, BLTIN }, |
||
76 |
{ "match", MATCHFCN, MATCHFCN }, |
||
77 |
{ "next", NEXT, NEXT }, |
||
78 |
{ "nextfile", NEXTFILE, NEXTFILE }, |
||
79 |
{ "or", FFOR, BLTIN }, |
||
80 |
{ "print", PRINT, PRINT }, |
||
81 |
{ "printf", PRINTF, PRINTF }, |
||
82 |
{ "rand", FRAND, BLTIN }, |
||
83 |
{ "return", RETURN, RETURN }, |
||
84 |
{ "rshift", FRSHIFT, BLTIN }, |
||
85 |
{ "sin", FSIN, BLTIN }, |
||
86 |
{ "split", SPLIT, SPLIT }, |
||
87 |
{ "sprintf", SPRINTF, SPRINTF }, |
||
88 |
{ "sqrt", FSQRT, BLTIN }, |
||
89 |
{ "srand", FSRAND, BLTIN }, |
||
90 |
{ "sub", SUB, SUB }, |
||
91 |
{ "substr", SUBSTR, SUBSTR }, |
||
92 |
{ "system", FSYSTEM, BLTIN }, |
||
93 |
{ "tolower", FTOLOWER, BLTIN }, |
||
94 |
{ "toupper", FTOUPPER, BLTIN }, |
||
95 |
{ "while", WHILE, WHILE }, |
||
96 |
{ "xor", FXOR, BLTIN }, |
||
97 |
}; |
||
98 |
|||
99 |
#define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); } |
||
100 |
|||
101 |
int peek(void); |
||
102 |
int gettok(char **, int *); |
||
103 |
int binsearch(char *, Keyword *, int); |
||
104 |
|||
105 |
int peek(void) |
||
106 |
{ |
||
107 |
9058 |
int c = input(); |
|
108 |
4529 |
unput(c); |
|
109 |
4529 |
return c; |
|
110 |
} |
||
111 |
|||
112 |
int gettok(char **pbuf, int *psz) /* get next input token */ |
||
113 |
{ |
||
114 |
int c, retc; |
||
115 |
73040 |
char *buf = *pbuf; |
|
116 |
36520 |
int sz = *psz; |
|
117 |
36520 |
char *bp = buf; |
|
118 |
|||
119 |
36520 |
c = input(); |
|
120 |
✓✓ | 36520 |
if (c == 0) |
121 |
487 |
return 0; |
|
122 |
36033 |
buf[0] = c; |
|
123 |
36033 |
buf[1] = 0; |
|
124 |
✓✓ | 36033 |
if (!isalnum(c) && c != '.' && c != '_') |
125 |
28853 |
return c; |
|
126 |
|||
127 |
7180 |
*bp++ = c; |
|
128 |
✓✓ | 7180 |
if (isalpha(c) || c == '_') { /* it's a varname */ |
129 |
✓✗ | 44776 |
for ( ; (c = input()) != 0; ) { |
130 |
✓✓ | 22388 |
if (bp-buf >= sz) |
131 |
✗✓ | 481 |
if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok")) |
132 |
FATAL( "out of space for name %.10s...", buf ); |
||
133 |
✓✓ | 22388 |
if (isalnum(c) || c == '_') |
134 |
17407 |
*bp++ = c; |
|
135 |
else { |
||
136 |
4981 |
*bp = 0; |
|
137 |
4981 |
unput(c); |
|
138 |
4981 |
break; |
|
139 |
} |
||
140 |
} |
||
141 |
4981 |
*bp = 0; |
|
142 |
retc = 'a'; /* alphanumeric */ |
||
143 |
4981 |
} else { /* maybe it's a number, but could be . */ |
|
144 |
2199 |
char *rem; |
|
145 |
/* read input until can't be a number */ |
||
146 |
✓✗ | 5704 |
for ( ; (c = input()) != 0; ) { |
147 |
✓✓ | 2852 |
if (bp-buf >= sz) |
148 |
✗✓ | 6 |
if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok")) |
149 |
FATAL( "out of space for number %.10s...", buf ); |
||
150 |
✓✓ | 11408 |
if (isdigit(c) || c == 'e' || c == 'E' |
151 |
8556 |
|| c == '.' || c == '+' || c == '-') |
|
152 |
653 |
*bp++ = c; |
|
153 |
else { |
||
154 |
2199 |
unput(c); |
|
155 |
2199 |
break; |
|
156 |
} |
||
157 |
} |
||
158 |
2199 |
*bp = 0; |
|
159 |
2199 |
strtod(buf, &rem); /* parse the number */ |
|
160 |
✗✓ | 2199 |
if (rem == buf) { /* it wasn't a valid number at all */ |
161 |
buf[1] = 0; /* return one character as token */ |
||
162 |
retc = buf[0]; /* character is its own type */ |
||
163 |
unputstr(rem+1); /* put rest back for later */ |
||
164 |
} else { /* some prefix was a number */ |
||
165 |
2199 |
unputstr(rem); /* put rest back for later */ |
|
166 |
2199 |
rem[0] = 0; /* truncate buf after number part */ |
|
167 |
retc = '0'; /* type is number */ |
||
168 |
} |
||
169 |
2199 |
} |
|
170 |
7180 |
*pbuf = buf; |
|
171 |
7180 |
*psz = sz; |
|
172 |
7180 |
return retc; |
|
173 |
36520 |
} |
|
174 |
|||
175 |
int word(char *); |
||
176 |
int string(void); |
||
177 |
int regexpr(void); |
||
178 |
int sc = 0; /* 1 => return a } right now */ |
||
179 |
int reg = 0; /* 1 => return a REGEXPR now */ |
||
180 |
|||
181 |
int yylex(void) |
||
182 |
{ |
||
183 |
int c; |
||
184 |
static char *buf = 0; |
||
185 |
static int bufsize = 5; /* BUG: setting this small causes core dump! */ |
||
186 |
|||
187 |
✓✓✗✓ |
44569 |
if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL) |
188 |
FATAL( "out of space in yylex" ); |
||
189 |
✓✓ | 22041 |
if (sc) { |
190 |
938 |
sc = 0; |
|
191 |
✗✓ | 1876 |
RET('}'); |
192 |
} |
||
193 |
✓✓ | 21103 |
if (reg) { |
194 |
80 |
reg = 0; |
|
195 |
80 |
return regexpr(); |
|
196 |
} |
||
197 |
35820 |
for (;;) { |
|
198 |
35820 |
c = gettok(&buf, &bufsize); |
|
199 |
✓✓ | 35820 |
if (c == 0) |
200 |
487 |
return 0; |
|
201 |
✓✓ | 35333 |
if (isalpha(c) || c == '_') |
202 |
4927 |
return word(buf); |
|
203 |
✓✓ | 30406 |
if (isdigit(c)) { |
204 |
1553 |
yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab); |
|
205 |
/* should this also have STR set? */ |
||
206 |
✗✓ | 3106 |
RET(NUMBER); |
207 |
} |
||
208 |
|||
209 |
29241 |
yylval.i = c; |
|
210 |
✓✓✓✗ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✓✓✓ ✓✓✓✓ ✓✓✗✗ ✓ |
29241 |
switch (c) { |
211 |
case '\n': /* {EOL} */ |
||
212 |
✗✓ | 6916 |
RET(NL); |
213 |
case '\r': /* assume \n is coming */ |
||
214 |
case ' ': /* {WS}+ */ |
||
215 |
case '\t': |
||
216 |
break; |
||
217 |
case '#': /* #.* strip comments */ |
||
218 |
✓✓ | 55276 |
while ((c = input()) != '\n' && c != 0) |
219 |
; |
||
220 |
388 |
unput(c); |
|
221 |
388 |
break; |
|
222 |
case ';': |
||
223 |
✗✓ | 2558 |
RET(';'); |
224 |
case '\\': |
||
225 |
if (peek() == '\n') { |
||
226 |
input(); |
||
227 |
} else if (peek() == '\r') { |
||
228 |
input(); input(); /* \n */ |
||
229 |
lineno++; |
||
230 |
} else { |
||
231 |
RET(c); |
||
232 |
} |
||
233 |
break; |
||
234 |
case '&': |
||
235 |
✓✗ | 17 |
if (peek() == '&') { |
236 |
✗✓ | 34 |
input(); RET(AND); |
237 |
} else |
||
238 |
RET('&'); |
||
239 |
case '|': |
||
240 |
✓✗ | 46 |
if (peek() == '|') { |
241 |
✗✓ | 92 |
input(); RET(BOR); |
242 |
} else |
||
243 |
RET('|'); |
||
244 |
case '!': |
||
245 |
✓✓ | 110 |
if (peek() == '=') { |
246 |
✗✓ | 212 |
input(); yylval.i = NE; RET(NE); |
247 |
✓✓ | 4 |
} else if (peek() == '~') { |
248 |
✗✓ | 4 |
input(); yylval.i = NOTMATCH; RET(MATCHOP); |
249 |
} else |
||
250 |
✗✓ | 4 |
RET(NOT); |
251 |
case '~': |
||
252 |
12 |
yylval.i = MATCH; |
|
253 |
✗✓ | 24 |
RET(MATCHOP); |
254 |
case '<': |
||
255 |
✓✓ | 149 |
if (peek() == '=') { |
256 |
✗✓ | 166 |
input(); yylval.i = LE; RET(LE); |
257 |
} else { |
||
258 |
✗✓ | 132 |
yylval.i = LT; RET(LT); |
259 |
} |
||
260 |
case '=': |
||
261 |
✓✓ | 987 |
if (peek() == '=') { |
262 |
✗✓ | 446 |
input(); yylval.i = EQ; RET(EQ); |
263 |
} else { |
||
264 |
✗✓ | 1528 |
yylval.i = ASSIGN; RET(ASGNOP); |
265 |
} |
||
266 |
case '>': |
||
267 |
✓✓ | 79 |
if (peek() == '=') { |
268 |
✗✓ | 30 |
input(); yylval.i = GE; RET(GE); |
269 |
✗✓ | 64 |
} else if (peek() == '>') { |
270 |
input(); yylval.i = APPEND; RET(APPEND); |
||
271 |
} else { |
||
272 |
✗✓ | 128 |
yylval.i = GT; RET(GT); |
273 |
} |
||
274 |
case '+': |
||
275 |
✓✓ | 297 |
if (peek() == '+') { |
276 |
✗✓ | 314 |
input(); yylval.i = INCR; RET(INCR); |
277 |
✓✓ | 140 |
} else if (peek() == '=') { |
278 |
✗✓ | 80 |
input(); yylval.i = ADDEQ; RET(ASGNOP); |
279 |
} else |
||
280 |
✗✓ | 200 |
RET('+'); |
281 |
case '-': |
||
282 |
✓✓ | 55 |
if (peek() == '-') { |
283 |
✗✓ | 26 |
input(); yylval.i = DECR; RET(DECR); |
284 |
✗✓ | 42 |
} else if (peek() == '=') { |
285 |
input(); yylval.i = SUBEQ; RET(ASGNOP); |
||
286 |
} else |
||
287 |
✗✓ | 84 |
RET('-'); |
288 |
case '*': |
||
289 |
✗✓ | 18 |
if (peek() == '=') { /* *= */ |
290 |
input(); yylval.i = MULTEQ; RET(ASGNOP); |
||
291 |
✗✓ | 18 |
} else if (peek() == '*') { /* ** or **= */ |
292 |
input(); /* eat 2nd * */ |
||
293 |
if (peek() == '=') { |
||
294 |
input(); yylval.i = POWEQ; RET(ASGNOP); |
||
295 |
} else { |
||
296 |
RET(POWER); |
||
297 |
} |
||
298 |
} else |
||
299 |
✗✓ | 36 |
RET('*'); |
300 |
case '/': |
||
301 |
✗✓ | 320 |
RET('/'); |
302 |
case '%': |
||
303 |
✗✓ | 68 |
if (peek() == '=') { |
304 |
input(); yylval.i = MODEQ; RET(ASGNOP); |
||
305 |
} else |
||
306 |
✗✓ | 136 |
RET('%'); |
307 |
case '^': |
||
308 |
if (peek() == '=') { |
||
309 |
input(); yylval.i = POWEQ; RET(ASGNOP); |
||
310 |
} else |
||
311 |
RET(POWER); |
||
312 |
|||
313 |
case '$': |
||
314 |
/* BUG: awkward, if not wrong */ |
||
315 |
700 |
c = gettok(&buf, &bufsize); |
|
316 |
✓✓ | 700 |
if (isalpha(c)) { |
317 |
✗✓ | 54 |
if (strcmp(buf, "NF") == 0) { /* very special */ |
318 |
unputstr("(NF)"); |
||
319 |
RET(INDIRECT); |
||
320 |
} |
||
321 |
54 |
c = peek(); |
|
322 |
✓✗✗✓ ✗✗ |
108 |
if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) { |
323 |
unputstr(buf); |
||
324 |
RET(INDIRECT); |
||
325 |
} |
||
326 |
54 |
yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab); |
|
327 |
✗✓ | 108 |
RET(IVAR); |
328 |
✗✓ | 646 |
} else if (c == 0) { /* */ |
329 |
SYNTAX( "unexpected end of input after $" ); |
||
330 |
RET(';'); |
||
331 |
} else { |
||
332 |
646 |
unputstr(buf); |
|
333 |
✗✓ | 1292 |
RET(INDIRECT); |
334 |
} |
||
335 |
|||
336 |
case '}': |
||
337 |
✗✓ | 938 |
if (--bracecnt < 0) |
338 |
SYNTAX( "extra }" ); |
||
339 |
938 |
sc = 1; |
|
340 |
✗✓ | 1876 |
RET(';'); |
341 |
case ']': |
||
342 |
✗✓ | 24 |
if (--brackcnt < 0) |
343 |
SYNTAX( "extra ]" ); |
||
344 |
✗✓ | 48 |
RET(']'); |
345 |
case ')': |
||
346 |
✗✓ | 1105 |
if (--parencnt < 0) |
347 |
SYNTAX( "extra )" ); |
||
348 |
✗✓ | 2210 |
RET(')'); |
349 |
case '{': |
||
350 |
938 |
bracecnt++; |
|
351 |
✗✓ | 1876 |
RET('{'); |
352 |
case '[': |
||
353 |
24 |
brackcnt++; |
|
354 |
✗✓ | 48 |
RET('['); |
355 |
case '(': |
||
356 |
1105 |
parencnt++; |
|
357 |
✗✓ | 2210 |
RET('('); |
358 |
|||
359 |
case '"': |
||
360 |
1788 |
return string(); /* BUG: should be like tran.c ? */ |
|
361 |
|||
362 |
default: |
||
363 |
✗✓ | 1398 |
RET(c); |
364 |
} |
||
365 |
} |
||
366 |
22041 |
} |
|
367 |
|||
368 |
int string(void) |
||
369 |
{ |
||
370 |
3576 |
int c, n; |
|
371 |
1788 |
char *s, *bp; |
|
372 |
static char *buf = 0; |
||
373 |
static int bufsz = 500; |
||
374 |
|||
375 |
✓✓✗✓ |
2065 |
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) |
376 |
FATAL("out of space for strings"); |
||
377 |
✓✓ | 52532 |
for (bp = buf; (c = input()) != '"'; ) { |
378 |
✗✓ | 24478 |
if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string")) |
379 |
FATAL("out of space for string %.10s...", buf); |
||
380 |
✗✗✗✓ ✓ |
24478 |
switch (c) { |
381 |
case '\n': |
||
382 |
case '\r': |
||
383 |
case 0: |
||
384 |
SYNTAX( "non-terminated string %.10s...", buf ); |
||
385 |
lineno++; |
||
386 |
if (c == 0) /* hopeless */ |
||
387 |
FATAL( "giving up" ); |
||
388 |
break; |
||
389 |
case '\\': |
||
390 |
989 |
c = input(); |
|
391 |
✓✓✓✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗ |
989 |
switch (c) { |
392 |
116 |
case '"': *bp++ = '"'; break; |
|
393 |
649 |
case 'n': *bp++ = '\n'; break; |
|
394 |
186 |
case 't': *bp++ = '\t'; break; |
|
395 |
case 'f': *bp++ = '\f'; break; |
||
396 |
case 'r': *bp++ = '\r'; break; |
||
397 |
case 'b': *bp++ = '\b'; break; |
||
398 |
case 'v': *bp++ = '\v'; break; |
||
399 |
case 'a': *bp++ = '\007'; break; |
||
400 |
38 |
case '\\': *bp++ = '\\'; break; |
|
401 |
|||
402 |
case '0': case '1': case '2': /* octal: \d \dd \ddd */ |
||
403 |
case '3': case '4': case '5': case '6': case '7': |
||
404 |
n = c - '0'; |
||
405 |
if ((c = peek()) >= '0' && c < '8') { |
||
406 |
n = 8 * n + input() - '0'; |
||
407 |
if ((c = peek()) >= '0' && c < '8') |
||
408 |
n = 8 * n + input() - '0'; |
||
409 |
} |
||
410 |
*bp++ = n; |
||
411 |
break; |
||
412 |
|||
413 |
case 'x': /* hex \x0-9a-fA-F + */ |
||
414 |
{ char xbuf[100], *px; |
||
415 |
for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) { |
||
416 |
if (isdigit(c) |
||
417 |
|| (c >= 'a' && c <= 'f') |
||
418 |
|| (c >= 'A' && c <= 'F')) |
||
419 |
*px++ = c; |
||
420 |
else |
||
421 |
break; |
||
422 |
} |
||
423 |
*px = 0; |
||
424 |
unput(c); |
||
425 |
sscanf(xbuf, "%x", (unsigned int *) &n); |
||
426 |
*bp++ = n; |
||
427 |
break; |
||
428 |
} |
||
429 |
|||
430 |
default: |
||
431 |
*bp++ = c; |
||
432 |
break; |
||
433 |
} |
||
434 |
break; |
||
435 |
default: |
||
436 |
23489 |
*bp++ = c; |
|
437 |
23489 |
break; |
|
438 |
} |
||
439 |
} |
||
440 |
1788 |
*bp = 0; |
|
441 |
1788 |
s = tostring(buf); |
|
442 |
1788 |
*bp++ = ' '; *bp++ = 0; |
|
443 |
1788 |
yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab); |
|
444 |
✗✓ | 3576 |
RET(STRING); |
445 |
1788 |
} |
|
446 |
|||
447 |
|||
448 |
int binsearch(char *w, Keyword *kp, int n) |
||
449 |
{ |
||
450 |
int cond, low, mid, high; |
||
451 |
|||
452 |
low = 0; |
||
453 |
9854 |
high = n - 1; |
|
454 |
✓✓ | 59916 |
while (low <= high) { |
455 |
27577 |
mid = (low + high) / 2; |
|
456 |
✓✓ | 27577 |
if ((cond = strcmp(w, kp[mid].word)) < 0) |
457 |
12341 |
high = mid - 1; |
|
458 |
✓✓ | 15236 |
else if (cond > 0) |
459 |
12690 |
low = mid + 1; |
|
460 |
else |
||
461 |
2546 |
return mid; |
|
462 |
} |
||
463 |
2381 |
return -1; |
|
464 |
4927 |
} |
|
465 |
|||
466 |
int word(char *w) |
||
467 |
{ |
||
468 |
Keyword *kp; |
||
469 |
int c, n; |
||
470 |
|||
471 |
9854 |
n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0])); |
|
472 |
/* BUG: this ought to be inside the if; in theory could fault (daniel barrett) */ |
||
473 |
4927 |
kp = keywords + n; |
|
474 |
✓✓ | 4927 |
if (n != -1) { /* found in table */ |
475 |
2546 |
yylval.i = kp->sub; |
|
476 |
✓✓✓✓ ✓ |
2546 |
switch (kp->type) { /* special handling */ |
477 |
case BLTIN: |
||
478 |
✗✓ | 38 |
if (kp->sub == FSYSTEM && safe) |
479 |
SYNTAX( "system is unsafe" ); |
||
480 |
✗✓ | 76 |
RET(kp->type); |
481 |
case FUNC: |
||
482 |
✗✓ | 24 |
if (infunc) |
483 |
SYNTAX( "illegal nested function" ); |
||
484 |
✗✓ | 48 |
RET(kp->type); |
485 |
case RETURN: |
||
486 |
✗✓ | 12 |
if (!infunc) |
487 |
SYNTAX( "return not in function" ); |
||
488 |
✗✓ | 24 |
RET(kp->type); |
489 |
case VARNF: |
||
490 |
12 |
yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab); |
|
491 |
✗✓ | 24 |
RET(VARNF); |
492 |
default: |
||
493 |
✗✓ | 4920 |
RET(kp->type); |
494 |
} |
||
495 |
} |
||
496 |
2381 |
c = peek(); /* look for '(' */ |
|
497 |
✓✓✓✓ |
2565 |
if (c != '(' && infunc && (n=isarg(w)) >= 0) { |
498 |
48 |
yylval.i = n; |
|
499 |
✗✓ | 96 |
RET(ARG); |
500 |
} else { |
||
501 |
2333 |
yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab); |
|
502 |
✓✓ | 2333 |
if (c == '(') { |
503 |
✗✓ | 268 |
RET(CALL); |
504 |
} else { |
||
505 |
✗✓ | 4398 |
RET(VAR); |
506 |
} |
||
507 |
} |
||
508 |
4927 |
} |
|
509 |
|||
510 |
void startreg(void) /* next call to yylex will return a regular expression */ |
||
511 |
{ |
||
512 |
160 |
reg = 1; |
|
513 |
80 |
} |
|
514 |
|||
515 |
int regexpr(void) |
||
516 |
{ |
||
517 |
int c, openclass = 0; |
||
518 |
static char *buf = 0; |
||
519 |
static int bufsz = 500; |
||
520 |
160 |
char *bp; |
|
521 |
|||
522 |
✓✓✗✓ |
142 |
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) |
523 |
FATAL("out of space for rex expr"); |
||
524 |
80 |
bp = buf; |
|
525 |
✓✓ | 1228 |
for ( ; ((c = input()) != '/' || openclass == 1) && c != 0; ) { |
526 |
✗✓ | 534 |
if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr")) |
527 |
FATAL("out of space for reg expr %.10s...", buf); |
||
528 |
✗✓ | 534 |
if (c == '\n') { |
529 |
SYNTAX( "newline in regular expression %.10s...", buf ); |
||
530 |
unput('\n'); |
||
531 |
break; |
||
532 |
✓✓ | 534 |
} else if (c == '\\') { |
533 |
18 |
*bp++ = '\\'; |
|
534 |
18 |
*bp++ = input(); |
|
535 |
18 |
} else { |
|
536 |
✓✓ | 516 |
if (c == '[') |
537 |
6 |
openclass = 1; |
|
538 |
✓✓ | 510 |
else if (c == ']') |
539 |
6 |
openclass = 0; |
|
540 |
516 |
*bp++ = c; |
|
541 |
} |
||
542 |
} |
||
543 |
80 |
*bp = 0; |
|
544 |
✗✓ | 80 |
if (c == 0) |
545 |
SYNTAX("non-terminated regular expression %.10s...", buf); |
||
546 |
80 |
yylval.s = tostring(buf); |
|
547 |
80 |
unput('/'); |
|
548 |
✗✓ | 160 |
RET(REGEXPR); |
549 |
80 |
} |
|
550 |
|||
551 |
/* low-level lexical stuff, sort of inherited from lex */ |
||
552 |
|||
553 |
char ebuf[300]; |
||
554 |
char *ep = ebuf; |
||
555 |
char yysbuf[100]; /* pushback buffer */ |
||
556 |
char *yysptr = yysbuf; |
||
557 |
FILE *yyin = 0; |
||
558 |
|||
559 |
int input(void) /* get next lexical input character */ |
||
560 |
{ |
||
561 |
int c; |
||
562 |
extern char *lexprog; |
||
563 |
|||
564 |
✓✓ | 245032 |
if (yysptr > yysbuf) |
565 |
12863 |
c = (uschar)*--yysptr; |
|
566 |
✓✓ | 109653 |
else if (lexprog != NULL) { /* awk '...' */ |
567 |
✓✓ | 34873 |
if ((c = (uschar)*lexprog) != 0) |
568 |
34402 |
lexprog++; |
|
569 |
} else /* awk -f ... */ |
||
570 |
74780 |
c = pgetc(); |
|
571 |
✓✓ | 122516 |
if (c == '\n') |
572 |
4057 |
lineno++; |
|
573 |
✓✓ | 118459 |
else if (c == EOF) |
574 |
16 |
c = 0; |
|
575 |
✓✓ | 122516 |
if (ep >= ebuf + sizeof ebuf) |
576 |
280 |
ep = ebuf; |
|
577 |
122516 |
return *ep++ = c; |
|
578 |
} |
||
579 |
|||
580 |
void unput(int c) /* put lexical character back on input */ |
||
581 |
{ |
||
582 |
✓✓ | 25726 |
if (c == '\n') |
583 |
599 |
lineno--; |
|
584 |
✗✓ | 12863 |
if (yysptr >= yysbuf + sizeof(yysbuf)) |
585 |
FATAL("pushed back too much: %.20s...", yysbuf); |
||
586 |
12863 |
*yysptr++ = c; |
|
587 |
12863 |
if (--ep < ebuf) |
|
588 |
ep = ebuf + sizeof(ebuf) - 1; |
||
589 |
12863 |
} |
|
590 |
|||
591 |
void unputstr(const char *s) /* put a string back on input */ |
||
592 |
{ |
||
593 |
int i; |
||
594 |
|||
595 |
✓✓ | 9907 |
for (i = strlen(s)-1; i >= 0; i--) |
596 |
686 |
unput(s[i]); |
|
597 |
2845 |
} |
Generated by: GCOVR (Version 3.3) |