[BACK]Return to scan.l CVS log [TXT][DIR] Up to [local] / src / usr.bin / bc

Annotation of src/usr.bin/bc/scan.l, Revision 1.30

1.1       otto        1: %{
1.30    ! espie       2: /*      $OpenBSD: scan.l,v 1.29 2017/07/02 23:19:07 deraadt Exp $      */
1.1       otto        3:
                      4: /*
                      5:  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: #include <err.h>
1.24      otto       21: #include <histedit.h>
1.16      otto       22: #include <signal.h>
1.1       otto       23: #include <string.h>
1.18      otto       24: #include <unistd.h>
1.1       otto       25:
                     26: #include "extern.h"
1.15      otto       27: #include "pathnames.h"
1.30    ! espie      28: #include "bc.h"
1.1       otto       29:
                     30: int            lineno;
1.21      otto       31: bool           interactive;
1.1       otto       32:
1.24      otto       33: HistEvent       he;
                     34: EditLine       *el;
                     35: History                *hist;
                     36:
1.2       deraadt    37: static char    *strbuf = NULL;
1.1       otto       38: static size_t  strbuf_sz = 1;
                     39: static bool    dot_seen;
1.25      otto       40: static int     use_el;
                     41: static volatile sig_atomic_t skipchars;
1.1       otto       42:
                     43: static void    init_strbuf(void);
                     44: static void    add_str(const char *);
                     45:
1.24      otto       46: static int      bc_yyinput(char *, int);
                     47:
                     48: #undef YY_INPUT
                     49: #define YY_INPUT(buf,retval,max) \
                     50:        (retval = bc_yyinput(buf, max))
                     51:
1.1       otto       52: %}
1.18      otto       53:
                     54: %option always-interactive
1.1       otto       55:
                     56: DIGIT          [0-9A-F]
1.14      otto       57: ALPHA          [a-z_]
                     58: ALPHANUM       [a-z_0-9]
                     59:
1.1       otto       60: %x             comment string number
                     61:
                     62: %%
                     63:
                     64: "/*"           BEGIN(comment);
                     65: <comment>{
                     66:        "*/"    BEGIN(INITIAL);
                     67:        \n      lineno++;
                     68:        \*      ;
                     69:        [^*\n]+ ;
1.5       otto       70:        <<EOF>> fatal("end of file in comment");
1.1       otto       71: }
                     72:
                     73: \"             BEGIN(string); init_strbuf();
                     74: <string>{
1.7       otto       75:        [^"\n\\\[\]]+   add_str(yytext);
                     76:        \[      add_str("\\[");
                     77:        \]      add_str("\\]");
                     78:        \\      add_str("\\\\");
1.1       otto       79:        \n      add_str("\n"); lineno++;
                     80:        \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
1.5       otto       81:        <<EOF>> fatal("end of file in string");
1.1       otto       82: }
                     83:
                     84: {DIGIT}+       {
                     85:                        BEGIN(number);
                     86:                        dot_seen = false;
                     87:                        init_strbuf();
                     88:                        add_str(yytext);
                     89:                }
                     90: \.             {
                     91:                        BEGIN(number);
                     92:                        dot_seen = true;
                     93:                        init_strbuf();
                     94:                        add_str(".");
                     95:                }
                     96: <number>{
                     97:        {DIGIT}+        add_str(yytext);
                     98:        \.      {
                     99:                        if (dot_seen) {
                    100:                                BEGIN(INITIAL);
                    101:                                yylval.str = strbuf;
                    102:                                unput('.');
                    103:                                return NUMBER;
                    104:                        } else {
                    105:                                dot_seen = true;
                    106:                                add_str(".");
                    107:                        }
                    108:                }
                    109:        \\\n[ \t]*      lineno++;
                    110:        [^0-9A-F\.]     {
1.6       otto      111:                        BEGIN(INITIAL);
                    112:                        unput(yytext[0]);
                    113:                        if (strcmp(strbuf, ".") == 0)
                    114:                                return DOT;
1.1       otto      115:                        else {
                    116:                                yylval.str = strbuf;
                    117:                                return NUMBER;
                    118:                        }
                    119:                }
                    120: }
                    121:
                    122: "auto"         return AUTO;
1.2       deraadt   123: "break"                return BREAK;
1.8       otto      124: "continue"     return CONTINUE;
1.1       otto      125: "define"       return DEFINE;
1.8       otto      126: "else"         return ELSE;
1.1       otto      127: "ibase"                return IBASE;
                    128: "if"           return IF;
1.10      otto      129: "last"         return DOT;
1.1       otto      130: "for"          return FOR;
                    131: "length"       return LENGTH;
                    132: "obase"                return OBASE;
1.11      otto      133: "print"                return PRINT;
1.1       otto      134: "quit"         return QUIT;
                    135: "return"       return RETURN;
                    136: "scale"                return SCALE;
                    137: "sqrt"         return SQRT;
                    138: "while"                return WHILE;
                    139:
                    140: "^"            return EXPONENT;
                    141: "*"            return MULTIPLY;
                    142: "/"            return DIVIDE;
                    143: "%"            return REMAINDER;
1.13      otto      144:
                    145: "!"            return BOOL_NOT;
                    146: "&&"           return BOOL_AND;
                    147: "||"           return BOOL_OR;
1.1       otto      148:
                    149: "+"            return PLUS;
                    150: "-"            return MINUS;
                    151:
                    152: "++"           return INCR;
                    153: "--"           return DECR;
                    154:
1.4       deraadt   155: "="            yylval.str = ""; return ASSIGN_OP;
1.1       otto      156: "+="           yylval.str = "+"; return ASSIGN_OP;
                    157: "-="           yylval.str = "-"; return ASSIGN_OP;
                    158: "*="           yylval.str = "*"; return ASSIGN_OP;
                    159: "/="           yylval.str = "/"; return ASSIGN_OP;
                    160: "%="           yylval.str = "%"; return ASSIGN_OP;
                    161: "^="           yylval.str = "^"; return ASSIGN_OP;
                    162:
                    163: "=="           return EQUALS;
                    164: "<="           return LESS_EQ;
                    165: ">="           return GREATER_EQ;
                    166: "!="           return UNEQUALS;
                    167: "<"            return LESS;
                    168: ">"            return GREATER;
                    169:
                    170: ","            return COMMA;
                    171: ";"            return SEMICOLON;
                    172:
                    173: "("            return LPAR;
                    174: ")"            return RPAR;
                    175:
                    176: "["            return LBRACKET;
                    177: "]"            return RBRACKET;
                    178:
                    179: "{"            return LBRACE;
                    180: "}"            return RBRACE;
                    181:
1.14      otto      182: {ALPHA}{ALPHANUM}* {
                    183:                        /* alloc an extra byte for the type marker */
                    184:                        char *p = malloc(yyleng + 2);
                    185:                        if (p == NULL)
                    186:                                err(1, NULL);
                    187:                        strlcpy(p, yytext, yyleng + 1);
                    188:                        yylval.astr = p;
                    189:                        return LETTER;
                    190:                }
1.1       otto      191:
                    192: \\\n           lineno++;
                    193: \n             lineno++; return NEWLINE;
                    194:
1.12      otto      195: #[^\n]*                ;
1.1       otto      196: [ \t]          ;
1.14      otto      197: <<EOF>>                return QUIT;
1.5       otto      198: .              yyerror("illegal character");
1.1       otto      199:
                    200: %%
                    201:
                    202: static void
                    203: init_strbuf(void)
                    204: {
                    205:        if (strbuf == NULL) {
                    206:                strbuf = malloc(strbuf_sz);
                    207:                if (strbuf == NULL)
1.9       otto      208:                        err(1, NULL);
1.1       otto      209:        }
                    210:        strbuf[0] = '\0';
                    211: }
                    212:
                    213: static void
                    214: add_str(const char *str)
                    215: {
                    216:        size_t arglen;
                    217:
                    218:        arglen = strlen(str);
                    219:
1.14      otto      220:        if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
1.1       otto      221:                size_t newsize;
1.3       deraadt   222:                char *p;
1.1       otto      223:
                    224:                newsize = strbuf_sz + arglen + 1;
                    225:                p = realloc(strbuf, newsize);
                    226:                if (p == NULL) {
                    227:                        free(strbuf);
1.9       otto      228:                        err(1, NULL);
1.1       otto      229:                }
                    230:                strbuf_sz = newsize;
                    231:                strbuf = p;
                    232:        }
                    233:        strlcat(strbuf, str, strbuf_sz);
                    234: }
                    235:
