diff options
Diffstat (limited to 'builtins/declare.def')
-rw-r--r-- | builtins/declare.def | 219 |
1 files changed, 153 insertions, 66 deletions
diff --git a/builtins/declare.def b/builtins/declare.def index 4d94fac..a0ce605 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -1,59 +1,67 @@ This file is declare.def, from which is created declare.c. It implements the builtins "declare" and "local" in Bash. -Copyright (C) 1987-2004 Free Software Foundation, Inc. +Copyright (C) 1987-2009 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. -Bash is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. -Bash is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. -You should have received a copy of the GNU General Public License along -with Bash; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. +You should have received a copy of the GNU General Public License +along with Bash. If not, see <http://www.gnu.org/licenses/>. $PRODUCES declare.c $BUILTIN declare $FUNCTION declare_builtin -$SHORT_DOC declare [-afFirtx] [-p] [name[=value] ...] -Declare variables and/or give them attributes. If no NAMEs are -given, then display the values of variables instead. The -p option -will display the attributes and values of each NAME. +$SHORT_DOC declare [-aAfFilrtux] [-p] [name[=value] ...] +Set variable values and attributes. -The flags are: +Declare variables and give them attributes. If no NAMEs are given, +display the attributes and values of all variables. - -a to make NAMEs arrays (if supported) - -f to select from among function names only - -F to display function names (and line number and source file name if - debugging) without definitions +Options: + -f restrict action or display to function names and definitions + -F restrict display to function names only (plus line number and + source file when debugging) + -p display the attributes and value of each NAME + +Options which set attributes: + -a to make NAMEs indexed arrays (if supported) + -A to make NAMEs associative arrays (if supported) -i to make NAMEs have the `integer' attribute + -l to convert NAMEs to lower case on assignment -r to make NAMEs readonly -t to make NAMEs have the `trace' attribute + -u to convert NAMEs to upper case on assignment -x to make NAMEs export +Using `+' instead of `-' turns off the given attribute. + Variables with the integer attribute have arithmetic evaluation (see -`let') done when the variable is assigned to. +the `let' command) performed when the variable is assigned a value. -When displaying values of variables, -f displays a function's name -and definition. The -F option restricts the display to function -name only. +When used in a function, `declare' makes NAMEs local, as with the `local' +command. -Using `+' instead of `-' turns off the given attribute instead. When -used in a function, makes NAMEs local, as with the `local' command. +Exit Status: +Returns success unless an invalid option is supplied or an error occurs. $END $BUILTIN typeset $FUNCTION declare_builtin -$SHORT_DOC typeset [-afFirtx] [-p] name[=value] ... -Obsolete. See `declare'. +$SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ... +Set variable values and attributes. + +Obsolete. See `help declare'. $END #include <config.h> @@ -90,10 +98,18 @@ declare_builtin (list) $BUILTIN local $FUNCTION local_builtin -$SHORT_DOC local name[=value] ... -Create a local variable called NAME, and give it VALUE. LOCAL -can only be used within a function; it makes the variable NAME -have a visible scope restricted to that function and its children. +$SHORT_DOC local [option] name[=value] ... +Define local variables. + +Create a local variable called NAME, and give it VALUE. OPTION can +be any option accepted by `declare'. + +Local variables can only be used within a function; they are visible +only to the function where they are defined and its children. + +Exit Status: +Returns success unless an invalid option is supplied, an error occurs, +or the shell is not executing a function. $END int local_builtin (list) @@ -109,9 +125,9 @@ local_builtin (list) } #if defined (ARRAY_VARS) -# define DECLARE_OPTS "+afiprtxF" +# define DECLARE_OPTS "+acfilprtuxAF" #else -# define DECLARE_OPTS "+fiprtxF" +# define DECLARE_OPTS "+cfilprtuxF" #endif /* The workhorse function. */ @@ -120,7 +136,8 @@ declare_internal (list, local_var) register WORD_LIST *list; int local_var; { - int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs, opt; + int flags_on, flags_off, *flags; + int any_failed, assign_error, pflag, nodefs, opt; char *t, *subscript_start; SHELL_VAR *var; FUNCTION_DEF *shell_fn; @@ -136,8 +153,19 @@ declare_internal (list, local_var) case 'a': #if defined (ARRAY_VARS) *flags |= att_array; + break; +#else + builtin_usage (); + return (EX_USAGE); #endif + case 'A': +#if defined (ARRAY_VARS) + *flags |= att_assoc; break; +#else + builtin_usage (); + return (EX_USAGE); +#endif case 'p': if (local_var == 0) pflag++; @@ -162,6 +190,25 @@ declare_internal (list, local_var) *flags |= att_exported; array_needs_making = 1; break; +#if defined (CASEMOD_ATTRS) +# if defined (CASEMOD_CAPCASE) + case 'c': + *flags |= att_capcase; + if (flags == &flags_on) + flags_off |= att_uppercase|att_lowercase; + break; +# endif + case 'l': + *flags |= att_lowercase; + if (flags == &flags_on) + flags_off |= att_capcase|att_uppercase; + break; + case 'u': + *flags |= att_uppercase; + if (flags == &flags_on) + flags_off |= att_capcase|att_lowercase; + break; +#endif /* CASEMOD_ATTRS */ default: builtin_usage (); return (EX_USAGE); @@ -172,7 +219,7 @@ declare_internal (list, local_var) /* If there are no more arguments left, then we just want to show some variables. */ - if (list == 0) /* declare -[afFirtx] */ + if (list == 0) /* declare -[aAfFirtx] */ { /* Show local variables defined at this context level if this is the `local' builtin. */ @@ -191,19 +238,17 @@ declare_internal (list, local_var) free (vlist); } } + else if (pflag && (flags_on == 0 || flags_on == att_function)) + show_all_var_attributes (flags_on == 0, nodefs); + else if (flags_on == 0) + return (set_builtin ((WORD_LIST *)NULL)); else - { - if (flags_on == 0) - set_builtin ((WORD_LIST *)NULL); - else - set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs); - } + set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs); - fflush (stdout); - return (EXECUTION_SUCCESS); + return (sh_chkwrite (EXECUTION_SUCCESS)); } - if (pflag) /* declare -p [-afFirtx] name [name...] */ + if (pflag) /* declare -p [-aAfFirtx] name [name...] */ { for (any_failed = 0; list; list = list->next) { @@ -214,13 +259,13 @@ declare_internal (list, local_var) any_failed++; } } - return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS); + return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS)); } #define NEXT_VARIABLE() free (name); list = list->next; continue /* There are arguments left, so we are making variables. */ - while (list) /* declare [-afFirx] name [name ...] */ + while (list) /* declare [-aAfFirx] name [name ...] */ { char *value, *name; int offset, aflags; @@ -232,7 +277,7 @@ declare_internal (list, local_var) offset = assignment (name, 0); aflags = 0; - if (offset) /* declare [-afFirx] name=value */ + if (offset) /* declare [-aAfFirx] name=value */ { name[offset] = '\0'; value = name + offset + 1; @@ -250,6 +295,13 @@ declare_internal (list, local_var) subscript_start = (char *)NULL; if (t = strchr (name, '[')) /* ] */ { + /* If offset != 0 we have already validated any array reference */ + if (offset == 0 && valid_array_reference (name) == 0) + { + sh_invalidid (name); + assign_error++; + NEXT_VARIABLE (); + } subscript_start = t; *t = '\0'; making_array_special = 1; @@ -279,7 +331,9 @@ declare_internal (list, local_var) if (variable_context && ((flags_on & att_function) == 0)) { #if defined (ARRAY_VARS) - if ((flags_on & att_array) || making_array_special) + if (flags_on & att_assoc) + var = make_local_assoc_variable (name); + else if ((flags_on & att_array) || making_array_special) var = make_local_array_variable (name); else #endif @@ -336,8 +390,9 @@ declare_internal (list, local_var) #endif /* DEBUGGER */ { t = nodefs ? var->name - : named_function_string (name, function_cell (var), 1); + : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL); printf ("%s\n", t); + any_failed = sh_chkwrite (any_failed); } } else /* declare -[fF] -[rx] name [name...] */ @@ -351,7 +406,7 @@ declare_internal (list, local_var) NEXT_VARIABLE (); } } - else /* declare -[airx] name [name...] */ + else /* declare -[aAirx] name [name...] */ { /* Non-null if we just created or fetched a local variable. */ if (var == 0) @@ -360,11 +415,20 @@ declare_internal (list, local_var) if (var == 0) { #if defined (ARRAY_VARS) - if ((flags_on & att_array) || making_array_special) + if (flags_on & att_assoc) + var = make_new_assoc_variable (name); + else if ((flags_on & att_array) || making_array_special) var = make_new_array_variable (name); else #endif - var = bind_variable (name, "", 0); + + if (offset) + var = bind_variable (name, "", 0); + else + { + var = bind_variable (name, (char *)NULL, 0); + VSETATTR (var, att_invisible); + } } /* Cannot use declare +r to turn off readonly attribute. */ @@ -386,30 +450,48 @@ declare_internal (list, local_var) } #if defined (ARRAY_VARS) - if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset) + if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset) { int vlen; vlen = STRLEN (value); -#if 0 - if (value[0] == '(' && strchr (value, ')')) -#else + if (value[0] == '(' && value[vlen-1] == ')') -#endif compound_array_assign = 1; else simple_array_assign = 1; } - /* Cannot use declare +a name to remove an array variable. */ - if ((flags_off & att_array) && array_p (var)) + /* Cannot use declare +a name or declare +A name to remove an + array variable. */ + if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var))) { builtin_error (_("%s: cannot destroy array variables in this way"), name); any_failed++; NEXT_VARIABLE (); } - /* declare -a name makes name an array variable. */ - if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0) + if ((flags_on & att_array) && assoc_p (var)) + { + builtin_error (_("%s: cannot convert associative to indexed array"), name); + any_failed++; + NEXT_VARIABLE (); + } + if ((flags_on & att_assoc) && array_p (var)) + { + builtin_error (_("%s: cannot convert indexed to associative array"), name); + any_failed++; + NEXT_VARIABLE (); + } + + /* declare -A name[[n]] makes name an associative array variable. */ + if (flags_on & att_assoc) + { + if (assoc_p (var) == 0) + var = convert_var_to_assoc (var); + } + /* declare -a name[[n]] or declare name[n] makes name an indexed + array variable. */ + else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0) var = convert_var_to_array (var); #endif /* ARRAY_VARS */ @@ -421,14 +503,19 @@ declare_internal (list, local_var) assign_array_var_from_string (var, value, aflags); else if (simple_array_assign && subscript_start) { - /* declare [-a] name[N]=value */ + /* declare [-aA] name[N]=value */ *subscript_start = '['; /* ] */ var = assign_array_element (name, value, 0); /* XXX - not aflags */ *subscript_start = '\0'; } else if (simple_array_assign) - /* let bind_array_variable take care of this. */ - bind_array_variable (name, 0, value, aflags); + { + /* let bind_{array,assoc}_variable take care of this. */ + if (assoc_p (var)) + bind_assoc_variable (var, name, "0", value, aflags); + else + bind_array_variable (name, 0, value, aflags); + } else #endif /* bind_variable_value duplicates the essential internals of |