xref: /freebsd-src/bin/sh/arith_yylex.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
16262b84eSJilles Tjoelker /*-
26262b84eSJilles Tjoelker  * Copyright (c) 2002
36262b84eSJilles Tjoelker  *	Herbert Xu.
46262b84eSJilles Tjoelker  * Copyright (c) 1993
56262b84eSJilles Tjoelker  *	The Regents of the University of California.  All rights reserved.
66262b84eSJilles Tjoelker  *
76262b84eSJilles Tjoelker  * This code is derived from software contributed to Berkeley by
86262b84eSJilles Tjoelker  * Kenneth Almquist.
96262b84eSJilles Tjoelker  *
106262b84eSJilles Tjoelker  * Redistribution and use in source and binary forms, with or without
116262b84eSJilles Tjoelker  * modification, are permitted provided that the following conditions
126262b84eSJilles Tjoelker  * are met:
136262b84eSJilles Tjoelker  * 1. Redistributions of source code must retain the above copyright
146262b84eSJilles Tjoelker  *    notice, this list of conditions and the following disclaimer.
156262b84eSJilles Tjoelker  * 2. Redistributions in binary form must reproduce the above copyright
166262b84eSJilles Tjoelker  *    notice, this list of conditions and the following disclaimer in the
176262b84eSJilles Tjoelker  *    documentation and/or other materials provided with the distribution.
186262b84eSJilles Tjoelker  * 3. Neither the name of the University nor the names of its contributors
196262b84eSJilles Tjoelker  *    may be used to endorse or promote products derived from this software
206262b84eSJilles Tjoelker  *    without specific prior written permission.
216262b84eSJilles Tjoelker  *
226262b84eSJilles Tjoelker  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236262b84eSJilles Tjoelker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246262b84eSJilles Tjoelker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256262b84eSJilles Tjoelker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
266262b84eSJilles Tjoelker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
276262b84eSJilles Tjoelker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
286262b84eSJilles Tjoelker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
296262b84eSJilles Tjoelker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
306262b84eSJilles Tjoelker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
316262b84eSJilles Tjoelker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326262b84eSJilles Tjoelker  * SUCH DAMAGE.
336262b84eSJilles Tjoelker  */
346262b84eSJilles Tjoelker 
356262b84eSJilles Tjoelker #include <sys/cdefs.h>
36*aac5464bSJilles Tjoelker #include <ctype.h>
37*aac5464bSJilles Tjoelker #include <errno.h>
386262b84eSJilles Tjoelker #include <inttypes.h>
396262b84eSJilles Tjoelker #include <stdlib.h>
406262b84eSJilles Tjoelker #include <string.h>
416262b84eSJilles Tjoelker #include "shell.h"
426262b84eSJilles Tjoelker #include "arith_yacc.h"
436262b84eSJilles Tjoelker #include "expand.h"
446262b84eSJilles Tjoelker #include "error.h"
456262b84eSJilles Tjoelker #include "memalloc.h"
466262b84eSJilles Tjoelker #include "parser.h"
476262b84eSJilles Tjoelker #include "syntax.h"
486262b84eSJilles Tjoelker 
496262b84eSJilles Tjoelker #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
506262b84eSJilles Tjoelker #error Arithmetic tokens are out of order.
516262b84eSJilles Tjoelker #endif
526262b84eSJilles Tjoelker 
53*aac5464bSJilles Tjoelker arith_t
strtoarith_t(const char * restrict nptr,char ** restrict endptr)54*aac5464bSJilles Tjoelker strtoarith_t(const char *restrict nptr, char **restrict endptr)
55*aac5464bSJilles Tjoelker {
56*aac5464bSJilles Tjoelker 	arith_t val;
57*aac5464bSJilles Tjoelker 
58*aac5464bSJilles Tjoelker 	while (isspace((unsigned char)*nptr))
59*aac5464bSJilles Tjoelker 		nptr++;
60*aac5464bSJilles Tjoelker 	switch (*nptr) {
61*aac5464bSJilles Tjoelker 		case '-':
62*aac5464bSJilles Tjoelker 			return strtoimax(nptr, endptr, 0);
63*aac5464bSJilles Tjoelker 		case '0':
64*aac5464bSJilles Tjoelker 			return (arith_t)strtoumax(nptr, endptr, 0);
65*aac5464bSJilles Tjoelker 		default:
66*aac5464bSJilles Tjoelker 			val = (arith_t)strtoumax(nptr, endptr, 0);
67*aac5464bSJilles Tjoelker 			if (val >= 0)
68*aac5464bSJilles Tjoelker 				return val;
69*aac5464bSJilles Tjoelker 			else if (val == ARITH_MIN) {
70*aac5464bSJilles Tjoelker 				errno = ERANGE;
71*aac5464bSJilles Tjoelker 				return ARITH_MIN;
72*aac5464bSJilles Tjoelker 			} else {
73*aac5464bSJilles Tjoelker 				errno = ERANGE;
74*aac5464bSJilles Tjoelker 				return ARITH_MAX;
75*aac5464bSJilles Tjoelker 			}
76*aac5464bSJilles Tjoelker 	}
77*aac5464bSJilles Tjoelker }
78*aac5464bSJilles Tjoelker 
796262b84eSJilles Tjoelker int
yylex(void)802fae4c3dSPhilippe Charnier yylex(void)
816262b84eSJilles Tjoelker {
826262b84eSJilles Tjoelker 	int value;
836262b84eSJilles Tjoelker 	const char *buf = arith_buf;
84976018d2SJilles Tjoelker 	char *end;
856262b84eSJilles Tjoelker 	const char *p;
866262b84eSJilles Tjoelker 
876262b84eSJilles Tjoelker 	for (;;) {
886262b84eSJilles Tjoelker 		value = *buf;
896262b84eSJilles Tjoelker 		switch (value) {
906262b84eSJilles Tjoelker 		case ' ':
916262b84eSJilles Tjoelker 		case '\t':
926262b84eSJilles Tjoelker 		case '\n':
936262b84eSJilles Tjoelker 			buf++;
946262b84eSJilles Tjoelker 			continue;
956262b84eSJilles Tjoelker 		default:
966262b84eSJilles Tjoelker 			return ARITH_BAD;
976262b84eSJilles Tjoelker 		case '0':
986262b84eSJilles Tjoelker 		case '1':
996262b84eSJilles Tjoelker 		case '2':
1006262b84eSJilles Tjoelker 		case '3':
1016262b84eSJilles Tjoelker 		case '4':
1026262b84eSJilles Tjoelker 		case '5':
1036262b84eSJilles Tjoelker 		case '6':
1046262b84eSJilles Tjoelker 		case '7':
1056262b84eSJilles Tjoelker 		case '8':
1066262b84eSJilles Tjoelker 		case '9':
107*aac5464bSJilles Tjoelker 			yylval.val = strtoarith_t(buf, &end);
108976018d2SJilles Tjoelker 			arith_buf = end;
1096262b84eSJilles Tjoelker 			return ARITH_NUM;
1106262b84eSJilles Tjoelker 		case 'A':
1116262b84eSJilles Tjoelker 		case 'B':
1126262b84eSJilles Tjoelker 		case 'C':
1136262b84eSJilles Tjoelker 		case 'D':
1146262b84eSJilles Tjoelker 		case 'E':
1156262b84eSJilles Tjoelker 		case 'F':
1166262b84eSJilles Tjoelker 		case 'G':
1176262b84eSJilles Tjoelker 		case 'H':
1186262b84eSJilles Tjoelker 		case 'I':
1196262b84eSJilles Tjoelker 		case 'J':
1206262b84eSJilles Tjoelker 		case 'K':
1216262b84eSJilles Tjoelker 		case 'L':
1226262b84eSJilles Tjoelker 		case 'M':
1236262b84eSJilles Tjoelker 		case 'N':
1246262b84eSJilles Tjoelker 		case 'O':
1256262b84eSJilles Tjoelker 		case 'P':
1266262b84eSJilles Tjoelker 		case 'Q':
1276262b84eSJilles Tjoelker 		case 'R':
1286262b84eSJilles Tjoelker 		case 'S':
1296262b84eSJilles Tjoelker 		case 'T':
1306262b84eSJilles Tjoelker 		case 'U':
1316262b84eSJilles Tjoelker 		case 'V':
1326262b84eSJilles Tjoelker 		case 'W':
1336262b84eSJilles Tjoelker 		case 'X':
1346262b84eSJilles Tjoelker 		case 'Y':
1356262b84eSJilles Tjoelker 		case 'Z':
1366262b84eSJilles Tjoelker 		case '_':
1376262b84eSJilles Tjoelker 		case 'a':
1386262b84eSJilles Tjoelker 		case 'b':
1396262b84eSJilles Tjoelker 		case 'c':
1406262b84eSJilles Tjoelker 		case 'd':
1416262b84eSJilles Tjoelker 		case 'e':
1426262b84eSJilles Tjoelker 		case 'f':
1436262b84eSJilles Tjoelker 		case 'g':
1446262b84eSJilles Tjoelker 		case 'h':
1456262b84eSJilles Tjoelker 		case 'i':
1466262b84eSJilles Tjoelker 		case 'j':
1476262b84eSJilles Tjoelker 		case 'k':
1486262b84eSJilles Tjoelker 		case 'l':
1496262b84eSJilles Tjoelker 		case 'm':
1506262b84eSJilles Tjoelker 		case 'n':
1516262b84eSJilles Tjoelker 		case 'o':
1526262b84eSJilles Tjoelker 		case 'p':
1536262b84eSJilles Tjoelker 		case 'q':
1546262b84eSJilles Tjoelker 		case 'r':
1556262b84eSJilles Tjoelker 		case 's':
1566262b84eSJilles Tjoelker 		case 't':
1576262b84eSJilles Tjoelker 		case 'u':
1586262b84eSJilles Tjoelker 		case 'v':
1596262b84eSJilles Tjoelker 		case 'w':
1606262b84eSJilles Tjoelker 		case 'x':
1616262b84eSJilles Tjoelker 		case 'y':
1626262b84eSJilles Tjoelker 		case 'z':
1636262b84eSJilles Tjoelker 			p = buf;
1646262b84eSJilles Tjoelker 			while (buf++, is_in_name(*buf))
1656262b84eSJilles Tjoelker 				;
1666262b84eSJilles Tjoelker 			yylval.name = stalloc(buf - p + 1);
1676262b84eSJilles Tjoelker 			memcpy(yylval.name, p, buf - p);
1686262b84eSJilles Tjoelker 			yylval.name[buf - p] = '\0';
1696262b84eSJilles Tjoelker 			value = ARITH_VAR;
1706262b84eSJilles Tjoelker 			goto out;
1716262b84eSJilles Tjoelker 		case '=':
1726262b84eSJilles Tjoelker 			value += ARITH_ASS - '=';
1736262b84eSJilles Tjoelker checkeq:
1746262b84eSJilles Tjoelker 			buf++;
1756262b84eSJilles Tjoelker checkeqcur:
1766262b84eSJilles Tjoelker 			if (*buf != '=')
1776262b84eSJilles Tjoelker 				goto out;
1786262b84eSJilles Tjoelker 			value += 11;
1796262b84eSJilles Tjoelker 			break;
1806262b84eSJilles Tjoelker 		case '>':
1816262b84eSJilles Tjoelker 			switch (*++buf) {
1826262b84eSJilles Tjoelker 			case '=':
1836262b84eSJilles Tjoelker 				value += ARITH_GE - '>';
1846262b84eSJilles Tjoelker 				break;
1856262b84eSJilles Tjoelker 			case '>':
1866262b84eSJilles Tjoelker 				value += ARITH_RSHIFT - '>';
1876262b84eSJilles Tjoelker 				goto checkeq;
1886262b84eSJilles Tjoelker 			default:
1896262b84eSJilles Tjoelker 				value += ARITH_GT - '>';
1906262b84eSJilles Tjoelker 				goto out;
1916262b84eSJilles Tjoelker 			}
1926262b84eSJilles Tjoelker 			break;
1936262b84eSJilles Tjoelker 		case '<':
1946262b84eSJilles Tjoelker 			switch (*++buf) {
1956262b84eSJilles Tjoelker 			case '=':
1966262b84eSJilles Tjoelker 				value += ARITH_LE - '<';
1976262b84eSJilles Tjoelker 				break;
1986262b84eSJilles Tjoelker 			case '<':
1996262b84eSJilles Tjoelker 				value += ARITH_LSHIFT - '<';
2006262b84eSJilles Tjoelker 				goto checkeq;
2016262b84eSJilles Tjoelker 			default:
2026262b84eSJilles Tjoelker 				value += ARITH_LT - '<';
2036262b84eSJilles Tjoelker 				goto out;
2046262b84eSJilles Tjoelker 			}
2056262b84eSJilles Tjoelker 			break;
2066262b84eSJilles Tjoelker 		case '|':
2076262b84eSJilles Tjoelker 			if (*++buf != '|') {
2086262b84eSJilles Tjoelker 				value += ARITH_BOR - '|';
2096262b84eSJilles Tjoelker 				goto checkeqcur;
2106262b84eSJilles Tjoelker 			}
2116262b84eSJilles Tjoelker 			value += ARITH_OR - '|';
2126262b84eSJilles Tjoelker 			break;
2136262b84eSJilles Tjoelker 		case '&':
2146262b84eSJilles Tjoelker 			if (*++buf != '&') {
2156262b84eSJilles Tjoelker 				value += ARITH_BAND - '&';
2166262b84eSJilles Tjoelker 				goto checkeqcur;
2176262b84eSJilles Tjoelker 			}
2186262b84eSJilles Tjoelker 			value += ARITH_AND - '&';
2196262b84eSJilles Tjoelker 			break;
2206262b84eSJilles Tjoelker 		case '!':
2216262b84eSJilles Tjoelker 			if (*++buf != '=') {
2226262b84eSJilles Tjoelker 				value += ARITH_NOT - '!';
2236262b84eSJilles Tjoelker 				goto out;
2246262b84eSJilles Tjoelker 			}
2256262b84eSJilles Tjoelker 			value += ARITH_NE - '!';
2266262b84eSJilles Tjoelker 			break;
2276262b84eSJilles Tjoelker 		case 0:
2286262b84eSJilles Tjoelker 			goto out;
2296262b84eSJilles Tjoelker 		case '(':
2306262b84eSJilles Tjoelker 			value += ARITH_LPAREN - '(';
2316262b84eSJilles Tjoelker 			break;
2326262b84eSJilles Tjoelker 		case ')':
2336262b84eSJilles Tjoelker 			value += ARITH_RPAREN - ')';
2346262b84eSJilles Tjoelker 			break;
2356262b84eSJilles Tjoelker 		case '*':
2366262b84eSJilles Tjoelker 			value += ARITH_MUL - '*';
2376262b84eSJilles Tjoelker 			goto checkeq;
2386262b84eSJilles Tjoelker 		case '/':
2396262b84eSJilles Tjoelker 			value += ARITH_DIV - '/';
2406262b84eSJilles Tjoelker 			goto checkeq;
2416262b84eSJilles Tjoelker 		case '%':
2426262b84eSJilles Tjoelker 			value += ARITH_REM - '%';
2436262b84eSJilles Tjoelker 			goto checkeq;
2446262b84eSJilles Tjoelker 		case '+':
2457e6e930dSJilles Tjoelker 			if (buf[1] == '+')
2467e6e930dSJilles Tjoelker 				return ARITH_BAD;
2476262b84eSJilles Tjoelker 			value += ARITH_ADD - '+';
2486262b84eSJilles Tjoelker 			goto checkeq;
2496262b84eSJilles Tjoelker 		case '-':
2507e6e930dSJilles Tjoelker 			if (buf[1] == '-')
2517e6e930dSJilles Tjoelker 				return ARITH_BAD;
2526262b84eSJilles Tjoelker 			value += ARITH_SUB - '-';
2536262b84eSJilles Tjoelker 			goto checkeq;
2546262b84eSJilles Tjoelker 		case '~':
2556262b84eSJilles Tjoelker 			value += ARITH_BNOT - '~';
2566262b84eSJilles Tjoelker 			break;
2576262b84eSJilles Tjoelker 		case '^':
2586262b84eSJilles Tjoelker 			value += ARITH_BXOR - '^';
2596262b84eSJilles Tjoelker 			goto checkeq;
2606262b84eSJilles Tjoelker 		case '?':
2616262b84eSJilles Tjoelker 			value += ARITH_QMARK - '?';
2626262b84eSJilles Tjoelker 			break;
2636262b84eSJilles Tjoelker 		case ':':
2646262b84eSJilles Tjoelker 			value += ARITH_COLON - ':';
2656262b84eSJilles Tjoelker 			break;
2666262b84eSJilles Tjoelker 		}
2676262b84eSJilles Tjoelker 		break;
2686262b84eSJilles Tjoelker 	}
2696262b84eSJilles Tjoelker 
2706262b84eSJilles Tjoelker 	buf++;
2716262b84eSJilles Tjoelker out:
2726262b84eSJilles Tjoelker 	arith_buf = buf;
2736262b84eSJilles Tjoelker 	return value;
2746262b84eSJilles Tjoelker }
275