]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
Imported from ../bash-3.2.48.tar.gz.
authorJari Aalto <jari.aalto@cante.net>
Tue, 18 Nov 2008 13:15:12 +0000 (13:15 +0000)
committerJari Aalto <jari.aalto@cante.net>
Sat, 12 Sep 2009 16:46:59 +0000 (16:46 +0000)
47 files changed:
array.c
array.h
arrayfunc.c
bashhist.c
bashhist.h
bashline.c
builtins/common.c
builtins/evalstring.c
builtins/printf.def
builtins/read.def
builtins/set.def
builtins/shopt.def
config-bot.h
config.h.in
configure
configure.in
doc/bash.1
doc/bashref.texi
execute_cmd.c
expr.c
findcmd.c
jobs.c
lib/readline/complete.c
lib/readline/display.c
lib/readline/input.c
lib/readline/isearch.c
lib/readline/misc.c
lib/readline/readline.c
lib/readline/text.c
lib/readline/vi_mode.c
lib/sh/getcwd.c
lib/sh/snprintf.c
parse.y
patchlevel.h
pathexp.c
pathexp.h
po/ru.gmo [new file with mode: 0644]
po/ru.po
shell.h
sig.c
sig.h
subst.c
subst.h
tests/new-exp.right
tests/shopt.right
variables.c
version.c

diff --git a/array.c b/array.c
index c32b61344d10c697ba26658cbe651aa663fa2ad4..cee9c1fff5996823e9c00c753bc7f5ba3c9ff8fc 100644 (file)
--- a/array.c
+++ b/array.c
@@ -120,7 +120,6 @@ ARRAY       *a;
        return(a1);
 }
 
-#ifdef INCLUDE_UNUSED
 /*
  * Make and return a new array composed of the elements in array A from
  * S to E, inclusive.
@@ -141,13 +140,12 @@ ARRAY_ELEMENT     *s, *e;
        for (p = s, i = 0; p != e; p = element_forw(p), i++) {
                n = array_create_element (element_index(p), element_value(p));
                ADD_BEFORE(a->head, n);
-               mi = element_index(ae);
+               mi = element_index(n);
        }
        a->num_elements = i;
        a->max_index = mi;
        return a;
 }
-#endif
 
 /*
  * Walk the array, calling FUNC once for each element, with the array
@@ -300,6 +298,23 @@ ARRAY      *array;
        return array;
 }
 
+ARRAY  *
+array_quote_escapes(array)
+ARRAY  *array;
+{
+       ARRAY_ELEMENT   *a;
+       char    *t;
+
+       if (array == 0 || array_head(array) == 0 || array_empty(array))
+               return (ARRAY *)NULL;
+       for (a = element_forw(array->head); a != array->head; a = element_forw(a)) {
+               t = quote_escapes (a->value);
+               FREE(a->value);
+               a->value = t;
+       }
+       return array;
+}
+
 /*
  * Return a string whose elements are the members of array A beginning at
  * index START and spanning NELEM members.  Null elements are counted.
@@ -311,9 +326,10 @@ ARRAY      *a;
 arrayind_t     start, nelem;
 int    starsub, quoted;
 {
+       ARRAY           *a2;
        ARRAY_ELEMENT   *h, *p;
        arrayind_t      i;
-       char            *ifs, sep[2];
+       char            *ifs, sep[2], *t;
 
        p = a ? array_head (a) : 0;
        if (p == 0 || array_empty (a) || start > array_max_index(a))
@@ -336,6 +352,13 @@ int        starsub, quoted;
        for (i = 0, h = p; p != a->head && i < nelem; i++, p = element_forw(p))
                ;
 
+       a2 = array_slice(a, h, p);
+
+       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+               array_quote(a2);
+       else
+               array_quote_escapes(a2);
+
        if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
                ifs = getifs();
                sep[0] = ifs ? *ifs : '\0';
@@ -343,7 +366,10 @@ int        starsub, quoted;
                sep[0] = ' ';
        sep[1] = '\0';
 
-       return (array_to_string_internal (h, p, sep, quoted));
+       t = array_to_string (a2, sep, 0);
+       array_dispose(a2);
+
+       return t;
 }
 
 char *
@@ -367,7 +393,9 @@ int mflags;
        }
 
        if (mflags & MATCH_QUOTED)
-               array_quote (a2);
+               array_quote(a2);
+       else
+               array_quote_escapes(a2);
        if (mflags & MATCH_STARSUB) {
                ifs = getifs();
                sifs[0] = ifs ? *ifs : '\0';
@@ -655,7 +683,7 @@ int quoted;
                is = inttostr (element_index(ae), indstr, sizeof(indstr));
                valstr = element_value (ae) ? sh_double_quote (element_value(ae))
                                            : (char *)NULL;
-               elen = STRLEN (indstr) + 8 + STRLEN (valstr);
+               elen = STRLEN (is) + 8 + STRLEN (valstr);
                RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize);
 
                result[rlen++] = '[';
diff --git a/array.h b/array.h
index 8c671b79e6c75f48b16a69fc419a97ef6cbf4c20..b9632b42e0a9b64b1f4676506022212254db7239 100644 (file)
--- a/array.h
+++ b/array.h
@@ -55,6 +55,7 @@ extern int    array_rshift __P((ARRAY *, int, char *));
 extern ARRAY_ELEMENT *array_unshift_element __P((ARRAY *));
 extern int     array_shift_element __P((ARRAY *, char *));
 extern ARRAY   *array_quote __P((ARRAY *));
+extern ARRAY   *array_quote_escapes __P((ARRAY *));
 
 extern char    *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
 extern char    *array_patsub __P((ARRAY *, char *, char *, int));
index 48a099dde0ee1676f7495281aa2d3c1287eb24dd..6bc248a7d0b0512948fae3ba14a3cd4dbae8d130 100644 (file)
@@ -618,6 +618,8 @@ array_expand_index (s, len)
   if (expok == 0)
     {
       last_command_exit_value = EXECUTION_FAILURE;
+
+      top_level_cleanup ();      
       jump_to_top_level (DISCARD);
     }
   return val;
@@ -720,7 +722,7 @@ array_value_internal (s, quoted, allow_all, rtype)
   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
     {
       if (rtype)
-       *rtype = 1;
+       *rtype = (t[0] == '*') ? 1 : 2;
       if (allow_all == 0)
        {
          err_badarraysub (s);
index 6468a538307ce63a94dc31e8c90af115cbd4b64e..3b8541609a51c393e275e037acfcdb9ba2dd59ee 100644 (file)
@@ -80,6 +80,7 @@ static struct ignorevar histignore =
    list.  This is different than the user-controlled behaviour; this
    becomes zero when we read lines from a file, for example. */
 int remember_on_history = 1;
+int enable_history_list = 1;   /* value for `set -o history' */
 
 /* The number of lines that Bash has added to this history session.  The
    difference between the number of the top element in the history list
@@ -234,7 +235,7 @@ bash_history_reinit (interact)
   history_expansion = interact != 0;
   history_expansion_inhibited = 1;
 #endif
-  remember_on_history = interact != 0;
+  remember_on_history = enable_history_list = interact != 0;
   history_inhibit_expansion_function = bash_history_inhibit_expansion;
 }
 
index 0a01d691eabb0bf0ecc4c8e93375e090749fb37c..654043c774fc2ab83ea9e227f8687bdc48339cd9 100644 (file)
@@ -31,6 +31,9 @@
 #define HC_IGNBOTH     (HC_IGNSPACE|HC_IGNDUPS)
 
 extern int remember_on_history;
+extern int enable_history_list;                /* value for `set -o history' */
+extern int literal_history;            /* controlled by `shopt lithist' */
+extern int force_append_history;
 extern int history_lines_this_session;
 extern int history_lines_in_file;
 extern int history_expansion;
index 809fe32b636f5a3f4deb0a2b65375da14ef549bc..fa4055e21d65d1b6caf90adbf1a89b07ebf60ad8 100644 (file)
@@ -2357,7 +2357,7 @@ bash_directory_completion_hook (dirname)
   if (should_expand_dirname)  
     {
       new_dirname = savestring (local_dirname);
-      wl = expand_prompt_string (new_dirname, 0);      /* does the right thing */
+      wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB);  /* does the right thing */
       if (wl)
        {
          *dirname = string_list (wl);
index 7b9613e1fae749943ef1b733ffc584d508e270b1..89c6a870abf3bcf3cc2ea36895fdbac1dc21ad17 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -131,6 +131,7 @@ no_args (list)
   if (list)
     {
       builtin_error (_("too many arguments"));
+      top_level_cleanup ();
       jump_to_top_level (DISCARD);
     }
 }
@@ -395,7 +396,10 @@ get_numeric_arg (list, fatal)
          if (fatal)
            throw_to_top_level ();
          else
-           jump_to_top_level (DISCARD);
+           {
+             top_level_cleanup ();
+             jump_to_top_level (DISCARD);
+           }
        }
       no_args (list->next);
     }
