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
85 ARITH_LPAREN expr ARITH_RPAREN
88 { $$
= $1 ?
$1 : $3 ?
$3 : 0; } |
90 { $$
= $1 ?
( $3 ?
$3 : 0 ) : 0; } |
109 expr ARITH_LSHIFT expr
111 expr ARITH_RSHIFT expr
122 yyerror("division by zero");
128 yyerror("division by zero");
135 ARITH_SUB expr %prec ARITH_UNARYMINUS
137 ARITH_ADD expr %prec ARITH_UNARYPLUS
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.
155 yyerror("variable conversion error");
158 ARITH_VAR ARITH_ASSIGN expr
160 if
(arith_assign
($1, $3) != 0)
161 yyerror("variable assignment error");
164 ARITH_VAR ARITH_ADDASSIGN expr
168 value
= atoarith_t
(lookupvar
($1)) + $3;
169 if
(arith_assign
($1, value
) != 0)
170 yyerror("variable assignment error");
173 ARITH_VAR ARITH_SUBASSIGN expr
177 value
= atoarith_t
(lookupvar
($1)) - $3;
178 if
(arith_assign
($1, value
) != 0)
179 yyerror("variable assignment error");
182 ARITH_VAR ARITH_MULASSIGN expr
186 value
= atoarith_t
(lookupvar
($1)) * $3;
187 if
(arith_assign
($1, value
) != 0)
188 yyerror("variable assignment error");
191 ARITH_VAR ARITH_DIVASSIGN expr
196 yyerror("division by zero");
198 value
= atoarith_t
(lookupvar
($1)) / $3;
199 if
(arith_assign
($1, value
) != 0)
200 yyerror("variable assignment error");
203 ARITH_VAR ARITH_REMASSIGN expr
208 yyerror("division by zero");
210 value
= atoarith_t
(lookupvar
($1)) %
$3;
211 if
(arith_assign
($1, value
) != 0)
212 yyerror("variable assignment error");
215 ARITH_VAR ARITH_RSHASSIGN expr
219 value
= atoarith_t
(lookupvar
($1)) >> $3;
220 if
(arith_assign
($1, value
) != 0)
221 yyerror("variable assignment error");
224 ARITH_VAR ARITH_LSHASSIGN expr
228 value
= atoarith_t
(lookupvar
($1)) << $3;
229 if
(arith_assign
($1, value
) != 0)
230 yyerror("variable assignment error");
233 ARITH_VAR ARITH_BANDASSIGN expr
237 value
= atoarith_t
(lookupvar
($1)) & $3;
238 if
(arith_assign
($1, value
) != 0)
239 yyerror("variable assignment error");
242 ARITH_VAR ARITH_BXORASSIGN expr
246 value
= atoarith_t
(lookupvar
($1)) ^
$3;
247 if
(arith_assign
($1, value
) != 0)
248 yyerror("variable assignment error");
251 ARITH_VAR ARITH_BORASSIGN expr
255 value
= atoarith_t
(lookupvar
($1)) |
$3;
256 if
(arith_assign
($1, value
) != 0)
257 yyerror("variable assignment error");
263 #include "memalloc.h"
265 #define YYPARSE_PARAM_TYPE arith_t *
266 #define YYPARSE_PARAM result
268 char *arith_buf
, *arith_startbuf
;
271 int yyparse(YYPARSE_PARAM_TYPE
);
274 arith_assign
(char *name
, arith_t value
)
279 str
= (char *)ckmalloc
(DIGITS
(value
));
280 sprintf
(str
, ARITH_FORMAT_STR
, value
);
281 ret
= setvarsafe
(name
, str
, 0);
291 arith_buf
= arith_startbuf
= s
;
295 arith_lex_reset
(); /* Reprime lex. */
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
)
326 * Concatenate arguments.
328 STARTSTACKSTR
(concat
);
332 STPUTC
(*p
++, concat
);
333 if
((p
= *ap
++) == NULL
)
337 STPUTC
('\0', concat
);
338 p
= grabstackstr
(concat
);
345 out1fmt
(ARITH_FORMAT_STR
"\n", i
);
349 /*************************/
352 main
(int argc
, char *argv
[])
354 printf
("%d\n", exp
(argv
[1]));
359 fprintf
(stderr
, "exp: %s\n", s
);