summaryrefslogtreecommitdiff
path: root/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'expr.c')
-rw-r--r--expr.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/expr.c b/expr.c
index 0930789d..3b7f80e5 100644
--- a/expr.c
+++ b/expr.c
@@ -27,6 +27,7 @@
"-", "+" [(unary operators)]
"!", "~"
+ "**" [(exponentiation)]
"*", "/", "%"
"+", "-"
"<<", ">>"
@@ -38,9 +39,7 @@
"&&"
"||"
"expr ? expr : expr"
- "=", "*=", "/=", "%=",
- "+=", "-=", "<<=", ">>=",
- "&=", "^=", "|="
+ "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
(Note that most of these operators have special meaning to bash, and an
entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure
@@ -68,7 +67,11 @@
#include <stdio.h>
#include "bashansi.h"
+
#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
# include <unistd.h>
#endif
@@ -99,7 +102,8 @@
#define LSH 9 /* "<<" Left SHift */
#define RSH 10 /* ">>" Right SHift */
#define OP_ASSIGN 11 /* op= expassign as in Posix.2 */
-#define COND 12
+#define COND 12 /* exp1 ? exp2 : exp3 */
+#define POWER 13 /* exp1**exp2 */
#define EQ '='
#define GT '>'
#define LT '<'
@@ -132,7 +136,7 @@ static procenv_t evalbuf;
static void readtok (); /* lexical analyzer */
static long subexpr (), expassign (), exp0 (), exp1 (), exp2 (), exp3 (),
exp4 (), exp5 (), expshift (), expland (), explor (),
- expband (), expbor (), expbxor (), expcond ();
+ expband (), expbor (), expbxor (), expcond (), exppower ();
static long strlong ();
static void evalerror ();
@@ -665,7 +669,7 @@ exp2 ()
{
register long val1, val2;
- val1 = exp1 ();
+ val1 = exppower ();
while ((curtok == MUL) ||
(curtok == DIV) ||
@@ -675,7 +679,7 @@ exp2 ()
readtok ();
- val2 = exp1 ();
+ val2 = exppower ();
if (((op == DIV) || (op == MOD)) && (val2 == 0))
evalerror ("division by 0");
@@ -691,6 +695,25 @@ exp2 ()
}
static long
+exppower ()
+{
+ register long val1, val2, c;
+
+ val1 = exp1 ();
+ if (curtok == POWER)
+ {
+ readtok ();
+ val2 = exp1 ();
+ if (val2 == 0)
+ return (1L);
+ for (c = 1; val2--; c *= val1)
+ ;
+ val1 = c;
+ }
+ return (val1);
+}
+
+static long
exp1 ()
{
register long val;
@@ -875,6 +898,8 @@ readtok ()
c = LAND;
else if ((c == BOR) && (c1 == BOR))
c = LOR;
+ else if ((c == '*') && (c1 == '*'))
+ c = POWER;
else if (c1 == EQ && member(c, "*/%+-&^|"))
{
assigntok = c; /* a OP= b */
@@ -905,7 +930,7 @@ evalerror (msg)
/* Convert a string to a long integer, with an arbitrary base.
0nnn -> base 8
- 0xnn -> base 16
+ 0[Xx]nn -> base 16
Anything else: [base#]number (this is implemented to match ksh93)
Base may be >=2 and <=64. If base is <= 36, the numbers are drawn