]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/declare.def
Bash-5.2 patch 26: fix typo when specifying readline's custom color prefix
[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
74091dd4 4Copyright (C) 1987-2021 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
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.
726f6388 12
3185942a
JA
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.
726f6388 17
3185942a
JA
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
74091dd4 25$SHORT_DOC declare [-aAfFgiIlnrtux] [name[=value] ...] or declare -p [-aAfFilnrtux] [name ...]
3185942a 26Set variable values and attributes.
726f6388 27
3185942a
JA
28Declare variables and give them attributes. If no NAMEs are given,
29display the attributes and values of all variables.
726f6388 30
3185942a
JA
31Options:
32 -f restrict action or display to function names and definitions
33 -F restrict display to function names only (plus line number and
a0c0a00f 34 source file when debugging)
495aee44 35 -g create global variables when used in a shell function; otherwise
a0c0a00f 36 ignored
8868edaf
CR
37 -I if creating a local variable, inherit the attributes and value
38 of a variable with the same name at a previous scope
3185942a
JA
39 -p display the attributes and value of each NAME
40
41Options which set attributes:
42 -a to make NAMEs indexed arrays (if supported)
43 -A to make NAMEs associative arrays (if supported)
7117c2d2 44 -i to make NAMEs have the `integer' attribute
d233b485 45 -l to convert the value of each NAME to lower case on assignment
ac50fbac 46 -n make NAME a reference to the variable named by its value
ccc6cda3 47 -r to make NAMEs readonly
7117c2d2 48 -t to make NAMEs have the `trace' attribute
d233b485 49 -u to convert the value of each NAME to upper case on assignment
ccc6cda3 50 -x to make NAMEs export
726f6388 51
3185942a
JA
52Using `+' instead of `-' turns off the given attribute.
53
726f6388 54Variables with the integer attribute have arithmetic evaluation (see
3185942a 55the `let' command) performed when the variable is assigned a value.
726f6388 56
3185942a 57When used in a function, `declare' makes NAMEs local, as with the `local'
495aee44 58command. The `-g' option suppresses this behavior.
ccc6cda3 59
3185942a 60Exit Status:
ac50fbac
CR
61Returns success unless an invalid option is supplied or a variable
62assignment error occurs.
726f6388
JA
63$END
64
65$BUILTIN typeset
66$FUNCTION declare_builtin
74091dd4 67$SHORT_DOC typeset [-aAfFgiIlnrtux] name[=value] ... or typeset -p [-aAfFilnrtux] [name ...]
3185942a
JA
68Set variable values and attributes.
69
a0c0a00f 70A synonym for `declare'. See `help declare'.
726f6388
JA
71$END
72
ccc6cda3
JA
73#include <config.h>
74
75#if defined (HAVE_UNISTD_H)
cce855bc
JA
76# ifdef _MINIX
77# include <sys/types.h>
78# endif
ccc6cda3
JA
79# include <unistd.h>
80#endif
81
726f6388
JA
82#include <stdio.h>
83
ccc6cda3 84#include "../bashansi.h"
b80f6443 85#include "../bashintl.h"
726f6388
JA
86
87#include "../shell.h"
a0c0a00f 88#include "../flags.h"
ccc6cda3
JA
89#include "common.h"
90#include "builtext.h"
7117c2d2 91#include "bashgetopt.h"
726f6388 92
8868edaf 93static SHELL_VAR *declare_find_variable PARAMS((const char *, int, int));
74091dd4
CR
94static char *declare_build_newname PARAMS((char *, char *, int, char *, int));
95static char *declare_transform_name PARAMS((char *, int, int));
96
8868edaf 97static int declare_internal PARAMS((register WORD_LIST *, int));
726f6388
JA
98
99/* Declare or change variable attributes. */
100int
101declare_builtin (list)
102 register WORD_LIST *list;
103{
104 return (declare_internal (list, 0));
105}
106
107$BUILTIN local
108$FUNCTION local_builtin
3185942a
JA
109$SHORT_DOC local [option] name[=value] ...
110Define local variables.
111
112Create a local variable called NAME, and give it VALUE. OPTION can
113be any option accepted by `declare'.
114
115Local variables can only be used within a function; they are visible
116only to the function where they are defined and its children.
117
118Exit Status:
ac50fbac
CR
119Returns success unless an invalid option is supplied, a variable
120assignment error occurs, or the shell is not executing a function.
726f6388
JA
121$END
122int
123local_builtin (list)
124 register WORD_LIST *list;
125{
d233b485
CR
126 /* Catch a straight `local --help' before checking function context */
127 if (list && list->word && STREQ (list->word->word, "--help"))
128 {
129 builtin_help ();
130 return (EX_USAGE);
131 }
132
726f6388
JA
133 if (variable_context)
134 return (declare_internal (list, 1));
135 else
136 {
b80f6443 137 builtin_error (_("can only be used in a function"));
726f6388
JA
138 return (EXECUTION_FAILURE);
139 }
140}
141
7117c2d2 142#if defined (ARRAY_VARS)
8868edaf 143# define DECLARE_OPTS "+acfgilnprtuxAFGI"
7117c2d2 144#else
8868edaf 145# define DECLARE_OPTS "+cfgilnprtuxFGI"
7117c2d2
JA
146#endif
147
d233b485
CR
148static SHELL_VAR *
149declare_find_variable (name, mkglobal, chklocal)
150 const char *name;
151 int mkglobal, chklocal;
152{
153 SHELL_VAR *var;
154
155 if (mkglobal == 0)
156 return (find_variable (name));
157 else if (chklocal)
158 {
159 var = find_variable (name);
160 if (var && local_p (var) && var->context == variable_context)
161 return var;
162 return (find_global_variable (name));
163 }
164 else
165 return (find_global_variable (name));
166}
167
74091dd4
CR
168/* Build a new string
169 NAME[SUBSCRIPT][[+]=VALUE]
170 from expanding a nameref into NAME */
171static char *
172declare_build_newname (name, subscript_start, offset, value, aflags)
173 char *name, *subscript_start;
174 int offset;
175 char *value;
176 int aflags;
177{
178 size_t namelen, savelen;
179 char *ret;
180
181 savelen = namelen = strlen (name);
182 if (subscript_start)
183 {
184 *subscript_start = '['; /* ] */
185 namelen += strlen (subscript_start);
186 }
187 ret = xmalloc (namelen + 2 + strlen (value) + 1);
188 strcpy (ret, name);
189 if (subscript_start)
190 strcpy (ret + savelen, subscript_start);
191 if (offset)
192 {
193 if (aflags & ASS_APPEND)
194 ret[namelen++] = '+';
195 ret[namelen++] = '=';
196 if (value && *value)
197 strcpy (ret + namelen, value);
198 else
199 ret[namelen] = '\0';
200 }
201
202 return (ret);
203}
204
205static char *
206declare_transform_name (name, flags_on, flags_off)
207 char *name;
208 int flags_on, flags_off;
209{
210 SHELL_VAR *var, *v;
211 char *newname;
212
213 var = find_variable (name);
214 if (var == 0)
215 newname = nameref_transform_name (name, ASS_MKLOCAL);
216 else if ((flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0)
217 {
218 /* Ok, we're following namerefs here, so let's make sure that if
219 we followed one, it was at the same context (see below for
220 more details). */
221 v = find_variable_last_nameref (name, 1);
222 newname = (v && v->context != variable_context) ? name : name_cell (var);
223 }
224 else
225 newname = name; /* dealing with nameref attribute */
226
227 return (newname);
228}
229
726f6388
JA
230/* The workhorse function. */
231static int
232declare_internal (list, local_var)
233 register WORD_LIST *list;
234 int local_var;
235{
3185942a 236 int flags_on, flags_off, *flags;
d233b485 237 int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
8868edaf 238 int mkglobal, chklocal, inherit_flag;
f73dda09 239 char *t, *subscript_start;
ac50fbac 240 SHELL_VAR *var, *refvar, *v;
b80f6443 241 FUNCTION_DEF *shell_fn;
726f6388 242
d233b485 243 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
8868edaf 244 mkglobal = chklocal = inherit_flag = 0;
ac50fbac 245 refvar = (SHELL_VAR *)NULL;
7117c2d2 246 reset_internal_getopt ();
a0c0a00f 247 while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1)
726f6388 248 {
7117c2d2 249 flags = list_opttype == '+' ? &flags_off : &flags_on;
726f6388 250
a0c0a00f
CR
251 /* If you add options here, see whether or not they need to be added to
252 the loop in subst.c:shell_expand_word_list() */
7117c2d2 253 switch (opt)
726f6388 254 {
7117c2d2 255 case 'a':
ccc6cda3 256#if defined (ARRAY_VARS)
7117c2d2 257 *flags |= att_array;
3185942a
JA
258 break;
259#else
260 builtin_usage ();
261 return (EX_USAGE);
ccc6cda3 262#endif
3185942a
JA
263 case 'A':
264#if defined (ARRAY_VARS)
265 *flags |= att_assoc;
7117c2d2 266 break;
3185942a
JA
267#else
268 builtin_usage ();
269 return (EX_USAGE);
270#endif
7117c2d2 271 case 'p':
74091dd4 272 pflag++;
7117c2d2 273 break;
74091dd4 274 case 'F':
7117c2d2
JA
275 nodefs++;
276 *flags |= att_function;
277 break;
278 case 'f':
279 *flags |= att_function;
280 break;
d233b485
CR
281 case 'G':
282 if (flags == &flags_on)
283 chklocal = 1;
284 /*FALLTHROUGH*/
495aee44
CR
285 case 'g':
286 if (flags == &flags_on)
287 mkglobal = 1;
288 break;
7117c2d2
JA
289 case 'i':
290 *flags |= att_integer;
291 break;
ac50fbac
CR
292 case 'n':
293 *flags |= att_nameref;
294 break;
7117c2d2
JA
295 case 'r':
296 *flags |= att_readonly;
297 break;
298 case 't':
299 *flags |= att_trace;
300 break;
301 case 'x':
302 *flags |= att_exported;
303 array_needs_making = 1;
304 break;
3185942a
JA
305#if defined (CASEMOD_ATTRS)
306# if defined (CASEMOD_CAPCASE)
307 case 'c':
308 *flags |= att_capcase;
309 if (flags == &flags_on)
310 flags_off |= att_uppercase|att_lowercase;
311 break;
312# endif
313 case 'l':
314 *flags |= att_lowercase;
315 if (flags == &flags_on)
316 flags_off |= att_capcase|att_uppercase;
317 break;
318 case 'u':
319 *flags |= att_uppercase;
320 if (flags == &flags_on)
321 flags_off |= att_capcase|att_lowercase;
322 break;
323#endif /* CASEMOD_ATTRS */
8868edaf
CR
324 case 'I':
325 inherit_flag = MKLOC_INHERIT;
326 break;
a0c0a00f 327 CASE_HELPOPT;
7117c2d2
JA
328 default:
329 builtin_usage ();
330 return (EX_USAGE);
726f6388 331 }
726f6388
JA
332 }
333
7117c2d2
JA
334 list = loptend;
335
726f6388
JA
336 /* If there are no more arguments left, then we just want to show
337 some variables. */
74091dd4 338 if (list == 0) /* declare -[aAfFilnrtux] */
726f6388
JA
339 {
340 /* Show local variables defined at this context level if this is
341 the `local' builtin. */
342 if (local_var)
8868edaf 343 show_local_var_attributes (0, nodefs); /* XXX - fix up args later */
3185942a
JA
344 else if (pflag && (flags_on == 0 || flags_on == att_function))
345 show_all_var_attributes (flags_on == 0, nodefs);
346 else if (flags_on == 0)
347 return (set_builtin ((WORD_LIST *)NULL));
726f6388 348 else
3185942a 349 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
726f6388 350
3185942a 351 return (sh_chkwrite (EXECUTION_SUCCESS));
726f6388
JA
352 }
353
74091dd4 354 if (pflag) /* declare -p [-aAfFilnrtux] [name ...] */
ccc6cda3
JA
355 {
356 for (any_failed = 0; list; list = list->next)
357 {
ac50fbac
CR
358 if (flags_on & att_function)
359 pflag = show_func_attributes (list->word->word, nodefs);
8868edaf
CR
360 else if (local_var)
361 pflag = show_localname_attributes (list->word->word, nodefs);
ac50fbac
CR
362 else
363 pflag = show_name_attributes (list->word->word, nodefs);
ccc6cda3
JA
364 if (pflag)
365 {
7117c2d2 366 sh_notfound (list->word->word);
ccc6cda3
JA
367 any_failed++;
368 }
369 }
3185942a 370 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
ccc6cda3
JA
371 }
372
74091dd4
CR
373 /* Some option combinations that don't make any sense */
374 if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
375 {
376 char *optchar;
377
378 if (flags_on & att_nameref)
379 optchar = "-n";
380 else if (flags_on & att_integer)
381 optchar = "-i";
382 else if (flags_on & att_assoc)
383 optchar = "-A";
384 else if (flags_on & att_array)
385 optchar = "-a";
386
387 sh_invalidopt (optchar);
388 return (EXECUTION_FAILURE);
389 }
390
726f6388
JA
391#define NEXT_VARIABLE() free (name); list = list->next; continue
392
393 /* There are arguments left, so we are making variables. */
74091dd4 394 while (list) /* declare [-aAfFilnrtux] name[=value] [name[=value] ...] */
726f6388 395 {
74091dd4
CR
396 char *value, *name, *newname;
397 int offset, aflags, wflags, created_var;
d233b485 398 int assoc_noexpand;
ccc6cda3 399#if defined (ARRAY_VARS)
f73dda09 400 int making_array_special, compound_array_assign, simple_array_assign;
a0c0a00f 401 int var_exists, array_exists, creating_array, array_subscript_assignment;
ccc6cda3
JA
402#endif
403
404 name = savestring (list->word->word);
a0c0a00f 405 wflags = list->word->flags;
d233b485
CR
406#if defined (ARRAY_VARS)
407 assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
408#else
409 assoc_noexpand = 0;
410#endif
74091dd4
CR
411 /* XXX - we allow unbalanced brackets if assoc_noexpand is set, we count
412 brackets and make sure they match if assoc_noexpand is not set. So we
413 need to make sure we're checking assoc_noexpand and expand_once_flag
414 for backwards compatibility. We also use assoc_noexpand below when
415 we call assign_array_element, so we need to make sure they're
416 consistent in how they count brackets. */
d233b485 417 offset = assignment (name, assoc_noexpand ? 2 : 0);
95732b49 418 aflags = 0;
a0c0a00f
CR
419 created_var = 0;
420
421 if (local_var && variable_context && STREQ (name, "-"))
422 {
c22ce0d0
CR
423 int o;
424
425 o = localvar_inherit;
426 localvar_inherit = 0;
d233b485 427 var = make_local_variable ("-", 0);
c22ce0d0
CR
428 localvar_inherit = o;
429
430 if (value_cell (var) == NULL) /* no duplicate instances */
431 {
432 value = get_current_options ();
433 var_setvalue (var, value);
434 VSETATTR (var, att_invisible);
435 }
a0c0a00f
CR
436 NEXT_VARIABLE ();
437 }
726f6388 438
74091dd4
CR
439 /* If we are declaring a function, then complain about it in some way.
440 We don't let people make functions by saying `typeset -f foo=bar'. */
441
442 /* Can't define functions using assignment statements */
443 if (offset && (flags_on & att_function)) /* declare -f [-rix] foo=bar */
444 {
445 builtin_error (_("cannot use `-f' to make functions"));
446 free (name);
447 return (EXECUTION_FAILURE);
448 }
449
450 /* There should be a way, however, to let people look at a particular
451 function definition by saying `typeset -f foo'. This is the only
452 place in this builtin where we deal with functions. */
453
454 if (flags_on & att_function)
455 {
456 /* Should we restrict this when the shell is in posix mode even if
457 the function was created before the shell entered posix mode?
458 Previous versions of the shell enforced the restriction. */
459 if (posixly_correct && legal_identifier (name) == 0)
460 {
461 sh_invalidid (name);
462 assign_error++;
463 NEXT_VARIABLE ();
464 }
465
466 var = find_function (name);
467
468 if (var)
469 {
470 if (readonly_p (var) && (flags_off & att_readonly))
471 {
472 builtin_error (_("%s: readonly function"), name);
473 any_failed++;
474 NEXT_VARIABLE ();
475 }
476 /* declare -[Ff] name [name...] */
477 if (flags_on == att_function && flags_off == 0)
478 {
479#if defined (DEBUGGER)
480 if (nodefs && debugging_mode)
481 {
482 shell_fn = find_function_def (name_cell (var));
483 if (shell_fn)
484 printf ("%s %d %s\n", name_cell (var), shell_fn->line, shell_fn->source_file);
485 else
486 printf ("%s\n", name_cell (var));
487 }
488 else
489#endif /* DEBUGGER */
490 {
491 t = nodefs ? name_cell (var) : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
492 printf ("%s\n", t);
493 any_failed = sh_chkwrite (any_failed);
494 }
495 }
496 else /* declare -[fF] -[rx] name [name...] */
497 {
498 VSETATTR (var, flags_on);
499 flags_off &= ~att_function; /* makes no sense */
500 VUNSETATTR (var, flags_off);
501 }
502 }
503 else
504 any_failed++;
505
506 NEXT_VARIABLE ();
507 }
508
3185942a 509 if (offset) /* declare [-aAfFirx] name=value */
726f6388
JA
510 {
511 name[offset] = '\0';
512 value = name + offset + 1;
95732b49
JA
513 if (name[offset - 1] == '+')
514 {
515 aflags |= ASS_APPEND;
516 name[offset - 1] = '\0';
517 }
726f6388
JA
518 }
519 else
520 value = "";
521
ac50fbac
CR
522 /* Do some lexical error checking on the LHS and RHS of the assignment
523 that is specific to nameref variables. */
524 if (flags_on & att_nameref)
525 {
a0c0a00f
CR
526#if defined (ARRAY_VARS)
527 if (valid_array_reference (name, 0))
ac50fbac
CR
528 {
529 builtin_error (_("%s: reference variable cannot be an array"), name);
74091dd4 530 any_failed++;
ac50fbac
CR
531 NEXT_VARIABLE ();
532 }
533 else
534#endif
a0c0a00f
CR
535 /* disallow self references at global scope, warn at function scope */
536 if (check_selfref (name, value, 0))
537 {
538 if (variable_context == 0)
539 {
540 builtin_error (_("%s: nameref variable self references not allowed"), name);
74091dd4 541 assign_error++; /* XXX any_failed++ instead? */
a0c0a00f
CR
542 NEXT_VARIABLE ();
543 }
544 else
545 builtin_warning (_("%s: circular name reference"), name);
546 }
a0c0a00f 547 if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 1) == 0)
ac50fbac 548 {
a0c0a00f 549 builtin_error (_("`%s': invalid variable name for name reference"), value);
ac50fbac
CR
550 assign_error++;
551 NEXT_VARIABLE ();
552 }
553 }
554
a0c0a00f 555restart_new_var_name:
74091dd4
CR
556
557 /* The rest of the loop body deals with declare -[aAlinrtux] name [name...]
558 where each NAME can be an assignment statement. */
559
560 subscript_start = (char *)NULL; /* used below */
ccc6cda3 561#if defined (ARRAY_VARS)
74091dd4 562 /* Determine whether we are creating or assigning an array variable */
a0c0a00f 563 var_exists = array_exists = creating_array = 0;
f73dda09 564 compound_array_assign = simple_array_assign = 0;
a0c0a00f 565 array_subscript_assignment = 0;
74091dd4 566 if (t = strchr (name, '[')) /* ] */
ccc6cda3 567 {
a0c0a00f
CR
568 /* If offset != 0 we have already validated any array reference
569 because assignment() calls skipsubscript() */
570 if (offset == 0 && valid_array_reference (name, 0) == 0)
89a92869
CR
571 {
572 sh_invalidid (name);
573 assign_error++;
574 NEXT_VARIABLE ();
575 }
f73dda09 576 subscript_start = t;
ccc6cda3 577 *t = '\0';
a0c0a00f
CR
578 making_array_special = 1; /* XXX - should this check offset? */
579 array_subscript_assignment = offset != 0;
ccc6cda3
JA
580 }
581 else
582 making_array_special = 0;
583#endif
0628567a 584
74091dd4
CR
585 /* Ensure the argument is a valid, well-formed shell identifier. */
586 if (legal_identifier (name) == 0)
726f6388 587 {
7117c2d2 588 sh_invalidid (name);
ccc6cda3 589 assign_error++;
726f6388
JA
590 NEXT_VARIABLE ();
591 }
592
593 /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
594 inside of a function. This means we should make local variables,
595 not global ones. */
596
7117c2d2
JA
597 /* XXX - this has consequences when we're making a local copy of a
598 variable that was in the temporary environment. Watch out
599 for this. */
ac50fbac 600 refvar = (SHELL_VAR *)NULL;
74091dd4 601 if (variable_context && mkglobal == 0)
ccc6cda3 602 {
74091dd4
CR
603 /* We don't check newname for validity here. We should not have an
604 invalid name assigned as the value of a nameref, but this could
605 cause problems. */
606 newname = declare_transform_name (name, flags_on, flags_off);
d233b485 607
ccc6cda3 608#if defined (ARRAY_VARS)
d233b485
CR
609 /* Pass 1 as second argument to make_local_{assoc,array}_variable
610 return an existing {array,assoc} variable to be flagged as an
611 error below. */
3185942a 612 if (flags_on & att_assoc)
8868edaf 613 var = make_local_assoc_variable (newname, MKLOC_ARRAYOK|inherit_flag);
3185942a 614 else if ((flags_on & att_array) || making_array_special)
8868edaf 615 var = make_local_array_variable (newname, MKLOC_ASSOCOK|inherit_flag);
ccc6cda3
JA
616 else
617#endif
a0c0a00f
CR
618 if (offset == 0 && (flags_on & att_nameref))
619 {
620 /* First look for refvar at current scope */
621 refvar = find_variable_last_nameref (name, 1);
a0c0a00f
CR
622 /* VARIABLE_CONTEXT != 0, so we are attempting to create or modify
623 the attributes for a local variable at the same scope. If we've
624 used a reference from a previous context to resolve VAR, we
625 want to throw REFVAR and VAR away and create a new local var. */
626 if (refvar && refvar->context != variable_context)
627 {
628 refvar = 0;
8868edaf 629 var = make_local_variable (name, inherit_flag);
a0c0a00f
CR
630 }
631 else if (refvar && refvar->context == variable_context)
632 var = refvar;
633 /* Maybe we just want to create a new local variable */
74091dd4 634 else if ((var = find_variable (name)) == 0 || var->context != variable_context)
8868edaf 635 var = make_local_variable (name, inherit_flag);
a0c0a00f
CR
636 /* otherwise we have a var at the right context */
637 }
638 else
74091dd4 639 /* XXX - check name for validity here with valid_nameref_value? */
8868edaf 640 var = make_local_variable ((flags_on & att_nameref) ? name : newname, inherit_flag); /* sets att_invisible for new vars */
d233b485 641
bb70624e
JA
642 if (var == 0)
643 {
644 any_failed++;
645 NEXT_VARIABLE ();
646 }
a0c0a00f
CR
647 if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
648 {
649 sh_readonly (name);
650 any_failed++;
651 NEXT_VARIABLE ();
652 }
ccc6cda3 653 }
7117c2d2
JA
654 else
655 var = (SHELL_VAR *)NULL;
726f6388 656
74091dd4 657 /* VAR is non-null if we just created or fetched a local variable. */
726f6388 658
74091dd4
CR
659 /* Here's what ksh93 seems to do as of the 2012 version: if we are
660 using declare -n to modify the value of an existing nameref
661 variable, don't follow the nameref chain at all and just search
662 for a nameref at the current context. If we have a nameref,
663 modify its value (changing which variable it references). */
664 if (var == 0 && (flags_on & att_nameref))
665 {
666 /* See if we are trying to modify an existing nameref variable,
667 but don't follow the nameref chain. */
668 var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
669 if (var && nameref_p (var) == 0)
670 var = 0;
671 }
726f6388 672
74091dd4
CR
673 /* However, if we're turning off the nameref attribute on an existing
674 nameref variable, we first follow the nameref chain to the end,
675 modify the value of the variable this nameref variable references
676 if there is an assignment statement argument,
677 *CHANGING ITS VALUE AS A SIDE EFFECT*, then turn off the nameref
678 flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
679 else if (var == 0 && (flags_off & att_nameref))
726f6388 680 {
74091dd4
CR
681 /* See if we are trying to modify an existing nameref variable */
682 refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
683 if (refvar && nameref_p (refvar) == 0)
684 refvar = 0;
685 /* If the nameref is readonly but doesn't have a value, ksh93
686 allows the nameref attribute to be removed. If it's readonly
687 and has a value, even if the value doesn't reference an
688 existing variable, we disallow the modification */
689 if (refvar && nameref_cell (refvar) && readonly_p (refvar))
726f6388 690 {
74091dd4
CR
691 sh_readonly (name);
692 any_failed++;
726f6388
JA
693 NEXT_VARIABLE ();
694 }
74091dd4
CR
695
696 /* If all we're doing is turning off the nameref attribute, don't
697 bother with VAR at all, whether it exists or not. Just turn it
698 off and go on. */
699 if (refvar && flags_on == 0 && offset == 0 && flags_off == att_nameref)
ac50fbac 700 {
74091dd4
CR
701 VUNSETATTR (refvar, att_nameref);
702 NEXT_VARIABLE ();
ac50fbac 703 }
d233b485 704
74091dd4
CR
705 if (refvar)
706 var = declare_find_variable (nameref_cell (refvar), mkglobal, 0);
707 }
a0c0a00f 708#if defined (ARRAY_VARS)
74091dd4
CR
709 /* If we have an array assignment to a nameref, remove the nameref
710 attribute and go on. This handles
711 declare -n xref[=value]; declare [-a] xref[1]=one */
712 else if (var == 0 && offset && array_subscript_assignment)
713 {
714 var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
715 if (var && nameref_p (var))
a0c0a00f 716 {
74091dd4
CR
717 internal_warning (_("%s: removing nameref attribute"), name);
718 FREE (value_cell (var)); /* XXX - bash-4.3 compat */
719 var_setvalue (var, (char *)NULL);
720 VUNSETATTR (var, att_nameref);
a0c0a00f 721 }
74091dd4 722 }
a0c0a00f
CR
723#endif
724
74091dd4
CR
725 /* See if we are trying to set flags or value (or create) for an
726 existing nameref that points to a non-existent variable: e.g.,
a0c0a00f
CR
727 declare -n foo=bar
728 unset foo # unsets bar
729 declare -i foo
730 foo=4+4
74091dd4
CR
731 declare -p foo
732 */
733 if (var == 0 && (mkglobal || flags_on || flags_off || offset))
734 {
735 refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
736 if (refvar && nameref_p (refvar) == 0)
737 refvar = 0;
738 if (refvar)
739 var = declare_find_variable (nameref_cell (refvar), mkglobal, 0);
740 if (refvar && var == 0)
a0c0a00f 741 {
74091dd4
CR
742 /* I'm not sure subscript_start is ever non-null here. In any
743 event, build a new name from the nameref value, including any
744 subscript, and add the [[+]=value] if offset != 0 */
745 newname = declare_build_newname (nameref_cell (refvar), subscript_start, offset, value, aflags);
746 free (name);
747 name = newname;
a0c0a00f 748
74091dd4
CR
749 if (offset)
750 {
751 offset = assignment (name, 0);
752 /* If offset was valid previously, but substituting the
753 the nameref value results in an invalid assignment,
754 throw an invalid identifier error */
755 if (offset == 0)
a0c0a00f 756 {
74091dd4
CR
757 sh_invalidid (name);
758 assign_error++;
759 NEXT_VARIABLE ();
a0c0a00f 760 }
74091dd4
CR
761 name[(aflags & ASS_APPEND) ? offset - 1 : offset] = '\0';
762 value = name + offset + 1;
763 }
d233b485 764
74091dd4
CR
765 /* OK, let's turn off the nameref attribute.
766 Now everything else applies to VAR. */
767 if (flags_off & att_nameref)
768 VUNSETATTR (refvar, att_nameref);
d233b485 769
74091dd4
CR
770 goto restart_new_var_name;
771 /* NOTREACHED */
a0c0a00f 772 }
74091dd4
CR
773 }
774 if (var == 0)
775 var = declare_find_variable (name, mkglobal, chklocal);
726f6388 776
74091dd4
CR
777 /* At this point, VAR is the variable we are dealing with; REFVAR is the
778 nameref variable we dereferenced to get VAR, if any. */
a0c0a00f 779#if defined (ARRAY_VARS)
74091dd4
CR
780 var_exists = var != 0;
781 array_exists = var && (array_p (var) || assoc_p (var));
782 creating_array = flags_on & (att_array|att_assoc);
a0c0a00f
CR
783#endif
784
74091dd4
CR
785 /* Make a new variable if we need to. */
786 if (var == 0)
787 {
ccc6cda3 788#if defined (ARRAY_VARS)
74091dd4
CR
789 if (flags_on & att_assoc)
790 var = make_new_assoc_variable (name);
791 else if ((flags_on & att_array) || making_array_special)
792 var = make_new_array_variable (name);
793 else
a0c0a00f 794#endif
74091dd4 795 var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
726f6388 796
74091dd4 797 if (var == 0)
726f6388 798 {
74091dd4 799 /* Has to appear in brackets */
726f6388
JA
800 NEXT_VARIABLE ();
801 }
74091dd4
CR
802 if (offset == 0)
803 VSETATTR (var, att_invisible);
804 created_var = 1;
805 }
726f6388 806
74091dd4
CR
807 /* Nameref variable error checking. */
808
809 /* Can't take an existing array variable and make it a nameref */
810 else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
811 {
812 builtin_error (_("%s: reference variable cannot be an array"), name);
813 any_failed++;
814 NEXT_VARIABLE ();
815 }
816 /* Can't have an invalid identifier as nameref value */
817 else if (nameref_p (var) && (flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0 && offset && valid_nameref_value (value, 1) == 0)
818 {
819 builtin_error (_("`%s': invalid variable name for name reference"), value);
820 any_failed++;
821 NEXT_VARIABLE ();
822 }
823 /* Can't make an existing variable a nameref if its current value is not
824 a valid identifier. Check of offset is to allow an assignment to a
825 nameref var as part of the declare word to override existing value. */
826 else if ((flags_on & att_nameref) && nameref_p (var) == 0 && var_isset (var) && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0)
827 {
828 builtin_error (_("`%s': invalid variable name for name reference"), value_cell (var));
829 any_failed++;
830 NEXT_VARIABLE ();
831 }
832 /* Can't make an existing readonly variable a nameref. */
833 else if ((flags_on & att_nameref) && readonly_p (var))
834 {
835 sh_readonly (name);
836 any_failed++;
837 NEXT_VARIABLE ();
838 }
839
840 /* Readonly variable error checking. */
841
842 /* Cannot use declare +r to turn off readonly attribute. */
843 if (readonly_p (var) && (flags_off & att_readonly))
844 {
845 sh_readonly (name_cell (var));
846 any_failed++;
847 NEXT_VARIABLE ();
848 }
849 /* Cannot use declare to assign value to readonly or noassign variable. */
850 else if ((readonly_p (var) || noassign_p (var)) && offset)
851 {
852 if (readonly_p (var))
853 sh_readonly (name);
854 assign_error++;
855 NEXT_VARIABLE ();
856 }
ccc6cda3
JA
857
858#if defined (ARRAY_VARS)
74091dd4 859 /* Array variable error checking. */
ccc6cda3 860
74091dd4
CR
861 /* Cannot use declare +a name or declare +A name to remove an array variable. */
862 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
863 {
864 builtin_error (_("%s: cannot destroy array variables in this way"), name);
865 any_failed++;
866 NEXT_VARIABLE ();
867 }
868 else if ((flags_on & att_array) && assoc_p (var))
869 {
870 builtin_error (_("%s: cannot convert associative to indexed array"), name);
871 any_failed++;
872 NEXT_VARIABLE ();
873 }
874 else if ((flags_on & att_assoc) && array_p (var))
875 {
876 builtin_error (_("%s: cannot convert indexed to associative array"), name);
877 any_failed++;
878 NEXT_VARIABLE ();
879 }
ccc6cda3 880
74091dd4
CR
881 /* make declare A[2]=foo as similar to A[2]=foo as possible if A is
882 already an array or assoc variable. */
883 if (array_subscript_assignment && array_exists && creating_array == 0)
884 simple_array_assign = 1;
885 else if ((making_array_special || creating_array || array_exists) && offset)
886 {
887 int vlen;
888 vlen = STRLEN (value);
889/*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/
3185942a 890
74091dd4
CR
891 if (shell_compatibility_level > 43 && (wflags & W_COMPASSIGN) == 0 &&
892 value[0] == '(' && value[vlen-1] == ')')
3185942a 893 {
74091dd4
CR
894 /* I don't believe this warning is printed any more.
895 We use creating_array to allow things like
896 declare -a foo$bar='(abc)'
897 to work as they have in the past. */
898 if (array_exists == 0 && creating_array == 0)
899 internal_warning (_("%s: quoted compound array assignment deprecated"), list->word->word);
900 compound_array_assign = array_exists || creating_array;
901 simple_array_assign = making_array_special;
3185942a 902 }
74091dd4
CR
903 else if (value[0] == '(' && value[vlen-1] == ')' && (shell_compatibility_level < 44 || (wflags & W_COMPASSIGN)))
904 compound_array_assign = 1;
905 else
906 simple_array_assign = 1;
907 }
908
909 /* declare -A name[[n]] makes name an associative array variable. */
910 if (flags_on & att_assoc)
911 {
912 if (assoc_p (var) == 0)
913 var = convert_var_to_assoc (var);
914 }
915 /* declare -a name[[n]] or declare name[n] makes NAME an indexed
916 array variable. */
917 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
918 var = convert_var_to_array (var);
ccc6cda3
JA
919#endif /* ARRAY_VARS */
920
74091dd4
CR
921 /* ksh93 compat: turning on nameref attribute turns off -ilu */
922 if (flags_on & att_nameref)
923 VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
924
925 /* XXX - we note that we are turning on nameref attribute and defer
926 setting it until the assignment has been made so we don't do an
927 inadvertent nameref lookup. Might have to do the same thing for
928 flags_off&att_nameref. */
929 /* XXX - ksh93 makes it an error to set a readonly nameref variable
930 using a single typeset command. */
931 onref = (flags_on & att_nameref);
932 flags_on &= ~att_nameref;
ac50fbac 933#if defined (ARRAY_VARS)
74091dd4
CR
934 /* I don't believe this condition ever tests true, but array variables
935 may not be namerefs */
936 if (array_p (var) || assoc_p (var) || compound_array_assign || simple_array_assign)
937 onref = 0;
ac50fbac
CR
938#endif
939
74091dd4
CR
940 /* ksh93 seems to do this */
941 offref = (flags_off & att_nameref);
942 flags_off &= ~att_nameref;
ac50fbac 943
74091dd4
CR
944 VSETATTR (var, flags_on);
945 VUNSETATTR (var, flags_off);
726f6388 946
ccc6cda3 947#if defined (ARRAY_VARS)
74091dd4
CR
948 if (offset && compound_array_assign)
949 assign_array_var_from_string (var, value, aflags|ASS_FORCE);
950 else if (simple_array_assign && subscript_start)
951 {
952 int local_aflags;
953
954 /* declare [-aA] name[N]=value */
955 *subscript_start = '['; /* ] */
956 /* XXX - problem here with appending */
957 local_aflags = aflags&ASS_APPEND;
958 local_aflags |= assoc_noexpand ? ASS_NOEXPAND : 0;
959 local_aflags |= ASS_ALLOWALLSUB; /* allow declare a[@]=at */
960 var = assign_array_element (name, value, local_aflags, (array_eltstate_t *)0); /* XXX - not aflags */
961 *subscript_start = '\0';
962 if (var == 0) /* some kind of assignment error */
0001803f 963 {
74091dd4
CR
964 assign_error++;
965 flags_on |= onref;
966 flags_off |= offref;
967 NEXT_VARIABLE ();
0001803f 968 }
74091dd4
CR
969 }
970 else if (simple_array_assign)
971 {
972 /* let bind_{array,assoc}_variable take care of this. */
973 if (assoc_p (var))
974 bind_assoc_variable (var, name, savestring ("0"), value, aflags|ASS_FORCE);
ccc6cda3 975 else
74091dd4
CR
976 bind_array_variable (name, 0, value, aflags|ASS_FORCE);
977 }
978 else
ccc6cda3 979#endif
74091dd4
CR
980 /* XXX - no ASS_FORCE here */
981 /* bind_variable_value duplicates the essential internals of bind_variable() */
982 if (offset)
983 {
984 if (onref || nameref_p (var))
985 aflags |= ASS_NAMEREF;
986 v = bind_variable_value (var, value, aflags);
987 if (v == 0 && (onref || nameref_p (var)))
ac50fbac 988 {
74091dd4
CR
989 if (valid_nameref_value (value, 1) == 0)
990 sh_invalidid (value);
991 assign_error++;
992 /* XXX - unset this variable? or leave it as normal var? */
993 if (created_var)
994 delete_var (name_cell (var), mkglobal ? global_variables : shell_variables);
995 flags_on |= onref; /* undo change from above */
996 flags_off |= offref;
997 NEXT_VARIABLE ();
ac50fbac 998 }
74091dd4 999 }
cce855bc 1000
74091dd4
CR
1001 /* If we found this variable in the temporary environment, as with
1002 `var=value declare -x var', make sure it is treated identically
1003 to `var=value export var'. Do the same for `declare -r' and
1004 `readonly'. Preserve the attributes, except for att_tempvar. */
1005 /* XXX -- should this create a variable in the global scope, or
1006 modify the local variable flags? ksh93 has it modify the
1007 global scope.
1008 Need to handle case like in set_var_attribute where a temporary
1009 variable is in the same table as the function local vars. */
1010 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
1011 {
1012 SHELL_VAR *tv;
1013 char *tvalue;
7117c2d2 1014
74091dd4
CR
1015 tv = find_tempenv_variable (name_cell (var));
1016 if (tv)
1017 {
1018 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
1019 tv = bind_variable (name_cell (var), tvalue, 0);
7117c2d2
JA
1020 if (tv)
1021 {
74091dd4
CR
1022 tv->attributes |= var->attributes & ~att_tempvar;
1023 if (tv->context > 0)
1024 VSETATTR (tv, att_propagate);
7117c2d2 1025 }
74091dd4 1026 free (tvalue);
cce855bc 1027 }
74091dd4 1028 VSETATTR (var, att_propagate);
726f6388
JA
1029 }
1030
ac50fbac 1031 /* Turn on nameref attribute we deferred above. */
ac50fbac
CR
1032 VSETATTR (var, onref);
1033 flags_on |= onref;
1034 VUNSETATTR (var, offref);
1035 flags_off |= offref;
74091dd4 1036
a0c0a00f
CR
1037 /* Yuck. ksh93 compatibility. XXX - need to investigate more but
1038 definitely happens when turning off nameref attribute on nameref
1039 (see comments above). Under no circumstances allow this to turn
1040 off readonly attribute on readonly nameref variable. */
ac50fbac 1041 if (refvar)
a0c0a00f
CR
1042 {
1043 if (flags_off & att_readonly)
1044 flags_off &= ~att_readonly;
1045 VUNSETATTR (refvar, flags_off);
1046 }
ac50fbac 1047
726f6388
JA
1048 stupidly_hack_special_variables (name);
1049
1050 NEXT_VARIABLE ();
1051 }
ccc6cda3
JA
1052
1053 return (assign_error ? EX_BADASSIGN
1054 : ((any_failed == 0) ? EXECUTION_SUCCESS
1055 : EXECUTION_FAILURE));
726f6388 1056}