On 10/4/23 18:42, Francis Laniel wrote:
If one defines HUSH_2021_PARSER, it is then possible to use 2021 parser with:
=> cli get
old
=> cli set 2021
=> cli get
2021

Reviewed-by: Simon Glass <s...@chromium.org>
Signed-off-by: Francis Laniel <francis.lan...@amarulasolutions.com>
---
  cmd/Kconfig                       |  8 +++++
  cmd/cli.c                         |  7 ++++-
  common/Makefile                   |  1 +
  common/cli.c                      | 38 +++++++++++++++++++----
  common/cli_hush_2021.c            |  3 ++
  common/cli_hush_upstream.c        | 46 +++++++++++++++++++++++++---
  doc/usage/cmd/cli.rst             | 17 ++++++++++-
  include/asm-generic/global_data.h |  4 +++
  include/cli_hush.h                | 51 +++++++++++++++++++++++++++++--
  9 files changed, 160 insertions(+), 15 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 5fb4cef54c..36595638a2 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -34,6 +34,14 @@ menu "Hush flavor to use"
                  2005.

                  It is actually the default U-Boot shell when decided to use 
hush as shell.
+
+       config HUSH_2021_PARSER
+               bool "Use hush 2021 parser"
+               help
+                 This option enables the new flavor of hush based on hush 
Busybox from
+                 2021.
+
+                 For the moment, it is highly experimental and should be used 
at own risks.

Every usage of GPL code is at own risk. That is in the license.

"This parser is experimental and not well tested."

Best regards

Heinrich

  endmenu

  config CMDLINE_EDITING
diff --git a/cmd/cli.c b/cmd/cli.c
index 7671785b83..d2b64da613 100644
--- a/cmd/cli.c
+++ b/cmd/cli.c
@@ -12,6 +12,8 @@ static const char *gd_flags_to_parser(void)
  {
        if (gd->flags & GD_FLG_HUSH_OLD_PARSER)
                return "old";
+       if (gd->flags & GD_FLG_HUSH_2021_PARSER)
+               return "2021";
        return NULL;
  }

@@ -34,12 +36,15 @@ static int parser_string_to_gd_flags(const char *parser)
  {
        if (!strcmp(parser, "old"))
                return GD_FLG_HUSH_OLD_PARSER;
+       if (!strcmp(parser, "2021"))
+               return GD_FLG_HUSH_2021_PARSER;
        return -1;
  }

  static void reset_parser_gd_flags(void)
  {
        gd->flags &= ~GD_FLG_HUSH_OLD_PARSER;
+       gd->flags &= ~GD_FLG_HUSH_2021_PARSER;
  }

  static int do_cli_set(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -108,7 +113,7 @@ static int do_cli(struct cmd_tbl *cmdtp, int flag, int argc,
  #if CONFIG_IS_ENABLED(SYS_LONGHELP)
  static char cli_help_text[] =
        "get - print current cli\n"
-       "set - set the current cli, possible value is: old"
+       "set - set the current cli, possible value are: old, 2021"
        ;
  #endif

diff --git a/common/Makefile b/common/Makefile
index 615eba8672..4b060bb565 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -9,6 +9,7 @@ obj-y += init/
  obj-y += main.o
  obj-y += exports.o
  obj-$(CONFIG_HUSH_OLD_PARSER) += cli_hush.o
+obj-$(CONFIG_HUSH_2021_PARSER) += cli_hush_2021.o
  obj-$(CONFIG_AUTOBOOT) += autoboot.o

  # # boards
diff --git a/common/cli.c b/common/cli.c
index d419671e8c..e3e2bc7fe1 100644
--- a/common/cli.c
+++ b/common/cli.c
@@ -43,12 +43,15 @@ int run_command(const char *cmd, int flag)
                return 1;

        return 0;
-#else
+#elif CONFIG_IS_ENABLED(HUSH_OLD_PARSER)
        int hush_flags = FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP;

        if (flag & CMD_FLAG_ENV)
                hush_flags |= FLAG_CONT_ON_NEWLINE;
        return parse_string_outer(cmd, hush_flags);
+#else /* HUSH_2021_PARSER */
+       /* Not yet implemented. */
+       return 1;
  #endif
  }

@@ -108,7 +111,12 @@ int run_command_list(const char *cmd, int len, int flag)
                buff[len] = '\0';
        }
  #ifdef CONFIG_HUSH_PARSER
+#if CONFIG_IS_ENABLED(HUSH_OLD_PARSER)
        rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON);
