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 #include <ctype.h> 37 #include <errno.h> 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 arith_t 54 strtoarith_t(const char *restrict nptr, char **restrict endptr) 55 { 56 arith_t val; 57 58 while (isspace((unsigned char)*nptr)) 59 nptr++; 60 switch (*nptr) { 61 case '-': 62 return strtoimax(nptr, endptr, 0); 63 case '0': 64 return (arith_t)strtoumax(nptr, endptr, 0); 65 default: 66 val = (arith_t)strtoumax(nptr, endptr, 0); 67 if (val >= 0) 68 return val; 69 else if (val == ARITH_MIN) { 70 errno = ERANGE; 71 return ARITH_MIN; 72 } else { 73 errno = ERANGE; 74 return ARITH_MAX; 75 } 76 } 77 } 78 79 int 80 yylex(void) 81 { 82 int value; 83 const char *buf = arith_buf; 84 char *end; 85 const char *p; 86 87 for (;;) { 88 value = *buf; 89 switch (value) { 90 case ' ': 91 case '\t': 92 case '\n': 93 buf++; 94 continue; 95 default: 96 return ARITH_BAD; 97 case '0': 98 case '1': 99 case '2': 100 case '3': 101 case '4': 102 case '5': 103 case '6': 104 case '7': 105 case '8': 106 case '9': 107 yylval.val = strtoarith_t(buf, &end); 108 arith_buf = end; 109 return ARITH_NUM; 110 case 'A': 111 case 'B': 112 case 'C': 113 case 'D': 114 case 'E': 115 case 'F': 116 case 'G': 117 case 'H': 118 case 'I': 119 case 'J': 120 case 'K': 121 case 'L': 122 case 'M': 123 case 'N': 124 case 'O': 125 case 'P': 126 case 'Q': 127 case 'R': 128 case 'S': 129 case 'T': 130 case 'U': 131 case 'V': 132 case 'W': 133 case 'X': 134 case 'Y': 135 case 'Z': 136 case '_': 137 case 'a': 138 case 'b': 139 case 'c': 140 case 'd': 141 case 'e': 142 case 'f': 143 case 'g': 144 case 'h': 145 case 'i': 146 case 'j': 147 case 'k': 148 case 'l': 149 case 'm': 150 case 'n': 151 case 'o': 152 case 'p': 153 case 'q': 154 case 'r': 155 case 's': 156 case 't': 157 case 'u': 158 case 'v': 159 case 'w': 160 case 'x': 161 case 'y': 162 case 'z': 163 p = buf; 164 while (buf++, is_in_name(*buf)) 165 ; 166 yylval.name = stalloc(buf - p + 1); 167 memcpy(yylval.name, p, buf - p); 168 yylval.name[buf - p] = '\0'; 169 value = ARITH_VAR; 170 goto out; 171 case '=': 172 value += ARITH_ASS - '='; 173 checkeq: 174 buf++; 175 checkeqcur: 176 if (*buf != '=') 177 goto out; 178 value += 11; 179 break; 180 case '>': 181 switch (*++buf) { 182 case '=': 183 value += ARITH_GE - '>'; 184 break; 185 case '>': 186 value += ARITH_RSHIFT - '>'; 187 goto checkeq; 188 default: 189 value += ARITH_GT - '>'; 190 goto out; 191 } 192 break; 193 case '<': 194 switch (*++buf) { 195 case '=': 196 value += ARITH_LE - '<'; 197 break; 198 case '<': 199 value += ARITH_LSHIFT - '<'; 200 goto checkeq; 201 default: 202 value += ARITH_LT - '<'; 203 goto out; 204 } 205 break; 206 case '|': 207 if (*++buf != '|') { 208 value += ARITH_BOR - '|'; 209 goto checkeqcur; 210 } 211 value += ARITH_OR - '|'; 212 break; 213 case '&': 214 if (*++buf != '&') { 215 value += ARITH_BAND - '&'; 216 goto checkeqcur; 217 } 218 value += ARITH_AND - '&'; 219 break; 220 case '!': 221 if (*++buf != '=') { 222 value += ARITH_NOT - '!'; 223 goto out; 224 } 225 value += ARITH_NE - '!'; 226 break; 227 case 0: 228 goto out; 229 case '(': 230 value += ARITH_LPAREN - '('; 231 break; 232 case ')': 233 value += ARITH_RPAREN - ')'; 234 break; 235 case '*': 236 value += ARITH_MUL - '*'; 237 goto checkeq; 238 case '/': 239 value += ARITH_DIV - '/'; 240 goto checkeq; 241 case '%': 242 value += ARITH_REM - '%'; 243 goto checkeq; 244 case '+': 245 if (buf[1] == '+') 246 return ARITH_BAD; 247 value += ARITH_ADD - '+'; 248 goto checkeq; 249 case '-': 250 if (buf[1] == '-') 251 return ARITH_BAD; 252 value += ARITH_SUB - '-'; 253 goto checkeq; 254 case '~': 255 value += ARITH_BNOT - '~'; 256 break; 257 case '^': 258 value += ARITH_BXOR - '^'; 259 goto checkeq; 260 case '?': 261 value += ARITH_QMARK - '?'; 262 break; 263 case ':': 264 value += ARITH_COLON - ':'; 265 break; 266 } 267 break; 268 } 269 270 buf++; 271 out: 272 arith_buf = buf; 273 return value; 274 } 275