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 },
94 #define RET(x) { if(dbg)print("lex %s\n", tokname(x)); return(x); }
96 #define RET(x) return(x)
106 int gettok(char **pbuf, int *psz) /* get next input token */
118 if (!isalnum(c) && c != '.' && c != '_')
122 if (isalpha(c) || c == '_') { /* it's a varname */
123 for ( ; (c = input()) != 0; ) {
125 if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
126 FATAL( "out of space for name %.10s...", buf );
127 if (isalnum(c) || c == '_')
135 } else { /* it's a number */
137 /* read input until can't be a number */
138 for ( ; (c = input()) != 0; ) {
140 if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
141 FATAL( "out of space for number %.10s...", buf );
142 if (isdigit(c) || c == 'e' || c == 'E'
143 || c == '.' || c == '+' || c == '-')
151 strtod(buf, &rem); /* parse the number */
152 unputstr(rem); /* put rest back for later */
163 int sc = 0; /* 1 => return a } right now */
164 int reg = 0; /* 1 => return a REGEXPR now */
169 static char *buf = 0;
170 static int bufsize = 500;
172 if (buf == 0 && (buf = (char *) malloc(bufsize)) == nil)
173 FATAL( "out of space in yylex" );
183 c = gettok(&buf, &bufsize);
186 if (isalpha(c) || c == '_')
188 if (isdigit(c) || c == '.') {
189 yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
190 /* should this also have STR set? */
196 case '\n': /* {EOL} */
198 case '\r': /* assume \n is coming */
199 case ' ': /* {WS}+ */
202 case '#': /* #.* strip comments */
203 while ((c = input()) != '\n' && c != 0)
210 if (peek() == '\n') {
212 } else if (peek() == '\r') {
213 input(); input(); /* \n */
231 input(); yylval.i = NE; RET(NE);
232 } else if (peek() == '~') {
233 input(); yylval.i = NOTMATCH; RET(MATCHOP);
241 input(); yylval.i = LE; RET(LE);
243 yylval.i = LT; RET(LT);
247 input(); yylval.i = EQ; RET(EQ);
249 yylval.i = ASSIGN; RET(ASGNOP);
253 input(); yylval.i = GE; RET(GE);
254 } else if (peek() == '>') {
255 input(); yylval.i = APPEND; RET(APPEND);
257 yylval.i = GT; RET(GT);
261 input(); yylval.i = INCR; RET(INCR);
262 } else if (peek() == '=') {
263 input(); yylval.i = ADDEQ; RET(ASGNOP);
268 input(); yylval.i = DECR; RET(DECR);
269 } else if (peek() == '=') {
270 input(); yylval.i = SUBEQ; RET(ASGNOP);
274 if (peek() == '=') { /* *= */
275 input(); yylval.i = MULTEQ; RET(ASGNOP);
276 } else if (peek() == '*') { /* ** or **= */
277 input(); /* eat 2nd * */
279 input(); yylval.i = POWEQ; RET(ASGNOP);
289 input(); yylval.i = MODEQ; RET(ASGNOP);
294 input(); yylval.i = POWEQ; RET(ASGNOP);
299 /* BUG: awkward, if not wrong */
300 c = gettok(&buf, &bufsize);
301 if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
304 } else if (isalpha(c)) {
305 if (strcmp(buf, "NF") == 0) { /* very special */
309 yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
340 return string(); /* BUG: should be like tran.c ? */
352 static char *buf = 0;
353 static int bufsz = 500;
355 if (buf == 0 && (buf = (char *) malloc(bufsz)) == nil)
356 FATAL("out of space for strings");
357 for (bp = buf; (c = input()) != '"'; ) {
358 if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, 0)){
360 FATAL("out of space for string %.10s...", buf);
367 SYNTAX( "non-terminated string %.10s...", buf );
373 case '"': *bp++ = '"'; break;
374 case 'n': *bp++ = '\n'; break;
375 case 't': *bp++ = '\t'; break;
376 case 'f': *bp++ = '\f'; break;
377 case 'r': *bp++ = '\r'; break;
378 case 'b': *bp++ = '\b'; break;
379 case 'v': *bp++ = '\v'; break;
380 case 'a': *bp++ = '\007'; break;
381 case '\\': *bp++ = '\\'; break;
383 case '0': case '1': case '2': /* octal: \d \dd \ddd */
384 case '3': case '4': case '5': case '6': case '7':
386 if ((c = peek()) >= '0' && c < '8') {
387 n = 8 * n + input() - '0';
388 if ((c = peek()) >= '0' && c < '8')
389 n = 8 * n + input() - '0';
394 case 'x': /* hex \x0-9a-fA-F + */
395 { char xbuf[100], *px;
396 for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
398 || (c >= 'a' && c <= 'f')
399 || (c >= 'A' && c <= 'F'))
406 n = strtol(xbuf, nil, 16);
423 *bp++ = ' '; *bp++ = 0;
424 yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
429 int binsearch(char *w, Keyword *kp, int n)
431 int cond, low, mid, high;
435 while (low <= high) {
436 mid = (low + high) / 2;
437 if ((cond = strcmp(w, kp[mid].word)) < 0)
452 n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
454 if (n != -1) { /* found in table */
456 switch (kp->type) { /* special handling */
459 SYNTAX( "system is unsafe" );
463 SYNTAX( "illegal nested function" );
467 SYNTAX( "return not in function" );
470 yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
476 c = peek(); /* look for '(' */
477 if (c != '(' && infunc && (n=isarg(w)) >= 0) {
481 yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
490 void startreg(void) /* next call to yyles will return a regular expression */
498 static char *buf = 0;
499 static int bufsz = 500;
502 if (buf == 0 && (buf = (char *) malloc(bufsz)) == nil)
503 FATAL("out of space for rex expr");
505 for ( ; (c = input()) != '/' && c != 0; ) {
506 if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0))
507 FATAL("out of space for reg expr %.10s...", buf);
509 SYNTAX( "newline in regular expression %.10s...", buf );
512 } else if (c == '\\') {
520 yylval.s = tostring(buf);
525 /* low-level lexical stuff, sort of inherited from lex */
529 char yysbuf[100]; /* pushback buffer */
530 char *yysptr = yysbuf;
533 int input(void) /* get next lexical input character */
536 extern char *lexprog;
540 else if (lexprog != nil) { /* awk '...' */
541 if ((c = *lexprog) != 0)
543 } else /* awk -f ... */
549 if (ep >= ebuf + sizeof ebuf)
554 void unput(int c) /* put lexical character back on input */
558 if (yysptr >= yysbuf + sizeof(yysbuf))
559 FATAL("pushed back too much: %.20s...", yysbuf);
562 ep = ebuf + sizeof(ebuf) - 1;
565 void unputstr(char *s) /* put a string back on input */
569 for (i = strlen(s)-1; i >= 0; i--)