1
/****************************************************************
2
Copyright (C) Lucent Technologies 1997
5
Permission to use, copy, modify, and distribute this software and
6
its documentation for any purpose and without fee is hereby
7
granted, provided that the above copyright notice appear in all
8
copies and that both that the copyright notice and this
9
permission notice and warranty disclaimer appear in supporting
10
documentation, and that the name Lucent Technologies or any of
11
its entities not be used in advertising or publicity pertaining
12
to distribution of the software without specific, written prior
15
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23
****************************************************************/
32
extern YYSTYPE yylval;
40
typedef struct Keyword {
46
Keyword keywords[] ={ /* keep sorted: binary searched */
47
{ "BEGIN", XBEGIN, XBEGIN },
48
{ "END", XEND, XEND },
49
{ "NF", VARNF, VARNF },
50
{ "atan2", FATAN, BLTIN },
51
{ "break", BREAK, BREAK },
52
{ "close", CLOSE, CLOSE },
53
{ "continue", CONTINUE, CONTINUE },
54
{ "cos", FCOS, BLTIN },
55
{ "delete", DELETE, DELETE },
57
{ "else", ELSE, ELSE },
58
{ "exit", EXIT, EXIT },
59
{ "exp", FEXP, BLTIN },
60
{ "fflush", FFLUSH, BLTIN },
62
{ "func", FUNC, FUNC },
63
{ "function", FUNC, FUNC },
64
{ "getline", GETLINE, GETLINE },
65
{ "gsub", GSUB, GSUB },
68
{ "index", INDEX, INDEX },
69
{ "int", FINT, BLTIN },
70
{ "length", FLENGTH, BLTIN },
71
{ "log", FLOG, BLTIN },
72
{ "match", MATCHFCN, MATCHFCN },
73
{ "next", NEXT, NEXT },
74
{ "nextfile", NEXTFILE, NEXTFILE },
75
{ "print", PRINT, PRINT },
76
{ "printf", PRINTF, PRINTF },
77
{ "rand", FRAND, BLTIN },
78
{ "return", RETURN, RETURN },
79
{ "sin", FSIN, BLTIN },
80
{ "split", SPLIT, SPLIT },
81
{ "sprintf", SPRINTF, SPRINTF },
82
{ "sqrt", FSQRT, BLTIN },
83
{ "srand", FSRAND, BLTIN },
85
{ "substr", SUBSTR, SUBSTR },
86
{ "system", FSYSTEM, BLTIN },
87
{ "tolower", FTOLOWER, BLTIN },
88
{ "toupper", FTOUPPER, BLTIN },
89
{ "while", WHILE, WHILE },
90
{ "utf", FUTF, BLTIN },
95
#define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); }
97
#define RET(x) return(x)
107
int gettok(char **pbuf, int *psz) /* get next input token */
119
if (!isalnum(c) && c != '.' && c != '_')
123
if (isalpha(c) || c == '_') { /* it's a varname */
124
for ( ; (c = input()) != 0; ) {
126
if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
127
FATAL( "out of space for name %.10s...", buf );
128
if (isalnum(c) || c == '_')
136
} else { /* it's a number */
138
/* read input until can't be a number */
139
for ( ; (c = input()) != 0; ) {
141
if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
142
FATAL( "out of space for number %.10s...", buf );
143
if (isdigit(c) || c == 'e' || c == 'E'
144
|| c == '.' || c == '+' || c == '-')
152
strtod(buf, &rem); /* parse the number */
153
unputstr(rem); /* put rest back for later */
164
int sc = 0; /* 1 => return a } right now */
165
int reg = 0; /* 1 => return a REGEXPR now */
170
static char *buf = 0;
171
static int bufsize = 500;
173
if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
174
FATAL( "out of space in yylex" );
184
c = gettok(&buf, &bufsize);
187
if (isalpha(c) || c == '_')
189
if (isdigit(c) || c == '.') {
190
yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
191
/* should this also have STR set? */
197
case '\n': /* {EOL} */
199
case '\r': /* assume \n is coming */
200
case ' ': /* {WS}+ */
203
case '#': /* #.* strip comments */
204
while ((c = input()) != '\n' && c != 0)
211
if (peek() == '\n') {
213
} else if (peek() == '\r') {
214
input(); input(); /* \n */
232
input(); yylval.i = NE; RET(NE);
233
} else if (peek() == '~') {
234
input(); yylval.i = NOTMATCH; RET(MATCHOP);
242
input(); yylval.i = LE; RET(LE);
244
yylval.i = LT; RET(LT);
248
input(); yylval.i = EQ; RET(EQ);
250
yylval.i = ASSIGN; RET(ASGNOP);
254
input(); yylval.i = GE; RET(GE);
255
} else if (peek() == '>') {
256
input(); yylval.i = APPEND; RET(APPEND);
258
yylval.i = GT; RET(GT);
262
input(); yylval.i = INCR; RET(INCR);
263
} else if (peek() == '=') {
264
input(); yylval.i = ADDEQ; RET(ASGNOP);
269
input(); yylval.i = DECR; RET(DECR);
270
} else if (peek() == '=') {
271
input(); yylval.i = SUBEQ; RET(ASGNOP);
275
if (peek() == '=') { /* *= */
276
input(); yylval.i = MULTEQ; RET(ASGNOP);
277
} else if (peek() == '*') { /* ** or **= */
278
input(); /* eat 2nd * */
280
input(); yylval.i = POWEQ; RET(ASGNOP);
290
input(); yylval.i = MODEQ; RET(ASGNOP);
295
input(); yylval.i = POWEQ; RET(ASGNOP);
300
/* BUG: awkward, if not wrong */
301
c = gettok(&buf, &bufsize);
302
if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
305
} else if (isalpha(c)) {
306
if (strcmp(buf, "NF") == 0) { /* very special */
310
yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
341
return string(); /* BUG: should be like tran.c ? */
353
static char *buf = 0;
354
static int bufsz = 500;
356
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
357
FATAL("out of space for strings");
358
for (bp = buf; (c = input()) != '"'; ) {
359
if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, 0))
360
FATAL("out of space for string %.10s...", buf);
365
SYNTAX( "non-terminated string %.10s...", buf );
371
case '"': *bp++ = '"'; break;
372
case 'n': *bp++ = '\n'; break;
373
case 't': *bp++ = '\t'; break;
374
case 'f': *bp++ = '\f'; break;
375
case 'r': *bp++ = '\r'; break;
376
case 'b': *bp++ = '\b'; break;
377
case 'v': *bp++ = '\v'; break;
378
case 'a': *bp++ = '\007'; break;
379
case '\\': *bp++ = '\\'; break;
381
case '0': case '1': case '2': /* octal: \d \dd \ddd */
382
case '3': case '4': case '5': case '6': case '7':
384
if ((c = peek()) >= '0' && c < '8') {
385
n = 8 * n + input() - '0';
386
if ((c = peek()) >= '0' && c < '8')
387
n = 8 * n + input() - '0';
392
case 'x': /* hex \x0-9a-fA-F + */
393
{ char xbuf[100], *px;
394
for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
396
|| (c >= 'a' && c <= 'f')
397
|| (c >= 'A' && c <= 'F'))
404
sscanf(xbuf, "%x", &n);
421
*bp++ = ' '; *bp++ = 0;
422
yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
427
int binsearch(char *w, Keyword *kp, int n)
429
int cond, low, mid, high;
433
while (low <= high) {
434
mid = (low + high) / 2;
435
if ((cond = strcmp(w, kp[mid].word)) < 0)
450
n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
452
if (n != -1) { /* found in table */
454
switch (kp->type) { /* special handling */
457
SYNTAX( "system is unsafe" );
461
SYNTAX( "illegal nested function" );
465
SYNTAX( "return not in function" );
468
yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
474
c = peek(); /* look for '(' */
475
if (c != '(' && infunc && (n=isarg(w)) >= 0) {
479
yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
488
void startreg(void) /* next call to yyles will return a regular expression */
496
static char *buf = 0;
497
static int bufsz = 500;
500
if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
501
FATAL("out of space for rex expr");
503
for ( ; (c = input()) != '/' && c != 0; ) {
504
if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0))
505
FATAL("out of space for reg expr %.10s...", buf);
507
SYNTAX( "newline in regular expression %.10s...", buf );
510
} else if (c == '\\') {
518
yylval.s = tostring(buf);
523
/* low-level lexical stuff, sort of inherited from lex */
527
char yysbuf[100]; /* pushback buffer */
528
char *yysptr = yysbuf;
531
int input(void) /* get next lexical input character */
534
extern char *lexprog;
538
else if (lexprog != NULL) { /* awk '...' */
539
if ((c = *lexprog) != 0)
541
} else /* awk -f ... */
547
if (ep >= ebuf + sizeof ebuf)
552
void unput(int c) /* put lexical character back on input */
556
if (yysptr >= yysbuf + sizeof(yysbuf))
557
FATAL("pushed back too much: %.20s...", yysbuf);
560
ep = ebuf + sizeof(ebuf) - 1;
563
void unputstr(char *s) /* put a string back on input */
567
for (i = strlen(s)-1; i >= 0; i--)