]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20070503 snapshot
authorChet Ramey <chet.ramey@case.edu>
Wed, 7 Dec 2011 14:07:29 +0000 (09:07 -0500)
committerChet Ramey <chet.ramey@case.edu>
Wed, 7 Dec 2011 14:07:29 +0000 (09:07 -0500)
29 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
builtins/alias.def
builtins/bind.def
builtins/cd.def
builtins/common.c
builtins/common.h
builtins/complete.def
builtins/declare.def
builtins/echo.def
builtins/fc.def
builtins/history.def
builtins/pushd.def
builtins/set.def
builtins/setattr.def
builtins/shopt.def
builtins/times.def
builtins/trap.def
builtins/type.def
builtins/ulimit.def
builtins/umask.def
doc/bash.1
doc/bashref.texi
doc/version.texi
lib/readline/examples/x [new file with mode: 0644]
lib/readline/input.c
print_cmd.c
print_cmd.c~ [new file with mode: 0644]
tests/RUN-ONE-TEST

index 50934714ab3d224fab722fa50e7e7ed014699cfe..4e7ea3e8fb26c2b4ea890ebe848ed13cf1217a64 100644 (file)
@@ -14537,6 +14537,45 @@ redir.c
          make sure all output is flushed before changing the underlying fd
          out from underneath stdio.  Fix suggested by Eric Blake <ebb9@byu.net>
 
+
+                                  4/30
+                                  ----
+
+builtins/common.c
+       - new function, sh_chkwrite(int), fflushes stdout and checks for error;
+         printing an error message and returning a new exit status if there's
+         an error on stdout.  Takes exit status as argument; returns new exit
+         status (EXECUTION_FAILURE if write error)
+
+builtins/common.h
+       - new extern declaration for sh_chkwrite
+
+builtins/{alias,cd,complete,echo,fc,history,pushd,shopt,times,trap,type,ulimit,umask}.def
+       - change to use sh_chkwrite to report write errors
+
+builtins/fc.def
+       - if an error occurs while writing commands from the history to a file
+         to be executed, report a write error and return failure without
+         attempting to execute any commands
+
+                                   5/1
+                                   ---
+builtins/{bind,declare,set,setattr}.def
+       - change to use sh_chkwrite to report write errors
+
+                                   5/2
+                                   ---
 lib/readline/input.c
-       - fix probable off-by-one error in ibuffer_space () prompted by bug
-         report from Tom Bjorkholm <tom.bjorkholm@ericsson.com>
+       - fix off-by-one errors in _rl_get_char (pop_index) and rl_stuff_char
+         (push_index) that caused the 511th character in the buffer to be
+         discarded.  Fixes bug reported by Tom Bjorkholm <tom.bjorkholm@ericsson.com>
+
+                                   5/5
+                                   ---
+print_cmd.c
+       - added logic (inside_pipeline variable) to print_connection code and
+         print_redirection to handle the case of a command with a here
+         document inside a pipeline.  In that case, print_redirection prints
+         the `|' before the here document text, so the parser knows the
+         command is continued.  Fixes problem with exporting functions with
+         pipelines like this reported by Chris Lesner <chris.lesner@gmail.com>
index 2329b2246d10658157598fa5f08b75b7d1623057..9aee4086c543626c2735b3034a830b02d0ac07c6 100644 (file)
@@ -14536,3 +14536,46 @@ redir.c
          is the same one used by the stdout stream, call fflush(stdout) to
          make sure all output is flushed before changing the underlying fd
          out from underneath stdio.  Fix suggested by Eric Blake <ebb9@byu.net>
+
+
+                                  4/30
+                                  ----
+
+builtins/common.c
+       - new function, sh_chkwrite(int), fflushes stdout and checks for error;
+         printing an error message and returning a new exit status if there's
+         an error on stdout.  Takes exit status as argument; returns new exit
+         status (EXECUTION_FAILURE if write error)
+
+builtins/common.h
+       - new extern declaration for sh_chkwrite
+
+builtins/{alias,cd,complete,echo,fc,history,pushd,shopt,times,trap,type,ulimit,umask}.def
+       - change to use sh_chkwrite to report write errors
+
+builtins/fc.def
+       - if an error occurs while writing commands from the history to a file
+         to be executed, report a write error and return failure without
+         attempting to execute any commands
+
+                                   5/1
+                                   ---
+builtins/{bind,declare,set,setattr}.def
+       - change to use sh_chkwrite to report write errors
+
+                                   5/2
+                                   ---
+lib/readline/input.c
+       - fix off-by-one errors in _rl_get_char (pop_index) and rl_stuff_char
+         (push_index) that caused the 511th character in the buffer to be
+         discarded.  Fixes bug reported by Tom Bjorkholm <tom.bjorkholm@ericsson.com>
+
+                                   5/5
+                                   ---
+print_cmd.c
+       - added logic (inside_pipeline variable) to print_connection code and
+         print_redirection to handle the case of a command with a here
+         document inside a pipeline.  In that case, print_redirection prints
+         the `|' before the here document text, so the parser knows the
+         command is continued.  Fixes problem reported by Chris Lesner
+         <chris.lesner@gmail.com>
index 572910bc41841cbc35e5aad8d2cb38668edaec56..db13869e8715be99a638bd8357039c17b04f0bf2 100644 (file)
@@ -103,7 +103,7 @@ alias_builtin (list)
       free (alias_list);       /* XXX - Do not free the strings. */
 
       if (list == 0)
-       return (EXECUTION_SUCCESS);
+       return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   any_failed = 0;
index ce246dde56fb3df75a5a0a4a7a530c65a021b024..0cbab504cd6caa5dfe78063b5a4f922fc7db23fa 100644 (file)
@@ -266,7 +266,7 @@ bind_builtin (list)
 
   run_unwind_frame ("bind_builtin");
 
-  return (return_code);
+  return (sh_chkwrite (return_code));
 }
 
 static int
index 7d3ff4617b26ce38de1e0eb1bca4b07472e0928c..f6258eb91c6698afabbcb64351a18e1aa0529978 100644 (file)
@@ -108,9 +108,11 @@ bindpwd (no_symlinks)
      int no_symlinks;
 {
   char *dirname, *pwdvar;
-  int old_anm;
+  int old_anm, r;
   SHELL_VAR *tvar;
 
+  r = sh_chkwrite (EXECUTION_SUCCESS);
+
 #define tcwd the_current_working_directory
   dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
                 : get_working_directory ("cd");
@@ -131,7 +133,7 @@ bindpwd (no_symlinks)
   if (dirname && dirname != the_current_working_directory)
     free (dirname);
 
-  return (EXECUTION_SUCCESS);
+  return (r);
 }
 
 /* Call get_working_directory to reset the value of
@@ -375,15 +377,7 @@ pwd_builtin (list)
        setpwd (directory);
       if (directory != the_current_working_directory)
        free (directory);
-      fflush (stdout);
-      if (ferror (stdout))
-       {
-         sh_wrerror ();
-         clearerr (stdout);
-         return (EXECUTION_FAILURE);
-       }
-
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
   else
     return (EXECUTION_FAILURE);
index 5d9b189fc0a8f69fccdd0fd6c0426f12613f5bd8..dcc5a4d4035157680ece5c973b06667ffd308307 100644 (file)
@@ -277,6 +277,19 @@ sh_wrerror ()
   builtin_error (_("write error: %s"), strerror (errno));
 }
 
+int
+sh_chkwrite (s)
+{
+  fflush (stdout);
+  if (ferror (stdout))
+    {
+      sh_wrerror ();
+      clearerr (stdout);
+      return (EXECUTION_FAILURE);
+    }
+  return (s);
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*          Shell positional parameter manipulation                */
index 1233d667a589d7dc5da9155330637be49f86ec1a..0a46d2001ec6a43333cc767699a61256b5ded331 100644 (file)
@@ -78,6 +78,7 @@ extern void sh_nojobs __P((char *));
 extern void sh_restricted __P((char *));
 extern void sh_notbuiltin __P((char *));
 extern void sh_wrerror __P((void));
