Home | History | Annotate | Download | only in sh
      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