17dd7cddfSDavid du Colombier /****************************************************************
27dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997
37dd7cddfSDavid du Colombier All Rights Reserved
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and
67dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby
77dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all
87dd7cddfSDavid du Colombier copies and that both that the copyright notice and this
97dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting
107dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of
117dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining
127dd7cddfSDavid du Colombier to distribution of the software without specific, written prior
137dd7cddfSDavid du Colombier permission.
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
167dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
177dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
187dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
197dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
207dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
217dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
227dd7cddfSDavid du Colombier THIS SOFTWARE.
237dd7cddfSDavid du Colombier ****************************************************************/
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier #include <stdio.h>
267dd7cddfSDavid du Colombier #include <stdlib.h>
277dd7cddfSDavid du Colombier #include <string.h>
287dd7cddfSDavid du Colombier #include <ctype.h>
297dd7cddfSDavid du Colombier #include "awk.h"
307dd7cddfSDavid du Colombier #include "y.tab.h"
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier extern YYSTYPE yylval;
337dd7cddfSDavid du Colombier extern int infunc;
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier int lineno = 1;
367dd7cddfSDavid du Colombier int bracecnt = 0;
377dd7cddfSDavid du Colombier int brackcnt = 0;
387dd7cddfSDavid du Colombier int parencnt = 0;
397dd7cddfSDavid du Colombier
407dd7cddfSDavid du Colombier typedef struct Keyword {
41*a2c41696SDavid du Colombier const char *word;
427dd7cddfSDavid du Colombier int sub;
437dd7cddfSDavid du Colombier int type;
447dd7cddfSDavid du Colombier } Keyword;
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier Keyword keywords[] ={ /* keep sorted: binary searched */
477dd7cddfSDavid du Colombier { "BEGIN", XBEGIN, XBEGIN },
487dd7cddfSDavid du Colombier { "END", XEND, XEND },
497dd7cddfSDavid du Colombier { "NF", VARNF, VARNF },
507dd7cddfSDavid du Colombier { "atan2", FATAN, BLTIN },
517dd7cddfSDavid du Colombier { "break", BREAK, BREAK },
527dd7cddfSDavid du Colombier { "close", CLOSE, CLOSE },
537dd7cddfSDavid du Colombier { "continue", CONTINUE, CONTINUE },
547dd7cddfSDavid du Colombier { "cos", FCOS, BLTIN },
557dd7cddfSDavid du Colombier { "delete", DELETE, DELETE },
567dd7cddfSDavid du Colombier { "do", DO, DO },
577dd7cddfSDavid du Colombier { "else", ELSE, ELSE },
587dd7cddfSDavid du Colombier { "exit", EXIT, EXIT },
597dd7cddfSDavid du Colombier { "exp", FEXP, BLTIN },
607dd7cddfSDavid du Colombier { "fflush", FFLUSH, BLTIN },
617dd7cddfSDavid du Colombier { "for", FOR, FOR },
627dd7cddfSDavid du Colombier { "func", FUNC, FUNC },
637dd7cddfSDavid du Colombier { "function", FUNC, FUNC },
647dd7cddfSDavid du Colombier { "getline", GETLINE, GETLINE },
657dd7cddfSDavid du Colombier { "gsub", GSUB, GSUB },
667dd7cddfSDavid du Colombier { "if", IF, IF },
677dd7cddfSDavid du Colombier { "in", IN, IN },
687dd7cddfSDavid du Colombier { "index", INDEX, INDEX },
697dd7cddfSDavid du Colombier { "int", FINT, BLTIN },
707dd7cddfSDavid du Colombier { "length", FLENGTH, BLTIN },
717dd7cddfSDavid du Colombier { "log", FLOG, BLTIN },
727dd7cddfSDavid du Colombier { "match", MATCHFCN, MATCHFCN },
737dd7cddfSDavid du Colombier { "next", NEXT, NEXT },
747dd7cddfSDavid du Colombier { "nextfile", NEXTFILE, NEXTFILE },
757dd7cddfSDavid du Colombier { "print", PRINT, PRINT },
767dd7cddfSDavid du Colombier { "printf", PRINTF, PRINTF },
777dd7cddfSDavid du Colombier { "rand", FRAND, BLTIN },
787dd7cddfSDavid du Colombier { "return", RETURN, RETURN },
797dd7cddfSDavid du Colombier { "sin", FSIN, BLTIN },
807dd7cddfSDavid du Colombier { "split", SPLIT, SPLIT },
817dd7cddfSDavid du Colombier { "sprintf", SPRINTF, SPRINTF },
827dd7cddfSDavid du Colombier { "sqrt", FSQRT, BLTIN },
837dd7cddfSDavid du Colombier { "srand", FSRAND, BLTIN },
847dd7cddfSDavid du Colombier { "sub", SUB, SUB },
857dd7cddfSDavid du Colombier { "substr", SUBSTR, SUBSTR },
867dd7cddfSDavid du Colombier { "system", FSYSTEM, BLTIN },
877dd7cddfSDavid du Colombier { "tolower", FTOLOWER, BLTIN },
887dd7cddfSDavid du Colombier { "toupper", FTOUPPER, BLTIN },
897dd7cddfSDavid du Colombier { "utf", FUTF, BLTIN },
9076f6a3b8SDavid du Colombier { "while", WHILE, WHILE },
917dd7cddfSDavid du Colombier };
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier #define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); }
947dd7cddfSDavid du Colombier
peek(void)957dd7cddfSDavid du Colombier int peek(void)
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier int c = input();
987dd7cddfSDavid du Colombier unput(c);
997dd7cddfSDavid du Colombier return c;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier
gettok(char ** pbuf,int * psz)1027dd7cddfSDavid du Colombier int gettok(char **pbuf, int *psz) /* get next input token */
1037dd7cddfSDavid du Colombier {
104*a2c41696SDavid du Colombier int c, retc;
1057dd7cddfSDavid du Colombier char *buf = *pbuf;
1067dd7cddfSDavid du Colombier int sz = *psz;
1077dd7cddfSDavid du Colombier char *bp = buf;
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier c = input();
1107dd7cddfSDavid du Colombier if (c == 0)
1117dd7cddfSDavid du Colombier return 0;
1127dd7cddfSDavid du Colombier buf[0] = c;
1137dd7cddfSDavid du Colombier buf[1] = 0;
1147dd7cddfSDavid du Colombier if (!isalnum(c) && c != '.' && c != '_')
1157dd7cddfSDavid du Colombier return c;
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier *bp++ = c;
1187dd7cddfSDavid du Colombier if (isalpha(c) || c == '_') { /* it's a varname */
1197dd7cddfSDavid du Colombier for ( ; (c = input()) != 0; ) {
1207dd7cddfSDavid du Colombier if (bp-buf >= sz)
121*a2c41696SDavid du Colombier if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
1227dd7cddfSDavid du Colombier FATAL( "out of space for name %.10s...", buf );
1237dd7cddfSDavid du Colombier if (isalnum(c) || c == '_')
1247dd7cddfSDavid du Colombier *bp++ = c;
1257dd7cddfSDavid du Colombier else {
1267dd7cddfSDavid du Colombier *bp = 0;
1277dd7cddfSDavid du Colombier unput(c);
1287dd7cddfSDavid du Colombier break;
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier }
131*a2c41696SDavid du Colombier *bp = 0;
132*a2c41696SDavid du Colombier retc = 'a'; /* alphanumeric */
133*a2c41696SDavid du Colombier } else { /* maybe it's a number, but could be . */
1347dd7cddfSDavid du Colombier char *rem;
1357dd7cddfSDavid du Colombier /* read input until can't be a number */
1367dd7cddfSDavid du Colombier for ( ; (c = input()) != 0; ) {
1377dd7cddfSDavid du Colombier if (bp-buf >= sz)
138*a2c41696SDavid du Colombier if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
1397dd7cddfSDavid du Colombier FATAL( "out of space for number %.10s...", buf );
1407dd7cddfSDavid du Colombier if (isdigit(c) || c == 'e' || c == 'E'
1417dd7cddfSDavid du Colombier || c == '.' || c == '+' || c == '-')
1427dd7cddfSDavid du Colombier *bp++ = c;
1437dd7cddfSDavid du Colombier else {
1447dd7cddfSDavid du Colombier unput(c);
1457dd7cddfSDavid du Colombier break;
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier *bp = 0;
1497dd7cddfSDavid du Colombier strtod(buf, &rem); /* parse the number */
150*a2c41696SDavid du Colombier if (rem == buf) { /* it wasn't a valid number at all */
151*a2c41696SDavid du Colombier buf[1] = 0; /* return one character as token */
152*a2c41696SDavid du Colombier retc = buf[0]; /* character is its own type */
153*a2c41696SDavid du Colombier unputstr(rem+1); /* put rest back for later */
154*a2c41696SDavid du Colombier } else { /* some prefix was a number */
1557dd7cddfSDavid du Colombier unputstr(rem); /* put rest back for later */
156*a2c41696SDavid du Colombier rem[0] = 0; /* truncate buf after number part */
157*a2c41696SDavid du Colombier retc = '0'; /* type is number */
158*a2c41696SDavid du Colombier }
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier *pbuf = buf;
1617dd7cddfSDavid du Colombier *psz = sz;
162*a2c41696SDavid du Colombier return retc;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier int word(char *);
1667dd7cddfSDavid du Colombier int string(void);
1677dd7cddfSDavid du Colombier int regexpr(void);
1687dd7cddfSDavid du Colombier int sc = 0; /* 1 => return a } right now */
1697dd7cddfSDavid du Colombier int reg = 0; /* 1 => return a REGEXPR now */
1707dd7cddfSDavid du Colombier
yylex(void)1717dd7cddfSDavid du Colombier int yylex(void)
1727dd7cddfSDavid du Colombier {
1737dd7cddfSDavid du Colombier int c;
1747dd7cddfSDavid du Colombier static char *buf = 0;
175*a2c41696SDavid du Colombier static int bufsize = 5; /* BUG: setting this small causes core dump! */
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
1787dd7cddfSDavid du Colombier FATAL( "out of space in yylex" );
1797dd7cddfSDavid du Colombier if (sc) {
1807dd7cddfSDavid du Colombier sc = 0;
1817dd7cddfSDavid du Colombier RET('}');
1827dd7cddfSDavid du Colombier }
1837dd7cddfSDavid du Colombier if (reg) {
1847dd7cddfSDavid du Colombier reg = 0;
1857dd7cddfSDavid du Colombier return regexpr();
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier for (;;) {
1887dd7cddfSDavid du Colombier c = gettok(&buf, &bufsize);
1897dd7cddfSDavid du Colombier if (c == 0)
1907dd7cddfSDavid du Colombier return 0;
1917dd7cddfSDavid du Colombier if (isalpha(c) || c == '_')
1927dd7cddfSDavid du Colombier return word(buf);
193*a2c41696SDavid du Colombier if (isdigit(c)) {
1947dd7cddfSDavid du Colombier yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
1957dd7cddfSDavid du Colombier /* should this also have STR set? */
1967dd7cddfSDavid du Colombier RET(NUMBER);
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier
1997dd7cddfSDavid du Colombier yylval.i = c;
2007dd7cddfSDavid du Colombier switch (c) {
2017dd7cddfSDavid du Colombier case '\n': /* {EOL} */
2027dd7cddfSDavid du Colombier RET(NL);
2037dd7cddfSDavid du Colombier case '\r': /* assume \n is coming */
2047dd7cddfSDavid du Colombier case ' ': /* {WS}+ */
2057dd7cddfSDavid du Colombier case '\t':
2067dd7cddfSDavid du Colombier break;
2077dd7cddfSDavid du Colombier case '#': /* #.* strip comments */
2087dd7cddfSDavid du Colombier while ((c = input()) != '\n' && c != 0)
2097dd7cddfSDavid du Colombier ;
2107dd7cddfSDavid du Colombier unput(c);
2117dd7cddfSDavid du Colombier break;
2127dd7cddfSDavid du Colombier case ';':
2137dd7cddfSDavid du Colombier RET(';');
2147dd7cddfSDavid du Colombier case '\\':
2157dd7cddfSDavid du Colombier if (peek() == '\n') {
2167dd7cddfSDavid du Colombier input();
2177dd7cddfSDavid du Colombier } else if (peek() == '\r') {
2187dd7cddfSDavid du Colombier input(); input(); /* \n */
2197dd7cddfSDavid du Colombier lineno++;
2207dd7cddfSDavid du Colombier } else {
2217dd7cddfSDavid du Colombier RET(c);
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier break;
2247dd7cddfSDavid du Colombier case '&':
2257dd7cddfSDavid du Colombier if (peek() == '&') {
2267dd7cddfSDavid du Colombier input(); RET(AND);
2277dd7cddfSDavid du Colombier } else
2287dd7cddfSDavid du Colombier RET('&');
2297dd7cddfSDavid du Colombier case '|':
2307dd7cddfSDavid du Colombier if (peek() == '|') {
2317dd7cddfSDavid du Colombier input(); RET(BOR);
2327dd7cddfSDavid du Colombier } else
2337dd7cddfSDavid du Colombier RET('|');
2347dd7cddfSDavid du Colombier case '!':
2357dd7cddfSDavid du Colombier if (peek() == '=') {
2367dd7cddfSDavid du Colombier input(); yylval.i = NE; RET(NE);
2377dd7cddfSDavid du Colombier } else if (peek() == '~') {
2387dd7cddfSDavid du Colombier input(); yylval.i = NOTMATCH; RET(MATCHOP);
2397dd7cddfSDavid du Colombier } else
2407dd7cddfSDavid du Colombier RET(NOT);
2417dd7cddfSDavid du Colombier case '~':
2427dd7cddfSDavid du Colombier yylval.i = MATCH;
2437dd7cddfSDavid du Colombier RET(MATCHOP);
2447dd7cddfSDavid du Colombier case '<':
2457dd7cddfSDavid du Colombier if (peek() == '=') {
2467dd7cddfSDavid du Colombier input(); yylval.i = LE; RET(LE);
2477dd7cddfSDavid du Colombier } else {
2487dd7cddfSDavid du Colombier yylval.i = LT; RET(LT);
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier case '=':
2517dd7cddfSDavid du Colombier if (peek() == '=') {
2527dd7cddfSDavid du Colombier input(); yylval.i = EQ; RET(EQ);
2537dd7cddfSDavid du Colombier } else {
2547dd7cddfSDavid du Colombier yylval.i = ASSIGN; RET(ASGNOP);
2557dd7cddfSDavid du Colombier }
2567dd7cddfSDavid du Colombier case '>':
2577dd7cddfSDavid du Colombier if (peek() == '=') {
2587dd7cddfSDavid du Colombier input(); yylval.i = GE; RET(GE);
2597dd7cddfSDavid du Colombier } else if (peek() == '>') {
2607dd7cddfSDavid du Colombier input(); yylval.i = APPEND; RET(APPEND);
2617dd7cddfSDavid du Colombier } else {
2627dd7cddfSDavid du Colombier yylval.i = GT; RET(GT);
2637dd7cddfSDavid du Colombier }
2647dd7cddfSDavid du Colombier case '+':
2657dd7cddfSDavid du Colombier if (peek() == '+') {
2667dd7cddfSDavid du Colombier input(); yylval.i = INCR; RET(INCR);
2677dd7cddfSDavid du Colombier } else if (peek() == '=') {
2687dd7cddfSDavid du Colombier input(); yylval.i = ADDEQ; RET(ASGNOP);
2697dd7cddfSDavid du Colombier } else
2707dd7cddfSDavid du Colombier RET('+');
2717dd7cddfSDavid du Colombier case '-':
2727dd7cddfSDavid du Colombier if (peek() == '-') {
2737dd7cddfSDavid du Colombier input(); yylval.i = DECR; RET(DECR);
2747dd7cddfSDavid du Colombier } else if (peek() == '=') {
2757dd7cddfSDavid du Colombier input(); yylval.i = SUBEQ; RET(ASGNOP);
2767dd7cddfSDavid du Colombier } else
2777dd7cddfSDavid du Colombier RET('-');
2787dd7cddfSDavid du Colombier case '*':
2797dd7cddfSDavid du Colombier if (peek() == '=') { /* *= */
2807dd7cddfSDavid du Colombier input(); yylval.i = MULTEQ; RET(ASGNOP);
2817dd7cddfSDavid du Colombier } else if (peek() == '*') { /* ** or **= */
2827dd7cddfSDavid du Colombier input(); /* eat 2nd * */
2837dd7cddfSDavid du Colombier if (peek() == '=') {
2847dd7cddfSDavid du Colombier input(); yylval.i = POWEQ; RET(ASGNOP);
2857dd7cddfSDavid du Colombier } else {
2867dd7cddfSDavid du Colombier RET(POWER);
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier } else
2897dd7cddfSDavid du Colombier RET('*');
2907dd7cddfSDavid du Colombier case '/':
2917dd7cddfSDavid du Colombier RET('/');
2927dd7cddfSDavid du Colombier case '%':
2937dd7cddfSDavid du Colombier if (peek() == '=') {
2947dd7cddfSDavid du Colombier input(); yylval.i = MODEQ; RET(ASGNOP);
2957dd7cddfSDavid du Colombier } else
2967dd7cddfSDavid du Colombier RET('%');
2977dd7cddfSDavid du Colombier case '^':
2987dd7cddfSDavid du Colombier if (peek() == '=') {
2997dd7cddfSDavid du Colombier input(); yylval.i = POWEQ; RET(ASGNOP);
3007dd7cddfSDavid du Colombier } else
3017dd7cddfSDavid du Colombier RET(POWER);
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier case '$':
3047dd7cddfSDavid du Colombier /* BUG: awkward, if not wrong */
3057dd7cddfSDavid du Colombier c = gettok(&buf, &bufsize);
306*a2c41696SDavid du Colombier if (isalpha(c)) {
3077dd7cddfSDavid du Colombier if (strcmp(buf, "NF") == 0) { /* very special */
3087dd7cddfSDavid du Colombier unputstr("(NF)");
3097dd7cddfSDavid du Colombier RET(INDIRECT);
3107dd7cddfSDavid du Colombier }
311*a2c41696SDavid du Colombier c = peek();
312*a2c41696SDavid du Colombier if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
313*a2c41696SDavid du Colombier unputstr(buf);
314*a2c41696SDavid du Colombier RET(INDIRECT);
315*a2c41696SDavid du Colombier }
3167dd7cddfSDavid du Colombier yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
3177dd7cddfSDavid du Colombier RET(IVAR);
318*a2c41696SDavid du Colombier } else if (c == 0) { /* */
319*a2c41696SDavid du Colombier SYNTAX( "unexpected end of input after $" );
320*a2c41696SDavid du Colombier RET(';');
3217dd7cddfSDavid du Colombier } else {
3227dd7cddfSDavid du Colombier unputstr(buf);
3237dd7cddfSDavid du Colombier RET(INDIRECT);
3247dd7cddfSDavid du Colombier }
3257dd7cddfSDavid du Colombier
3267dd7cddfSDavid du Colombier case '}':
3277dd7cddfSDavid du Colombier if (--bracecnt < 0)
3287dd7cddfSDavid du Colombier SYNTAX( "extra }" );
3297dd7cddfSDavid du Colombier sc = 1;
3307dd7cddfSDavid du Colombier RET(';');
3317dd7cddfSDavid du Colombier case ']':
3327dd7cddfSDavid du Colombier if (--brackcnt < 0)
3337dd7cddfSDavid du Colombier SYNTAX( "extra ]" );
3347dd7cddfSDavid du Colombier RET(']');
3357dd7cddfSDavid du Colombier case ')':
3367dd7cddfSDavid du Colombier if (--parencnt < 0)
3377dd7cddfSDavid du Colombier SYNTAX( "extra )" );
3387dd7cddfSDavid du Colombier RET(')');
3397dd7cddfSDavid du Colombier case '{':
3407dd7cddfSDavid du Colombier bracecnt++;
3417dd7cddfSDavid du Colombier RET('{');
3427dd7cddfSDavid du Colombier case '[':
3437dd7cddfSDavid du Colombier brackcnt++;
3447dd7cddfSDavid du Colombier RET('[');
3457dd7cddfSDavid du Colombier case '(':
3467dd7cddfSDavid du Colombier parencnt++;
3477dd7cddfSDavid du Colombier RET('(');
3487dd7cddfSDavid du Colombier
3497dd7cddfSDavid du Colombier case '"':
3507dd7cddfSDavid du Colombier return string(); /* BUG: should be like tran.c ? */
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier default:
3537dd7cddfSDavid du Colombier RET(c);
3547dd7cddfSDavid du Colombier }
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
string(void)3587dd7cddfSDavid du Colombier int string(void)
3597dd7cddfSDavid du Colombier {
3607dd7cddfSDavid du Colombier int c, n;
3617dd7cddfSDavid du Colombier char *s, *bp;
3627dd7cddfSDavid du Colombier static char *buf = 0;
3637dd7cddfSDavid du Colombier static int bufsz = 500;
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
3667dd7cddfSDavid du Colombier FATAL("out of space for strings");
3677dd7cddfSDavid du Colombier for (bp = buf; (c = input()) != '"'; ) {
368*a2c41696SDavid du Colombier if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
3697dd7cddfSDavid du Colombier FATAL("out of space for string %.10s...", buf);
3707dd7cddfSDavid du Colombier switch (c) {
3717dd7cddfSDavid du Colombier case '\n':
3727dd7cddfSDavid du Colombier case '\r':
3737dd7cddfSDavid du Colombier case 0:
3747dd7cddfSDavid du Colombier SYNTAX( "non-terminated string %.10s...", buf );
3757dd7cddfSDavid du Colombier lineno++;
376*a2c41696SDavid du Colombier if (c == 0) /* hopeless */
377*a2c41696SDavid du Colombier FATAL( "giving up" );
3787dd7cddfSDavid du Colombier break;
3797dd7cddfSDavid du Colombier case '\\':
3807dd7cddfSDavid du Colombier c = input();
3817dd7cddfSDavid du Colombier switch (c) {
3827dd7cddfSDavid du Colombier case '"': *bp++ = '"'; break;
3837dd7cddfSDavid du Colombier case 'n': *bp++ = '\n'; break;
3847dd7cddfSDavid du Colombier case 't': *bp++ = '\t'; break;
3857dd7cddfSDavid du Colombier case 'f': *bp++ = '\f'; break;
3867dd7cddfSDavid du Colombier case 'r': *bp++ = '\r'; break;
3877dd7cddfSDavid du Colombier case 'b': *bp++ = '\b'; break;
3887dd7cddfSDavid du Colombier case 'v': *bp++ = '\v'; break;
3897dd7cddfSDavid du Colombier case 'a': *bp++ = '\007'; break;
3907dd7cddfSDavid du Colombier case '\\': *bp++ = '\\'; break;
3917dd7cddfSDavid du Colombier
3927dd7cddfSDavid du Colombier case '0': case '1': case '2': /* octal: \d \dd \ddd */
3937dd7cddfSDavid du Colombier case '3': case '4': case '5': case '6': case '7':
3947dd7cddfSDavid du Colombier n = c - '0';
3957dd7cddfSDavid du Colombier if ((c = peek()) >= '0' && c < '8') {
3967dd7cddfSDavid du Colombier n = 8 * n + input() - '0';
3977dd7cddfSDavid du Colombier if ((c = peek()) >= '0' && c < '8')
3987dd7cddfSDavid du Colombier n = 8 * n + input() - '0';
3997dd7cddfSDavid du Colombier }
4007dd7cddfSDavid du Colombier *bp++ = n;
4017dd7cddfSDavid du Colombier break;
4027dd7cddfSDavid du Colombier
4037dd7cddfSDavid du Colombier case 'x': /* hex \x0-9a-fA-F + */
4047dd7cddfSDavid du Colombier { char xbuf[100], *px;
4057dd7cddfSDavid du Colombier for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
4067dd7cddfSDavid du Colombier if (isdigit(c)
4077dd7cddfSDavid du Colombier || (c >= 'a' && c <= 'f')
4087dd7cddfSDavid du Colombier || (c >= 'A' && c <= 'F'))
4097dd7cddfSDavid du Colombier *px++ = c;
4107dd7cddfSDavid du Colombier else
4117dd7cddfSDavid du Colombier break;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier *px = 0;
4147dd7cddfSDavid du Colombier unput(c);
415*a2c41696SDavid du Colombier sscanf(xbuf, "%x", (unsigned int *) &n);
4167dd7cddfSDavid du Colombier *bp++ = n;
4177dd7cddfSDavid du Colombier break;
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier
4207dd7cddfSDavid du Colombier default:
4217dd7cddfSDavid du Colombier *bp++ = c;
4227dd7cddfSDavid du Colombier break;
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier break;
4257dd7cddfSDavid du Colombier default:
4267dd7cddfSDavid du Colombier *bp++ = c;
4277dd7cddfSDavid du Colombier break;
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier }
4307dd7cddfSDavid du Colombier *bp = 0;
4317dd7cddfSDavid du Colombier s = tostring(buf);
4327dd7cddfSDavid du Colombier *bp++ = ' '; *bp++ = 0;
4337dd7cddfSDavid du Colombier yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
4347dd7cddfSDavid du Colombier RET(STRING);
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier
4377dd7cddfSDavid du Colombier
binsearch(char * w,Keyword * kp,int n)4387dd7cddfSDavid du Colombier int binsearch(char *w, Keyword *kp, int n)
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier int cond, low, mid, high;
4417dd7cddfSDavid du Colombier
4427dd7cddfSDavid du Colombier low = 0;
4437dd7cddfSDavid du Colombier high = n - 1;
4447dd7cddfSDavid du Colombier while (low <= high) {
4457dd7cddfSDavid du Colombier mid = (low + high) / 2;
4467dd7cddfSDavid du Colombier if ((cond = strcmp(w, kp[mid].word)) < 0)
4477dd7cddfSDavid du Colombier high = mid - 1;
4487dd7cddfSDavid du Colombier else if (cond > 0)
4497dd7cddfSDavid du Colombier low = mid + 1;
4507dd7cddfSDavid du Colombier else
4517dd7cddfSDavid du Colombier return mid;
4527dd7cddfSDavid du Colombier }
4537dd7cddfSDavid du Colombier return -1;
4547dd7cddfSDavid du Colombier }
4557dd7cddfSDavid du Colombier
word(char * w)4567dd7cddfSDavid du Colombier int word(char *w)
4577dd7cddfSDavid du Colombier {
4587dd7cddfSDavid du Colombier Keyword *kp;
4597dd7cddfSDavid du Colombier int c, n;
4607dd7cddfSDavid du Colombier
4617dd7cddfSDavid du Colombier n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
462*a2c41696SDavid du Colombier /* BUG: this ought to be inside the if; in theory could fault (daniel barrett) */
4637dd7cddfSDavid du Colombier kp = keywords + n;
4647dd7cddfSDavid du Colombier if (n != -1) { /* found in table */
4657dd7cddfSDavid du Colombier yylval.i = kp->sub;
4667dd7cddfSDavid du Colombier switch (kp->type) { /* special handling */
467*a2c41696SDavid du Colombier case BLTIN:
468*a2c41696SDavid du Colombier if (kp->sub == FSYSTEM && safe)
4697dd7cddfSDavid du Colombier SYNTAX( "system is unsafe" );
4707dd7cddfSDavid du Colombier RET(kp->type);
4717dd7cddfSDavid du Colombier case FUNC:
4727dd7cddfSDavid du Colombier if (infunc)
4737dd7cddfSDavid du Colombier SYNTAX( "illegal nested function" );
4747dd7cddfSDavid du Colombier RET(kp->type);
4757dd7cddfSDavid du Colombier case RETURN:
4767dd7cddfSDavid du Colombier if (!infunc)
4777dd7cddfSDavid du Colombier SYNTAX( "return not in function" );
4787dd7cddfSDavid du Colombier RET(kp->type);
4797dd7cddfSDavid du Colombier case VARNF:
4807dd7cddfSDavid du Colombier yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
4817dd7cddfSDavid du Colombier RET(VARNF);
4827dd7cddfSDavid du Colombier default:
4837dd7cddfSDavid du Colombier RET(kp->type);
4847dd7cddfSDavid du Colombier }
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier c = peek(); /* look for '(' */
4877dd7cddfSDavid du Colombier if (c != '(' && infunc && (n=isarg(w)) >= 0) {
4887dd7cddfSDavid du Colombier yylval.i = n;
4897dd7cddfSDavid du Colombier RET(ARG);
4907dd7cddfSDavid du Colombier } else {
4917dd7cddfSDavid du Colombier yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
4927dd7cddfSDavid du Colombier if (c == '(') {
4937dd7cddfSDavid du Colombier RET(CALL);
4947dd7cddfSDavid du Colombier } else {
4957dd7cddfSDavid du Colombier RET(VAR);
4967dd7cddfSDavid du Colombier }
4977dd7cddfSDavid du Colombier }
4987dd7cddfSDavid du Colombier }
4997dd7cddfSDavid du Colombier
startreg(void)500*a2c41696SDavid du Colombier void startreg(void) /* next call to yylex will return a regular expression */
5017dd7cddfSDavid du Colombier {
5027dd7cddfSDavid du Colombier reg = 1;
5037dd7cddfSDavid du Colombier }
5047dd7cddfSDavid du Colombier
regexpr(void)5057dd7cddfSDavid du Colombier int regexpr(void)
5067dd7cddfSDavid du Colombier {
5077dd7cddfSDavid du Colombier int c;
5087dd7cddfSDavid du Colombier static char *buf = 0;
5097dd7cddfSDavid du Colombier static int bufsz = 500;
5107dd7cddfSDavid du Colombier char *bp;
5117dd7cddfSDavid du Colombier
5127dd7cddfSDavid du Colombier if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
5137dd7cddfSDavid du Colombier FATAL("out of space for rex expr");
5147dd7cddfSDavid du Colombier bp = buf;
5157dd7cddfSDavid du Colombier for ( ; (c = input()) != '/' && c != 0; ) {
516*a2c41696SDavid du Colombier if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
5177dd7cddfSDavid du Colombier FATAL("out of space for reg expr %.10s...", buf);
5187dd7cddfSDavid du Colombier if (c == '\n') {
5197dd7cddfSDavid du Colombier SYNTAX( "newline in regular expression %.10s...", buf );
5207dd7cddfSDavid du Colombier unput('\n');
5217dd7cddfSDavid du Colombier break;
5227dd7cddfSDavid du Colombier } else if (c == '\\') {
5237dd7cddfSDavid du Colombier *bp++ = '\\';
5247dd7cddfSDavid du Colombier *bp++ = input();
5257dd7cddfSDavid du Colombier } else {
5267dd7cddfSDavid du Colombier *bp++ = c;
5277dd7cddfSDavid du Colombier }
5287dd7cddfSDavid du Colombier }
5297dd7cddfSDavid du Colombier *bp = 0;
530*a2c41696SDavid du Colombier if (c == 0)
531*a2c41696SDavid du Colombier SYNTAX("non-terminated regular expression %.10s...", buf);
5327dd7cddfSDavid du Colombier yylval.s = tostring(buf);
5337dd7cddfSDavid du Colombier unput('/');
5347dd7cddfSDavid du Colombier RET(REGEXPR);
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier /* low-level lexical stuff, sort of inherited from lex */
5387dd7cddfSDavid du Colombier
5397dd7cddfSDavid du Colombier char ebuf[300];
5407dd7cddfSDavid du Colombier char *ep = ebuf;
5417dd7cddfSDavid du Colombier char yysbuf[100]; /* pushback buffer */
5427dd7cddfSDavid du Colombier char *yysptr = yysbuf;
5437dd7cddfSDavid du Colombier FILE *yyin = 0;
5447dd7cddfSDavid du Colombier
input(void)5457dd7cddfSDavid du Colombier int input(void) /* get next lexical input character */
5467dd7cddfSDavid du Colombier {
5477dd7cddfSDavid du Colombier int c;
5487dd7cddfSDavid du Colombier extern char *lexprog;
5497dd7cddfSDavid du Colombier
5507dd7cddfSDavid du Colombier if (yysptr > yysbuf)
551*a2c41696SDavid du Colombier c = (uschar)*--yysptr;
5527dd7cddfSDavid du Colombier else if (lexprog != NULL) { /* awk '...' */
553*a2c41696SDavid du Colombier if ((c = (uschar)*lexprog) != 0)
5547dd7cddfSDavid du Colombier lexprog++;
5557dd7cddfSDavid du Colombier } else /* awk -f ... */
5567dd7cddfSDavid du Colombier c = pgetc();
5577dd7cddfSDavid du Colombier if (c == '\n')
5587dd7cddfSDavid du Colombier lineno++;
5597dd7cddfSDavid du Colombier else if (c == EOF)
5607dd7cddfSDavid du Colombier c = 0;
5617dd7cddfSDavid du Colombier if (ep >= ebuf + sizeof ebuf)
5627dd7cddfSDavid du Colombier ep = ebuf;
5637dd7cddfSDavid du Colombier return *ep++ = c;
5647dd7cddfSDavid du Colombier }
5657dd7cddfSDavid du Colombier
unput(int c)5667dd7cddfSDavid du Colombier void unput(int c) /* put lexical character back on input */
5677dd7cddfSDavid du Colombier {
5687dd7cddfSDavid du Colombier if (c == '\n')
5697dd7cddfSDavid du Colombier lineno--;
5707dd7cddfSDavid du Colombier if (yysptr >= yysbuf + sizeof(yysbuf))
5717dd7cddfSDavid du Colombier FATAL("pushed back too much: %.20s...", yysbuf);
5727dd7cddfSDavid du Colombier *yysptr++ = c;
5737dd7cddfSDavid du Colombier if (--ep < ebuf)
5747dd7cddfSDavid du Colombier ep = ebuf + sizeof(ebuf) - 1;
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier
unputstr(const char * s)577*a2c41696SDavid du Colombier void unputstr(const char *s) /* put a string back on input */
5787dd7cddfSDavid du Colombier {
5797dd7cddfSDavid du Colombier int i;
5807dd7cddfSDavid du Colombier
5817dd7cddfSDavid du Colombier for (i = strlen(s)-1; i >= 0; i--)
5827dd7cddfSDavid du Colombier unput(s[i]);
5837dd7cddfSDavid du Colombier }
584