[RFC PATCH 00/11] Tidy command option parsing and use it a bit
Simon Glass
sjg at chromium.org
Fri May 15 22:32:51 CEST 2026
We have had getopt() for over five years but it is not much used. It is
much easier to understand arg-parsing using getopt() and it avoids
common errors. As the named maintainer I decided to look at how to make
more use of it.
So this series explores the impact of converting a few commands to use
getopt() instead of ad-hoc parsing. It updates getopt() to handle flags
anywhere in the cmdline and provides a few helpers to reduce
boilerplate.
The chosen commands are:
- echo: very simple with no flags
- hash: fairly simple with just one flag
- env grep/export/import - fuller examples
The series also adds a recommendation to use getopt() for new commands.
To try to reduce the code-size increase, a lower-case function is added
and called from a few places. The difference is fairly marginal.
Overall, the result is not pretty (see below) with about a 1.1K size
increase on arm64:
01: Prepare v2026.07-rc2
aarch64: w+ firefly-rk3399
02: lib: string: Add strlower()
aarch64: (for 1/1 boards) all +40.0 rodata +40.0 spl/u-boot-spl:all
+20.0 spl/u-boot-spl:rodata +20.0 tpl/u-boot-tpl:all +20.0
tpl/u-boot-tpl:rodata +20.0
03: cmd: ini: Use strlower() to normalise case
04: fs: fat: Use strlower() to normalise case
aarch64: (for 1/1 boards) all -24.0 text -24.0
05: boot: pxe_utils: Use strlower() in get_string()
aarch64: (for 1/1 boards) all -56.0 text -56.0
06: doc: commands: Recommend getopt() for option parsing
07: lib: getopt: Permute by default with inline reorder
08: lib: getopt: Add getopt_pop() helper
09: cmd: echo: Use getopt() with '+' prefix for option parsing
aarch64: (for 1/1 boards) all +1235.0 rodata +175.0 text +1060.0
10: cmd: hash: Use getopt() for option parsing
11: cmd: nvedit: Use getopt() in env grep
12: cmd: nvedit: Use getopt() in env export and env import
aarch64: (for 1/1 boards) all +176.0 rodata +12.0 text +164.0
Ideally we would use getopt() everywhere, but at least with these
examples it does seem to produce at least a small increase in each case,
even ignoring the 'hit' of about 1K for the function itself.
One option would be to make the getopt_init_state() in command.c and
pass struct getopt_state to the commands. This would reduce code size at
each size, but obviously requires a different command signature, unless
a global is used.
Another small improvement could be to include a getopt function to
return the next arg as hex.
Ideas are welcome!
Simon Glass (11):
lib: string: Add strlower()
cmd: ini: Use strlower() to normalise case
fs: fat: Use strlower() to normalise case
boot: pxe_utils: Use strlower() in get_string()
lib: getopt: Permute by default with inline reorder
lib: getopt: Add getopt_pop() helper
cmd: echo: Use getopt() with '+' prefix for option parsing
cmd: hash: Use getopt() for option parsing
cmd: nvedit: Use getopt() in env grep
cmd: nvedit: Use getopt() in env export and env import
doc: commands: Recommend getopt() for option parsing
boot/pxe_utils.c | 12 +--
cmd/Kconfig | 5 +
cmd/bdinfo.c | 4 +-
cmd/echo.c | 23 ++--
cmd/hash.c | 37 ++++---
cmd/ini.c | 21 ++--
cmd/log.c | 12 +--
cmd/nvedit.c | 219 +++++++++++++++++++--------------------
doc/develop/commands.rst | 62 +++++++++++
fs/fat/fat.c | 20 +---
fs/fat/fat_write.c | 2 +-
include/getopt.h | 169 +++++++++++++++++-------------
include/linux/string.h | 12 +++
lib/getopt.c | 67 +++++++++---
lib/string.c | 10 ++
test/cmd/test_echo.c | 10 ++
test/lib/getopt.c | 6 +-
test/lib/string.c | 27 +++++
18 files changed, 441 insertions(+), 277 deletions(-)
---
base-commit: 215496fec59b3fa09256b4fb62f92af46e2ec7f9
branch: clid
--
2.43.0
More information about the U-Boot
mailing list