]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/sh/arith_yylex.c
kern: cpuset: allow jails to modify child jails' roots
[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 __FBSDID("$FreeBSD$");
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
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
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 }