]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/declare.def
bash-4.3-beta overlay
[thirdparty/bash.git] / builtins / declare.def
CommitLineData
726f6388
JA
1This file is declare.def, from which is created declare.c.
2It implements the builtins "declare" and "local" in Bash.
3
d42cb8c1 4Copyright (C) 1987-2012 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
2e4498b3
CR
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES declare.c
22
23$BUILTIN declare
24$FUNCTION declare_builtin
d42cb8c1 25$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
6a8fd0ed
CR
26Set variable values and attributes.
27
9cbcc93b
CR
28Declare variables and give them attributes. If no NAMEs are given,
29display the attributes and values of all variables.
726f6388 30
9cbcc93b
CR
31Options:
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)
6faad625
CR
35 -g create global variables when used in a shell function; otherwise
36 ignored
9cbcc93b 37 -p display the attributes and value of each NAME
726f6388 38
9cbcc93b 39Options which set attributes:
fdf670ea
CR
40 -a to make NAMEs indexed arrays (if supported)
41 -A to make NAMEs associative arrays (if supported)
7117c2d2 42 -i to make NAMEs have the `integer' attribute
09767ff0 43 -l to convert NAMEs to lower case on assignment
d42cb8c1 44 -n make NAME a reference to the variable named by its value
ccc6cda3 45 -r to make NAMEs readonly
7117c2d2 46 -t to make NAMEs have the `trace' attribute
09767ff0 47 -u to convert NAMEs to upper case on assignment
ccc6cda3 48 -x to make NAMEs export
726f6388 49
d3ad40de 50Using `+' instead of `-' turns off the given attribute.
28157acd 51
d3ad40de 52Variables with the integer attribute have arithmetic evaluation (see
9cbcc93b 53the `let' command) performed when the variable is assigned a value.
ccc6cda3 54
d3ad40de 55When used in a function, `declare' makes NAMEs local, as with the `local'
6faad625 56command. The `-g' option suppresses this behavior.
6a8fd0ed
CR
57
58Exit Status:
77b3aacb
CR
59Returns success unless an invalid option is supplied or a variable
60assignment error occurs.
726f6388
JA
61$END
62
63$BUILTIN typeset
64$FUNCTION declare_builtin
6faad625 65$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
6a8fd0ed
CR
66Set variable values and attributes.
67
9cbcc93b 68Obsolete. See `help declare'.
726f6388
JA
69$END
70
ccc6cda3
JA
71#include <config.h>
72
73#if defined (HAVE_UNISTD_H)
cce855bc
JA
74# ifdef _MINIX
75# include <sys/types.h>
76# endif
ccc6cda3
JA
77# include <unistd.h>
78#endif
79
726f6388
JA
80#include <stdio.h>
81
ccc6cda3 82#include "../bashansi.h"
5e13499c 83#include "../bashintl.h"
726f6388
JA
84
85#include "../shell.h"
ccc6cda3
JA
86#include "common.h"
87#include "builtext.h"
7117c2d2 88#include "bashgetopt.h"
726f6388 89
f73dda09 90extern int array_needs_making;
ac18b312 91extern int posixly_correct;
726f6388 92
f73dda09 93static int declare_internal __P((register WORD_LIST *, int));
726f6388
JA
94
95/* Declare or change variable attributes. */
96int
97declare_builtin (list)
98 register WORD_LIST *list;
99{
100 return (declare_internal (list, 0));
101}
102
103$BUILTIN local
104$FUNCTION local_builtin
d3ad40de 105$SHORT_DOC local [option] name[=value] ...
6a8fd0ed
CR
106Define local variables.
107
9cbcc93b
CR
108Create a local variable called NAME, and give it VALUE. OPTION can
109be any option accepted by `declare'.
110
111Local variables can only be used within a function; they are visible
112only to the function where they are defined and its children.
6a8fd0ed
CR
113
114Exit Status:
77b3aacb
CR
115Returns success unless an invalid option is supplied, a variable
116assignment error occurs, or the shell is not executing a function.
726f6388
JA
117$END
118int
119local_builtin (list)
120 register WORD_LIST *list;
121{
122 if (variable_context)
123 return (declare_internal (list, 1));
124 else
125 {
5e13499c 126 builtin_error (_("can only be used in a function"));
726f6388
JA
127 return (EXECUTION_FAILURE);
128 }
129}
130
7117c2d2 131#if defined (ARRAY_VARS)
d42cb8c1 132# define DECLARE_OPTS "+acfgilnprtuxAF"
7117c2d2 133#else
d42cb8c1 134# define DECLARE_OPTS "+cfgilnprtuxF"
7117c2d2
JA
135#endif
136
726f6388
JA
137/* The workhorse function. */
138static int
139declare_internal (list, local_var)
140 register WORD_LIST *list;
141 int local_var;
142{
fdf670ea 143 int flags_on, flags_off, *flags;
d42cb8c1 144 int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
f73dda09 145 char *t, *subscript_start;
d42cb8c1 146 SHELL_VAR *var, *refvar;
d3a24ed2 147 FUNCTION_DEF *shell_fn;
726f6388 148
6faad625 149 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
d42cb8c1 150 refvar = (SHELL_VAR *)NULL;
7117c2d2
JA
151 reset_internal_getopt ();
152 while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
726f6388 153 {
7117c2d2 154 flags = list_opttype == '+' ? &flags_off : &flags_on;
726f6388 155
7117c2d2 156 switch (opt)
726f6388 157 {
7117c2d2 158 case 'a':
ccc6cda3 159#if defined (ARRAY_VARS)
7117c2d2 160 *flags |= att_array;
fdf670ea
CR
161 break;
162#else
163 builtin_usage ();
164 return (EX_USAGE);
ccc6cda3 165#endif
fdf670ea
CR
166 case 'A':
167#if defined (ARRAY_VARS)
168 *flags |= att_assoc;
7117c2d2 169 break;
fdf670ea
CR
170#else
171 builtin_usage ();
172 return (EX_USAGE);
173#endif
7117c2d2
JA
174 case 'p':
175 if (local_var == 0)
176 pflag++;
177 break;
178 case 'F':
179 nodefs++;
180 *flags |= att_function;
181 break;
182 case 'f':
183 *flags |= att_function;
184 break;
6faad625
CR
185 case 'g':
186 if (flags == &flags_on)
187 mkglobal = 1;
188 break;
7117c2d2
JA
189 case 'i':
190 *flags |= att_integer;
191 break;
d42cb8c1
CR
192 case 'n':
193 *flags |= att_nameref;
194 break;
7117c2d2
JA
195 case 'r':
196 *flags |= att_readonly;
197 break;
198 case 't':
199 *flags |= att_trace;
200 break;
201 case 'x':
202 *flags |= att_exported;
203 array_needs_making = 1;
204 break;
09767ff0
CR
205#if defined (CASEMOD_ATTRS)
206# if defined (CASEMOD_CAPCASE)
207 case 'c':
208 *flags |= att_capcase;
209 if (flags == &flags_on)
210 flags_off |= att_uppercase|att_lowercase;
211 break;
212# endif
213 case 'l':
214 *flags |= att_lowercase;
215 if (flags == &flags_on)
216 flags_off |= att_capcase|att_uppercase;
217 break;
218 case 'u':
219 *flags |= att_uppercase;
220 if (flags == &flags_on)
221 flags_off |= att_capcase|att_lowercase;
222 break;
223#endif /* CASEMOD_ATTRS */
7117c2d2
JA
224 default:
225 builtin_usage ();
226 return (EX_USAGE);
726f6388 227 }
726f6388
JA
228 }
229
7117c2d2
JA
230 list = loptend;
231
726f6388
JA
232 /* If there are no more arguments left, then we just want to show
233 some variables. */
fdf670ea 234 if (list == 0) /* declare -[aAfFirtx] */
726f6388
JA
235 {
236 /* Show local variables defined at this context level if this is
237 the `local' builtin. */
238 if (local_var)
239 {
240 register SHELL_VAR **vlist;
241 register int i;
242
7117c2d2 243 vlist = all_local_variables ();
726f6388
JA
244
245 if (vlist)
246 {
247 for (i = 0; vlist[i]; i++)
248 print_assignment (vlist[i]);
249
250 free (vlist);
251 }
252 }
6fbe7620
CR
253 else if (pflag && (flags_on == 0 || flags_on == att_function))
254 show_all_var_attributes (flags_on == 0, nodefs);
641d8f00
CR
255 else if (flags_on == 0)
256 return (set_builtin ((WORD_LIST *)NULL));
726f6388 257 else
641d8f00 258 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
726f6388 259
641d8f00 260 return (sh_chkwrite (EXECUTION_SUCCESS));
726f6388
JA
261 }
262
fdf670ea 263 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
ccc6cda3
JA
264 {
265 for (any_failed = 0; list; list = list->next)
266 {
1442f67c
CR
267 if (flags_on & att_function)
268 pflag = show_func_attributes (list->word->word, nodefs);
269 else
270 pflag = show_name_attributes (list->word->word, nodefs);
ccc6cda3
JA
271 if (pflag)
272 {
7117c2d2 273 sh_notfound (list->word->word);
ccc6cda3
JA
274 any_failed++;
275 }
276 }
641d8f00 277 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
ccc6cda3
JA
278 }
279
726f6388
JA
280#define NEXT_VARIABLE() free (name); list = list->next; continue
281
282 /* There are arguments left, so we are making variables. */
fdf670ea 283 while (list) /* declare [-aAfFirx] name [name ...] */
726f6388 284 {
ccc6cda3 285 char *value, *name;
d11b8b46 286 int offset, aflags;
ccc6cda3 287#if defined (ARRAY_VARS)
f73dda09 288 int making_array_special, compound_array_assign, simple_array_assign;
ccc6cda3
JA
289#endif
290
291 name = savestring (list->word->word);
5e13499c 292 offset = assignment (name, 0);
d11b8b46 293 aflags = 0;
726f6388 294
fdf670ea 295 if (offset) /* declare [-aAfFirx] name=value */
726f6388
JA
296 {
297 name[offset] = '\0';
298 value = name + offset + 1;
d11b8b46
CR
299 if (name[offset - 1] == '+')
300 {
301 aflags |= ASS_APPEND;
302 name[offset - 1] = '\0';
303 }
726f6388
JA
304 }
305 else
306 value = "";
307
15623760
CR
308 /* Do some lexical error checking on the LHS and RHS of the assignment
309 that is specific to nameref variables. */
310 if (flags_on & att_nameref)
311 {
b721485f 312#if defined (ARRAY_VARIABLES)
15623760
CR
313 if (valid_array_reference (name))
314 {
315 builtin_error (_("%s: reference variable cannot be an array"), name);
316 assign_error++;
317 NEXT_VARIABLE ();
318 }
b721485f
CR
319 else
320#endif
1442f67c
CR
321 /* disallow self references at global scope */
322 if (STREQ (name, value) && variable_context == 0)
15623760
CR
323 {
324 builtin_error (_("%s: nameref variable self references not allowed"), name);
325 assign_error++;
326 NEXT_VARIABLE ();
327 }
328 }
329
ccc6cda3 330#if defined (ARRAY_VARS)
f73dda09
JA
331 compound_array_assign = simple_array_assign = 0;
332 subscript_start = (char *)NULL;
333 if (t = strchr (name, '[')) /* ] */
ccc6cda3 334 {
6932f7f5
CR
335 /* If offset != 0 we have already validated any array reference */
336 if (offset == 0 && valid_array_reference (name) == 0)
337 {
338 sh_invalidid (name);
339 assign_error++;
340 NEXT_VARIABLE ();
341 }
f73dda09 342 subscript_start = t;
ccc6cda3
JA
343 *t = '\0';
344 making_array_special = 1;
345 }
346 else
347 making_array_special = 0;
348#endif
ac18b312
CR
349
350 /* If we're in posix mode or not looking for a shell function (since
351 shell function names don't have to be valid identifiers when the
352 shell's not in posix mode), check whether or not the argument is a
353 valid, well-formed shell identifier. */
354 if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
726f6388 355 {
7117c2d2 356 sh_invalidid (name);
ccc6cda3 357 assign_error++;
726f6388
JA
358 NEXT_VARIABLE ();
359 }
360
361 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
362 inside of a function. This means we should make local variables,
363 not global ones. */
364
7117c2d2
JA
365 /* XXX - this has consequences when we're making a local copy of a
366 variable that was in the temporary environment. Watch out
367 for this. */
d42cb8c1 368 refvar = (SHELL_VAR *)NULL;
6faad625 369 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
ccc6cda3
JA
370 {
371#if defined (ARRAY_VARS)
fdf670ea
CR
372 if (flags_on & att_assoc)
373 var = make_local_assoc_variable (name);
374 else if ((flags_on & att_array) || making_array_special)
7f947b68 375 var = make_local_array_variable (name, making_array_special);
ccc6cda3
JA
376 else
377#endif
d42cb8c1
CR
378#if 0
379 /* XXX - this doesn't work right yet. */
380 /* See below for rationale for doing this. */
381 if (flags_on & att_nameref)
382 {
383 /* See if we are trying to modify an existing nameref variable */
384 var = find_variable_last_nameref (name);
385 if (var && nameref_p (var) == 0)
386 var = make_local_variable (name);
387 }
388 else if (flags_off & att_nameref)
389 {
390 var = (SHELL_VAR *)NULL;
391 /* See if we are trying to modify an existing nameref variable */
392 refvar = find_variable_last_nameref (name);
393 if (refvar && nameref_p (refvar) == 0)
394 refvar = 0;
395 if (refvar)
396 var = make_local_variable (nameref_cell (refvar));
397 if (var == 0)
398 var = make_local_variable (name);
399 }
400 else
401#endif
402 var = make_local_variable (name);
bb70624e
JA
403 if (var == 0)
404 {
405 any_failed++;
406 NEXT_VARIABLE ();
407 }
ccc6cda3 408 }
7117c2d2
JA
409 else
410 var = (SHELL_VAR *)NULL;
726f6388
JA
411
412 /* If we are declaring a function, then complain about it in some way.
413 We don't let people make functions by saying `typeset -f foo=bar'. */
414
415 /* There should be a way, however, to let people look at a particular
416 function definition by saying `typeset -f foo'. */
417
418 if (flags_on & att_function)
419 {
ccc6cda3 420 if (offset) /* declare -f [-rix] foo=bar */
726f6388 421 {
5e13499c 422 builtin_error (_("cannot use `-f' to make functions"));
d166f048 423 free (name);
726f6388
JA
424 return (EXECUTION_FAILURE);
425 }
ccc6cda3 426 else /* declare -f [-rx] name [name...] */
726f6388 427 {
ccc6cda3 428 var = find_function (name);
726f6388 429
ccc6cda3 430 if (var)
726f6388 431 {
ccc6cda3 432 if (readonly_p (var) && (flags_off & att_readonly))
726f6388 433 {
5e13499c 434 builtin_error (_("%s: readonly function"), name);
726f6388
JA
435 any_failed++;
436 NEXT_VARIABLE ();
437 }
438
ccc6cda3 439 /* declare -[Ff] name [name...] */
726f6388
JA
440 if (flags_on == att_function && flags_off == 0)
441 {
d3a24ed2
CR
442#if defined (DEBUGGER)
443 if (nodefs && debugging_mode)
444 {
445 shell_fn = find_function_def (var->name);
446 if (shell_fn)
447 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
448 else
449 printf ("%s\n", var->name);
450 }
451 else
452#endif /* DEBUGGER */
453 {
454 t = nodefs ? var->name
b0c16657 455 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
d3a24ed2 456 printf ("%s\n", t);
641d8f00 457 any_failed = sh_chkwrite (any_failed);
d3a24ed2 458 }
726f6388 459 }
ccc6cda3 460 else /* declare -[fF] -[rx] name [name...] */
726f6388 461 {
bb70624e
JA
462 VSETATTR (var, flags_on);
463 VUNSETATTR (var, flags_off);
726f6388
JA
464 }
465 }
466 else
467 any_failed++;
468 NEXT_VARIABLE ();
469 }
470 }
fdf670ea 471 else /* declare -[aAirx] name [name...] */
726f6388 472 {
7117c2d2 473 /* Non-null if we just created or fetched a local variable. */
d42cb8c1
CR
474 /* Here's what ksh93 seems to do. If we are modifying an existing
475 nameref variable, we don't follow the nameref chain past the last
476 nameref, and we set the nameref variable's value so future
477 references to that variable will return the value of the variable
478 we're assigning right now. */
479 if (var == 0 && (flags_on & att_nameref))
480 {
481 /* See if we are trying to modify an existing nameref variable */
482 var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
483 if (var && nameref_p (var) == 0)
484 var = 0;
485 }
486 /* However, if we're turning off the nameref attribute on an existing
487 nameref variable, we first follow the nameref chain to the end,
488 modify the value of the variable this nameref variable references,
489 *CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
490 flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
491 else if (var == 0 && (flags_off & att_nameref))
492 {
493 /* See if we are trying to modify an existing nameref variable */
494 refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
495 if (refvar && nameref_p (refvar) == 0)
496 refvar = 0;
497 if (refvar)
498 var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
499 }
500
7117c2d2 501 if (var == 0)
6faad625 502 var = mkglobal ? find_global_variable (name) : find_variable (name);
726f6388 503
ccc6cda3
JA
504 if (var == 0)
505 {
506#if defined (ARRAY_VARS)
fdf670ea 507 if (flags_on & att_assoc)
3087e51c
CR
508 {
509 var = make_new_assoc_variable (name);
510 if (offset == 0)
511 VSETATTR (var, att_invisible);
512 }
fdf670ea 513 else if ((flags_on & att_array) || making_array_special)
3087e51c
CR
514 {
515 var = make_new_array_variable (name);
516 if (offset == 0)
517 VSETATTR (var, att_invisible);
518 }
ccc6cda3
JA
519 else
520#endif
f1c4df24
CR
521
522 if (offset)
36eb585c 523 var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
f1c4df24
CR
524 else
525 {
36eb585c 526 var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
f1c4df24
CR
527 VSETATTR (var, att_invisible);
528 }
ccc6cda3 529 }
15623760
CR
530 /* Can't take an existing array variable and make it a nameref */
531 else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
532 {
533 builtin_error (_("%s: reference variable cannot be an array"), name);
534 assign_error++;
535 NEXT_VARIABLE ();
536 }
726f6388 537
ccc6cda3 538 /* Cannot use declare +r to turn off readonly attribute. */
726f6388
JA
539 if (readonly_p (var) && (flags_off & att_readonly))
540 {
7117c2d2 541 sh_readonly (name);
726f6388
JA
542 any_failed++;
543 NEXT_VARIABLE ();
544 }
545
28ef6c31
JA
546 /* Cannot use declare to assign value to readonly or noassign
547 variable. */
548 if ((readonly_p (var) || noassign_p (var)) && offset)
ccc6cda3 549 {
28ef6c31 550 if (readonly_p (var))
7117c2d2 551 sh_readonly (name);
ccc6cda3
JA
552 assign_error++;
553 NEXT_VARIABLE ();
554 }
555
556#if defined (ARRAY_VARS)
fdf670ea 557 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
ccc6cda3 558 {
43df7bbb
CR
559 int vlen;
560 vlen = STRLEN (value);
6a8fd0ed 561
43df7bbb 562 if (value[0] == '(' && value[vlen-1] == ')')
f73dda09 563 compound_array_assign = 1;
ccc6cda3 564 else
f73dda09 565 simple_array_assign = 1;
ccc6cda3
JA
566 }
567
fdf670ea
CR
568 /* Cannot use declare +a name or declare +A name to remove an
569 array variable. */
570 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
ccc6cda3 571 {
5e13499c 572 builtin_error (_("%s: cannot destroy array variables in this way"), name);
ccc6cda3
JA
573 any_failed++;
574 NEXT_VARIABLE ();
575 }
576
fdf670ea
CR
577 if ((flags_on & att_array) && assoc_p (var))
578 {
579 builtin_error (_("%s: cannot convert associative to indexed array"), name);
580 any_failed++;
581 NEXT_VARIABLE ();
582 }
583 if ((flags_on & att_assoc) && array_p (var))
584 {
585 builtin_error (_("%s: cannot convert indexed to associative array"), name);
586 any_failed++;
587 NEXT_VARIABLE ();
588 }
589
590 /* declare -A name[[n]] makes name an associative array variable. */
591 if (flags_on & att_assoc)
592 {
593 if (assoc_p (var) == 0)
594 var = convert_var_to_assoc (var);
595 }
596 /* declare -a name[[n]] or declare name[n] makes name an indexed
597 array variable. */
6932f7f5 598 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
ccc6cda3
JA
599 var = convert_var_to_array (var);
600#endif /* ARRAY_VARS */
601
d42cb8c1
CR
602 /* XXX - we note that we are turning on nameref attribute and defer
603 setting it until the assignment has been made so we don't do an
604 inadvertent nameref lookup. Might have to do the same thing for
605 flags_off&att_nameref. */
606 /* XXX - ksh93 makes it an error to set a readonly nameref variable
607 using a single typeset command. */
608 onref = (flags_on & att_nameref);
609 flags_on &= ~att_nameref;
b721485f 610#if defined (ARRAY_VARS)
d42cb8c1
CR
611 if (array_p (var) || assoc_p (var)
612 || (offset && compound_array_assign)
613 || simple_array_assign)
614 onref = 0; /* array variables may not be namerefs */
b721485f 615#endif
d42cb8c1
CR
616
617 /* ksh93 seems to do this */
618 offref = (flags_off & att_nameref);
619 flags_off &= ~att_nameref;
620
bb70624e
JA
621 VSETATTR (var, flags_on);
622 VUNSETATTR (var, flags_off);
726f6388 623
ccc6cda3 624#if defined (ARRAY_VARS)
f73dda09 625 if (offset && compound_array_assign)
d11b8b46 626 assign_array_var_from_string (var, value, aflags);
f73dda09
JA
627 else if (simple_array_assign && subscript_start)
628 {
6932f7f5 629 /* declare [-aA] name[N]=value */
f73dda09 630 *subscript_start = '['; /* ] */
d11b8b46 631 var = assign_array_element (name, value, 0); /* XXX - not aflags */
f73dda09 632 *subscript_start = '\0';
b13b8a87
CR
633 if (var == 0) /* some kind of assignment error */
634 {
635 assign_error++;
d42cb8c1
CR
636 flags_on |= onref;
637 flags_off |= offref;
b13b8a87
CR
638 NEXT_VARIABLE ();
639 }
f73dda09
JA
640 }
641 else if (simple_array_assign)
f486d0a1
CR
642 {
643 /* let bind_{array,assoc}_variable take care of this. */
644 if (assoc_p (var))
d1fab3dc 645 bind_assoc_variable (var, name, savestring ("0"), value, aflags);
f486d0a1
CR
646 else
647 bind_array_variable (name, 0, value, aflags);
648 }
ccc6cda3
JA
649 else
650#endif
bb70624e
JA
651 /* bind_variable_value duplicates the essential internals of
652 bind_variable() */
726f6388 653 if (offset)
d11b8b46 654 bind_variable_value (var, value, aflags);
cce855bc
JA
655
656 /* If we found this variable in the temporary environment, as with
657 `var=value declare -x var', make sure it is treated identically
658 to `var=value export var'. Do the same for `declare -r' and
659 `readonly'. Preserve the attributes, except for att_tempvar. */
7117c2d2
JA
660 /* XXX -- should this create a variable in the global scope, or
661 modify the local variable flags? ksh93 has it modify the
662 global scope.
663 Need to handle case like in set_var_attribute where a temporary
664 variable is in the same table as the function local vars. */
cce855bc
JA
665 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
666 {
667 SHELL_VAR *tv;
7117c2d2
JA
668 char *tvalue;
669
670 tv = find_tempenv_variable (var->name);
671 if (tv)
672 {
673 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
d11b8b46 674 tv = bind_variable (var->name, tvalue, 0);
7117c2d2
JA
675 tv->attributes |= var->attributes & ~att_tempvar;
676 if (tv->context > 0)
677 VSETATTR (tv, att_propagate);
678 free (tvalue);
679 }
680 VSETATTR (var, att_propagate);
cce855bc 681 }
726f6388
JA
682 }
683
d42cb8c1
CR
684 /* Turn on nameref attribute we deferred above. */
685 /* XXX - should we turn on the noassign attribute for consistency with
686 ksh93 when we turn on the nameref attribute? */
687 VSETATTR (var, onref);
688 flags_on |= onref;
689 VUNSETATTR (var, offref);
690 flags_off |= offref;
691 /* Yuck. ksh93 compatibility */
692 if (refvar)
693 VUNSETATTR (refvar, flags_off);
694
726f6388
JA
695 stupidly_hack_special_variables (name);
696
697 NEXT_VARIABLE ();
698 }
ccc6cda3
JA
699
700 return (assign_error ? EX_BADASSIGN
701 : ((any_failed == 0) ? EXECUTION_SUCCESS
702 : EXECUTION_FAILURE));
726f6388 703}