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