Annotation of coherent/d/bin/bc/lex.c, revision 1.1

1.1     ! root        1: #include <stdio.h>
        !             2: #include <ctype.h>
        !             3: #include <setjmp.h>
        !             4: #include "bc.h"
        !             5: #include "yy.h"
        !             6: 
        !             7: /*
        !             8:  *     The jump buffer lexenv is used to hold the environment in
        !             9:  *     yylex that will be returned to if there is some lexical
        !            10:  *     error.
        !            11:  */
        !            12: 
        !            13: static jmp_buf lexenv;
        !            14: 
        !            15: 
        !            16: /*
        !            17:  *     Lexerror issues the appropriate error message on stderr and
        !            18:  *     then longjumps back to lex which return ERROR.
        !            19:  */
        !            20: 
        !            21: lexerror(str)
        !            22: char   *str;
        !            23: {
        !            24:        gerror("%r", &str);
        !            25:        longjmp(lexenv, TRUE);
        !            26: }
        !            27: 
        !            28: /*
        !            29:  * This buffer is used for strings, words, and shell commands.
        !            30:  */
        !            31: static char buff[MAXSTRING];
        !            32: 
        !            33: /*
        !            34:  *     Yylex is the lexical analyzer for bc.
        !            35:  */
        !            36: 
        !            37: yylex()
        !            38: {
        !            39:        register int    ch;
        !            40:        register int    nexteq;
        !            41:        register FILE   *inf = infile;
        !            42:        static int      newline = TRUE;         /* TRUE iff at start of line */
        !            43:        char            *getword();
        !            44:        char            *getqs();
        !            45: 
        !            46: Again:
        !            47:        if (setjmp(lexenv))
        !            48:                return ERROR;
        !            49:        ch = getc(inf);
        !            50:        if (newline && ch == '!') {
        !            51:                shell();
        !            52:                goto Again;
        !            53:        }
        !            54:        while (ch == '\t' || ch == ' ')
        !            55:                ch = getc(inf);
        !            56:        if (inline != 0 && newline == TRUE)
        !            57:                inline += 1;
        !            58:        if (ch == '\n' || ch == EOF) {
        !            59:                newline = TRUE;
        !            60:                return (ch);
        !            61:        } else
        !            62:                newline = FALSE;
        !            63:        if ( ! isascii(ch))
        !            64:                lexerror("Illegal character: %d", ch);
        !            65:        if (isalpha(ch))
        !            66:                return (token(getword(ch)));
        !            67:        if (isdigit(ch)) {
        !            68:                if (digit(ch) < ibase) {
        !            69:                        yylval.lvalue = getnum(ch);
        !            70:                        return (NUMBER);
        !            71:                }
        !            72:                lexerror("Illegal digit: %c", ch);
        !            73:        }
        !            74:        if (ch == '.') {
        !            75:                ch = getc(inf);
        !            76:                ungetc(ch, inf);
        !            77:                if (digit(ch) < ibase) {
        !            78:                        yylval.lvalue = getnum('.');
        !            79:                        return (NUMBER);
        !            80:                }
        !            81:                return (DOT);
        !            82:        }
        !            83:        nexteq = next('=');
        !            84:        switch (ch) {
        !            85:        case '+': return (nexteq ? ADDAB :  (next('+') ? INCR : ch));
        !            86:        case '-': return (nexteq ? SUBAB :  (next('-') ? DECR : ch));
        !            87:        case '*': return (nexteq ? MULAB : ch);
        !            88:        case '%': return (nexteq ? REMAB : ch);
        !            89:        case '^': return (nexteq ? EXPAB : ch);
        !            90:        case '/':
        !            91:                if (!nexteq && next('*')) {
        !            92:                        do {
        !            93:                                ch = getc(inf);
        !            94:                        } while (ch != '*' || !next('/'));
        !            95:                        goto Again;
        !            96:                }
        !            97:                return (nexteq ? DIVAB : ch);
        !            98:        case '=': return (nexteq ? EQP : ch);
        !            99:        case '<': return (nexteq ? LEP : LTP);
        !           100:        case '>': return (nexteq ? GEP : GTP);
        !           101:        case '!': return (nexteq ? NEP : ch);
        !           102:        case '"':
        !           103:                yylval.svalue = getqs();
        !           104:                return(STRING);
        !           105:        default:
        !           106:                if (nexteq)
        !           107:                        ungetc('=', inf);
        !           108:                return(ch);
        !           109:        }
        !           110: }
        !           111: 
        !           112: /*
        !           113:  *     Next returns TRUE iff the next character on input is "testc".
        !           114:  *     If the next character is not "testc" then it is pushed back
        !           115:  *     for later consumption.
        !           116:  */
        !           117: 
        !           118: int
        !           119: next(testc)
        !           120: char testc;
        !           121: {
        !           122:        register int ch;
        !           123:        register int result;
        !           124: 
        !           125:        ch = getc(infile);
        !           126:        if (! (result = ch == testc))
        !           127:                ungetc(ch, infile);
        !           128:        return(result);
        !           129: }
        !           130: 
        !           131: /*
        !           132:  *     Getqs reads in a quoted string.  It assumes that the initial
        !           133:  *     double quote has already been read in and it returns a pointer
        !           134:  *     to an allocated area where the string has been copyied.
        !           135:  */
        !           136: 
        !           137: char   *
        !           138: getqs()
        !           139: {
        !           140:        register char   *ptr;
        !           141:        register int    ch;
        !           142: 
        !           143:        ptr = buff;
        !           144:        while ((ch = getc(infile)) != '"') {
        !           145:                if (ch == EOF || ch == '\n')
        !           146:                        lexerror("Unexpected end of quoted string");
        !           147:                if (ptr < &buff[MAXSTRING])
        !           148:                        *ptr++ = ch;
        !           149:        }
        !           150:        if (ptr >= &buff[MAXSTRING])
        !           151:                lexerror("String too long");
        !           152:        *ptr = '\0';
        !           153:        ptr = (char *)mpalc(1 + ptr - buff);
        !           154:        strcpy(ptr, buff);
        !           155:        return (ptr);
        !           156: }
        !           157: 
        !           158: /*
        !           159:  *     Token looks up the string pointed to by "word" in the
        !           160:  *     list of keywords.  If the word is found, then it returns
        !           161:  *     the corresponding value.  If not, then it makes sure that
        !           162:  *     the string is in the string table, sets yylval to a pointer to
        !           163:  *     the string table entry and returns IDENTIFIER.
        !           164:  */
        !           165: 
        !           166: int
        !           167: token(word)
        !           168: char *word;
        !           169: {
        !           170:        static struct keyword {
        !           171:                char *key;
        !           172:                int keyval;
        !           173:        } keywords[] = {
        !           174:                "auto",   AUTO,    "break", BREAK,  "continue", CONTINUE,
        !           175:                "define", DEFINE,  "do",    DO,     "else",     ELSE,
        !           176:                "for",    FOR,     "ibase", IBASE,  "if",       IF,
        !           177:                "length", LENGTH_, "obase", OBASE,  "quit",     QUIT,
        !           178:                "return", RETURN_, "scale", SCALE_, "sqrt",     SQRT_,
        !           179:                "while",  WHILE
        !           180:        };
        !           181:        register struct keyword *probe;
        !           182:        register struct keyword *fwa = keywords;
        !           183:        register struct keyword *lwa = &keywords[nel(keywords) - 1];
        !           184:        int     cmp;
        !           185:        dicent  *lookword();
        !           186: 
        !           187:        while (fwa <= lwa) {
        !           188:                probe = fwa + (lwa - fwa) / 2;
        !           189:                cmp = strcmp(word, probe->key);
        !           190:                if (cmp > 0)
        !           191:                        fwa = probe + 1;
        !           192:                else if (cmp < 0)
        !           193:                        lwa = probe - 1;
        !           194:                else
        !           195:                        return (probe->keyval);
        !           196:        }
        !           197:        yylval.dvalue = lookword(word);
        !           198:        return (IDENTIFIER);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  *     Lookword looks up the string str in the string table dictionary.
        !           203:  *     If it is not already there, then it adds it and initializes the
        !           204:  *     type fields to indicate it as undefined.
        !           205:  *     It returns the pointer to the dictionary entry for the string.
        !           206:  */
        !           207: 
        !           208: dicent *
        !           209: lookword(str)
        !           210: char   *str;
        !           211: {
        !           212:        register dicent **father,
        !           213:                        *probe;
        !           214:        register int    rel;
        !           215: 
        !           216:        father = &dictionary;
        !           217:        while ( (probe = *father) != NULL) {
        !           218:                rel = strcmp(probe->word, str);
        !           219:                if (rel == 0)
        !           220:                        return (probe);
        !           221:                father = (rel < 0 ? &probe->left : &probe->right);
        !           222:        }
        !           223:        probe = (dicent *)mpalc((sizeof *probe) + strlen(str) + 1);
        !           224:        probe->left = probe->right = NULL;
        !           225:        probe->globalt = probe->localt = UNDEFINED;
        !           226:        strcpy(probe->word, str);
        !           227:        *father = probe;
        !           228:        return (probe);
        !           229: }
        !           230: 
        !           231: /*
        !           232:  *     Getword reads in a word (alphanumeric sequence) which starts
        !           233:  *     with "ch".  It returns a pointer to the string read in.
        !           234:  *     Note that the pointer is to a static area and hence
        !           235:  *     the result must be copyied if it is to be used after another
        !           236:  *     call to getword.
        !           237:  */
        !           238: 
        !           239: char *
        !           240: getword(ch)
        !           241: register char ch;
        !           242: {
        !           243:        register char *chp = &buff[0];
        !           244: 
        !           245:        do {
        !           246:                if (chp < &buff[MAXWORD])
        !           247:                        *chp++ = ch;
        !           248:                ch = getc(infile);
        !           249:        } while (isascii(ch) && isalnum(ch));
        !           250:        ungetc(ch, infile);
        !           251:        if (chp >= &buff[MAXWORD])
        !           252:                lexerror("Identifier too long");
        !           253:        *chp = '\0';
        !           254:        return (buff);
        !           255: }
        !           256: 
        !           257: /*
        !           258:  *     Shell reads in a line from the standard input and forks a shell
        !           259:  *     to execute it.
        !           260:  */
        !           261: 
        !           262: shell()
        !           263: {
        !           264:        register char   *ptr;
        !           265:        register int    ch;
        !           266: 
        !           267:        ptr = buff;
        !           268:        while ((ch = getc(infile)) != '\n' && ch != EOF)
        !           269:                if (ptr < &buff[MAXSTRING])
        !           270:                        *ptr++ = ch;
        !           271:        if (ptr >= &buff[MAXSTRING]) {
        !           272:                fprintf(stderr, "! line too long\n");
        !           273:                return;
        !           274:        }
        !           275:        *ptr = '\0';
        !           276:        fflush(infile);
        !           277:        if (system(buff) == NOSHELL)
        !           278:                fprintf(stderr, "bc: shell couldn't execute\n");
        !           279:        printf("!\n");
        !           280: }
        !           281: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.