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