Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / builtins / declare.def
index 4d94fac..9931f5e 100644 (file)
@@ -1,59 +1,67 @@
 This file is declare.def, from which is created declare.c.
 It implements the builtins "declare" and "local" in Bash.
 
 This file is declare.def, from which is created declare.c.
 It implements the builtins "declare" and "local" in Bash.
 
-Copyright (C) 1987-2004 Free Software Foundation, Inc.
+Copyright (C) 1987-2009 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
 
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 
 $PRODUCES declare.c
 
 $BUILTIN declare
 $FUNCTION declare_builtin
 
 $PRODUCES declare.c
 
 $BUILTIN declare
 $FUNCTION declare_builtin
-$SHORT_DOC declare [-afFirtx] [-p] [name[=value] ...]
-Declare variables and/or give them attributes.  If no NAMEs are
-given, then display the values of variables instead.  The -p option
-will display the attributes and values of each NAME.
+$SHORT_DOC declare [-aAfFilrtux] [-p] [name[=value] ...]
+Set variable values and attributes.
 
 
-The flags are:
+Declare variables and give them attributes.  If no NAMEs are given,
+display the attributes and values of all variables.
 
 
-  -a   to make NAMEs arrays (if supported)
-  -f   to select from among function names only
-  -F   to display function names (and line number and source file name if
-       debugging) without definitions 
+Options:
+  -f   restrict action or display to function names and definitions
+  -F   restrict display to function names only (plus line number and
+       source file when debugging)
+  -p   display the attributes and value of each NAME
+
+Options which set attributes:
+  -a   to make NAMEs indexed arrays (if supported)
+  -A   to make NAMEs associative arrays (if supported)
   -i   to make NAMEs have the `integer' attribute
   -i   to make NAMEs have the `integer' attribute
+  -l   to convert NAMEs to lower case on assignment
   -r   to make NAMEs readonly
   -t   to make NAMEs have the `trace' attribute
   -r   to make NAMEs readonly
   -t   to make NAMEs have the `trace' attribute
+  -u   to convert NAMEs to upper case on assignment
   -x   to make NAMEs export
 
   -x   to make NAMEs export
 
+Using `+' instead of `-' turns off the given attribute.
+
 Variables with the integer attribute have arithmetic evaluation (see
 Variables with the integer attribute have arithmetic evaluation (see
-`let') done when the variable is assigned to.
+the `let' command) performed when the variable is assigned a value.
 
 
-When displaying values of variables, -f displays a function's name
-and definition.  The -F option restricts the display to function
-name only.
+When used in a function, `declare' makes NAMEs local, as with the `local'
+command.
 
 
-Using `+' instead of `-' turns off the given attribute instead.  When
-used in a function, makes NAMEs local, as with the `local' command.
+Exit Status:
+Returns success unless an invalid option is supplied or an error occurs.
 $END
 
 $BUILTIN typeset
 $FUNCTION declare_builtin
 $END
 
 $BUILTIN typeset
 $FUNCTION declare_builtin
-$SHORT_DOC typeset [-afFirtx] [-p] name[=value] ...
-Obsolete.  See `declare'.
+$SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ...
+Set variable values and attributes.
+
+Obsolete.  See `help declare'.
 $END
 
 #include <config.h>
 $END
 
 #include <config.h>
@@ -90,10 +98,18 @@ declare_builtin (list)
 
 $BUILTIN local
 $FUNCTION local_builtin
 
 $BUILTIN local
 $FUNCTION local_builtin
-$SHORT_DOC local name[=value] ...
-Create a local variable called NAME, and give it VALUE.  LOCAL
-can only be used within a function; it makes the variable NAME
-have a visible scope restricted to that function and its children.
+$SHORT_DOC local [option] name[=value] ...
+Define local variables.
+
+Create a local variable called NAME, and give it VALUE.  OPTION can
+be any option accepted by `declare'.
+
+Local variables can only be used within a function; they are visible
+only to the function where they are defined and its children.
+
+Exit Status:
+Returns success unless an invalid option is supplied, an error occurs,
+or the shell is not executing a function.
 $END
 int
 local_builtin (list)
 $END
 int
 local_builtin (list)
@@ -109,9 +125,9 @@ local_builtin (list)
 }
 
 #if defined (ARRAY_VARS)
 }
 
 #if defined (ARRAY_VARS)
-#  define DECLARE_OPTS "+afiprtxF"
+#  define DECLARE_OPTS "+acfilprtuxAF"
 #else
 #else
-#  define DECLARE_OPTS "+fiprtxF"
+#  define DECLARE_OPTS "+cfilprtuxF"
 #endif
 
 /* The workhorse function. */
 #endif
 
 /* The workhorse function. */
