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
, '[')) /* ] */
298 /* If offset
!= 0 we have already validated any array reference
*/
299 if (offset
== 0 && valid_array_reference (name
) == 0)
307 making_array_special
= 1;
310 making_array_special
= 0;
313 /* If we
're in posix mode or not looking for a shell function (since
314 shell function names don't have to be valid identifiers when the
315 shell
's not in posix mode), check whether or not the argument is a
316 valid, well-formed shell identifier. */
317 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
324 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
325 inside of a function. This means we should make local variables,
328 /* XXX - this has consequences when we're making a local copy of a
329 variable that was in the temporary environment. Watch out
331 if (variable_context
&& ((flags_on
& att_function
) == 0))
333 #if
defined (ARRAY_VARS
)
334 if (flags_on
& att_assoc
)
335 var
= make_local_assoc_variable (name
);
336 else
if ((flags_on
& att_array
) || making_array_special
)
337 var
= make_local_array_variable (name
);
340 var
= make_local_variable (name
);
348 var
= (SHELL_VAR *)NULL
;
350 /* If we are declaring a function
, then complain about it in some way.
351 We don
't let people make functions by saying `typeset -f foo=bar'.
*/
353 /* There should be a way
, however
, to let people look at a particular
354 function definition by saying `typeset
-f foo
'. */
356 if (flags_on & att_function)
358 if (offset) /* declare -f [-rix] foo=bar */
360 builtin_error (_("cannot use `-f' to make functions
"));
362 return (EXECUTION_FAILURE);
364 else /* declare -f [-rx] name [name...] */
366 var = find_function (name);
370 if (readonly_p (var) && (flags_off & att_readonly))
372 builtin_error (_("%s
: readonly function
"), name);
377 /* declare -[Ff] name [name...] */
378 if (flags_on == att_function && flags_off == 0)
380 #if defined (DEBUGGER)
381 if (nodefs && debugging_mode)
383 shell_fn = find_function_def (var->name);
385 printf ("%s
%d
%s
\n", var->name, shell_fn->line, shell_fn->source_file);
387 printf ("%s
\n", var->name);
390 #endif /* DEBUGGER */
392 t = nodefs ? var->name
393 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
395 any_failed = sh_chkwrite (any_failed);
398 else /* declare -[fF] -[rx] name [name...] */
400 VSETATTR (var, flags_on);
401 VUNSETATTR (var, flags_off);
409 else /* declare -[aAirx] name [name...] */
411 /* Non-null if we just created or fetched a local variable. */
413 var = find_variable (name);
417 #if defined (ARRAY_VARS)
418 if (flags_on & att_assoc)
419 var = make_new_assoc_variable (name);
420 else if ((flags_on & att_array) || making_array_special)
421 var = make_new_array_variable (name);
426 var = bind_variable (name, "", 0);
429 var = bind_variable (name, (char *)NULL, 0);
430 VSETATTR (var, att_invisible);
434 /* Cannot use declare +r to turn off readonly attribute. */
435 if (readonly_p (var) && (flags_off & att_readonly))
442 /* Cannot use declare to assign value to readonly or noassign
444 if ((readonly_p (var) || noassign_p (var)) && offset)
446 if (readonly_p (var))
452 #if defined (ARRAY_VARS)
453 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
456 vlen = STRLEN (value);
458 if (value[0] == '(' && value[vlen-1] == ')')
459 compound_array_assign = 1;
461 simple_array_assign = 1;
464 /* Cannot use declare +a name or declare +A name to remove an
466 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
468 builtin_error (_("%s
: cannot destroy array variables in this way
"), name);
473 if ((flags_on & att_array) && assoc_p (var))
475 builtin_error (_("%s
: cannot convert associative to indexed array
"), name);
479 if ((flags_on & att_assoc) && array_p (var))
481 builtin_error (_("%s
: cannot convert indexed to associative array
"), name);
486 /* declare -A name[[n]] makes name an associative array variable. */
487 if (flags_on & att_assoc)
489 if (assoc_p (var) == 0)
490 var = convert_var_to_assoc (var);
492 /* declare -a name[[n]] or declare name[n] makes name an indexed
494 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
495 var = convert_var_to_array (var);
496 #endif /* ARRAY_VARS */
498 VSETATTR (var, flags_on);
499 VUNSETATTR (var, flags_off);
501 #if defined (ARRAY_VARS)
502 if (offset && compound_array_assign)
503 assign_array_var_from_string (var, value, aflags);
504 else if (simple_array_assign && subscript_start)
506 /* declare [-a] name[N]=value */
507 *subscript_start = '['; /* ] */
508 var = assign_array_element (name, value, 0); /* XXX - not aflags */
509 *subscript_start = '\0';
511 else if (simple_array_assign)
512 /* let bind_array_variable take care of this. */
513 bind_array_variable (name, 0, value, aflags);
516 /* bind_variable_value duplicates the essential internals of
519 bind_variable_value (var, value, aflags);
521 /* If we found this variable in the temporary environment, as with
522 `var=value declare -x var', make sure it is treated identically
523 to `var=value export var'. Do the same for `declare -r' and
524 `readonly'. Preserve the attributes, except for att_tempvar. */
525 /* XXX -- should this create a variable in the global scope, or
526 modify the local variable flags? ksh93 has it modify the
528 Need to handle case like in set_var_attribute where a temporary
529 variable is in the same table as the function local vars. */
530 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
535 tv = find_tempenv_variable (var->name);
538 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
539 tv = bind_variable (var->name, tvalue, 0);
540 tv->attributes |= var->attributes & ~att_tempvar;
542 VSETATTR (tv, att_propagate);
545 VSETATTR (var, att_propagate);
549 stupidly_hack_special_variables (name);
554 return (assign_error ? EX_BADASSIGN
555 : ((any_failed == 0) ? EXECUTION_SUCCESS
556 : EXECUTION_FAILURE));