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
strtoarith_t(const char * restrict nptr,char ** restrict endptr)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
yylex(void)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