+extern int sh_chkwrite __P((int));
 
 extern char **make_builtin_argv __P((WORD_LIST *, int *));
 extern void remember_args __P((WORD_LIST *, int));
index aab43153fedcbd53c1682c793fe8a231b0e7bfd3..24707a744b7db87373922da05bbae04dc03be39a 100644 (file)
@@ -528,7 +528,8 @@ print_cmd_completions (list)
          ret = EXECUTION_FAILURE;
        }
     }
-  return (ret);
+
+  return (sh_chkwrite (ret));
 }
 
 $BUILTIN compgen
index a806f10a5bde9e4af9a86c45ab77be67b41e2b9d..2bb9e1d2de461e6f4f2fe1cedad2fce92d7819a4 100644 (file)
@@ -191,16 +191,12 @@ declare_internal (list, local_var)
              free (vlist);
            }
        }
+      else if (flags_on == 0)
+       return (set_builtin ((WORD_LIST *)NULL));
       else
-       {
-         if (flags_on == 0)
-           set_builtin ((WORD_LIST *)NULL);
-         else
-           set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
-       }
+       set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
 
-      fflush (stdout);
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   if (pflag)   /* declare -p [-afFirtx] name [name...] */
@@ -214,7 +210,7 @@ declare_internal (list, local_var)
              any_failed++;
            }
        }
-      return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+      return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
     }
 
 #define NEXT_VARIABLE() free (name); list = list->next; continue
@@ -338,6 +334,7 @@ declare_internal (list, local_var)
                          t = nodefs ? var->name
                                     : named_function_string (name, function_cell (var), 1);
                          printf ("%s\n", t);
+                         any_failed = sh_chkwrite (any_failed);
                        }
                    }
                  else          /* declare -[fF] -[rx] name [name...] */
index 4291d7c16188bed69a7f73ab632c5a7281f89634..483f93bc95a9dccde49a7f330ebf1a4f39c64fb0 100644 (file)
@@ -177,12 +177,5 @@ just_echo:
 
   if (display_return)
     putchar ('\n');
-  fflush (stdout);
-  if (ferror (stdout))
-    {
-      sh_wrerror ();
-      clearerr (stdout);
-      return (EXECUTION_FAILURE);
-    }
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
index a807309dacad6134ab2438495c0ebf5156aea882..5d6d530ea035290a9b5a12a5c6e667cff3ecfc6a 100644 (file)
@@ -368,8 +368,15 @@ fc_builtin (list)
     }
 
   if (listing)
-    return (EXECUTION_SUCCESS);
+    return (sh_chkwrite (EXECUTION_SUCCESS));
 
+  fflush (stream);
+  if (ferror (stream))
+    {
+      sh_wrerror ();
+      fclose (stream);
+      return (EXECUTION_FAILURE);
+    }
   fclose (stream);
 
   /* Now edit the file of commands. */
index 972079221e192c90798e844841b2f96fc56653e1..434fe271c97cca1a1650d8c4eea13b25cd150848 100644 (file)
@@ -170,7 +170,7 @@ history_builtin (list)
     {
       if (list)
        return (expand_and_print_history (list));
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 #endif
   else if (flags & DFLAG)
@@ -193,7 +193,7 @@ history_builtin (list)
   else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
     {
       display_history (list);
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   filename = list ? list->word->word : get_string_value ("HISTFILE");
index 86f0b94597167708ada48f6f33b0a449765276ef..c69e11b2a8243f186eed479ef4c9af686fe1cae1 100644 (file)
@@ -448,7 +448,7 @@ dirs_builtin (list)
       if (index_flag)
        {
          putchar ('\n');
-         return EXECUTION_SUCCESS;
+         return (sh_chkwrite (EXECUTION_SUCCESS));
        }
     }
 
@@ -473,8 +473,8 @@ dirs_builtin (list)
        printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i));
 
   putchar ('\n');
-  fflush (stdout);
-  return (EXECUTION_SUCCESS);
+
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
 
 static void
index 9de094c2595bbbef602822ba0770e9aedf21bb17..ee87a27468ec29290320230593d13285007aebc5 100644 (file)
@@ -580,17 +580,18 @@ int
 set_builtin (list)
      WORD_LIST *list;
 {
-  int on_or_off, flag_name, force_assignment, opts_changed;
+  int on_or_off, flag_name, force_assignment, opts_changed, rv;
   register char *arg;
   char s[3];
 
   if (list == 0)
     {
       print_all_shell_variables ();
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   /* Check validity of flag arguments. */
+  rv = EXECUTION_SUCCESS;
   reset_internal_getopt ();
   while ((flag_name = internal_getopt (list, optflags)) != -1)
     {
@@ -653,6 +654,7 @@ set_builtin (list)
                  if (opt == 0)
                    {
                      list_minus_o_opts (-1, (on_or_off == '+'));
+                     rv = sh_chkwrite (rv);
                      continue;
                    }
 
@@ -699,7 +701,7 @@ set_builtin (list)
   /* Set up new value of $SHELLOPTS */
   if (opts_changed)
     set_shellopts ();
-  return (EXECUTION_SUCCESS);
+  return (rv);
 }
 
 $BUILTIN unset
index d4fe9871ef26fd0ac4ddd6c9f81798dee5aa0504..8507120bb569203ae0b437e99e3fa8ac92f2ef4a 100644 (file)
@@ -1,7 +1,7 @@
 This file is setattr.def, from which is created setattr.c.
 It implements the builtins "export" and "readonly", in 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.
 
@@ -268,7 +268,11 @@ set_or_show_attributes (list, attribute, nodefs)
                continue;
 #endif
              if ((var->attributes & attribute))
-               show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+               {
+                 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+                 if (any_failed = sh_chkwrite (any_failed))
+                   break;
+               }
            }
          free (variable_list);
        }
index 8055473e506d4945bc4eca870c0a632b5db83a4e..080a03f4090dc4a4b31c7360f80036da4452a3e3 100644 (file)
@@ -352,7 +352,7 @@ list_shopts (list, flags)
          if ((flags & QFLAG) == 0)
            print_shopt (shopt_vars[i].name, val, flags);
        }
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
@@ -371,7 +371,7 @@ list_shopts (list, flags)
        print_shopt (l->word->word, val, flags);
     }
 
-  return (rval);
+  return (sh_chkwrite (rval));
 }
 
 static int
@@ -386,7 +386,7 @@ list_some_shopts (mode, flags)
       if (((flags & QFLAG) == 0) && mode == val)
        print_shopt (shopt_vars[i].name, val, flags);
     }
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
 
 static int
@@ -401,7 +401,7 @@ list_shopt_o_options (list, flags)
     {
       if ((flags & QFLAG) == 0)
        list_minus_o_opts (-1, (flags & PFLAG));
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
@@ -423,7 +423,7 @@ list_shopt_o_options (list, flags)
            printf (OPTFMT, l->word->word, val ? on : off);
        }
     }
-  return (rval);
+  return (sh_chkwrite (rval));
 }
 
 static int
