[PATCH 14/15] RFC: lib: Use 0o prefix for octal

Simon Glass
2021-07-20T13:32:35Z

At present if no expected base is provided, a 0 prefix indicates that the
value is octal, so that 077 is interpreted as octal 77 (hex 3f).

If hex is expected, this is interpreted as hex 77 (hex 4d).

This is a little confusing. Since octal is so rarely used, it seems
reasonable to use a special prefix for it. There does not seem to be any
use of octal in the in-tree environment scripts.

Select '0o' which is used in some other languages. Drop support for using
0 as an octal prefix.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

doc/usage/cmdline.rst | 17 ++++++++---------
include/vsprintf.h | 22 ++++++++++++++--------
lib/strto.c | 16 +++++++---------
test/str_ut.c | 7 +++++--
4 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/doc/usage/cmdline.rst b/doc/usage/cmdline.rst
index 05ce65958c4..5142966f5f0 100644
--- a/doc/usage/cmdline.rst
+++ b/doc/usage/cmdline.rst
@@ -82,15 +82,6 @@ Some commands use decimal where it is more natural::
=> i2c speed 100000
Setting bus speed to 100000 Hz

-In some cases the default is decimal but it is possible to use octal if that is
-useful::
-
- pmic dev pmic@41
- dev: 1 @ pmic@41
- => pmic write 2 0177
- => pmic read 2
- 0x02: 0x00007f
-
It is possible to use a `0x` prefix to use a hex value if that is more
convenient::

@@ -102,3 +93,11 @@ U-Boot also supports a `0y` for binary base 2 ("binarY")::
=> mw 100 0y11010011
=> md 100 1
00000100: 000000d3 ....
+
+It is possible to use a 0o prefix for octal if that is useful::
+
+ => pmic dev pmic@41
+ dev: 1 @ pmic@41
+ => pmic write 2 0o177
+ => pmic read 2
+ 0x02: 0x00007f
diff --git a/include/vsprintf.h b/include/vsprintf.h
index 91822ecbe6a..054e0a4dee3 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -24,11 +24,14 @@
*
* A hex prefix is supported (e.g. 0x123) regardless of the value of @base.
* If found, the base is set to hex (16). Similarly a decimal prefix (e.g. 0d12)
- * causes the base to be set to decimal (10).
+ * causes the base to be set to decimal (10) and an octal prefix (e.g. 0o177)
+ * causes the base to be set to octal (8).
*
- * If @base is 0:
- * - an octal '0' prefix (e.g. 0777) sets the base to octal (8).
- * - otherwise the base defaults to decimal (10).
+ * Note that the '0' prefix is not supported for octal. So "0123" is interpreted
+ * as decimal 123, not octal. This is to avoid confusion with hex values which
+ * can start with 0.
+ *
+ * If @base is 0 it defaults to decimal (10).
*/
ulong simple_strtoul(const char *cp, char **endp, unsigned int base);

@@ -78,11 +81,14 @@ unsigned long dectoul(const char *cp, char **endp);
*
* A hex prefix is supported (e.g. 0x123) regardless of the value of @base.
* If found, the base is set to hex (16). Similarly a decimal prefix (e.g. 0d12)
- * causes the base to be set to decimal (10).
+ * causes the base to be set to decimal (10) and an octal prefix (e.g. 0o177)
+ * causes the base to be set to octal (8).
+ *
+ * Note that the '0' prefix is not supported for octal. So "0123" is interpreted
+ * as decimal 123, not octal. This is to avoid confusion with hex values which
+ * can start with 0.
*
- * If @base is 0:
- * - an octal '0' prefix (e.g. 0777) sets the base to octal (8).
- * - otherwise the base defaults to decimal (10).
+ * If @base is 0 it defaults to decimal (10).
*
* Copied this function from Linux 2.6.38 commit ID:
* 521cb40b0c44418a4fd36dc633f575813d59a43d
diff --git a/lib/strto.c b/lib/strto.c
index a7531e877f5..066e5748285 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -20,19 +20,17 @@ static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
if (s[0] == '0') {
int ch = tolower(s[1]);

- if (ch == 'x') {
+ s += 2;
+ if (ch == 'x')
*basep = 16;
- s += 2;
- } else if (ch == 'm') {
+ else if (ch == 'm')
*basep = 10;
- s += 2;
- } else if (ch == 'y') {
+ else if (ch == 'y')
*basep = 2;
- s += 2;
- } else if (!*basep) {
- /* Only select octal if we don't have a base */
+ else if (ch == 'o')
*basep = 8;
- }
+ else
+ s -= 2; /* odd, nothing found */
}

/* Use decimal by default */
diff --git a/test/str_ut.c b/test/str_ut.c
index 731ef0c49ae..90e77d49377 100644
--- a/test/str_ut.c
+++ b/test/str_ut.c
@@ -19,6 +19,7 @@ static const char str4[] = "1234567890123 I lost closer friends";
static const char str5[] = "0x9876543210the last time I was deloused";
static const char str6[] = "0778octal is seldom used";
static const char str7[] = "707it is a piece of computing history";
+static const char str8[] = "0o778use a prefix for octal";

/* Declare a new str test */
#define STR_TEST(_name, _flags) UNIT_TEST(_name, _flags, str_test)
@@ -92,8 +93,9 @@ static int str_simple_strtoul(struct unit_test_state *uts)
ut_assertok(run_strtoul(uts, str3, 10, 0xb, 3, upper));

/* Octal */
- ut_assertok(run_strtoul(uts, str6, 0, 63, 3, upper));
+ ut_assertok(run_strtoul(uts, str6, 0, 778, 4, upper));
ut_assertok(run_strtoul(uts, str7, 8, 0x1c7, 3, upper));
+ ut_assertok(run_strtoul(uts, str8, 0, 63, 4, upper));

/* Invalid string */
ut_assertok(run_strtoul(uts, str1, 10, 0, 0, upper));
@@ -157,8 +159,9 @@ static int str_simple_strtoull(struct unit_test_state *uts)
ut_assertok(run_strtoull(uts, str3, 10, 0xb, 3, upper));

/* Octal */
- ut_assertok(run_strtoull(uts, str6, 0, 63, 3, upper));
+ ut_assertok(run_strtoull(uts, str6, 0, 778, 4, upper));
ut_assertok(run_strtoull(uts, str7, 8, 0x1c7, 3, upper));
+ ut_assertok(run_strtoull(uts, str8, 0, 63, 4, upper));

/* Large values */
ut_assertok(run_strtoull(uts, str4, 10, 1234567890123, 13,
--
2.32.0.402.g57bb445576-goog