@@ -475,7 +479,11 @@ get_working_directory (for_whom)
 
   if (the_current_working_directory == 0)
     {
+#if defined (GETCWD_BROKEN)
+      the_current_working_directory = getcwd (0, PATH_MAX);
+#else
       the_current_working_directory = getcwd (0, 0);
+#endif
       if (the_current_working_directory == 0)
        {
          fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
index 36f0ad398c33fcb163dba45d9038f083a9746d60..511ce86c35ffe8a79f6635a99a13d56bb364f35a 100644 (file)
@@ -67,6 +67,14 @@ int parse_and_execute_level = 0;
 
 static int cat_file __P((REDIRECT *));
 
+#if defined (HISTORY)
+static void
+set_history_remembering ()
+{
+  remember_on_history = enable_history_list;
+}
+#endif
+
 /* How to force parse_and_execute () to clean up after itself. */
 void
 parse_and_execute_cleanup ()
@@ -115,7 +123,10 @@ parse_and_execute (string, from_file, flags)
   lreset = flags & SEVAL_RESETLINE;
 
 #if defined (HISTORY)
-  unwind_protect_int (remember_on_history);    /* can be used in scripts */
+  if (parse_and_execute_level == 0)
+    add_unwind_protect (set_history_remembering, (char *)NULL);
+  else
+    unwind_protect_int (remember_on_history);  /* can be used in scripts */
 #  if defined (BANG_HISTORY)
   if (interactive_shell)
     {
@@ -237,6 +248,7 @@ parse_and_execute (string, from_file, flags)
               *   parse_and_execute has not been called recursively AND
               *   we're not running a trap AND
               *   we have parsed the full command (string == '\0') AND
+              *   we're not going to run the exit trap AND
               *   we have a simple command without redirections AND
               *   the command is not being timed AND
               *   the command's return status is not being inverted
@@ -247,7 +259,8 @@ parse_and_execute (string, from_file, flags)
                  running_trap == 0 &&
                  *bash_input.location.string == '\0' &&
                  command->type == cm_simple &&
-                 !command->redirects && !command->value.Simple->redirects &&
+                 signal_is_trapped (EXIT_TRAP) == 0 &&
+                 command->redirects == 0 && command->value.Simple->redirects == 0 &&
                  ((command->flags & CMD_TIME_PIPELINE) == 0) &&
                  ((command->flags & CMD_INVERT_RETURN) == 0))
                {
index 0e1d4aa929e6343f3a7ed80cc26f32f3771f003e..5a631677bbd1160b400e73c3cbdaf8b45af2b8bc 100644 (file)
@@ -1,7 +1,7 @@
 This file is printf.def, from which is created printf.c.
 It implements the builtin "printf" in Bash.
 
-Copyright (C) 1997-2005 Free Software Foundation, Inc.
+Copyright (C) 1997-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -49,6 +49,12 @@ $END
 #  define INT_MIN              (-2147483647-1)
 #endif
 
+#if defined (PREFER_STDARG)
+#  include <stdarg.h>
+#else
+#  include <varargs.h>
+#endif
+
 #include <stdio.h>
 #include <chartypes.h>
 
@@ -64,6 +70,10 @@ $END
 #include "bashgetopt.h"
 #include "common.h"
 
+#if defined (PRI_MACROS_BROKEN)
+#  undef PRIdMAX
+#endif
+
 #if !defined (PRIdMAX)
 #  if HAVE_LONG_LONG
 #    define PRIdMAX    "lld"
@@ -151,6 +161,10 @@ extern int errno;
 #define SKIP1 "#'-+ 0"
 #define LENMODS "hjlLtz"
 
+#ifndef HAVE_ASPRINTF
+extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
+#endif
+
 static void printf_erange __P((char *));
 static int printstr __P((char *, char *, int, int, int));
 static int tescape __P((char *, char *, int *));
index 21521db0f21deaec21e94725378e2cf98d5bf793..afa549ed9d42122ad5a63ee060c6af6cfdaa5127 100644 (file)
@@ -127,14 +127,14 @@ read_builtin (list)
      WORD_LIST *list;
 {
   register char *varname;
-  int size, i, nr, pass_next, saw_escape, eof, opt, retval, code;
-  int input_is_tty, input_is_pipe, unbuffered_read;
+  int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
+  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
   int raw, edit, nchars, silent, have_timeout, fd;
   unsigned int tmout;
   intmax_t intval;
   char c;
   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
-  char *e, *t, *t1;
+  char *e, *t, *t1, *ps2, *tofree;
   struct stat tsb;
   SHELL_VAR *var;
 #if defined (ARRAY_VARS)
@@ -148,6 +148,7 @@ read_builtin (list)
   USE_VAR(size);
   USE_VAR(i);
   USE_VAR(pass_next);
+  USE_VAR(print_ps2);
   USE_VAR(saw_escape);
   USE_VAR(input_is_pipe);
 /*  USE_VAR(raw); */
@@ -163,6 +164,7 @@ read_builtin (list)
   USE_VAR(rlind);
 #endif
   USE_VAR(list);
+  USE_VAR(ps2);
 
   i = 0;               /* Index into the string that we are reading. */
   raw = edit = 0;      /* Not reading raw input by default. */
@@ -386,7 +388,8 @@ read_builtin (list)
   setmode (0, O_TEXT);
 #endif
 
-  for (eof = retval = 0;;)
+  ps2 = 0;
+  for (print_ps2 = eof = retval = 0;;)
     {
 #if defined (READLINE)
       if (edit)
@@ -412,6 +415,15 @@ read_builtin (list)
        {
 #endif
 
+      if (print_ps2)
+       {
+         if (ps2 == 0)
+           ps2 = get_string_value ("PS2");
+         fprintf (stderr, "%s", ps2 ? ps2 : "");
+         fflush (stderr);
+         print_ps2 = 0;
+       }
+
       if (unbuffered_read)
        retval = zread (fd, &c, 1);
       else
@@ -440,7 +452,11 @@ read_builtin (list)
        {
          pass_next = 0;
          if (c == '\n')
-           i--;                /* back up over the CTLESC */
+           {
+             i--;              /* back up over the CTLESC */
+             if (interactive && input_is_tty && raw == 0)
+               print_ps2 = 1;
+           }
          else
            goto add_char;
          continue;
@@ -658,12 +674,13 @@ add_char:
 #else
   /* Check whether or not the number of fields is exactly the same as the
      number of variables. */
+  tofree = NULL;
   if (*input_string)
     {
       t1 = input_string;
       t = get_word_from_string (&input_string, ifs_chars, &e);
       if (*input_string == 0)
-       input_string = t;
+       tofree = input_string = t;
       else
        input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
     }
@@ -678,6 +695,8 @@ add_char:
   else
     var = bind_read_variable (list->word->word, input_string);
   stupidly_hack_special_variables (list->word->word);
+  FREE (tofree);
+
   if (var)
     VUNSETATTR (var, att_invisible);
   xfree (orig_input_string);
index d1086695a3d89171ccae84852ea464e9281f3d08..9d8631915cbb83eaae57b3aa1368253f4fa123dc 100644 (file)
@@ -189,7 +189,7 @@ struct {
   { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #endif /* BANG_HISTORY */
 #if defined (HISTORY)
-  { "history",   '\0', &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
+  { "history",   '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
 #endif
   { "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 },
@@ -381,13 +381,17 @@ bash_set_history (on_or_off, option_name)
 {
   if (on_or_off == FLAG_ON)
     {
+      enable_history_list = 1;
       bash_history_enable ();
       if (history_lines_this_session == 0)
        load_history ();
     }
   else
-    bash_history_disable ();
-  return (1 - remember_on_history);
+    {
+      enable_history_list = 0;
+      bash_history_disable ();
+    }
+  return (1 - enable_history_list);
 }
 #endif
 
@@ -565,7 +569,7 @@ void
 reset_shell_options ()
 {
 #if defined (HISTORY)
-  remember_on_history = 1;
+  remember_on_history = enable_history_list = 1;
 #endif
   ignoreeof = 0;
 }
index ae100ace47c2b3cd3662bccb133a708d2a94d002..db46c318b8a3375826dfa7b389396520ae850a57 100644 (file)
@@ -101,11 +101,14 @@ static void shopt_error __P((char *));
 
 static int set_shellopts_after_change __P((int));
 
+static int set_compatibility_level __P((int));
+
 #if defined (RESTRICTED_SHELL)
 static int set_restricted_shell __P((int));
 #endif
 
 static int shopt_login_shell;
+static int shopt_compat31;
 
 typedef int shopt_set_func_t __P((int));
 
@@ -121,6 +124,7 @@ static struct {
 #if defined (HISTORY)
   { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
 #endif
+  { "compat31", &shopt_compat31, set_compatibility_level },
   { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
   { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
   { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
@@ -459,6 +463,18 @@ set_shellopts_after_change (mode)
   return (0);
 }
 
+static int
+set_compatibility_level (mode)
+     int mode;
+{
+  /* Need to change logic here as we add more compatibility levels */
+  if (shopt_compat31)
+    shell_compatibility_level = 31;
+  else
+    shell_compatibility_level = 32;
+  return 0;
+}
+
 #if defined (RESTRICTED_SHELL)
 /* Don't allow the value of restricted_shell to be modified. */
 
index c2200f20a64078420d3ee0798838d3f829e7cf6c..4efa63c590d1b854f6d1b878d4ce9e1853d389a9 100644 (file)
@@ -1,7 +1,7 @@
 /* config-bot.h */
 /* modify settings or make new ones based on what autoconf tells us. */
 
-/* Copyright (C) 1989-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #  define TERMIOS_MISSING
 #endif
 
-/* If we have a getcwd(3), but it calls popen(), #undef HAVE_GETCWD so
-   the replacement in getcwd.c will be built. */
-#if defined (HAVE_GETCWD) && defined (GETCWD_BROKEN)
+/* If we have a getcwd(3), but one that does not dynamically allocate memory,
+   #undef HAVE_GETCWD so the replacement in getcwd.c will be built.  We do
+   not do this on Solaris, because their implementation of loopback mounts
+   breaks the traditional file system assumptions that getcwd uses. */
+#if defined (HAVE_GETCWD) && defined (GETCWD_BROKEN) && !defined (SOLARIS)
 #  undef HAVE_GETCWD
 #endif
 
index 0ae1f1c78b7ca756a914f772e1e9142c1fc9db19..3699374d4d3276f4647233db21593aba8761ae3f 100644 (file)
@@ -1,6 +1,6 @@
 /* config.h -- Configuration file for bash. */
 
-/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 
 #undef HAVE_DECL_STRTOLD
 
+#undef PRI_MACROS_BROKEN
+
 #undef STRTOLD_BROKEN
 
 /* Define if WCONTINUED is defined in system headers, but rejected by waitpid */
 /* Define if you have the `dcgettext' function. */
 #undef HAVE_DCGETTEXT
 
+/* Define if you have the `localeconv' function. */
+#undef HAVE_LOCALECONV
+
 /* Define if your system has a working `malloc' function. */
 /* #undef HAVE_MALLOC */
 
index a60857c5bf0747db4e58c726f0ed3cf880d859be..3477a08fbc009ba36283715a9960b16a1edb5fbd 100755 (executable)
--- a/configure
+++ b/configure
@@ -4871,7 +4871,7 @@ _ACEOF
                # static version specified as -llibname to override the
                # dynamic version
                case "${host_os}" in
-               darwin8*)       READLINE_LIB='${READLINE_LIBRARY}' ;;
+               darwin[89]*)    READLINE_LIB='${READLINE_LIBRARY}' ;;
                *)              READLINE_LIB=-lreadline ;;
                esac
        fi
@@ -27316,7 +27316,8 @@ sco3.2v5*)      LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
 sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
 sco3.2*)       LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
 sunos4*)       LOCAL_CFLAGS=-DSunOS4 ;;
-solaris2.5*)   LOCAL_CFLAGS=-DSunOS5 ;;
+solaris2.5*)   LOCAL_CFLAGS="-DSunOS5 -DSOLARIS" ;;
+solaris2*)     LOCAL_CFLAGS=-DSOLARIS ;;
 lynxos*)       LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
 linux*)                LOCAL_LDFLAGS=-rdynamic          # allow dynamic loading
                case "`uname -r`" in
index 0e808cde2b196fd108e1110285fd88801571a061..a688b2d19563d08d8cebf2fd4e447427f40a0bdd 100644 (file)
@@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu
 dnl
 dnl Process this file with autoconf to produce a configure script.
 
-# Copyright (C) 1987-2006 Free Software Foundation, Inc.
+# Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -518,7 +518,7 @@ if test $opt_readline = yes; then
                # static version specified as -llibname to override the
                # dynamic version
                case "${host_os}" in
-               darwin8*)       READLINE_LIB='${READLINE_LIBRARY}' ;;
+               darwin[[89]]*)  READLINE_LIB='${READLINE_LIBRARY}' ;;
                *)              READLINE_LIB=-lreadline ;;
                esac
        fi
@@ -991,7 +991,8 @@ sco3.2v5*)  LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
 sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
 sco3.2*)       LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
 sunos4*)       LOCAL_CFLAGS=-DSunOS4 ;;
