This is the other gnarly hand-rolled parser in nvedit.c

The code walks each -prefixed argv element by hand, opens an inner
while (*++arg) to split grouped flags, and tracks a fmt counter to
catch a second -b / -c / -t

getopt() collapses all of that. The mutex check for the format flags
is done after the option loop (it is a per-command rule, not an
option-parsing rule) and the trailing positional list is read from
argv + gs.index.

Adjust CMD_IMPORTENV to select GETOPT so the parser is linked in on
boards that did not already enable it.

Also redo the sep_err logic and error message, along with a fmt tweak
to reduce code size.

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

 cmd/Kconfig  |  1 +
 cmd/nvedit.c | 95 ++++++++++++++++++++++++----------------------------
 env/common.c |  2 +-
 3 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index a5a20bde4b5..72ff4dbfe60 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 5dca1b804fd..ce1f0e9bd2c 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -752,64 +752,64 @@ static int do_env_export(struct cmd_tbl *cmdtp, int flag,
 static int do_env_import(struct cmd_tbl *cmdtp, int flag,
                         int argc, char *const argv[])
 {
+       struct getopt_state gs;
        ulong   addr;
-       char    *cmd, *ptr;
+       char    *ptr, *tok;
        char    sep = '\n';
        int     chk = 0;
        int     fmt = 0;
        int     del = 0;
        int     crlf_is_lf = 0;
-       int     wl = 0;
+       int     wl;
        size_t  size;
+       int     opt;
 
-       cmd = *argv;
-
-       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;
-                       }
+       getopt_init_state(&gs);
+       while ((opt = getopt(&gs, argc, argv, "bctrd")) > 0) {
+               fmt++;
+               switch (opt) {
+               case 'b':               /* raw binary format */
+                       sep = '\0';
+                       break;
+               case 'c':               /* external checksum format */
+                       sep = '\0';
+                       chk = 1;
+                       break;
+               case 't':               /* text format (default) */
+                       break;
+               case 'r':               /* handle CRLF like LF */
+                       crlf_is_lf = 1;
+                       fmt--;
+                       break;
+               case 'd':
+                       del = 1;
+                       fmt--;
+                       break;
+               default:
+                       return CMD_RET_USAGE;
                }
        }
 
-       if (argc < 1)
+       if (gs.index >= argc)
+               return CMD_RET_USAGE;
+       if (fmt > 1) {
+               printf("## Error: %s: only one of -b/c/t allowed\n", argv[0]);
+
                return CMD_RET_USAGE;
+       }
 
        if (!fmt)
                printf("## Warning: defaulting to text format\n");
 
-       if (sep != '\n' && crlf_is_lf )
+       if (sep != '\n' && crlf_is_lf)
                crlf_is_lf = 0;
 
-       addr = hextoul(argv[0], NULL);
+       addr = hextoul(argv[gs.index++], NULL);
        ptr = map_sysmem(addr, 0);
 
-       if (argc >= 2 && strcmp(argv[1], "-")) {
-               size = hextoul(argv[1], NULL);
+       tok = gs.index < argc ? argv[gs.index++] : NULL;
+       if (tok && strcmp(tok, "-")) {
+               size = hextoul(tok, NULL);
        } else if (chk) {
                puts("## Error: external checksum format must pass size\n");
                return CMD_RET_FAILURE;
@@ -825,22 +825,19 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
                        ++size;
                }
                if (size == MAX_ENV_SIZE) {
-                       printf("## Warning: Input data exceeds %d bytes"
+                       printf("## Warning: Input exceeds %d bytes"
                                " - truncated\n", MAX_ENV_SIZE);
                }
                size += 2;
-               printf("## Info: input data size = %zu = 0x%zX\n", size, size);
+               printf("## Info: input size = %zu = %#zX\n", size, size);
        }
 
-       if (argc > 2)
-               wl = 1;
-
        if (chk) {
                uint32_t crc;
                env_t *ep = (env_t *)ptr;
 
                if (size <= offsetof(env_t, data)) {
-                       printf("## Error: Invalid size 0x%zX\n", size);
+                       printf("## Error: Invalid size %#zX\n", size);
                        return 1;
                }
 
@@ -854,20 +851,16 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
                ptr = (char *)ep->data;
        }
 
+       wl = argc - gs.index;
        if (!himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
-                      crlf_is_lf, wl ? argc - 2 : 0, wl ? &argv[2] : NULL)) {
-               pr_err("## Error: Environment import failed: errno = %d\n",
+                      crlf_is_lf, wl, wl ? &argv[gs.index] : NULL)) {
+               pr_err("## Error: Environment import failed (err %dE)\n",
                       errno);
                return 1;
        }
        gd->flags |= GD_FLG_ENV_READY;
 
        return 0;
-
-sep_err:
-       printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
-               cmd);
-       return 1;
 }
 #endif
 
diff --git a/env/common.c b/env/common.c
index b2adbe93dbe..986400f912f 100644
--- a/env/common.c
+++ b/env/common.c
@@ -402,7 +402,7 @@ void env_set_default(const char *s, int flags)
        if (himport_r(&env_htab, default_environment,
                        sizeof(default_environment), '\0', flags, 0,
                        0, NULL) == 0) {
-               pr_err("## Error: Environment import failed: errno = %d\n",
+               pr_err("## Error: Environment import failed (err %dE)\n",
                       errno);
                return;
        }
-- 
2.43.0

Reply via email to