+#else /* HUSH_2021_PARSER */
+       /* Not yet implemented. */
+       rcode = 1;
+#endif
  #else
        /*
         * This function will overwrite any \n it sees with a \0, which
@@ -254,8 +262,13 @@ err:
  void cli_loop(void)
  {
        bootstage_mark(BOOTSTAGE_ID_ENTER_CLI_LOOP);
-#ifdef CONFIG_HUSH_PARSER
-       parse_file_outer();
+#if CONFIG_IS_ENABLED(HUSH_PARSER)
+       if (gd->flags & GD_FLG_HUSH_2021_PARSER)
+               parse_and_run_file();
+       else if (gd->flags & GD_FLG_HUSH_OLD_PARSER)
+               parse_file_outer();
+
+       printf("Problem\n");
        /* This point is never reached */
        for (;;);
  #elif defined(CONFIG_CMDLINE)
@@ -268,10 +281,23 @@ void cli_loop(void)
  void cli_init(void)
  {
  #ifdef CONFIG_HUSH_PARSER
+       /* This if block is used to initialize hush parser gd flag. */
        if (!(gd->flags & GD_FLG_HUSH_OLD_PARSER)
-               && CONFIG_IS_ENABLED(HUSH_OLD_PARSER))
-               gd->flags |= GD_FLG_HUSH_OLD_PARSER;
-       u_boot_hush_start();
+               && !(gd->flags & GD_FLG_HUSH_2021_PARSER)) {
+               if (CONFIG_IS_ENABLED(HUSH_OLD_PARSER))
+                       gd->flags |= GD_FLG_HUSH_OLD_PARSER;
+               else if (CONFIG_IS_ENABLED(HUSH_2021_PARSER))
+                       gd->flags |= GD_FLG_HUSH_2021_PARSER;
+       }
+
+       if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+               u_boot_hush_start();
+       } else if (gd->flags & GD_FLG_HUSH_2021_PARSER) {
+               u_boot_hush_start_2021();
+       } else {
+               printf("No valid hush parser to use, cli will not 
initialized!\n");
+               return;
+       }
  #endif

  #if defined(CONFIG_HUSH_INIT_VAR)
diff --git a/common/cli_hush_2021.c b/common/cli_hush_2021.c
index 6d109933b8..653ea52929 100644
--- a/common/cli_hush_2021.c
+++ b/common/cli_hush_2021.c
@@ -221,6 +221,9 @@ static uint8_t xfunc_error_retval;
  static const char defifsvar[] __aligned(1) = "IFS= \t\n";
  #define defifs (defifsvar + 4)

+/* This define is used to check if exit command was called. */
+#define EXIT_RET_CODE -2
+
  /*
   * This define is used for changes that need be done directly in the upstream
   * sources still. Ideally, its use should be minimized as much as possible.
diff --git a/common/cli_hush_upstream.c b/common/cli_hush_upstream.c
index cc64af4e0c..84227a248e 100644
--- a/common/cli_hush_upstream.c
+++ b/common/cli_hush_upstream.c
@@ -7914,7 +7914,17 @@ static void parse_and_run_stream(struct in_str *inp, int 
end_trigger)
                }
                debug_print_tree(pipe_list, 0);
                debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
+#ifndef __U_BOOT__
                run_and_free_list(pipe_list);
+#else /* __U_BOOT__ */
+               int rcode = run_and_free_list(pipe_list);
+               /*
+                * We reset input string to not run the following command, so 
running
+                * 'exit; echo foo' does not print foo.
+                */
+               if (rcode <= EXIT_RET_CODE)
+                       setup_file_in_str(inp);
+#endif /* __U_BOOT__ */
                empty = 0;
                if (G_flag_return_in_progress == 1)
                        break;
@@ -10369,13 +10379,39 @@ static int run_list(struct pipe *pi)
  #endif /* !__U_BOOT__ */
                rcode = r = run_pipe(pi); /* NB: rcode is a smalluint, r is int 
*/
  #ifdef __U_BOOT__
-               if (r == -2) {
-                       /* -2 indicates exit was called, so we need to quit 
now. */
-                       G.last_exitcode = rcode;
+               if (r <= EXIT_RET_CODE) {
+                       int previous_rcode = G.last_exitcode;
+                       /*
+                        * This magic is to get the exit code given by the user.
+                        * Contrary to old shell code, we use + EXIT_RET_CODE 
as EXIT_RET_CODE
+                        * equals -2.
+                        */
+                       G.last_exitcode = -r + EXIT_RET_CODE;

-                       break;
+                       /*
+                        * This case deals with the following:
+                        * => setenv inner 'echo entry inner; exit; echo inner 
done'
+                        * => setenv outer 'echo entry outer; run inner; echo 
outer done'
+                        * => run outer
+                        * So, if we are in inner, we need to break and not run 
the other
+                        * commands.
+                        * Otherwise, we just continue in outer.
+                        * As return code are propagated, we use the previous 
value to check if
+                        * exit was just called or was propagated.
+                        */
+                       if (previous_rcode != r) {
+                               /*
+                                * If run from run_command, run_command_flags 
will be set, so we check
+                                * this to know if we are in main input shell.
+                                */
+                               if (!G.run_command_flags)
+                                       printf("exit not allowed from main input 
shell.\n");
+
+                               break;
+                       }
+                       continue;
                }
-#endif
+#endif /* __U_BOOT__ */
                if (r != -1) {
                        /* We ran a builtin, function, or group.
                         * rcode is already known
diff --git a/doc/usage/cmd/cli.rst b/doc/usage/cmd/cli.rst
index 89ece3203d..bc600bf9e9 100644
--- a/doc/usage/cmd/cli.rst
+++ b/doc/usage/cmd/cli.rst
@@ -41,7 +41,14 @@ Get the current parser::

  Change the current parser::

+    => cli get
+    old
+    => cli set 2021
+    => cli get
+    2021
      => cli set old
+    => cli get
+    old

  Trying to set the current parser to an unknown value::

@@ -51,7 +58,15 @@ Trying to set the current parser to an unknown value::

      Usage:
      cli get - print current cli
-    set - set the current cli, possible value is: old
+    set - set the current cli, possible values are: old, 2021
+
+Trying to set the current parser to a correct value but its code was not
+compiled::
+
+    => cli get
+    2021
+    => cli set old
+    Want to set current parser to old, but its code was not compiled!

  Return value
  ------------
diff --git a/include/asm-generic/global_data.h 
b/include/asm-generic/global_data.h
index f21926aa23..49ac892912 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -671,6 +671,10 @@ enum gd_flags {
         * @GD_FLG_HUSH_OLD_PARSER: Use hush old parser.
         */
        GD_FLG_HUSH_OLD_PARSER = 0x400000,
+       /**
+        * @GD_FLG_HUSH_2021_PARSER: Use hush 2021 parser.
+        */
+       GD_FLG_HUSH_2021_PARSER = 0x800000,
  };

  #endif /* __ASSEMBLY__ */
diff --git a/include/cli_hush.h b/include/cli_hush.h
index 2bd35670c7..4ef79de53c 100644
--- a/include/cli_hush.h
+++ b/include/cli_hush.h
@@ -12,11 +12,58 @@
  #define FLAG_REPARSING       (1 << 2)     /* >=2nd pass */
  #define FLAG_CONT_ON_NEWLINE (1 << 3)     /* continue when we see \n */

+#if CONFIG_IS_ENABLED(HUSH_OLD_PARSER)
  extern int u_boot_hush_start(void);
-extern int parse_string_outer(const char *, int);
+extern int parse_string_outer(const char *str, int flag);
  extern int parse_file_outer(void);
-
  int set_local_var(const char *s, int flg_export);
+#else
+static inline int u_boot_hush_start(void)
+{
+       return 0;
+}
+
+static inline int parse_string_outer(const char *str, int flag)
+{
+       return 1;
+}
+
+static inline int parse_file_outer(void)
+{
+       return 0;
+}
+
+static inline int set_local_var(const char *s, int flg_export)
+{
+       return 0;
+}
+#endif
+#if CONFIG_IS_ENABLED(HUSH_2021_PARSER)
+extern int u_boot_hush_start_2021(void);
+extern int parse_string_outer_2021(const char *str, int flag);
+extern void parse_and_run_file(void);
+int set_local_var_2021(char *s, int flg_export);
+#else
+static inline int u_boot_hush_start_2021(void)
+{
+       return 0;
+}
+
+static inline int parse_string_outer_2021(const char *str, int flag)
+{
+       return 1;
+}
+
+static inline void parse_and_run_file(void)
+{
+}
+
+static inline int set_local_var_2021(char *s, int flg_export)
+{
+       return 0;
+}
+#endif
+
  void unset_local_var(const char *name);
  char *get_local_var(const char *s);


Reply via email to