summaryrefslogtreecommitdiff
path: root/variables.c
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2011-11-28 14:41:26 -0500
committerChet Ramey <chet.ramey@case.edu>2011-11-28 14:41:26 -0500
commitd3a24ed242e91e6afb53b2cbf38b89667637168d (patch)
treeb67e38d2eca8abd31da74e1dcbe69dd1bfa679a3 /variables.c
parent7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (diff)
downloadbash-d3a24ed242e91e6afb53b2cbf38b89667637168d.tar.gz
Initial devel branch import from bash-3.0-alpha
Diffstat (limited to 'variables.c')
-rw-r--r--variables.c355
1 files changed, 312 insertions, 43 deletions
diff --git a/variables.c b/variables.c
index 1f9180e8..97a00849 100644
--- a/variables.c
+++ b/variables.c
@@ -1,6 +1,6 @@
/* variables.c -- Functions for hacking shell variables. */
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2003 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -72,17 +72,24 @@
/* Variables used here and defined in other files. */
extern int posixly_correct;
extern int line_number;
-extern int subshell_environment, indirection_level;
+extern int subshell_environment, indirection_level, subshell_level;
extern int build_version, patch_level;
+extern int expanding_redir;
extern char *dist_version, *release_status;
extern char *shell_name;
extern char *primary_prompt, *secondary_prompt;
extern char *current_host_name;
extern sh_builtin_func_t *this_shell_builtin;
extern SHELL_VAR *this_shell_function;
+extern char *the_printed_command_except_trap;
extern char *this_command_name;
+extern char *command_execution_string;
extern time_t shell_start_time;
+#if defined (READLINE)
+extern int perform_hostname_completion;
+#endif
+
/* The list of shell variables that the user has created at the global
scope, or that came from the environment. */
VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
@@ -94,6 +101,12 @@ VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
the environment. */
HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
+#if defined (DEBUGGER)
+/* The table of shell function definitions that the user defined or that
+ came from the environment. */
+HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
+#endif
+
/* The current variable context. This is really a count of how deep into
executing functions we are. */
int variable_context = 0;
@@ -139,6 +152,11 @@ static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
#if defined (ARRAY_VARS)
static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
#endif
+static SHELL_VAR *get_self __P((SHELL_VAR *));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
+#endif
static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
static SHELL_VAR *get_seconds __P((SHELL_VAR *));
@@ -152,6 +170,9 @@ static SHELL_VAR *get_random __P((SHELL_VAR *));
static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
static SHELL_VAR *get_lineno __P((SHELL_VAR *));
+static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
+static SHELL_VAR *get_subshell __P((SHELL_VAR *));
+
#if defined (HISTORY)
static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
#endif
@@ -159,12 +180,10 @@ static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
-static SHELL_VAR *init_dirstack_var __P((void));
#endif
#if defined (ARRAY_VARS)
static SHELL_VAR *get_groupset __P((SHELL_VAR *));
-static SHELL_VAR *init_groups_var __P((void));
#endif
static SHELL_VAR *get_funcname __P((SHELL_VAR *));
@@ -239,6 +258,11 @@ initialize_shell_variables (env, privmode)
if (shell_functions == 0)
shell_functions = hash_create (0);
+#if defined (DEBUGGER)
+ if (shell_function_defs == 0)
+ shell_function_defs = hash_create (0);
+#endif
+
for (string_index = 0; string = env[string_index++]; )
{
char_index = 0;
@@ -408,6 +432,9 @@ initialize_shell_variables (env, privmode)
make_vers_array ();
#endif
+ if (command_execution_string)
+ bind_variable ("BASH_EXECUTION_STRING", command_execution_string);
+
/* Find out if we're supposed to be in Posix.2 mode via an
environment variable. */
temp_var = find_variable ("POSIXLY_CORRECT");
@@ -986,6 +1013,38 @@ null_array_assign (self, value, ind)
}
#endif
+/* Degenerate `dynamic_value' function; just returns what's passed without
+ manipulation. */
+static SHELL_VAR *
+get_self (self)
+ SHELL_VAR *self;
+{
+ return (self);
+}
+
+#if defined (ARRAY_VARS)
+/* A generic dynamic array variable initializer. Intialize array variable
+ NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
+static SHELL_VAR *
+init_dynamic_array_var (name, getfunc, setfunc, attrs)
+ char *name;
+ sh_var_value_func_t *getfunc;
+ sh_var_assign_func_t *setfunc;
+ int attrs;
+{
+ SHELL_VAR *v;
+
+ v = find_variable (name);
+ if (v)
+ return (v);
+ INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
+ if (attrs)
+ VSETATTR (v, attrs);
+ return v;
+}
+#endif
+
+
/* The value of $SECONDS. This is the number of seconds since shell
invocation, or, the number of seconds since the last assignment + the
value of the last assignment. */
@@ -1132,6 +1191,44 @@ get_lineno (var)
return (var);
}
+static SHELL_VAR *
+assign_subshell (var, value, unused)
+ SHELL_VAR *var;
+ char *value;
+ arrayind_t unused;
+{
+ intmax_t new_value;
+
+ if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+ new_value = 0;
+ subshell_level = new_value;
+ return var;
+}
+
+static SHELL_VAR *
+get_subshell (var)
+ SHELL_VAR *var;
+{
+ char *p;
+
+ p = itos (subshell_level);
+ FREE (value_cell (var));
+ var_setvalue (var, p);
+ return (var);
+}
+
+static SHELL_VAR *
+get_bash_command (var)
+ SHELL_VAR *var;
+{
+ char *p;
+
+ p = savestring (the_printed_command_except_trap);
+ FREE (value_cell (var));
+ var_setvalue (var, p);
+ return (var);
+}
+
#if defined (HISTORY)
static SHELL_VAR *
get_histcmd (var)
@@ -1146,8 +1243,49 @@ get_histcmd (var)
}
#endif
+#if defined (READLINE)
+/* When this function returns, VAR->value points to malloced memory. */
+static SHELL_VAR *
+get_comp_wordbreaks (var)
+ SHELL_VAR *var;
+{
+ char *p;
+
+ /* If we don't have anything yet, assign a default value. */
+ if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
+ enable_hostname_completion (perform_hostname_completion);
+
+#if 0
+ FREE (value_cell (var));
+ p = savestring (rl_completer_word_break_characters);
+
+ var_setvalue (var, p);
+#else
+ var_setvalue (var, rl_completer_word_break_characters);
+#endif
+
+ return (var);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+ malloced memory. */
+static SHELL_VAR *
+assign_comp_wordbreaks (self, value, unused)
+ SHELL_VAR *self;
+ char *value;
+ arrayind_t unused;
+{
+ if (rl_completer_word_break_characters &&
+ rl_completer_word_break_characters != rl_basic_word_break_characters)
+ free (rl_completer_word_break_characters);
+
+ rl_completer_word_break_characters = savestring (value);
+ return self;
+}
+#endif /* READLINE */
+
#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
-static SHELL_VAR *
+static SHELL_VAR *
assign_dirstack (self, value, ind)
SHELL_VAR *self;
char *value;
@@ -1171,18 +1309,6 @@ get_dirstack (self)
var_setarray (self, a);
return self;
}
-
-static SHELL_VAR *
-init_dirstack_var ()
-{
- SHELL_VAR *v;
-
- v = find_variable ("DIRSTACK");
- if (v)
- return v;
- INIT_DYNAMIC_ARRAY_VAR ("DIRSTACK", get_dirstack, assign_dirstack);
- return v;
-}
#endif /* PUSHD AND POPD && ARRAY_VARS */
#if defined (ARRAY_VARS)
@@ -1206,25 +1332,15 @@ get_groupset (self)
}
return (self);
}
-
-static SHELL_VAR *
-init_groups_var ()
-{
- SHELL_VAR *v;
-
- v = find_variable ("GROUPS");
- if (v)
- return (v);
- INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign);
- VSETATTR (v, att_noassign);
- return v;
-}
#endif /* ARRAY_VARS */
+/* If ARRAY_VARS is not defined, this just returns the name of any
+ currently-executing function. If we have arrays, it's a call stack. */
static SHELL_VAR *
get_funcname (self)
SHELL_VAR *self;
{
+#if ! defined (ARRAY_VARS)
char *t;
if (variable_context && this_shell_function)
{
@@ -1232,6 +1348,7 @@ get_funcname (self)
t = savestring (this_shell_function->name);
var_setvalue (self, t);
}
+#endif
return (self);
}
@@ -1259,7 +1376,11 @@ init_funcname_var ()
v = find_variable ("FUNCNAME");
if (v)
return v;
+#if defined (ARRAY_VARS)
+ INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
+#else
INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
+#endif
VSETATTR (v, att_invisible|att_noassign);
return v;
}
@@ -1271,6 +1392,9 @@ initialize_dynamic_variables ()
v = init_seconds_var ();
+ INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
+ INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
+
INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
@@ -1278,12 +1402,23 @@ initialize_dynamic_variables ()
INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
#endif
+#if defined (READLINE)
+ INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
+#endif
+
#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
- v = init_dirstack_var ();
+ v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
#endif /* PUSHD_AND_POPD && ARRAY_VARS */
#if defined (ARRAY_VARS)
- v = init_groups_var ();
+ v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
+
+# if defined (DEBUGGER)
+ v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, (att_invisible|att_noassign));
+ v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, (att_invisible|att_noassign));
+# endif /* DEBUGGER */
+ v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, (att_invisible|att_noassign));
+ v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, (att_invisible|att_noassign));
#endif
v = init_funcname_var ();
@@ -1334,11 +1469,12 @@ var_lookup (name, vcontext)
*/
SHELL_VAR *
-find_variable_internal (name, search_tempenv)
+find_variable_internal (name, force_tempenv)
const char *name;
- int search_tempenv;
+ int force_tempenv;
{
SHELL_VAR *var;
+ int search_tempenv;
var = (SHELL_VAR *)NULL;
@@ -1347,7 +1483,9 @@ find_variable_internal (name, search_tempenv)
to get the `exported' value of $foo. This happens if we are executing
a function or builtin, or if we are looking up a variable in a
"subshell environment". */
- if ((search_tempenv || subshell_environment) && temporary_env)
+ search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
+
+ if (search_tempenv && temporary_env)
var = hash_lookup (name, temporary_env);
if (var == 0)
@@ -1364,7 +1502,7 @@ SHELL_VAR *
find_variable (name)
const char *name;
{
- return (find_variable_internal (name, this_shell_builtin != 0));
+ return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
}
/* Look up the function entry whose name matches STRING.
@@ -1376,6 +1514,15 @@ find_function (name)
return (hash_lookup (name, shell_functions));
}
+/* Find the function definition for the shell function named NAME. Returns
+ the entry or NULL. */
+FUNCTION_DEF *
+find_function_def (name)
+ const char *name;
+{
+ return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
+}
+
/* Return the value of VAR. VAR is assumed to have been the result of a
lookup without any subscript, if arrays are compiled into the shell. */
char *
@@ -1788,7 +1935,11 @@ bind_int_variable (lhs, rhs)
isint = isarr = 0;
#if defined (ARRAY_VARS)
+# if 0
if (t = xstrchr (lhs, '[')) /*]*/
+# else
+ if (valid_array_reference (lhs))
+# endif
{
isarr = 1;
v = array_variable_part (lhs, (char **)0, (int *)0);
@@ -1873,6 +2024,31 @@ bind_function (name, value)
return (entry);
}
+/* Bind a function definition, which includes source file and line number
+ information in addition to the command, into the FUNCTION_DEF hash table.*/
+void
+bind_function_def (name, value)
+ const char *name;
+ FUNCTION_DEF *value;
+{
+ FUNCTION_DEF *entry;
+ BUCKET_CONTENTS *elt;
+
+ entry = find_function_def (name);
+ if (entry)
+ {
+ dispose_function_def_contents (entry);
+ entry = copy_function_def_contents (value, entry);
+ }
+ else
+ {
+ entry = copy_function_def (value);
+
+ elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
+ elt->data = (PTR_T *)entry;
+ }
+}
+
/* Add STRING, which is of the form foo=bar, to the temporary environment
HASH_TABLE (temporary_env). The functions in execute_cmd.c are
responsible for moving the main temporary env to one of the other
@@ -2062,6 +2238,28 @@ unbind_func (name)
return 0;
}
+int
+unbind_function_def (name)
+ const char *name;
+{
+ BUCKET_CONTENTS *elt;
+ FUNCTION_DEF *funcdef;
+
+ elt = hash_remove (name, shell_function_defs, 0);
+
+ if (elt == 0)
+ return -1;
+
+ funcdef = (FUNCTION_DEF *)elt->data;
+ if (funcdef)
+ dispose_function_def (funcdef);
+
+ free (elt->key);
+ free (elt);
+
+ return 0;
+}
+
/* Make the variable associated with NAME go away. HASH_LIST is the
hash table from which this variable should be deleted (either
shell_variables or shell_functions).
@@ -3334,6 +3532,56 @@ dispose_saved_dollar_vars ()
dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
}
+/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
+
+void
+push_args (list)
+ WORD_LIST *list;
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+ SHELL_VAR *bash_argv_v, *bash_argc_v;
+ ARRAY *bash_argv_a, *bash_argc_a;
+ WORD_LIST *l;
+ arrayind_t i;
+ char *t;
+
+ GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+ GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+ for (l = list, i = 0; l; l = l->next, i++)
+ array_push (bash_argv_a, l->word->word);
+
+ t = itos (i);
+ array_push (bash_argc_a, t);
+ free (t);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
+/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
+ array and use that value as the count of elements to remove from
+ BASH_ARGV. */
+void
+pop_args ()
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+ SHELL_VAR *bash_argv_v, *bash_argc_v;
+ ARRAY *bash_argv_a, *bash_argc_a;
+ ARRAY_ELEMENT *ce;
+ intmax_t i;
+
+ GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+ GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+ ce = array_shift (bash_argc_a, 1, 0);
+ if (ce == 0 || legal_number (element_value (ce), &i) == 0)
+ i = 0;
+
+ for ( ; i > 0; i--)
+ array_pop (bash_argv_a);
+ array_dispose_element (ce);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
/*************************************************
* *
* Functions to manage special variables *
@@ -3369,6 +3617,7 @@ static struct name_and_function special_vars[] = {
{ "HISTFILESIZE", sv_histsize },
{ "HISTIGNORE", sv_histignore },
{ "HISTSIZE", sv_histsize },
+ { "HISTTIMEFORMAT", sv_histtimefmt },
#endif
#if defined (READLINE)
@@ -3598,18 +3847,28 @@ sv_history_control (name)
char *name;
{
char *temp;
+ char *val;
+ int tptr;
history_control = 0;
temp = get_string_value (name);
- if (temp && *temp && STREQN (temp, "ignore", 6))
+ if (temp == 0 || *temp == 0)
+ return;
+
+ tptr = 0;
+ while (val = extract_colon_unit (temp, &tptr))
{
- if (temp[6] == 's') /* ignorespace */
- history_control = 1;
- else if (temp[6] == 'd') /* ignoredups */
- history_control = 2;
- else if (temp[6] == 'b') /* ignoreboth */
- history_control = 3;
+ if (STREQ (val, "ignorespace"))
+ history_control |= HC_IGNSPACE;
+ else if (STREQ (val, "ignoredups"))
+ history_control |= HC_IGNDUPS;
+ else if (STREQ (val, "ignoreboth"))
+ history_control |= HC_IGNBOTH;
+ else if (STREQ (val, "erasedups"))
+ history_control |= HC_ERASEDUPS;
+
+ free (val);
}
}
@@ -3640,6 +3899,16 @@ sv_histchars (name)
}
}
#endif /* BANG_HISTORY */
+
+void
+sv_histtimefmt (name)
+ char *name;
+{
+ SHELL_VAR *v;
+
+ v = find_variable (name);
+ history_write_timestamps = (v != 0);
+}
#endif /* HISTORY */
#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)