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