@@ -432,7 +432,7 @@ list_some_o_options (mode, flags)
 {
   if ((flags & QFLAG) == 0)
     list_minus_o_opts (mode, (flags & PFLAG));
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
 
 static int
@@ -540,5 +540,5 @@ shopt_listopt (name, reusable)
     }
 
   print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0);
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
index db54558d0253e01034bde817dccb2fbc4c375034..42a160f3a817f6747f868bd03b1f300c2de77421 100644 (file)
@@ -111,5 +111,5 @@ times_builtin (list)
 #  endif /* HAVE_TIMES */
 #endif /* !HAVE_TIMES */
 
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
index 9e7d763617920ceb4a8f1ca529e17e04674157c8..7affa1cd10c269fcbb93fe5f078c71d12b35dde9 100644 (file)
@@ -112,9 +112,9 @@ trap_builtin (list)
   opt = DSIG_NOCASE|DSIG_SIGPREFIX;    /* flags for decode_signal */
 
   if (list_signal_names)
-    return (display_signal_list ((WORD_LIST *)NULL, 1));
+    return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
   else if (display || list == 0)
-    return (display_traps (list));
+    return (sh_chkwrite (display_traps (list)));
   else
     {
       char *first_arg;
index 39a43162b921b18d23e9a90cd3cf1d29f7215145..370e596c825c1555d5df59bbcec3d805c0ba075e 100644 (file)
@@ -185,9 +185,8 @@ type_builtin (list)
       list = list->next;
     }
 
-  fflush (stdout);
-
-  return ((successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+  opt = (successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
+  return (sh_chkwrite (opt));
 }
 
 /*
index 2307c4650f717adca63f86e5aad6393b437f5a6c..d1ac71df4e6f5c0e055c396f6e2a5ddcdf646ca5 100644 (file)
@@ -356,7 +356,7 @@ ulimit_builtin (list)
         }
 #endif
       print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   /* default is `ulimit -f' */
index 489ca33050cbaf6750375e69fbb4d99951073bd6..23e819941666974f6a041cdd34c0b49eaae844f7 100644 (file)
@@ -137,8 +137,7 @@ umask_builtin (list)
        printf ("%04lo\n", (unsigned long)umask_arg);
     }
 
-  fflush (stdout);
-  return (EXECUTION_SUCCESS);
+  return (sh_chkwrite (EXECUTION_SUCCESS));
 }
 
 /* Print the umask in a symbolic form.  In the output, a letter is
index 181dc6341a8aa0ab6b37e362f7ce00829d701fa9..5a3d2ee581195c3ee9d14898ef061f19d3bc6675 100644 (file)
@@ -5,12 +5,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.cwru.edu
 .\"
-.\"    Last Change: Fri Jan 12 16:29:22 EST 2007
+.\"    Last Change: Tue May  1 10:05:17 EDT 2007
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2007 January 12" "GNU Bash-3.2"
+.TH BASH 1 "2007 May 1" "GNU Bash-3.2"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -645,7 +645,8 @@ The return status is the exit status of
 Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and
 \fB}\fP are \fIreserved words\fP and must occur where a reserved
 word is permitted to be recognized.  Since they do not cause a word
-break, they must be separated from \fIlist\fP by whitespace.
+break, they must be separated from \fIlist\fP by whitespace or another
+shell metacharacter.
 .TP
 ((\fIexpression\fP))
 The \fIexpression\fP is evaluated according to the rules described
@@ -8318,6 +8319,7 @@ an argument of \fB\-\-\fP as signifying the end of options.
 .if n .sp 1
 Expressions may be combined using the following operators, listed
 in decreasing order of precedence.
+The evaluation depends on the number of arguments; see below.
 .RS
 .PD 0
 .TP
@@ -8375,14 +8377,14 @@ under
 .BR "CONDITIONAL EXPRESSIONS" ,
 the result of the expression is the result of the binary test using
 the first and third arguments as operands.
+The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
+when there are three arguments.  
 If the first argument is \fB!\fP, the value is the negation of
 the two-argument test using the second and third arguments.
 If the first argument is exactly \fB(\fP and the third argument is
 exactly \fB)\fP, the result is the one-argument test of the second
 argument.
 Otherwise, the expression is false.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-in this case.  
 .TP
 4 arguments
 If the first argument is \fB!\fP, the result is the negation of
index 78f9c4cb20e5e5d9b52b0a7410c9eb2cec12bcb5..62b0c5978db795752ccc34f8c97cdc8ba2c146d9 100644 (file)
@@ -1041,7 +1041,8 @@ The semicolon (or newline) following @var{list} is required.
 In addition to the creation of a subshell, there is a subtle difference
 between these two constructs due to historical reasons.  The braces
 are @code{reserved words}, so they must be separated from the @var{list}
-by @code{blank}s.  The parentheses are @code{operators}, and are
+by @code{blank}s or other shell metacharacters.
+The parentheses are @code{operators}, and are
 recognized as separate tokens by the shell even if they are not separated
 from the @var{list} by whitespace.
 
@@ -1092,7 +1093,8 @@ Note that for historical reasons, in the most common usage the curly braces
 that surround the body of the function must be separated from the body by
 @code{blank}s or newlines.
 This is because the braces are reserved words and are only recognized
-as such when they are separated by whitespace.
+as such when they are separated from the command list
+by whitespace or another shell metacharacter.
 Also, when using the braces, the @var{list} must be terminated by a semicolon,
 a @samp{&}, or a newline.
 
@@ -2918,6 +2920,7 @@ be a @code{]}.
 
 Expressions may be combined using the following operators, listed in
 decreasing order of precedence.
+The evaluation depends on the number of arguments; see below.
 
 @table @code
 @item ! @var{expr}
@@ -2958,14 +2961,14 @@ If the second argument is one of the binary conditional
 operators (@pxref{Bash Conditional Expressions}), the
 result of the expression is the result of the binary test using the
 first and third arguments as operands.
+The @samp{-a} and @samp{-o} operators are considered binary operators
+when there are three arguments.
 If the first argument is @samp{!}, the value is the negation of
 the two-argument test using the second and third arguments.
 If the first argument is exactly @samp{(} and the third argument is
 exactly @samp{)}, the result is the one-argument test of the second
 argument.
 Otherwise, the expression is false.
-The @samp{-a} and @samp{-o} operators are considered binary operators
-in this case.  
 
 @item 4 arguments
 If the first argument is @samp{!}, the result is the negation of
index 79525961d34a5658967c75e327a2f313bd617aa4..dc36632b552ccef94c145cfacdaf2e9869d116ed 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2007 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Fri Jan 12 16:29:58 EST 2007
+@set LASTCHANGE Tue May  1 10:05:36 EDT 2007
 
 @set EDITION 3.2
 @set VERSION 3.2
-@set UPDATED 12 January 2007
-@set UPDATED-MONTH January 2007
+@set UPDATED 1 May 2007
+@set UPDATED-MONTH May 2007
diff --git a/lib/readline/examples/x b/lib/readline/examples/x
new file mode 100644 (file)
index 0000000..239dcab
--- /dev/null
@@ -0,0 +1 @@
+N   3149)   5/1 To: peggy.gup@c Re: FW: Phone for Mike Dailey   (2413 chars)N   3150)   5/1 Jason Cutcher   RE: Phone for Mike Dailey       (34705 chars)N   3151)   5/1 Wizards         *****SPAM***** Relief           (7291 chars)N   3152)   5/1 FCG Help Desk   Case HD0000002533519, Medium, h (2537 chars)N   3153)   5/1 To: jrw11@case. HD0000002533519                 (2247 chars)N   3154)   5/1 Peggy Watts Gup RE: [tis-staff] Boxes back to m (12903 chars)N   3155)   5/1 Debbie Andrews  [firewall-changes] Firewa
index d4ff47b86596fe1026fbc121cf19b8a26b9a68bb..607f5e26154889e557ff90667b447381596ae35c 100644 (file)
@@ -119,7 +119,7 @@ ibuffer_space ()
   if (pop_index > push_index)
     return (pop_index - push_index - 1);
   else
-    return (ibuffer_len - (push_index - pop_index) - 1);
+    return (ibuffer_len - (push_index - pop_index));
 }
 
 /* Get a key from the buffer of characters to be read.
@@ -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);
@@ -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;
index d1dfd1a78be7ed92def9cbac50c01de36c1d9cf1..28bec1b5e6f400afd443cc48f8d0c59d1e4b88b5 100644 (file)
@@ -106,7 +106,15 @@ int command_string_index = 0;
 
 /* Non-zero means the stuff being printed is inside of a function def. */
 static int inside_function_def;
