xref: /freebsd/bin/sh/arith_yylex.c (revision 7431dfd4580e850375fe5478d92ec770344db098)
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 <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 extern const char *arith_buf;
54 
55 int
56 yylex(void)
57 {
58 	int value;
59 	const char *buf = arith_buf;
60 	char *end;
61 	const char *p;
62 
63 	for (;;) {
64 		value = *buf;
65 		switch (value) {
66 		case ' ':
67 		case '\t':
68 		case '\n':
69 			buf++;
70 			continue;
71 		default:
72 			return ARITH_BAD;
73 		case '0':
74 		case '1':
75 		case '2':
76 		case '3':
77 		case '4':
78 		case '5':
79 		case '6':
80 		case '7':
81 		case '8':
82 		case '9':
83 			yylval.val = strtoarith_t(buf, &end, 0);
84 			arith_buf = end;
85 			return ARITH_NUM;
86 		case 'A':
87 		case 'B':
88 		case 'C':
89 		case 'D':
90 		case 'E':
91 		case 'F':
92 		case 'G':
93 		case 'H':
94 		case 'I':
95 		case 'J':
96 		case 'K':
97 		case 'L':
98 		case 'M':
99 		case 'N':
100 		case 'O':
101 		case 'P':
102 		case 'Q':
103 		case 'R':
104 		case 'S':
105 		case 'T':
106 		case 'U':
107 		case 'V':
108 		case 'W':
109 		case 'X':
110 		case 'Y':
111 		case 'Z':
112 		case '_':
113 		case 'a':
114 		case 'b':
115 		case 'c':
116 		case 'd':
117 		case 'e':
118 		case 'f':
119 		case 'g':
120 		case 'h':
121 		case 'i':
122 		case 'j':
123 		case 'k':
124 		case 'l':
125 		case 'm':
126 		case 'n':
127 		case 'o':
128 		case 'p':
129 		case 'q':
130 		case 'r':
131 		case 's':
132 		case 't':
133 		case 'u':
134 		case 'v':
135 		case 'w':
136 		case 'x':
137 		case 'y':
138 		case 'z':
139 			p = buf;
140 			while (buf++, is_in_name(*buf))
141 				;
142 			yylval.name = stalloc(buf - p + 1);
143 			memcpy(yylval.name, p, buf - p);
144 			yylval.name[buf - p] = '\0';
145 			value = ARITH_VAR;
146 			goto out;
147 		case '=':
148 			value += ARITH_ASS - '=';
149 checkeq:
150 			buf++;
151 checkeqcur:
152 			if (*buf != '=')
153 				goto out;
154 			value += 11;
155 			break;
156 		case '>':
157 			switch (*++buf) {
158 			case '=':
159 				value += ARITH_GE - '>';
160 				break;
161 			case '>':
162 				value += ARITH_RSHIFT - '>';
163 				goto checkeq;
164 			default:
165 				value += ARITH_GT - '>';
166 				goto out;
167 			}
168 			break;
169 		case '<':
170 			switch (*++buf) {
171 			case '=':
172 				value += ARITH_LE - '<';
173 				break;
174 			case '<':
175 				value += ARITH_LSHIFT - '<';
176 				goto checkeq;
177 			default:
178 				value += ARITH_LT - '<';
179 				goto out;
180 			}
181 			break;
182 		case '|':
183 			if (*++buf != '|') {
184 				value += ARITH_BOR - '|';
185 				goto checkeqcur;
186 			}
187 			value += ARITH_OR - '|';
188 			break;
189 		case '&':
190 			if (*++buf != '&') {
191 				value += ARITH_BAND - '&';
192 				goto checkeqcur;
193 			}
194 			value += ARITH_AND - '&';
195 			break;
196 		case '!':
197 			if (*++buf != '=') {
198 				value += ARITH_NOT - '!';
199 				goto out;
200 			}
201 			value += ARITH_NE - '!';
202 			break;
203 		case 0:
204 			goto out;
205 		case '(':
206 			value += ARITH_LPAREN - '(';
207 			break;
208 		case ')':
209 			value += ARITH_RPAREN - ')';
210 			break;
211 		case '*':
212 			value += ARITH_MUL - '*';
213 			goto checkeq;
214 		case '/':
215 			value += ARITH_DIV - '/';
216 			goto checkeq;
217 		case '%':
218 			value += ARITH_REM - '%';
219 			goto checkeq;
220 		case '+':
221 			if (buf[1] == '+')
222 				return ARITH_BAD;
223 			value += ARITH_ADD - '+';
224 			goto checkeq;
225 		case '-':
226 			if (buf[1] == '-')
227 				return ARITH_BAD;
228 			value += ARITH_SUB - '-';
229 			goto checkeq;
230 		case '~':
231 			value += ARITH_BNOT - '~';
232 			break;
233 		case '^':
234 			value += ARITH_BXOR - '^';
235 			goto checkeq;
236 		case '?':
237 			value += ARITH_QMARK - '?';
238 			break;
239 		case ':':
240 			value += ARITH_COLON - ':';
241 			break;
242 		}
243 		break;
244 	}
245 
246 	buf++;
247 out:
248 	arith_buf = buf;
249 	return value;
250 }
251