1.19      deraadt   236: /* ARGSUSED */
1.1       otto      237: void
                    238: abort_line(int sig)
                    239: {
1.25      otto      240:        static const char str1[] = "[\n]P\n";
                    241:        static const char str2[] = "[^C\n]P\n";
1.16      otto      242:        int save_errno;
1.25      otto      243:        const LineInfo *info;
1.16      otto      244:
1.21      otto      245:        save_errno = errno;
1.25      otto      246:        if (use_el) {
                    247:                write(STDOUT_FILENO, str2, sizeof(str2) - 1);
                    248:                info = el_line(el);
                    249:                skipchars = info->lastchar - info->buffer;
                    250:        } else
                    251:                write(STDOUT_FILENO, str1, sizeof(str1) - 1);
1.27      otto      252:        errno = save_errno;
                    253: }
                    254:
1.26      otto      255: /*
                    256:  * Avoid the echo of ^D by the default code of editline and take
                    257:  * into account skipchars to make ^D work when the cursor is at start of
                    258:  * line after a ^C.
                    259:  */
                    260: unsigned char
                    261: bc_eof(EditLine *e, int ch)
                    262: {
                    263:        const struct lineinfo *info = el_line(e);
                    264:
                    265:        if (info->buffer + skipchars == info->cursor &&
                    266:            info->cursor == info->lastchar)
                    267:                return (CC_EOF);
                    268:        else
                    269:                return (CC_ERROR);
1.1       otto      270: }
1.15      otto      271:
                    272: int
                    273: yywrap(void)
                    274: {
                    275:        static int state;
                    276:        static YY_BUFFER_STATE buf;
                    277:
                    278:        if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
                    279:                filename = sargv[fileindex++];
                    280:                yyin = fopen(filename, "r");
                    281:                lineno = 1;
                    282:                if (yyin == NULL)
                    283:                        err(1, "cannot open %s", filename);
                    284:                return (0);
                    285:        }
                    286:        if (state == 0 && cmdexpr[0] != '\0') {
                    287:                buf = yy_scan_string(cmdexpr);
                    288:                state++;
                    289:                lineno = 1;
                    290:                filename = "command line";
                    291:                return (0);
                    292:        } else if (state == 1) {
                    293:                yy_delete_buffer(buf);
                    294:                free(cmdexpr);
                    295:                state++;
                    296:        }
