]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/sh/arith_yylex.c
sqlite3: Vendor import of sqlite3 3.45.0
[FreeBSD/FreeBSD.git] / bin / sh / arith_yylex.c
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
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
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 }