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