4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
36 static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
54 %token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
55 %token <s_value> ARITH_VAR
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
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
82 ARITH_LPAREN expr ARITH_RPAREN
85 { $$ = $1 ? $1 : $3 ? $3 : 0; } |
87 { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
106 expr ARITH_LSHIFT expr
108 expr ARITH_RSHIFT expr
119 yyerror("division by zero");
125 yyerror("division by zero");
132 ARITH_SUB expr %prec ARITH_UNARYMINUS
134 ARITH_ADD expr %prec ARITH_UNARYPLUS
143 if (lookupvar($1) == NULL)
144 setvarsafe($1, "0", 0);
145 str_val = lookupvar($1);
146 arith_val = strtoarith_t(str_val, &p, 0);
148 * Conversion is successful only in case
149 * we've converted _all_ characters.
152 yyerror("variable conversion error");
155 ARITH_VAR ARITH_ASSIGN expr
157 if (arith_assign($1, $3) != 0)
158 yyerror("variable assignment error");
161 ARITH_VAR ARITH_ADDASSIGN expr
165 value = atoarith_t(lookupvar($1)) + $3;
166 if (arith_assign($1, value) != 0)
167 yyerror("variable assignment error");
170 ARITH_VAR ARITH_SUBASSIGN expr
174 value = atoarith_t(lookupvar($1)) - $3;
175 if (arith_assign($1, value) != 0)
176 yyerror("variable assignment error");
179 ARITH_VAR ARITH_MULASSIGN expr
183 value = atoarith_t(lookupvar($1)) * $3;
184 if (arith_assign($1, value) != 0)
185 yyerror("variable assignment error");
188 ARITH_VAR ARITH_DIVASSIGN expr
193 yyerror("division by zero");
195 value = atoarith_t(lookupvar($1)) / $3;
196 if (arith_assign($1, value) != 0)
197 yyerror("variable assignment error");
200 ARITH_VAR ARITH_REMASSIGN expr
205 yyerror("division by zero");
207 value = atoarith_t(lookupvar($1)) % $3;
208 if (arith_assign($1, value) != 0)
209 yyerror("variable assignment error");
212 ARITH_VAR ARITH_RSHASSIGN expr
216 value = atoarith_t(lookupvar($1)) >> $3;
217 if (arith_assign($1, value) != 0)
218 yyerror("variable assignment error");
221 ARITH_VAR ARITH_LSHASSIGN expr
225 value = atoarith_t(lookupvar($1)) << $3;
226 if (arith_assign($1, value) != 0)
227 yyerror("variable assignment error");
230 ARITH_VAR ARITH_BANDASSIGN expr
234 value = atoarith_t(lookupvar($1)) & $3;
235 if (arith_assign($1, value) != 0)
236 yyerror("variable assignment error");
239 ARITH_VAR ARITH_BXORASSIGN expr
243 value = atoarith_t(lookupvar($1)) ^ $3;
244 if (arith_assign($1, value) != 0)
245 yyerror("variable assignment error");
248 ARITH_VAR ARITH_BORASSIGN expr
252 value = atoarith_t(lookupvar($1)) | $3;
253 if (arith_assign($1, value) != 0)
254 yyerror("variable assignment error");
260 #include "memalloc.h"
262 #define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
264 char *arith_buf, *arith_startbuf;
270 arith_assign(char *name, arith_t value)
275 str = (char *)ckmalloc(lstrlen(value));
276 sprintf(str, ARITH_FORMAT_STR, value);
277 ret = setvarsafe(name, str, 0);
287 arith_buf = arith_startbuf = s;
291 arith_lex_reset(); /* Reprime lex. */
303 arith_lex_reset(); /* Reprime lex. */
304 error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
308 * The exp(1) builtin.
311 expcmd(int argc, char **argv)
322 * Concatenate arguments.
324 STARTSTACKSTR(concat);
328 STPUTC(*p++, concat);
329 if ((p = *ap++) == NULL)
333 STPUTC('\0', concat);
334 p = grabstackstr(concat);
345 /*************************/
348 main(int argc, char *argv[])
350 printf("%d\n", exp(argv[1]));
355 fprintf(stderr, "exp: %s\n", s);