sh: Sync with FreeBSD
[dragonfly.git] / bin / sh / arith_yylex.c
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 "shell.h"
39 #include "arith_yacc.h"
40 #include "expand.h"
41 #include "error.h"
42 #include "memalloc.h"
43 #include "parser.h"
44 #include "syntax.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
53 yylex(void)
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 = strtoarith_t(buf,
80                             __DECONST(char **, &arith_buf), 0);
81                         return ARITH_NUM;
82                 case 'A':
83                 case 'B':
84                 case 'C':
85                 case 'D':
86                 case 'E':
87                 case 'F':
88                 case 'G':
89                 case 'H':
90                 case 'I':
91                 case 'J':
92                 case 'K':
93                 case 'L':
94                 case 'M':
95                 case 'N':
96                 case 'O':
97                 case 'P':
98                 case 'Q':
99                 case 'R':
100                 case 'S':
101                 case 'T':
102                 case 'U':
103                 case 'V':
104                 case 'W':
105                 case 'X':
106                 case 'Y':
107                 case 'Z':
108                 case '_':
109                 case 'a':
110                 case 'b':
111                 case 'c':
112                 case 'd':
113                 case 'e':
114                 case 'f':
115                 case 'g':
116                 case 'h':
117                 case 'i':
118                 case 'j':
119                 case 'k':
120                 case 'l':
121                 case 'm':
122                 case 'n':
123                 case 'o':
124                 case 'p':
125                 case 'q':
126                 case 'r':
127                 case 's':
128                 case 't':
129                 case 'u':
130                 case 'v':
131                 case 'w':
132                 case 'x':
133                 case 'y':
134                 case 'z':
135                         p = buf;
136                         while (buf++, is_in_name(*buf))
137                                 ;
138                         yylval.name = stalloc(buf - p + 1);
139                         memcpy(yylval.name, p, buf - p);
140                         yylval.name[buf - p] = '\0';
141                         value = ARITH_VAR;
142                         goto out;
143                 case '=':
144                         value += ARITH_ASS - '=';
145 checkeq:
146                         buf++;
147 checkeqcur:
148                         if (*buf != '=')
149                                 goto out;
150                         value += 11;
151                         break;
152                 case '>':
153                         switch (*++buf) {
154                         case '=':
155                                 value += ARITH_GE - '>';
156                                 break;
157                         case '>':
158                                 value += ARITH_RSHIFT - '>';
159                                 goto checkeq;
160                         default:
161                                 value += ARITH_GT - '>';
162                                 goto out;
163                         }
164                         break;
165                 case '<':
166                         switch (*++buf) {
167                         case '=':
168                                 value += ARITH_LE - '<';
169                                 break;
170                         case '<':
171                                 value += ARITH_LSHIFT - '<';
172                                 goto checkeq;
173                         default:
174                                 value += ARITH_LT - '<';
175                                 goto out;
176                         }
177                         break;
178                 case '|':
179                         if (*++buf != '|') {
180                                 value += ARITH_BOR - '|';
181                                 goto checkeqcur;
182                         }
183                         value += ARITH_OR - '|';
184                         break;
185                 case '&':
186                         if (*++buf != '&') {
187                                 value += ARITH_BAND - '&';
188                                 goto checkeqcur;
189                         }
190                         value += ARITH_AND - '&';
191                         break;
192                 case '!':
193                         if (*++buf != '=') {
194                                 value += ARITH_NOT - '!';
195                                 goto out;
196                         }
197                         value += ARITH_NE - '!';
198                         break;
199                 case 0:
200                         goto out;
201                 case '(':
202                         value += ARITH_LPAREN - '(';
203                         break;
204                 case ')':
205                         value += ARITH_RPAREN - ')';
206                         break;
207                 case '*':
208                         value += ARITH_MUL - '*';
209                         goto checkeq;
210                 case '/':
211                         value += ARITH_DIV - '/';
212                         goto checkeq;
213                 case '%':
214                         value += ARITH_REM - '%';
215                         goto checkeq;
216                 case '+':
217                         value += ARITH_ADD - '+';
218                         goto checkeq;
219                 case '-':
220                         value += ARITH_SUB - '-';
221                         goto checkeq;
222                 case '~':
223                         value += ARITH_BNOT - '~';
224                         break;
225                 case '^':
226                         value += ARITH_BXOR - '^';
227                         goto checkeq;
228                 case '?':
229                         value += ARITH_QMARK - '?';
230                         break;
231                 case ':':
232                         value += ARITH_COLON - ':';
233                         break;
234                 }
235                 break;
236         }
237
238         buf++;
239 out:
240         arith_buf = buf;
241         return value;
242 }