do_env_import() is the other gnarly hand-rolled parser in nvedit.c, and
walks each - argument by hand, opens an inner while (*++arg) to split
grouped flags and tracks an fmt counter to reject a second -b/-c/-t.

Replace the parser with getopt(). Move do_env_import() to the
getopt-state command signature, declared with U_BOOT_CMD_MKENT_GETOPT().
Move the format-flag mutual-exclusion check after the option loop and
read the trailing positional list from gs->argv[gs->index].

Keep the + prefix on the optstring so getopt() stops at the first
non-option, exactly as the hand-rolled loop did. This matters here: the
size positional can be a literal - (meaning no size, rely on the '\0'
termination), which the permuting parser would otherwise consume. The
behaviour is otherwise unchanged; keep the messages and the
size/checksum handling as-is.

CMD_IMPORTENV selects GETOPT so the parser is linked in on boards that
do not already enable it.

Leave the himport_r() interface unchanged for now. It would benefit
from an API rethink at some point, since passing argc/argv is a bit
clunky now.

Signed-off-by: Simon Glass <[email protected]>
---

Changes in v4:
- Update commit message to mention himport_r()

 cmd/Kconfig  |  1 +
 cmd/nvedit.c | 67 ++++++++++++++++++++++++++--------------------------
 2 files changed, 35 insertions(+), 33 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index e3d92055f17..842afa2f390 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -711,6 +711,7 @@ config CMD_EXPORTENV
 config CMD_IMPORTENV
        bool "env import"
        default y
+       select GETOPT
        help
          Import environments.
 
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index c74898a05fb..95d53ba5c32 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -760,8 +760,7 @@ sep_err:
  *             the environment at address 'addr'. Without arguments, the whole
  *             environment gets imported.
  */
-static int do_env_import(struct cmd_tbl *cmdtp, int flag,
-                        int argc, char *const argv[])
+static int do_env_import(struct getopt_state *gs)
 {
        ulong   addr;
        char    *cmd, *ptr;
@@ -772,40 +771,42 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
        int     crlf_is_lf = 0;
        int     wl = 0;
        size_t  size;
+       int     argc;
+       char    *const *argv;
+       int     opt;
 
-       cmd = *argv;
+       cmd = gs->argv[0];
 
-       while (--argc > 0 && **++argv == '-') {
-               char *arg = *argv;
-               while (*++arg) {
-                       switch (*arg) {
-                       case 'b':               /* raw binary format */
-                               if (fmt++)
-                                       goto sep_err;
-                               sep = '\0';
-                               break;
-                       case 'c':               /* external checksum format */
-                               if (fmt++)
-                                       goto sep_err;
-                               sep = '\0';
-                               chk = 1;
-                               break;
-                       case 't':               /* text format */
-                               if (fmt++)
-                                       goto sep_err;
-                               sep = '\n';
-                               break;
-                       case 'r':               /* handle CRLF like LF */
-                               crlf_is_lf = 1;
-                               break;
-                       case 'd':
-                               del = 1;
-                               break;
-                       default:
-                               return CMD_RET_USAGE;
-                       }
+       while ((opt = getopt(gs, "+bcdrt")) > 0) {
+               switch (opt) {
+               case 'b':               /* raw binary format */
+                       sep = '\0';
+                       fmt++;
+                       break;
+               case 'c':               /* external checksum format */
+                       sep = '\0';
+                       chk = 1;
+                       fmt++;
+                       break;
+               case 't':               /* text format */
+                       sep = '\n';
+                       fmt++;
+                       break;
+               case 'r':               /* handle CRLF like LF */
+                       crlf_is_lf = 1;
+                       break;
+               case 'd':
+                       del = 1;
+                       break;
+               default:
+                       return CMD_RET_USAGE;
                }
        }
+       if (fmt > 1)
+               goto sep_err;
+
+       argc = gs->argc - gs->index;
+       argv = &gs->argv[gs->index];
 
        if (argc < 1)
                return CMD_RET_USAGE;
@@ -1079,7 +1080,7 @@ static struct cmd_tbl cmd_env_sub[] = {
        U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
-       U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
+       U_BOOT_CMD_MKENT_GETOPT(import, 5, 0, do_env_import, "", ""),
 #endif
 #if defined(CONFIG_CMD_NVEDIT_INDIRECT)
        U_BOOT_CMD_MKENT(indirect, 3, 0, do_env_indirect, "", ""),
-- 
2.43.0

Reply via email to