- switch (**p)
- {
- case '\0':
- break;
-
-#define BKM_SCALE(x, scale_factor, error_return) \
- do \
- { \
- if ((x) > (double) __ZLONG_MAX / (scale_factor)) \
- return (error_return); \
- (x) *= (scale_factor); \
- } \
- while (0)
-
- case 'b':
- BKM_SCALE (tmp, 512, LONGINT_OVERFLOW);
- ++(*p);
- break;
-
- case 'k':
- BKM_SCALE (tmp, 1024, LONGINT_OVERFLOW);
- ++(*p);
- break;
-
- case 'm':
- BKM_SCALE (tmp, 1024 * 1024, LONGINT_OVERFLOW);
- ++(*p);
- break;
-
- default:
- return LONGINT_INVALID_SUFFIX_CHAR;
- break;
+ if (strchr (valid_suffixes, '0'))
+ {
+ /* The ``valid suffix'' '0' is a special flag meaning that
+ an optional second suffix is allowed, which can change
+ the base, e.g. "100MD" for 100 megabytes decimal. */
+
+ switch (p[0][1])
+ {
+ case 'B':
+ suffixes++;
+ break;
+
+ case 'D':
+ base = 1000;
+ suffixes++;
+ break;
+ }
+ }
+
+ switch (**p)
+ {
+ case 'b':
+ overflow = bkm_scale (&tmp, 512);
+ break;
+
+ case 'B':
+ overflow = bkm_scale (&tmp, 1024);
+ break;
+
+ case 'c':
+ overflow = 0;
+ break;
+
+ case 'E': /* Exa */
+ overflow = bkm_scale_by_power (&tmp, base, 6);
+ break;
+
+ case 'G': /* Giga */
+ overflow = bkm_scale_by_power (&tmp, base, 3);
+ break;
+
+ case 'k': /* kilo */
+ overflow = bkm_scale_by_power (&tmp, base, 1);
+ break;
+
+ case 'M': /* Mega */
+ case 'm': /* 'm' is undocumented; for backward compatibility only */
+ overflow = bkm_scale_by_power (&tmp, base, 2);
+ break;
+
+ case 'P': /* Peta */
+ overflow = bkm_scale_by_power (&tmp, base, 5);
+ break;
+
+ case 'T': /* Tera */
+ overflow = bkm_scale_by_power (&tmp, base, 4);
+ break;
+
+ case 'w':
+ overflow = bkm_scale (&tmp, 2);
+ break;
+
+ case 'Y': /* Yotta */
+ overflow = bkm_scale_by_power (&tmp, base, 8);
+ break;
+
+ case 'Z': /* Zetta */
+ overflow = bkm_scale_by_power (&tmp, base, 7);
+ break;
+
+ default:
+ *val = tmp;
+ return LONGINT_INVALID_SUFFIX_CHAR;
+ break;
+ }
+
+ if (overflow)
+ return LONGINT_OVERFLOW;
+
+ (*p) += suffixes;