-solaris2.5*)   LOCAL_CFLAGS=-DSunOS5 ;;
+solaris2.5*)   LOCAL_CFLAGS="-DSunOS5 -DSOLARIS" ;;
+solaris2*)     LOCAL_CFLAGS=-DSOLARIS ;;
 lynxos*)       LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
 linux*)                LOCAL_LDFLAGS=-rdynamic          # allow dynamic loading
                case "`uname -r`" in
index f9e536eb4e62d69f7fbbd8a81c13be7ef223a58b..4d977f9a14fade558af4d7c9cb6773a5abe80fef 100644 (file)
@@ -7977,6 +7977,12 @@ attempts to save all lines of a multiple-line
 command in the same history entry.  This allows
 easy re-editing of multi-line commands.
 .TP 8
+.B compat31
+If set,
+.B bash
+changes its behavior to that of version 3.1 with respect to quoted
+arguments to the conditional command's =~ operator.
+.TP 8
 .B dotglob
 If set, 
 .B bash
index 2acf21f6212bf9591ac3b07e5bcad678560e9e19..c2892d63b6368bc8f147a4a8e1917c0ae9470244 100644 (file)
@@ -3598,6 +3598,11 @@ attempts to save all lines of a multiple-line
 command in the same history entry.  This allows
 easy re-editing of multi-line commands.
 
