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-2009 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 [-aAfFilrtux] [-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 -p display the attributes and value of each NAME
37 Options which set attributes:
38 -a to make NAMEs indexed arrays (if supported)
39 -A to make NAMEs associative arrays (if supported)
40 -i to make NAMEs have the `integer' attribute
41 -l to convert NAMEs to lower case on assignment
42 -r to make NAMEs readonly
43 -t to make NAMEs have the `trace' attribute
44 -u to convert NAMEs to upper case on assignment
45 -x to make NAMEs export
47 Using `+' instead of `-' turns off the given attribute.
49 Variables with the integer attribute have arithmetic evaluation (see
50 the `let' command) performed when the variable is assigned a value.
52 When used in a function, `declare' makes NAMEs local, as with the `local'
56 Returns success unless an invalid option is supplied or an error occurs.
60 $FUNCTION declare_builtin
61 $SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ...
62 Set variable values and attributes.
64 Obsolete. See `help declare'.
69 #if defined (HAVE_UNISTD_H)
71 # include <sys/types.h>
78 #include "../bashansi.h"
79 #include "../bashintl.h"
84 #include "bashgetopt.h"
86 extern int array_needs_making;
87 extern int posixly_correct;
89 static int declare_internal __P((register WORD_LIST *, int));
91 /* Declare or change variable attributes. */
93 declare_builtin (list)
94 register WORD_LIST *list;
96 return (declare_internal (list, 0));
100 $FUNCTION local_builtin
101 $SHORT_DOC local [option] name[=value] ...
102 Define local variables.
104 Create a local variable called NAME, and give it VALUE. OPTION can
105 be any option accepted by `declare'.
107 Local variables can only be used within a function; they are visible
108 only to the function where they are defined and its children.
111 Returns success unless an invalid option is supplied, an error occurs,
112 or the shell is not executing a function.
116 register WORD_LIST *list;
118 if (variable_context)
119 return (declare_internal (list, 1));
122 builtin_error (_("can only be used in a function"));
123 return (EXECUTION_FAILURE);
127 #if defined (ARRAY_VARS)
128 # define DECLARE_OPTS "+acfilprtuxAF"
130 # define DECLARE_OPTS "+cfilprtuxF"
133 /* The workhorse function. */
135 declare_internal (list, local_var)
136 register WORD_LIST *list;
139 int flags_on, flags_off, *flags;
140 int any_failed, assign_error, pflag, nodefs, opt;
141 char *t, *subscript_start;
143 FUNCTION_DEF *shell_fn;
145 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
146 reset_internal_getopt ();
147 while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
149 flags = list_opttype == '+' ? &flags_off : &flags_on;
154 #if defined (ARRAY_VARS)
162 #if defined (ARRAY_VARS)
175 *flags |= att_function;
178 *flags |= att_function;
181 *flags |= att_integer;
184 *flags |= att_readonly;
190 *flags |= att_exported;
191 array_needs_making = 1;
193 #if defined (CASEMOD_ATTRS)
194 # if defined (CASEMOD_CAPCASE)
196 *flags |= att_capcase;
197 if (flags == &flags_on)
198 flags_off |= att_uppercase|att_lowercase;
202 *flags |= att_lowercase;
203 if (flags == &flags_on)
204 flags_off |= att_capcase|att_uppercase;
207 *flags |= att_uppercase;
208 if (flags == &flags_on)
209 flags_off |= att_capcase|att_lowercase;
211 #endif /* CASEMOD_ATTRS */
220 /* If there are no more arguments left, then we just want to show
222 if (list == 0) /* declare -[aAfFirtx] */
224 /* Show local variables defined at this context level if this is
225 the `local' builtin. */
228 register SHELL_VAR **vlist;
231 vlist = all_local_variables ();
235 for (i = 0; vlist[i]; i++)
236 print_assignment (vlist[i]);
241 else if (pflag && (flags_on == 0 || flags_on == att_function))
242 show_all_var_attributes (flags_on == 0, nodefs);
243 else if (flags_on == 0)
244 return (set_builtin ((WORD_LIST *)NULL));
246 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
248 return (sh_chkwrite (EXECUTION_SUCCESS));
251 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
253 for (any_failed = 0; list; list = list->next)
255 pflag = show_name_attributes (list->word->word, nodefs);
258 sh_notfound (list->word->word);
262 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
265 #define NEXT_VARIABLE() free (name); list = list->next; continue
267 /* There are arguments left, so we are making variables. */
268 while (list) /* declare [-aAfFirx] name [name ...] */
272 #if defined (ARRAY_VARS)
273 int making_array_special, compound_array_assign, simple_array_assign;
276 name = savestring (list->word->word);
277 offset = assignment (name, 0);
280 if (offset) /* declare [-aAfFirx] name=value */
283 value = name + offset + 1;
284 if (name[offset - 1] == '+')
286 aflags |= ASS_APPEND;
287 name[offset - 1] = '\0';
293 #if defined (ARRAY_VARS)
294 compound_array_assign = simple_array_assign = 0;
295 subscript_start = (char *)NULL;
296 if (t = strchr (name, '[')) /* ] */
300 making_array_special = 1;
303 making_array_special = 0;
306 /* If we're in posix mode or not looking for a shell function (since
307 shell function names don't have to be valid identifiers when the
308 shell's not in posix mode), check whether or not the argument is a
309 valid, well-formed shell identifier. */
310 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
317 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
318 inside of a function. This means we should make local variables,
321 /* XXX - this has consequences when we're making a local copy of a
322 variable that was in the temporary environment. Watch out
324 if (variable_context && ((flags_on & att_function) == 0))
326 #if defined (ARRAY_VARS)
327 if (flags_on & att_assoc)
328 var = make_local_assoc_variable (name);
329 else if ((flags_on & att_array) || making_array_special)
330 var = make_local_array_variable (name);
333 var = make_local_variable (name);
341 var = (SHELL_VAR *)NULL;
343 /* If we are declaring a function, then complain about it in some way.
344 We don't let people make functions by saying `typeset -f foo=bar'. */
346 /* There should be a way, however, to let people look at a particular
347 function definition by saying `typeset -f foo'. */
349 if (flags_on & att_function)
351 if (offset) /* declare -f [-rix] foo=bar */
353 builtin_error (_("cannot use `-f' to make functions"));
355 return (EXECUTION_FAILURE);
357 else /* declare -f [-rx] name [name...] */
359 var = find_function (name);
363 if (readonly_p (var) && (flags_off & att_readonly))
365 builtin_error (_("%s: readonly function"), name);
370 /* declare -[Ff] name [name...] */
371 if (flags_on == att_function && flags_off == 0)
373 #if defined (DEBUGGER)
374 if (nodefs && debugging_mode)
376 shell_fn = find_function_def (var->name);
378 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
380 printf ("%s\n", var->name);
383 #endif /* DEBUGGER */
385 t = nodefs ? var->name
386 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
388 any_failed = sh_chkwrite (any_failed);
391 else /* declare -[fF] -[rx] name [name...] */
393 VSETATTR (var, flags_on);
394 VUNSETATTR (var, flags_off);
402 else /* declare -[aAirx] name [name...] */
404 /* Non-null if we just created or fetched a local variable. */
406 var = find_variable (name);
410 #if defined (ARRAY_VARS)
411 if (flags_on & att_assoc)
412 var = make_new_assoc_variable (name);
413 else if ((flags_on & att_array) || making_array_special)
414 var = make_new_array_variable (name);
419 var = bind_variable (name, "", 0);
422 var = bind_variable (name, (char *)NULL, 0);
423 VSETATTR (var, att_invisible);
427 /* Cannot use declare +r to turn off readonly attribute. */
428 if (readonly_p (var) && (flags_off & att_readonly))
435 /* Cannot use declare to assign value to readonly or noassign
437 if ((readonly_p (var) || noassign_p (var)) && offset)
439 if (readonly_p (var))
445 #if defined (ARRAY_VARS)
446 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
449 vlen = STRLEN (value);
451 if (value[0] == '(' && value[vlen-1] == ')')
452 compound_array_assign = 1;
454 simple_array_assign = 1;
457 /* Cannot use declare +a name or declare +A name to remove an
459 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
461 builtin_error (_("%s: cannot destroy array variables in this way"), name);
466 if ((flags_on & att_array) && assoc_p (var))
468 builtin_error (_("%s: cannot convert associative to indexed array"), name);
472 if ((flags_on & att_assoc) && array_p (var))
474 builtin_error (_("%s: cannot convert indexed to associative array"), name);
479 /* declare -A name[[n]] makes name an associative array variable. */
480 if (flags_on & att_assoc)
482 if (assoc_p (var) == 0)
483 var = convert_var_to_assoc (var);
485 /* declare -a name[[n]] or declare name[n] makes name an indexed
487 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
488 var = convert_var_to_array (var);
489 #endif /* ARRAY_VARS */
491 VSETATTR (var, flags_on);
492 VUNSETATTR (var, flags_off);
494 #if defined (ARRAY_VARS)
495 if (offset && compound_array_assign)
496 assign_array_var_from_string (var, value, aflags);
497 else if (simple_array_assign && subscript_start)
499 /* declare [-a] name[N]=value */
500 *subscript_start = '['; /* ] */
501 var = assign_array_element (name, value, 0); /* XXX - not aflags */
502 *subscript_start = '\0';
504 else if (simple_array_assign)
505 /* let bind_array_variable take care of this. */
506 bind_array_variable (name, 0, value, aflags);
509 /* bind_variable_value duplicates the essential internals of
512 bind_variable_value (var, value, aflags);
514 /* If we found this variable in the temporary environment, as with
515 `var=value declare -x var', make sure it is treated identically
516 to `var=value export var'. Do the same for `declare -r' and
517 `readonly'. Preserve the attributes, except for att_tempvar. */
518 /* XXX -- should this create a variable in the global scope, or
519 modify the local variable flags? ksh93 has it modify the
521 Need to handle case like in set_var_attribute where a temporary
522 variable is in the same table as the function local vars. */
523 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
528 tv = find_tempenv_variable (var->name);
531 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
532 tv = bind_variable (var->name, tvalue, 0);
533 tv->attributes |= var->attributes & ~att_tempvar;
535 VSETATTR (tv, att_propagate);
538 VSETATTR (var, att_propagate);
542 stupidly_hack_special_variables (name);
547 return (assign_error ? EX_BADASSIGN
548 : ((any_failed == 0) ? EXECUTION_SUCCESS
549 : EXECUTION_FAILURE));