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
50extern const char *arith_buf;
51
52int
53yylex()
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 - '=';
143checkeq:
144			buf++;
145checkeqcur:
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++;
237out:
238	arith_buf = buf;
239	return value;
240}
241