74a334c040c3a07bd7ef87bd28c94e0242c62c64
[dragonfly.git] / bin / sh / arith.y
1 %token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
2
3 %left ARITH_OR
4 %left ARITH_AND
5 %left ARITH_BOR
6 %left ARITH_BXOR
7 %left ARITH_BAND
8 %left ARITH_EQ ARITH_NE
9 %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
10 %left ARITH_LSHIFT ARITH_RSHIFT
11 %left ARITH_ADD ARITH_SUB
12 %left ARITH_MUL ARITH_DIV ARITH_REM
13 %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
14 %%
15
16 exp:    expr = {
17                         return ($1);
18                 }
19         ;
20
21
22 expr:   ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
23         | expr ARITH_OR expr    = { $$ = $1 ? $1 : $3 ? $3 : 0; }
24         | expr ARITH_AND expr   = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
25         | expr ARITH_BOR expr   = { $$ = $1 | $3; }
26         | expr ARITH_BXOR expr  = { $$ = $1 ^ $3; }
27         | expr ARITH_BAND expr  = { $$ = $1 & $3; }
28         | expr ARITH_EQ expr    = { $$ = $1 == $3; }
29         | expr ARITH_GT expr    = { $$ = $1 > $3; }
30         | expr ARITH_GE expr    = { $$ = $1 >= $3; }
31         | expr ARITH_LT expr    = { $$ = $1 < $3; }
32         | expr ARITH_LE expr    = { $$ = $1 <= $3; }
33         | expr ARITH_NE expr    = { $$ = $1 != $3; }
34         | expr ARITH_LSHIFT expr = { $$ = $1 << $3; }
35         | expr ARITH_RSHIFT expr = { $$ = $1 >> $3; }
36         | expr ARITH_ADD expr   = { $$ = $1 + $3; }
37         | expr ARITH_SUB expr   = { $$ = $1 - $3; }
38         | expr ARITH_MUL expr   = { $$ = $1 * $3; }
39         | expr ARITH_DIV expr   = {
40                         if ($3 == 0)
41                                 yyerror("division by zero");
42                         $$ = $1 / $3;
43                         }
44         | expr ARITH_REM expr   = {
45                         if ($3 == 0)
46                                 yyerror("division by zero");
47                         $$ = $1 % $3;
48                         }
49         | ARITH_NOT expr        = { $$ = !($2); }
50         | ARITH_BNOT expr       = { $$ = ~($2); }
51         | ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
52         | ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
53         | ARITH_NUM
54         ;
55 %%
56 /*-
57  * Copyright (c) 1993
58  *      The Regents of the University of California.  All rights reserved.
59  *
60  * This code is derived from software contributed to Berkeley by
61  * Kenneth Almquist.
62  *
63  * Redistribution and use in source and binary forms, with or without
64  * modification, are permitted provided that the following conditions
65  * are met:
66  * 1. Redistributions of source code must retain the above copyright
67  *    notice, this list of conditions and the following disclaimer.
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in the
70  *    documentation and/or other materials provided with the distribution.
71  * 3. All advertising materials mentioning features or use of this software
72  *    must display the following acknowledgement:
73  *      This product includes software developed by the University of
74  *      California, Berkeley and its contributors.
75  * 4. Neither the name of the University nor the names of its contributors
76  *    may be used to endorse or promote products derived from this software
77  *    without specific prior written permission.
78  *
79  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89  * SUCH DAMAGE.
90  *
91  * @(#)arith.y  8.3 (Berkeley) 5/4/95
92  * $FreeBSD: src/bin/sh/arith.y,v 1.10.2.2 2002/07/19 04:38:51 tjr Exp $
93  * $DragonFly: src/bin/sh/arith.y,v 1.2 2003/06/17 04:22:50 dillon Exp $
94  */
95
96 #include "shell.h"
97 #include "error.h"
98 #include "output.h"
99 #include "memalloc.h"
100
101 char *arith_buf, *arith_startbuf;
102 extern void arith_lex_reset();
103
104 int yylex(void);
105 int yyparse(void);
106
107 int
108 arith(char *s)
109 {
110         long result;
111
112         arith_buf = arith_startbuf = s;
113
114         INTOFF;
115         result = yyparse();
116         arith_lex_reset();      /* reprime lex */
117         INTON;
118
119         return (result);
120 }
121
122 void
123 yyerror(char *s)
124 {
125
126         yyerrok;
127         yyclearin;
128         arith_lex_reset();      /* reprime lex */
129         error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
130 }
131
132 /*
133  *  The exp(1) builtin.
134  */
135 int
136 expcmd(int argc, char **argv)
137 {
138         char *p;
139         char *concat;
140         char **ap;
141         long i;
142
143         if (argc > 1) {
144                 p = argv[1];
145                 if (argc > 2) {
146                         /*
147                          * concatenate arguments
148                          */
149                         STARTSTACKSTR(concat);
150                         ap = argv + 2;
151                         for (;;) {
152                                 while (*p)
153                                         STPUTC(*p++, concat);
154                                 if ((p = *ap++) == NULL)
155                                         break;
156                                 STPUTC(' ', concat);
157                         }
158                         STPUTC('\0', concat);
159                         p = grabstackstr(concat);
160                 }
161         } else
162                 p = "";
163
164         i = arith(p);
165
166         out1fmt("%ld\n", i);
167         return (! i);
168 }
169
170 /*************************/
171 #ifdef TEST_ARITH
172 #include <stdio.h>
173 main(int argc, char *argv[])
174 {
175         printf("%d\n", exp(argv[1]));
176 }
177
178 error(char *s)
179 {
180         fprintf(stderr, "exp: %s\n", s);
181         exit(1);
182 }
183 #endif