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