+@item compat31
+If set, Bash
+changes its behavior to that of version 3.1 with respect to quoted
+arguments to the conditional command's =~ operator.
+
 @item dotglob
 If set, Bash includes filenames beginning with a `.' in
 the results of filename expansion.
index dde6b52c40ebe42f65da4ad4322b3107ec2797c5..81de1dc00cf52a1d86f6d28c26b6fece8513ea45 100644 (file)
@@ -1,6 +1,6 @@
 /* execute_cmd.c -- Execute a COMMAND structure. */
 
-/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -501,8 +501,15 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
   volatile int last_pid;
   volatile int save_line_number;
 
+#if 0
   if (command == 0 || breaking || continuing || read_but_dont_execute)
     return (EXECUTION_SUCCESS);
+#else
+  if (breaking || continuing)
+    return (last_command_exit_value);
+  if (command == 0 || read_but_dont_execute)
+    return (EXECUTION_SUCCESS);
+#endif
 
   QUIT;
   run_pending_traps ();
@@ -614,7 +621,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
       cleanup_redirects (redirection_undo_list);
       redirection_undo_list = (REDIRECT *)NULL;
       dispose_exec_redirects ();
-      return (EXECUTION_FAILURE);
+      return (last_command_exit_value = EXECUTION_FAILURE);
     }
 
   if (redirection_undo_list)
@@ -2546,7 +2553,8 @@ execute_cond_node (cond)
       arg1 = cond_expand_word (cond->left->op, 0);
       if (arg1 == 0)
        arg1 = nullstr;
-      arg2 = cond_expand_word (cond->right->op, patmatch||rmatch);
+      arg2 = cond_expand_word (cond->right->op,
+                              (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
       if (arg2 == 0)
        arg2 = nullstr;
 
@@ -3050,6 +3058,11 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   if (command_line == 0)
     command_line = savestring (the_printed_command_except_trap);
 
+#if defined (PROCESS_SUBSTITUTION)
+  if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
+    simple_command->flags &= ~CMD_NO_FORK;
+#endif
+
   execute_disk_command (words, simple_command->redirects, command_line,
                        pipe_in, pipe_out, async, fds_to_close,
                        simple_command->flags);
@@ -3875,6 +3888,8 @@ initialize_subshell ()
     shell_variables = shell_variables->down;
 
   clear_unwind_protect_list (0);
+  /* XXX -- are there other things we should be resetting here? */
+  parse_and_execute_level = 0;         /* nothing left to restore it */
 
   /* We're no longer inside a shell function. */
   variable_context = return_catch_flag = 0;
diff --git a/expr.c b/expr.c
index 418f48d0ec8736701926a4c94320c3da9300df30..a5cb0388e80666def999132f7b48cf348c2660ab 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -286,6 +286,8 @@ expr_unwind ()
       free (expr_stack[expr_depth]);
     }
   free (expr_stack[expr_depth]);       /* free the allocated EXPR_CONTEXT */
+
+  noeval = 0;  /* XXX */
 }
 
 static void
@@ -319,6 +321,7 @@ evalexp (expr, validp)
   procenv_t oevalbuf;
 
   val = 0;
+  noeval = 0;
 
   FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
 
@@ -517,7 +520,8 @@ expcond ()
          set_noeval = 1;
          noeval++;
        }
-      val2 = explor ();
+
+      val2 = expcond ();
       if (set_noeval)
        noeval--;
       rval = cval ? val1 : val2;
@@ -929,6 +933,7 @@ expr_streval (tok, e)
       if (interactive_shell)
        {
          expr_unwind ();
+         top_level_cleanup ();
          jump_to_top_level (DISCARD);
        }
       else
index 6f5ff8584a607d4a1fd76f3cb6664f44a22d9107..27720f8aa8b3d78e461e17e4bb1b701ca803130f 100644 (file)
--- a/findcmd.c
+++ b/findcmd.c
@@ -308,7 +308,7 @@ search_for_command (pathname)
   if (hashed_file && (posixly_correct || check_hashed_filenames))
     {
       st = file_status (hashed_file);
-      if ((st ^ (FS_EXISTS | FS_EXECABLE)) != 0)
+      if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE))
        {
          phash_remove (pathname);
          free (hashed_file);
diff --git a/jobs.c b/jobs.c
index 5e4b1f67589299a67edbb883370de2d4294b363c..d18339435e12a6fd9ef9e8fadbd6682ebccbcc4c 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -250,6 +250,7 @@ static int job_exit_status __P((int));
 static int job_exit_signal __P((int));
 static int set_job_status_and_cleanup __P((int));
 
+static WAIT job_signal_status __P((int));
 static WAIT raw_job_exit_status __P((int));
 
 static void notify_of_job_status __P((void));
@@ -783,11 +784,13 @@ reset_job_indices ()
   if (jobs[js.j_firstj] == 0)
     {
       old = js.j_firstj++;
+      if (old >= js.j_jobslots)
+       old = js.j_jobslots - 1;
       while (js.j_firstj != old)
        {
          if (js.j_firstj >= js.j_jobslots)
            js.j_firstj = 0;
-         if (jobs[js.j_firstj])
+         if (jobs[js.j_firstj] || js.j_firstj == old)  /* needed if old == 0 */
            break;
          js.j_firstj++;
        }
@@ -797,11 +800,13 @@ reset_job_indices ()
   if (jobs[js.j_lastj] == 0)
     {
       old = js.j_lastj--;
+      if (old < 0)
+       old = 0;
       while (js.j_lastj != old)
        {
          if (js.j_lastj < 0)
            js.j_lastj = js.j_jobslots - 1;
-         if (jobs[js.j_lastj])
+         if (jobs[js.j_lastj] || js.j_lastj == old)    /* needed if old == js.j_jobslots */
            break;
          js.j_lastj--;
        }
@@ -963,7 +968,11 @@ compact_jobs_list (flags)
   reap_dead_jobs ();
   realloc_jobs_list ();
 
-  return (js.j_lastj);
+#ifdef DEBUG
+  itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+#endif
+
+  return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
 }
 
 /* Delete the job at INDEX from the job list.  Must be called
@@ -984,8 +993,6 @@ delete_job (job_index, dflags)
   temp = jobs[job_index];
   if (temp == 0)
     return;
-  if (job_index == js.j_current || job_index == js.j_previous)
-    reset_current ();
 
   if ((dflags & DEL_NOBGPID) == 0)
     {
@@ -1028,6 +1035,9 @@ delete_job (job_index, dflags)
     js.j_firstj = js.j_lastj = 0;
   else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
     reset_job_indices ();
+
+  if (job_index == js.j_current || job_index == js.j_previous)
+    reset_current ();
 }
 
 /* Must be called with SIGCHLD blocked. */
@@ -2210,6 +2220,26 @@ process_exit_status (status)
     return (EXECUTION_SUCCESS);
 }
 
+static WAIT
+job_signal_status (job)
+     int job;
+{
+  register PROCESS *p;
+  WAIT s;
+
+  p = jobs[job]->pipe;
+  do
+    {
+      s = p->status;
+      if (WIFSIGNALED(s) || WIFSTOPPED(s))
+       break;
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  return s;
+}
+  
 /* Return the exit status of the last process in the pipeline for job JOB.
    This is the exit status of the entire job. */
 static WAIT
@@ -2292,11 +2322,14 @@ wait_for (pid)
      to finish.  We don't want the shell to exit if an interrupt is
      received, only if one of the jobs run is killed via SIGINT.  If
      job control is not set, the job will be run in the same pgrp as
-     the shell, and the shell will see any signals the job gets. */
+     the shell, and the shell will see any signals the job gets.  In
+     fact, we want this set every time the waiting shell and the waited-
+     for process are in the same process group, including command
+     substitution. */
 
   /* This is possibly a race condition -- should it go in stop_pipeline? */
   wait_sigint_received = 0;
-  if (job_control == 0)
+  if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
     {
       old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
       if (old_sigint_handler == SIG_IGN)
@@ -2442,15 +2475,7 @@ if (job == NO_JOB)
             to a signal.  We might want to change this later to just check
             the last process in the pipeline.  If no process exits due to a
             signal, S is left as the status of the last job in the pipeline. */
-         p = jobs[job]->pipe;
-         do
-           {
-             s = p->status;
-             if (WIFSIGNALED(s) || WIFSTOPPED(s))
-               break;
-             p = p->next;
-           }
-         while (p != jobs[job]->pipe);
+         s = job_signal_status (job);
 
          if (WIFSIGNALED (s) || WIFSTOPPED (s))
            {
@@ -2484,6 +2509,24 @@ if (job == NO_JOB)
                }
            }
        }
+      else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
+       {
+         /* If waiting for a job in a subshell started to do command
+            substitution, simulate getting and being killed by the SIGINT to
+            pass the status back to our parent. */
+         s = job_signal_status (job);
+       
+         if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
+           {
+             UNBLOCK_CHILD (oset);
+             restore_sigint_handler ();
+             old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
+             if (old_sigint_handler == SIG_IGN)
+               restore_sigint_handler ();
+             else
+               kill (getpid (), SIGINT);
+           }
+       }
 
       /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
          signal handler path */
index 73f834a68a79a2fe0d47087de3c06dd7e5fab282..5ff198d346a5b36e144f2ddd2fae221daf4e73c3 100644 (file)
@@ -428,7 +428,7 @@ get_y_or_n (for_pager)
        return (1);
       if (c == 'n' || c == 'N' || c == RUBOUT)
        return (0);
-      if (c == ABORT_CHAR)
+      if (c == ABORT_CHAR || c < 0)
        _rl_abort_internal ();
       if (for_pager && (c == NEWLINE || c == RETURN))
        return (2);
index 47ff06159747583defb3a320b92a8b4614497856..2a482ef5dbc38eed5687fe36fa33181cd1bdc9f8 100644 (file)
@@ -391,14 +391,14 @@ rl_expand_prompt (prompt)
       t = ++p;
       local_prompt = expand_prompt (p, &prompt_visible_length,
                                       &prompt_last_invisible,
-                                      (int *)NULL,
+                                      &prompt_invis_chars_first_line,
                                       &prompt_physical_chars);
       c = *t; *t = '\0';
       /* The portion of the prompt string up to and including the
         final newline is now null-terminated. */
       local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
                                                   (int *)NULL,
-                                                  &prompt_invis_chars_first_line,
+                                                  (int *)NULL,
                                                   (int *)NULL);
       *t = c;
       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
@@ -561,6 +561,17 @@ rl_redisplay ()
       wrap_offset = prompt_invis_chars_first_line = 0;
     }
 
+#if defined (HANDLE_MULTIBYTE)
+#define CHECK_INV_LBREAKS() \
+      do { \
+       if (newlines >= (inv_lbsize - 2)) \
+         { \
+           inv_lbsize *= 2; \
+           inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+           _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
+         } \
+      } while (0)
+#else
 #define CHECK_INV_LBREAKS() \
       do { \
        if (newlines >= (inv_lbsize - 2)) \
@@ -569,6 +580,7 @@ rl_redisplay ()
            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
          } \
       } while (0)
+#endif /* HANDLE_MULTIBYTE */
 
 #if defined (HANDLE_MULTIBYTE)   
 #define CHECK_LPOS() \
@@ -898,6 +910,10 @@ rl_redisplay ()
             second and subsequent lines start at inv_lbreaks[N], offset by
             OFFSET (which has already been calculated above).  */
 
+#define INVIS_FIRST()  (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
+#define WRAP_OFFSET(line, offset)  ((line == 0) \
+                                       ? (offset ? INVIS_FIRST() : 0) \
+                                       : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
 #define VIS_LLEN(l)    ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
 #define INV_LLEN(l)    (inv_lbreaks[l+1] - inv_lbreaks[l])
@@ -932,7 +948,13 @@ rl_redisplay ()
                  _rl_last_c_pos != o_cpos &&
                  _rl_last_c_pos > wrap_offset &&
                  o_cpos < prompt_last_invisible)
-               _rl_last_c_pos -= wrap_offset;
+               _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
+             else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
+                       (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
+                       cpos_adjusted == 0 &&
+                       _rl_last_c_pos != o_cpos &&
+                       _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
+               _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
                  
              /* If this is the line with the prompt, we might need to
                 compensate for invisible characters in the new line. Do
@@ -1036,7 +1058,7 @@ rl_redisplay ()
                tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
              else
                tx = nleft;
-             if (_rl_last_c_pos > tx)
+             if (tx >= 0 && _rl_last_c_pos > tx)
                {
                  _rl_backspace (_rl_last_c_pos - tx);  /* XXX */
                  _rl_last_c_pos = tx;
@@ -1192,7 +1214,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
      int current_line, omax, nmax, inv_botlin;
 {
   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
-  int temp, lendiff, wsatend, od, nd;
+  int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
   int current_invis_chars;
   int col_lendiff, col_temp;
 #if defined (HANDLE_MULTIBYTE)
@@ -1208,7 +1230,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
     temp = _rl_last_c_pos;
   else
-    temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+    temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
        && _rl_last_v_pos == current_line - 1)
     {
@@ -1453,6 +1475,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
        _rl_last_c_pos = lendiff;
     }
 
+  o_cpos = _rl_last_c_pos;
+
   /* When this function returns, _rl_last_c_pos is correct, and an absolute
      cursor postion in multibyte mode, but a buffer index when not in a
      multibyte locale. */
@@ -1462,7 +1486,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   /* We need to indicate that the cursor position is correct in the presence of
      invisible characters in the prompt string.  Let's see if setting this when
      we make sure we're at the end of the drawn prompt string works. */
-  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
+  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && 
+      (_rl_last_c_pos > 0 || o_cpos > 0) &&
+      _rl_last_c_pos == prompt_physical_chars)
     cpos_adjusted = 1;
 #endif
 #endif
@@ -1506,11 +1532,31 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* If col_lendiff is > 0, implying that the new string takes up more
+        screen real estate than the old, but lendiff is < 0, meaning that it
+        takes fewer bytes, we need to just output the characters starting
+        from the first difference.  These will overwrite what is on the
+        display, so there's no reason to do a smart update.  This can really
+        only happen in a multibyte environment. */
+      if (lendiff < 0)
+       {
+         _rl_output_some_chars (nfd, temp);
+         _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
+         /* If nfd begins before any invisible characters in the prompt,
+            adjust _rl_last_c_pos to account for wrap_offset and set
+            cpos_adjusted to let the caller know. */
+         if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+           {
+             _rl_last_c_pos -= wrap_offset;
+             cpos_adjusted = 1;
+           }
+         return;
+       }
       /* Sometimes it is cheaper to print the characters rather than
         use the terminal's capabilities.  If we're growing the number
         of lines, make sure we actually cause the new line to wrap
         around on auto-wrapping terminals. */
-      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
        {
          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
             _rl_horizontal_scroll_mode == 1, inserting the characters with
@@ -1533,11 +1579,16 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
            }
          else
            {
-             /* We have horizontal scrolling and we are not inserting at
-                the end.  We have invisible characters in this line.  This
-                is a dumb update. */
              _rl_output_some_chars (nfd, temp);
              _rl_last_c_pos += col_temp;
+             /* If nfd begins before any invisible characters in the prompt,
+                adjust _rl_last_c_pos to account for wrap_offset and set
+                cpos_adjusted to let the caller know. */
+             if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+               {
+                 _rl_last_c_pos -= wrap_offset;
+                 cpos_adjusted = 1;
+               }
              return;
            }
          /* Copy (new) chars to screen from first diff to last match. */
@@ -1545,15 +1596,15 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if ((temp - lendiff) > 0)
            {
              _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-#if 1
             /* XXX -- this bears closer inspection.  Fixes a redisplay bug
                reported against bash-3.0-alpha by Andreas Schwab involving
                multibyte characters and prompt strings with invisible
                characters, but was previously disabled. */
-             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
-#else
-             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
-#endif
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+             else
+               twidth = temp - lendiff;
+             _rl_last_c_pos += twidth;
            }
        }
       else
@@ -1586,8 +1637,22 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          temp = nls - nfd;
          if (temp > 0)
            {
+             /* If nfd begins at the prompt, or before the invisible
+                characters in the prompt, we need to adjust _rl_last_c_pos
+                in a multibyte locale to account for the wrap offset and
+                set cpos_adjusted accordingly. */
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               {
+                  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
+                  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
+                   {
+                     _rl_last_c_pos -= wrap_offset;
+                     cpos_adjusted = 1;
+                   }
+               }
+              else
+                _rl_last_c_pos += temp;
            }
        }
       /* Otherwise, print over the existing material. */
@@ -1595,8 +1660,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
        {
          if (temp > 0)
            {
+             /* If nfd begins at the prompt, or before the invisible
+                characters in the prompt, we need to adjust _rl_last_c_pos
+                in a multibyte locale to account for the wrap offset and
+                set cpos_adjusted accordingly. */
              _rl_output_some_chars (nfd, temp);
              _rl_last_c_pos += col_temp;               /* XXX */
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               {
+                 if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
+                   {
+                     _rl_last_c_pos -= wrap_offset;
+                     cpos_adjusted = 1;
+                   }
+               }
            }
          lendiff = (oe - old) - (ne - new);
          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1721,7 +1798,7 @@ _rl_move_cursor_relative (new, data)
   int woff;                    /* number of invisible chars on current line */
   int cpos, dpos;              /* current and desired cursor positions */
 
-  woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
+  woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
   cpos = _rl_last_c_pos;
 #if defined (HANDLE_MULTIBYTE)
   /* If we have multibyte characters, NEW is indexed by the buffer point in
@@ -1732,7 +1809,14 @@ _rl_move_cursor_relative (new, data)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
     {
       dpos = _rl_col_width (data, 0, new);
-      if (dpos > prompt_last_invisible)                /* XXX - don't use woff here */
+      /* Use NEW when comparing against the last invisible character in the
+        prompt string, since they're both buffer indices and DPOS is a
+        desired display position. */
+      if ((new > prompt_last_invisible) ||             /* XXX - don't use woff here */
+         (prompt_physical_chars > _rl_screenwidth &&
+          _rl_last_v_pos == prompt_last_screen_line &&
+          wrap_offset != woff &&
+          new > (prompt_last_invisible-_rl_screenwidth-wrap_offset)))
        {
          dpos -= woff;
          /* Since this will be assigned to _rl_last_c_pos at the end (more
@@ -2380,6 +2464,8 @@ _rl_col_width (str, start, end)
 
   if (end <= start)
     return 0;
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (end - start);
 
   memset (&ps, 0, sizeof (mbstate_t));
 
index da5d771c4818419983495a28d1e8e0b4aa4faaf8..4206a3e522ba2e1600866f6cbdbf186ef7b9cb88 100644 (file)
@@ -133,8 +133,11 @@ rl_get_char (key)
     return (0);
 
   *key = ibuffer[pop_index++];
-
+#if 0
   if (pop_index >= ibuffer_len)
+#else
+  if (pop_index > ibuffer_len)
+#endif
     pop_index = 0;
 
   return (1);
@@ -151,7 +154,7 @@ _rl_unget_char (key)
     {
       pop_index--;
       if (pop_index < 0)
-       pop_index = ibuffer_len - 1;
+       pop_index = ibuffer_len;
       ibuffer[pop_index] = key;
       return (1);
     }
@@ -250,7 +253,8 @@ rl_gather_tyi ()
       while (chars_avail--)
        {
          k = (*rl_getc_function) (rl_instream);
-         rl_stuff_char (k);
+         if (rl_stuff_char (k) == 0)
+           break;                      /* some problem; no more room */
          if (k == NEWLINE || k == RETURN)
            break;
        }
@@ -373,7 +377,11 @@ rl_stuff_char (key)
       RL_SETSTATE (RL_STATE_INPUTPENDING);
     }
   ibuffer[push_index++] = key;
+#if 0
   if (push_index >= ibuffer_len)
+#else
+  if (push_index > ibuffer_len)
+#endif
     push_index = 0;
 
   return 1;
@@ -513,20 +521,26 @@ _rl_read_mbchar (mbchar, size)
      char *mbchar;
      int size;
 {
-  int mb_len = 0;
+  int mb_len, c;
   size_t mbchar_bytes_length;
   wchar_t wc;
   mbstate_t ps, ps_back;
 
   memset(&ps, 0, sizeof (mbstate_t));
   memset(&ps_back, 0, sizeof (mbstate_t));
-  
+
+  mb_len = 0;  
   while (mb_len < size)
     {
       RL_SETSTATE(RL_STATE_MOREINPUT);
-      mbchar[mb_len++] = rl_read_key ();
+      c = rl_read_key ();
       RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+      if (c < 0)
+       break;
+
+      mbchar[mb_len++] = c;
+
       mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
       if (mbchar_bytes_length == (size_t)(-1))
        break;          /* invalid byte sequence for the current locale */
@@ -564,7 +578,7 @@ _rl_read_mbstring (first, mb, mlen)
 
   c = first;
   memset (mb, 0, mlen);
-  for (i = 0; i < mlen; i++)
+  for (i = 0; c >= 0 && i < mlen; i++)
     {
       mb[i] = (char)c;
       memset (&ps, 0, sizeof (mbstate_t));
index 9f67bfc08018723f2896932e0c70ddf157b5e156..2ed459f1cd5eca38cd33085ddcbad40d48f94e44 100644 (file)
@@ -327,8 +327,15 @@ _rl_isearch_dispatch (cxt, c)
   rl_command_func_t *f;
 
   f = (rl_command_func_t *)NULL;
- /* Translate the keys we do something with to opcodes. */
+
+  if (c < 0)
+    {
+      cxt->sflags |= SF_FAILED;
+      cxt->history_pos = cxt->last_found_line;
+      return -1;
+    }
+
+  /* Translate the keys we do something with to opcodes. */
   if (c >= 0 && _rl_keymap[c].type == ISFUNC)
     {
       f = _rl_keymap[c].function;
index 94ecb25900a033da18d51d8b68e316cdb641453d..e9c72c50cdb5be3a13a2ef1822f112f0f6c45273 100644 (file)
@@ -146,6 +146,8 @@ _rl_arg_dispatch (cxt, c)
          rl_restore_prompt ();
          rl_clear_message ();
          RL_UNSETSTATE(RL_STATE_NUMERICARG);
+         if (key < 0)
+           return -1;
          return (_rl_dispatch (key, _rl_keymap));
        }
     }
index c2b74006b05045ceb82542ddc6e2d910e979bf2c..bd4d263761899eae44bc8a102f0cfbbe93ee04de 100644 (file)
@@ -645,6 +645,11 @@ _rl_dispatch_callback (cxt)
   if ((cxt->flags & KSEQ_DISPATCHED) == 0)
     {
       nkey = _rl_subseq_getchar (cxt->okey);
+      if (nkey < 0)
+       {
+         _rl_abort_internal ();
+         return -1;
+       }
       r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
       cxt->flags |= KSEQ_DISPATCHED;
     }
index 399a48c5f1e7a297069bf0ed8caa09523312650f..cb2f5ad201598ddbb5667930b9a90c5228035f54 100644 (file)
@@ -857,6 +857,9 @@ _rl_insert_next (count)
   c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+  if (c < 0)
+    return -1;
+
 #if defined (HANDLE_SIGNALS)
   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
     _rl_restore_tty_signals ();
@@ -1520,6 +1523,9 @@ _rl_char_search (count, fdir, bdir)
 
   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
 
+  if (mb_len <= 0)
+    return -1;
+
   if (count < 0)
     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
   else
@@ -1536,6 +1542,9 @@ _rl_char_search (count, fdir, bdir)
   c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+  if (c < 0)
+    return -1;
+
   if (count < 0)
     return (_rl_char_search_internal (-count, bdir, c));
   else
index d0b7e330adc479191dcf6faa121aa2f681b405f3..b0da0abd247fd92049a2752494c73a114e1066c6 100644 (file)
@@ -886,6 +886,13 @@ rl_vi_domove (key, nextkey)
   RL_SETSTATE(RL_STATE_MOREINPUT);
   c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    {
+      *nextkey = 0;
+      return -1;
+    }
+
   *nextkey = c;
 
   if (!member (c, vi_motion))
@@ -902,6 +909,11 @@ rl_vi_domove (key, nextkey)
          RL_SETSTATE(RL_STATE_MOREINPUT);
          c = rl_read_key ();   /* real command */
          RL_UNSETSTATE(RL_STATE_MOREINPUT);
+         if (c < 0)
+           {
+             *nextkey = 0;
+             return -1;
+           }
          *nextkey = c;
        }
       else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
@@ -1224,14 +1236,22 @@ static int
 _rl_vi_callback_char_search (data)
      _rl_callback_generic_arg *data;
 {
+  int c;
 #if defined (HANDLE_MULTIBYTE)
-  _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+  c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
 #else
   RL_SETSTATE(RL_STATE_MOREINPUT);
-  _rl_vi_last_search_char = rl_read_key ();
+  c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 #endif
 
+  if (c <= 0)
+    return -1;
+
+#if !defined (HANDLE_MULTIBYTE)
+  _rl_vi_last_search_char = c;
+#endif
+
   _rl_callback_func = 0;
   _rl_want_redisplay = 1;
 
@@ -1247,6 +1267,7 @@ int
 rl_vi_char_search (count, key)
      int count, key;
 {
+  int c;
 #if defined (HANDLE_MULTIBYTE)
   static char *target;
   static int tlen;
@@ -1293,11 +1314,17 @@ rl_vi_char_search (count, key)
       else
        {
 #if defined (HANDLE_MULTIBYTE)
-         _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+         c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+         if (c <= 0)
+           return -1;
+         _rl_vi_last_search_mblen = c;
 #else
          RL_SETSTATE(RL_STATE_MOREINPUT);
-         _rl_vi_last_search_char = rl_read_key ();
+         c = rl_read_key ();
          RL_UNSETSTATE(RL_STATE_MOREINPUT);
+         if (c < 0)
+           return -1;
+         _rl_vi_last_search_char = c;
 #endif
        }
     }
@@ -1467,6 +1494,9 @@ _rl_vi_callback_getchar (mb, mlen)
   c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+  if (c < 0)
+    return -1;
+
 #if defined (HANDLE_MULTIBYTE)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
     c = _rl_read_mbstring (c, mb, mlen);
@@ -1485,6 +1515,9 @@ _rl_vi_callback_change_char (data)
 
   _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
 
+  if (c < 0)
+    return -1;
+
   _rl_callback_func = 0;
   _rl_want_redisplay = 1;
 
@@ -1516,6 +1549,9 @@ rl_vi_change_char (count, key)
   else
     _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
 
+  if (c < 0)
+    return -1;
+
   return (_rl_vi_change_char (count, c, mb));
 }
 
@@ -1650,7 +1686,7 @@ _rl_vi_set_mark ()
   ch = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
-  if (ch < 'a' || ch > 'z')
+  if (ch < 0 || ch < 'a' || ch > 'z')  /* make test against 0 explicit */
     {
       rl_ding ();
       return -1;
@@ -1702,7 +1738,7 @@ _rl_vi_goto_mark ()
       rl_point = rl_mark;
       return 0;
     }
-  else if (ch < 'a' || ch > 'z')
+  else if (ch < 0 || ch < 'a' || ch > 'z')     /* make test against 0 explicit */
     {
       rl_ding ();
       return -1;
index cd724f6f8d9bdc64b226fddabeddada6d0407918..1a0279435325a0d45be6e2e2811529483bcff195 100644 (file)
@@ -251,19 +251,21 @@ getcwd (buf, size)
 
   {
     size_t len = pathbuf + pathsize - pathp;
+    if (buf == NULL && size <= 0)
+      size = len;
+
+    if ((size_t) size < len)
+      {
+       errno = ERANGE;
+       goto lose2;
+      }
     if (buf == NULL)
       {
-       if (len < (size_t) size)
-         len = size;
-       buf = (char *) malloc (len);
+       buf = (char *) malloc (size);
        if (buf == NULL)
          goto lose2;
       }
-    else if ((size_t) size < len)
-      {
-       errno = ERANGE;
-       goto lose2;
-      }
+
     (void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
   }
 
index 4a964746d1f6c1c3b6b566ab8783dc97915f461f..246a01aee5cc59194ec656dc14c643f785ae5019 100644 (file)
@@ -471,6 +471,8 @@ pow_10(n)
          10^x ~= r
  * log_10(200) = 2;
  * log_10(250) = 2;
+ *
+ * NOTE: do not call this with r == 0 -- an infinite loop results.
  */
 static int
 log_10(r)
@@ -576,8 +578,11 @@ numtoa(number, base, precision, fract)
     { 
       integral_part[0] = '0';
       integral_part[1] = '\0';
-      fraction_part[0] = '0';
-      fraction_part[1] = '\0';
+      /* The fractional part has to take the precision into account */
+      for (ch = 0; ch < precision-1; ch++)
+       fraction_part[ch] = '0';
+      fraction_part[ch] = '0';
+      fraction_part[ch+1] = '\0';
       if (fract)
        *fract = fraction_part;
       return integral_part;
@@ -663,7 +668,8 @@ number(p, d, base)
     p->flags &= ~PF_ZEROPAD;
 
   sd = d;      /* signed for ' ' padding in base 10 */
-  flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
+  flags = 0;
+  flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
   if (*p->pf == 'X')
     flags |= FL_HEXUPPER;
 
@@ -733,7 +739,7 @@ lnumber(p, d, base)
     p->flags &= ~PF_ZEROPAD;
 
   sd = d;      /* signed for ' ' padding in base 10 */
-  flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
+  flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
   if (*p->pf == 'X')
     flags |= FL_HEXUPPER;
 
@@ -805,6 +811,7 @@ pointer(p, d)
       PUT_CHAR(*tmp, p);
       tmp++;
     }
+
   PAD_LEFT(p);
 }
 
@@ -972,11 +979,21 @@ floating(p, d)
   if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
     tmp = t;
 
+  if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
+    {
+      /* smash the trailing zeros unless altform */
+      for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
+        tmp2[i] = '\0'; 
+      if (tmp2[0] == '\0')
+       p->precision = 0;
+    }
+
   /* calculate the padding. 1 for the dot */
   p->width = p->width -
            ((d > 0. && p->justify == RIGHT) ? 1:0) -
            ((p->flags & PF_SPACE) ? 1:0) -
-           strlen(tmp) - p->precision - 1;
+           strlen(tmp) - p->precision -
+           ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0);   /* radix char */
   PAD_RIGHT(p);  
   PUT_PLUS(d, p, 0.);
   PUT_SPACE(d, p, 0.);
@@ -991,11 +1008,6 @@ floating(p, d)
   if (p->precision != 0 || (p->flags & PF_ALTFORM))
     PUT_CHAR(decpoint, p);  /* put the '.' */
 
-  if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
-    /* smash the trailing zeros unless altform */
-    for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
-      tmp2[i] = '\0'; 
-
   for (; *tmp2; tmp2++)
     PUT_CHAR(*tmp2, p); /* the fraction */
   
@@ -1011,14 +1023,19 @@ exponent(p, d)
   char *tmp, *tmp2;
   int j, i;
 
-  if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
+  if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
     return;    /* already printed nan or inf */
 
   GETLOCALEDATA(decpoint, thoussep, grouping);
   DEF_PREC(p);
-  j = log_10(d);
-  d = d / pow_10(j);  /* get the Mantissa */
-  d = ROUND(d, p);               
+  if (d == 0.)
+    j = 0;
+  else
+    {
+      j = log_10(d);
+      d = d / pow_10(j);  /* get the Mantissa */
+      d = ROUND(d, p);           
+    }
   tmp = dtoa(d, p->precision, &tmp2);
 
   /* 1 for unit, 1 for the '.', 1 for 'e|E',
@@ -1076,6 +1093,7 @@ exponent(p, d)
        PUT_CHAR(*tmp, p);
        tmp++;
      }
+
    PAD_LEFT(p);
 }
 #endif
@@ -1358,7 +1376,7 @@ conv_break:
                STAR_ARGS(data);
                DEF_PREC(data);
                d = GETDOUBLE(data);
-               i = log_10(d);
+               i = (d != 0.) ? log_10(d) : -1;
                /*
                 * for '%g|%G' ANSI: use f if exponent
                 * is in the range or [-4,p] exclusively
diff --git a/parse.y b/parse.y
index c7dd436f6d19aab7d13b8e960579e19e2fd58379..8a2b081ac0ff8a7d394962c514e19ad63b30ea54 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -1029,6 +1029,7 @@ timespec: TIME
 #define PST_CMDTOKEN   0x1000          /* command token OK - unused */
 #define PST_COMPASSIGN 0x2000          /* parsing x=(...) compound assignment */
 #define PST_ASSIGNOK   0x4000          /* assignment statement ok in this context */
+#define PST_REGEXP     0x8000          /* parsing an ERE/BRE as a single word */
 
 /* Initial size to allocate for tokens, and the
    amount to grow them by. */
@@ -2591,6 +2592,9 @@ read_token (command)
       return (character);
     }
 
+  if (parser_state & PST_REGEXP)
+    goto tokword;
+
   /* Shell meta-characters. */
   if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
     {
@@ -2698,6 +2702,7 @@ read_token (command)
   if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
     return (character);
 
+tokword:
   /* Okay, if we got this far, we have to read a word.  Read one,
      and then check it against the known ones. */
   result = read_token_word (character);
@@ -2735,7 +2740,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
 /* itrace("parse_matched_pair: open = %c close = %c", open, close); */
   count = 1;
   pass_next_character = backq_backslash = was_dollar = in_comment = 0;
-  check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
+  check_comment = (flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
 
   /* RFLAGS is the set of flags we want to pass to recursive calls. */
   rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
@@ -3202,8 +3207,11 @@ cond_term ()
       if (tok == WORD && test_binop (yylval.word->word))
        op = yylval.word;
 #if defined (COND_REGEXP)
-      else if (tok == WORD && STREQ (yylval.word->word,"=~"))
-       op = yylval.word;
+      else if (tok == WORD && STREQ (yylval.word->word, "=~"))
+       {
+         op = yylval.word;
+         parser_state |= PST_REGEXP;
+       }
 #endif
       else if (tok == '<' || tok == '>')
        op = make_word_from_token (tok);  /* ( */
@@ -3234,6 +3242,7 @@ cond_term ()
 
       /* rhs */
       tok = read_token (READ);
+      parser_state &= ~PST_REGEXP;
       if (tok == WORD)
        {
          tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
@@ -3367,7 +3376,7 @@ read_token_word (character)
       if (pass_next_character)
        {
          pass_next_character = 0;
-         goto got_character;
+         goto got_escaped_character;
        }
 
       cd = current_delimiter (dstack);
@@ -3419,9 +3428,34 @@ read_token_word (character)
          goto next_character;
        }
 
+#ifdef COND_REGEXP
+      /* When parsing a regexp as a single word inside a conditional command,
+        we need to special-case characters special to both the shell and
+        regular expressions.  Right now, that is only '(' and '|'. */ /*)*/
+      if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|'))         /*)*/
+        {
+          if (character == '|')
+            goto got_character;
+
+         push_delimiter (dstack, character);
+         ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
+         pop_delimiter (dstack);
+         if (ttok == &matched_pair_error)
+           return -1;          /* Bail immediately. */
+         RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+                                 token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
+         token[token_index++] = character;
+         strcpy (token + token_index, ttok);
+         token_index += ttoklen;
+         FREE (ttok);
+         dollar_present = all_digit_token = 0;
+         goto next_character;
+        }
+#endif /* COND_REGEXP */
+
 #ifdef EXTENDED_GLOB
       /* Parse a ksh-style extended pattern matching specification. */
-      if (extended_glob && PATTERN_CHAR (character))
+      if MBTEST(extended_glob && PATTERN_CHAR (character))
        {
          peek_char = shell_getc (1);
          if MBTEST(peek_char == '(')           /* ) */
@@ -3616,12 +3650,14 @@ read_token_word (character)
 
     got_character:
 
-      all_digit_token &= DIGIT (character);
-      dollar_present |= character == '$';
-
       if (character == CTLESC || character == CTLNUL)
        token[token_index++] = CTLESC;
 
+    got_escaped_character:
+
+      all_digit_token &= DIGIT (character);
+      dollar_present |= character == '$';
+
       token[token_index++] = character;
 
       RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
@@ -4330,7 +4366,7 @@ not_escape:
   if (promptvars || posixly_correct)
     {
       last_exit_value = last_command_exit_value;
-      list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
+      list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
       free (result);
       result = string_list (list);
       dispose_words (list);
index 246f7eed949c3a11a822e78de40e5901c4c9129f..aff99d93eb59707e4ec7e6778829a1983d767a5a 100644 (file)
@@ -25,6 +25,6 @@
    regexp `^#define[   ]*PATCHLEVEL', since that's what support/mkversion.sh
    looks for to find the patch level (for the sccs version string). */
 
