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