| /*- | |
| * 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; | |
| } |