diff options
author | Chet Ramey <chet.ramey@case.edu> | 2011-11-28 14:41:26 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2011-11-28 14:41:26 -0500 |
commit | d3a24ed242e91e6afb53b2cbf38b89667637168d (patch) | |
tree | b67e38d2eca8abd31da74e1dcbe69dd1bfa679a3 /variables.c | |
parent | 7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (diff) | |
download | bash-d3a24ed242e91e6afb53b2cbf38b89667637168d.tar.gz |
Initial devel branch import from bash-3.0-alpha
Diffstat (limited to 'variables.c')
-rw-r--r-- | variables.c | 355 |
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) |