+
+ c = strdup(p);
+
+ for (i = 0; i < strlen(c); i++) {
+ c[i] = tolower(c[i]);
+ if (is_separator(c[i])) {
+ c[i] = '\0';
+ break;
+ }
+ }
+
+ if (!strncmp("pib", c, 3)) {
+ pow = 5;
+ mult = 1000;
+ } else if (!strncmp("tib", c, 3)) {
+ pow = 4;
+ mult = 1000;
+ } else if (!strncmp("gib", c, 3)) {
+ pow = 3;
+ mult = 1000;
+ } else if (!strncmp("mib", c, 3)) {
+ pow = 2;
+ mult = 1000;
+ } else if (!strncmp("kib", c, 3)) {
+ pow = 1;
+ mult = 1000;
+ } else if (!strncmp("p", c, 1) || !strncmp("pb", c, 2))
+ pow = 5;
+ else if (!strncmp("t", c, 1) || !strncmp("tb", c, 2))
+ pow = 4;
+ else if (!strncmp("g", c, 1) || !strncmp("gb", c, 2))
+ pow = 3;
+ else if (!strncmp("m", c, 1) || !strncmp("mb", c, 2))
+ pow = 2;
+ else if (!strncmp("k", c, 1) || !strncmp("kb", c, 2))
+ pow = 1;
+ else if (!strncmp("%", c, 1)) {
+ *percent = 1;
+ free(c);
+ return ret;
+ }
+
+ while (pow--)
+ ret *= (unsigned long long) mult;
+
+ free(c);
+ return ret;
+}
+
+static unsigned long long get_mult_bytes(const char *str, int len, void *data,
+ int *percent)
+{
+ const char *p = str;
+ int digit_seen = 0;
+
+ if (len < 2)
+ return __get_mult_bytes(str, data, percent);
+
+ /*
+ * Go forward until we hit a non-digit, or +/- sign
+ */
+ while ((p - str) <= len) {
+ if (!isdigit((int) *p) &&
+ (((*p != '+') && (*p != '-')) || digit_seen))
+ break;
+ digit_seen |= isdigit((int) *p);
+ p++;
+ }
+
+ if (!isalpha((int) *p) && (*p != '%'))
+ p = NULL;
+
+ return __get_mult_bytes(p, data, percent);
+}
+
+extern int evaluate_arithmetic_expression(const char *buffer, long long *ival,
+ double *dval, double implied_units,
+ int is_time);
+
+#ifdef CONFIG_ARITHMETIC
+/*
+ * These two verification functions are just to gain confidence that
+ * the arithmetic processing code is always getting the same answer as the
+ * original number parsing code. Once sufficiently sure that the arithmetic
+ * code is always getting the right answers, these can be removed.
+ */
+static void verify_exp_parser_float(const char *str, double implied_units, int is_time)
+{
+ long long ival;
+ double dval, tmpval;
+
+ if (sscanf(str, "%lf", &tmpval) != 1)
+ return;
+
+ if (evaluate_arithmetic_expression(str, &ival, &dval, implied_units, is_time) != 0) {
+ log_info("Arithmetic failed on '%s'\n", str);
+ return;
+ }
+ if (dval != tmpval) {
+ log_info("Arithmetic failed on: '%s' got %lf, expected %lf\n",
+ str, dval, tmpval);
+ }
+}
+
+static void verify_exp_parser_decimal(const char *str, long long val, int kilo, int is_seconds,
+ int is_time)
+{
+ int rc;
+ long long ival;
+ double dval;
+ double implied_units = 1.0;
+
+ if (is_seconds)
+ implied_units = 1000000.0;
+
+ rc = evaluate_arithmetic_expression(str, &ival, &dval, implied_units, is_time);
+ if (!rc) {
+ if (ival != val)
+ log_info("Arithmetic failed on '%s', expected %lld, got %lld\n",
+ str, val, ival);
+ } else {
+ log_info("Arithmetic failed on '%s'\n", str);