135f471cbSchristos /****************************************************************
235f471cbSchristos Copyright (C) Lucent Technologies 1997
335f471cbSchristos All Rights Reserved
435f471cbSchristos
535f471cbSchristos Permission to use, copy, modify, and distribute this software and
635f471cbSchristos its documentation for any purpose and without fee is hereby
735f471cbSchristos granted, provided that the above copyright notice appear in all
835f471cbSchristos copies and that both that the copyright notice and this
935f471cbSchristos permission notice and warranty disclaimer appear in supporting
1035f471cbSchristos documentation, and that the name Lucent Technologies or any of
1135f471cbSchristos its entities not be used in advertising or publicity pertaining
1235f471cbSchristos to distribution of the software without specific, written prior
1335f471cbSchristos permission.
1435f471cbSchristos
1535f471cbSchristos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1635f471cbSchristos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1735f471cbSchristos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
1835f471cbSchristos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1935f471cbSchristos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
2035f471cbSchristos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2135f471cbSchristos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2235f471cbSchristos THIS SOFTWARE.
2335f471cbSchristos ****************************************************************/
2435f471cbSchristos
255642d004Schristos #if HAVE_NBTOOL_CONFIG_H
265642d004Schristos #include "nbtool_config.h"
275642d004Schristos #endif
285642d004Schristos
2935f471cbSchristos #include <stdio.h>
3035f471cbSchristos #include <stdlib.h>
3135f471cbSchristos #include <string.h>
3235f471cbSchristos #include <ctype.h>
3335f471cbSchristos #include "awk.h"
345642d004Schristos #include "awkgram.h"
3535f471cbSchristos
3635f471cbSchristos extern YYSTYPE yylval;
3735f471cbSchristos extern int infunc;
3835f471cbSchristos
3935f471cbSchristos int lineno = 1;
4035f471cbSchristos int bracecnt = 0;
4135f471cbSchristos int brackcnt = 0;
4235f471cbSchristos int parencnt = 0;
4335f471cbSchristos
4435f471cbSchristos typedef struct Keyword {
4535f471cbSchristos const char *word;
4635f471cbSchristos int sub;
4735f471cbSchristos int type;
4835f471cbSchristos } Keyword;
4935f471cbSchristos
505642d004Schristos const Keyword keywords[] = { /* keep sorted: binary searched */
5135f471cbSchristos { "BEGIN", XBEGIN, XBEGIN },
5235f471cbSchristos { "END", XEND, XEND },
5335f471cbSchristos { "NF", VARNF, VARNF },
548eaba782Schristos { "and", FAND, BLTIN },
5535f471cbSchristos { "atan2", FATAN, BLTIN },
5635f471cbSchristos { "break", BREAK, BREAK },
5735f471cbSchristos { "close", CLOSE, CLOSE },
588eaba782Schristos { "compl", FCOMPL, BLTIN },
5935f471cbSchristos { "continue", CONTINUE, CONTINUE },
6035f471cbSchristos { "cos", FCOS, BLTIN },
6135f471cbSchristos { "delete", DELETE, DELETE },
6235f471cbSchristos { "do", DO, DO },
6335f471cbSchristos { "else", ELSE, ELSE },
6435f471cbSchristos { "exit", EXIT, EXIT },
6535f471cbSchristos { "exp", FEXP, BLTIN },
6635f471cbSchristos { "fflush", FFLUSH, BLTIN },
6735f471cbSchristos { "for", FOR, FOR },
6835f471cbSchristos { "func", FUNC, FUNC },
6935f471cbSchristos { "function", FUNC, FUNC },
705642d004Schristos { "gensub", GENSUB, GENSUB },
7135f471cbSchristos { "getline", GETLINE, GETLINE },
7235f471cbSchristos { "gsub", GSUB, GSUB },
7335f471cbSchristos { "if", IF, IF },
7435f471cbSchristos { "in", IN, IN },
7535f471cbSchristos { "index", INDEX, INDEX },
7635f471cbSchristos { "int", FINT, BLTIN },
7735f471cbSchristos { "length", FLENGTH, BLTIN },
7835f471cbSchristos { "log", FLOG, BLTIN },
798eaba782Schristos { "lshift", FLSHIFT, BLTIN },
8035f471cbSchristos { "match", MATCHFCN, MATCHFCN },
8135f471cbSchristos { "next", NEXT, NEXT },
8235f471cbSchristos { "nextfile", NEXTFILE, NEXTFILE },
838eaba782Schristos { "or", FFOR, BLTIN },
8435f471cbSchristos { "print", PRINT, PRINT },
8535f471cbSchristos { "printf", PRINTF, PRINTF },
8635f471cbSchristos { "rand", FRAND, BLTIN },
8735f471cbSchristos { "return", RETURN, RETURN },
888eaba782Schristos { "rshift", FRSHIFT, BLTIN },
8935f471cbSchristos { "sin", FSIN, BLTIN },
9035f471cbSchristos { "split", SPLIT, SPLIT },
9135f471cbSchristos { "sprintf", SPRINTF, SPRINTF },
9235f471cbSchristos { "sqrt", FSQRT, BLTIN },
9335f471cbSchristos { "srand", FSRAND, BLTIN },
945642d004Schristos { "strftime", FSTRFTIME, BLTIN },
9535f471cbSchristos { "sub", SUB, SUB },
9635f471cbSchristos { "substr", SUBSTR, SUBSTR },
9735f471cbSchristos { "system", FSYSTEM, BLTIN },
985642d004Schristos { "systime", FSYSTIME, BLTIN },
9935f471cbSchristos { "tolower", FTOLOWER, BLTIN },
10035f471cbSchristos { "toupper", FTOUPPER, BLTIN },
10135f471cbSchristos { "while", WHILE, WHILE },
1028eaba782Schristos { "xor", FXOR, BLTIN },
10335f471cbSchristos };
10435f471cbSchristos
10535f471cbSchristos #define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); }
10635f471cbSchristos
peek(void)1078eaba782Schristos static int peek(void)
10835f471cbSchristos {
10935f471cbSchristos int c = input();
11035f471cbSchristos unput(c);
11135f471cbSchristos return c;
11235f471cbSchristos }
11335f471cbSchristos
gettok(char ** pbuf,int * psz)1148eaba782Schristos static int gettok(char **pbuf, int *psz) /* get next input token */
11535f471cbSchristos {
11635f471cbSchristos int c, retc;
1178eaba782Schristos char *buf = *pbuf;
11835f471cbSchristos int sz = *psz;
1198eaba782Schristos char *bp = buf;
12035f471cbSchristos
12135f471cbSchristos c = input();
12235f471cbSchristos if (c == 0)
12335f471cbSchristos return 0;
12435f471cbSchristos buf[0] = c;
12535f471cbSchristos buf[1] = 0;
12635f471cbSchristos if (!isalnum(c) && c != '.' && c != '_')
12735f471cbSchristos return c;
12835f471cbSchristos
12935f471cbSchristos *bp++ = c;
13035f471cbSchristos if (isalpha(c) || c == '_') { /* it's a varname */
13135f471cbSchristos for ( ; (c = input()) != 0; ) {
13235f471cbSchristos if (bp-buf >= sz)
13335f471cbSchristos if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
13435f471cbSchristos FATAL( "out of space for name %.10s...", buf );
13535f471cbSchristos if (isalnum(c) || c == '_')
13635f471cbSchristos *bp++ = c;
13735f471cbSchristos else {
13835f471cbSchristos *bp = 0;
13935f471cbSchristos unput(c);
14035f471cbSchristos break;
14135f471cbSchristos }
14235f471cbSchristos }
14335f471cbSchristos *bp = 0;
14435f471cbSchristos retc = 'a'; /* alphanumeric */
14535f471cbSchristos } else { /* maybe it's a number, but could be . */
14635f471cbSchristos char *rem;
14735f471cbSchristos /* read input until can't be a number */
14835f471cbSchristos for ( ; (c = input()) != 0; ) {
14935f471cbSchristos if (bp-buf >= sz)
15035f471cbSchristos if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
15135f471cbSchristos FATAL( "out of space for number %.10s...", buf );
15235f471cbSchristos if (isdigit(c) || c == 'e' || c == 'E'
15335f471cbSchristos || c == '.' || c == '+' || c == '-')
15435f471cbSchristos *bp++ = c;
15535f471cbSchristos else {
15635f471cbSchristos unput(c);
15735f471cbSchristos break;
15835f471cbSchristos }
15935f471cbSchristos }
16035f471cbSchristos *bp = 0;
16135f471cbSchristos strtod(buf, &rem); /* parse the number */
1628eaba782Schristos if (rem == buf) { /* it wasn't a valid number at all */
16335f471cbSchristos buf[1] = 0; /* return one character as token */
16435f471cbSchristos retc = buf[0]; /* character is its own type */
16535f471cbSchristos unputstr(rem+1); /* put rest back for later */
16635f471cbSchristos } else { /* some prefix was a number */
16735f471cbSchristos unputstr(rem); /* put rest back for later */
16835f471cbSchristos rem[0] = 0; /* truncate buf after number part */
16935f471cbSchristos retc = '0'; /* type is number */
17035f471cbSchristos }
17135f471cbSchristos }
17235f471cbSchristos *pbuf = buf;
17335f471cbSchristos *psz = sz;
17435f471cbSchristos return retc;
17535f471cbSchristos }
17635f471cbSchristos
17735f471cbSchristos int word(char *);
17835f471cbSchristos int string(void);
17935f471cbSchristos int regexpr(void);
1808eaba782Schristos bool sc = false; /* true => return a } right now */
1818eaba782Schristos bool reg = false; /* true => return a REGEXPR now */
18235f471cbSchristos
yylex(void)18335f471cbSchristos int yylex(void)
18435f471cbSchristos {
18535f471cbSchristos int c;
1868eaba782Schristos static char *buf = NULL;
18735f471cbSchristos static int bufsize = 5; /* BUG: setting this small causes core dump! */
18835f471cbSchristos
1898eaba782Schristos if (buf == NULL && (buf = malloc(bufsize)) == NULL)
19035f471cbSchristos FATAL( "out of space in yylex" );
19135f471cbSchristos if (sc) {
1928eaba782Schristos sc = false;
19335f471cbSchristos RET('}');
19435f471cbSchristos }
19535f471cbSchristos if (reg) {
1968eaba782Schristos reg = false;
19735f471cbSchristos return regexpr();
19835f471cbSchristos }
19935f471cbSchristos for (;;) {
20035f471cbSchristos c = gettok(&buf, &bufsize);
20135f471cbSchristos if (c == 0)
20235f471cbSchristos return 0;
20335f471cbSchristos if (isalpha(c) || c == '_')
20435f471cbSchristos return word(buf);
20535f471cbSchristos if (isdigit(c)) {
2068eaba782Schristos char *cp = tostring(buf);
2078eaba782Schristos yylval.cp = setsymtab(buf, cp, atof(buf), CON|NUM, symtab);
2088eaba782Schristos free(cp);
20935f471cbSchristos /* should this also have STR set? */
21035f471cbSchristos RET(NUMBER);
21135f471cbSchristos }
21235f471cbSchristos
21335f471cbSchristos yylval.i = c;
21435f471cbSchristos switch (c) {
21535f471cbSchristos case '\n': /* {EOL} */
2168eaba782Schristos lineno++;
21735f471cbSchristos RET(NL);
21835f471cbSchristos case '\r': /* assume \n is coming */
21935f471cbSchristos case ' ': /* {WS}+ */
22035f471cbSchristos case '\t':
22135f471cbSchristos break;
22235f471cbSchristos case '#': /* #.* strip comments */
22335f471cbSchristos while ((c = input()) != '\n' && c != 0)
22435f471cbSchristos ;
22535f471cbSchristos unput(c);
2268eaba782Schristos /*
2278eaba782Schristos * Next line is a hack, itcompensates for
2288eaba782Schristos * unput's treatment of \n.
2298eaba782Schristos */
2308eaba782Schristos lineno++;
23135f471cbSchristos break;
23235f471cbSchristos case ';':
23335f471cbSchristos RET(';');
23435f471cbSchristos case '\\':
23535f471cbSchristos if (peek() == '\n') {
23635f471cbSchristos input();
2378eaba782Schristos lineno++;
23835f471cbSchristos } else if (peek() == '\r') {
23935f471cbSchristos input(); input(); /* \n */
24035f471cbSchristos lineno++;
24135f471cbSchristos } else {
24235f471cbSchristos RET(c);
24335f471cbSchristos }
24435f471cbSchristos break;
24535f471cbSchristos case '&':
24635f471cbSchristos if (peek() == '&') {
24735f471cbSchristos input(); RET(AND);
24835f471cbSchristos } else
24935f471cbSchristos RET('&');
25035f471cbSchristos case '|':
25135f471cbSchristos if (peek() == '|') {
25235f471cbSchristos input(); RET(BOR);
25335f471cbSchristos } else
25435f471cbSchristos RET('|');
25535f471cbSchristos case '!':
25635f471cbSchristos if (peek() == '=') {
25735f471cbSchristos input(); yylval.i = NE; RET(NE);
25835f471cbSchristos } else if (peek() == '~') {
25935f471cbSchristos input(); yylval.i = NOTMATCH; RET(MATCHOP);
26035f471cbSchristos } else
26135f471cbSchristos RET(NOT);
26235f471cbSchristos case '~':
26335f471cbSchristos yylval.i = MATCH;
26435f471cbSchristos RET(MATCHOP);
26535f471cbSchristos case '<':
26635f471cbSchristos if (peek() == '=') {
26735f471cbSchristos input(); yylval.i = LE; RET(LE);
26835f471cbSchristos } else {
26935f471cbSchristos yylval.i = LT; RET(LT);
27035f471cbSchristos }
27135f471cbSchristos case '=':
27235f471cbSchristos if (peek() == '=') {
27335f471cbSchristos input(); yylval.i = EQ; RET(EQ);
27435f471cbSchristos } else {
27535f471cbSchristos yylval.i = ASSIGN; RET(ASGNOP);
27635f471cbSchristos }
27735f471cbSchristos case '>':
27835f471cbSchristos if (peek() == '=') {
27935f471cbSchristos input(); yylval.i = GE; RET(GE);
28035f471cbSchristos } else if (peek() == '>') {
28135f471cbSchristos input(); yylval.i = APPEND; RET(APPEND);
28235f471cbSchristos } else {
28335f471cbSchristos yylval.i = GT; RET(GT);
28435f471cbSchristos }
28535f471cbSchristos case '+':
28635f471cbSchristos if (peek() == '+') {
28735f471cbSchristos input(); yylval.i = INCR; RET(INCR);
28835f471cbSchristos } else if (peek() == '=') {
28935f471cbSchristos input(); yylval.i = ADDEQ; RET(ASGNOP);
29035f471cbSchristos } else
29135f471cbSchristos RET('+');
29235f471cbSchristos case '-':
29335f471cbSchristos if (peek() == '-') {
29435f471cbSchristos input(); yylval.i = DECR; RET(DECR);
29535f471cbSchristos } else if (peek() == '=') {
29635f471cbSchristos input(); yylval.i = SUBEQ; RET(ASGNOP);
29735f471cbSchristos } else
29835f471cbSchristos RET('-');
29935f471cbSchristos case '*':
30035f471cbSchristos if (peek() == '=') { /* *= */
30135f471cbSchristos input(); yylval.i = MULTEQ; RET(ASGNOP);
30235f471cbSchristos } else if (peek() == '*') { /* ** or **= */
30335f471cbSchristos input(); /* eat 2nd * */
30435f471cbSchristos if (peek() == '=') {
30535f471cbSchristos input(); yylval.i = POWEQ; RET(ASGNOP);
30635f471cbSchristos } else {
30735f471cbSchristos RET(POWER);
30835f471cbSchristos }
30935f471cbSchristos } else
31035f471cbSchristos RET('*');
31135f471cbSchristos case '/':
31235f471cbSchristos RET('/');
31335f471cbSchristos case '%':
31435f471cbSchristos if (peek() == '=') {
31535f471cbSchristos input(); yylval.i = MODEQ; RET(ASGNOP);
31635f471cbSchristos } else
31735f471cbSchristos RET('%');
31835f471cbSchristos case '^':
31935f471cbSchristos if (peek() == '=') {
32035f471cbSchristos input(); yylval.i = POWEQ; RET(ASGNOP);
32135f471cbSchristos } else
32235f471cbSchristos RET(POWER);
32335f471cbSchristos
32435f471cbSchristos case '$':
32535f471cbSchristos /* BUG: awkward, if not wrong */
32635f471cbSchristos c = gettok(&buf, &bufsize);
32735f471cbSchristos if (isalpha(c)) {
32835f471cbSchristos if (strcmp(buf, "NF") == 0) { /* very special */
32935f471cbSchristos unputstr("(NF)");
33035f471cbSchristos RET(INDIRECT);
33135f471cbSchristos }
33235f471cbSchristos c = peek();
33335f471cbSchristos if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
33435f471cbSchristos unputstr(buf);
33535f471cbSchristos RET(INDIRECT);
33635f471cbSchristos }
33735f471cbSchristos yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
33835f471cbSchristos RET(IVAR);
33935f471cbSchristos } else if (c == 0) { /* */
34035f471cbSchristos SYNTAX( "unexpected end of input after $" );
34135f471cbSchristos RET(';');
34235f471cbSchristos } else {
34335f471cbSchristos unputstr(buf);
34435f471cbSchristos RET(INDIRECT);
34535f471cbSchristos }
34635f471cbSchristos
34735f471cbSchristos case '}':
34835f471cbSchristos if (--bracecnt < 0)
34935f471cbSchristos SYNTAX( "extra }" );
3508eaba782Schristos sc = true;
35135f471cbSchristos RET(';');
35235f471cbSchristos case ']':
35335f471cbSchristos if (--brackcnt < 0)
35435f471cbSchristos SYNTAX( "extra ]" );
35535f471cbSchristos RET(']');
35635f471cbSchristos case ')':
35735f471cbSchristos if (--parencnt < 0)
35835f471cbSchristos SYNTAX( "extra )" );
35935f471cbSchristos RET(')');
36035f471cbSchristos case '{':
36135f471cbSchristos bracecnt++;
36235f471cbSchristos RET('{');
36335f471cbSchristos case '[':
36435f471cbSchristos brackcnt++;
36535f471cbSchristos RET('[');
36635f471cbSchristos case '(':
36735f471cbSchristos parencnt++;
36835f471cbSchristos RET('(');
36935f471cbSchristos
37035f471cbSchristos case '"':
37135f471cbSchristos return string(); /* BUG: should be like tran.c ? */
37235f471cbSchristos
37335f471cbSchristos default:
37435f471cbSchristos RET(c);
37535f471cbSchristos }
37635f471cbSchristos }
37735f471cbSchristos }
37835f471cbSchristos
string(void)37935f471cbSchristos int string(void)
38035f471cbSchristos {
38135f471cbSchristos int c, n;
3828eaba782Schristos char *s, *bp;
3838eaba782Schristos static char *buf = NULL;
38435f471cbSchristos static int bufsz = 500;
38535f471cbSchristos
3868eaba782Schristos if (buf == NULL && (buf = malloc(bufsz)) == NULL)
38735f471cbSchristos FATAL("out of space for strings");
38835f471cbSchristos for (bp = buf; (c = input()) != '"'; ) {
38935f471cbSchristos if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
39035f471cbSchristos FATAL("out of space for string %.10s...", buf);
39135f471cbSchristos switch (c) {
39235f471cbSchristos case '\n':
39335f471cbSchristos case '\r':
39435f471cbSchristos case 0:
3958eaba782Schristos *bp = '\0';
39635f471cbSchristos SYNTAX( "non-terminated string %.10s...", buf );
39735f471cbSchristos if (c == 0) /* hopeless */
39835f471cbSchristos FATAL( "giving up" );
3998eaba782Schristos lineno++;
40035f471cbSchristos break;
40135f471cbSchristos case '\\':
40235f471cbSchristos c = input();
40335f471cbSchristos switch (c) {
404*e66db18eSchristos case '\n': break;
40535f471cbSchristos case '"': *bp++ = '"'; break;
40635f471cbSchristos case 'n': *bp++ = '\n'; break;
40735f471cbSchristos case 't': *bp++ = '\t'; break;
40835f471cbSchristos case 'f': *bp++ = '\f'; break;
40935f471cbSchristos case 'r': *bp++ = '\r'; break;
41035f471cbSchristos case 'b': *bp++ = '\b'; break;
41135f471cbSchristos case 'v': *bp++ = '\v'; break;
4128eaba782Schristos case 'a': *bp++ = '\a'; break;
41335f471cbSchristos case '\\': *bp++ = '\\'; break;
41435f471cbSchristos
41535f471cbSchristos case '0': case '1': case '2': /* octal: \d \dd \ddd */
41635f471cbSchristos case '3': case '4': case '5': case '6': case '7':
41735f471cbSchristos n = c - '0';
41835f471cbSchristos if ((c = peek()) >= '0' && c < '8') {
41935f471cbSchristos n = 8 * n + input() - '0';
42035f471cbSchristos if ((c = peek()) >= '0' && c < '8')
42135f471cbSchristos n = 8 * n + input() - '0';
42235f471cbSchristos }
42335f471cbSchristos *bp++ = n;
42435f471cbSchristos break;
42535f471cbSchristos
42635f471cbSchristos case 'x': /* hex \x0-9a-fA-F + */
42735f471cbSchristos { char xbuf[100], *px;
42835f471cbSchristos for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
42935f471cbSchristos if (isdigit(c)
43035f471cbSchristos || (c >= 'a' && c <= 'f')
43135f471cbSchristos || (c >= 'A' && c <= 'F'))
43235f471cbSchristos *px++ = c;
43335f471cbSchristos else
43435f471cbSchristos break;
43535f471cbSchristos }
43635f471cbSchristos *px = 0;
43735f471cbSchristos unput(c);
4388eaba782Schristos sscanf(xbuf, "%x", (unsigned int *) &n);
43935f471cbSchristos *bp++ = n;
44035f471cbSchristos break;
44135f471cbSchristos }
44235f471cbSchristos
44335f471cbSchristos default:
44435f471cbSchristos *bp++ = c;
44535f471cbSchristos break;
44635f471cbSchristos }
44735f471cbSchristos break;
44835f471cbSchristos default:
44935f471cbSchristos *bp++ = c;
45035f471cbSchristos break;
45135f471cbSchristos }
45235f471cbSchristos }
45335f471cbSchristos *bp = 0;
45435f471cbSchristos s = tostring(buf);
4558eaba782Schristos *bp++ = ' '; *bp++ = '\0';
45635f471cbSchristos yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
4578eaba782Schristos free(s);
45835f471cbSchristos RET(STRING);
45935f471cbSchristos }
46035f471cbSchristos
46135f471cbSchristos
binsearch(char * w,const Keyword * kp,int n)4628eaba782Schristos static int binsearch(char *w, const Keyword *kp, int n)
46335f471cbSchristos {
46435f471cbSchristos int cond, low, mid, high;
46535f471cbSchristos
46635f471cbSchristos low = 0;
46735f471cbSchristos high = n - 1;
46835f471cbSchristos while (low <= high) {
46935f471cbSchristos mid = (low + high) / 2;
47035f471cbSchristos if ((cond = strcmp(w, kp[mid].word)) < 0)
47135f471cbSchristos high = mid - 1;
47235f471cbSchristos else if (cond > 0)
47335f471cbSchristos low = mid + 1;
47435f471cbSchristos else
47535f471cbSchristos return mid;
47635f471cbSchristos }
47735f471cbSchristos return -1;
47835f471cbSchristos }
47935f471cbSchristos
word(char * w)48035f471cbSchristos int word(char *w)
48135f471cbSchristos {
4825642d004Schristos const Keyword *kp;
48335f471cbSchristos int c, n;
48435f471cbSchristos
48535f471cbSchristos n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
48635f471cbSchristos if (n != -1) { /* found in table */
48708f0f4e6Skamil kp = keywords + n;
48835f471cbSchristos yylval.i = kp->sub;
48935f471cbSchristos switch (kp->type) { /* special handling */
49035f471cbSchristos case BLTIN:
49135f471cbSchristos if (kp->sub == FSYSTEM && safe)
49235f471cbSchristos SYNTAX( "system is unsafe" );
49335f471cbSchristos RET(kp->type);
49435f471cbSchristos case FUNC:
49535f471cbSchristos if (infunc)
49635f471cbSchristos SYNTAX( "illegal nested function" );
49735f471cbSchristos RET(kp->type);
49835f471cbSchristos case RETURN:
49935f471cbSchristos if (!infunc)
50035f471cbSchristos SYNTAX( "return not in function" );
50135f471cbSchristos RET(kp->type);
50235f471cbSchristos case VARNF:
50335f471cbSchristos yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
50435f471cbSchristos RET(VARNF);
50535f471cbSchristos default:
50635f471cbSchristos RET(kp->type);
50735f471cbSchristos }
50835f471cbSchristos }
50935f471cbSchristos c = peek(); /* look for '(' */
51035f471cbSchristos if (c != '(' && infunc && (n=isarg(w)) >= 0) {
51135f471cbSchristos yylval.i = n;
51235f471cbSchristos RET(ARG);
51335f471cbSchristos } else {
51435f471cbSchristos yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
51535f471cbSchristos if (c == '(') {
51635f471cbSchristos RET(CALL);
51735f471cbSchristos } else {
51835f471cbSchristos RET(VAR);
51935f471cbSchristos }
52035f471cbSchristos }
52135f471cbSchristos }
52235f471cbSchristos
startreg(void)52335f471cbSchristos void startreg(void) /* next call to yylex will return a regular expression */
52435f471cbSchristos {
5258eaba782Schristos reg = true;
52635f471cbSchristos }
52735f471cbSchristos
regexpr(void)52835f471cbSchristos int regexpr(void)
52935f471cbSchristos {
53035f471cbSchristos int c;
5318eaba782Schristos static char *buf = NULL;
53235f471cbSchristos static int bufsz = 500;
5338eaba782Schristos char *bp;
53435f471cbSchristos
5358eaba782Schristos if (buf == NULL && (buf = malloc(bufsz)) == NULL)
53635f471cbSchristos FATAL("out of space for rex expr");
53735f471cbSchristos bp = buf;
53835f471cbSchristos for ( ; (c = input()) != '/' && c != 0; ) {
53935f471cbSchristos if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
54035f471cbSchristos FATAL("out of space for reg expr %.10s...", buf);
54135f471cbSchristos if (c == '\n') {
5428eaba782Schristos *bp = '\0';
54335f471cbSchristos SYNTAX( "newline in regular expression %.10s...", buf );
54435f471cbSchristos unput('\n');
54535f471cbSchristos break;
54635f471cbSchristos } else if (c == '\\') {
54735f471cbSchristos *bp++ = '\\';
54835f471cbSchristos *bp++ = input();
54935f471cbSchristos } else {
55035f471cbSchristos *bp++ = c;
55135f471cbSchristos }
55235f471cbSchristos }
55335f471cbSchristos *bp = 0;
55435f471cbSchristos if (c == 0)
55535f471cbSchristos SYNTAX("non-terminated regular expression %.10s...", buf);
55635f471cbSchristos yylval.s = tostring(buf);
55735f471cbSchristos unput('/');
55835f471cbSchristos RET(REGEXPR);
55935f471cbSchristos }
56035f471cbSchristos
56135f471cbSchristos /* low-level lexical stuff, sort of inherited from lex */
56235f471cbSchristos
56335f471cbSchristos char ebuf[300];
56435f471cbSchristos char *ep = ebuf;
56535f471cbSchristos char yysbuf[100]; /* pushback buffer */
56635f471cbSchristos char *yysptr = yysbuf;
5678eaba782Schristos FILE *yyin = NULL;
56835f471cbSchristos
input(void)56935f471cbSchristos int input(void) /* get next lexical input character */
57035f471cbSchristos {
57135f471cbSchristos int c;
57235f471cbSchristos extern char *lexprog;
57335f471cbSchristos
57435f471cbSchristos if (yysptr > yysbuf)
57535f471cbSchristos c = (uschar)*--yysptr;
57635f471cbSchristos else if (lexprog != NULL) { /* awk '...' */
57735f471cbSchristos if ((c = (uschar)*lexprog) != 0)
57835f471cbSchristos lexprog++;
57935f471cbSchristos } else /* awk -f ... */
58035f471cbSchristos c = pgetc();
5818eaba782Schristos if (c == EOF)
58235f471cbSchristos c = 0;
58335f471cbSchristos if (ep >= ebuf + sizeof ebuf)
58435f471cbSchristos ep = ebuf;
5858eaba782Schristos *ep = c;
5868eaba782Schristos if (c != 0) {
5878eaba782Schristos ep++;
5888eaba782Schristos }
5898eaba782Schristos return (c);
59035f471cbSchristos }
59135f471cbSchristos
unput(int c)59235f471cbSchristos void unput(int c) /* put lexical character back on input */
59335f471cbSchristos {
59435f471cbSchristos if (c == '\n')
59535f471cbSchristos lineno--;
59635f471cbSchristos if (yysptr >= yysbuf + sizeof(yysbuf))
59735f471cbSchristos FATAL("pushed back too much: %.20s...", yysbuf);
59835f471cbSchristos *yysptr++ = c;
59935f471cbSchristos if (--ep < ebuf)
60035f471cbSchristos ep = ebuf + sizeof(ebuf) - 1;
60135f471cbSchristos }
60235f471cbSchristos
unputstr(const char * s)60335f471cbSchristos void unputstr(const char *s) /* put a string back on input */
60435f471cbSchristos {
60535f471cbSchristos int i;
60635f471cbSchristos
60735f471cbSchristos for (i = strlen(s)-1; i >= 0; i--)
60835f471cbSchristos unput(s[i]);
60935f471cbSchristos }
610