+
+/* Used to decide where to put the `|' if the command in the pipeline has
+   here documents associated with it.  If non-zero, print_redirection
+   prints the `|' before the text of the here document and print_connection
+   suppresses the `|'. */
+static int inside_pipeline;
 static int skip_this_indent;
+
+/* Flag indicating we printed a here-document. */
 static int was_heredoc;
 
 /* The depth of the group commands that we are currently printing.  This
@@ -133,7 +141,7 @@ char *
 make_command_string (command)
      COMMAND *command;
 {
-  command_string_index = was_heredoc = 0;
+  command_string_index = was_heredoc = inside_pipeline = 0;
   make_command_string_internal (command);
   return (the_printed_command);
 }
@@ -215,7 +223,11 @@ make_command_string_internal (command)
        case cm_connection:
 
          skip_this_indent++;
+         if (command->value.Connection->connector == '|')
+           inside_pipeline = 1;
          make_command_string_internal (command->value.Connection->first);
+         if (command->value.Connection->connector == '|')
+           inside_pipeline = 0;
 
          switch (command->value.Connection->connector)
            {
@@ -223,7 +235,10 @@ make_command_string_internal (command)
            case '|':
              {
                char c = command->value.Connection->connector;
-               cprintf (" %c", c);
+               if (c == '&' || was_heredoc == 0)
+                 cprintf (" %c", c);
+               else
+                 was_heredoc = 0;
                if (c != '&' || command->value.Connection->second)
                  {
                    cprintf (" ");
@@ -851,6 +866,10 @@ print_redirection_list (redirects)
      print the here documents. */
   if (heredocs)
     {
+if (inside_pipeline)
+{
+itrace("print_redirection_list: here documents inside pipeline");
+}
       cprintf (" "); 
       for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
        {
@@ -868,6 +887,7 @@ print_redirection (redirect)
 {
   int kill_leading, redirector, redir_fd;
   WORD_DESC *redirectee;
+  char *x;
 
   kill_leading = 0;
   redirectee = redirect->redirectee.filename;
@@ -905,17 +925,16 @@ print_redirection (redirect)
       if (redirector != 0)
        cprintf ("%d", redirector);
       /* If the here document delimiter is quoted, single-quote it. */
-      if (redirect->redirectee.filename->flags & W_QUOTED)
-       {
-         char *x;
-         x = sh_single_quote (redirect->here_doc_eof);
-         cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
-         free (x);
-       }
-      else
-       cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
-      cprintf ("%s%s",
-              redirect->redirectee.filename->word, redirect->here_doc_eof);
+      x = (redirect->redirectee.filename->flags & W_QUOTED)
+               ? sh_single_quote (redirect->here_doc_eof)
+               : redirect->here_doc_eof;
+      cprintf ("<<%s%s", kill_leading? "-" : "", x);
+      if (x != redirect->here_doc_eof)
+       free (x);
+if (inside_pipeline)
+  cprintf (" |");
+      cprintf ("\n");
+      cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
       break;
 
     case r_reading_string:
@@ -991,6 +1010,7 @@ reset_locals ()
 {
   inside_function_def = 0;
   indentation = 0;
+  inside_pipeline = 0;
 }
 
 static void
@@ -1010,7 +1030,7 @@ print_function_def (func)
   inside_function_def++;
   indentation += indentation_amount;
 
-  cmdcopy = copy_command (func->command);
+  cmdcopy = copy_command (func->command);      /* possible mem leak on unwind-protect */
   if (cmdcopy->type == cm_group)
     {
       func_redirects = cmdcopy->redirects;
@@ -1055,6 +1075,7 @@ named_function_string (name, command, multi_line)
   old_indent = indentation;
   old_amount = indentation_amount;
   command_string_index = was_heredoc = 0;
+  inside_pipeline = 0;
 
   if (name && *name)
     cprintf ("%s ", name);
diff --git a/print_cmd.c~ b/print_cmd.c~
new file mode 100644 (file)
index 0000000..e68619f
--- /dev/null
@@ -0,0 +1,1322 @@
+/* print_command -- A way to make readable commands from a command tree. */
+
+/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#if defined (PREFER_STDARG)
+#  include <stdarg.h>
+#else
+#  include <varargs.h>
+#endif
+
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "flags.h"
+#include <y.tab.h>     /* use <...> so we pick it up from the build directory */
+
+#include "shmbutil.h"
+
+#include "builtins/common.h"
+
+#if !HAVE_DECL_PRINTF
+extern int printf __P((const char *, ...));    /* Yuck.  Double yuck. */
+#endif
+
+extern int indirection_level;
+
+static int indentation;
+static int indentation_amount = 4;
+
+#if defined (PREFER_STDARG)
+typedef void PFUNC __P((const char *, ...));
+
+static void cprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
+static void xprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
+#else
+#define PFUNC VFunction
+static void cprintf ();
+static void xprintf ();
+#endif
+
+static void reset_locals __P((void));
+static void newline __P((char *));
+static void indent __P((int));
+static void semicolon __P((void));
+static void the_printed_command_resize __P((int));
+
+static void make_command_string_internal __P((COMMAND *));
+static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
+static void command_print_word_list __P((WORD_LIST *, char *));
+static void print_case_clauses __P((PATTERN_LIST *));
+static void print_redirection_list __P((REDIRECT *));
+static void print_redirection __P((REDIRECT *));
+
+static void print_for_command __P((FOR_COM *));
+#if defined (ARITH_FOR_COMMAND)
+static void print_arith_for_command __P((ARITH_FOR_COM *));
+#endif
+#if defined (SELECT_COMMAND)
+static void print_select_command __P((SELECT_COM *));
+#endif
+static void print_group_command __P((GROUP_COM *));
+static void print_case_command __P((CASE_COM *));
+static void print_while_command __P((WHILE_COM *));
+static void print_until_command __P((WHILE_COM *));
+static void print_until_or_while __P((WHILE_COM *, char *));
+static void print_if_command __P((IF_COM *));
+#if defined (COND_COMMAND)
+static void print_cond_node __P((COND_COM *));
+#endif
+static void print_function_def __P((FUNCTION_DEF *));
+
+#define PRINTED_COMMAND_INITIAL_SIZE 64
+#define PRINTED_COMMAND_GROW_SIZE 128
+
+char *the_printed_command = (char *)NULL;
+int the_printed_command_size = 0;
+int command_string_index = 0;
+
+/* Non-zero means the stuff being printed is inside of a function def. */
+static int inside_function_def;
+
+static int inside_pipeline;
+static int skip_this_indent;
+static int was_heredoc;
+
+/* The depth of the group commands that we are currently printing.  This
+   includes the group command that is a function body. */
+static int group_command_nesting;
+
+/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
+static char indirection_string[100];
+
+/* Print COMMAND (a command tree) on standard output. */
+void
+print_command (command)
+     COMMAND *command;
+{
+  command_string_index = 0;
+  printf ("%s", make_command_string (command));
+}
+
+/* Make a string which is the printed representation of the command
+   tree in COMMAND.  We return this string.  However, the string is
+   not consed, so you have to do that yourself if you want it to
+   remain around. */
+char *
+make_command_string (command)
+     COMMAND *command;
+{
+  command_string_index = was_heredoc = inside_pipeline = 0;
+  make_command_string_internal (command);
+  return (the_printed_command);
+}
+
+/* The internal function.  This is the real workhorse. */
+static void
+make_command_string_internal (command)
+     COMMAND *command;
+{
+  if (command == 0)
+    cprintf ("");
+  else
+    {
+      if (skip_this_indent)
+       skip_this_indent--;
+      else
+       indent (indentation);
+
+      if (command->flags & CMD_TIME_PIPELINE)
+       {
+         cprintf ("time ");
+         if (command->flags & CMD_TIME_POSIX)
+           cprintf ("-p ");
+       }
+
+      if (command->flags & CMD_INVERT_RETURN)
+       cprintf ("! ");
+
+      switch (command->type)
+       {
+       case cm_for:
+         print_for_command (command->value.For);
+         break;
+
+#if defined (ARITH_FOR_COMMAND)
+       case cm_arith_for:
+         print_arith_for_command (command->value.ArithFor);
+         break;
+#endif
+
+#if defined (SELECT_COMMAND)
+       case cm_select:
+         print_select_command (command->value.Select);
+         break;
+#endif
+
+       case cm_case:
+         print_case_command (command->value.Case);
+         break;
+
+       case cm_while:
+         print_while_command (command->value.While);
+         break;
+
+       case cm_until:
+         print_until_command (command->value.While);
+         break;
+
+       case cm_if:
+         print_if_command (command->value.If);
+         break;
+
+#if defined (DPAREN_ARITHMETIC)
+       case cm_arith:
+         print_arith_command (command->value.Arith->exp);
+         break;
+#endif
+
+#if defined (COND_COMMAND)
+       case cm_cond:
+         print_cond_command (command->value.Cond);
+         break;
+#endif
+
+       case cm_simple:
+         print_simple_command (command->value.Simple);
+         break;
+
+       case cm_connection:
+
+         skip_this_indent++;
+         if (command->value.Connection->connector == '|')
+           inside_pipeline = 1;
+         make_command_string_internal (command->value.Connection->first);
+         if (command->value.Connection->connector == '|')
+           inside_pipeline = 0;
+
+         switch (command->value.Connection->connector)
+           {
+           case '&':
+           case '|':
+             {
+               char c = command->value.Connection->connector;
+               if (c == '&' || was_heredoc == 0)
+                 cprintf (" %c", c);
+               else
+                 was_heredoc = 0;
+               if (c != '&' || command->value.Connection->second)
+                 {
+                   cprintf (" ");
+                   skip_this_indent++;
+                 }
+             }
+             break;
+
+           case AND_AND:
+             cprintf (" && ");
+             if (command->value.Connection->second)
+               skip_this_indent++;
+             break;
+
+           case OR_OR:
+             cprintf (" || ");
+             if (command->value.Connection->second)
+               skip_this_indent++;
+             break;
+
+           case ';':
+             if (was_heredoc == 0)
+               cprintf (";");
+             else
+               was_heredoc = 0;
+
+             if (inside_function_def)
+               cprintf ("\n");
+             else
+               {
+                 cprintf (" ");
+                 if (command->value.Connection->second)
+                   skip_this_indent++;
+               }
+             break;
+
+           default:
+             cprintf (_("print_command: bad connector `%d'"),
+                      command->value.Connection->connector);
+             break;
+           }
+
+         make_command_string_internal (command->value.Connection->second);
+         break;
+
+       case cm_function_def:
+         print_function_def (command->value.Function_def);
+         break;
+
+       case cm_group:
+         print_group_command (command->value.Group);
+         break;
+
+       case cm_subshell:
+         cprintf ("( ");
+         skip_this_indent++;
+         make_command_string_internal (command->value.Subshell->command);
+         cprintf (" )");
+         break;
+
+       default:
+         command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
+         break;
+       }
+
+
+      if (command->redirects)
+       {
+         cprintf (" ");
+         print_redirection_list (command->redirects);
+       }
+    }
+}
+
+static void
+_print_word_list (list, separator, pfunc)
+     WORD_LIST *list;
+     char *separator;
+     PFUNC *pfunc;
+{
+  WORD_LIST *w;
+
+  for (w = list; w; w = w->next)
+    (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
+}
+
+void
+print_word_list (list, separator)
+     WORD_LIST *list;
+     char *separator;
+{
+  _print_word_list (list, separator, xprintf);
+}
+
+/* Return a string denoting what our indirection level is. */
+
+char *
+indirection_level_string ()
+{
+  register int i, j;
+  char *ps4;
+  char ps4_firstc[MB_LEN_MAX+1];
+  int ps4_firstc_len, ps4_len;
+
+  indirection_string[0] = '\0';
+  ps4 = get_string_value ("PS4");
+
+  if (ps4 == 0 || *ps4 == '\0')
+    return (indirection_string);
+
+  change_flag ('x', FLAG_OFF);
+  ps4 = decode_prompt_string (ps4);
+  change_flag ('x', FLAG_ON);
+
+  if (ps4 == 0 || *ps4 == '\0')
+    return (indirection_string);
+
+#if defined (HANDLE_MULTIBYTE)
+  ps4_len = strnlen (ps4, MB_CUR_MAX);
+  ps4_firstc_len = MBLEN (ps4, ps4_len);
+  if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
+    {
+      ps4_firstc[0] = ps4[0];
+      ps4_firstc[ps4_firstc_len = 1] = '\0';
+    }
+  else
+    memcpy (ps4_firstc, ps4, ps4_firstc_len);
+#else
+  ps4_firstc[0] = ps4[0];
+  ps4_firstc[ps4_firstc_len = 1] = '\0';
+#endif
+      
+  for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
+    {
+      if (ps4_firstc_len == 1)
+       indirection_string[i] = ps4_firstc[0];
+      else
+       memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
+    }      
+
+  for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
+    indirection_string[i] = ps4[j];
+
+  indirection_string[i] = '\0';
+  free (ps4);
+  return (indirection_string);
+}
+
+void
+xtrace_print_assignment (name, value, assign_list, xflags)
+     char *name, *value;
+     int assign_list, xflags;
+{
+  char *nval;
+
+  if (xflags)
+    fprintf (stderr, "%s", indirection_level_string ());
+
+  /* VALUE should not be NULL when this is called. */
+  if (*value == '\0' || assign_list)
+    nval = value;
+  else if (sh_contains_shell_metas (value))
+    nval = sh_single_quote (value);
+  else if (ansic_shouldquote (value))
+    nval = ansic_quote (value, 0, (int *)0);
+  else
+    nval = value;
+
+  if (assign_list)
+    fprintf (stderr, "%s=(%s)\n", name, nval);
+  else
+    fprintf (stderr, "%s=%s\n", name, nval);
+
+  if (nval != value)
+    FREE (nval);
+
+  fflush (stderr);
+}
+
+/* A function to print the words of a simple command when set -x is on. */
+void
+xtrace_print_word_list (list, xtflags)
+     WORD_LIST *list;
+     int xtflags;
+{
+  WORD_LIST *w;
+  char *t, *x;
+
+  if (xtflags)
+    fprintf (stderr, "%s", indirection_level_string ());
+
+  for (w = list; w; w = w->next)
+    {
+      t = w->word->word;
+      if (t == 0 || *t == '\0')
+       fprintf (stderr, "''%s", w->next ? " " : "");
+      else if (sh_contains_shell_metas (t))
+       {
+         x = sh_single_quote (t);
+         fprintf (stderr, "%s%s", x, w->next ? " " : "");
+         free (x);
+       }
+      else if (ansic_shouldquote (t))
+       {
+         x = ansic_quote (t, 0, (int *)0);
+         fprintf (stderr, "%s%s", x, w->next ? " " : "");
+         free (x);
+       }
+      else
+       fprintf (stderr, "%s%s", t, w->next ? " " : "");
+    }
+  fprintf (stderr, "\n");
+}
+
+static void
+command_print_word_list (list, separator)
+     WORD_LIST *list;
+     char *separator;
+{
+  _print_word_list (list, separator, cprintf);
+}
+
+void
+print_for_command_head (for_command)
+     FOR_COM *for_command;
+{
+  cprintf ("for %s in ", for_command->name->word);
+  command_print_word_list (for_command->map_list, " ");
+}
+
+void
+xtrace_print_for_command_head (for_command)
+     FOR_COM *for_command;
+{
+  fprintf (stderr, "%s", indirection_level_string ());
+  fprintf (stderr, "for %s in ", for_command->name->word);
+  xtrace_print_word_list (for_command->map_list, 0);
+}
+
+static void
+print_for_command (for_command)
+     FOR_COM *for_command;
+{
+  print_for_command_head (for_command);
+
+  cprintf (";");
+  newline ("do\n");
+  indentation += indentation_amount;
+  make_command_string_internal (for_command->action);
+  semicolon ();
+  indentation -= indentation_amount;
+  newline ("done");
+}
+
+#if defined (ARITH_FOR_COMMAND)
+static void
+print_arith_for_command (arith_for_command)
+     ARITH_FOR_COM *arith_for_command;
+{
+  cprintf ("for ((");
+  command_print_word_list (arith_for_command->init, " ");
+  cprintf ("; ");
+  command_print_word_list (arith_for_command->test, " ");
+  cprintf ("; ");
+  command_print_word_list (arith_for_command->step, " ");
+  cprintf ("))");
+  newline ("do\n");
+  indentation += indentation_amount;
+  make_command_string_internal (arith_for_command->action);
+  semicolon ();
+  indentation -= indentation_amount;
+  newline ("done");
+}
+#endif /* ARITH_FOR_COMMAND */
+
+#if defined (SELECT_COMMAND)
+void
+print_select_command_head (select_command)
+     SELECT_COM *select_command;
+{
+  cprintf ("select %s in ", select_command->name->word);
+  command_print_word_list (select_command->map_list, " ");
+}
+
+void
+xtrace_print_select_command_head (select_command)
+     SELECT_COM *select_command;
+{
+  fprintf (stderr, "%s", indirection_level_string ());
+  fprintf (stderr, "select %s in ", select_command->name->word);
+  xtrace_print_word_list (select_command->map_list, 0);
+}
+
+static void
+print_select_command (select_command)
+     SELECT_COM *select_command;
+{
+  print_select_command_head (select_command);
+
+  cprintf (";");
+  newline ("do\n");
+  indentation += indentation_amount;
+  make_command_string_internal (select_command->action);
+  semicolon ();
+  indentation -= indentation_amount;
+  newline ("done");
+}
+#endif /* SELECT_COMMAND */
+
+static void
+print_group_command (group_command)
+     GROUP_COM *group_command;
+{
+  group_command_nesting++;
+  cprintf ("{ ");
+
+  if (inside_function_def == 0)
+    skip_this_indent++;
+  else
+    {
+      /* This is a group command { ... } inside of a function
+        definition, and should be printed as a multiline group
+        command, using the current indentation. */
+      cprintf ("\n");
+      indentation += indentation_amount;
+    }
+
+  make_command_string_internal (group_command->command);
+
+  if (inside_function_def)
+    {
+      cprintf ("\n");
+      indentation -= indentation_amount;
+      indent (indentation);
+    }
+  else
+    {
+      semicolon ();
+      cprintf (" ");
+    }
+
+  cprintf ("}");
+
+  group_command_nesting--;
+}
+
+void
+print_case_command_head (case_command)
+     CASE_COM *case_command;
+{
+  cprintf ("case %s in ", case_command->word->word);
+}
+
+void
+xtrace_print_case_command_head (case_command)
+     CASE_COM *case_command;
+{
+  fprintf (stderr, "%s", indirection_level_string ());
+  fprintf (stderr, "case %s in\n", case_command->word->word);
+}
+
+static void
+print_case_command (case_command)
+     CASE_COM *case_command;
+{
+  print_case_command_head (case_command);
+
+  if (case_command->clauses)
+    print_case_clauses (case_command->clauses);
+  newline ("esac");
+}
+
+static void
+print_case_clauses (clauses)
+     PATTERN_LIST *clauses;
+{
+  indentation += indentation_amount;
+  while (clauses)
+    {
+      newline ("");
+      command_print_word_list (clauses->patterns, " | ");
+      cprintf (")\n");
+      indentation += indentation_amount;
+      make_command_string_internal (clauses->action);
+      indentation -= indentation_amount;
+      newline (";;");
+      clauses = clauses->next;
+    }
+  indentation -= indentation_amount;
+}
+
+static void
+print_while_command (while_command)
+     WHILE_COM *while_command;
+{
+  print_until_or_while (while_command, "while");
+}
+
+static void
+print_until_command (while_command)
+     WHILE_COM *while_command;
+{
+  print_until_or_while (while_command, "until");
+}
+
+static void
+print_until_or_while (while_command, which)
+     WHILE_COM *while_command;
+     char *which;
+{
+  cprintf ("%s ", which);
+  skip_this_indent++;
+  make_command_string_internal (while_command->test);
+  semicolon ();
+  cprintf (" do\n");   /* was newline ("do\n"); */
+  indentation += indentation_amount;
+  make_command_string_internal (while_command->action);
+  indentation -= indentation_amount;
+  semicolon ();
+  newline ("done");
+}
+
+static void
+print_if_command (if_command)
+     IF_COM *if_command;
+{
+  cprintf ("if ");
+  skip_this_indent++;
+  make_command_string_internal (if_command->test);
+  semicolon ();
+  cprintf (" then\n");
+  indentation += indentation_amount;
+  make_command_string_internal (if_command->true_case);
+  indentation -= indentation_amount;
+
+  if (if_command->false_case)
+    {
+      semicolon ();
+      newline ("else\n");
+      indentation += indentation_amount;
+      make_command_string_internal (if_command->false_case);
+      indentation -= indentation_amount;
+    }
+  semicolon ();
+  newline ("fi");
+}
+
+#if defined (DPAREN_ARITHMETIC)
+void
+print_arith_command (arith_cmd_list)
+     WORD_LIST *arith_cmd_list;
+{
+  cprintf ("((");
+  command_print_word_list (arith_cmd_list, " ");
+  cprintf ("))");
+}
+#endif
+
+#if defined (COND_COMMAND)
+static void
+print_cond_node (cond)
+     COND_COM *cond;
+{
+  if (cond->flags & CMD_INVERT_RETURN)
+    cprintf ("! ");
+
+  if (cond->type == COND_EXPR)
+    {
+      cprintf ("( ");
+      print_cond_node (cond->left);
+      cprintf (" )");
+    }
+  else if (cond->type == COND_AND)
+    {
+      print_cond_node (cond->left);
+      cprintf (" && ");
+      print_cond_node (cond->right);
+    }
+  else if (cond->type == COND_OR)
+    {
+      print_cond_node (cond->left);
+      cprintf (" || ");
+      print_cond_node (cond->right);
+    }
+  else if (cond->type == COND_UNARY)
+    {
+      cprintf ("%s", cond->op->word);
+      cprintf (" ");
+      print_cond_node (cond->left);
+    }
+  else if (cond->type == COND_BINARY)
+    {
+      print_cond_node (cond->left);
+      cprintf (" ");
+      cprintf ("%s", cond->op->word);
+      cprintf (" ");
+      print_cond_node (cond->right);
+    }
+  else if (cond->type == COND_TERM)
+    {
+      cprintf ("%s", cond->op->word);          /* need to add quoting here */
+    }
+}
+
+void
+print_cond_command (cond)
+     COND_COM *cond;
+{
+  cprintf ("[[ ");
+  print_cond_node (cond);
+  cprintf (" ]]");
+}
+
+#ifdef DEBUG
+void
+debug_print_cond_command (cond)
+     COND_COM *cond;
+{
+  fprintf (stderr, "DEBUG: ");
+  command_string_index = 0;
+  print_cond_command (cond);
+  fprintf (stderr, "%s\n", the_printed_command);
+}
+#endif
+
+void
+xtrace_print_cond_term (type, invert, op, arg1, arg2)
+     int type, invert;
+     WORD_DESC *op;
+     char *arg1, *arg2;
+{
+  command_string_index = 0;
+  fprintf (stderr, "%s", indirection_level_string ());
+  fprintf (stderr, "[[ ");
+  if (invert)
+    fprintf (stderr, "! ");
+
+  if (type == COND_UNARY)
+    {
+      fprintf (stderr, "%s ", op->word);
+      fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
+    }
+  else if (type == COND_BINARY)
+    {
+      fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
+      fprintf (stderr, " %s ", op->word);
+      fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
+    }
+
+  fprintf (stderr, " ]]\n");
+}        
+#endif /* COND_COMMAND */
+
+#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+/* A function to print the words of an arithmetic command when set -x is on. */
+void
+xtrace_print_arith_cmd (list)
+     WORD_LIST *list;
+{
+  WORD_LIST *w;
+
+  fprintf (stderr, "%s", indirection_level_string ());
+  fprintf (stderr, "(( ");
+  for (w = list; w; w = w->next)
+    fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
+  fprintf (stderr, " ))\n");
+}
+#endif
+
+void
+print_simple_command (simple_command)
+     SIMPLE_COM *simple_command;
+{
+  command_print_word_list (simple_command->words, " ");
+
+  if (simple_command->redirects)
+    {
+      cprintf (" ");
+      print_redirection_list (simple_command->redirects);
+    }
+}
+
+static void
+print_redirection_list (redirects)
+     REDIRECT *redirects;
+{
+  REDIRECT *heredocs, *hdtail, *newredir;
+
+  heredocs = (REDIRECT *)NULL;
+  hdtail = heredocs;
+
+  was_heredoc = 0;
+  while (redirects)
+    {
+      /* Defer printing the here documents until we've printed the
+        rest of the redirections. */
+      if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
+       {
+         newredir = copy_redirect (redirects);
+         newredir->next = (REDIRECT *)NULL;
+         if (heredocs)
+           {
+             hdtail->next = newredir;
+             hdtail = newredir;
+           }
+         else
+           hdtail = heredocs = newredir;
+       }
+      else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
+       {
+         /* Temporarily translate it as the execution code does. */
+         redirects->instruction = r_err_and_out;
+         print_redirection (redirects);
+         redirects->instruction = r_duplicating_output_word;
+       }
+      else
+       print_redirection (redirects);
+
+      redirects = redirects->next;
+      if (redirects)
+       cprintf (" ");
+    }
+
+  /* Now that we've printed all the other redirections (on one line),
+     print the here documents. */
+  if (heredocs)
+    {
+if (inside_pipeline)
+{
+itrace("print_redirection_list: here documents inside pipeline");
+}
+      cprintf (" "); 
+      for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
+       {
+         print_redirection (hdtail);
+         cprintf ("\n");
+       }
+      dispose_redirects (heredocs);
+      was_heredoc = 1;
+    }
+}
+
+static void
+print_redirection (redirect)
+     REDIRECT *redirect;
+{
+  int kill_leading, redirector, redir_fd;
+  WORD_DESC *redirectee;
+  char *x;
+
+  kill_leading = 0;
+  redirectee = redirect->redirectee.filename;
+  redirector = redirect->redirector;
+  redir_fd = redirect->redirectee.dest;
+
+  switch (redirect->instruction)
+    {
+    case r_output_direction:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf ("> %s", redirectee->word);
+      break;
+
+    case r_input_direction:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      cprintf ("< %s", redirectee->word);
+      break;
+
+    case r_inputa_direction:   /* Redirection created by the shell. */
+      cprintf ("&");
+      break;
+
+    case r_appending_to:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf (">> %s", redirectee->word);
+      break;
+
+    case r_deblank_reading_until:
+      kill_leading++;
+      /* ... */
+    case r_reading_until:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      /* If the here document delimiter is quoted, single-quote it. */
+      x = (redirect->redirectee.filename->flags & W_QUOTED)
+               ? sh_single_quote (redirect->here_doc_eof)
+               : redirect->here_doc_eof;
+      cprintf ("<<%s%s", kill_leading? "-" : "", x);
+      if (x != redirect->here_doc_eof)
+       free (x);
+if (inside_pipeline)
+  cprintf (" |");
+      cprintf ("\n");
+      cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
+      break;
+
+    case r_reading_string:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      if (ansic_shouldquote (redirect->redirectee.filename->word))
+       {
+         char *x;
+         x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
+         cprintf ("<<< %s", x);
+         free (x);
+       }
+      else
+       cprintf ("<<< %s", redirect->redirectee.filename->word);
+      break;
+
+    case r_duplicating_input:
+      cprintf ("%d<&%d", redirector, redir_fd);
+      break;
+
+    case r_duplicating_output:
+      cprintf ("%d>&%d", redirector, redir_fd);
+      break;
+
+    case r_duplicating_input_word:
+      cprintf ("%d<&%s", redirector, redirectee->word);
+      break;
+
+    case r_duplicating_output_word:
+      cprintf ("%d>&%s", redirector, redirectee->word);
+      break;
+
+    case r_move_input:
+      cprintf ("%d<&%d-", redirector, redir_fd);
+      break;
+
+    case r_move_output:
+      cprintf ("%d>&%d-", redirector, redir_fd);
+      break;
+
+    case r_move_input_word:
+      cprintf ("%d<&%s-", redirector, redirectee->word);
+      break;
+
+    case r_move_output_word:
+      cprintf ("%d>&%s-", redirector, redirectee->word);
+      break;
+
+    case r_close_this:
+      cprintf ("%d>&-", redirector);
+      break;
+
+    case r_err_and_out:
+      cprintf (">&%s", redirectee->word);
+      break;
+
+    case r_input_output:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf ("<> %s", redirectee->word);
+      break;
+
+    case r_output_force:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf (">|%s", redirectee->word);
+      break;
+    }
+}
+
+static void
+reset_locals ()
+{
+  inside_function_def = 0;
+  indentation = 0;
+  inside_pipeline = 0;
+}
+
+static void
+print_function_def (func)
+     FUNCTION_DEF *func;
+{
+  COMMAND *cmdcopy;
+  REDIRECT *func_redirects;
+
+  func_redirects = NULL;
+  cprintf ("function %s () \n", func->name->word);
+  add_unwind_protect (reset_locals, 0);
+
+  indent (indentation);
+  cprintf ("{ \n");
+
+  inside_function_def++;
+  indentation += indentation_amount;
+
+  cmdcopy = copy_command (func->command);      /* possible mem leak on unwind-protect */
+  if (cmdcopy->type == cm_group)
+    {
+      func_redirects = cmdcopy->redirects;
+      cmdcopy->redirects = (REDIRECT *)NULL;
+    }
+  make_command_string_internal (cmdcopy->type == cm_group
+                                       ? cmdcopy->value.Group->command
+                                       : cmdcopy);
+
+  remove_unwind_protect ();
+  indentation -= indentation_amount;
+  inside_function_def--;
+
+  if (func_redirects)
+    { /* { */
+      newline ("} ");
+      print_redirection_list (func_redirects);
+      cmdcopy->redirects = func_redirects;
+    }
+  else
+    newline ("}");
+
+  dispose_command (cmdcopy);
+}
+
+/* Return the string representation of the named function.
+   NAME is the name of the function.
+   COMMAND is the function body.  It should be a GROUP_COM.
+   MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
+  */
+char *
+named_function_string (name, command, multi_line)
+     char *name;
+     COMMAND *command;
+     int multi_line;
+{
+  char *result;
+  int old_indent, old_amount;
+  COMMAND *cmdcopy;
+  REDIRECT *func_redirects;
+
+  old_indent = indentation;
+  old_amount = indentation_amount;
+  command_string_index = was_heredoc = 0;
+  inside_pipeline = 0;
+
+  if (name && *name)
+    cprintf ("%s ", name);
+
+  cprintf ("() ");
+
+  if (multi_line == 0)
+    {
+      indentation = 1;
+      indentation_amount = 0;
+    }
+  else
+    {
+      cprintf ("\n");
+      indentation += indentation_amount;
+    }
+
+  inside_function_def++;
+
+  cprintf (multi_line ? "{ \n" : "{ ");
+
+  cmdcopy = copy_command (command);
+  /* Take any redirections specified in the function definition (which should
+     apply to the function as a whole) and save them for printing later. */
+  func_redirects = (REDIRECT *)NULL;
+  if (cmdcopy->type == cm_group)
+    {
+      func_redirects = cmdcopy->redirects;
+      cmdcopy->redirects = (REDIRECT *)NULL;
+    }
+  make_command_string_internal (cmdcopy->type == cm_group
+                                       ? cmdcopy->value.Group->command
+                                       : cmdcopy);
+
+  indentation = old_indent;
+  indentation_amount = old_amount;
+  inside_function_def--;
+
+  if (func_redirects)
+    { /* { */
+      newline ("} ");
+      print_redirection_list (func_redirects);
+      cmdcopy->redirects = func_redirects;
+    }
+  else
+    newline ("}");
+
+  result = the_printed_command;
+
+  if (!multi_line)
+    {
+#if 0
+      register int i;
+      for (i = 0; result[i]; i++)
+       if (result[i] == '\n')
+         {
+           strcpy (result + i, result + i + 1);
+           --i;
+         }
+#else
+      if (result[2] == '\n')   /* XXX -- experimental */
+       strcpy (result + 2, result + 3);
+#endif
+    }
+
+  dispose_command (cmdcopy);
+
+  return (result);
+}
+
+static void
+newline (string)
+     char *string;
+{
+  cprintf ("\n");
+  indent (indentation);
+  if (string && *string)
+    cprintf ("%s", string);
+}
+
+static char *indentation_string;
+static int indentation_size;
+
+static void
+indent (amount)
+     int amount;
+{
+  register int i;
+
+  RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
+
+  for (i = 0; amount > 0; amount--)
+    indentation_string[i++] = ' ';
+  indentation_string[i] = '\0';
+  cprintf (indentation_string);
+}
+
+static void
+semicolon ()
+{
+  if (command_string_index > 0 &&
+       (the_printed_command[command_string_index - 1] == '&' ||
+        the_printed_command[command_string_index - 1] == '\n'))
+    return;
+  cprintf (";");
+}
+
+/* How to make the string. */
+static void
+#if defined (PREFER_STDARG)
+cprintf (const char *control, ...)
+#else
+cprintf (control, va_alist)
+     const char *control;
+     va_dcl
+#endif
+{
+  register const char *s;
+  char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
+  int digit_arg, arg_len, c;
+  va_list args;
+
+  SH_VA_START (args, control);
+
+  arg_len = strlen (control);
+  the_printed_command_resize (arg_len + 1);
+
+  char_arg[1] = '\0';
+  s = control;
+  while (s && *s)
+    {
+      c = *s++;
+      argp = (char *)NULL;
+      if (c != '%' || !*s)
+       {
+         char_arg[0] = c;
+         argp = char_arg;
+         arg_len = 1;
+       }
+      else
+       {
+         c = *s++;
+         switch (c)
+           {
+           case '%':
+             char_arg[0] = c;
+             argp = char_arg;
+             arg_len = 1;
+             break;
+
+           case 's':
+             argp = va_arg (args, char *);
+             arg_len = strlen (argp);
+             break;
+
+           case 'd':
+             /* Represent an out-of-range file descriptor with an out-of-range
+                integer value.  We can do this because the only use of `%d' in
+                the calls to cprintf is to output a file descriptor number for
+                a redirection. */
+             digit_arg = va_arg (args, int);
+             if (digit_arg < 0)
+               {
+                 sprintf (intbuf, "%u", (unsigned)-1);
+                 argp = intbuf;
+               }
+             else
+               argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
+             arg_len = strlen (argp);
+             break;
+
+           case 'c':
+             char_arg[0] = va_arg (args, int);
+             argp = char_arg;
+             arg_len = 1;
+             break;
+
+           default:
+             programming_error (_("cprintf: `%c': invalid format character"), c);
+             /*NOTREACHED*/
+           }
+       }
+
+      if (argp && arg_len)
+       {
+         the_printed_command_resize (arg_len + 1);
+         FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
+         command_string_index += arg_len;
+       }
+    }
+
+  the_printed_command[command_string_index] = '\0';
+}
+
+/* Ensure that there is enough space to stuff LENGTH characters into
+   THE_PRINTED_COMMAND. */
+static void
+the_printed_command_resize (length)
+     int length;
+{
+  if (the_printed_command == 0)
+    {
+      the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
+      the_printed_command = (char *)xmalloc (the_printed_command_size);
+      command_string_index = 0;
+    }
+  else if ((command_string_index + length) >= the_printed_command_size)
+    {
+      int new;
+      new = command_string_index + length + 1;
+
+      /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
+      new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
+      the_printed_command_size = new;
+
+      the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
+    }
+}
+
+#if defined (HAVE_VPRINTF)
+/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
+     also available.'' */
+
+static void
+#if defined (PREFER_STDARG)
+xprintf (const char *format, ...)
+#else
+xprintf (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  SH_VA_START (args, format);
+
+  vfprintf (stdout, format, args);
+  va_end (args);
+}
+
+#else
+
+static void
+xprintf (format, arg1, arg2, arg3, arg4, arg5)
+     const char *format;
+{
+  printf (format, arg1, arg2, arg3, arg4, arg5);
+}
+
+#endif /* !HAVE_VPRINTF */
index 3efcf32d68e9722024b6ca9d67f9e81b2aa5ac04..72ec06a2c1fd8dde92acea5e8ac773e35f1d061b 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR