]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - bin/sh/arith_yylex.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.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 <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <inttypes.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include "shell.h"
42 #include "arith_yacc.h"
43 #include "expand.h"
44 #include "error.h"
45 #include "memalloc.h"
46 #include "parser.h"
47 #include "syntax.h"
48
49 #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
50 #error Arithmetic tokens are out of order.
51 #endif
52
53 extern const char *arith_buf;
54
55 int
56 yylex(void)
57 {
58         int value;
59         const char *buf = arith_buf;
60         char *end;
61         const char *p;
62
63         for (;;) {
64                 value = *buf;
65                 switch (value) {
66                 case ' ':
67                 case '\t':
68                 case '\n':
69                         buf++;
70                         continue;
71                 default:
72                         return ARITH_BAD;
73                 case '0':
74                 case '1':
75                 case '2':
76                 case '3':
77                 case '4':
78                 case '5':
79                 case '6':
80                 case '7':
81                 case '8':
82                 case '9':
83                         yylval.val = strtoarith_t(buf, &end, 0);
84                         arith_buf = end;
85                         return ARITH_NUM;
86                 case 'A':
87                 case 'B':
88                 case 'C':
89                 case 'D':
90                 case 'E':
91                 case 'F':
92                 case 'G':
93                 case 'H':
94                 case 'I':
95                 case 'J':
96                 case 'K':
97                 case 'L':
98                 case 'M':
99                 case 'N':
100                 case 'O':
101                 case 'P':
102                 case 'Q':
103                 case 'R':
104                 case 'S':
105                 case 'T':
106                 case 'U':
107                 case 'V':
108                 case 'W':
109                 case 'X':
110                 case 'Y':
111                 case 'Z':
112                 case '_':
113                 case 'a':
114                 case 'b':
115                 case 'c':
116                 case 'd':
117                 case 'e':
118                 case 'f':
119                 case 'g':
120                 case 'h':
121                 case 'i':
122                 case 'j':
123                 case 'k':
124                 case 'l':
125                 case 'm':
126                 case 'n':
127                 case 'o':
128                 case 'p':
129                 case 'q':
130                 case 'r':
131                 case 's':
132                 case 't':
133                 case 'u':
134                 case 'v':
135                 case 'w':
136                 case 'x':
137                 case 'y':
138                 case 'z':
139                         p = buf;
140                         while (buf++, is_in_name(*buf))
141                                 ;
142                         yylval.name = stalloc(buf - p + 1);
143                         memcpy(yylval.name, p, buf - p);
144                         yylval.name[buf - p] = '\0';
145                         value = ARITH_VAR;
146                         goto out;
147                 case '=':
148                         value += ARITH_ASS - '=';
149 checkeq:
150                         buf++;
151 checkeqcur:
152                         if (*buf != '=')
153                                 goto out;
154                         value += 11;
155                         break;
156                 case '>':
157                         switch (*++buf) {
158                         case '=':
159                                 value += ARITH_GE - '>';
160                                 break;
161                         case '>':
162                                 value += ARITH_RSHIFT - '>';
163                                 goto checkeq;
164                         default:
165                                 value += ARITH_GT - '>';
166                                 goto out;
167                         }
168                         break;
169                 case '<':
170                         switch (*++buf) {
171                         case '=':
172                                 value += ARITH_LE - '<';
173                                 break;
174                         case '<':
175                                 value += ARITH_LSHIFT - '<';
176                                 goto checkeq;
177                         default:
178                                 value += ARITH_LT - '<';
179                                 goto out;
180                         }
181                         break;
182                 case '|':
183                         if (*++buf != '|') {
184                                 value += ARITH_BOR - '|';
185                                 goto checkeqcur;
186                         }
187                         value += ARITH_OR - '|';
188                         break;
189                 case '&':
190                         if (*++buf != '&') {
191                                 value += ARITH_BAND - '&';
192                                 goto checkeqcur;
193                         }
194                         value += ARITH_AND - '&';
195                         break;
196                 case '!':
197                         if (*++buf != '=') {
198                                 value += ARITH_NOT - '!';
199                                 goto out;
200                         }
201                         value += ARITH_NE - '!';
202                         break;
203                 case 0:
204                         goto out;
205                 case '(':
206                         value += ARITH_LPAREN - '(';
207                         break;
208                 case ')':
209                         value += ARITH_RPAREN - ')';
210                         break;
211                 case '*':
212                         value += ARITH_MUL - '*';
213                         goto checkeq;
214                 case '/':
215                         value += ARITH_DIV - '/';
216                         goto checkeq;
217                 case '%':
218                         value += ARITH_REM - '%';
219                         goto checkeq;
220                 case '+':
221                         if (buf[1] == '+')
222                                 return ARITH_BAD;
223                         value += ARITH_ADD - '+';
224                         goto checkeq;
225                 case '-':
226                         if (buf[1] == '-')
227                                 return ARITH_BAD;
228                         value += ARITH_SUB - '-';
229                         goto checkeq;
230                 case '~':
231                         value += ARITH_BNOT - '~';
232                         break;
233                 case '^':
234                         value += ARITH_BXOR - '^';
235                         goto checkeq;
236                 case '?':
237                         value += ARITH_QMARK - '?';
238                         break;
239                 case ':':
240                         value += ARITH_COLON - ':';
241                         break;
242                 }
243                 break;
244         }
245
246         buf++;
247 out:
248         arith_buf = buf;
249         return value;
250 }