-#define PATCHLEVEL 0
+#define PATCHLEVEL 48
 
 #endif /* _PATCHLEVEL_H_ */
index a498672f51ec668c266fb581a0a637b726b913c2..69966ac4331bbc2f7d431341d8996b548ac46563 100644 (file)
--- a/pathexp.c
+++ b/pathexp.c
@@ -1,6 +1,6 @@
 /* pathexp.c -- The shell interface to the globbing library. */
 
-/* Copyright (C) 1995-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -110,6 +110,33 @@ unquoted_glob_pattern_p (string)
   return (0);
 }
 
+/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
+   be quoted to match itself. */
+static inline int
+ere_char (c)
+     int c;
+{
+  switch (c)
+    {
+    case '.':
+    case '[':
+    case '\\':
+    case '(':
+    case ')':
+    case '*':
+    case '+':
+    case '?':
+    case '{':
+    case '|':
+    case '^':
+    case '$':
+      return 1;
+    default: 
+      return 0;
+    }
+  return (0);
+}
+
 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
    that the character is to be quoted.  We quote it here in the style
    that the glob library recognizes.  If flags includes QGLOB_CVTNULL,
@@ -142,6 +169,8 @@ quote_string_for_globbing (pathname, qflags)
        {
          if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
            continue;
+         if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
+           continue;
          temp[j++] = '\\';
          i++;
          if (pathname[i] == '\0')
index 5f1731ad99b3b9a2d811d867a373f3e3d70b8ea3..b4afcb3a4d0dbe4e1b67464e9e67a1bffb235795 100644 (file)
--- a/pathexp.h
+++ b/pathexp.h
@@ -1,6 +1,6 @@
 /* pathexp.h -- The shell interface to the globbing library. */
 
-/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -32,6 +32,7 @@ extern char *glob_error_return;
 /* Flag values for quote_string_for_globbing */
 #define QGLOB_CVTNULL  0x01    /* convert QUOTED_NULL strings to '\0' */
 #define QGLOB_FILENAME 0x02    /* do correct quoting for matching filenames */
+#define QGLOB_REGEXP   0x04    /* quote an ERE for regcomp/regexec */
 
 #if defined (EXTENDED_GLOB)
 /* Flags to OR with other flag args to strmatch() to enabled the extended
diff --git a/po/ru.gmo b/po/ru.gmo
new file mode 100644 (file)
index 0000000..53c5ef4
Binary files /dev/null and b/po/ru.gmo differ
index 5eecad930221c14dfef01618bb3f5ee6f8844f0a..30b487717324f494ab1d0971847e34d331b3f762 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -12,7 +12,7 @@ msgstr ""
 "Last-Translator: Evgeniy Dushistov <dushistov@mail.ru>\n"
 "Language-Team: Russian <ru@li.org>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Type: text/plain; charset=KOI8-R\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
diff --git a/shell.h b/shell.h
index ec086885ef57f1ba651716c8460dfe8d1b85ae04..8b6a4fc592ccef331187ef8a117aa0dccd9085f3 100644 (file)
--- a/shell.h
+++ b/shell.h
@@ -89,6 +89,7 @@ extern int debugging_mode;
 extern int executing, login_shell;
 extern int interactive, interactive_shell;
 extern int startup_state;
+extern int shell_compatibility_level;
 
 /* Structure to pass around that holds a bitmap of file descriptors
    to close, and the size of that structure.  Used in execute_cmd.c. */
diff --git a/sig.c b/sig.c
index 2bd6cae606dd8c24a01f2f897636036f79627b3b..c479a4a0dfa0338cc88b7681fbd8b9d076d084ed 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -350,6 +350,25 @@ reset_terminating_signals ()
 #undef XSIG
 #undef XHANDLER
 
+/* Run some of the cleanups that should be performed when we run
+   jump_to_top_level from a builtin command context.  XXX - might want to
+   also call reset_parser here. */
+void
+top_level_cleanup ()
+{
+  /* Clean up string parser environment. */
+  while (parse_and_execute_level)
+    parse_and_execute_cleanup ();
+
+#if defined (PROCESS_SUBSTITUTION)
+  unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+  run_unwind_protects ();
+  loop_level = continuing = breaking = 0;
+  return_catch_flag = 0;
+}
+
 /* What to do when we've been interrupted, and it is safe to handle it. */
 void
 throw_to_top_level ()
diff --git a/sig.h b/sig.h
index a23f94c59a522d938218488180ec0dbe1e3433e3..46bded81f6ca06990d380b201629d77cb50bfba4 100644 (file)
--- a/sig.h
+++ b/sig.h
@@ -121,6 +121,7 @@ extern sighandler sigint_sighandler __P((int));
 extern void initialize_signals __P((int));
 extern void initialize_terminating_signals __P((void));
 extern void reset_terminating_signals __P((void));
+extern void top_level_cleanup __P((void));
 extern void throw_to_top_level __P((void));
 extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
 
diff --git a/subst.c b/subst.c
index 37f5d00b8bec812520acabb821cd0eb4e55f8232..089457fb09ee539354ae6de773337a5fcd8b965e 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4,7 +4,7 @@
 /* ``Have a little faith, there's magic in the night.  You ain't a
      beauty, but, hey, you're alright.'' */
 
-/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -137,7 +137,7 @@ unsigned char ifs_firstc;
 /* Extern functions and variables from different files. */
 extern int last_command_exit_value, last_command_exit_signal;
 extern int subshell_environment;
-extern int subshell_level;
+extern int subshell_level, parse_and_execute_level;
 extern int eof_encountered;
 extern int return_catch_flag, return_catch_value;
 extern pid_t dollar_dollar_pid;
@@ -1278,7 +1278,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
     {
       if (no_longjmp_on_fatal_error == 0)
        {                       /* { */
-         report_error ("bad substitution: no closing `%s' in %s", "}", string);
+         report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
          last_command_exit_value = EXECUTION_FAILURE;
          exp_jump_to_top_level (DISCARD);
        }
@@ -1887,7 +1887,13 @@ string_list_dollar_at (list, quoted)
   sep[1] = '\0';
 #endif
 
+  /* XXX -- why call quote_list if ifs == 0?  we can get away without doing
+     it now that quote_escapes quotes spaces */
+#if 0
   tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
+#else
+  tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+#endif
                ? quote_list (list)
                : list_quote_escapes (list);
 
@@ -2646,11 +2652,12 @@ remove_backslashes (string)
 
 /* This needs better error handling. */
 /* Expand W for use as an argument to a unary or binary operator in a
-   [[...]] expression.  If SPECIAL is nonzero, this is the rhs argument
+   [[...]] expression.  If SPECIAL is 1, this is the rhs argument
    to the != or == operator, and should be treated as a pattern.  In
-   this case, we quote the string specially for the globbing code.  The
-   caller is responsible for removing the backslashes if the unquoted
-   words is needed later. */   
+   this case, we quote the string specially for the globbing code.  If
+   SPECIAL is 2, this is an rhs argument for the =~ operator, and should
+   be quoted appropriately for regcomp/regexec.  The caller is responsible
+   for removing the backslashes if the unquoted word is needed later. */   
 char *
 cond_expand_word (w, special)
      WORD_DESC *w;
@@ -2658,6 +2665,7 @@ cond_expand_word (w, special)
 {
   char *r, *p;
   WORD_LIST *l;
+  int qflags;
 
   if (w->word == 0 || w->word[0] == '\0')
     return ((char *)NULL);
@@ -2672,8 +2680,11 @@ cond_expand_word (w, special)
        }
       else
        {
+         qflags = QGLOB_CVTNULL;
+         if (special == 2)
+           qflags |= QGLOB_REGEXP;
          p = string_list (l);
-         r = quote_string_for_globbing (p, QGLOB_CVTNULL);
+         r = quote_string_for_globbing (p, qflags);
          free (p);
        }
       dispose_words (l);
@@ -2803,9 +2814,10 @@ expand_string_assignment (string, quoted)
    passed string when an error occurs.  Might want to trap other calls
    to jump_to_top_level here so we don't endlessly loop. */
 WORD_LIST *
-expand_prompt_string (string, quoted)
+expand_prompt_string (string, quoted, wflags)
      char *string;
      int quoted;
+     int wflags;
 {
   WORD_LIST *value;
   WORD_DESC td;
@@ -2813,7 +2825,7 @@ expand_prompt_string (string, quoted)
   if (string == 0 || *string == 0)
     return ((WORD_LIST *)NULL);
 
-  td.flags = 0;
+  td.flags = wflags;
   td.word = savestring (string);
 
   no_longjmp_on_fatal_error = 1;
@@ -2916,7 +2928,12 @@ expand_string (string, quoted)
 
 /* Quote escape characters in string s, but no other characters.  This is
    used to protect CTLESC and CTLNUL in variable values from the rest of
-   the word expansion process after the variable is expanded. */
+   the word expansion process after the variable is expanded.  If IFS is
+   null, we quote spaces as well, just in case we split on spaces later
+   (in the case of unquoted $@, we will eventually attempt to split the
+   entire word on spaces).  Corresponding code exists in dequote_escapes.
+   Even if we don't end up splitting on spaces, quoting spaces is not a
+   problem. */
 char *
 quote_escapes (string)
      char *string;
@@ -2924,17 +2941,19 @@ quote_escapes (string)
   register char *s, *t;
   size_t slen;
   char *result, *send;
+  int quote_spaces;
   DECLARE_MBSTATE; 
 
   slen = strlen (string);
   send = string + slen;
 
+  quote_spaces = (ifs_value && *ifs_value == 0);
   t = result = (char *)xmalloc ((slen * 2) + 1);
   s = string;
 
   while (*s)
     {
-      if (*s == CTLESC || *s == CTLNUL)
+      if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
        *t++ = CTLESC;
       COPY_CHAR_P (t, s, send);
     }
@@ -2976,6 +2995,7 @@ dequote_escapes (string)
   register char *s, *t;
   size_t slen;
   char *result, *send;
+  int quote_spaces;
   DECLARE_MBSTATE;
 
   if (string == 0)
@@ -2990,9 +3010,10 @@ dequote_escapes (string)
   if (strchr (string, CTLESC) == 0)
     return (strcpy (result, s));
 
+  quote_spaces = (ifs_value && *ifs_value == 0);
   while (*s)
     {
-      if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
+      if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
        {
          s++;
          if (*s == '\0')
@@ -3954,7 +3975,11 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
     patstr++;
 
-  pattern = getpattern (patstr, quoted, 1);
+  /* Need to pass getpattern newly-allocated memory in case of expansion --
+     the expansion code will free the passed string on an error. */
+  temp1 = savestring (patstr);
+  pattern = getpattern (temp1, quoted, 1);
+  free (temp1);
 
   temp1 = (char *)NULL;                /* shut up gcc */
   switch (vtype)
@@ -4123,6 +4148,12 @@ unlink_fifo_list ()
     nfifo = 0;
 }
 
+int
+fifos_pending ()
+{
+  return nfifo;
+}
+
 static char *
 make_named_pipe ()
 {
@@ -4172,6 +4203,12 @@ add_fifo_list (fd)
   nfds++;
 }
 
+int
+fifos_pending ()
+{
+  return 0;    /* used for cleanup; not needed with /dev/fd */
+}
+
 void
 unlink_fifo_list ()
 {
@@ -4456,7 +4493,15 @@ read_comsub (fd, quoted)
       /* Add the character to ISTRING, possibly after resizing it. */
       RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
 
-      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
+      /* This is essentially quote_string inline */
+      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
+       istring[istring_index++] = CTLESC;
+      /* Escape CTLESC and CTLNUL in the output to protect those characters
+        from the rest of the word expansions (word splitting and globbing.)
+        This is essentially quote_escapes inline. */
+      else if (c == CTLESC)
+       istring[istring_index++] = CTLESC;
+      else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
        istring[istring_index++] = CTLESC;
 
       istring[istring_index++] = c;
@@ -4578,7 +4623,8 @@ command_substitute (string, quoted)
 #if defined (JOB_CONTROL)
   set_sigchld_handler ();
   stop_making_children ();
-  pipeline_pgrp = old_pipeline_pgrp;
+  if (pid != 0)
+    pipeline_pgrp = old_pipeline_pgrp;
 #else
   stop_making_children ();
 #endif /* JOB_CONTROL */
@@ -4665,6 +4711,9 @@ command_substitute (string, quoted)
 
       last_command_exit_value = rc;
       rc = run_exit_trap ();
+#if defined (PROCESS_SUBSTITUTION)
+      unlink_fifo_list ();
+#endif
       exit (rc);
     }
   else
@@ -4763,7 +4812,7 @@ array_length_reference (s)
   else
     t = (ind == 0) ? value_cell (var) : (char *)NULL;
 
-  len = STRLEN (t);
+  len = MB_STRLEN (t);
   return (len);
 }
 #endif /* ARRAY_VARS */
@@ -4860,10 +4909,11 @@ parameter_brace_expand_word (name, var_is_special, quoted)
   char *temp, *tt;
   intmax_t arg_index;
   SHELL_VAR *var;
-  int atype;
+  int atype, rflags;
 
   ret = 0;
   temp = 0;
+  rflags = 0;
 
   /* Handle multiple digit arguments, as in ${11}. */  
   if (legal_number (name, &arg_index))
@@ -4896,6 +4946,8 @@ parameter_brace_expand_word (name, var_is_special, quoted)
        temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
                  ? quote_string (temp)
                  : quote_escapes (temp);
+      else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+       rflags |= W_HASQUOTEDNULL;
     }
 #endif
   else if (var = find_variable (name))
@@ -4923,6 +4975,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
     {
       ret = alloc_word_desc ();
       ret->word = temp;
+      ret->flags |= rflags;
     }
   return ret;
 }
@@ -5546,12 +5599,16 @@ parameter_brace_substring (varname, value, substr, quoted)
         so verify_substring_values just returns the numbers specified and we
         rely on array_subrange to understand how to deal with them). */
       tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
