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-2016 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 [-aAfFgilnrtux] [-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 the value of each NAME to lower case on assignment
44 -n make NAME a reference to the variable named by its value
45 -r to make NAMEs readonly
46 -t to make NAMEs have the `trace' attribute
47 -u to convert the value of each NAME to upper case on assignment
48 -x to make NAMEs export
50 Using `+' instead of `-' turns off the given attribute.
52 Variables with the integer attribute have arithmetic evaluation (see
53 the `let' command) performed when the variable is assigned a value.
55 When used in a function, `declare' makes NAMEs local, as with the `local'
56 command. The `-g' option suppresses this behavior.
59 Returns success unless an invalid option is supplied or a variable
60 assignment error occurs.
64 $FUNCTION declare_builtin
65 $SHORT_DOC typeset [-aAfFgilnrtux] [-p] name[=value] ...
66 Set variable values and attributes.
68 A synonym for `declare'. See `help declare'.
73 #if defined (HAVE_UNISTD_H)
75 # include <sys/types.h>
82 #include "../bashansi.h"
83 #include "../bashintl.h"
89 #include "bashgetopt.h"
91 static SHELL_VAR *declare_find_variable __P((const char *, int, int));
92 static int declare_internal __P((register WORD_LIST *, int));
94 /* Declare or change variable attributes. */
96 declare_builtin (list)
97 register WORD_LIST *list;
99 return (declare_internal (list, 0));
103 $FUNCTION local_builtin
104 $SHORT_DOC local [option] name[=value] ...
105 Define local variables.
107 Create a local variable called NAME, and give it VALUE. OPTION can
108 be any option accepted by `declare'.
110 Local variables can only be used within a function; they are visible
111 only to the function where they are defined and its children.
114 Returns success unless an invalid option is supplied, a variable
115 assignment error occurs, or the shell is not executing a function.
119 register WORD_LIST *list;
121 /* Catch a straight `local --help' before checking function context */
122 if (list && list->word && STREQ (list->word->word, "--help"))
128 if (variable_context)
129 return (declare_internal (list, 1));
132 builtin_error (_("can only be used in a function"));
133 return (EXECUTION_FAILURE);
137 #if defined (ARRAY_VARS)
138 # define DECLARE_OPTS "+acfgilnprtuxAFG"
140 # define DECLARE_OPTS "+cfgilnprtuxFG"
144 declare_find_variable (name, mkglobal, chklocal)
146 int mkglobal, chklocal;
151 return (find_variable (name));
154 var = find_variable (name);
155 if (var && local_p (var) && var->context == variable_context)
157 return (find_global_variable (name));
160 return (find_global_variable (name));
163 /* The workhorse function. */
165 declare_internal (list, local_var)
166 register WORD_LIST *list;
169 int flags_on, flags_off, *flags;
170 int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
171 int mkglobal, chklocal;
172 char *t, *subscript_start;
173 SHELL_VAR *var, *refvar, *v;
174 FUNCTION_DEF *shell_fn;
176 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
177 mkglobal = chklocal = 0;
178 refvar = (SHELL_VAR *)NULL;
179 reset_internal_getopt ();
180 while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1)
182 flags = list_opttype == '+' ? &flags_off : &flags_on;
184 /* If you add options here, see whether or not they need to be added to
185 the loop in subst.c:shell_expand_word_list() */
189 #if defined (ARRAY_VARS)
197 #if defined (ARRAY_VARS)
210 *flags |= att_function;
213 *flags |= att_function;
216 if (flags == &flags_on)
220 if (flags == &flags_on)
224 *flags |= att_integer;
227 *flags |= att_nameref;
230 *flags |= att_readonly;
236 *flags |= att_exported;
237 array_needs_making = 1;
239 #if defined (CASEMOD_ATTRS)
240 # if defined (CASEMOD_CAPCASE)
242 *flags |= att_capcase;
243 if (flags == &flags_on)
244 flags_off |= att_uppercase|att_lowercase;
248 *flags |= att_lowercase;
249 if (flags == &flags_on)
250 flags_off |= att_capcase|att_uppercase;
253 *flags |= att_uppercase;
254 if (flags == &flags_on)
255 flags_off |= att_capcase|att_lowercase;
257 #endif /* CASEMOD_ATTRS */
267 /* If there are no more arguments left, then we just want to show
269 if (list == 0) /* declare -[aAfFirtx] */
271 /* Show local variables defined at this context level if this is
272 the `local' builtin. */
275 register SHELL_VAR **vlist;
278 vlist = all_local_variables ();
282 for (i = 0; vlist[i]; i++)
283 print_assignment (vlist[i]);
288 else if (pflag && (flags_on == 0 || flags_on == att_function))
289 show_all_var_attributes (flags_on == 0, nodefs);
290 else if (flags_on == 0)
291 return (set_builtin ((WORD_LIST *)NULL));
293 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
295 return (sh_chkwrite (EXECUTION_SUCCESS));
298 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
300 for (any_failed = 0; list; list = list->next)
302 if (flags_on & att_function)
303 pflag = show_func_attributes (list->word->word, nodefs);
305 pflag = show_name_attributes (list->word->word, nodefs);
308 sh_notfound (list->word->word);
312 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
315 #define NEXT_VARIABLE() free (name); list = list->next; continue
317 /* There are arguments left, so we are making variables. */
318 while (list) /* declare [-aAfFirx] name [name ...] */
320 char *value, *name, *oldname;
321 int offset, aflags, wflags, created_var, namelen;
323 #if defined (ARRAY_VARS)
324 int making_array_special, compound_array_assign, simple_array_assign;
325 int var_exists, array_exists, creating_array, array_subscript_assignment;
328 name = savestring (list->word->word);
329 wflags = list->word->flags;
330 #if defined (ARRAY_VARS)
331 assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
335 offset = assignment (name, assoc_noexpand ? 2 : 0);
339 if (local_var && variable_context && STREQ (name, "-"))
341 var = make_local_variable ("-", 0);
342 FREE (value_cell (var)); /* just in case */
343 value = get_current_options ();
344 var_setvalue (var, value);
345 VSETATTR (var, att_invisible);
349 if (offset) /* declare [-aAfFirx] name=value */
352 value = name + offset + 1;
353 if (name[offset - 1] == '+')
355 aflags |= ASS_APPEND;
356 name[offset - 1] = '\0';
362 /* Do some lexical error checking on the LHS and RHS of the assignment
363 that is specific to nameref variables. */
364 if (flags_on & att_nameref)
366 #if defined (ARRAY_VARS)
367 if (valid_array_reference (name, 0))
369 builtin_error (_("%s: reference variable cannot be an array"), name);
375 /* disallow self references at global scope, warn at function scope */
376 if (check_selfref (name, value, 0))
378 if (variable_context == 0)
380 builtin_error (_("%s: nameref variable self references not allowed"), name);
385 builtin_warning (_("%s: circular name reference"), name);
388 if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 1) == 0)
390 builtin_error (_("`%s': invalid variable name for name reference"), value);
397 restart_new_var_name:
398 #if defined (ARRAY_VARS)
399 var_exists = array_exists = creating_array = 0;
400 compound_array_assign = simple_array_assign = 0;
401 array_subscript_assignment = 0;
402 subscript_start = (char *)NULL;
403 if ((t = strchr (name, '[')) && (flags_on & att_function) == 0) /* ] */
405 /* If offset != 0 we have already validated any array reference
406 because assignment() calls skipsubscript() */
407 if (offset == 0 && valid_array_reference (name, 0) == 0)
415 making_array_special = 1; /* XXX - should this check offset? */
416 array_subscript_assignment = offset != 0;
419 making_array_special = 0;
422 /* If we're in posix mode or not looking for a shell function (since
423 shell function names don't have to be valid identifiers when the
424 shell's not in posix mode), check whether or not the argument is a
425 valid, well-formed shell identifier. */
426 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
433 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
434 inside of a function. This means we should make local variables,
437 /* XXX - this has consequences when we're making a local copy of a
438 variable that was in the temporary environment. Watch out
440 refvar = (SHELL_VAR *)NULL;
441 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
445 /* check name for validity here? */
446 var = find_variable (name);
448 newname = nameref_transform_name (name, ASS_MKLOCAL);
449 else if ((flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0)
451 /* Ok, we're following namerefs here, so let's make sure that if
452 we followed one, it was at the same context (see below for
454 refvar = find_variable_last_nameref (name, 1);
455 newname = (refvar && refvar->context != variable_context) ? name : var->name;
456 refvar = (SHELL_VAR *)NULL;
459 newname = name; /* dealing with nameref attribute */
461 #if defined (ARRAY_VARS)
462 /* Pass 1 as second argument to make_local_{assoc,array}_variable
463 return an existing {array,assoc} variable to be flagged as an
465 if (flags_on & att_assoc)
466 var = make_local_assoc_variable (newname, 1);
467 else if ((flags_on & att_array) || making_array_special)
468 var = make_local_array_variable (newname, 1);
471 if (offset == 0 && (flags_on & att_nameref))
473 /* First look for refvar at current scope */
474 refvar = find_variable_last_nameref (name, 1);
475 /* VARIABLE_CONTEXT != 0, so we are attempting to create or modify
476 the attributes for a local variable at the same scope. If we've
477 used a reference from a previous context to resolve VAR, we
478 want to throw REFVAR and VAR away and create a new local var. */
479 if (refvar && refvar->context != variable_context)
482 var = make_local_variable (name, 0);
484 else if (refvar && refvar->context == variable_context)
486 /* Maybe we just want to create a new local variable */
487 else if (var == 0 || var->context != variable_context)
488 var = make_local_variable (name, 0);
489 /* otherwise we have a var at the right context */
492 /* XXX - check name for validity here with valid_nameref_value */
493 var = make_local_variable ((flags_on & att_nameref) ? name : newname, 0); /* sets att_invisible for new vars */
500 if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
508 var = (SHELL_VAR *)NULL;
510 /* If we are declaring a function, then complain about it in some way.
511 We don't let people make functions by saying `typeset -f foo=bar'. */
513 /* There should be a way, however, to let people look at a particular
514 function definition by saying `typeset -f foo'. */
516 if (flags_on & att_function)
518 if (offset) /* declare -f [-rix] foo=bar */
520 builtin_error (_("cannot use `-f' to make functions"));
522 return (EXECUTION_FAILURE);
524 else /* declare -f [-rx] name [name...] */
526 var = find_function (name);
530 if (readonly_p (var) && (flags_off & att_readonly))
532 builtin_error (_("%s: readonly function"), name);
537 /* declare -[Ff] name [name...] */
538 if (flags_on == att_function && flags_off == 0)
540 #if defined (DEBUGGER)
541 if (nodefs && debugging_mode)
543 shell_fn = find_function_def (var->name);
545 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
547 printf ("%s\n", var->name);
550 #endif /* DEBUGGER */
552 t = nodefs ? var->name
553 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
555 any_failed = sh_chkwrite (any_failed);
558 else /* declare -[fF] -[rx] name [name...] */
560 VSETATTR (var, flags_on);
561 VUNSETATTR (var, flags_off);
569 else /* declare -[aAinrx] name [name...] */
571 /* Non-null if we just created or fetched a local variable. */
573 /* This is bash-4.3 code. */
574 /* Here's what ksh93 seems to do. If we are modifying an existing
575 nameref variable, we don't follow the nameref chain past the last
576 nameref, and we set the nameref variable's value so future
577 references to that variable will return the value of the variable
578 we're assigning right now. */
580 /* Here's what ksh93 seems to do as of the 2012 version: if we are
581 using declare -n to modify the value of an existing nameref
582 variable, don't follow the nameref chain at all and just search
583 for a nameref at the current context. If we have a nameref,
584 modify its value (changing which variable it references). */
586 if (var == 0 && (flags_on & att_nameref))
588 /* See if we are trying to modify an existing nameref variable,
589 but don't follow the nameref chain. */
590 var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
591 if (var && nameref_p (var) == 0)
594 /* However, if we're turning off the nameref attribute on an existing
595 nameref variable, we first follow the nameref chain to the end,
596 modify the value of the variable this nameref variable references
597 if there is an assignment statement argument,
598 *CHANGING ITS VALUE AS A SIDE EFFECT*, then turn off the nameref
599 flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
600 else if (var == 0 && (flags_off & att_nameref))
602 /* See if we are trying to modify an existing nameref variable */
603 refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
604 if (refvar && nameref_p (refvar) == 0)
606 /* If the nameref is readonly but doesn't have a value, ksh93
607 allows the nameref attribute to be removed. If it's readonly
608 and has a value, even if the value doesn't reference an
609 existing variable, we disallow the modification */
610 if (refvar && nameref_cell (refvar) && readonly_p (refvar))
617 /* If all we're doing is turning off the nameref attribute, don't
618 bother with VAR at all, whether it exists or not. Just turn it
620 if (refvar && flags_on == 0 && offset == 0 && (flags_off & ~att_nameref) == 0)
622 VUNSETATTR (refvar, att_nameref);
627 /* XXX - use declare_find_variable here? */
628 var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
630 #if defined (ARRAY_VARS)
631 /* If we have an array assignment to a nameref, remove the nameref
632 attribute and go on. */
633 else if (var == 0 && offset && array_subscript_assignment)
635 var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
636 if (var && nameref_p (var))
638 internal_warning (_("%s: removing nameref attribute"), name);
639 FREE (value_cell (var)); /* XXX - bash-4.3 compat */
640 var_setvalue (var, (char *)NULL);
641 VUNSETATTR (var, att_nameref);
646 /* See if we are trying to set flags or value (or create) for an
647 existing nameref that points to a non-existent variable: e.g.,
649 unset foo # unsets bar
653 if (var == 0 && (mkglobal || flags_on || flags_off || offset))
655 refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
656 if (refvar && nameref_p (refvar) == 0)
659 /* XXX - use declare_find_variable here? */
660 var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
661 if (refvar && var == 0)
663 oldname = name; /* need to free this */
665 namelen = strlen (nameref_cell (refvar));
666 #if defined (ARRAY_VARS)
669 *subscript_start = '['; /*]*/
670 namelen += strlen (subscript_start);
673 name = xmalloc (namelen + 2 + strlen (value) + 1);
674 strcpy (name, nameref_cell (refvar));
675 #if defined (ARRAY_VARS)
677 strcpy (name + strlen (nameref_cell (refvar)), subscript_start);
679 /* We are committed to using the new name, so reset */
682 /* Rebuild assignment and restore offset and value */
683 if (aflags & ASS_APPEND)
684 name[namelen++] = '+';
685 name[namelen++] = '=';
687 strcpy (name + namelen, value);
689 name[namelen] = '\0';
690 offset = assignment (name, 0);
691 /* if offset was valid previously, but the substituting
692 of the nameref value results in an invalid assignment,
693 throw an invalid identifier error */
702 value = name + namelen;
706 /* OK, let's turn off the nameref attribute.
707 Now everything else applies to VAR. */
708 if (flags_off & att_nameref)
709 VUNSETATTR (refvar, att_nameref);
711 goto restart_new_var_name;
716 var = declare_find_variable (name, mkglobal, chklocal);
718 #if defined (ARRAY_VARS)
719 var_exists = var != 0;
720 array_exists = var && (array_p (var) || assoc_p (var));
721 creating_array = flags_on & (att_array|att_assoc);
726 #if defined (ARRAY_VARS)
727 if (flags_on & att_assoc)
729 var = make_new_assoc_variable (name);
730 if (var && offset == 0 && no_invisible_vars == 0)
731 VSETATTR (var, att_invisible);
733 else if ((flags_on & att_array) || making_array_special)
735 var = make_new_array_variable (name);
736 if (var && offset == 0 && no_invisible_vars == 0)
737 VSETATTR (var, att_invisible);
742 var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
743 if (var && offset == 0 && no_invisible_vars == 0)
744 VSETATTR (var, att_invisible);
748 /* Has to appear in brackets */
753 /* Can't take an existing array variable and make it a nameref */
754 else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
756 builtin_error (_("%s: reference variable cannot be an array"), name);
760 else if (nameref_p (var) && (flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0 && offset && valid_nameref_value (value, 1) == 0)
762 builtin_error (_("`%s': invalid variable name for name reference"), value);
766 else if (flags_on & att_nameref)
769 /* Check of offset is to allow an assignment to a nameref var as
770 part of the declare word to override existing value */
771 if (nameref_p (var) == 0 && var_isset (var) && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0)
773 builtin_error (_("`%s': invalid variable name for name reference"), value_cell (var));
778 if (readonly_p (var))
784 /* ksh93 compat: turning on nameref attribute turns off -ilu */
785 VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
788 /* Cannot use declare +r to turn off readonly attribute. */
789 if (readonly_p (var) && (flags_off & att_readonly))
791 sh_readonly (name_cell (var));
796 /* Cannot use declare to assign value to readonly or noassign
798 if ((readonly_p (var) || noassign_p (var)) && offset)
800 if (readonly_p (var))
806 #if defined (ARRAY_VARS)
807 /* make declare a[2]=foo as similar to a[2]=foo as possible if
808 a is already an array or assoc variable. */
809 if (array_subscript_assignment && array_exists && creating_array == 0)
810 simple_array_assign = 1;
811 else if ((making_array_special || creating_array || array_exists) && offset)
814 vlen = STRLEN (value);
815 /*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/
816 if (shell_compatibility_level > 43 && (wflags & W_COMPASSIGN) == 0 &&
817 value[0] == '(' && value[vlen-1] == ')')
819 /* The warning is only printed when using compound assignment
820 to an array variable that doesn't already exist. We use
821 creating_array to allow things like
822 declare -a foo$bar='(abc)' to work. */
823 if (array_exists == 0 && creating_array == 0)
824 internal_warning (_("%s: quoted compound array assignment deprecated"), list->word->word);
825 compound_array_assign = array_exists || creating_array;
826 simple_array_assign = making_array_special;
828 else if (value[0] == '(' && value[vlen-1] == ')' && (shell_compatibility_level < 44 || (wflags & W_COMPASSIGN)))
829 compound_array_assign = 1;
831 simple_array_assign = 1;
834 /* Cannot use declare +a name or declare +A name to remove an
836 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
838 builtin_error (_("%s: cannot destroy array variables in this way"), name);
843 if ((flags_on & att_array) && assoc_p (var))
845 builtin_error (_("%s: cannot convert associative to indexed array"), name);
849 if ((flags_on & att_assoc) && array_p (var))
851 builtin_error (_("%s: cannot convert indexed to associative array"), name);
856 /* declare -A name[[n]] makes name an associative array variable. */
857 if (flags_on & att_assoc)
859 if (assoc_p (var) == 0)
860 var = convert_var_to_assoc (var);
862 /* declare -a name[[n]] or declare name[n] makes name an indexed
864 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
865 var = convert_var_to_array (var);
866 #endif /* ARRAY_VARS */
868 /* XXX - we note that we are turning on nameref attribute and defer
869 setting it until the assignment has been made so we don't do an
870 inadvertent nameref lookup. Might have to do the same thing for
871 flags_off&att_nameref. */
872 /* XXX - ksh93 makes it an error to set a readonly nameref variable
873 using a single typeset command. */
874 onref = (flags_on & att_nameref);
875 flags_on &= ~att_nameref;
876 #if defined (ARRAY_VARS)
877 if (array_p (var) || assoc_p (var)
878 || (offset && compound_array_assign)
879 || simple_array_assign)
880 onref = 0; /* array variables may not be namerefs */
883 /* ksh93 seems to do this */
884 offref = (flags_off & att_nameref);
885 flags_off &= ~att_nameref;
887 VSETATTR (var, flags_on);
888 VUNSETATTR (var, flags_off);
890 #if defined (ARRAY_VARS)
891 if (offset && compound_array_assign)
892 assign_array_var_from_string (var, value, aflags|ASS_FORCE);
893 else if (simple_array_assign && subscript_start)
896 /* declare [-aA] name[N]=value */
897 *subscript_start = '['; /* ] */
898 /* XXX - problem here with appending */
899 local_aflags = aflags&ASS_APPEND;
900 local_aflags |= assoc_noexpand ? ASS_NOEXPAND : 0;
901 var = assign_array_element (name, value, local_aflags); /* XXX - not aflags */
902 *subscript_start = '\0';
903 if (var == 0) /* some kind of assignment error */
911 else if (simple_array_assign)
913 /* let bind_{array,assoc}_variable take care of this. */
915 bind_assoc_variable (var, name, savestring ("0"), value, aflags|ASS_FORCE);
917 bind_array_variable (name, 0, value, aflags|ASS_FORCE);
921 /* XXX - no ASS_FORCE here */
922 /* bind_variable_value duplicates the essential internals of
926 if (onref || nameref_p (var))
927 aflags |= ASS_NAMEREF;
928 v = bind_variable_value (var, value, aflags);
929 if (v == 0 && (onref || nameref_p (var)))
931 if (valid_nameref_value (value, 1) == 0)
932 sh_invalidid (value);
934 /* XXX - unset this variable? or leave it as normal var? */
936 delete_var (var->name, mkglobal ? global_variables : shell_variables);
937 flags_on |= onref; /* undo change from above */
943 /* If we found this variable in the temporary environment, as with
944 `var=value declare -x var', make sure it is treated identically
945 to `var=value export var'. Do the same for `declare -r' and
946 `readonly'. Preserve the attributes, except for att_tempvar. */
947 /* XXX -- should this create a variable in the global scope, or
948 modify the local variable flags? ksh93 has it modify the
950 Need to handle case like in set_var_attribute where a temporary
951 variable is in the same table as the function local vars. */
952 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
957 tv = find_tempenv_variable (var->name);
960 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
961 tv = bind_variable (var->name, tvalue, 0);
964 tv->attributes |= var->attributes & ~att_tempvar;
966 VSETATTR (tv, att_propagate);
970 VSETATTR (var, att_propagate);
974 /* Turn on nameref attribute we deferred above. */
975 /* XXX - should we turn on the noassign attribute for consistency with
976 ksh93 when we turn on the nameref attribute? */
977 VSETATTR (var, onref);
979 VUNSETATTR (var, offref);
981 /* Yuck. ksh93 compatibility. XXX - need to investigate more but
982 definitely happens when turning off nameref attribute on nameref
983 (see comments above). Under no circumstances allow this to turn
984 off readonly attribute on readonly nameref variable. */
987 if (flags_off & att_readonly)
988 flags_off &= ~att_readonly;
989 VUNSETATTR (refvar, flags_off);
992 stupidly_hack_special_variables (name);
997 return (assign_error ? EX_BADASSIGN
998 : ((any_failed == 0) ? EXECUTION_SUCCESS
999 : EXECUTION_FAILURE));