[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.24

1.1       otto        1: %{
1.24    ! otto        2: /*      $OpenBSD: scan.l,v 1.24 2011/03/07 08:09:25 otto 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 <stdbool.h>
                     24: #include <string.h>
1.18      otto       25: #include <unistd.h>
1.1       otto       26:
                     27: #include "extern.h"
1.15      otto       28: #include "pathnames.h"
1.1       otto       29: #include "y.tab.h"
                     30:
                     31: int            lineno;
1.21      otto       32: bool           interactive;
1.1       otto       33:
1.24    ! otto       34: HistEvent       he;
        !            35: EditLine       *el;
        !            36: History                *hist;
        !            37:
1.2       deraadt    38: static char    *strbuf = NULL;
1.1       otto       39: static size_t  strbuf_sz = 1;
                     40: static bool    dot_seen;
                     41:
                     42: static void    init_strbuf(void);
                     43: static void    add_str(const char *);
                     44:
1.24    ! otto       45: static int      bc_yyinput(char *, int);
        !            46:
        !            47: #undef YY_INPUT
        !            48: #define YY_INPUT(buf,retval,max) \
        !            49:        (retval = bc_yyinput(buf, max))
        !            50:
1.1       otto       51: %}
1.18      otto       52:
                     53: %option always-interactive
1.1       otto       54:
                     55: DIGIT          [0-9A-F]
1.14      otto       56: ALPHA          [a-z_]
                     57: ALPHANUM       [a-z_0-9]
                     58:
1.1       otto       59: %x             comment string number
                     60:
                     61: %%
                     62:
                     63: "/*"           BEGIN(comment);
                     64: <comment>{
                     65:        "*/"    BEGIN(INITIAL);
                     66:        \n      lineno++;
                     67:        \*      ;
                     68:        [^*\n]+ ;
1.5       otto       69:        <<EOF>> fatal("end of file in comment");
1.1       otto       70: }
                     71:
                     72: \"             BEGIN(string); init_strbuf();
                     73: <string>{
1.7       otto       74:        [^"\n\\\[\]]+   add_str(yytext);
                     75:        \[      add_str("\\[");
                     76:        \]      add_str("\\]");
                     77:        \\      add_str("\\\\");
1.1       otto       78:        \n      add_str("\n"); lineno++;
                     79:        \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
1.5       otto       80:        <<EOF>> fatal("end of file in string");
1.1       otto       81: }
                     82:
                     83: {DIGIT}+       {
                     84:                        BEGIN(number);
                     85:                        dot_seen = false;
                     86:                        init_strbuf();
                     87:                        add_str(yytext);
                     88:                }
                     89: \.             {
                     90:                        BEGIN(number);
                     91:                        dot_seen = true;
                     92:                        init_strbuf();
                     93:                        add_str(".");
                     94:                }
                     95: <number>{
                     96:        {DIGIT}+        add_str(yytext);
                     97:        \.      {
                     98:                        if (dot_seen) {
                     99:                                BEGIN(INITIAL);
                    100:                                yylval.str = strbuf;
                    101:                                unput('.');
                    102:                                return NUMBER;
                    103:                        } else {
                    104:                                dot_seen = true;
                    105:                                add_str(".");
                    106:                        }
                    107:                }
                    108:        \\\n[ \t]*      lineno++;
                    109:        [^0-9A-F\.]     {
1.6       otto      110:                        BEGIN(INITIAL);
                    111:                        unput(yytext[0]);
                    112:                        if (strcmp(strbuf, ".") == 0)
                    113:                                return DOT;
1.1       otto      114:                        else {
                    115:                                yylval.str = strbuf;
                    116:                                return NUMBER;
                    117:                        }
                    118:                }
                    119: }
                    120:
                    121: "auto"         return AUTO;
1.2       deraadt   122: "break"                return BREAK;
1.8       otto      123: "continue"     return CONTINUE;
1.1       otto      124: "define"       return DEFINE;
1.8       otto      125: "else"         return ELSE;
1.1       otto      126: "ibase"                return IBASE;
                    127: "if"           return IF;
1.10      otto      128: "last"         return DOT;
1.1       otto      129: "for"          return FOR;
                    130: "length"       return LENGTH;
                    131: "obase"                return OBASE;
1.11      otto      132: "print"                return PRINT;
1.1       otto      133: "quit"         return QUIT;
                    134: "return"       return RETURN;
                    135: "scale"                return SCALE;
                    136: "sqrt"         return SQRT;
                    137: "while"                return WHILE;
                    138:
                    139: "^"            return EXPONENT;
                    140: "*"            return MULTIPLY;
                    141: "/"            return DIVIDE;
                    142: "%"            return REMAINDER;
1.13      otto      143:
                    144: "!"            return BOOL_NOT;
                    145: "&&"           return BOOL_AND;
                    146: "||"           return BOOL_OR;
1.1       otto      147:
                    148: "+"            return PLUS;
                    149: "-"            return MINUS;
                    150:
                    151: "++"           return INCR;
                    152: "--"           return DECR;
                    153:
1.4       deraadt   154: "="            yylval.str = ""; return ASSIGN_OP;
1.1       otto      155: "+="           yylval.str = "+"; return ASSIGN_OP;
                    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:
                    162: "=="           return EQUALS;
                    163: "<="           return LESS_EQ;
                    164: ">="           return GREATER_EQ;
                    165: "!="           return UNEQUALS;
                    166: "<"            return LESS;
                    167: ">"            return GREATER;
                    168:
                    169: ","            return COMMA;
                    170: ";"            return SEMICOLON;
                    171:
                    172: "("            return LPAR;
                    173: ")"            return RPAR;
                    174:
                    175: "["            return LBRACKET;
                    176: "]"            return RBRACKET;
                    177:
                    178: "{"            return LBRACE;
                    179: "}"            return RBRACE;
                    180:
1.14      otto      181: {ALPHA}{ALPHANUM}* {
                    182:                        /* alloc an extra byte for the type marker */
                    183:                        char *p = malloc(yyleng + 2);
                    184:                        if (p == NULL)
                    185:                                err(1, NULL);
                    186:                        strlcpy(p, yytext, yyleng + 1);
                    187:                        yylval.astr = p;
                    188:                        return LETTER;
                    189:                }
1.1       otto      190:
                    191: \\\n           lineno++;
                    192: \n             lineno++; return NEWLINE;
                    193:
1.12      otto      194: #[^\n]*                ;
1.1       otto      195: [ \t]          ;
1.14      otto      196: <<EOF>>                return QUIT;
1.5       otto      197: .              yyerror("illegal character");
1.1       otto      198:
                    199: %%
                    200:
                    201: static void
                    202: init_strbuf(void)
                    203: {
                    204:        if (strbuf == NULL) {
                    205:                strbuf = malloc(strbuf_sz);
                    206:                if (strbuf == NULL)
1.9       otto      207:                        err(1, NULL);
1.1       otto      208:        }
                    209:        strbuf[0] = '\0';
                    210: }
                    211:
                    212: static void
                    213: add_str(const char *str)
                    214: {
                    215:        size_t arglen;
                    216:
                    217:        arglen = strlen(str);
                    218:
1.14      otto      219:        if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
1.1       otto      220:                size_t newsize;
1.3       deraadt   221:                char *p;
1.1       otto      222:
                    223:                newsize = strbuf_sz + arglen + 1;
                    224:                p = realloc(strbuf, newsize);
                    225:                if (p == NULL) {
                    226:                        free(strbuf);
1.9       otto      227:                        err(1, NULL);
1.1       otto      228:                }
                    229:                strbuf_sz = newsize;
                    230:                strbuf = p;
                    231:        }
                    232:        strlcat(strbuf, str, strbuf_sz);
                    233: }
                    234:
1.19      deraadt   235: /* ARGSUSED */
1.1       otto      236: void
                    237: abort_line(int sig)
                    238: {
1.22      otto      239:        static const char str[] = "[\n]P\n";
1.16      otto      240:        int save_errno;
                    241:
1.21      otto      242:        save_errno = errno;
                    243:        YY_FLUSH_BUFFER;        /* XXX signal race? */
                    244:        write(STDOUT_FILENO, str, sizeof(str) - 1);
                    245:        errno = save_errno;
1.1       otto      246: }
1.15      otto      247:
                    248: int
                    249: yywrap(void)
                    250: {
                    251:        static int state;
                    252:        static YY_BUFFER_STATE buf;
                    253:
                    254:        if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
                    255:                filename = sargv[fileindex++];
                    256:                yyin = fopen(filename, "r");
                    257:                lineno = 1;
                    258:                if (yyin == NULL)
                    259:                        err(1, "cannot open %s", filename);
                    260:                return (0);
                    261:        }
                    262:        if (state == 0 && cmdexpr[0] != '\0') {
                    263:                buf = yy_scan_string(cmdexpr);
                    264:                state++;
                    265:                lineno = 1;
                    266:                filename = "command line";
                    267:                return (0);
                    268:        } else if (state == 1) {
                    269:                yy_delete_buffer(buf);
                    270:                free(cmdexpr);
                    271:                state++;
                    272:        }
1.20      otto      273:        if (yyin != NULL && yyin != stdin)
                    274:                fclose(yyin);
1.15      otto      275:        if (fileindex < sargc) {
                    276:                filename = sargv[fileindex++];
                    277:                yyin = fopen(filename, "r");
                    278:                lineno = 1;
                    279:                if (yyin == NULL)
                    280:                        err(1, "cannot open %s", filename);
                    281:                return (0);
                    282:        } else if (fileindex == sargc) {
                    283:                fileindex++;
                    284:                yyin = stdin;
1.21      otto      285:                if (interactive)
                    286:                        signal(SIGINT, abort_line);
1.15      otto      287:                lineno = 1;
                    288:                filename = "stdin";
                    289:                return (0);
                    290:        }
                    291:        return (1);
                    292: }
1.24    ! otto      293:
        !           294: static int
        !           295: bc_yyinput(char *buf, int maxlen)
        !           296: {
        !           297:        int num;
        !           298:        if (yyin == stdin && interactive) {
        !           299:                const char *bp;
        !           300:
        !           301:                if ((bp = el_gets(el, &num)) == NULL || num == 0)
        !           302:                        return (0);
        !           303:                if (num > maxlen) {
        !           304:                        el_push(el, (char *)(void *)bp + maxlen);
        !           305:                        num = maxlen;
        !           306:                }
        !           307:                memcpy(buf, bp, num);
        !           308:                history(hist, &he, H_ENTER, bp);
        !           309:        } else {
        !           310:                int c = '*';
        !           311:                for (num = 0; num < maxlen &&
        !           312:                    (c = getc(yyin)) != EOF && c != '\n'; ++num)
        !           313:                        buf[num] = (char) c;
        !           314:                if (c == '\n')
        !           315:                        buf[num++] = (char) c;
        !           316:                if (c == EOF && ferror(yyin))
        !           317:                        YY_FATAL_ERROR( "input in flex scanner failed" );
        !           318:        }
        !           319:        return (num);
        !           320: }
        !           321:
1.15      otto      322: