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 { "utf", FUTF, BLTIN },
90 { "while", WHILE, WHILE },
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--)