| /*- |
| * Copyright (c) 2002 |
| * Herbert Xu. |
| * Copyright (c) 1993 |
| * The Regents of the University of California. All rights reserved. |
| * |
| * This code is derived from software contributed to Berkeley by |
| * Kenneth Almquist. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the University nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #include <inttypes.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "arith_yacc.h" |
| #include "expand.h" |
| #include "error.h" |
| #include "shell.h" |
| #include "memalloc.h" |
| #include "syntax.h" |
| #include "system.h" |
| |
| #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ |
| #error Arithmetic tokens are out of order. |
| #endif |
| |
| extern const char *arith_buf; |
| |
| int |
| yylex() |
| { |
| int value; |
| const char *buf = arith_buf; |
| const char *p; |
| |
| for (;;) { |
| value = *buf; |
| switch (value) { |
| case ' ': |
| case '\t': |
| case '\n': |
| buf++; |
| continue; |
| default: |
| return ARITH_BAD; |
| case '0': |
| case '1': |
| case '2': |
| case '3': |
| case '4': |
| case '5': |
| case '6': |
| case '7': |
| case '8': |
| case '9': |
| yylval.val = strtoimax(buf, (char **)&arith_buf, 0); |
| return ARITH_NUM; |
| case 'A': |
| case 'B': |
| case 'C': |
| case 'D': |
| case 'E': |
| case 'F': |
| case 'G': |
| case 'H': |
| case 'I': |
| case 'J': |
| case 'K': |
| case 'L': |
| case 'M': |
| case 'N': |
| case 'O': |
| case 'P': |
| case 'Q': |
| case 'R': |
| case 'S': |
| case 'T': |
| case 'U': |
| case 'V': |
| case 'W': |
| case 'X': |
| case 'Y': |
| case 'Z': |
| case '_': |
| case 'a': |
| case 'b': |
| case 'c': |
| case 'd': |
| case 'e': |
| case 'f': |
| case 'g': |
| case 'h': |
| case 'i': |
| case 'j': |
| case 'k': |
| case 'l': |
| case 'm': |
| case 'n': |
| case 'o': |
| case 'p': |
| case 'q': |
| case 'r': |
| case 's': |
| case 't': |
| case 'u': |
| case 'v': |
| case 'w': |
| case 'x': |
| case 'y': |
| case 'z': |
| p = buf; |
| while (buf++, is_in_name(*buf)) |
| ; |
| yylval.name = stalloc(buf - p + 1); |
| *(char *)mempcpy(yylval.name, p, buf - p) = 0; |
| value = ARITH_VAR; |
| goto out; |
| case '=': |
| value += ARITH_ASS - '='; |
| checkeq: |
| buf++; |
| checkeqcur: |
| if (*buf != '=') |
| goto out; |
| value += 11; |
| break; |
| case '>': |
| switch (*++buf) { |
| case '=': |
| value += ARITH_GE - '>'; |
| break; |
| case '>': |
| value += ARITH_RSHIFT - '>'; |
| goto checkeq; |
| default: |
| value += ARITH_GT - '>'; |
| goto out; |
| } |
| break; |
| case '<': |
| switch (*++buf) { |
| case '=': |
| value += ARITH_LE - '<'; |
| break; |
| case '<': |
| value += ARITH_LSHIFT - '<'; |
| goto checkeq; |
| default: |
| value += ARITH_LT - '<'; |
| goto out; |
| } |
| break; |
| case '|': |
| if (*++buf != '|') { |
| value += ARITH_BOR - '|'; |
| goto checkeqcur; |
| } |
| value += ARITH_OR - '|'; |
| break; |
| case '&': |
| if (*++buf != '&') { |
| value += ARITH_BAND - '&'; |
| goto checkeqcur; |
| } |
| value += ARITH_AND - '&'; |
| break; |
| case '!': |
| if (*++buf != '=') { |
| value += ARITH_NOT - '!'; |
| goto out; |
| } |
| value += ARITH_NE - '!'; |
| break; |
| case 0: |
| goto out; |
| case '(': |
| value += ARITH_LPAREN - '('; |
| break; |
| case ')': |
| value += ARITH_RPAREN - ')'; |
| break; |
| case '*': |
| value += ARITH_MUL - '*'; |
| goto checkeq; |
| case '/': |
| value += ARITH_DIV - '/'; |
| goto checkeq; |
| case '%': |
| value += ARITH_REM - '%'; |
| goto checkeq; |
| case '+': |
| value += ARITH_ADD - '+'; |
| goto checkeq; |
| case '-': |
| value += ARITH_SUB - '-'; |
| goto checkeq; |
| case '~': |
| value += ARITH_BNOT - '~'; |
| break; |
| case '^': |
| value += ARITH_BXOR - '^'; |
| goto checkeq; |
| case '?': |
| value += ARITH_QMARK - '?'; |
| break; |
| case ':': |
| value += ARITH_COLON - ':'; |
| break; |
| } |
| break; |
| } |
| |
| buf++; |
| out: |
| arith_buf = buf; |
| return value; |
| } |