fio: support exponentiation in expression parser

Signed-off-by: Stephen M. Cameron <stephenmcameron@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
diff --git a/exp/expression-parser.l b/exp/expression-parser.l
index f688da1..a0c6b24 100644
--- a/exp/expression-parser.l
+++ b/exp/expression-parser.l
@@ -158,7 +158,8 @@
 		}
 	}
 \n	return 0;
-[+-/*()]	return yytext[0];
+[+-/*()^]	return yytext[0];
+
 .	{
 		yylval.v.has_error = 1;
 		return NUMBER;	
diff --git a/exp/expression-parser.y b/exp/expression-parser.y
index 1c1ebf8..f5a7981 100644
--- a/exp/expression-parser.y
+++ b/exp/expression-parser.y
@@ -20,7 +20,7 @@
 
 #include <stdio.h>
 #include <string.h>
-
+#include <math.h>
 struct parser_value_type {
 	double dval;
 	long long ival;
@@ -58,6 +58,7 @@
 %token <v> SUFFIX 
 %left '-' '+'
 %left '*' '/'
+%right '^'
 %nonassoc UMINUS
 %parse-param { long long *result }
 %parse-param { double *dresult }
@@ -131,6 +132,36 @@
 				$$.dval = $1.ival * $2.ival;
 			$$.has_error = $1.has_error || $2.has_error;
 		}
+	|	expression '^' expression {
+			$$.has_error = $1.has_error || $3.has_error;
+			if (!$1.has_dval && !$3.has_dval) {
+				int i;
+
+				if ($3.ival == 0) {
+					$$.ival = 1;
+				} else if ($3.ival > 0) {
+					long long tmp = $1.ival;
+					$$.ival = 1.0;
+					for (i = 0; i < $3.ival; i++)
+						$$.ival *= tmp;
+				}  else {
+					/* integers, 2^-3, ok, we now have doubles */
+					double tmp;
+					if ($1.ival == 0 && $3.ival == 0) {
+						tmp = 1.0;
+						$$.has_error = 1;
+					} else {
+						tmp = pow((double) $1.ival,
+								(double) $3.ival);
+					}
+					$$.ival = (long long) tmp;
+				}
+				$$.dval = pow($1.dval, $3.dval);
+			} else {
+				$$.dval = pow($1.dval, $3.dval);
+				$$.ival = (long long) $$.dval;
+			}
+		}
 	|	NUMBER { $$ = $1; }
 	|	BYE { $$ = $1; *bye = 1; };
 %%
diff --git a/fio.1 b/fio.1
index fb5ca46..66c9cb0 100644
--- a/fio.1
+++ b/fio.1
@@ -119,7 +119,7 @@
 Anywhere a numeric value is required, an arithmetic expression may be used,
 provided it is surrounded by parentheses.
 Supported operators are
-addition, subtraction, multiplication and division.
+addition, subtraction, multiplication, division and exponentiation.
 For time values in expressions
 units are microseconds by default.  This is different than for time
 values not in expressions (not enclosed in parentheses).