bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issues with exported functions


From: Ángel González
Subject: Re: Issues with exported functions
Date: Fri, 26 Sep 2014 00:58:43 +0200

Chet Ramey wrote:
> On 9/25/14, 2:47 PM, lolilolicon wrote:
> > On Fri, Sep 26, 2014 at 2:28 AM, Ángel González wrote:
> > [...]
> >> On the other hand, this approach would be much more interesting if bash
> >> delayed parsing of exported functions until they are used (ie. check
> > 
> > This is what function autoload is for in zsh. It's indeed a better
> > approach. It was also suggested by Dan Douglas in this thread ("FPATH
> > mechanism").
> 
> Not quite.  While autoloaded functions are lazily evaluated, you have to
> pay the price of searching $FPATH and loading them in every shell, and
> there still has to be a mechanism to indicate which functions should be
> autoloaded in each shell.
> 
> Chet

I wasn't refering to storing the functions in files, but to lazily parse
the command from the environment. It wouldn't affect the way bash
functions are transfered.

See the naive implementation provided below:


diff --git a/variables.h b/variables.h
index 1a783b9..f496b9d 100644
--- a/variables.h
+++ b/variables.h
@@ -125,6 +125,7 @@ typedef struct _vlist {
 #define att_imported   0x0008000       /* came from environment */
 #define att_special    0x0010000       /* requires special handling */
 #define att_nofree     0x0020000       /* do not free value on unset */
+#define att_unparsed   0x0040000       /* it was not parsed after loading from 
environ */
 
 #define        attmask_int     0x00ff000
 
@@ -153,6 +154,7 @@ typedef struct _vlist {
 #define imported_p(var)                ((((var)->attributes) & (att_imported)))
 #define specialvar_p(var)      ((((var)->attributes) & (att_special)))
 #define nofree_p(var)          ((((var)->attributes) & (att_nofree)))
+#define unparsed_p(var)                ((((var)->attributes) & (att_unparsed)))
 
 #define tempvar_p(var)         ((((var)->attributes) & (att_tempvar)))
 
diff --git a/variables.c b/variables.c
index 92a5a10..a0e42ff 100644
--- a/variables.c
+++ b/variables.c
@@ -351,34 +351,13 @@ initialize_shell_variables (env, privmode)
         the environment in privileged mode. */
       if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", 
string, 4))
        {
-         string_length = strlen (string);
-         temp_string = (char *)xmalloc (3 + string_length + char_index);
 
-         strcpy (temp_string, name);
-         temp_string[char_index] = ' ';
-         strcpy (temp_string + char_index + 1, string);
-
-         /* Don't import function names that are invalid identifiers from the
-            environment, though we still allow them to be defined as shell
-            variables. */
-         if (legal_identifier (name))
-           parse_and_execute (temp_string, name, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
-
-         if (temp_var = find_function (name))
-           {
-             VSETATTR (temp_var, (att_exported|att_imported));
-             array_needs_making = 1;
-           }
-         else
-           {
-             if (temp_var = bind_variable (name, string, 0))
+             if (temp_var = bind_function (name, 0))
                {
-                 VSETATTR (temp_var, (att_exported | att_imported | 
att_invisible));
+                 VSETATTR (temp_var, (att_exported | att_imported | 
att_unparsed));
+                 SET_EXPORTSTR(temp_var, savestring (string));
                  array_needs_making = 1;
                }
-             last_command_exit_value = 1;
-             report_error (_("error importing function definition for `%s'"), 
name);
-           }
        }
 #if defined (ARRAY_VARS)
 #  if ARRAY_EXPORT
@@ -1049,8 +1028,11 @@ print_var_function (var)
 
   if (function_p (var) && var_isset (var))
     {
-      x = named_function_string ((char *)NULL, function_cell(var), 
FUNC_MULTILINE|FUNC_EXTERNAL);
-      printf ("%s", x);
+         if (!maybe_parse_unparsed_func (var))
+           {
+          x = named_function_string ((char *)NULL, function_cell(var), 
FUNC_MULTILINE|FUNC_EXTERNAL);
+          printf ("%s", x);
+           }
     }
 }
 
@@ -3929,7 +3911,16 @@ make_env_array_from_var_list (vars)
       if (var->exportstr)
        value = var->exportstr;
       else if (function_p (var))
-       value = named_function_string ((char *)NULL, function_cell (var), 0);
+               {
+                 if (unparsed_p (var))
+                   {
+                         value = var->exportstr;
+                       }
+                 else
+                   {
+                         value = named_function_string ((char *)NULL, 
function_cell (var), 0);
+                   }
+               }
 #if defined (ARRAY_VARS)
       else if (array_p (var))
 #  if ARRAY_EXPORT
diff --git a/execute_cmd.h b/execute_cmd.h
index 67ae93a..4f4e3ee 100644
--- a/execute_cmd.h
+++ b/execute_cmd.h
@@ -27,6 +27,7 @@ extern struct fd_bitmap *new_fd_bitmap __P((int));
 extern void dispose_fd_bitmap __P((struct fd_bitmap *));
 extern void close_fd_bitmap __P((struct fd_bitmap *));
 extern int executing_line_number __P((void));
+extern int maybe_parse_unparsed_func __P((SHELL_VAR*));
 extern int execute_command __P((COMMAND *));
 extern int execute_command_internal __P((COMMAND *, int, int, int, struct 
fd_bitmap *));
 extern int shell_execve __P((char *, char **, char **));
diff --git a/execute_cmd.c b/execute_cmd.c
index 9cebaef..df060d3 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -4368,6 +4368,46 @@ execute_builtin (builtin, words, flags, subshell)
   return (result);
 }
 
+int
+maybe_parse_unparsed_func (var)
+     SHELL_VAR *var;
+{
+       int result, string_length, char_index;
+       char *temp_string;
+
+       if (!unparsed_p(var))
+    return 0;
+
+       string_length = strlen (var->exportstr);
+       char_index = strlen (var->name);
+       temp_string = (char *)xmalloc (3 + string_length + char_index);
+
+       strcpy (temp_string, var->name);
+       temp_string[char_index] = ' ';
+       strcpy (temp_string + char_index + 1, var->exportstr);
+
+       /* Don't import function names that are invalid identifiers from the
+        environment, though we still allow them to be defined as shell
+        variables. */
+       result = 1;
+       if (legal_identifier (var->name) &&
+                       !(result = parse_and_execute (temp_string, var->name, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD)))
+               {
+                       var = find_function (var->name);
+                       VSETATTR (var, (att_exported|att_imported));
+                       VUNSETATTR(var, att_unparsed);
+               }
+       else
+               {
+                       if (!legal_identifier (var->name))
+                               free (temp_string);
+                       last_command_exit_value = 1;
+                       report_error (_("error importing function definition 
for `%s'"), var->name);
+                       return result;
+               }
+       return 0;
+}
+
 static int
 execute_function (var, words, flags, fds_to_close, async, subshell)
      SHELL_VAR *var;
@@ -4403,6 +4443,10 @@ execute_function (var, words, flags, fds_to_close, 
async, subshell)
   GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
 #endif
 
+  if (result = maybe_parse_unparsed_func (var))
+     return result;
+
+
   tc = (COMMAND *)copy_command (function_cell (var));
   if (tc && (flags & CMD_IGNORE_RETURN))
     tc->flags |= CMD_IGNORE_RETURN;
@@ -4502,7 +4546,7 @@ execute_function (var, words, flags, fds_to_close, async, 
subshell)
     push_args (words->next);
 
   /* Number of the line on which the function body starts. */
-  line_number = function_line_number = tc->line;
+  line_number = function_line_number = tc ? tc->line : 0;
 
 #if defined (JOB_CONTROL)
   if (subshell)
diff --git a/builtins/type.def b/builtins/type.def
index bd9ecfc..25c1943 100644
--- a/builtins/type.def
+++ b/builtins/type.def
@@ -274,7 +274,8 @@ describe_command (command, dflags)
          printf (_("%s is a function\n"), command);
 
          /* We're blowing away THE_PRINTED_COMMAND here... */
-
+      if (result = maybe_parse_unparsed_func (func))
+               return result;
          result = named_function_string (command, function_cell (func), 
FUNC_MULTILINE|FUNC_EXTERNAL);
          printf ("%s\n", result);
        }
diff --git a/builtins/setattr.def b/builtins/setattr.def
index 3be3189..f25558e 100644
--- a/builtins/setattr.def
+++ b/builtins/setattr.def
@@ -348,7 +348,7 @@ show_var_attributes (var, pattr, nodefs)
      int pattr, nodefs;
 {
   char flags[16], *x;
-  int i;
+  int i, result;
 
   i = 0;
 
@@ -411,6 +411,8 @@ show_var_attributes (var, pattr, nodefs)
      reused as input to recreate the current state. */
   if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
     {
+      if (result = maybe_parse_unparsed_func (var))
+               return result;
       printf ("%s\n", named_function_string (var->name, function_cell (var), 
FUNC_MULTILINE|FUNC_EXTERNAL));
       nodefs++;
       if (pattr == 0 && i == 1 && flags[0] == 'f')



reply via email to

[Prev in Thread] Current Thread [Next in Thread]