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