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))
359 FATAL("out of space for string %.10s...", buf);
364 SYNTAX( "non-terminated string %.10s...", buf );
370 case '"': *bp++ = '"'; break;
371 case 'n': *bp++ = '\n'; break;
372 case 't': *bp++ = '\t'; break;
373 case 'f': *bp++ = '\f'; break;
374 case 'r': *bp++ = '\r'; break;
375 case 'b': *bp++ = '\b'; break;
376 case 'v': *bp++ = '\v'; break;
377 case 'a': *bp++ = '\007'; break;
378 case '\\': *bp++ = '\\'; break;
380 case '0': case '1': case '2': /* octal: \d \dd \ddd */
381 case '3': case '4': case '5': case '6': case '7':
383 if ((c = peek()) >= '0' && c < '8') {
384 n = 8 * n + input() - '0';
385 if ((c = peek()) >= '0' && c < '8')
386 n = 8 * n + input() - '0';
391 case 'x': /* hex \x0-9a-fA-F + */
392 { char xbuf[100], *px;
393 for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
395 || (c >= 'a' && c <= 'f')
396 || (c >= 'A' && c <= 'F'))
403 n = strtol(xbuf, nil, 16);
420 *bp++ = ' '; *bp++ = 0;
421 yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
426 int binsearch(char *w, Keyword *kp, int n)
428 int cond, low, mid, high;
432 while (low <= high) {
433 mid = (low + high) / 2;
434 if ((cond = strcmp(w, kp[mid].word)) < 0)
449 n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
451 if (n != -1) { /* found in table */
453 switch (kp->type) { /* special handling */
456 SYNTAX( "system is unsafe" );
460 SYNTAX( "illegal nested function" );
464 SYNTAX( "return not in function" );
467 yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
473 c = peek(); /* look for '(' */
474 if (c != '(' && infunc && (n=isarg(w)) >= 0) {
478 yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
487 void startreg(void) /* next call to yyles will return a regular expression */
495 static char *buf = 0;
496 static int bufsz = 500;
499 if (buf == 0 && (buf = (char *) malloc(bufsz)) == nil)
500 FATAL("out of space for rex expr");
502 for ( ; (c = input()) != '/' && c != 0; ) {
503 if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0))
504 FATAL("out of space for reg expr %.10s...", buf);
506 SYNTAX( "newline in regular expression %.10s...", buf );
509 } else if (c == '\\') {
517 yylval.s = tostring(buf);
522 /* low-level lexical stuff, sort of inherited from lex */
526 char yysbuf[100]; /* pushback buffer */
527 char *yysptr = yysbuf;
530 int input(void) /* get next lexical input character */
533 extern char *lexprog;
537 else if (lexprog != nil) { /* awk '...' */
538 if ((c = *lexprog) != 0)
540 } else /* awk -f ... */
546 if (ep >= ebuf + sizeof ebuf)
551 void unput(int c) /* put lexical character back on input */
555 if (yysptr >= yysbuf + sizeof(yysbuf))
556 FATAL("pushed back too much: %.20s...", yysbuf);
559 ep = ebuf + sizeof(ebuf) - 1;
562 void unputstr(char *s) /* put a string back on input */
566 for (i = strlen(s)-1; i >= 0; i--)