@@ -120,7 +136,8 @@ declare_internal (list, local_var)
      register WORD_LIST *list;
      int local_var;
 {
      register WORD_LIST *list;
      int local_var;
 {
-  int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs, opt;
+  int flags_on, flags_off, *flags;
+  int any_failed, assign_error, pflag, nodefs, opt;
   char *t, *subscript_start;
   SHELL_VAR *var;
   FUNCTION_DEF *shell_fn;
   char *t, *subscript_start;
   SHELL_VAR *var;
   FUNCTION_DEF *shell_fn;
@@ -136,8 +153,19 @@ declare_internal (list, local_var)
        case 'a':
 #if defined (ARRAY_VARS)
          *flags |= att_array;
        case 'a':
 #if defined (ARRAY_VARS)
          *flags |= att_array;
+         break;
+#else
+         builtin_usage ();
+         return (EX_USAGE);
 #endif
 #endif
+       case 'A':
+#if defined (ARRAY_VARS)
+         *flags |= att_assoc;
          break;
          break;
+#else
+         builtin_usage ();
+         return (EX_USAGE);
+#endif
        case 'p':
          if (local_var == 0)
            pflag++;
        case 'p':
          if (local_var == 0)
            pflag++;
@@ -162,6 +190,25 @@ declare_internal (list, local_var)
          *flags |= att_exported;
          array_needs_making = 1;
          break;
          *flags |= att_exported;
          array_needs_making = 1;
          break;
+#if defined (CASEMOD_ATTRS)
+#  if defined (CASEMOD_CAPCASE)
+        case 'c':
+         *flags |= att_capcase;
+         if (flags == &flags_on)
+           flags_off |= att_uppercase|att_lowercase;
+         break;
+#  endif
+       case 'l':
+         *flags |= att_lowercase;
+         if (flags == &flags_on)
+           flags_off |= att_capcase|att_uppercase;
+         break;
+       case 'u':
+         *flags |= att_uppercase;
+         if (flags == &flags_on)
+           flags_off |= att_capcase|att_lowercase;
+         break;
+#endif /* CASEMOD_ATTRS */
        default:
          builtin_usage ();
          return (EX_USAGE);
        default:
          builtin_usage ();
          return (EX_USAGE);
@@ -172,7 +219,7 @@ declare_internal (list, local_var)
 
   /* If there are no more arguments left, then we just want to show
      some variables. */
 
   /* If there are no more arguments left, then we just want to show
      some variables. */
-  if (list == 0)       /* declare -[afFirtx] */
+  if (list == 0)       /* declare -[aAfFirtx] */
     {
       /* Show local variables defined at this context level if this is
         the `local' builtin. */
     {
       /* Show local variables defined at this context level if this is
         the `local' builtin. */
@@ -191,19 +238,17 @@ declare_internal (list, local_var)
              free (vlist);
            }
        }
              free (vlist);
            }
        }
+      else if (pflag && (flags_on == 0 || flags_on == att_function))
+       show_all_var_attributes (flags_on == 0, nodefs);
+      else if (flags_on == 0)
+       return (set_builtin ((WORD_LIST *)NULL));
       else
       else
-       {
-         if (flags_on == 0)
-           set_builtin ((WORD_LIST *)NULL);
-         else
-           set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
-       }
+       set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
 
 
-      fflush (stdout);
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
     }
 
-  if (pflag)   /* declare -p [-afFirtx] name [name...] */
+  if (pflag)   /* declare -p [-aAfFirtx] name [name...] */
     {
       for (any_failed = 0; list; list = list->next)
        {
     {
       for (any_failed = 0; list; list = list->next)
        {
@@ -214,13 +259,13 @@ declare_internal (list, local_var)
              any_failed++;
            }
        }
              any_failed++;
            }
        }
-      return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+      return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
     }
 
 #define NEXT_VARIABLE() free (name); list = list->next; continue
 
   /* There are arguments left, so we are making variables. */
     }
 
 #define NEXT_VARIABLE() free (name); list = list->next; continue
 
   /* There are arguments left, so we are making variables. */
