xref: /dflybsd-src/bin/sh/arith_yylex.c (revision 3e3895bf4584c1562faf4533cbd97026ee6a8dcf)
199512ac4SPeter Avalos /*-
299512ac4SPeter Avalos  * Copyright (c) 2002
399512ac4SPeter Avalos  *	Herbert Xu.
499512ac4SPeter Avalos  * Copyright (c) 1993
599512ac4SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
699512ac4SPeter Avalos  *
799512ac4SPeter Avalos  * This code is derived from software contributed to Berkeley by
899512ac4SPeter Avalos  * Kenneth Almquist.
999512ac4SPeter Avalos  *
1099512ac4SPeter Avalos  * Redistribution and use in source and binary forms, with or without
1199512ac4SPeter Avalos  * modification, are permitted provided that the following conditions
1299512ac4SPeter Avalos  * are met:
1399512ac4SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1499512ac4SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1599512ac4SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1699512ac4SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1799512ac4SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1899512ac4SPeter Avalos  * 3. Neither the name of the University nor the names of its contributors
1999512ac4SPeter Avalos  *    may be used to endorse or promote products derived from this software
2099512ac4SPeter Avalos  *    without specific prior written permission.
2199512ac4SPeter Avalos  *
2299512ac4SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2399512ac4SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2499512ac4SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2599512ac4SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2699512ac4SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2799512ac4SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2899512ac4SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2999512ac4SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3099512ac4SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3199512ac4SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3299512ac4SPeter Avalos  * SUCH DAMAGE.
3399512ac4SPeter Avalos  */
3499512ac4SPeter Avalos 
3502d0b1ceSMatthew Dillon #include <sys/cdefs.h>
36*3e3895bfSKrzysztof Piecuch __FBSDID("$FreeBSD: head/bin/sh/arith_yylex.c 343981 2019-02-10 22:23:05Z jilles $");
3702d0b1ceSMatthew Dillon 
38*3e3895bfSKrzysztof Piecuch #include <ctype.h>
39*3e3895bfSKrzysztof Piecuch #include <errno.h>
4099512ac4SPeter Avalos #include <inttypes.h>
4199512ac4SPeter Avalos #include <stdlib.h>
4299512ac4SPeter Avalos #include <string.h>
4399512ac4SPeter Avalos #include "shell.h"
4499512ac4SPeter Avalos #include "arith_yacc.h"
4599512ac4SPeter Avalos #include "expand.h"
4699512ac4SPeter Avalos #include "error.h"
4799512ac4SPeter Avalos #include "memalloc.h"
4899512ac4SPeter Avalos #include "parser.h"
4999512ac4SPeter Avalos #include "syntax.h"
5099512ac4SPeter Avalos 
5199512ac4SPeter Avalos #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
5299512ac4SPeter Avalos #error Arithmetic tokens are out of order.
5399512ac4SPeter Avalos #endif
5499512ac4SPeter Avalos 
55*3e3895bfSKrzysztof Piecuch arith_t
strtoarith_t(const char * restrict nptr,char ** restrict endptr)56*3e3895bfSKrzysztof Piecuch strtoarith_t(const char *restrict nptr, char **restrict endptr)
57*3e3895bfSKrzysztof Piecuch {
58*3e3895bfSKrzysztof Piecuch 	arith_t val;
59*3e3895bfSKrzysztof Piecuch 
60*3e3895bfSKrzysztof Piecuch 	while (isspace((unsigned char)*nptr))
61*3e3895bfSKrzysztof Piecuch 		nptr++;
62*3e3895bfSKrzysztof Piecuch 	switch (*nptr) {
63*3e3895bfSKrzysztof Piecuch 		case '-':
64*3e3895bfSKrzysztof Piecuch 			return strtoimax(nptr, endptr, 0);
65*3e3895bfSKrzysztof Piecuch 		case '0':
66*3e3895bfSKrzysztof Piecuch 			return (arith_t)strtoumax(nptr, endptr, 0);
67*3e3895bfSKrzysztof Piecuch 		default:
68*3e3895bfSKrzysztof Piecuch 			val = (arith_t)strtoumax(nptr, endptr, 0);
69*3e3895bfSKrzysztof Piecuch 			if (val >= 0)
70*3e3895bfSKrzysztof Piecuch 				return val;
71*3e3895bfSKrzysztof Piecuch 			else if (val == ARITH_MIN) {
72*3e3895bfSKrzysztof Piecuch 				errno = ERANGE;
73*3e3895bfSKrzysztof Piecuch 				return ARITH_MIN;
74*3e3895bfSKrzysztof Piecuch 			} else {
75*3e3895bfSKrzysztof Piecuch 				errno = ERANGE;
76*3e3895bfSKrzysztof Piecuch 				return ARITH_MAX;
77*3e3895bfSKrzysztof Piecuch 			}
78*3e3895bfSKrzysztof Piecuch 	}
79*3e3895bfSKrzysztof Piecuch }
80*3e3895bfSKrzysztof Piecuch 
8199512ac4SPeter Avalos int
yylex(void)8299512ac4SPeter Avalos yylex(void)
8399512ac4SPeter Avalos {
8499512ac4SPeter Avalos 	int value;
8599512ac4SPeter Avalos 	const char *buf = arith_buf;
86cb26c088SPeter Avalos 	char *end;
8799512ac4SPeter Avalos 	const char *p;
8899512ac4SPeter Avalos 
8999512ac4SPeter Avalos 	for (;;) {
9099512ac4SPeter Avalos 		value = *buf;
9199512ac4SPeter Avalos 		switch (value) {
9299512ac4SPeter Avalos 		case ' ':
9399512ac4SPeter Avalos 		case '\t':
9499512ac4SPeter Avalos 		case '\n':
9599512ac4SPeter Avalos 			buf++;
9699512ac4SPeter Avalos 			continue;
9799512ac4SPeter Avalos 		default:
9899512ac4SPeter Avalos 			return ARITH_BAD;
9999512ac4SPeter Avalos 		case '0':
10099512ac4SPeter Avalos 		case '1':
10199512ac4SPeter Avalos 		case '2':
10299512ac4SPeter Avalos 		case '3':
10399512ac4SPeter Avalos 		case '4':
10499512ac4SPeter Avalos 		case '5':
10599512ac4SPeter Avalos 		case '6':
10699512ac4SPeter Avalos 		case '7':
10799512ac4SPeter Avalos 		case '8':
10899512ac4SPeter Avalos 		case '9':
109*3e3895bfSKrzysztof Piecuch 			yylval.val = strtoarith_t(buf, &end);
110cb26c088SPeter Avalos 			arith_buf = end;
11199512ac4SPeter Avalos 			return ARITH_NUM;
11299512ac4SPeter Avalos 		case 'A':
11399512ac4SPeter Avalos 		case 'B':
11499512ac4SPeter Avalos 		case 'C':
11599512ac4SPeter Avalos 		case 'D':
11699512ac4SPeter Avalos 		case 'E':
11799512ac4SPeter Avalos 		case 'F':
11899512ac4SPeter Avalos 		case 'G':
11999512ac4SPeter Avalos 		case 'H':
12099512ac4SPeter Avalos 		case 'I':
12199512ac4SPeter Avalos 		case 'J':
12299512ac4SPeter Avalos 		case 'K':
12399512ac4SPeter Avalos 		case 'L':
12499512ac4SPeter Avalos 		case 'M':
12599512ac4SPeter Avalos 		case 'N':
12699512ac4SPeter Avalos 		case 'O':
12799512ac4SPeter Avalos 		case 'P':
12899512ac4SPeter Avalos 		case 'Q':
12999512ac4SPeter Avalos 		case 'R':
13099512ac4SPeter Avalos 		case 'S':
13199512ac4SPeter Avalos 		case 'T':
13299512ac4SPeter Avalos 		case 'U':
13399512ac4SPeter Avalos 		case 'V':
13499512ac4SPeter Avalos 		case 'W':
13599512ac4SPeter Avalos 		case 'X':
13699512ac4SPeter Avalos 		case 'Y':
13799512ac4SPeter Avalos 		case 'Z':
13899512ac4SPeter Avalos 		case '_':
13999512ac4SPeter Avalos 		case 'a':
14099512ac4SPeter Avalos 		case 'b':
14199512ac4SPeter Avalos 		case 'c':
14299512ac4SPeter Avalos 		case 'd':
14399512ac4SPeter Avalos 		case 'e':
14499512ac4SPeter Avalos 		case 'f':
14599512ac4SPeter Avalos 		case 'g':
14699512ac4SPeter Avalos 		case 'h':
14799512ac4SPeter Avalos 		case 'i':
14899512ac4SPeter Avalos 		case 'j':
14999512ac4SPeter Avalos 		case 'k':
15099512ac4SPeter Avalos 		case 'l':
15199512ac4SPeter Avalos 		case 'm':
15299512ac4SPeter Avalos 		case 'n':
15399512ac4SPeter Avalos 		case 'o':
15499512ac4SPeter Avalos 		case 'p':
15599512ac4SPeter Avalos 		case 'q':
15699512ac4SPeter Avalos 		case 'r':
15799512ac4SPeter Avalos 		case 's':
15899512ac4SPeter Avalos 		case 't':
15999512ac4SPeter Avalos 		case 'u':
16099512ac4SPeter Avalos 		case 'v':
16199512ac4SPeter Avalos 		case 'w':
16299512ac4SPeter Avalos 		case 'x':
16399512ac4SPeter Avalos 		case 'y':
16499512ac4SPeter Avalos 		case 'z':
16599512ac4SPeter Avalos 			p = buf;
16699512ac4SPeter Avalos 			while (buf++, is_in_name(*buf))
16799512ac4SPeter Avalos 				;
16899512ac4SPeter Avalos 			yylval.name = stalloc(buf - p + 1);
16999512ac4SPeter Avalos 			memcpy(yylval.name, p, buf - p);
17099512ac4SPeter Avalos 			yylval.name[buf - p] = '\0';
17199512ac4SPeter Avalos 			value = ARITH_VAR;
17299512ac4SPeter Avalos 			goto out;
17399512ac4SPeter Avalos 		case '=':
17499512ac4SPeter Avalos 			value += ARITH_ASS - '=';
17599512ac4SPeter Avalos checkeq:
17699512ac4SPeter Avalos 			buf++;
17799512ac4SPeter Avalos checkeqcur:
17899512ac4SPeter Avalos 			if (*buf != '=')
17999512ac4SPeter Avalos 				goto out;
18099512ac4SPeter Avalos 			value += 11;
18199512ac4SPeter Avalos 			break;
18299512ac4SPeter Avalos 		case '>':
18399512ac4SPeter Avalos 			switch (*++buf) {
18499512ac4SPeter Avalos 			case '=':
18599512ac4SPeter Avalos 				value += ARITH_GE - '>';
18699512ac4SPeter Avalos 				break;
18799512ac4SPeter Avalos 			case '>':
18899512ac4SPeter Avalos 				value += ARITH_RSHIFT - '>';
18999512ac4SPeter Avalos 				goto checkeq;
19099512ac4SPeter Avalos 			default:
19199512ac4SPeter Avalos 				value += ARITH_GT - '>';
19299512ac4SPeter Avalos 				goto out;
19399512ac4SPeter Avalos 			}
19499512ac4SPeter Avalos 			break;
19599512ac4SPeter Avalos 		case '<':
19699512ac4SPeter Avalos 			switch (*++buf) {
19799512ac4SPeter Avalos 			case '=':
19899512ac4SPeter Avalos 				value += ARITH_LE - '<';
19999512ac4SPeter Avalos 				break;
20099512ac4SPeter Avalos 			case '<':
20199512ac4SPeter Avalos 				value += ARITH_LSHIFT - '<';
20299512ac4SPeter Avalos 				goto checkeq;
20399512ac4SPeter Avalos 			default:
20499512ac4SPeter Avalos 				value += ARITH_LT - '<';
20599512ac4SPeter Avalos 				goto out;
20699512ac4SPeter Avalos 			}
20799512ac4SPeter Avalos 			break;
20899512ac4SPeter Avalos 		case '|':
20999512ac4SPeter Avalos 			if (*++buf != '|') {
21099512ac4SPeter Avalos 				value += ARITH_BOR - '|';
21199512ac4SPeter Avalos 				goto checkeqcur;
21299512ac4SPeter Avalos 			}
21399512ac4SPeter Avalos 			value += ARITH_OR - '|';
21499512ac4SPeter Avalos 			break;
21599512ac4SPeter Avalos 		case '&':
21699512ac4SPeter Avalos 			if (*++buf != '&') {
21799512ac4SPeter Avalos 				value += ARITH_BAND - '&';
21899512ac4SPeter Avalos 				goto checkeqcur;
21999512ac4SPeter Avalos 			}
22099512ac4SPeter Avalos 			value += ARITH_AND - '&';
22199512ac4SPeter Avalos 			break;
22299512ac4SPeter Avalos 		case '!':
22399512ac4SPeter Avalos 			if (*++buf != '=') {
22499512ac4SPeter Avalos 				value += ARITH_NOT - '!';
22599512ac4SPeter Avalos 				goto out;
22699512ac4SPeter Avalos 			}
22799512ac4SPeter Avalos 			value += ARITH_NE - '!';
22899512ac4SPeter Avalos 			break;
22999512ac4SPeter Avalos 		case 0:
23099512ac4SPeter Avalos 			goto out;
23199512ac4SPeter Avalos 		case '(':
23299512ac4SPeter Avalos 			value += ARITH_LPAREN - '(';
23399512ac4SPeter Avalos 			break;
23499512ac4SPeter Avalos 		case ')':
23599512ac4SPeter Avalos 			value += ARITH_RPAREN - ')';
23699512ac4SPeter Avalos 			break;
23799512ac4SPeter Avalos 		case '*':
23899512ac4SPeter Avalos 			value += ARITH_MUL - '*';
23999512ac4SPeter Avalos 			goto checkeq;
24099512ac4SPeter Avalos 		case '/':
24199512ac4SPeter Avalos 			value += ARITH_DIV - '/';
24299512ac4SPeter Avalos 			goto checkeq;
24399512ac4SPeter Avalos 		case '%':
24499512ac4SPeter Avalos 			value += ARITH_REM - '%';
24599512ac4SPeter Avalos 			goto checkeq;
24699512ac4SPeter Avalos 		case '+':
24702d0b1ceSMatthew Dillon 			if (buf[1] == '+')
24802d0b1ceSMatthew Dillon 				return ARITH_BAD;
24999512ac4SPeter Avalos 			value += ARITH_ADD - '+';
25099512ac4SPeter Avalos 			goto checkeq;
25199512ac4SPeter Avalos 		case '-':
25202d0b1ceSMatthew Dillon 			if (buf[1] == '-')
25302d0b1ceSMatthew Dillon 				return ARITH_BAD;
25499512ac4SPeter Avalos 			value += ARITH_SUB - '-';
25599512ac4SPeter Avalos 			goto checkeq;
25699512ac4SPeter Avalos 		case '~':
25799512ac4SPeter Avalos 			value += ARITH_BNOT - '~';
25899512ac4SPeter Avalos 			break;
25999512ac4SPeter Avalos 		case '^':
26099512ac4SPeter Avalos 			value += ARITH_BXOR - '^';
26199512ac4SPeter Avalos 			goto checkeq;
26299512ac4SPeter Avalos 		case '?':
26399512ac4SPeter Avalos 			value += ARITH_QMARK - '?';
26499512ac4SPeter Avalos 			break;
26599512ac4SPeter Avalos 		case ':':
26699512ac4SPeter Avalos 			value += ARITH_COLON - ':';
26799512ac4SPeter Avalos 			break;
26899512ac4SPeter Avalos 		}
26999512ac4SPeter Avalos 		break;
27099512ac4SPeter Avalos 	}
27199512ac4SPeter Avalos 
27299512ac4SPeter Avalos 	buf++;
27399512ac4SPeter Avalos out:
27499512ac4SPeter Avalos 	arith_buf = buf;
27599512ac4SPeter Avalos 	return value;
27699512ac4SPeter Avalos }
277