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