do_env_grep() hand-rolls the same grouped-flag parser as the other env
subcommands: an outer loop over - arguments and an inner while (*++arg)
over the characters, with an explicit case to spot the -- terminator.

Parse the options with getopt() instead. getopt() handles the grouped
form and the -- terminator natively, and the optstring keeps the +
prefix so it stops at the first non-option as the hand-rolled loop did.
Read the search patterns from gs.argv[gs.index] onward.

Move do_env_grep() to the getopt-state command signature, like env
export and env import. The standalone grepenv command uses tab
completion, so declare it with the new U_BOOT_CMD_GETOPT_COMPLETE()
which keeps the auto-complete function.

The existing code ORs the command flag into the hexport_r() flags. That
is inherited from the original parser but is wrong: flag holds
CMD_FLAG_* bits which alias the H_NOCLEAR/H_FORCE/H_INTERACTIVE bits
hexport_r() uses (they happen to be ignored on the export path). Drop it
and pass only grep_what | grep_how. The behaviour is otherwise
unchanged.

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

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

(no changes since v1)

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

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 842afa2f390..9cafeb5d07c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -723,6 +723,7 @@ config CMD_EDITENV
 
 config CMD_GREPENV
        bool "search env"
+       select GETOPT
        help
          Allow for searching environment variables
 
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 95d53ba5c32..2af6e9dc03e 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -129,49 +129,46 @@ static int do_env_print(struct cmd_tbl *cmdtp, int flag, 
int argc,
 }
 
 #ifdef CONFIG_CMD_GREPENV
-static int do_env_grep(struct cmd_tbl *cmdtp, int flag,
-                      int argc, char *const argv[])
+static int do_env_grep(struct getopt_state *gs)
 {
+       const char *optstring = IS_ENABLED(CONFIG_REGEX) ? "+envb" : "+nvb";
        char *res = NULL;
        int len, grep_how, grep_what;
-
-       if (argc < 2)
-               return CMD_RET_USAGE;
+       int argc;
+       char *const *argv;
+       int opt;
 
        grep_how  = H_MATCH_SUBSTR;     /* default: substring search    */
        grep_what = H_MATCH_BOTH;       /* default: grep names and values */
 
-       while (--argc > 0 && **++argv == '-') {
-               char *arg = *argv;
-               while (*++arg) {
-                       switch (*arg) {
-#ifdef CONFIG_REGEX
-                       case 'e':               /* use regex matching */
+       while ((opt = getopt(gs, optstring)) > 0) {
+               switch (opt) {
+               case 'e':               /* use regex matching */
+                       if (IS_ENABLED(CONFIG_REGEX))
                                grep_how  = H_MATCH_REGEX;
-                               break;
-#endif
-                       case 'n':               /* grep for name */
-                               grep_what = H_MATCH_KEY;
-                               break;
-                       case 'v':               /* grep for value */
-                               grep_what = H_MATCH_DATA;
-                               break;
-                       case 'b':               /* grep for both */
-                               grep_what = H_MATCH_BOTH;
-                               break;
-                       case '-':
-                               goto DONE;
-                       default:
-                               return CMD_RET_USAGE;
-                       }
+                       break;
+               case 'n':               /* grep for name */
+                       grep_what = H_MATCH_KEY;
+                       break;
+               case 'v':               /* grep for value */
+                       grep_what = H_MATCH_DATA;
+                       break;
+               case 'b':               /* grep for both */
+                       grep_what = H_MATCH_BOTH;
+                       break;
+               default:
+                       return CMD_RET_USAGE;
                }
        }
 
-DONE:
-       len = hexport_r(&env_htab, '\n',
-                       flag | grep_what | grep_how,
-                       &res, 0, argc, argv);
+       argc = gs->argc - gs->index;
+       argv = &gs->argv[gs->index];
 
+       if (argc < 1)
+               return CMD_RET_USAGE;
+
+       len = hexport_r(&env_htab, '\n', grep_what | grep_how, &res, 0,
+                       argc, argv);
        if (len > 0) {
                puts(res);
                free(res);
@@ -1077,7 +1074,7 @@ static struct cmd_tbl cmd_env_sub[] = {
        U_BOOT_CMD_MKENT_GETOPT(export, 4, 0, do_env_export, "", ""),
 #endif
 #if defined(CONFIG_CMD_GREPENV)
-       U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
+       U_BOOT_CMD_MKENT_GETOPT(grep, CONFIG_SYS_MAXARGS, 0, do_env_grep, "", 
""),
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
        U_BOOT_CMD_MKENT_GETOPT(import, 5, 0, do_env_import, "", ""),
@@ -1232,7 +1229,7 @@ U_BOOT_CMD_COMPLETE(
 );
 
 #ifdef CONFIG_CMD_GREPENV
-U_BOOT_CMD_COMPLETE(
+U_BOOT_CMD_GETOPT_COMPLETE(
        grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
        "search environment variables",
 #ifdef CONFIG_REGEX
-- 
2.43.0

Reply via email to