xref: /original-bsd/bin/sh/arith.y (revision b3c06cab)
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  * %sccs.include.redist.c%
64  */
65 
66 #ifndef lint
67 static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 05/04/95";
68 #endif /* not lint */
69 
70 #include "shell.h"
71 #include "error.h"
72 #include "output.h"
73 #include "memalloc.h"
74 
75 char *arith_buf, *arith_startbuf;
76 
77 int
78 arith(s)
79 	char *s;
80 {
81 	long result;
82 
83 	arith_buf = arith_startbuf = s;
84 
85 	INTOFF;
86 	result = yyparse();
87 	arith_lex_reset();	/* reprime lex */
88 	INTON;
89 
90 	return (result);
91 }
92 
93 void
94 yyerror(s)
95 	char *s;
96 {
97 
98 	yyerrok;
99 	yyclearin;
100 	arith_lex_reset();	/* reprime lex */
101 	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
102 }
103 
104 /*
105  *  The exp(1) builtin.
106  */
107 int
108 expcmd(argc, argv)
109 	int argc;
110 	char **argv;
111 {
112 	char *p;
113 	char *concat;
114 	char **ap;
115 	long i;
116 
117 	if (argc > 1) {
118 		p = argv[1];
119 		if (argc > 2) {
120 			/*
121 			 * concatenate arguments
122 			 */
123 			STARTSTACKSTR(concat);
124 			ap = argv + 2;
125 			for (;;) {
126 				while (*p)
127 					STPUTC(*p++, concat);
128 				if ((p = *ap++) == NULL)
129 					break;
130 				STPUTC(' ', concat);
131 			}
132 			STPUTC('\0', concat);
133 			p = grabstackstr(concat);
134 		}
135 	} else
136 		p = "";
137 
138 	i = arith(p);
139 
140 	out1fmt("%d\n", i);
141 	return (! i);
142 }
143 
144 /*************************/
145 #ifdef TEST_ARITH
146 #include <stdio.h>
147 main(argc, argv)
148 	char *argv[];
149 {
150 	printf("%d\n", exp(argv[1]));
151 }
152 error(s)
153 	char *s;
154 {
155 	fprintf(stderr, "exp: %s\n", s);
156 	exit(1);
157 }
158 #endif
159