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
arith(s)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
yyerror(s)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
expcmd(argc,argv)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>
main(argc,argv)147 main(argc, argv)
148 char *argv[];
149 {
150 printf("%d\n", exp(argv[1]));
151 }
error(s)152 error(s)
153 char *s;
154 {
155 fprintf(stderr, "exp: %s\n", s);
156 exit(1);
157 }
158 #endif
159