]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/declare.def
bash-4.3-beta overlay
[thirdparty/bash.git] / builtins / declare.def
1 This file is declare.def, from which is created declare.c.
2 It implements the builtins "declare" and "local" in Bash.
3
4 Copyright (C) 1987-2012 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES declare.c
22
23 $BUILTIN declare
24 $FUNCTION declare_builtin
25 $SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
26 Set variable values and attributes.
27
28 Declare variables and give them attributes. If no NAMEs are given,
29 display the attributes and values of all variables.
30
31 Options:
32 -f restrict action or display to function names and definitions
33 -F restrict display to function names only (plus line number and
34 source file when debugging)
35 -g create global variables when used in a shell function; otherwise
36 ignored
37 -p display the attributes and value of each NAME
38
39 Options which set attributes:
40 -a to make NAMEs indexed arrays (if supported)
41 -A to make NAMEs associative arrays (if supported)
42 -i to make NAMEs have the `integer' attribute
43 -l to convert NAMEs to lower case on assignment
44 -n make NAME a reference to the variable named by its value
45 -r to make NAMEs readonly
46 -t to make NAMEs have the `trace' attribute
47 -u to convert NAMEs to upper case on assignment
48 -x to make NAMEs export
49
50 Using `+' instead of `-' turns off the given attribute.
51
52 Variables with the integer attribute have arithmetic evaluation (see
53 the `let' command) performed when the variable is assigned a value.
54
55 When used in a function, `declare' makes NAMEs local, as with the `local'
56 command. The `-g' option suppresses this behavior.
57
58 Exit Status:
59 Returns success unless an invalid option is supplied or a variable
60 assignment error occurs.
61 $END
62
63 $BUILTIN typeset
64 $FUNCTION declare_builtin
65 $SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
66 Set variable values and attributes.
67
68 Obsolete. See `help declare'.
69 $END
70
71 #include <config.h>
72
73 #if defined (HAVE_UNISTD_H)
74 # ifdef _MINIX
75 # include <sys/types.h>
76 # endif
77 # include <unistd.h>
78 #endif
79
80 #include <stdio.h>
81
82 #include "../bashansi.h"
83 #include "../bashintl.h"
84
85 #include "../shell.h"
86 #include "common.h"
87 #include "builtext.h"
88 #include "bashgetopt.h"
89
90 extern int array_needs_making;
91 extern int posixly_correct;
92
93 static int declare_internal __P((register WORD_LIST *, int));
94
95 /* Declare or change variable attributes. */
96 int
97 declare_builtin (list)
98 register WORD_LIST *list;
99 {
100 return (declare_internal (list, 0));
101 }
102
103 $BUILTIN local
104 $FUNCTION local_builtin
105 $SHORT_DOC local [option] name[=value] ...
106 Define local variables.
107
108 Create a local variable called NAME, and give it VALUE. OPTION can
109 be any option accepted by `declare'.
110
111 Local variables can only be used within a function; they are visible
112 only to the function where they are defined and its children.
113
114 Exit Status:
115 Returns success unless an invalid option is supplied, a variable
116 assignment error occurs, or the shell is not executing a function.
117 $END
118 int
119 local_builtin (list)
120 register WORD_LIST *list;
121 {
122 if (variable_context)
123 return (declare_internal (list, 1));
124 else
125 {
126 builtin_error (_("can only be used in a function"));
127 return (EXECUTION_FAILURE);
128 }
129 }
130
131 #if defined (ARRAY_VARS)
132 # define DECLARE_OPTS "+acfgilnprtuxAF"
133 #else
134 # define DECLARE_OPTS "+cfgilnprtuxF"
135 #endif
136
137 /* The workhorse function. */
138 static int
139 declare_internal (list, local_var)
140 register WORD_LIST *list;
141 int local_var;
142 {
143 int flags_on, flags_off, *flags;
144 int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
145 char *t, *subscript_start;
146 SHELL_VAR *var, *refvar;
147 FUNCTION_DEF *shell_fn;
148
149 flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
150 refvar = (SHELL_VAR *)NULL;
151 reset_internal_getopt ();
152 while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
153 {
154 flags = list_opttype == '+' ? &flags_off : &flags_on;
155
156 switch (opt)
157 {
158 case 'a':
159 #if defined (ARRAY_VARS)
160 *flags |= att_array;
161 break;
162 #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
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;
185 case 'g':
186 if (flags == &flags_on)
187 mkglobal = 1;
188 break;
189 case 'i':
190 *flags |= att_integer;
191 break;
192 case 'n':
193 *flags |= att_nameref;
194 break;
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;
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 */
224 default:
225 builtin_usage ();
226 return (EX_USAGE);
227 }
228 }
229
230 list = loptend;
231
232 /* If there are no more arguments left, then we just want to show
233 some variables. */
234 if (list == 0) /* declare -[aAfFirtx] */
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
243 vlist = all_local_variables ();
244
245 if (vlist)
246 {
247 for (i = 0; vlist[i]; i++)
248 print_assignment (vlist[i]);
249
250 free (vlist);
251 }
252 }
253 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));
257 else
258 set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
259
260 return (sh_chkwrite (EXECUTION_SUCCESS));
261 }
262
263 if (pflag) /* declare -p [-aAfFirtx] name [name...] */
264 {
265 for (any_failed = 0; list; list = list->next)
266 {
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);
271 if (pflag)
272 {
273 sh_notfound (list->word->word);
274 any_failed++;
275 }
276 }
277 return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
278 }
279
280 #define NEXT_VARIABLE() free (name); list = list->next; continue
281
282 /* There are arguments left, so we are making variables. */
283 while (list) /* declare [-aAfFirx] name [name ...] */
284 {
285 char *value, *name;
286 int offset, aflags;
287 #if defined (ARRAY_VARS)
288 int making_array_special, compound_array_assign, simple_array_assign;
289 #endif
290
291 name = savestring (list->word->word);
292 offset = assignment (name, 0);
293 aflags = 0;
294
295 if (offset) /* declare [-aAfFirx] name=value */
296 {
297 name[offset] = '\0';
298 value = name + offset + 1;
299 if (name[offset - 1] == '+')
300 {
301 aflags |= ASS_APPEND;
302 name[offset - 1] = '\0';
303 }
304 }
305 else
306 value = "";
307
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 {
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
330 #if defined (ARRAY_VARS)
331 compound_array_assign = simple_array_assign = 0;
332 subscript_start = (char *)NULL;
333 if (t = strchr (name, '[')) /* ] */
334 {
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 }
342 subscript_start = t;
343 *t = '\0';
344 making_array_special = 1;
345 }
346 else
347 making_array_special = 0;
348 #endif
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)
355 {
356 sh_invalidid (name);
357 assign_error++;
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
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. */
368 refvar = (SHELL_VAR *)NULL;
369 if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
370 {
371 #if defined (ARRAY_VARS)
372 if (flags_on & att_assoc)
373 var = make_local_assoc_variable (name);
374 else if ((flags_on & att_array) || making_array_special)
375 var = make_local_array_variable (name, making_array_special);
376 else
377 #endif
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);
403 if (var == 0)
404 {
405 any_failed++;
406 NEXT_VARIABLE ();
407 }
408 }
409 else
410 var = (SHELL_VAR *)NULL;
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 {
420 if (offset) /* declare -f [-rix] foo=bar */
421 {
422 builtin_error (_("cannot use `-f' to make functions"));
423 free (name);
424 return (EXECUTION_FAILURE);
425 }
426 else /* declare -f [-rx] name [name...] */
427 {
428 var = find_function (name);
429
430 if (var)
431 {
432 if (readonly_p (var) && (flags_off & att_readonly))
433 {
434 builtin_error (_("%s: readonly function"), name);
435 any_failed++;
436 NEXT_VARIABLE ();
437 }
438
439 /* declare -[Ff] name [name...] */
440 if (flags_on == att_function && flags_off == 0)
441 {
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
455 : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
456 printf ("%s\n", t);
457 any_failed = sh_chkwrite (any_failed);
458 }
459 }
460 else /* declare -[fF] -[rx] name [name...] */
461 {
462 VSETATTR (var, flags_on);
463 VUNSETATTR (var, flags_off);
464 }
465 }
466 else
467 any_failed++;
468 NEXT_VARIABLE ();
469 }
470 }
471 else /* declare -[aAirx] name [name...] */
472 {
473 /* Non-null if we just created or fetched a local variable. */
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
501 if (var == 0)
502 var = mkglobal ? find_global_variable (name) : find_variable (name);
503
504 if (var == 0)
505 {
506 #if defined (ARRAY_VARS)
507 if (flags_on & att_assoc)
508 {
509 var = make_new_assoc_variable (name);
510 if (offset == 0)
511 VSETATTR (var, att_invisible);
512 }
513 else if ((flags_on & att_array) || making_array_special)
514 {
515 var = make_new_array_variable (name);
516 if (offset == 0)
517 VSETATTR (var, att_invisible);
518 }
519 else
520 #endif
521
522 if (offset)
523 var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
524 else
525 {
526 var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
527 VSETATTR (var, att_invisible);
528 }
529 }
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 }
537
538 /* Cannot use declare +r to turn off readonly attribute. */
539 if (readonly_p (var) && (flags_off & att_readonly))
540 {
541 sh_readonly (name);
542 any_failed++;
543 NEXT_VARIABLE ();
544 }
545
546 /* Cannot use declare to assign value to readonly or noassign
547 variable. */
548 if ((readonly_p (var) || noassign_p (var)) && offset)
549 {
550 if (readonly_p (var))
551 sh_readonly (name);
552 assign_error++;
553 NEXT_VARIABLE ();
554 }
555
556 #if defined (ARRAY_VARS)
557 if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
558 {
559 int vlen;
560 vlen = STRLEN (value);
561
562 if (value[0] == '(' && value[vlen-1] == ')')
563 compound_array_assign = 1;
564 else
565 simple_array_assign = 1;
566 }
567
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)))
571 {
572 builtin_error (_("%s: cannot destroy array variables in this way"), name);
573 any_failed++;
574 NEXT_VARIABLE ();
575 }
576
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. */
598 else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
599 var = convert_var_to_array (var);
600 #endif /* ARRAY_VARS */
601
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;
610 #if defined (ARRAY_VARS)
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 */
615 #endif
616
617 /* ksh93 seems to do this */
618 offref = (flags_off & att_nameref);
619 flags_off &= ~att_nameref;
620
621 VSETATTR (var, flags_on);
622 VUNSETATTR (var, flags_off);
623
624 #if defined (ARRAY_VARS)
625 if (offset && compound_array_assign)
626 assign_array_var_from_string (var, value, aflags);
627 else if (simple_array_assign && subscript_start)
628 {
629 /* declare [-aA] name[N]=value */
630 *subscript_start = '['; /* ] */
631 var = assign_array_element (name, value, 0); /* XXX - not aflags */
632 *subscript_start = '\0';
633 if (var == 0) /* some kind of assignment error */
634 {
635 assign_error++;
636 flags_on |= onref;
637 flags_off |= offref;
638 NEXT_VARIABLE ();
639 }
640 }
641 else if (simple_array_assign)
642 {
643 /* let bind_{array,assoc}_variable take care of this. */
644 if (assoc_p (var))
645 bind_assoc_variable (var, name, savestring ("0"), value, aflags);
646 else
647 bind_array_variable (name, 0, value, aflags);
648 }
649 else
650 #endif
651 /* bind_variable_value duplicates the essential internals of
652 bind_variable() */
653 if (offset)
654 bind_variable_value (var, value, aflags);
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. */
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. */
665 if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
666 {
667 SHELL_VAR *tv;
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 ("");
674 tv = bind_variable (var->name, tvalue, 0);
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);
681 }
682 }
683
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
695 stupidly_hack_special_variables (name);
696
697 NEXT_VARIABLE ();
698 }
699
700 return (assign_error ? EX_BADASSIGN
701 : ((any_failed == 0) ? EXECUTION_SUCCESS
702 : EXECUTION_FAILURE));
703 }