New rldt() to go with lldt()
[freebsd-src/fkvm-freebsd.git] / bin / sh / arith.y
blob542fc445a8a7a33bbaa5870d62d5fc85ea68a027
1 %{
2 /*-
3 * Copyright (c) 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Kenneth Almquist.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #if 0
35 #ifndef lint
36 static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
37 #endif
38 #endif /* not lint */
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
43 #include <limits.h>
44 #include <stdio.h>
46 #include "arith.h"
47 #include "shell.h"
48 #include "var.h"
50 %union {
51 arith_t l_value;
52 char* s_value;
54 %token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
55 %token <s_value> ARITH_VAR
57 %type <l_value> expr
58 %right ARITH_ASSIGN
59 %right ARITH_ADDASSIGN ARITH_SUBASSIGN
60 %right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
61 %right ARITH_RSHASSIGN ARITH_LSHASSIGN
62 %right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
63 %left ARITH_OR
64 %left ARITH_AND
65 %left ARITH_BOR
66 %left ARITH_BXOR
67 %left ARITH_BAND
68 %left ARITH_EQ ARITH_NE
69 %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
70 %left ARITH_LSHIFT ARITH_RSHIFT
71 %left ARITH_ADD ARITH_SUB
72 %left ARITH_MUL ARITH_DIV ARITH_REM
73 %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
76 exp:
77 expr
79 *YYPARSE_PARAM = $1;
80 return (0);
84 expr:
85 ARITH_LPAREN expr ARITH_RPAREN
86 { $$ = $2; } |
87 expr ARITH_OR expr
88 { $$ = $1 ? $1 : $3 ? $3 : 0; } |
89 expr ARITH_AND expr
90 { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
91 expr ARITH_BOR expr
92 { $$ = $1 | $3; } |
93 expr ARITH_BXOR expr
94 { $$ = $1 ^ $3; } |
95 expr ARITH_BAND expr
96 { $$ = $1 & $3; } |
97 expr ARITH_EQ expr
98 { $$ = $1 == $3; } |
99 expr ARITH_GT expr
100 { $$ = $1 > $3; } |
101 expr ARITH_GE expr
102 { $$ = $1 >= $3; } |
103 expr ARITH_LT expr
104 { $$ = $1 < $3; } |
105 expr ARITH_LE expr
106 { $$ = $1 <= $3; } |
107 expr ARITH_NE expr
108 { $$ = $1 != $3; } |
109 expr ARITH_LSHIFT expr
110 { $$ = $1 << $3; } |
111 expr ARITH_RSHIFT expr
112 { $$ = $1 >> $3; } |
113 expr ARITH_ADD expr
114 { $$ = $1 + $3; } |
115 expr ARITH_SUB expr
116 { $$ = $1 - $3; } |
117 expr ARITH_MUL expr
118 { $$ = $1 * $3; } |
119 expr ARITH_DIV expr
121 if ($3 == 0)
122 yyerror("division by zero");
123 $$ = $1 / $3;
125 expr ARITH_REM expr
127 if ($3 == 0)
128 yyerror("division by zero");
129 $$ = $1 % $3;
131 ARITH_NOT expr
132 { $$ = !($2); } |
133 ARITH_BNOT expr
134 { $$ = ~($2); } |
135 ARITH_SUB expr %prec ARITH_UNARYMINUS
136 { $$ = -($2); } |
137 ARITH_ADD expr %prec ARITH_UNARYPLUS
138 { $$ = $2; } |
139 ARITH_NUM |
140 ARITH_VAR
142 char *p;
143 arith_t arith_val;
144 char *str_val;
146 if (lookupvar($1) == NULL)
147 setvarsafe($1, "0", 0);
148 str_val = lookupvar($1);
149 arith_val = strtoarith_t(str_val, &p, 0);
151 * Conversion is successful only in case
152 * we've converted _all_ characters.
154 if (*p != '\0')
155 yyerror("variable conversion error");
156 $$ = arith_val;
158 ARITH_VAR ARITH_ASSIGN expr
160 if (arith_assign($1, $3) != 0)
161 yyerror("variable assignment error");
162 $$ = $3;
164 ARITH_VAR ARITH_ADDASSIGN expr
166 arith_t value;
168 value = atoarith_t(lookupvar($1)) + $3;
169 if (arith_assign($1, value) != 0)
170 yyerror("variable assignment error");
171 $$ = value;
173 ARITH_VAR ARITH_SUBASSIGN expr
175 arith_t value;
177 value = atoarith_t(lookupvar($1)) - $3;
178 if (arith_assign($1, value) != 0)
179 yyerror("variable assignment error");
180 $$ = value;
182 ARITH_VAR ARITH_MULASSIGN expr
184 arith_t value;
186 value = atoarith_t(lookupvar($1)) * $3;
187 if (arith_assign($1, value) != 0)
188 yyerror("variable assignment error");
189 $$ = value;
191 ARITH_VAR ARITH_DIVASSIGN expr
193 arith_t value;
195 if ($3 == 0)
196 yyerror("division by zero");
198 value = atoarith_t(lookupvar($1)) / $3;
199 if (arith_assign($1, value) != 0)
200 yyerror("variable assignment error");
201 $$ = value;
203 ARITH_VAR ARITH_REMASSIGN expr
205 arith_t value;
207 if ($3 == 0)
208 yyerror("division by zero");
210 value = atoarith_t(lookupvar($1)) % $3;
211 if (arith_assign($1, value) != 0)
212 yyerror("variable assignment error");
213 $$ = value;
215 ARITH_VAR ARITH_RSHASSIGN expr
217 arith_t value;
219 value = atoarith_t(lookupvar($1)) >> $3;
220 if (arith_assign($1, value) != 0)
221 yyerror("variable assignment error");
222 $$ = value;
224 ARITH_VAR ARITH_LSHASSIGN expr
226 arith_t value;
228 value = atoarith_t(lookupvar($1)) << $3;
229 if (arith_assign($1, value) != 0)
230 yyerror("variable assignment error");
231 $$ = value;
233 ARITH_VAR ARITH_BANDASSIGN expr
235 arith_t value;
237 value = atoarith_t(lookupvar($1)) & $3;
238 if (arith_assign($1, value) != 0)
239 yyerror("variable assignment error");
240 $$ = value;
242 ARITH_VAR ARITH_BXORASSIGN expr
244 arith_t value;
246 value = atoarith_t(lookupvar($1)) ^ $3;
247 if (arith_assign($1, value) != 0)
248 yyerror("variable assignment error");
249 $$ = value;
251 ARITH_VAR ARITH_BORASSIGN expr
253 arith_t value;
255 value = atoarith_t(lookupvar($1)) | $3;
256 if (arith_assign($1, value) != 0)
257 yyerror("variable assignment error");
258 $$ = value;
261 #include "error.h"
262 #include "output.h"
263 #include "memalloc.h"
265 #define YYPARSE_PARAM_TYPE arith_t *
266 #define YYPARSE_PARAM result
268 char *arith_buf, *arith_startbuf;
270 int yylex(void);
271 int yyparse(YYPARSE_PARAM_TYPE);
273 static int
274 arith_assign(char *name, arith_t value)
276 char *str;
277 int ret;
279 str = (char *)ckmalloc(DIGITS(value));
280 sprintf(str, ARITH_FORMAT_STR, value);
281 ret = setvarsafe(name, str, 0);
282 free(str);
283 return ret;
286 arith_t
287 arith(char *s)
289 arith_t result;
291 arith_buf = arith_startbuf = s;
293 INTOFF;
294 yyparse(&result);
295 arith_lex_reset(); /* Reprime lex. */
296 INTON;
298 return result;
301 static void
302 yyerror(char *s)
305 yyerrok;
306 yyclearin;
307 arith_lex_reset(); /* Reprime lex. */
308 error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
312 * The exp(1) builtin.
315 expcmd(int argc, char **argv)
317 char *p;
318 char *concat;
319 char **ap;
320 arith_t i;
322 if (argc > 1) {
323 p = argv[1];
324 if (argc > 2) {
326 * Concatenate arguments.
328 STARTSTACKSTR(concat);
329 ap = argv + 2;
330 for (;;) {
331 while (*p)
332 STPUTC(*p++, concat);
333 if ((p = *ap++) == NULL)
334 break;
335 STPUTC(' ', concat);
337 STPUTC('\0', concat);
338 p = grabstackstr(concat);
340 } else
341 p = "";
343 i = arith(p);
345 out1fmt(ARITH_FORMAT_STR "\n", i);
346 return !i;
349 /*************************/
350 #ifdef TEST_ARITH
351 #include <stdio.h>
352 main(int argc, char *argv[])
354 printf("%d\n", exp(argv[1]));
357 error(char *s)
359 fprintf(stderr, "exp: %s\n", s);
360 exit(1);
362 #endif