Initial import from FreeBSD RELENG_4:
[games.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
92 #ifndef lint
93 #if 0
94 static char sccsid[] = "@(#)arith.y     8.3 (Berkeley) 5/4/95";
95 #endif
96 static const char rcsid[] =
97   "$FreeBSD: src/bin/sh/arith.y,v 1.10.2.2 2002/07/19 04:38:51 tjr Exp $";
98 #endif /* not lint */
99
100 #include "shell.h"
101 #include "error.h"
102 #include "output.h"
103 #include "memalloc.h"
104
105 char *arith_buf, *arith_startbuf;
106 extern void arith_lex_reset();
107
108 int yylex(void);
109 int yyparse(void);
110
111 int
112 arith(char *s)
113 {
114         long result;
115
116         arith_buf = arith_startbuf = s;
117
118         INTOFF;
119         result = yyparse();
120         arith_lex_reset();      /* reprime lex */
121         INTON;
122
123         return (result);
124 }
125
126 void
127 yyerror(char *s)
128 {
129
130         yyerrok;
131         yyclearin;
132         arith_lex_reset();      /* reprime lex */
133         error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
134 }
135
136 /*
137  *  The exp(1) builtin.
138  */
139 int
140 expcmd(int argc, char **argv)
141 {
142         char *p;
143         char *concat;
144         char **ap;
145         long i;
146
147         if (argc > 1) {
148                 p = argv[1];
149                 if (argc > 2) {
150                         /*
151                          * concatenate arguments
152                          */
153                         STARTSTACKSTR(concat);
154                         ap = argv + 2;
155                         for (;;) {
156                                 while (*p)
157                                         STPUTC(*p++, concat);
158                                 if ((p = *ap++) == NULL)
159                                         break;
160                                 STPUTC(' ', concat);
161                         }
162                         STPUTC('\0', concat);
163                         p = grabstackstr(concat);
164                 }
165         } else
166                 p = "";
167
168         i = arith(p);
169
170         out1fmt("%ld\n", i);
171         return (! i);
172 }
173
174 /*************************/
175 #ifdef TEST_ARITH
176 #include <stdio.h>
177 main(int argc, char *argv[])
178 {
179         printf("%d\n", exp(argv[1]));
180 }
181
182 error(char *s)
183 {
184         fprintf(stderr, "exp: %s\n", s);
185         exit(1);
186 }
187 #endif