+#if 0
+      /* array_subrange now calls array_quote_escapes as appropriate, so the
+        caller no longer needs to. */
       if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
        {
          temp = tt ? quote_escapes (tt) : (char *)NULL;
          FREE (tt);
        }
       else
+#endif
        temp = tt;
       break;
 #endif
@@ -5707,6 +5764,11 @@ parameter_brace_patsub (varname, value, patsub, quoted)
   vtype &= ~VT_STARSUB;
 
   mflags = 0;
+  if (patsub && *patsub == '/')
+    {
+      mflags |= MATCH_GLOBREP;
+      patsub++;
+    }
 
   /* Malloc this because expand_string_if_necessary or one of the expansion
      functions in its call chain may free it on a substitution error. */
@@ -5741,13 +5803,12 @@ parameter_brace_patsub (varname, value, patsub, quoted)
     }
 
   /* ksh93 doesn't allow the match specifier to be a part of the expanded
-     pattern.  This is an extension. */
+     pattern.  This is an extension.  Make sure we don't anchor the pattern
+     at the beginning or end of the string if we're doing global replacement,
+     though. */
   p = pat;
-  if (pat && pat[0] == '/')
-    {
-      mflags |= MATCH_GLOBREP|MATCH_ANY;
-      p++;
-    }
+  if (mflags & MATCH_GLOBREP)
+    mflags |= MATCH_ANY;
   else if (pat && pat[0] == '#')
     {
       mflags |= MATCH_BEG;
@@ -5798,12 +5859,16 @@ parameter_brace_patsub (varname, value, patsub, quoted)
 #if defined (ARRAY_VARS)
     case VT_ARRAYVAR:
       temp = array_patsub (array_cell (v), p, rep, mflags);
+#if 0
+      /* Don't need to do this anymore; array_patsub calls array_quote_escapes
+        as appropriate before adding the space separators. */
       if (temp && (mflags & MATCH_QUOTED) == 0)
        {
          tt = quote_escapes (temp);
          free (temp);
          temp = tt;
        }
+#endif
       break;
 #endif
     }
