Imported from ../bash-3.1.tar.gz.
[platform/upstream/bash.git] / builtins / set.def
index 8f96017..3bb3270 100644 (file)
@@ -1,7 +1,7 @@
 This file is set.def, from which is created set.c.
 It implements the "set" and "unset" builtins in Bash.
 
 This file is set.def, from which is created set.c.
 It implements the "set" and "unset" builtins in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2004 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.
 
@@ -33,6 +33,7 @@ $PRODUCES set.c
 #include <stdio.h>
 
 #include "../bashansi.h"
 #include <stdio.h>
 
 #include "../bashansi.h"
+#include "../bashintl.h"
 
 #include "../shell.h"
 #include "../flags.h"
 
 #include "../shell.h"
 #include "../flags.h"
@@ -49,7 +50,7 @@ $PRODUCES set.c
 #  include "../bashhist.h"
 #endif
 
 #  include "../bashhist.h"
 #endif
 
-extern int noclobber, posixly_correct, ignoreeof, eof_encountered_limit;
+extern int posixly_correct, ignoreeof, eof_encountered_limit;
 #if defined (HISTORY)
 extern int dont_save_function_defs;
 #endif
 #if defined (HISTORY)
 extern int dont_save_function_defs;
 #endif
@@ -65,8 +66,6 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
     -e  Exit immediately if a command exits with a non-zero status.
     -f  Disable file name generation (globbing).
     -h  Remember the location of commands as they are looked up.
     -e  Exit immediately if a command exits with a non-zero status.
     -f  Disable file name generation (globbing).
     -h  Remember the location of commands as they are looked up.