1.20      otto      297:        if (yyin != NULL && yyin != stdin)
                    298:                fclose(yyin);
1.15      otto      299:        if (fileindex < sargc) {
                    300:                filename = sargv[fileindex++];
                    301:                yyin = fopen(filename, "r");
                    302:                lineno = 1;
                    303:                if (yyin == NULL)
                    304:                        err(1, "cannot open %s", filename);
                    305:                return (0);
                    306:        } else if (fileindex == sargc) {
                    307:                fileindex++;
                    308:                yyin = stdin;
1.27      otto      309:                if (interactive) {
1.21      otto      310:                        signal(SIGINT, abort_line);
1.27      otto      311:                        signal(SIGTSTP, tstpcont);
                    312:                }
1.15      otto      313:                lineno = 1;
                    314:                filename = "stdin";
                    315:                return (0);
                    316:        }
                    317:        return (1);
                    318: }
1.24      otto      319:
                    320: static int
                    321: bc_yyinput(char *buf, int maxlen)
                    322: {
                    323:        int num;
1.25      otto      324:
                    325:        if (el != NULL)
                    326:                el_get(el, EL_EDITMODE, &use_el);
1.29      deraadt   327:
1.25      otto      328:        if (yyin == stdin && interactive && use_el) {
1.24      otto      329:                const char *bp;
1.25      otto      330:                sigset_t oset, nset;
1.24      otto      331:
                    332:                if ((bp = el_gets(el, &num)) == NULL || num == 0)
                    333:                        return (0);
1.25      otto      334:                sigemptyset(&nset);
                    335:                sigaddset(&nset, SIGINT);
                    336:                sigprocmask(SIG_BLOCK, &nset, &oset);
                    337:                if (skipchars < num) {
                    338:                        bp += skipchars;
                    339:                        num -= skipchars;
                    340:                }
                    341:                skipchars = 0;
                    342:                sigprocmask(SIG_SETMASK, &oset, NULL);
1.24      otto      343:                if (num > maxlen) {
                    344:                        el_push(el, (char *)(void *)bp + maxlen);
                    345:                        num = maxlen;
                    346:                }
                    347:                memcpy(buf, bp, num);
                    348:                history(hist, &he, H_ENTER, bp);
1.25      otto      349:                el_get(el, EL_EDITMODE, &use_el);
1.24      otto      350:        } else {
                    351:                int c = '*';
                    352:                for (num = 0; num < maxlen &&
                    353:                    (c = getc(yyin)) != EOF && c != '\n'; ++num)
                    354:                        buf[num] = (char) c;
                    355:                if (c == '\n')
                    356:                        buf[num++] = (char) c;
                    357:                if (c == EOF && ferror(yyin))
                    358:                        YY_FATAL_ERROR( "input in flex scanner failed" );
                    359:        }
                    360:        return (num);
                    361: }
                    362:
1.15      otto      363: