1 This file is declare.def, from which is created declare.c.
2 It implements the builtins "declare" and "local" in Bash.
4 Copyright (C) 1987-2010 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
24 $FUNCTION declare_builtin
25 $SHORT_DOC declare [-aAfFgilrtux] [-p] [name[=value] ...]
26 Set variable values and attributes.
28 Declare variables and give them attributes. If no NAMEs are given,
29 display the attributes and values of all variables.
32 -f restrict action or display to function names and definitions
33 -F restrict display to function names only (plus line number and
34 source file when debugging)
35 -g create global variables when used in a shell function; otherwise
37 -p display the attributes and value of each NAME
39 Options which set attributes:
40 -a to make NAMEs indexed arrays (if supported)
41 -A to make NAMEs associative arrays (if supported)
42 -i to make NAMEs have the `integer' attribute
43 -l to convert NAMEs to lower case on assignment
44 -r to make NAMEs readonly
45 -t to make NAMEs have the `trace' attribute
46 -u to convert NAMEs to upper case on assignment
47 -x to make NAMEs export
49 Using `+' instead of `-' turns off the given attribute.
51 Variables with the integer attribute have arithmetic evaluation (see
52 the `let' command) performed when the variable is assigned a value.
54 When used in a function, `declare' makes NAMEs local, as with the `local'
55 command. The `-g' option suppresses this behavior.
58 Returns success unless an invalid option is supplied or an error occurs.
62 $FUNCTION declare_builtin
63 $SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
64 Set variable values and attributes.
66 Obsolete. See `help declare'.
71 #if defined (HAVE_UNISTD_H)
73 # include <sys/types.h>
80 #include "../bashansi.h"
81 #include "../bashintl.h"
86 #include "bashgetopt.h"
88 extern int array_needs_making;
89 extern int posixly_correct;
91 static int declare_internal __P((register WORD_LIST *, int));
93 /* Declare or change variable attributes. */
95 declare_builtin (list)
96 register WORD_LIST *list;
98 return (declare_internal (list, 0));
102 $FUNCTION local_builtin
103 $SHORT_DOC local [option] name[=value] ...
104 Define local variables.
106 Create a local variable called NAME, and give it VALUE. OPTION can
107 be any option accepted by `declare'.
109 Local variables can only be used within a function; they are visible
110 only to the function where they are defined and its children.
113 Returns success unless an invalid option is supplied, an error occurs,
114 or the shell is not executing a function.
118 register WORD_LIST *list;
120 if (variable_context)
121 return (declare_internal (list, 1));
124 builtin_error (_("can only be used in a function"));
125 return (EXECUTION_FAILURE);
129 #if defined (ARRAY_VARS)
130 # define DECLARE_OPTS "+acfgilprtuxAF"
132 # define DECLARE_OPTS "+cfgilprtuxF"
135 /* The workhorse function. */
137 declare_internal (list, local_var)
138 register WORD_LIST *list;
141 int flags_on, flags_off, *flags;
142 int any_failed, assign_error, pflag, nodefs, opt, mkglobal;
143 char *t, *subscript_start;
145 FUNCTION_DEF *shell_fn;
147 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
148 reset_internal_getopt ();
149 while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
151 flags = list_opttype == '+' ? &flags_off : &flags_on;
156 #if defined (ARRAY_VARS)
164 #if defined (ARRAY_VARS)
177 *flags |= att_function;
180 *flags |= att_function;
183 if (flags == &flags_on)
187 *flags |= att_integer;
190 *flags |= att_readonly;
196 *flags |= att_exported;
197 array_needs_making = 1;
199 #if defined (CASEMOD_ATTRS)
200 # if defined (CASEMOD_CAPCASE)
202 *flags |= att_capcase;
203 if (flags == &flags_on)
204 flags_off |= att_uppercase|att_lowercase;
208 *flags |= att_lowercase;
209 if (flags == &flags_on)
210 flags_off |= att_capcase|att_uppercase;
213 *flags |= att_uppercase;
214 if (flags == &flags_on)
215 flags_off |= att_capcase|att_lowercase;
217 #endif /* CASEMOD_ATTRS */
226 /* If there are no more arguments left, then we just want to show
228 if (list == 0) /* declare -[aAfFirtx] */
230 /* Show local variables defined at this context level if this is
231 the `local' builtin. */
234 register SHELL_VAR **vlist;
237 vlist = all_local_variables ();
241 for (i = 0; vlist[i]; i++)
242 print_assignment (vlist[i]);
247 else if (pflag && (flags_on == 0 || flags_on == att_function))
248 show_all_var_attributes (flags_on == 0, nodefs);
249 else if (flags_on == 0)
250 return (set_builtin ((WORD_LIST *)NULL));
252 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
254 return (sh_chkwrite (EXECUTION_SUCCESS));
257 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
259 for (any_failed = 0; list; list = list->next)
261 pflag = show_name_attributes (list->word->word, nodefs);
264 sh_notfound (list->word->word);
268 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
271 #define NEXT_VARIABLE() free (name); list = list->next; continue
273 /* There are arguments left, so we are making variables. */
274 while (list) /* declare [-aAfFirx] name [name ...] */
278 #if defined (ARRAY_VARS)
279 int making_array_special, compound_array_assign, simple_array_assign;
282 name = savestring (list->word->word);
283 offset = assignment (name, 0);
286 if (offset) /* declare [-aAfFirx] name=value */
289 value = name + offset + 1;
290 if (name[offset - 1] == '+')
292 aflags |= ASS_APPEND;
293 name[offset - 1] = '\0';
299 #if defined (ARRAY_VARS)
300 compound_array_assign = simple_array_assign = 0;
301 subscript_start = (char *)NULL;
302 if (t = strchr (name, '[')) /* ] */
304 /* If offset != 0 we have already validated any array reference */
305 if (offset == 0 && valid_array_reference (name) == 0)
313 making_array_special = 1;
316 making_array_special = 0;
319 /* If we're in posix mode or not looking for a shell function (since
320 shell function names don't have to be valid identifiers when the
321 shell's not in posix mode), check whether or not the argument is a
322 valid, well-formed shell identifier. */
323 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
330 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
331 inside of a function. This means we should make local variables,
334 /* XXX - this has consequences when we're making a local copy of a
335 variable that was in the temporary environment. Watch out
337 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
339 #if defined (ARRAY_VARS)
340 if (flags_on & att_assoc)
341 var = make_local_assoc_variable (name);
342 else if ((flags_on & att_array) || making_array_special)
343 var = make_local_array_variable (name);
346 var = make_local_variable (name);
354 var = (SHELL_VAR *)NULL;
356 /* If we are declaring a function, then complain about it in some way.
357 We don't let people make functions by saying `typeset -f foo=bar'. */
359 /* There should be a way, however, to let people look at a particular
360 function definition by saying `typeset -f foo'. */
362 if (flags_on & att_function)
364 if (offset) /* declare -f [-rix] foo=bar */
366 builtin_error (_("cannot use `-f' to make functions"));
368 return (EXECUTION_FAILURE);
370 else /* declare -f [-rx] name [name...] */
372 var = find_function (name);
376 if (readonly_p (var) && (flags_off & att_readonly))
378 builtin_error (_("%s: readonly function"), name);
383 /* declare -[Ff] name [name...] */
384 if (flags_on == att_function && flags_off == 0)
386 #if defined (DEBUGGER)
387 if (nodefs && debugging_mode)
389 shell_fn = find_function_def (var->name);
391 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
393 printf ("%s\n", var->name);
396 #endif /* DEBUGGER */
398 t = nodefs ? var->name
399 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
401 any_failed = sh_chkwrite (any_failed);
404 else /* declare -[fF] -[rx] name [name...] */
406 VSETATTR (var, flags_on);
407 VUNSETATTR (var, flags_off);
415 else /* declare -[aAirx] name [name...] */
417 /* Non-null if we just created or fetched a local variable. */
419 var = mkglobal ? find_global_variable (name) : find_variable (name);
423 #if defined (ARRAY_VARS)
424 if (flags_on & att_assoc)
425 var = make_new_assoc_variable (name);
426 else if ((flags_on & att_array) || making_array_special)
427 var = make_new_array_variable (name);
432 var = bind_variable (name, "", 0);
435 var = bind_variable (name, (char *)NULL, 0);
436 VSETATTR (var, att_invisible);
440 /* Cannot use declare +r to turn off readonly attribute. */
441 if (readonly_p (var) && (flags_off & att_readonly))
448 /* Cannot use declare to assign value to readonly or noassign
450 if ((readonly_p (var) || noassign_p (var)) && offset)
452 if (readonly_p (var))
458 #if defined (ARRAY_VARS)
459 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
462 vlen = STRLEN (value);
464 if (value[0] == '(' && value[vlen-1] == ')')
465 compound_array_assign = 1;
467 simple_array_assign = 1;
470 /* Cannot use declare +a name or declare +A name to remove an
472 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
474 builtin_error (_("%s: cannot destroy array variables in this way"), name);
479 if ((flags_on & att_array) && assoc_p (var))
481 builtin_error (_("%s: cannot convert associative to indexed array"), name);
485 if ((flags_on & att_assoc) && array_p (var))
487 builtin_error (_("%s: cannot convert indexed to associative array"), name);
492 /* declare -A name[[n]] makes name an associative array variable. */
493 if (flags_on & att_assoc)
495 if (assoc_p (var) == 0)
496 var = convert_var_to_assoc (var);
498 /* declare -a name[[n]] or declare name[n] makes name an indexed
500 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
501 var = convert_var_to_array (var);
502 #endif /* ARRAY_VARS */
504 VSETATTR (var, flags_on);
505 VUNSETATTR (var, flags_off);
507 #if defined (ARRAY_VARS)
508 if (offset && compound_array_assign)
509 assign_array_var_from_string (var, value, aflags);
510 else if (simple_array_assign && subscript_start)
512 /* declare [-aA] name[N]=value */
513 *subscript_start = '['; /* ] */
514 var = assign_array_element (name, value, 0); /* XXX - not aflags */
515 *subscript_start = '\0';
516 if (var == 0) /* some kind of assignment error */
522 else if (simple_array_assign)
524 /* let bind_{array,assoc}_variable take care of this. */
526 bind_assoc_variable (var, name, savestring ("0"), value, aflags);
528 bind_array_variable (name, 0, value, aflags);
532 /* bind_variable_value duplicates the essential internals of
535 bind_variable_value (var, value, aflags);
537 /* If we found this variable in the temporary environment, as with
538 `var=value declare -x var', make sure it is treated identically
539 to `var=value export var'. Do the same for `declare -r' and
540 `readonly'. Preserve the attributes, except for att_tempvar. */
541 /* XXX -- should this create a variable in the global scope, or
542 modify the local variable flags? ksh93 has it modify the
544 Need to handle case like in set_var_attribute where a temporary
545 variable is in the same table as the function local vars. */
546 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
551 tv = find_tempenv_variable (var->name);
554 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
555 tv = bind_variable (var->name, tvalue, 0);
556 tv->attributes |= var->attributes & ~att_tempvar;
558 VSETATTR (tv, att_propagate);
561 VSETATTR (var, att_propagate);
565 stupidly_hack_special_variables (name);
570 return (assign_error ? EX_BADASSIGN
571 : ((any_failed == 0) ? EXECUTION_SUCCESS
572 : EXECUTION_FAILURE));