-    -i  Force the shell to be an "interactive" one.  Interactive shells
-        always read `~/.bashrc' on startup.
     -k  All assignment arguments are placed in the environment for a
         command, not just those that precede the command name.
     -m  Job control is enabled.
     -k  All assignment arguments are placed in the environment for a
         command, not just those that precede the command name.
     -m  Job control is enabled.
@@ -79,6 +78,8 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
             emacs        use an emacs-style line editing interface
 #endif /* READLINE */
             errexit      same as -e
             emacs        use an emacs-style line editing interface
 #endif /* READLINE */
             errexit      same as -e
+            errtrace     same as -E
+            functrace    same as -T
             hashall      same as -h
 #if defined (BANG_HISTORY)
             histexpand   same as -H
             hashall      same as -h
 #if defined (BANG_HISTORY)
             histexpand   same as -H
@@ -99,6 +100,9 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
             nounset      same as -u
             onecmd       same as -t
             physical     same as -P
             nounset      same as -u
             onecmd       same as -t
             physical     same as -P
+            pipefail     the return value of a pipeline is the status of
+                         the last command to exit with a non-zero status,
+                         or zero if no command exited with a non-zero status
             posix        change the behavior of bash where the default
                          operation differs from the 1003.2 standard to
                          match the standard
             posix        change the behavior of bash where the default
                          operation differs from the 1003.2 standard to
                          match the standard
@@ -121,12 +125,16 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
 #endif /* BRACE_EXPANSION */
     -C  If set, disallow existing regular files to be overwritten
         by redirection of output.
 #endif /* BRACE_EXPANSION */
     -C  If set, disallow existing regular files to be overwritten
         by redirection of output.
+    -E  If set, the ERR trap is inherited by shell functions.
 #if defined (BANG_HISTORY)
     -H  Enable ! style history substitution.  This flag is on
 #if defined (BANG_HISTORY)
     -H  Enable ! style history substitution.  This flag is on
-        by default.
+        by default when the shell is interactive.
 #endif /* BANG_HISTORY */
     -P  If set, do not follow symbolic links when executing commands
         such as cd which change the current directory.
 #endif /* BANG_HISTORY */
     -P  If set, do not follow symbolic links when executing commands
         such as cd which change the current directory.
+    -T  If set, the DEBUG trap is inherited by shell functions.
+    -   Assign any remaining arguments to the positional parameters.
+        The -x and -v options are turned off.
 
 Using + rather than - causes these flags to be turned off.  The
 flags can also be used upon invocation of the shell.  The current
 
 Using + rather than - causes these flags to be turned off.  The
 flags can also be used upon invocation of the shell.  The current
@@ -135,6 +143,9 @@ parameters and are assigned, in order, to $1, $2, .. $n.  If no
 ARGs are given, all shell variables are printed.
 $END
 
 ARGs are given, all shell variables are printed.
 $END
 
+typedef int setopt_set_func_t __P((int, char *));
+typedef int setopt_get_func_t __P((char *));
+
 static void print_minus_o_option __P((char *, int, int));
 static void print_all_shell_variables __P((void));
 
 static void print_minus_o_option __P((char *, int, int));
 static void print_all_shell_variables __P((void));
 
@@ -153,70 +164,69 @@ static int bash_set_history __P((int, char *));
 static char *on = "on";
 static char *off = "off";
 
 static char *on = "on";
 static char *off = "off";
 
-/* An a-list used to match long options for set -o to the corresponding
-   option letter. */
+/* A struct used to match long options for set -o to the corresponding
+   option letter or internal variable.  The functions can be called to
+   dynamically generate values. */
 struct {
   char *name;
   int letter;
 struct {
   char *name;
   int letter;
+  int *variable;
+  setopt_set_func_t *set_func;
+  setopt_get_func_t *get_func;
 } o_options[] = {
 } o_options[] = {
-  { "allexport",  'a' },
+  { "allexport",  'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 #if defined (BRACE_EXPANSION)
 #if defined (BRACE_EXPANSION)
-  { "braceexpand",'B' },
+  { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #endif
 #endif
-  { "errexit",   'e' },
-  { "hashall",    'h' },
+#if defined (READLINE)
+  { "emacs",     '\0', (int *)NULL, set_edit_mode, get_edit_mode },
+#endif
+  { "errexit",   'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "errtrace",          'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "functrace",  'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "hashall",    'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (BANG_HISTORY)
 #if defined (BANG_HISTORY)
-  { "histexpand", 'H' },
+  { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #endif /* BANG_HISTORY */
 #endif /* BANG_HISTORY */
-  { "keyword",    'k' },
-  { "monitor",   'm' },
-  { "noclobber",  'C' },
-  { "noexec",    'n' },
-  { "noglob",    'f' },
-#if defined (JOB_CONTROL)
-  { "notify",    'b' },
-#endif /* JOB_CONTROL */
-  { "nounset",   'u' },
-  { "onecmd",    't' },
-  { "physical",   'P' },
-  { "privileged", 'p' },
-  { "verbose",   'v' },
-  { "xtrace",    'x' },
-  {(char *)NULL, 0 },
-};
-
-typedef int setopt_set_func_t __P((int, char *));
-typedef int setopt_get_func_t __P((char *));
-
-struct {
-  char *name;
-  int *variable;
-  setopt_set_func_t *set_func;
-  setopt_get_func_t *get_func;
-} binary_o_options[] = {
 #if defined (HISTORY)
 #if defined (HISTORY)
-  { "history", &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
+  { "history",   '\0', &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
 #endif
 #endif
-  { "ignoreeof", &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
-  { "interactive-comments", &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
+  { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "keyword",    'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "monitor",   'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noclobber",  'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noexec",    'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noglob",    'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (HISTORY)
 #if defined (HISTORY)
-  { "nolog", &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "nolog",     '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 #endif
 #endif
-  { "posix", &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+#if defined (JOB_CONTROL)
+  { "notify",    'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#endif /* JOB_CONTROL */
+  { "nounset",   'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "onecmd",    't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "physical",   'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "pipefail",  '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "posix",     '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+  { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "verbose",   'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (READLINE)
 #if defined (READLINE)
-  { "emacs", (int *)NULL, set_edit_mode, get_edit_mode },
-  { "vi", (int *)NULL, set_edit_mode, get_edit_mode },
+  { "vi",        '\0', (int *)NULL, set_edit_mode, get_edit_mode },
 #endif
 #endif
-  { (char *)NULL, (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }
+  { "xtrace",    'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 };
 
 };
 
+#define N_O_OPTIONS    (sizeof (o_options) / sizeof (o_options[0]))
+
 #define GET_BINARY_O_OPTION_VALUE(i, name) \
 #define GET_BINARY_O_OPTION_VALUE(i, name) \
-  ((binary_o_options[i].get_func) ? (*binary_o_options[i].get_func) (name) \
-                                 : (*binary_o_options[i].variable))
+  ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
+                          : (*o_options[i].variable))
 
 #define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
 
 #define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
-  ((binary_o_options[i].set_func) ? (*binary_o_options[i].set_func) (onoff, name) \
-                                 : (*binary_o_options[i].variable = (onoff == FLAG_ON)))
+  ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
+                          : (*o_options[i].variable = (onoff == FLAG_ON)))
 
 int
 minus_o_option_value (name)
 
 int
 minus_o_option_value (name)
@@ -229,15 +239,15 @@ minus_o_option_value (name)
     {
       if (STREQ (name, o_options[i].name))
        {
     {
       if (STREQ (name, o_options[i].name))
        {
-         on_or_off = find_flag (o_options[i].letter);
-         return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+         if (o_options[i].letter)
+           {
+             on_or_off = find_flag (o_options[i].letter);
+             return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+           }
+         else
+           return (GET_BINARY_O_OPTION_VALUE (i, name));
        }
     }
        }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    {
-      if (STREQ (name, binary_o_options[i].name))
-       return (GET_BINARY_O_OPTION_VALUE (i, name));
-    }
 
   return (-1);
 }
 
   return (-1);
 }
@@ -262,19 +272,23 @@ list_minus_o_opts (mode, reusable)
   register int i;
   int *on_or_off, value;
 
   register int i;
   int *on_or_off, value;
 
-  for (value = i = 0; o_options[i].name; i++)
-    {
-      on_or_off = find_flag (o_options[i].letter);
-      if (on_or_off == FLAG_UNKNOWN)
-       on_or_off = &value;
-      if (mode == -1 || mode == *on_or_off)
-       print_minus_o_option (o_options[i].name, *on_or_off, reusable);
-    }
-  for (i = 0; binary_o_options[i].name; i++)
+  for (i = 0; o_options[i].name; i++)
     {
     {
-      value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name);
-      if (mode == -1 || mode == value)
-       print_minus_o_option (binary_o_options[i].name, value, reusable);
+      if (o_options[i].letter)
+       {
+         value = 0;
+         on_or_off = find_flag (o_options[i].letter);
+         if (on_or_off == FLAG_UNKNOWN)
+           on_or_off = &value;
+         if (mode == -1 || mode == *on_or_off)
+           print_minus_o_option (o_options[i].name, *on_or_off, reusable);
+       }
+      else
+       {
+         value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
+         if (mode == -1 || mode == value)
+           print_minus_o_option (o_options[i].name, value, reusable);
+       }
     }
 }
 
     }
 }
 
@@ -282,16 +296,12 @@ char **
 get_minus_o_opts ()
 {
   char **ret;
 get_minus_o_opts ()
 {
   char **ret;
-  int n, i, ind;
-
-  n = (sizeof (o_options) / sizeof (o_options[0])) +
-      (sizeof (binary_o_options) / sizeof (binary_o_options[0]));
-  ret = alloc_array (n + 1);
-  for (i = ind = 0; o_options[i].name; i++)
-    ret[ind++] = o_options[i].name;
-  for (i = 0; binary_o_options[i].name; i++)
-    ret[ind++] = binary_o_options[i].name;
-  ret[ind] = (char *)NULL;
+  int i;
+
+  ret = strvec_create (N_O_OPTIONS + 1);
+  for (i = 0; o_options[i].name; i++)
+    ret[i] = o_options[i].name;
+  ret[i] = (char *)NULL;
   return ret;
 }
 
   return ret;
 }
 
@@ -303,7 +313,7 @@ set_ignoreeof (on_or_off, option_name)
   ignoreeof = on_or_off == FLAG_ON;
   unbind_variable ("ignoreeof");
   if (ignoreeof)
   ignoreeof = on_or_off == FLAG_ON;
   unbind_variable ("ignoreeof");
   if (ignoreeof)
-    bind_variable ("IGNOREEOF", "10"); 
+    bind_variable ("IGNOREEOF", "10", 0); 
   else
     unbind_variable ("IGNOREEOF");
   sv_ignoreeof ("IGNOREEOF");
   else
     unbind_variable ("IGNOREEOF");
   sv_ignoreeof ("IGNOREEOF");
@@ -319,7 +329,7 @@ set_posix_mode (on_or_off, option_name)
   if (posixly_correct == 0)
     unbind_variable ("POSIXLY_CORRECT");
   else
   if (posixly_correct == 0)
     unbind_variable ("POSIXLY_CORRECT");
   else
-    bind_variable ("POSIXLY_CORRECT", "y");
+    bind_variable ("POSIXLY_CORRECT", "y", 0);
   sv_strict_posix ("POSIXLY_CORRECT");
   return (0);
 }
   sv_strict_posix ("POSIXLY_CORRECT");
   return (0);
 }
@@ -386,37 +396,33 @@ set_minus_o_option (on_or_off, option_name)
      int on_or_off;
      char *option_name;
 {
      int on_or_off;
      char *option_name;
 {
-  int option_char;
   register int i;
 
   register int i;
 
-  for (i = 0; binary_o_options[i].name; i++)
-    {
-      if (STREQ (option_name, binary_o_options[i].name))
-       {
-         SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
-         return (EXECUTION_SUCCESS);
-       }
-    }
-
-  for (i = 0, option_char = -1; o_options[i].name; i++)
+  for (i = 0; o_options[i].name; i++)
     {
       if (STREQ (option_name, o_options[i].name))
        {
     {
       if (STREQ (option_name, o_options[i].name))
        {
-         option_char = o_options[i].letter;
-         break;
+         if (o_options[i].letter == 0)
+           {
+             SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
+             return (EXECUTION_SUCCESS);
+           }
+         else
+           {
+             if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
+               {
+                 sh_invalidoptname (option_name);
+                 return (EXECUTION_FAILURE);
+               }
+             else
+               return (EXECUTION_SUCCESS);
+           }
+
        }
     }
        }
     }
-  if (option_char == -1)
-    {
-      builtin_error ("%s: unknown option name", option_name);
-      return (EXECUTION_FAILURE);
-    }
- if (change_flag (option_char, on_or_off) == FLAG_ERROR)
-    {
-      bad_option (option_name);
-      return (EXECUTION_FAILURE);
-    }
-  return (EXECUTION_SUCCESS);
+
+  sh_invalidoptname (option_name);
+  return (EXECUTION_FAILURE);
 }
 
 static void
 }
 
 static void
@@ -448,38 +454,41 @@ void
 set_shellopts ()
 {
   char *value;
 set_shellopts ()
 {
   char *value;
+  char tflag[N_O_OPTIONS];
   int vsize, i, vptr, *ip, exported;
   SHELL_VAR *v;
 
   for (vsize = i = 0; o_options[i].name; i++)
     {
   int vsize, i, vptr, *ip, exported;
   SHELL_VAR *v;
 
   for (vsize = i = 0; o_options[i].name; i++)
     {
-      ip = find_flag (o_options[i].letter);
-      if (ip && *ip)
-       vsize += strlen (o_options[i].name) + 1;
+      tflag[i] = 0;
+      if (o_options[i].letter)
+       {
+         ip = find_flag (o_options[i].letter);
+         if (ip && *ip)
+           {
+             vsize += strlen (o_options[i].name) + 1;
+             tflag[i] = 1;
+           }
+       }
+      else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
+       {
+         vsize += strlen (o_options[i].name) + 1;
+         tflag[i] = 1;
+       }
     }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
-      vsize += strlen (binary_o_options[i].name) + 1;
 
   value = (char *)xmalloc (vsize + 1);
 
   for (i = vptr = 0; o_options[i].name; i++)
     {
 
   value = (char *)xmalloc (vsize + 1);
 
   for (i = vptr = 0; o_options[i].name; i++)
     {
-      ip = find_flag (o_options[i].letter);
-      if (ip && *ip)
+      if (tflag[i])
        {
          strcpy (value + vptr, o_options[i].name);
          vptr += strlen (o_options[i].name);
          value[vptr++] = ':';
        }
     }
        {
          strcpy (value + vptr, o_options[i].name);
          vptr += strlen (o_options[i].name);
          value[vptr++] = ':';
        }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
-      {
-       strcpy (value + vptr, binary_o_options[i].name);
-       vptr += strlen (binary_o_options[i].name);
-       value[vptr++] = ':';
-      }
+
   if (vptr)
     vptr--;                    /* cut off trailing colon */
   value[vptr] = '\0';
   if (vptr)
     vptr--;                    /* cut off trailing colon */
   value[vptr] = '\0';
@@ -496,7 +505,7 @@ set_shellopts ()
   else
     exported = 0;
 
   else
     exported = 0;
 
-  v = bind_variable ("SHELLOPTS", value);
+  v = bind_variable ("SHELLOPTS", value, 0);
 
   /* Turn the read-only attribute back on, and turn off the export attribute
      if it was set implicitly by mark_modified_vars and SHELLOPTS was not
 
   /* Turn the read-only attribute back on, and turn off the export attribute
      if it was set implicitly by mark_modified_vars and SHELLOPTS was not
@@ -571,6 +580,7 @@ set_builtin (list)
   int on_or_off, flag_name, force_assignment, opts_changed;
   WORD_LIST *l;
   register char *arg;
   int on_or_off, flag_name, force_assignment, opts_changed;
   WORD_LIST *l;
   register char *arg;
+  char s[3];
 
   if (list == 0)
     {
 
   if (list == 0)
     {
@@ -579,34 +589,19 @@ set_builtin (list)
     }
 
   /* Check validity of flag arguments. */
     }
 
   /* Check validity of flag arguments. */
-  if (*list->word->word == '-' || *list->word->word == '+')
+  reset_internal_getopt ();
+  while ((flag_name = internal_getopt (list, optflags)) != -1)
     {
     {
-      for (l = list; l && (arg = l->word->word); l = l->next)
+      switch (flag_name)
        {
        {
-         char c;
-
-         if (arg[0] != '-' && arg[0] != '+')
+         case '?':
+           builtin_usage ();
+           return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
+         default:
            break;
            break;
-
-         /* `-' or `--' signifies end of flag arguments. */
-         if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
-           break;
-
-         while (c = *++arg)
-           {
-             if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
-               {
-                 char s[2];
-                 s[0] = c; s[1] = '\0';
-                 bad_option (s);
-                 if (c == '?')
-                   builtin_usage ();
-                 return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-               }
-           }
        }
     }
        }
     }
