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-2020 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 [-aAfFgiIlnrtux] [-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 -I if creating a local variable, inherit the attributes and value
38 of a variable with the same name at a previous scope
39 -p display the attributes and value of each NAME
41 Options which set attributes:
42 -a to make NAMEs indexed arrays (if supported)
43 -A to make NAMEs associative arrays (if supported)
44 -i to make NAMEs have the `integer' attribute
45 -l to convert the value of each NAME to lower case on assignment
46 -n make NAME a reference to the variable named by its value
47 -r to make NAMEs readonly
48 -t to make NAMEs have the `trace' attribute
49 -u to convert the value of each NAME to upper case on assignment
50 -x to make NAMEs export
52 Using `+' instead of `-' turns off the given attribute.
54 Variables with the integer attribute have arithmetic evaluation (see
55 the `let' command) performed when the variable is assigned a value.
57 When used in a function, `declare' makes NAMEs local, as with the `local'
58 command. The `-g' option suppresses this behavior.
61 Returns success unless an invalid option is supplied or a variable
62 assignment error occurs.
66 $FUNCTION declare_builtin
67 $SHORT_DOC typeset [-aAfFgiIlnrtux] [-p] name[=value] ...
68 Set variable values and attributes.
70 A synonym for `declare'. See `help declare'.
75 #if defined (HAVE_UNISTD_H)
77 # include <sys/types.h>
84 #include "../bashansi.h"
85 #include "../bashintl.h"
91 #include "bashgetopt.h"
93 static SHELL_VAR *declare_find_variable PARAMS((const char *, int, int));
94 static int declare_internal PARAMS((register WORD_LIST *, int));
96 /* Declare or change variable attributes. */
98 declare_builtin (list)
99 register WORD_LIST *list;
101 return (declare_internal (list, 0));
105 $FUNCTION local_builtin
106 $SHORT_DOC local [option] name[=value] ...
107 Define local variables.
109 Create a local variable called NAME, and give it VALUE. OPTION can
110 be any option accepted by `declare'.
112 Local variables can only be used within a function; they are visible
113 only to the function where they are defined and its children.
116 Returns success unless an invalid option is supplied, a variable
117 assignment error occurs, or the shell is not executing a function.
121 register WORD_LIST *list;
123 /* Catch a straight `local --help' before checking function context */
124 if (list && list->word && STREQ (list->word->word, "--help"))
130 if (variable_context)
131 return (declare_internal (list, 1));
134 builtin_error (_("can only be used in a function"));
135 return (EXECUTION_FAILURE);
139 #if defined (ARRAY_VARS)
140 # define DECLARE_OPTS "+acfgilnprtuxAFGI"
142 # define DECLARE_OPTS "+cfgilnprtuxFGI"
146 declare_find_variable (name, mkglobal, chklocal)
148 int mkglobal, chklocal;
153 return (find_variable (name));
156 var = find_variable (name);
157 if (var && local_p (var) && var->context == variable_context)
159 return (find_global_variable (name));
162 return (find_global_variable (name));
165 /* The workhorse function. */
167 declare_internal (list, local_var)
168 register WORD_LIST *list;
171 int flags_on, flags_off, *flags;
172 int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
173 int mkglobal, chklocal, inherit_flag;
174 char *t, *subscript_start;
175 SHELL_VAR *var, *refvar, *v;
176 FUNCTION_DEF *shell_fn;
178 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
179 mkglobal = chklocal = inherit_flag = 0;
180 refvar = (SHELL_VAR *)NULL;
181 reset_internal_getopt ();
182 while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1)
184 flags = list_opttype == '+' ? &flags_off : &flags_on;
186 /* If you add options here, see whether or not they need to be added to
187 the loop in subst.c:shell_expand_word_list() */
191 #if defined (ARRAY_VARS)
199 #if defined (ARRAY_VARS)
207 /* if (local_var == 0) */
212 *flags |= att_function;
215 *flags |= att_function;
218 if (flags == &flags_on)
222 if (flags == &flags_on)
226 *flags |= att_integer;
229 *flags |= att_nameref;
232 *flags |= att_readonly;
238 *flags |= att_exported;
239 array_needs_making = 1;
241 #if defined (CASEMOD_ATTRS)
242 # if defined (CASEMOD_CAPCASE)
244 *flags |= att_capcase;
245 if (flags == &flags_on)
246 flags_off |= att_uppercase|att_lowercase;
250 *flags |= att_lowercase;
251 if (flags == &flags_on)
252 flags_off |= att_capcase|att_uppercase;
255 *flags |= att_uppercase;
256 if (flags == &flags_on)
257 flags_off |= att_capcase|att_lowercase;
259 #endif /* CASEMOD_ATTRS */
261 inherit_flag = MKLOC_INHERIT;
272 /* If there are no more arguments left, then we just want to show
274 if (list == 0) /* declare -[aAfFirtx] */
276 /* Show local variables defined at this context level if this is
277 the `local' builtin. */
279 show_local_var_attributes (0, nodefs); /* XXX - fix up args later */
280 else if (pflag && (flags_on == 0 || flags_on == att_function))
281 show_all_var_attributes (flags_on == 0, nodefs);
282 else if (flags_on == 0)
283 return (set_builtin ((WORD_LIST *)NULL));
285 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
287 return (sh_chkwrite (EXECUTION_SUCCESS));
290 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
292 for (any_failed = 0; list; list = list->next)
294 if (flags_on & att_function)
295 pflag = show_func_attributes (list->word->word, nodefs);
297 pflag = show_localname_attributes (list->word->word, nodefs);
299 pflag = show_name_attributes (list->word->word, nodefs);
302 sh_notfound (list->word->word);
306 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
309 #define NEXT_VARIABLE() free (name); list = list->next; continue
311 /* There are arguments left, so we are making variables. */
312 while (list) /* declare [-aAfFirx] name [name ...] */
314 char *value, *name, *oldname;
315 int offset, aflags, wflags, created_var, namelen;
317 #if defined (ARRAY_VARS)
318 int making_array_special, compound_array_assign, simple_array_assign;
319 int var_exists, array_exists, creating_array, array_subscript_assignment;
322 name = savestring (list->word->word);
323 wflags = list->word->flags;
324 #if defined (ARRAY_VARS)
325 assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
329 offset = assignment (name, assoc_noexpand ? 2 : 0);
333 if (local_var && variable_context && STREQ (name, "-"))
335 var = make_local_variable ("-", 0);
336 FREE (value_cell (var)); /* just in case */
337 value = get_current_options ();
338 var_setvalue (var, value);
339 VSETATTR (var, att_invisible);
343 if (offset) /* declare [-aAfFirx] name=value */
346 value = name + offset + 1;
347 if (name[offset - 1] == '+')
349 aflags |= ASS_APPEND;
350 name[offset - 1] = '\0';
356 /* Do some lexical error checking on the LHS and RHS of the assignment
357 that is specific to nameref variables. */
358 if (flags_on & att_nameref)
360 #if defined (ARRAY_VARS)
361 if (valid_array_reference (name, 0))
363 builtin_error (_("%s: reference variable cannot be an array"), name);
369 /* disallow self references at global scope, warn at function scope */
370 if (check_selfref (name, value, 0))
372 if (variable_context == 0)
374 builtin_error (_("%s: nameref variable self references not allowed"), name);
379 builtin_warning (_("%s: circular name reference"), name);
382 if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 1) == 0)
384 builtin_error (_("`%s': invalid variable name for name reference"), value);
391 restart_new_var_name:
392 #if defined (ARRAY_VARS)
393 var_exists = array_exists = creating_array = 0;
394 compound_array_assign = simple_array_assign = 0;
395 array_subscript_assignment = 0;
396 subscript_start = (char *)NULL;
397 if ((t = strchr (name, '[')) && (flags_on & att_function) == 0) /* ] */
399 /* If offset != 0 we have already validated any array reference
400 because assignment() calls skipsubscript() */
401 if (offset == 0 && valid_array_reference (name, 0) == 0)
409 making_array_special = 1; /* XXX - should this check offset? */
410 array_subscript_assignment = offset != 0;
413 making_array_special = 0;
416 /* If we're in posix mode or not looking for a shell function (since
417 shell function names don't have to be valid identifiers when the
418 shell's not in posix mode), check whether or not the argument is a
419 valid, well-formed shell identifier. */
420 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
427 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
428 inside of a function. This means we should make local variables,
431 /* XXX - this has consequences when we're making a local copy of a
432 variable that was in the temporary environment. Watch out
434 refvar = (SHELL_VAR *)NULL;
435 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
439 /* check name for validity here? */
440 var = find_variable (name);
442 newname = nameref_transform_name (name, ASS_MKLOCAL);
443 else if ((flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0)
445 /* Ok, we're following namerefs here, so let's make sure that if
446 we followed one, it was at the same context (see below for
448 refvar = find_variable_last_nameref (name, 1);
449 newname = (refvar && refvar->context != variable_context) ? name : var->name;
450 refvar = (SHELL_VAR *)NULL;
453 newname = name; /* dealing with nameref attribute */
455 #if defined (ARRAY_VARS)
456 /* Pass 1 as second argument to make_local_{assoc,array}_variable
457 return an existing {array,assoc} variable to be flagged as an
459 if (flags_on & att_assoc)
460 var = make_local_assoc_variable (newname, MKLOC_ARRAYOK|inherit_flag);
461 else if ((flags_on & att_array) || making_array_special)
462 var = make_local_array_variable (newname, MKLOC_ASSOCOK|inherit_flag);
465 if (offset == 0 && (flags_on & att_nameref))
467 /* First look for refvar at current scope */
468 refvar = find_variable_last_nameref (name, 1);
469 /* VARIABLE_CONTEXT != 0, so we are attempting to create or modify
470 the attributes for a local variable at the same scope. If we've
471 used a reference from a previous context to resolve VAR, we
472 want to throw REFVAR and VAR away and create a new local var. */
473 if (refvar && refvar->context != variable_context)
476 var = make_local_variable (name, inherit_flag);
478 else if (refvar && refvar->context == variable_context)
480 /* Maybe we just want to create a new local variable */
481 else if (var == 0 || var->context != variable_context)
482 var = make_local_variable (name, inherit_flag);
483 /* otherwise we have a var at the right context */
486 /* XXX - check name for validity here with valid_nameref_value */
487 var = make_local_variable ((flags_on & att_nameref) ? name : newname, inherit_flag); /* sets att_invisible for new vars */
494 if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
502 var = (SHELL_VAR *)NULL;
504 /* If we are declaring a function, then complain about it in some way.
505 We don't let people make functions by saying `typeset -f foo=bar'. */
507 /* There should be a way, however, to let people look at a particular
508 function definition by saying `typeset -f foo'. */
510 if (flags_on & att_function)
512 if (offset) /* declare -f [-rix] foo=bar */
514 builtin_error (_("cannot use `-f' to make functions"));
516 return (EXECUTION_FAILURE);
518 else /* declare -f [-rx] name [name...] */
520 var = find_function (name);
524 if (readonly_p (var) && (flags_off & att_readonly))
526 builtin_error (_("%s: readonly function"), name);
530 else if (flags_on & (att_array|att_assoc))
532 sh_invalidopt ((flags_on & att_array) ? "-a" : "-A");
536 /* declare -[Ff] name [name...] */
537 if (flags_on == att_function && flags_off == 0)
539 #if defined (DEBUGGER)
540 if (nodefs && debugging_mode)
542 shell_fn = find_function_def (var->name);
544 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
546 printf ("%s\n", var->name);
549 #endif /* DEBUGGER */
551 t = nodefs ? var->name
552 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
554 any_failed = sh_chkwrite (any_failed);
557 else /* declare -[fF] -[rx] name [name...] */
559 VSETATTR (var, flags_on);
560 flags_off &= ~att_function; /* makes no sense */
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)
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)
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)
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));