-  while (list)         /* declare [-afFirx] name [name ...] */
+  while (list)         /* declare [-aAfFirx] name [name ...] */
     {
       char *value, *name;
       int offset, aflags;
     {
       char *value, *name;
       int offset, aflags;
@@ -232,7 +277,7 @@ declare_internal (list, local_var)
       offset = assignment (name, 0);
       aflags = 0;
 
       offset = assignment (name, 0);
       aflags = 0;
 
-      if (offset)      /* declare [-afFirx] name=value */
+      if (offset)      /* declare [-aAfFirx] name=value */
        {
          name[offset] = '\0';
          value = name + offset + 1;
        {
          name[offset] = '\0';
          value = name + offset + 1;
@@ -279,7 +324,9 @@ declare_internal (list, local_var)
       if (variable_context && ((flags_on & att_function) == 0))
        {
 #if defined (ARRAY_VARS)
       if (variable_context && ((flags_on & att_function) == 0))
        {
 #if defined (ARRAY_VARS)
-         if ((flags_on & att_array) || making_array_special)
+         if (flags_on & att_assoc)
+           var = make_local_assoc_variable (name);
+         else if ((flags_on & att_array) || making_array_special)
            var = make_local_array_variable (name);
          else
 #endif
            var = make_local_array_variable (name);
          else
 #endif
@@ -336,8 +383,9 @@ declare_internal (list, local_var)
 #endif /* DEBUGGER */
                        {       
                          t = nodefs ? var->name
 #endif /* DEBUGGER */
                        {       
                          t = nodefs ? var->name
-                                    : named_function_string (name, function_cell (var), 1);
+                                    : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
                          printf ("%s\n", t);
                          printf ("%s\n", t);
+                         any_failed = sh_chkwrite (any_failed);
                        }
                    }
                  else          /* declare -[fF] -[rx] name [name...] */
                        }
                    }
                  else          /* declare -[fF] -[rx] name [name...] */
@@ -351,7 +399,7 @@ declare_internal (list, local_var)
              NEXT_VARIABLE ();
            }
        }
              NEXT_VARIABLE ();
            }
        }
-      else             /* declare -[airx] name [name...] */
+      else             /* declare -[aAirx] name [name...] */
        {
          /* Non-null if we just created or fetched a local variable. */
          if (var == 0)
        {
          /* Non-null if we just created or fetched a local variable. */
          if (var == 0)
@@ -360,11 +408,20 @@ declare_internal (list, local_var)
          if (var == 0)
            {
 #if defined (ARRAY_VARS)
          if (var == 0)
            {
 #if defined (ARRAY_VARS)
-             if ((flags_on & att_array) || making_array_special)
+             if (flags_on & att_assoc)
+               var = make_new_assoc_variable (name);
+             else if ((flags_on & att_array) || making_array_special)
                var = make_new_array_variable (name);
              else
 #endif
                var = make_new_array_variable (name);
              else
 #endif
-             var = bind_variable (name, "", 0);
+
+             if (offset)
+               var = bind_variable (name, "", 0);
+             else
+               {
+                 var = bind_variable (name, (char *)NULL, 0);
+                 VSETATTR (var, att_invisible);
+               }
            }
 
          /* Cannot use declare +r to turn off readonly attribute. */ 
            }
 
          /* Cannot use declare +r to turn off readonly attribute. */ 
@@ -386,30 +443,48 @@ declare_internal (list, local_var)
            }
 
 #if defined (ARRAY_VARS)
            }
 
 #if defined (ARRAY_VARS)
-         if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset)
+         if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
            {
              int vlen;
              vlen = STRLEN (value);
            {
              int vlen;
              vlen = STRLEN (value);
-#if 0
-             if (value[0] == '(' && strchr (value, ')'))
-#else
+
              if (value[0] == '(' && value[vlen-1] == ')')
              if (value[0] == '(' && value[vlen-1] == ')')
-#endif
                compound_array_assign = 1;
              else
                simple_array_assign = 1;
            }
 
                compound_array_assign = 1;
              else
                simple_array_assign = 1;
            }
 
-         /* Cannot use declare +a name to remove an array variable. */
-         if ((flags_off & att_array) && array_p (var))
+         /* Cannot use declare +a name or declare +A name to remove an
+            array variable. */
+         if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
            {
              builtin_error (_("%s: cannot destroy array variables in this way"), name);
              any_failed++;
              NEXT_VARIABLE ();
            }
 
            {
              builtin_error (_("%s: cannot destroy array variables in this way"), name);
              any_failed++;
              NEXT_VARIABLE ();
            }
 
-         /* declare -a name makes name an array variable. */
-         if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
+         if ((flags_on & att_array) && assoc_p (var))
+           {
+             builtin_error (_("%s: cannot convert associative to indexed array"), name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+         if ((flags_on & att_assoc) && array_p (var))
+           {
+             builtin_error (_("%s: cannot convert indexed to associative array"), name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+
+         /* declare -A name[[n]] makes name an associative array variable. */
+         if (flags_on & att_assoc)
+           {
+             if (assoc_p (var) == 0)
+               var = convert_var_to_assoc (var);
+           }
+         /* declare -a name[[n]] or declare name[n] makes name an indexed
+            array variable. */
+         else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
            var = convert_var_to_array (var);
 #endif /* ARRAY_VARS */
 
            var = convert_var_to_array (var);
 #endif /* ARRAY_VARS */