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 39 static 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 52 const char *arith_buf, *arith_startbuf; 53 54 void yyerror(const char *); 55 #ifdef TESTARITH 56 int main(int , char *[]); 57 int 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 76 exp: expr { 77 return ($1); 78 } 79 ; 80 81 82 expr: 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 %% 116 int 117 arith(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 */ 136 int 137 expcmd(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> 176 main(argc, argv) 177 char *argv[]; 178 { 179 printf("%d\n", exp(argv[1])); 180 } 181 error(s) 182 char *s; 183 { 184 fprintf(stderr, "exp: %s\n", s); 185 exit(1); 186 } 187 #endif 188 189 void 190 yyerror(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