blob: a634e7ce82f6390578a6f1946c4313fa182716ff [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is declare.def, from which is created declare.c.
2It implements the builtins "declare" and "local" in Bash.
3
Chet Rameyac50fba2014-02-26 09:36:43 -05004Copyright (C) 1987-2012 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES declare.c
22
23$BUILTIN declare
24$FUNCTION declare_builtin
Chet Rameyac50fba2014-02-26 09:36:43 -050025$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
Jari Aalto31859422009-01-12 13:36:28 +000026Set variable values and attributes.
Jari Aalto726f6381996-08-26 18:22:31 +000027
Jari Aalto31859422009-01-12 13:36:28 +000028Declare variables and give them attributes. If no NAMEs are given,
29display the attributes and values of all variables.
Jari Aalto726f6381996-08-26 18:22:31 +000030
Jari Aalto31859422009-01-12 13:36:28 +000031Options:
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)
Chet Ramey495aee42011-11-22 19:11:26 -050035 -g create global variables when used in a shell function; otherwise
36 ignored
Jari Aalto31859422009-01-12 13:36:28 +000037 -p display the attributes and value of each NAME
38
39Options which set attributes:
40 -a to make NAMEs indexed arrays (if supported)
41 -A to make NAMEs associative arrays (if supported)
Jari Aalto7117c2d2002-07-17 14:10:11 +000042 -i to make NAMEs have the `integer' attribute
Jari Aalto31859422009-01-12 13:36:28 +000043 -l to convert NAMEs to lower case on assignment
Chet Rameyac50fba2014-02-26 09:36:43 -050044 -n make NAME a reference to the variable named by its value
Jari Aaltoccc6cda1996-12-23 17:02:34 +000045 -r to make NAMEs readonly
Jari Aalto7117c2d2002-07-17 14:10:11 +000046 -t to make NAMEs have the `trace' attribute
Jari Aalto31859422009-01-12 13:36:28 +000047 -u to convert NAMEs to upper case on assignment
Jari Aaltoccc6cda1996-12-23 17:02:34 +000048 -x to make NAMEs export
Jari Aalto726f6381996-08-26 18:22:31 +000049
Jari Aalto31859422009-01-12 13:36:28 +000050Using `+' instead of `-' turns off the given attribute.
51
Jari Aalto726f6381996-08-26 18:22:31 +000052Variables with the integer attribute have arithmetic evaluation (see
Jari Aalto31859422009-01-12 13:36:28 +000053the `let' command) performed when the variable is assigned a value.
Jari Aalto726f6381996-08-26 18:22:31 +000054
Jari Aalto31859422009-01-12 13:36:28 +000055When used in a function, `declare' makes NAMEs local, as with the `local'
Chet Ramey495aee42011-11-22 19:11:26 -050056command. The `-g' option suppresses this behavior.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000057
Jari Aalto31859422009-01-12 13:36:28 +000058Exit Status:
Chet Rameyac50fba2014-02-26 09:36:43 -050059Returns success unless an invalid option is supplied or a variable
60assignment error occurs.
Jari Aalto726f6381996-08-26 18:22:31 +000061$END
62
63$BUILTIN typeset
64$FUNCTION declare_builtin
Chet Ramey495aee42011-11-22 19:11:26 -050065$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
Jari Aalto31859422009-01-12 13:36:28 +000066Set variable values and attributes.
67
68Obsolete. See `help declare'.
Jari Aalto726f6381996-08-26 18:22:31 +000069$END
70
Jari Aaltoccc6cda1996-12-23 17:02:34 +000071#include <config.h>
72
73#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000074# ifdef _MINIX
75# include <sys/types.h>
76# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000077# include <unistd.h>
78#endif
79
Jari Aalto726f6381996-08-26 18:22:31 +000080#include <stdio.h>
81
Jari Aaltoccc6cda1996-12-23 17:02:34 +000082#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000083#include "../bashintl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000084
85#include "../shell.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000086#include "common.h"
87#include "builtext.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000088#include "bashgetopt.h"
Jari Aalto726f6381996-08-26 18:22:31 +000089
Jari Aaltof73dda02001-11-13 17:56:06 +000090extern int array_needs_making;
Jari Aalto06285672006-10-10 14:15:34 +000091extern int posixly_correct;
Jari Aalto726f6381996-08-26 18:22:31 +000092
Jari Aaltof73dda02001-11-13 17:56:06 +000093static int declare_internal __P((register WORD_LIST *, int));
Jari Aalto726f6381996-08-26 18:22:31 +000094
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
Jari Aalto31859422009-01-12 13:36:28 +0000105$SHORT_DOC local [option] name[=value] ...
106Define local variables.
107
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.
113
114Exit Status:
Chet Rameyac50fba2014-02-26 09:36:43 -0500115Returns success unless an invalid option is supplied, a variable
116assignment error occurs, or the shell is not executing a function.
Jari Aalto726f6381996-08-26 18:22:31 +0000117$END
118int
119local_builtin (list)
120 register WORD_LIST *list;
121{
122 if (variable_context)
123 return (declare_internal (list, 1));
124 else
125 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000126 builtin_error (_("can only be used in a function"));
Jari Aalto726f6381996-08-26 18:22:31 +0000127 return (EXECUTION_FAILURE);
128 }
129}
130
Jari Aalto7117c2d2002-07-17 14:10:11 +0000131#if defined (ARRAY_VARS)
Chet Rameyac50fba2014-02-26 09:36:43 -0500132# define DECLARE_OPTS "+acfgilnprtuxAF"
Jari Aalto7117c2d2002-07-17 14:10:11 +0000133#else
Chet Rameyac50fba2014-02-26 09:36:43 -0500134# define DECLARE_OPTS "+cfgilnprtuxF"
Jari Aalto7117c2d2002-07-17 14:10:11 +0000135#endif
136
Jari Aalto726f6381996-08-26 18:22:31 +0000137/* The workhorse function. */
138static int
139declare_internal (list, local_var)
140 register WORD_LIST *list;
141 int local_var;
142{
Jari Aalto31859422009-01-12 13:36:28 +0000143 int flags_on, flags_off, *flags;
Chet Rameyac50fba2014-02-26 09:36:43 -0500144 int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
Jari Aaltof73dda02001-11-13 17:56:06 +0000145 char *t, *subscript_start;
Chet Rameyac50fba2014-02-26 09:36:43 -0500146 SHELL_VAR *var, *refvar, *v;
Jari Aaltob80f6442004-07-27 13:29:18 +0000147 FUNCTION_DEF *shell_fn;
Jari Aalto726f6381996-08-26 18:22:31 +0000148
Chet Ramey495aee42011-11-22 19:11:26 -0500149 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
Chet Rameyac50fba2014-02-26 09:36:43 -0500150 refvar = (SHELL_VAR *)NULL;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000151 reset_internal_getopt ();
152 while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
Jari Aalto726f6381996-08-26 18:22:31 +0000153 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000154 flags = list_opttype == '+' ? &flags_off : &flags_on;
155
156 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +0000157 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000158 case 'a':
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000159#if defined (ARRAY_VARS)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000160 *flags |= att_array;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000161 break;
Jari Aalto31859422009-01-12 13:36:28 +0000162#else
163 builtin_usage ();
164 return (EX_USAGE);
165#endif
166 case 'A':
167#if defined (ARRAY_VARS)
168 *flags |= att_assoc;
169 break;
170#else
171 builtin_usage ();
172 return (EX_USAGE);
173#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000174 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;
Chet Ramey495aee42011-11-22 19:11:26 -0500185 case 'g':
186 if (flags == &flags_on)
187 mkglobal = 1;
188 break;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000189 case 'i':
190 *flags |= att_integer;
191 break;
Chet Rameyac50fba2014-02-26 09:36:43 -0500192 case 'n':
193 *flags |= att_nameref;
194 break;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000195 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;
Jari Aalto31859422009-01-12 13:36:28 +0000205#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 */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000224 default:
225 builtin_usage ();
226 return (EX_USAGE);
Jari Aalto726f6381996-08-26 18:22:31 +0000227 }
Jari Aalto726f6381996-08-26 18:22:31 +0000228 }
229
Jari Aalto7117c2d2002-07-17 14:10:11 +0000230 list = loptend;
231
Jari Aalto726f6381996-08-26 18:22:31 +0000232 /* If there are no more arguments left, then we just want to show
233 some variables. */
Jari Aalto31859422009-01-12 13:36:28 +0000234 if (list == 0) /* declare -[aAfFirtx] */
Jari Aalto726f6381996-08-26 18:22:31 +0000235 {
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
Jari Aalto7117c2d2002-07-17 14:10:11 +0000243 vlist = all_local_variables ();
Jari Aalto726f6381996-08-26 18:22:31 +0000244
245 if (vlist)
246 {
247 for (i = 0; vlist[i]; i++)
248 print_assignment (vlist[i]);
249
250 free (vlist);
251 }
252 }
Jari Aalto31859422009-01-12 13:36:28 +0000253 else if (pflag && (flags_on == 0 || flags_on == att_function))
254 show_all_var_attributes (flags_on == 0, nodefs);
255 else if (flags_on == 0)
256 return (set_builtin ((WORD_LIST *)NULL));
Jari Aalto726f6381996-08-26 18:22:31 +0000257 else
Jari Aalto31859422009-01-12 13:36:28 +0000258 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
Jari Aalto726f6381996-08-26 18:22:31 +0000259
Jari Aalto31859422009-01-12 13:36:28 +0000260 return (sh_chkwrite (EXECUTION_SUCCESS));
Jari Aalto726f6381996-08-26 18:22:31 +0000261 }
262
Jari Aalto31859422009-01-12 13:36:28 +0000263 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000264 {
265 for (any_failed = 0; list; list = list->next)
266 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500267 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);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000271 if (pflag)
272 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000273 sh_notfound (list->word->word);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000274 any_failed++;
275 }
276 }
Jari Aalto31859422009-01-12 13:36:28 +0000277 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000278 }
279
Jari Aalto726f6381996-08-26 18:22:31 +0000280#define NEXT_VARIABLE() free (name); list = list->next; continue
281
282 /* There are arguments left, so we are making variables. */
Jari Aalto31859422009-01-12 13:36:28 +0000283 while (list) /* declare [-aAfFirx] name [name ...] */
Jari Aalto726f6381996-08-26 18:22:31 +0000284 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000285 char *value, *name;
Jari Aalto95732b42005-12-07 14:08:12 +0000286 int offset, aflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000287#if defined (ARRAY_VARS)
Jari Aaltof73dda02001-11-13 17:56:06 +0000288 int making_array_special, compound_array_assign, simple_array_assign;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000289#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000290
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000291 name = savestring (list->word->word);
Jari Aaltob80f6442004-07-27 13:29:18 +0000292 offset = assignment (name, 0);
Jari Aalto95732b42005-12-07 14:08:12 +0000293 aflags = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000294
Jari Aalto31859422009-01-12 13:36:28 +0000295 if (offset) /* declare [-aAfFirx] name=value */
Jari Aalto726f6381996-08-26 18:22:31 +0000296 {
297 name[offset] = '\0';
298 value = name + offset + 1;
Jari Aalto95732b42005-12-07 14:08:12 +0000299 if (name[offset - 1] == '+')
300 {
301 aflags |= ASS_APPEND;
302 name[offset - 1] = '\0';
303 }
Jari Aalto726f6381996-08-26 18:22:31 +0000304 }
305 else
306 value = "";
307
Chet Rameyac50fba2014-02-26 09:36:43 -0500308 /* 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 {
312#if defined (ARRAY_VARIABLES)
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 }
319 else
320#endif
321 /* disallow self references at global scope */
322 if (STREQ (name, value) && variable_context == 0)
323 {
324 builtin_error (_("%s: nameref variable self references not allowed"), name);
325 assign_error++;
326 NEXT_VARIABLE ();
327 }
328 }
329
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000330#if defined (ARRAY_VARS)
Jari Aaltof73dda02001-11-13 17:56:06 +0000331 compound_array_assign = simple_array_assign = 0;
332 subscript_start = (char *)NULL;
333 if (t = strchr (name, '[')) /* ] */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000334 {
Chet Ramey89a92862011-11-21 20:49:12 -0500335 /* 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 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000342 subscript_start = t;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000343 *t = '\0';
344 making_array_special = 1;
345 }
346 else
347 making_array_special = 0;
348#endif
Jari Aalto06285672006-10-10 14:15:34 +0000349
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)
Jari Aalto726f6381996-08-26 18:22:31 +0000355 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000356 sh_invalidid (name);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000357 assign_error++;
Jari Aalto726f6381996-08-26 18:22:31 +0000358 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
Jari Aalto7117c2d2002-07-17 14:10:11 +0000365 /* 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. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500368 refvar = (SHELL_VAR *)NULL;
Chet Ramey495aee42011-11-22 19:11:26 -0500369 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000370 {
371#if defined (ARRAY_VARS)
Jari Aalto31859422009-01-12 13:36:28 +0000372 if (flags_on & att_assoc)
373 var = make_local_assoc_variable (name);
374 else if ((flags_on & att_array) || making_array_special)
Chet Rameyac50fba2014-02-26 09:36:43 -0500375 var = make_local_array_variable (name, making_array_special);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000376 else
377#endif
Chet Rameyac50fba2014-02-26 09:36:43 -0500378 var = make_local_variable (name); /* sets att_invisible for new vars */
Jari Aaltobb706242000-03-17 21:46:59 +0000379 if (var == 0)
380 {
381 any_failed++;
382 NEXT_VARIABLE ();
383 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000384 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000385 else
386 var = (SHELL_VAR *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000387
388 /* If we are declaring a function, then complain about it in some way.
389 We don't let people make functions by saying `typeset -f foo=bar'. */
390
391 /* There should be a way, however, to let people look at a particular
392 function definition by saying `typeset -f foo'. */
393
394 if (flags_on & att_function)
395 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000396 if (offset) /* declare -f [-rix] foo=bar */
Jari Aalto726f6381996-08-26 18:22:31 +0000397 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000398 builtin_error (_("cannot use `-f' to make functions"));
Jari Aaltod166f041997-06-05 14:59:13 +0000399 free (name);
Jari Aalto726f6381996-08-26 18:22:31 +0000400 return (EXECUTION_FAILURE);
401 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000402 else /* declare -f [-rx] name [name...] */
Jari Aalto726f6381996-08-26 18:22:31 +0000403 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000404 var = find_function (name);
Jari Aalto726f6381996-08-26 18:22:31 +0000405
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000406 if (var)
Jari Aalto726f6381996-08-26 18:22:31 +0000407 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000408 if (readonly_p (var) && (flags_off & att_readonly))
Jari Aalto726f6381996-08-26 18:22:31 +0000409 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000410 builtin_error (_("%s: readonly function"), name);
Jari Aalto726f6381996-08-26 18:22:31 +0000411 any_failed++;
412 NEXT_VARIABLE ();
413 }
414
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000415 /* declare -[Ff] name [name...] */
Jari Aalto726f6381996-08-26 18:22:31 +0000416 if (flags_on == att_function && flags_off == 0)
417 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000418#if defined (DEBUGGER)
419 if (nodefs && debugging_mode)
420 {
421 shell_fn = find_function_def (var->name);
422 if (shell_fn)
423 printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
424 else
425 printf ("%s\n", var->name);
426 }
427 else
428#endif /* DEBUGGER */
429 {
430 t = nodefs ? var->name
Jari Aalto31859422009-01-12 13:36:28 +0000431 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
Jari Aaltob80f6442004-07-27 13:29:18 +0000432 printf ("%s\n", t);
Jari Aalto31859422009-01-12 13:36:28 +0000433 any_failed = sh_chkwrite (any_failed);
Jari Aaltob80f6442004-07-27 13:29:18 +0000434 }
Jari Aalto726f6381996-08-26 18:22:31 +0000435 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000436 else /* declare -[fF] -[rx] name [name...] */
Jari Aalto726f6381996-08-26 18:22:31 +0000437 {
Jari Aaltobb706242000-03-17 21:46:59 +0000438 VSETATTR (var, flags_on);
439 VUNSETATTR (var, flags_off);
Jari Aalto726f6381996-08-26 18:22:31 +0000440 }
441 }
442 else
443 any_failed++;
444 NEXT_VARIABLE ();
445 }
446 }
Jari Aalto31859422009-01-12 13:36:28 +0000447 else /* declare -[aAirx] name [name...] */
Jari Aalto726f6381996-08-26 18:22:31 +0000448 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000449 /* Non-null if we just created or fetched a local variable. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500450 /* Here's what ksh93 seems to do. If we are modifying an existing
451 nameref variable, we don't follow the nameref chain past the last
452 nameref, and we set the nameref variable's value so future
453 references to that variable will return the value of the variable
454 we're assigning right now. */
455 if (var == 0 && (flags_on & att_nameref))
456 {
457 /* See if we are trying to modify an existing nameref variable */
458 var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
459 if (var && nameref_p (var) == 0)
460 var = 0;
461 }
462 /* However, if we're turning off the nameref attribute on an existing
463 nameref variable, we first follow the nameref chain to the end,
464 modify the value of the variable this nameref variable references,
465 *CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
466 flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
467 else if (var == 0 && (flags_off & att_nameref))
468 {
469 /* See if we are trying to modify an existing nameref variable */
470 refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
471 if (refvar && nameref_p (refvar) == 0)
472 refvar = 0;
473 if (refvar)
474 var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
475 }
476
Jari Aalto7117c2d2002-07-17 14:10:11 +0000477 if (var == 0)
Chet Ramey495aee42011-11-22 19:11:26 -0500478 var = mkglobal ? find_global_variable (name) : find_variable (name);
Jari Aalto726f6381996-08-26 18:22:31 +0000479
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000480 if (var == 0)
481 {
482#if defined (ARRAY_VARS)
Jari Aalto31859422009-01-12 13:36:28 +0000483 if (flags_on & att_assoc)
Chet Rameyac50fba2014-02-26 09:36:43 -0500484 {
485 var = make_new_assoc_variable (name);
486 if (offset == 0)
487 VSETATTR (var, att_invisible);
488 }
Jari Aalto31859422009-01-12 13:36:28 +0000489 else if ((flags_on & att_array) || making_array_special)
Chet Rameyac50fba2014-02-26 09:36:43 -0500490 {
491 var = make_new_array_variable (name);
492 if (offset == 0)
493 VSETATTR (var, att_invisible);
494 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000495 else
496#endif
Jari Aalto31859422009-01-12 13:36:28 +0000497
498 if (offset)
Chet Rameyac50fba2014-02-26 09:36:43 -0500499 var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
Jari Aalto31859422009-01-12 13:36:28 +0000500 else
501 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500502 var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
Jari Aalto31859422009-01-12 13:36:28 +0000503 VSETATTR (var, att_invisible);
504 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000505 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500506 /* Can't take an existing array variable and make it a nameref */
507 else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
508 {
509 builtin_error (_("%s: reference variable cannot be an array"), name);
510 assign_error++;
511 NEXT_VARIABLE ();
512 }
513 else if (flags_on & att_nameref)
514 {
515 /* ksh93 compat: turning on nameref attribute turns off -ilu */
516 VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
517 }
Jari Aalto726f6381996-08-26 18:22:31 +0000518
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000519 /* Cannot use declare +r to turn off readonly attribute. */
Jari Aalto726f6381996-08-26 18:22:31 +0000520 if (readonly_p (var) && (flags_off & att_readonly))
521 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000522 sh_readonly (name);
Jari Aalto726f6381996-08-26 18:22:31 +0000523 any_failed++;
524 NEXT_VARIABLE ();
525 }
526
Jari Aalto28ef6c32001-04-06 19:14:31 +0000527 /* Cannot use declare to assign value to readonly or noassign
528 variable. */
529 if ((readonly_p (var) || noassign_p (var)) && offset)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000530 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000531 if (readonly_p (var))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000532 sh_readonly (name);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000533 assign_error++;
534 NEXT_VARIABLE ();
535 }
536
537#if defined (ARRAY_VARS)
Jari Aalto31859422009-01-12 13:36:28 +0000538 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000539 {
Jari Aalto95732b42005-12-07 14:08:12 +0000540 int vlen;
541 vlen = STRLEN (value);
Jari Aalto31859422009-01-12 13:36:28 +0000542
Jari Aalto95732b42005-12-07 14:08:12 +0000543 if (value[0] == '(' && value[vlen-1] == ')')
Jari Aaltof73dda02001-11-13 17:56:06 +0000544 compound_array_assign = 1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000545 else
Jari Aaltof73dda02001-11-13 17:56:06 +0000546 simple_array_assign = 1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000547 }
548
Jari Aalto31859422009-01-12 13:36:28 +0000549 /* Cannot use declare +a name or declare +A name to remove an
550 array variable. */
551 if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000552 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000553 builtin_error (_("%s: cannot destroy array variables in this way"), name);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000554 any_failed++;
555 NEXT_VARIABLE ();
556 }
557
Jari Aalto31859422009-01-12 13:36:28 +0000558 if ((flags_on & att_array) && assoc_p (var))
559 {
560 builtin_error (_("%s: cannot convert associative to indexed array"), name);
561 any_failed++;
562 NEXT_VARIABLE ();
563 }
564 if ((flags_on & att_assoc) && array_p (var))
565 {
566 builtin_error (_("%s: cannot convert indexed to associative array"), name);
567 any_failed++;
568 NEXT_VARIABLE ();
569 }
570
571 /* declare -A name[[n]] makes name an associative array variable. */
572 if (flags_on & att_assoc)
573 {
574 if (assoc_p (var) == 0)
575 var = convert_var_to_assoc (var);
576 }
577 /* declare -a name[[n]] or declare name[n] makes name an indexed
578 array variable. */
Chet Ramey89a92862011-11-21 20:49:12 -0500579 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000580 var = convert_var_to_array (var);
581#endif /* ARRAY_VARS */
582
Chet Rameyac50fba2014-02-26 09:36:43 -0500583 /* XXX - we note that we are turning on nameref attribute and defer
584 setting it until the assignment has been made so we don't do an
585 inadvertent nameref lookup. Might have to do the same thing for
586 flags_off&att_nameref. */
587 /* XXX - ksh93 makes it an error to set a readonly nameref variable
588 using a single typeset command. */
589 onref = (flags_on & att_nameref);
590 flags_on &= ~att_nameref;
591#if defined (ARRAY_VARS)
592 if (array_p (var) || assoc_p (var)
593 || (offset && compound_array_assign)
594 || simple_array_assign)
595 onref = 0; /* array variables may not be namerefs */
596#endif
597
598 /* ksh93 seems to do this */
599 offref = (flags_off & att_nameref);
600 flags_off &= ~att_nameref;
601
Jari Aaltobb706242000-03-17 21:46:59 +0000602 VSETATTR (var, flags_on);
603 VUNSETATTR (var, flags_off);
Jari Aalto726f6381996-08-26 18:22:31 +0000604
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000605#if defined (ARRAY_VARS)
Jari Aaltof73dda02001-11-13 17:56:06 +0000606 if (offset && compound_array_assign)
Jari Aalto95732b42005-12-07 14:08:12 +0000607 assign_array_var_from_string (var, value, aflags);
Jari Aaltof73dda02001-11-13 17:56:06 +0000608 else if (simple_array_assign && subscript_start)
609 {
Chet Ramey00018032011-11-21 20:51:19 -0500610 /* declare [-aA] name[N]=value */
Jari Aaltof73dda02001-11-13 17:56:06 +0000611 *subscript_start = '['; /* ] */
Jari Aalto95732b42005-12-07 14:08:12 +0000612 var = assign_array_element (name, value, 0); /* XXX - not aflags */
Jari Aaltof73dda02001-11-13 17:56:06 +0000613 *subscript_start = '\0';
Chet Ramey307dbc72011-11-22 20:03:23 -0500614 if (var == 0) /* some kind of assignment error */
615 {
616 assign_error++;
Chet Rameyac50fba2014-02-26 09:36:43 -0500617 flags_on |= onref;
618 flags_off |= offref;
Chet Ramey307dbc72011-11-22 20:03:23 -0500619 NEXT_VARIABLE ();
620 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000621 }
622 else if (simple_array_assign)
Chet Ramey00018032011-11-21 20:51:19 -0500623 {
624 /* let bind_{array,assoc}_variable take care of this. */
625 if (assoc_p (var))
Chet Ramey30d188c2011-11-21 20:57:16 -0500626 bind_assoc_variable (var, name, savestring ("0"), value, aflags);
Chet Ramey00018032011-11-21 20:51:19 -0500627 else
628 bind_array_variable (name, 0, value, aflags);
629 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000630 else
631#endif
Jari Aaltobb706242000-03-17 21:46:59 +0000632 /* bind_variable_value duplicates the essential internals of
633 bind_variable() */
Jari Aalto726f6381996-08-26 18:22:31 +0000634 if (offset)
Chet Rameyac50fba2014-02-26 09:36:43 -0500635 {
636 if (onref)
637 aflags |= ASS_NAMEREF;
638 v = bind_variable_value (var, value, aflags);
639 if (v == 0 && onref)
640 {
641 sh_invalidid (value);
642 assign_error++;
643 /* XXX - unset this variable? or leave it as normal var? */
644 delete_var (var->name, mkglobal ? global_variables : shell_variables);
645 NEXT_VARIABLE ();
646 }
647 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000648
649 /* If we found this variable in the temporary environment, as with
650 `var=value declare -x var', make sure it is treated identically
651 to `var=value export var'. Do the same for `declare -r' and
652 `readonly'. Preserve the attributes, except for att_tempvar. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000653 /* XXX -- should this create a variable in the global scope, or
654 modify the local variable flags? ksh93 has it modify the
655 global scope.
656 Need to handle case like in set_var_attribute where a temporary
657 variable is in the same table as the function local vars. */
Jari Aaltocce855b1998-04-17 19:52:44 +0000658 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
659 {
660 SHELL_VAR *tv;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000661 char *tvalue;
662
663 tv = find_tempenv_variable (var->name);
664 if (tv)
665 {
666 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
Jari Aalto95732b42005-12-07 14:08:12 +0000667 tv = bind_variable (var->name, tvalue, 0);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000668 tv->attributes |= var->attributes & ~att_tempvar;
669 if (tv->context > 0)
670 VSETATTR (tv, att_propagate);
671 free (tvalue);
672 }
673 VSETATTR (var, att_propagate);
Jari Aaltocce855b1998-04-17 19:52:44 +0000674 }
Jari Aalto726f6381996-08-26 18:22:31 +0000675 }
676
Chet Rameyac50fba2014-02-26 09:36:43 -0500677 /* Turn on nameref attribute we deferred above. */
678 /* XXX - should we turn on the noassign attribute for consistency with
679 ksh93 when we turn on the nameref attribute? */
680 VSETATTR (var, onref);
681 flags_on |= onref;
682 VUNSETATTR (var, offref);
683 flags_off |= offref;
684 /* Yuck. ksh93 compatibility */
685 if (refvar)
686 VUNSETATTR (refvar, flags_off);
687
Jari Aalto726f6381996-08-26 18:22:31 +0000688 stupidly_hack_special_variables (name);
689
690 NEXT_VARIABLE ();
691 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000692
693 return (assign_error ? EX_BADASSIGN
694 : ((any_failed == 0) ? EXECUTION_SUCCESS
695 : EXECUTION_FAILURE));
Jari Aalto726f6381996-08-26 18:22:31 +0000696}