168929Sbostic %token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
254332Smarc
354332Smarc %left ARITH_OR
454332Smarc %left ARITH_AND
568929Sbostic %left ARITH_BOR
668929Sbostic %left ARITH_BXOR
768929Sbostic %left ARITH_BAND
868929Sbostic %left ARITH_EQ ARITH_NE
968929Sbostic %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
1068929Sbostic %left ARITH_LSHIFT ARITH_RSHIFT
1168929Sbostic %left ARITH_ADD ARITH_SUB
1268929Sbostic %left ARITH_MUL ARITH_DIV ARITH_REM
1368929Sbostic %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
1454332Smarc %%
1554332Smarc
1654332Smarc exp: expr = {
1754332Smarc return ($1);
1854332Smarc }
1954332Smarc ;
2054332Smarc
2154332Smarc
2254332Smarc expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
2368929Sbostic | expr ARITH_OR expr = { $$ = $1 ? $1 : $3 ? $3 : 0; }
2468929Sbostic | expr ARITH_AND expr = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
2568929Sbostic | expr ARITH_BOR expr = { $$ = $1 | $3; }
2668929Sbostic | expr ARITH_BXOR expr = { $$ = $1 ^ $3; }
2768929Sbostic | expr ARITH_BAND expr = { $$ = $1 & $3; }
2868929Sbostic | expr ARITH_EQ expr = { $$ = $1 == $3; }
2968929Sbostic | expr ARITH_GT expr = { $$ = $1 > $3; }
3068929Sbostic | expr ARITH_GE expr = { $$ = $1 >= $3; }
3168929Sbostic | expr ARITH_LT expr = { $$ = $1 < $3; }
3268929Sbostic | expr ARITH_LE expr = { $$ = $1 <= $3; }
3368929Sbostic | expr ARITH_NE expr = { $$ = $1 != $3; }
3468929Sbostic | expr ARITH_LSHIFT expr = { $$ = $1 << $3; }
3568929Sbostic | expr ARITH_RSHIFT expr = { $$ = $1 >> $3; }
3668929Sbostic | expr ARITH_ADD expr = { $$ = $1 + $3; }
3768929Sbostic | expr ARITH_SUB expr = { $$ = $1 - $3; }
3868929Sbostic | expr ARITH_MUL expr = { $$ = $1 * $3; }
3968929Sbostic | expr ARITH_DIV expr = {
4054332Smarc if ($3 == 0)
4154332Smarc yyerror("division by zero");
4254332Smarc $$ = $1 / $3;
4354332Smarc }
4468929Sbostic | expr ARITH_REM expr = {
4568929Sbostic if ($3 == 0)
4668929Sbostic yyerror("division by zero");
4768929Sbostic $$ = $1 % $3;
4868929Sbostic }
4954332Smarc | ARITH_NOT expr = { $$ = !($2); }
5068929Sbostic | ARITH_BNOT expr = { $$ = ~($2); }
5168929Sbostic | ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
5268929Sbostic | ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
5354332Smarc | ARITH_NUM
5454332Smarc ;
5554332Smarc %%
5660701Sbostic /*-
5760701Sbostic * Copyright (c) 1993
5860701Sbostic * The Regents of the University of California. All rights reserved.
5960701Sbostic *
6060701Sbostic * This code is derived from software contributed to Berkeley by
6160701Sbostic * Kenneth Almquist.
6260701Sbostic *
6360701Sbostic * %sccs.include.redist.c%
6460701Sbostic */
6554332Smarc
6660701Sbostic #ifndef lint
67*69273Schristos static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 05/04/95";
6860701Sbostic #endif /* not lint */
6960701Sbostic
7054332Smarc #include "shell.h"
7154332Smarc #include "error.h"
7254332Smarc #include "output.h"
7354332Smarc #include "memalloc.h"
7454332Smarc
7554332Smarc char *arith_buf, *arith_startbuf;
7654332Smarc
77*69273Schristos int
arith(s)7854332Smarc arith(s)
7954332Smarc char *s;
8054332Smarc {
8154332Smarc long result;
8254332Smarc
8354332Smarc arith_buf = arith_startbuf = s;
8454332Smarc
8554332Smarc INTOFF;
8654332Smarc result = yyparse();
8754332Smarc arith_lex_reset(); /* reprime lex */
8854332Smarc INTON;
8954332Smarc
9054332Smarc return (result);
9154332Smarc }
9254332Smarc
93*69273Schristos void
yyerror(s)9454332Smarc yyerror(s)
9554332Smarc char *s;
9654332Smarc {
9754332Smarc
9854332Smarc yyerrok;
9954332Smarc yyclearin;
10054332Smarc arith_lex_reset(); /* reprime lex */
10154332Smarc error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
10254332Smarc }
10354332Smarc
10454332Smarc /*
10554332Smarc * The exp(1) builtin.
10654332Smarc */
107*69273Schristos int
expcmd(argc,argv)10854332Smarc expcmd(argc, argv)
109*69273Schristos int argc;
11054332Smarc char **argv;
11154332Smarc {
11254332Smarc char *p;
11354332Smarc char *concat;
11454332Smarc char **ap;
11554332Smarc long i;
11654332Smarc
11754332Smarc if (argc > 1) {
11854332Smarc p = argv[1];
11954332Smarc if (argc > 2) {
12054332Smarc /*
12154332Smarc * concatenate arguments
12254332Smarc */
12354332Smarc STARTSTACKSTR(concat);
12454332Smarc ap = argv + 2;
12554332Smarc for (;;) {
12654332Smarc while (*p)
12754332Smarc STPUTC(*p++, concat);
12854332Smarc if ((p = *ap++) == NULL)
12954332Smarc break;
13054332Smarc STPUTC(' ', concat);
13154332Smarc }
13254332Smarc STPUTC('\0', concat);
13354332Smarc p = grabstackstr(concat);
13454332Smarc }
13554332Smarc } else
13654332Smarc p = "";
13754332Smarc
13854332Smarc i = arith(p);
13954332Smarc
14054332Smarc out1fmt("%d\n", i);
14154332Smarc return (! i);
14254332Smarc }
14354332Smarc
14454332Smarc /*************************/
14554332Smarc #ifdef TEST_ARITH
14654332Smarc #include <stdio.h>
main(argc,argv)14754332Smarc main(argc, argv)
14854332Smarc char *argv[];
14954332Smarc {
15054332Smarc printf("%d\n", exp(argv[1]));
15154332Smarc }
error(s)15254332Smarc error(s)
15354332Smarc char *s;
15454332Smarc {
15554332Smarc fprintf(stderr, "exp: %s\n", s);
15654332Smarc exit(1);
15754332Smarc }
15854332Smarc #endif
159