1 /*- 2 * Copyright (c) 2002 3 * Herbert Xu. 4 * Copyright (c) 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <inttypes.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include "shell.h" 42 #include "arith_yacc.h" 43 #include "expand.h" 44 #include "error.h" 45 #include "memalloc.h" 46 #include "parser.h" 47 #include "syntax.h" 48 49 #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ 50 #error Arithmetic tokens are out of order. 51 #endif 52 53 extern const char *arith_buf; 54 55 int 56 yylex(void) 57 { 58 int value; 59 const char *buf = arith_buf; 60 char *end; 61 const char *p; 62 63 for (;;) { 64 value = *buf; 65 switch (value) { 66 case ' ': 67 case '\t': 68 case '\n': 69 buf++; 70 continue; 71 default: 72 return ARITH_BAD; 73 case '0': 74 case '1': 75 case '2': 76 case '3': 77 case '4': 78 case '5': 79 case '6': 80 case '7': 81 case '8': 82 case '9': 83 yylval.val = strtoarith_t(buf, &end, 0); 84 arith_buf = end; 85 return ARITH_NUM; 86 case 'A': 87 case 'B': 88 case 'C': 89 case 'D': 90 case 'E': 91 case 'F': 92 case 'G': 93 case 'H': 94 case 'I': 95 case 'J': 96 case 'K': 97 case 'L': 98 case 'M': 99 case 'N': 100 case 'O': 101 case 'P': 102 case 'Q': 103 case 'R': 104 case 'S': 105 case 'T': 106 case 'U': 107 case 'V': 108 case 'W': 109 case 'X': 110 case 'Y': 111 case 'Z': 112 case '_': 113 case 'a': 114 case 'b': 115 case 'c': 116 case 'd': 117 case 'e': 118 case 'f': 119 case 'g': 120 case 'h': 121 case 'i': 122 case 'j': 123 case 'k': 124 case 'l': 125 case 'm': 126 case 'n': 127 case 'o': 128 case 'p': 129 case 'q': 130 case 'r': 131 case 's': 132 case 't': 133 case 'u': 134 case 'v': 135 case 'w': 136 case 'x': 137 case 'y': 138 case 'z': 139 p = buf; 140 while (buf++, is_in_name(*buf)) 141 ; 142 yylval.name = stalloc(buf - p + 1); 143 memcpy(yylval.name, p, buf - p); 144 yylval.name[buf - p] = '\0'; 145 value = ARITH_VAR; 146 goto out; 147 case '=': 148 value += ARITH_ASS - '='; 149 checkeq: 150 buf++; 151 checkeqcur: 152 if (*buf != '=') 153 goto out; 154 value += 11; 155 break; 156 case '>': 157 switch (*++buf) { 158 case '=': 159 value += ARITH_GE - '>'; 160 break; 161 case '>': 162 value += ARITH_RSHIFT - '>'; 163 goto checkeq; 164 default: 165 value += ARITH_GT - '>'; 166 goto out; 167 } 168 break; 169 case '<': 170 switch (*++buf) { 171 case '=': 172 value += ARITH_LE - '<'; 173 break; 174 case '<': 175 value += ARITH_LSHIFT - '<'; 176 goto checkeq; 177 default: 178 value += ARITH_LT - '<'; 179 goto out; 180 } 181 break; 182 case '|': 183 if (*++buf != '|') { 184 value += ARITH_BOR - '|'; 185 goto checkeqcur; 186 } 187 value += ARITH_OR - '|'; 188 break; 189 case '&': 190 if (*++buf != '&') { 191 value += ARITH_BAND - '&'; 192 goto checkeqcur; 193 } 194 value += ARITH_AND - '&'; 195 break; 196 case '!': 197 if (*++buf != '=') { 198 value += ARITH_NOT - '!'; 199 goto out; 200 } 201 value += ARITH_NE - '!'; 202 break; 203 case 0: 204 goto out; 205 case '(': 206 value += ARITH_LPAREN - '('; 207 break; 208 case ')': 209 value += ARITH_RPAREN - ')'; 210 break; 211 case '*': 212 value += ARITH_MUL - '*'; 213 goto checkeq; 214 case '/': 215 value += ARITH_DIV - '/'; 216 goto checkeq; 217 case '%': 218 value += ARITH_REM - '%'; 219 goto checkeq; 220 case '+': 221 if (buf[1] == '+') 222 return ARITH_BAD; 223 value += ARITH_ADD - '+'; 224 goto checkeq; 225 case '-': 226 if (buf[1] == '-') 227 return ARITH_BAD; 228 value += ARITH_SUB - '-'; 229 goto checkeq; 230 case '~': 231 value += ARITH_BNOT - '~'; 232 break; 233 case '^': 234 value += ARITH_BXOR - '^'; 235 goto checkeq; 236 case '?': 237 value += ARITH_QMARK - '?'; 238 break; 239 case ':': 240 value += ARITH_COLON - ':'; 241 break; 242 } 243 break; 244 } 245 246 buf++; 247 out: 248 arith_buf = buf; 249 return value; 250 } 251