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: head/bin/sh/arith_yylex.c 343981 2019-02-10 22:23:05Z jilles $");
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
strtoarith_t(const char * restrict nptr,char ** restrict endptr)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
yylex(void)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