vm: restore stacktrace on SIGSEGV
[minix.git] / commands / ash / arith.y
blob50dfd5e29039657e181bb99182e5beb2597d71b7
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: src/bin/sh/arith.y,v 1.19 2004/05/24 10:11:31 stefanf Exp $");
44 #include <limits.h>
45 #include <stdio.h>
48 #include "shell.h"
49 #include "expand.h"
50 #include "var.h"
52 %union {
53 arith_t l_value;
54 char* s_value;
56 %token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
57 %token <s_value> ARITH_VAR
59 %type <l_value> expr
60 %right ARITH_ASSIGN
61 %right ARITH_ADDASSIGN ARITH_SUBASSIGN
62 %right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
63 %right ARITH_RSHASSIGN ARITH_LSHASSIGN
64 %right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
65 %left ARITH_OR
66 %left ARITH_AND
67 %left ARITH_BOR
68 %left ARITH_BXOR
69 %left ARITH_BAND
70 %left ARITH_EQ ARITH_NE
71 %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
72 %left ARITH_LSHIFT ARITH_RSHIFT
73 %left ARITH_ADD ARITH_SUB
74 %left ARITH_MUL ARITH_DIV ARITH_REM
75 %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
78 exp:
79 expr
80 { return ($1); }
83 expr:
84 ARITH_LPAREN expr ARITH_RPAREN
85 { $$ = $2; } |
86 expr ARITH_OR expr
87 { $$ = $1 ? $1 : $3 ? $3 : 0; } |
88 expr ARITH_AND expr
89 { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
90 expr ARITH_BOR expr
91 { $$ = $1 | $3; } |
92 expr ARITH_BXOR expr
93 { $$ = $1 ^ $3; } |
94 expr ARITH_BAND expr
95 { $$ = $1 & $3; } |
96 expr ARITH_EQ expr
97 { $$ = $1 == $3; } |
98 expr ARITH_GT expr
99 { $$ = $1 > $3; } |
100 expr ARITH_GE expr
101 { $$ = $1 >= $3; } |
102 expr ARITH_LT expr
103 { $$ = $1 < $3; } |
104 expr ARITH_LE expr
105 { $$ = $1 <= $3; } |
106 expr ARITH_NE expr
107 { $$ = $1 != $3; } |
108 expr ARITH_LSHIFT expr
109 { $$ = $1 << $3; } |
110 expr ARITH_RSHIFT expr
111 { $$ = $1 >> $3; } |
112 expr ARITH_ADD expr
113 { $$ = $1 + $3; } |
114 expr ARITH_SUB expr
115 { $$ = $1 - $3; } |
116 expr ARITH_MUL expr
117 { $$ = $1 * $3; } |
118 expr ARITH_DIV expr
120 if ($3 == 0)
121 yyerror("division by zero");
122 $$ = $1 / $3;
124 expr ARITH_REM expr
126 if ($3 == 0)
127 yyerror("division by zero");
128 $$ = $1 % $3;
130 ARITH_NOT expr
131 { $$ = !($2); } |
132 ARITH_BNOT expr
133 { $$ = ~($2); } |
134 ARITH_SUB expr %prec ARITH_UNARYMINUS
135 { $$ = -($2); } |
136 ARITH_ADD expr %prec ARITH_UNARYPLUS
137 { $$ = $2; } |
138 ARITH_NUM |
139 ARITH_VAR
141 char *p;
142 arith_t arith_val;
143 char *str_val;
145 if (lookupvar($1) == NULL)
146 setvarsafe($1, "0", 0);
147 str_val = lookupvar($1);
148 arith_val = strtoarith_t(str_val, &p, 0);
150 * Conversion is successful only in case
151 * we've converted _all_ characters.
153 if (*p != '\0')
154 yyerror("variable conversion error");
155 $$ = arith_val;
157 ARITH_VAR ARITH_ASSIGN expr
159 if (arith_assign($1, $3) != 0)
160 yyerror("variable assignment error");
161 $$ = $3;
163 ARITH_VAR ARITH_ADDASSIGN expr
165 arith_t value;
167 value = atoarith_t(lookupvar($1)) + $3;
168 if (arith_assign($1, value) != 0)
169 yyerror("variable assignment error");
170 $$ = value;
172 ARITH_VAR ARITH_SUBASSIGN expr
174 arith_t value;
176 value = atoarith_t(lookupvar($1)) - $3;
177 if (arith_assign($1, value) != 0)
178 yyerror("variable assignment error");
179 $$ = value;
181 ARITH_VAR ARITH_MULASSIGN expr
183 arith_t value;
185 value = atoarith_t(lookupvar($1)) * $3;
186 if (arith_assign($1, value) != 0)
187 yyerror("variable assignment error");
188 $$ = value;
190 ARITH_VAR ARITH_DIVASSIGN expr
192 arith_t value;
194 if ($3 == 0)
195 yyerror("division by zero");
197 value = atoarith_t(lookupvar($1)) / $3;
198 if (arith_assign($1, value) != 0)
199 yyerror("variable assignment error");
200 $$ = value;
202 ARITH_VAR ARITH_REMASSIGN expr
204 arith_t value;
206 if ($3 == 0)
207 yyerror("division by zero");
209 value = atoarith_t(lookupvar($1)) % $3;
210 if (arith_assign($1, value) != 0)
211 yyerror("variable assignment error");
212 $$ = value;
214 ARITH_VAR ARITH_RSHASSIGN expr
216 arith_t value;
218 value = atoarith_t(lookupvar($1)) >> $3;
219 if (arith_assign($1, value) != 0)
220 yyerror("variable assignment error");
221 $$ = value;
223 ARITH_VAR ARITH_LSHASSIGN expr
225 arith_t value;
227 value = atoarith_t(lookupvar($1)) << $3;
228 if (arith_assign($1, value) != 0)
229 yyerror("variable assignment error");
230 $$ = value;
232 ARITH_VAR ARITH_BANDASSIGN expr
234 arith_t value;
236 value = atoarith_t(lookupvar($1)) & $3;
237 if (arith_assign($1, value) != 0)
238 yyerror("variable assignment error");
239 $$ = value;
241 ARITH_VAR ARITH_BXORASSIGN expr
243 arith_t value;
245 value = atoarith_t(lookupvar($1)) ^ $3;
246 if (arith_assign($1, value) != 0)
247 yyerror("variable assignment error");
248 $$ = value;
250 ARITH_VAR ARITH_BORASSIGN expr
252 arith_t value;
254 value = atoarith_t(lookupvar($1)) | $3;
255 if (arith_assign($1, value) != 0)
256 yyerror("variable assignment error");
257 $$ = value;
260 #include "error.h"
261 #include "output.h"
262 #include "memalloc.h"
264 #define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
266 char *arith_buf, *arith_startbuf;
268 int yylex(void);
269 int yyparse(void);
272 arith_assign(char *name, arith_t value)
274 char *str;
275 int ret;
277 str = (char *)ckmalloc(lstrlen(value));
278 sprintf(str, ARITH_FORMAT_STR, value);
279 ret = setvarsafe(name, str, 0);
280 free(str);
281 return ret;
285 arith(char *s)
287 long result;
289 arith_buf = arith_startbuf = s;
291 INTOFF;
292 result = yyparse();
293 arith_lex_reset(); /* Reprime lex. */
294 INTON;
296 return result;
299 void
300 yyerror(char *s)
303 yyerrok;
304 yyclearin;
305 arith_lex_reset(); /* Reprime lex. */
306 error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
310 * The exp(1) builtin.
313 expcmd(int argc, char **argv)
315 char *p;
316 char *concat;
317 char **ap;
318 long i;
320 if (argc > 1) {
321 p = argv[1];
322 if (argc > 2) {
324 * Concatenate arguments.
326 STARTSTACKSTR(concat);
327 ap = argv + 2;
328 for (;;) {
329 while (*p)
330 STPUTC(*p++, concat);
331 if ((p = *ap++) == NULL)
332 break;
333 STPUTC(' ', concat);
335 STPUTC('\0', concat);
336 p = grabstackstr(concat);
338 } else
339 p = "";
341 i = arith(p);
343 out1fmt("%ld\n", i);
344 return !i;
347 /*************************/
348 #ifdef TEST_ARITH
349 #include <stdio.h>
350 main(int argc, char *argv[])
352 printf("%d\n", exp(argv[1]));
355 error(char *s)
357 fprintf(stderr, "exp: %s\n", s);
358 exit(1);
360 #endif