-
+    
   /* Do the set command.  While the list consists of words starting with
      '-' or '+' treat them as flags, otherwise, start assigning them to
      $1 ... $n. */
   /* Do the set command.  While the list consists of words starting with
      '-' or '+' treat them as flags, otherwise, start assigning them to
      $1 ... $n. */
@@ -678,11 +673,10 @@ set_builtin (list)
                }
              else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
                {
                }
              else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
                {
-                 char opt[3];
-                 opt[0] = on_or_off;
-                 opt[1] = flag_name;
-                 opt[2] = '\0';
-                 bad_option (opt);
+                 s[0] = on_or_off;
+                 s[1] = flag_name;
+                 s[2] = '\0';
+                 sh_invalidopt (s);
                  builtin_usage ();
                  set_shellopts ();
                  return (EXECUTION_FAILURE);
                  builtin_usage ();
                  set_shellopts ();
                  return (EXECUTION_FAILURE);
@@ -748,7 +742,7 @@ unset_builtin (list)
 
   if (unset_function && unset_variable)
     {
 
   if (unset_function && unset_variable)
     {
-      builtin_error ("cannot simultaneously unset a function and a variable");
+      builtin_error (_("cannot simultaneously unset a function and a variable"));
       return (EXECUTION_FAILURE);
     }
 
       return (EXECUTION_FAILURE);
     }
 
@@ -777,7 +771,7 @@ unset_builtin (list)
         mode when unsetting a function. */
       if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
        {
         mode when unsetting a function. */
       if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
        {
-         builtin_error ("`%s': not a valid identifier", name);
+         sh_invalidid (name);
          NEXT_VARIABLE ();
        }
 
          NEXT_VARIABLE ();
        }
 
@@ -785,14 +779,14 @@ unset_builtin (list)
 
       if (var && !unset_function && non_unsettable_p (var))
        {
 
       if (var && !unset_function && non_unsettable_p (var))
        {
-         builtin_error ("%s: cannot unset", name);
+         builtin_error (_("%s: cannot unset"), name);
          NEXT_VARIABLE ();
        }
 
       /* Posix.2 says that unsetting readonly variables is an error. */
       if (var && readonly_p (var))
        {
          NEXT_VARIABLE ();
        }
 
       /* Posix.2 says that unsetting readonly variables is an error. */
       if (var && readonly_p (var))
        {
-         builtin_error ("%s: cannot unset: readonly %s",
+         builtin_error (_("%s: cannot unset: readonly %s"),
                         name, unset_function ? "function" : "variable");
          NEXT_VARIABLE ();
        }
                         name, unset_function ? "function" : "variable");
          NEXT_VARIABLE ();
        }
@@ -803,26 +797,31 @@ unset_builtin (list)
        {
          if (array_p (var) == 0)
            {
        {
          if (array_p (var) == 0)
            {
-             builtin_error ("%s: not an array variable", name);
+             builtin_error (_("%s: not an array variable"), name);
              NEXT_VARIABLE ();
            }
          else
              NEXT_VARIABLE ();
            }
          else
-           tem = unbind_array_element (var, t);
+           {
+             tem = unbind_array_element (var, t);
+             if (tem == -1)
+               any_failed++;
+           }
        }
       else
 #endif /* ARRAY_VARS */
        }
       else
 #endif /* ARRAY_VARS */
-      tem = makunbound (name, unset_function ? shell_functions : shell_variables);
+      tem = unset_function ? unbind_func (name) : unbind_variable (name);
 
       /* This is what Posix.2 draft 11+ says.  ``If neither -f nor -v
         is specified, the name refers to a variable; if a variable by
         that name does not exist, a function by that name, if any,
         shall be unset.'' */
       if (tem == -1 && !unset_function && !unset_variable)
 
       /* This is what Posix.2 draft 11+ says.  ``If neither -f nor -v
         is specified, the name refers to a variable; if a variable by
         that name does not exist, a function by that name, if any,
         shall be unset.'' */
       if (tem == -1 && !unset_function && !unset_variable)
-       tem = makunbound (name, shell_functions);
+       tem = unbind_func (name);
+
+      /* SUSv3, POSIX.1-2001 say:  ``Unsetting a variable or function that
+        was not previously set shall not be considered an error.'' */
 
 
-      if (tem == -1)
-       any_failed++;
-      else if (!unset_function)
+      if (unset_function == 0)
        stupidly_hack_special_variables (name);
 
       list = list->next;
        stupidly_hack_special_variables (name);
 
       list = list->next;