@@ -7607,6 +7672,10 @@ exp_jump_to_top_level (v)
   expand_no_split_dollar_star = 0;     /* XXX */
   expanding_redir = 0;
 
+  if (parse_and_execute_level == 0)
+    top_level_cleanup ();                      /* from sig.c */
+
+
   jump_to_top_level (v);
 }
 
@@ -7824,7 +7893,7 @@ glob_expand_word_list (tlist, eflags)
          else if (fail_glob_expansion != 0)
            {
              report_error (_("no match: %s"), tlist->word->word);
-             jump_to_top_level (DISCARD);
+             exp_jump_to_top_level (DISCARD);
            }
          else if (allow_null_glob_expansion == 0)
            {
diff --git a/subst.h b/subst.h
index 9bc6e2be0f81af1ab9574f2ad24d841e91110bd4..3c3828f5455f6ba938b4ad70dcd9997778ee3abc 100644 (file)
--- a/subst.h
+++ b/subst.h
@@ -135,7 +135,7 @@ extern WORD_LIST *expand_string_unsplit __P((char *, int));
 extern WORD_LIST *expand_string_assignment __P((char *, int));
 
 /* Expand a prompt string. */
-extern WORD_LIST *expand_prompt_string __P((char *, int));
+extern WORD_LIST *expand_prompt_string __P((char *, int, int));
 
 /* Expand STRING just as if you were expanding a word.  This also returns
    a list of words.  Note that filename globbing is *NOT* done for word
@@ -222,6 +222,7 @@ extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
 extern char *command_substitute __P((char *, int));
 extern char *pat_subst __P((char *, char *, char *, int));
 
+extern int fifos_pending __P((void));
 extern void unlink_fifo_list __P((void));
 
 extern WORD_LIST *list_string_with_quotes __P((char *));
index f2dfbc1378adb6d3ca5a126738630f1be9afb626..bff3dd4b075fa504febcd0ec16e9618a367497a2 100644 (file)
@@ -430,7 +430,7 @@ Case05---3---A:B:C---
 Case06---1---A B C::---
 Case07---3---A:B:C---
 Case08---3---A:B:C---
-./new-exp.tests: line 506: /${$(($#-1))}: bad substitution
+./new-exp.tests: line 506: ${$(($#-1))}: bad substitution
 argv[1] = <a>
 argv[2] = <b>
 argv[3] = <c>
index b2fc219c272689ad5ecde5322e7c0f841a0983a0..55b6fc9528f1c280ac39458dd1a03dcd26064af4 100644 (file)
@@ -6,6 +6,7 @@ shopt -s cdspell
 shopt -u checkhash
 shopt -u checkwinsize
 shopt -s cmdhist
+shopt -u compat31
 shopt -u dotglob
 shopt -u execfail
 shopt -s expand_aliases
@@ -53,6 +54,7 @@ shopt -s sourcepath
 shopt -u cdable_vars
 shopt -u checkhash
 shopt -u checkwinsize
+shopt -u compat31
 shopt -u dotglob
 shopt -u execfail
 shopt -u extdebug
@@ -77,6 +79,7 @@ shopt -u xpg_echo
 cdable_vars            off
 checkhash              off
 checkwinsize           off
+compat31               off
 dotglob                off
 execfail               off
 extdebug               off
index 5fd9d0e992e30ff419df63af981d1081770f732e..725cfa6927867316169b16c2296be77bbc29e70d 100644 (file)
@@ -1821,11 +1821,17 @@ make_variable_value (var, value, flags)
          oval = value_cell (var);
          lval = evalexp (oval, &expok);        /* ksh93 seems to do this */
          if (expok == 0)
-           jump_to_top_level (DISCARD);
+           {
+             top_level_cleanup ();
+             jump_to_top_level (DISCARD);
+           }
        }
       rval = evalexp (value, &expok);
       if (expok == 0)
