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