No specific user configuration
[platform/upstream/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, *v;
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             var = make_local_variable (name);   /* sets att_invisible for new vars */
379           if (var == 0)
380             {
381               any_failed++;
382               NEXT_VARIABLE ();
383             }
384         }
385       else
386         var = (SHELL_VAR *)NULL;
387
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         {
396           if (offset)   /* declare -f [-rix] foo=bar */
397             {
398               builtin_error (_("cannot use `-f' to make functions"));
399               free (name);
400               return (EXECUTION_FAILURE);
401             }
402           else          /* declare -f [-rx] name [name...] */
403             {
404               var = find_function (name);
405
406               if (var)
407                 {
408                   if (readonly_p (var) && (flags_off & att_readonly))
409                     {
410                       builtin_error (_("%s: readonly function"), name);
411                       any_failed++;
412                       NEXT_VARIABLE ();
413                     }
414
415                   /* declare -[Ff] name [name...] */
416                   if (flags_on == att_function && flags_off == 0)
417                     {
418 #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
431                                      : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
432                           printf ("%s\n", t);
433                           any_failed = sh_chkwrite (any_failed);
434                         }
435                     }
436                   else          /* declare -[fF] -[rx] name [name...] */
437                     {
438                       VSETATTR (var, flags_on);
439                       VUNSETATTR (var, flags_off);
440                     }
441                 }
442               else
443                 any_failed++;
444               NEXT_VARIABLE ();
445             }
446         }
447       else              /* declare -[aAirx] name [name...] */
448         {
449           /* Non-null if we just created or fetched a local variable. */
450           /* 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         
477           if (var == 0)
478             var = mkglobal ? find_global_variable (name) : find_variable (name);
479
480           if (var == 0)
481             {
482 #if defined (ARRAY_VARS)
483               if (flags_on & att_assoc)
484                 {
485                   var = make_new_assoc_variable (name);
486                   if (offset == 0)
487                     VSETATTR (var, att_invisible);
488                 }
489               else if ((flags_on & att_array) || making_array_special)
490                 {
491                   var = make_new_array_variable (name);
492                   if (offset == 0)
493                     VSETATTR (var, att_invisible);
494                 }
495               else
496 #endif
497
498               if (offset)
499                 var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
500               else
501                 {
502                   var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
503                   VSETATTR (var, att_invisible);
504                 }
505             }
506           /* 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             }
518
519           /* Cannot use declare +r to turn off readonly attribute. */ 
520           if (readonly_p (var) && (flags_off & att_readonly))
521             {
522               sh_readonly (name);
523               any_failed++;
524               NEXT_VARIABLE ();
525             }
526
527           /* Cannot use declare to assign value to readonly or noassign
528              variable. */
529           if ((readonly_p (var) || noassign_p (var)) && offset)
530             {
531               if (readonly_p (var))
532                 sh_readonly (name);
533               assign_error++;
534               NEXT_VARIABLE ();
535             }
536
537 #if defined (ARRAY_VARS)
538           if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
539             {
540               int vlen;
541               vlen = STRLEN (value);
542
543               if (value[0] == '(' && value[vlen-1] == ')')
544                 compound_array_assign = 1;
545               else
546                 simple_array_assign = 1;
547             }
548
549           /* 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)))
552             {
553               builtin_error (_("%s: cannot destroy array variables in this way"), name);
554               any_failed++;
555               NEXT_VARIABLE ();
556             }
557
558           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. */
579           else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
580             var = convert_var_to_array (var);
581 #endif /* ARRAY_VARS */
582
583           /* 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
602           VSETATTR (var, flags_on);
603           VUNSETATTR (var, flags_off);
604
605 #if defined (ARRAY_VARS)
606           if (offset && compound_array_assign)
607             assign_array_var_from_string (var, value, aflags);
608           else if (simple_array_assign && subscript_start)
609             {
610               /* declare [-aA] name[N]=value */
611               *subscript_start = '[';   /* ] */
612               var = assign_array_element (name, value, 0);      /* XXX - not aflags */
613               *subscript_start = '\0';
614               if (var == 0)     /* some kind of assignment error */
615                 {
616                   assign_error++;
617                   flags_on |= onref;
618                   flags_off |= offref;
619                   NEXT_VARIABLE ();
620                 }
621             }
622           else if (simple_array_assign)
623             {
624               /* let bind_{array,assoc}_variable take care of this. */
625               if (assoc_p (var))
626                 bind_assoc_variable (var, name, savestring ("0"), value, aflags);
627               else
628                 bind_array_variable (name, 0, value, aflags);
629             }
630           else
631 #endif
632           /* bind_variable_value duplicates the essential internals of
633              bind_variable() */
634           if (offset)
635             {
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             }
648
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. */
653           /* 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. */
658           if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
659             {
660               SHELL_VAR *tv;
661               char *tvalue;
662
663               tv = find_tempenv_variable (var->name);
664               if (tv)
665                 {
666                   tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
667                   tv = bind_variable (var->name, tvalue, 0);
668                   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);
674             }
675         }
676
677       /* 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
688       stupidly_hack_special_variables (name);
689
690       NEXT_VARIABLE ();
691     }
692
693   return (assign_error ? EX_BADASSIGN
694                        : ((any_failed == 0) ? EXECUTION_SUCCESS
695                                             : EXECUTION_FAILURE));
696 }