-       jump_to_top_level (DISCARD);
+       {
+         top_level_cleanup ();
+         jump_to_top_level (DISCARD);
+       }
       if (flags & ASS_APPEND)
        rval += lval;
       retval = itos (rval);
@@ -3452,9 +3458,11 @@ push_func_var (data)
       if (shell_variables == global_variables)
        var->attributes &= ~(att_tempvar|att_propagate);
       else
-        shell_variables->flags |= VC_HASTMPVAR;
+       shell_variables->flags |= VC_HASTMPVAR;
       v->attributes |= var->attributes;
     }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
 
   dispose_variable (var);
 }
@@ -3541,6 +3549,8 @@ push_exported_var (data)
        var->attributes &= ~att_propagate;
       v->attributes |= var->attributes;
     }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
 
   dispose_variable (var);
 }
index f373372765db581d873e2a040c828712225eec6b..0a8173f89b94da3cb24dec91d4f0a501d57767ed 100644 (file)
--- a/version.c
+++ b/version.c
@@ -43,6 +43,9 @@ const char *release_status = (char *)0;
 #endif
 const char *sccs_version = SCCSVERSION;
 
+/* If == 31, shell compatible with bash-3.1, == 32 with bash-3.2, and so on */
+int shell_compatibility_level = 32;
+
 /* Functions for getting, setting, and displaying the shell version. */
 
 /* Forward declarations so we don't have to include externs.h */
@@ -79,5 +82,5 @@ show_shell_version (extended)
 {
   printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE);
   if (extended)
-    printf (_("Copyright (C) 2005 Free Software Foundation, Inc.\n"));
+    printf (_("Copyright (C) 2007 Free Software Foundation, Inc.\n"));
 }