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 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * @(#)arith.y 8.3 (Berkeley) 5/4/95
38 * $FreeBSD: src/bin/sh/arith.y,v 1.21 2005/08/13 07:59:46 stefanf Exp $
39 * $DragonFly: src/bin/sh/arith.y,v 1.5 2007/01/04 14:06:21 pavalos Exp $
53 %token
<l_value
> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
54 %token
<s_value
> ARITH_VAR
58 %right ARITH_ADDASSIGN ARITH_SUBASSIGN
59 %right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
60 %right ARITH_RSHASSIGN ARITH_LSHASSIGN
61 %right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
67 %left ARITH_EQ ARITH_NE
68 %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
69 %left ARITH_LSHIFT ARITH_RSHIFT
70 %left ARITH_ADD ARITH_SUB
71 %left ARITH_MUL ARITH_DIV ARITH_REM
72 %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
81 ARITH_LPAREN expr ARITH_RPAREN
84 { $$
= $1 ?
$1 : $3 ?
$3 : 0; } |
86 { $$
= $1 ?
( $3 ?
$3 : 0 ) : 0; } |
105 expr ARITH_LSHIFT expr
107 expr ARITH_RSHIFT expr
118 yyerror("division by zero");
124 yyerror("division by zero");
131 ARITH_SUB expr %prec ARITH_UNARYMINUS
133 ARITH_ADD expr %prec ARITH_UNARYPLUS
142 if
(lookupvar
($1) == NULL
)
143 setvarsafe
($1, "0", 0);
144 str_val
= lookupvar
($1);
145 arith_val
= strtoarith_t
(str_val
, &p
, 0);
147 * Conversion is successful only in case
148 * we've converted _all_ characters.
151 yyerror("variable conversion error");
154 ARITH_VAR ARITH_ASSIGN expr
156 if
(arith_assign
($1, $3) != 0)
157 yyerror("variable assignment error");
160 ARITH_VAR ARITH_ADDASSIGN expr
164 value
= atoarith_t
(lookupvar
($1)) + $3;
165 if
(arith_assign
($1, value
) != 0)
166 yyerror("variable assignment error");
169 ARITH_VAR ARITH_SUBASSIGN expr
173 value
= atoarith_t
(lookupvar
($1)) - $3;
174 if
(arith_assign
($1, value
) != 0)
175 yyerror("variable assignment error");
178 ARITH_VAR ARITH_MULASSIGN expr
182 value
= atoarith_t
(lookupvar
($1)) * $3;
183 if
(arith_assign
($1, value
) != 0)
184 yyerror("variable assignment error");
187 ARITH_VAR ARITH_DIVASSIGN expr
192 yyerror("division by zero");
194 value
= atoarith_t
(lookupvar
($1)) / $3;
195 if
(arith_assign
($1, value
) != 0)
196 yyerror("variable assignment error");
199 ARITH_VAR ARITH_REMASSIGN expr
204 yyerror("division by zero");
206 value
= atoarith_t
(lookupvar
($1)) %
$3;
207 if
(arith_assign
($1, value
) != 0)
208 yyerror("variable assignment error");
211 ARITH_VAR ARITH_RSHASSIGN expr
215 value
= atoarith_t
(lookupvar
($1)) >> $3;
216 if
(arith_assign
($1, value
) != 0)
217 yyerror("variable assignment error");
220 ARITH_VAR ARITH_LSHASSIGN expr
224 value
= atoarith_t
(lookupvar
($1)) << $3;
225 if
(arith_assign
($1, value
) != 0)
226 yyerror("variable assignment error");
229 ARITH_VAR ARITH_BANDASSIGN expr
233 value
= atoarith_t
(lookupvar
($1)) & $3;
234 if
(arith_assign
($1, value
) != 0)
235 yyerror("variable assignment error");
238 ARITH_VAR ARITH_BXORASSIGN expr
242 value
= atoarith_t
(lookupvar
($1)) ^
$3;
243 if
(arith_assign
($1, value
) != 0)
244 yyerror("variable assignment error");
247 ARITH_VAR ARITH_BORASSIGN expr
251 value
= atoarith_t
(lookupvar
($1)) |
$3;
252 if
(arith_assign
($1, value
) != 0)
253 yyerror("variable assignment error");
259 #include "memalloc.h"
261 #define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
263 const char *arith_buf
, *arith_startbuf
;
267 static void yyerror(const char *s
);
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. */
298 yyerror(const char *s
)
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
);