LCOV - code coverage report
Current view: top level - bash-4.4.23 - print_cmd.c (source / functions) Hit Total Coverage
Test: cov-sh.info Lines: 347 786 44.1 %
Date: 2020-10-29 14:49:55 Functions: 22 49 44.9 %

          Line data    Source code
       1             : /* print_command -- A way to make readable commands from a command tree. */
       2             : 
       3             : /* Copyright (C) 1989-2016 Free Software Foundation, Inc.
       4             : 
       5             :    This file is part of GNU Bash, the Bourne Again SHell.
       6             : 
       7             :    Bash is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    Bash is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "config.h"
      22             : 
      23             : #include <stdio.h>
      24             : 
      25             : #if defined (HAVE_UNISTD_H)
      26             : #  ifdef _MINIX
      27             : #    include <sys/types.h>
      28             : #  endif
      29             : #  include <unistd.h>
      30             : #endif
      31             : 
      32             : #if defined (PREFER_STDARG)
      33             : #  include <stdarg.h>
      34             : #else
      35             : #  include <varargs.h>
      36             : #endif
      37             : 
      38             : #include "bashansi.h"
      39             : #include "bashintl.h"
      40             : 
      41             : #include "shell.h"
      42             : #include "flags.h"
      43             : #include <y.tab.h>        /* use <...> so we pick it up from the build directory */
      44             : #include "input.h"
      45             : 
      46             : #include "shmbutil.h"
      47             : 
      48             : #include "builtins/common.h"
      49             : 
      50             : #if !HAVE_DECL_PRINTF
      51             : extern int printf __P((const char *, ...));     /* Yuck.  Double yuck. */
      52             : #endif
      53             : 
      54             : extern int indirection_level;
      55             : extern int posixly_correct;
      56             : 
      57             : static int indentation;
      58             : static int indentation_amount = 4;
      59             : 
      60             : #if defined (PREFER_STDARG)
      61             : typedef void PFUNC __P((const char *, ...));
      62             : 
      63             : static void cprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
      64             : static void xprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
      65             : #else
      66             : #define PFUNC VFunction
      67             : static void cprintf ();
      68             : static void xprintf ();
      69             : #endif
      70             : 
      71             : static void reset_locals __P((void));
      72             : static void newline __P((char *));
      73             : static void indent __P((int));
      74             : static void semicolon __P((void));
      75             : static void the_printed_command_resize __P((int));
      76             : 
      77             : static void make_command_string_internal __P((COMMAND *));
      78             : static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
      79             : static void command_print_word_list __P((WORD_LIST *, char *));
      80             : static void print_case_clauses __P((PATTERN_LIST *));
      81             : static void print_redirection_list __P((REDIRECT *));
      82             : static void print_redirection __P((REDIRECT *));
      83             : static void print_heredoc_header __P((REDIRECT *));
      84             : static void print_heredoc_body __P((REDIRECT *));
      85             : static void print_heredocs __P((REDIRECT *));
      86             : static void print_deferred_heredocs __P((const char *));
      87             : 
      88             : static void print_for_command __P((FOR_COM *));
      89             : #if defined (ARITH_FOR_COMMAND)
      90             : static void print_arith_for_command __P((ARITH_FOR_COM *));
      91             : #endif
      92             : #if defined (SELECT_COMMAND)
      93             : static void print_select_command __P((SELECT_COM *));
      94             : #endif
      95             : static void print_group_command __P((GROUP_COM *));
      96             : static void print_case_command __P((CASE_COM *));
      97             : static void print_while_command __P((WHILE_COM *));
      98             : static void print_until_command __P((WHILE_COM *));
      99             : static void print_until_or_while __P((WHILE_COM *, char *));
     100             : static void print_if_command __P((IF_COM *));
     101             : #if defined (COND_COMMAND)
     102             : static void print_cond_node __P((COND_COM *));
     103             : #endif
     104             : static void print_function_def __P((FUNCTION_DEF *));
     105             : 
     106             : #define PRINTED_COMMAND_INITIAL_SIZE 64
     107             : #define PRINTED_COMMAND_GROW_SIZE 128
     108             : 
     109             : char *the_printed_command = (char *)NULL;
     110             : int the_printed_command_size = 0;
     111             : int command_string_index = 0;
     112             : 
     113             : int xtrace_fd = -1;
     114             : FILE *xtrace_fp = 0;
     115             : 
     116             : #define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
     117             : 
     118             : /* shell expansion characters: used in print_redirection_list */
     119             : #define EXPCHAR(c) ((c) == '{' || (c) == '~' || (c) == '$' || (c) == '`')
     120             : 
     121             : #define PRINT_DEFERRED_HEREDOCS(x) \
     122             :   do { \
     123             :     if (deferred_heredocs) \
     124             :       print_deferred_heredocs (x); \
     125             :   } while (0)
     126             : 
     127             : /* Non-zero means the stuff being printed is inside of a function def. */
     128             : static int inside_function_def;
     129             : static int skip_this_indent;
     130             : static int was_heredoc;
     131             : static int printing_connection;
     132             : static REDIRECT *deferred_heredocs;
     133             : 
     134             : /* The depth of the group commands that we are currently printing.  This
     135             :    includes the group command that is a function body. */
     136             : static int group_command_nesting;
     137             : 
     138             : /* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
     139             : static char *indirection_string = 0;
     140             : static int indirection_stringsiz = 0;
     141             : 
     142             : /* Print COMMAND (a command tree) on standard output. */
     143             : void
     144           0 : print_command (command)
     145             :      COMMAND *command;
     146             : {
     147           0 :   command_string_index = 0;
     148           0 :   printf ("%s", make_command_string (command));
     149           0 : }
     150             : 
     151             : /* Make a string which is the printed representation of the command
     152             :    tree in COMMAND.  We return this string.  However, the string is
     153             :    not consed, so you have to do that yourself if you want it to
     154             :    remain around. */
     155             : char *
     156        3601 : make_command_string (command)
     157             :      COMMAND *command;
     158             : {
     159        3601 :   command_string_index = was_heredoc = 0;
     160        3601 :   deferred_heredocs = 0;
     161        3601 :   make_command_string_internal (command);
     162           0 :   return (the_printed_command);
     163             : }
     164             : 
     165             : /* The internal function.  This is the real workhorse. */
     166             : static void
     167       19715 : make_command_string_internal (command)
     168             :      COMMAND *command;
     169             : {
     170       19715 :   char s[3];
     171             : 
     172       19715 :   if (command == 0)
     173          41 :     cprintf ("");
     174             :   else
     175             :     {
     176       19674 :       if (skip_this_indent)
     177       11061 :         skip_this_indent--;
     178             :       else
     179        8613 :         indent (indentation);
     180             : 
     181       19674 :       if (command->flags & CMD_TIME_PIPELINE)
     182             :         {
     183           0 :           cprintf ("time ");
     184           0 :           if (command->flags & CMD_TIME_POSIX)
     185           0 :             cprintf ("-p ");
     186             :         }
     187             : 
     188       19674 :       if (command->flags & CMD_INVERT_RETURN)
     189           0 :         cprintf ("! ");
     190             : 
     191       19674 :       switch (command->type)
     192             :         {
     193           0 :         case cm_for:
     194           0 :           print_for_command (command->value.For);
     195           0 :           break;
     196             : 
     197             : #if defined (ARITH_FOR_COMMAND)
     198           0 :         case cm_arith_for:
     199           0 :           print_arith_for_command (command->value.ArithFor);
     200           0 :           break;
     201             : #endif
     202             : 
     203             : #if defined (SELECT_COMMAND)
     204           0 :         case cm_select:
     205           0 :           print_select_command (command->value.Select);
     206           0 :           break;
     207             : #endif
     208             : 
     209         123 :         case cm_case:
     210         123 :           print_case_command (command->value.Case);
     211         123 :           break;
     212             : 
     213        2938 :         case cm_while:
     214        2938 :           print_while_command (command->value.While);
     215        2938 :           break;
     216             : 
     217           0 :         case cm_until:
     218           0 :           print_until_command (command->value.While);
     219           0 :           break;
     220             : 
     221         155 :         case cm_if:
     222         155 :           print_if_command (command->value.If);
     223         155 :           break;
     224             : 
     225             : #if defined (DPAREN_ARITHMETIC)
     226           0 :         case cm_arith:
     227           0 :           print_arith_command (command->value.Arith->exp);
     228           0 :           break;
     229             : #endif
     230             : 
     231             : #if defined (COND_COMMAND)
     232           0 :         case cm_cond:
     233           0 :           print_cond_command (command->value.Cond);
     234           0 :           break;
     235             : #endif
     236             : 
     237       11772 :         case cm_simple:
     238       11772 :           print_simple_command (command->value.Simple);
     239       11772 :           break;
     240             : 
     241        4269 :         case cm_connection:
     242             : 
     243        4269 :           skip_this_indent++;
     244        4269 :           printing_connection++;
     245        4269 :           make_command_string_internal (command->value.Connection->first);
     246             : 
     247        4269 :           switch (command->value.Connection->connector)
     248             :             {
     249          73 :             case '&':
     250             :             case '|':
     251             :               {
     252          73 :                 char c = command->value.Connection->connector;
     253             : 
     254          73 :                 s[0] = ' ';
     255          73 :                 s[1] = c;
     256          73 :                 s[2] = '\0';
     257             :                 
     258          73 :                 print_deferred_heredocs (s);
     259             : 
     260          73 :                 if (c != '&' || command->value.Connection->second)
     261             :                   {
     262          73 :                     cprintf (" ");
     263          73 :                     skip_this_indent++;
     264             :                   }
     265             :               }
     266             :               break;
     267             : 
     268           0 :             case AND_AND:
     269           0 :               print_deferred_heredocs (" && ");
     270           0 :               if (command->value.Connection->second)
     271           0 :                 skip_this_indent++;
     272             :               break;
     273             : 
     274        3115 :             case OR_OR:
     275        3115 :               print_deferred_heredocs (" || ");
     276        3115 :               if (command->value.Connection->second)
     277        3115 :                 skip_this_indent++;
     278             :               break;
     279             : 
     280        1081 :             case ';':
     281        1081 :               if (deferred_heredocs == 0)
     282             :                 {
     283        1081 :                   if (was_heredoc == 0)
     284        1081 :                     cprintf (";");
     285             :                   else
     286           0 :                     was_heredoc = 0;
     287             :                 }
     288             :               else
     289           0 :                 print_deferred_heredocs (inside_function_def ? "" : ";");
     290             : 
     291        1081 :               if (inside_function_def)
     292         684 :                 cprintf ("\n");
     293             :               else
     294             :                 {
     295         397 :                   cprintf (" ");
     296         397 :                   if (command->value.Connection->second)
     297         397 :                     skip_this_indent++;
     298             :                 }
     299             :               break;
     300             : 
     301           0 :             default:
     302           0 :               cprintf (_("print_command: bad connector `%d'"),
     303             :                        command->value.Connection->connector);
     304           0 :               break;
     305             :             }
     306             : 
     307        4269 :           make_command_string_internal (command->value.Connection->second);
     308        4269 :           PRINT_DEFERRED_HEREDOCS ("");
     309        4269 :           printing_connection--;                  
     310        4269 :           break;
     311             : 
     312         303 :         case cm_function_def:
     313         303 :           print_function_def (command->value.Function_def);
     314         303 :           break;
     315             : 
     316           9 :         case cm_group:
     317           9 :           print_group_command (command->value.Group);
     318           9 :           break;
     319             : 
     320         105 :         case cm_subshell:
     321         105 :           cprintf ("( ");
     322         105 :           skip_this_indent++;
     323         105 :           make_command_string_internal (command->value.Subshell->command);
     324         105 :           PRINT_DEFERRED_HEREDOCS ("");
     325         105 :           cprintf (" )");
     326         105 :           break;
     327             : 
     328           0 :         case cm_coproc:
     329           0 :           cprintf ("coproc %s ", command->value.Coproc->name);
     330           0 :           skip_this_indent++;
     331           0 :           make_command_string_internal (command->value.Coproc->command);
     332           0 :           break;
     333             : 
     334           0 :         default:
     335           0 :           command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
     336           0 :           break;
     337             :         }
     338             : 
     339             : 
     340       19674 :       if (command->redirects)
     341             :         {
     342           0 :           cprintf (" ");
     343           0 :           print_redirection_list (command->redirects);
     344             :         }
     345             :     }
     346       19715 : }
     347             : 
     348             : static void
     349             : _print_word_list (list, separator, pfunc)
     350             :      WORD_LIST *list;
     351             :      char *separator;
     352             :      PFUNC *pfunc;
     353             : {
     354    86316420 :   WORD_LIST *w;
     355             : 
     356   284601743 :   for (w = list; w; w = w->next)
     357   284600805 :     (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
     358             : }
     359             : 
     360             : void
     361           0 : print_word_list (list, separator)
     362             :      WORD_LIST *list;
     363             :      char *separator;
     364             : {
     365           0 :   _print_word_list (list, separator, xprintf);
     366           0 : }
     367             : 
     368             : void
     369     9542957 : xtrace_set (fd, fp)
     370             :      int fd;
     371             :      FILE *fp;
     372             : {
     373     9542957 :   if (fd >= 0 && sh_validfd (fd) == 0)
     374             :     {
     375           0 :       internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
     376           0 :       return;
     377             :     }
     378     9542957 :   if (fp == 0)
     379             :     {
     380           0 :       internal_error (_("xtrace_set: NULL file pointer"));
     381           0 :       return;
     382             :     }
     383     9542957 :   if (fd >= 0 && fileno (fp) != fd)
     384           0 :     internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
     385             :   
     386     9542957 :   xtrace_fd = fd;
     387     9542957 :   xtrace_fp = fp;
     388             : }
     389             : 
     390             : void
     391     9542957 : xtrace_init ()
     392             : {
     393     9542957 :   xtrace_set (-1, stderr);
     394     9542957 : }
     395             : 
     396             : void
     397           0 : xtrace_reset ()
     398             : {
     399           0 :   if (xtrace_fd >= 0 && xtrace_fp)
     400             :     {
     401           0 :       fflush (xtrace_fp);
     402           0 :       fclose (xtrace_fp);
     403             :     }
     404           0 :   else if (xtrace_fd >= 0)
     405           0 :     close (xtrace_fd);
     406             : 
     407           0 :   xtrace_fd = -1;
     408           0 :   xtrace_fp = stderr;
     409           0 : }
     410             : 
     411             : void
     412         699 : xtrace_fdchk (fd)
     413             :      int fd;
     414             : {
     415         699 :   if (fd == xtrace_fd)
     416           0 :     xtrace_reset ();
     417         699 : }
     418             : 
     419             : /* Return a string denoting what our indirection level is. */
     420             : 
     421             : char *
     422           0 : indirection_level_string ()
     423             : {
     424           0 :   register int i, j;
     425           0 :   char *ps4;
     426           0 :   char ps4_firstc[MB_LEN_MAX+1];
     427           0 :   int ps4_firstc_len, ps4_len, ineed, old;
     428             : 
     429           0 :   ps4 = get_string_value ("PS4");
     430           0 :   if (indirection_string == 0)
     431           0 :     indirection_string = xmalloc (indirection_stringsiz = 100);
     432           0 :   indirection_string[0] = '\0';
     433             : 
     434           0 :   if (ps4 == 0 || *ps4 == '\0')
     435             :     return (indirection_string);
     436             : 
     437           0 :   old = change_flag ('x', FLAG_OFF);
     438           0 :   ps4 = decode_prompt_string (ps4);
     439           0 :   if (old)
     440           0 :     change_flag ('x', FLAG_ON);
     441             : 
     442           0 :   if (ps4 == 0 || *ps4 == '\0')
     443           0 :     return (indirection_string);
     444             : 
     445             : #if defined (HANDLE_MULTIBYTE)
     446           0 :   ps4_len = strnlen (ps4, MB_CUR_MAX);
     447           0 :   ps4_firstc_len = MBLEN (ps4, ps4_len);
     448           0 :   if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || ps4_firstc_len < 0)
     449             :     {
     450           0 :       ps4_firstc[0] = ps4[0];
     451           0 :       ps4_firstc[ps4_firstc_len = 1] = '\0';
     452             :     }
     453             :   else
     454           0 :     memcpy (ps4_firstc, ps4, ps4_firstc_len);
     455             : #else
     456             :   ps4_firstc[0] = ps4[0];
     457             :   ps4_firstc[ps4_firstc_len = 1] = '\0';
     458             : #endif
     459             : 
     460             :   /* Dynamically resize indirection_string so we have room for everything
     461             :      and we don't have to truncate ps4 */
     462           0 :   ineed = (ps4_firstc_len * indirection_level) + strlen (ps4);
     463           0 :   if (ineed > indirection_stringsiz - 1)
     464             :     {
     465           0 :       indirection_stringsiz = ineed + 1;
     466           0 :       indirection_string = xrealloc (indirection_string, indirection_stringsiz);
     467             :     }
     468             : 
     469           0 :   for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < indirection_stringsiz - 1; i += ps4_firstc_len, j++)
     470             :     {
     471           0 :       if (ps4_firstc_len == 1)
     472           0 :         indirection_string[i] = ps4_firstc[0];
     473             :       else
     474           0 :         memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
     475             :     }      
     476             : 
     477           0 :   for (j = ps4_firstc_len; *ps4 && ps4[j] && i < indirection_stringsiz - 1; i++, j++)
     478           0 :     indirection_string[i] = ps4[j];
     479             : 
     480           0 :   indirection_string[i] = '\0';
     481           0 :   free (ps4);
     482           0 :   return (indirection_string);
     483             : }
     484             : 
     485             : void
     486           0 : xtrace_print_assignment (name, value, assign_list, xflags)
     487             :      char *name, *value;
     488             :      int assign_list, xflags;
     489             : {
     490           0 :   char *nval;
     491             : 
     492           0 :   CHECK_XTRACE_FP;
     493             : 
     494           0 :   if (xflags)
     495           0 :     fprintf (xtrace_fp, "%s", indirection_level_string ());
     496             : 
     497             :   /* VALUE should not be NULL when this is called. */
     498           0 :   if (*value == '\0' || assign_list)
     499             :     nval = value;
     500           0 :   else if (sh_contains_shell_metas (value))
     501           0 :     nval = sh_single_quote (value);
     502           0 :   else if (ansic_shouldquote (value))
     503           0 :     nval = ansic_quote (value, 0, (int *)0);
     504             :   else
     505             :     nval = value;
     506             : 
     507           0 :   if (assign_list)
     508           0 :     fprintf (xtrace_fp, "%s=(%s)\n", name, nval);
     509             :   else
     510           0 :     fprintf (xtrace_fp, "%s=%s\n", name, nval);
     511             : 
     512           0 :   if (nval != value)
     513           0 :     FREE (nval);
     514             : 
     515           0 :   fflush (xtrace_fp);
     516           0 : }
     517             : 
     518             : /* A function to print the words of a simple command when set -x is on.  Also
     519             :    used to print the word list in a for or select command header; in that case,
     520             :    we suppress quoting the words because they haven't been expanded yet.
     521             :    XTFLAGS&1 means to print $PS4; XTFLAGS&2 means to suppress quoting the
     522             :    words in LIST. */
     523             : void
     524           0 : xtrace_print_word_list (list, xtflags)
     525             :      WORD_LIST *list;
     526             :      int xtflags;
     527             : {
     528           0 :   WORD_LIST *w;
     529           0 :   char *t, *x;
     530             : 
     531           0 :   CHECK_XTRACE_FP;
     532             : 
     533           0 :   if (xtflags&1)
     534           0 :     fprintf (xtrace_fp, "%s", indirection_level_string ());
     535             : 
     536           0 :   for (w = list; w; w = w->next)
     537             :     {
     538           0 :       t = w->word->word;
     539           0 :       if (t == 0 || *t == '\0')
     540           0 :         fprintf (xtrace_fp, "''%s", w->next ? " " : "");
     541           0 :       else if (xtflags & 2)
     542           0 :         fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
     543           0 :       else if (sh_contains_shell_metas (t))
     544             :         {
     545           0 :           x = sh_single_quote (t);
     546           0 :           fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
     547           0 :           free (x);
     548             :         }
     549           0 :       else if (ansic_shouldquote (t))
     550             :         {
     551           0 :           x = ansic_quote (t, 0, (int *)0);
     552           0 :           fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
     553           0 :           free (x);
     554             :         }
     555             :       else
     556           0 :         fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
     557             :     }
     558           0 :   fprintf (xtrace_fp, "\n");
     559           0 :   fflush (xtrace_fp);
     560           0 : }
     561             : 
     562             : static void
     563    86316420 : command_print_word_list (list, separator)
     564             :      WORD_LIST *list;
     565             :      char *separator;
     566             : {
     567    86316420 :   _print_word_list (list, separator, cprintf);
     568    86316420 : }
     569             : 
     570             : void
     571           0 : print_for_command_head (for_command)
     572             :      FOR_COM *for_command;
     573             : {
     574           0 :   cprintf ("for %s in ", for_command->name->word);
     575           0 :   command_print_word_list (for_command->map_list, " ");
     576           0 : }
     577             : 
     578             : void
     579           0 : xtrace_print_for_command_head (for_command)
     580             :      FOR_COM *for_command;
     581             : {
     582           0 :   CHECK_XTRACE_FP;
     583           0 :   fprintf (xtrace_fp, "%s", indirection_level_string ());
     584           0 :   fprintf (xtrace_fp, "for %s in ", for_command->name->word);
     585           0 :   xtrace_print_word_list (for_command->map_list, 2);
     586           0 : }
     587             : 
     588             : static void
     589           0 : print_for_command (for_command)
     590             :      FOR_COM *for_command;
     591             : {
     592           0 :   print_for_command_head (for_command);
     593           0 :   cprintf (";");
     594           0 :   newline ("do\n");
     595             : 
     596           0 :   indentation += indentation_amount;
     597           0 :   make_command_string_internal (for_command->action);
     598           0 :   PRINT_DEFERRED_HEREDOCS ("");
     599           0 :   semicolon ();
     600           0 :   indentation -= indentation_amount;
     601             : 
     602           0 :   newline ("done");
     603           0 : }
     604             : 
     605             : #if defined (ARITH_FOR_COMMAND)
     606             : static void
     607           0 : print_arith_for_command (arith_for_command)
     608             :      ARITH_FOR_COM *arith_for_command;
     609             : {
     610           0 :   cprintf ("for ((");
     611           0 :   command_print_word_list (arith_for_command->init, " ");
     612           0 :   cprintf ("; ");
     613           0 :   command_print_word_list (arith_for_command->test, " ");
     614           0 :   cprintf ("; ");
     615           0 :   command_print_word_list (arith_for_command->step, " ");
     616           0 :   cprintf ("))");
     617           0 :   newline ("do\n");
     618           0 :   indentation += indentation_amount;
     619           0 :   make_command_string_internal (arith_for_command->action);
     620           0 :   PRINT_DEFERRED_HEREDOCS ("");
     621           0 :   semicolon ();
     622           0 :   indentation -= indentation_amount;
     623           0 :   newline ("done");
     624           0 : }
     625             : #endif /* ARITH_FOR_COMMAND */
     626             : 
     627             : #if defined (SELECT_COMMAND)
     628             : void
     629           0 : print_select_command_head (select_command)
     630             :      SELECT_COM *select_command;
     631             : {
     632           0 :   cprintf ("select %s in ", select_command->name->word);
     633           0 :   command_print_word_list (select_command->map_list, " ");
     634           0 : }
     635             : 
     636             : void
     637           0 : xtrace_print_select_command_head (select_command)
     638             :      SELECT_COM *select_command;
     639             : {
     640           0 :   CHECK_XTRACE_FP;
     641           0 :   fprintf (xtrace_fp, "%s", indirection_level_string ());
     642           0 :   fprintf (xtrace_fp, "select %s in ", select_command->name->word);
     643           0 :   xtrace_print_word_list (select_command->map_list, 2);
     644           0 : }
     645             : 
     646             : static void
     647           0 : print_select_command (select_command)
     648             :      SELECT_COM *select_command;
     649             : {
     650           0 :   print_select_command_head (select_command);
     651             : 
     652           0 :   cprintf (";");
     653           0 :   newline ("do\n");
     654           0 :   indentation += indentation_amount;
     655           0 :   make_command_string_internal (select_command->action);
     656           0 :   PRINT_DEFERRED_HEREDOCS ("");
     657           0 :   semicolon ();
     658           0 :   indentation -= indentation_amount;
     659           0 :   newline ("done");
     660           0 : }
     661             : #endif /* SELECT_COMMAND */
     662             : 
     663             : static void
     664           0 : print_group_command (group_command)
     665             :      GROUP_COM *group_command;
     666             : {
     667           0 :   group_command_nesting++;
     668           0 :   cprintf ("{ ");
     669             : 
     670           0 :   if (inside_function_def == 0)
     671           0 :     skip_this_indent++;
     672             :   else
     673             :     {
     674             :       /* This is a group command { ... } inside of a function
     675             :          definition, and should be printed as a multiline group
     676             :          command, using the current indentation. */
     677           0 :       cprintf ("\n");
     678           0 :       indentation += indentation_amount;
     679             :     }
     680             : 
     681           0 :   make_command_string_internal (group_command->command);
     682           0 :   PRINT_DEFERRED_HEREDOCS ("");
     683             : 
     684           0 :   if (inside_function_def)
     685             :     {
     686           0 :       cprintf ("\n");
     687           0 :       indentation -= indentation_amount;
     688           0 :       indent (indentation);
     689             :     }
     690             :   else
     691             :     {
     692           0 :       semicolon ();
     693           0 :       cprintf (" ");
     694             :     }
     695             : 
     696           0 :   cprintf ("}");
     697             : 
     698           0 :   group_command_nesting--;
     699           0 : }
     700             : 
     701             : void
     702     5643926 : print_case_command_head (case_command)
     703             :      CASE_COM *case_command;
     704             : {
     705     5643926 :   cprintf ("case %s in ", case_command->word->word);
     706     5643926 : }
     707             : 
     708             : void
     709           0 : xtrace_print_case_command_head (case_command)
     710             :      CASE_COM *case_command;
     711             : {
     712           0 :   CHECK_XTRACE_FP;
     713           0 :   fprintf (xtrace_fp, "%s", indirection_level_string ());
     714           0 :   fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
     715           0 : }
     716             : 
     717             : static void
     718           0 : print_case_command (case_command)
     719             :      CASE_COM *case_command;
     720             : {
     721           0 :   print_case_command_head (case_command);
     722             : 
     723           0 :   if (case_command->clauses)
     724           0 :     print_case_clauses (case_command->clauses);
     725           0 :   newline ("esac");
     726           0 : }
     727             : 
     728             : static void
     729         123 : print_case_clauses (clauses)
     730             :      PATTERN_LIST *clauses;
     731             : {
     732         123 :   indentation += indentation_amount;
     733         943 :   while (clauses)
     734             :     {
     735         820 :       newline ("");
     736         820 :       command_print_word_list (clauses->patterns, " | ");
     737         820 :       cprintf (")\n");
     738         820 :       indentation += indentation_amount;
     739         820 :       make_command_string_internal (clauses->action);
     740         820 :       indentation -= indentation_amount;
     741         820 :       PRINT_DEFERRED_HEREDOCS ("");
     742         820 :       if (clauses->flags & CASEPAT_FALLTHROUGH)
     743           0 :         newline (";&");
     744         820 :       else if (clauses->flags & CASEPAT_TESTNEXT)
     745           0 :         newline (";;&");
     746             :       else
     747         820 :         newline (";;");
     748         820 :       clauses = clauses->next;
     749             :     }
     750         123 :   indentation -= indentation_amount;
     751         123 : }
     752             : 
     753             : static void
     754        2938 : print_while_command (while_command)
     755             :      WHILE_COM *while_command;
     756             : {
     757        2938 :   print_until_or_while (while_command, "while");
     758        2938 : }
     759             : 
     760             : static void
     761           0 : print_until_command (while_command)
     762             :      WHILE_COM *while_command;
     763             : {
     764           0 :   print_until_or_while (while_command, "until");
     765           0 : }
     766             : 
     767             : static void
     768           0 : print_until_or_while (while_command, which)
     769             :      WHILE_COM *while_command;
     770             :      char *which;
     771             : {
     772           0 :   cprintf ("%s ", which);
     773           0 :   skip_this_indent++;
     774           0 :   make_command_string_internal (while_command->test);
     775           0 :   PRINT_DEFERRED_HEREDOCS ("");
     776           0 :   semicolon ();
     777           0 :   cprintf (" do\n");  /* was newline ("do\n"); */
     778           0 :   indentation += indentation_amount;
     779           0 :   make_command_string_internal (while_command->action);
     780           0 :   PRINT_DEFERRED_HEREDOCS ("");
     781           0 :   indentation -= indentation_amount;
     782           0 :   semicolon ();
     783           0 :   newline ("done");
     784           0 : }
     785             : 
     786             : static void
     787         155 : print_if_command (if_command)
     788             :      IF_COM *if_command;
     789             : {
     790         155 :   cprintf ("if ");
     791         155 :   skip_this_indent++;
     792         155 :   make_command_string_internal (if_command->test);
     793         155 :   semicolon ();
     794         155 :   cprintf (" then\n");
     795         155 :   indentation += indentation_amount;
     796         155 :   make_command_string_internal (if_command->true_case);
     797         155 :   PRINT_DEFERRED_HEREDOCS ("");
     798         155 :   indentation -= indentation_amount;
     799             : 
     800         155 :   if (if_command->false_case)
     801             :     {
     802          10 :       semicolon ();
     803          10 :       newline ("else\n");
     804          10 :       indentation += indentation_amount;
     805          10 :       make_command_string_internal (if_command->false_case);
     806          10 :       PRINT_DEFERRED_HEREDOCS ("");
     807          10 :       indentation -= indentation_amount;
     808             :     }
     809         155 :   semicolon ();
     810         155 :   newline ("fi");
     811         155 : }
     812             : 
     813             : #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
     814             : void
     815           0 : print_arith_command (arith_cmd_list)
     816             :      WORD_LIST *arith_cmd_list;
     817             : {
     818           0 :   cprintf ("((");
     819           0 :   command_print_word_list (arith_cmd_list, " ");
     820           0 :   cprintf ("))");
     821           0 : }
     822             : #endif
     823             : 
     824             : #if defined (COND_COMMAND)
     825             : static void
     826           0 : print_cond_node (cond)
     827             :      COND_COM *cond;
     828             : {
     829           0 :   if (cond->flags & CMD_INVERT_RETURN)
     830           0 :     cprintf ("! ");
     831             : 
     832           0 :   if (cond->type == COND_EXPR)
     833             :     {
     834           0 :       cprintf ("( ");
     835           0 :       print_cond_node (cond->left);
     836           0 :       cprintf (" )");
     837             :     }
     838           0 :   else if (cond->type == COND_AND)
     839             :     {
     840           0 :       print_cond_node (cond->left);
     841           0 :       cprintf (" && ");
     842           0 :       print_cond_node (cond->right);
     843             :     }
     844           0 :   else if (cond->type == COND_OR)
     845             :     {
     846           0 :       print_cond_node (cond->left);
     847           0 :       cprintf (" || ");
     848           0 :       print_cond_node (cond->right);
     849             :     }
     850           0 :   else if (cond->type == COND_UNARY)
     851             :     {
     852           0 :       cprintf ("%s", cond->op->word);
     853           0 :       cprintf (" ");
     854           0 :       print_cond_node (cond->left);
     855             :     }
     856           0 :   else if (cond->type == COND_BINARY)
     857             :     {
     858           0 :       print_cond_node (cond->left);
     859           0 :       cprintf (" ");
     860           0 :       cprintf ("%s", cond->op->word);
     861           0 :       cprintf (" ");
     862           0 :       print_cond_node (cond->right);
     863             :     }
     864           0 :   else if (cond->type == COND_TERM)
     865             :     {
     866           0 :       cprintf ("%s", cond->op->word);           /* need to add quoting here */
     867             :     }
     868           0 : }
     869             : 
     870             : void
     871           0 : print_cond_command (cond)
     872             :      COND_COM *cond;
     873             : {
     874           0 :   cprintf ("[[ ");
     875           0 :   print_cond_node (cond);
     876           0 :   cprintf (" ]]");
     877           0 : }
     878             : 
     879             : #ifdef DEBUG
     880             : void
     881             : debug_print_word_list (s, list, sep)
     882             :      char *s;
     883             :      WORD_LIST *list;
     884             :      char *sep;
     885             : {
     886             :   WORD_LIST *w;
     887             : 
     888             :   if (s)
     889             :     fprintf (stderr, "%s: ", s);
     890             :   for (w = list; w; w = w->next)
     891             :     fprintf (stderr, "%s%s", w->word->word, w->next ? sep : "");
     892             :   fprintf (stderr, "\n");
     893             : }
     894             : 
     895             : void
     896             : debug_print_cond_command (cond)
     897             :      COND_COM *cond;
     898             : {
     899             :   fprintf (stderr, "DEBUG: ");
     900             :   command_string_index = 0;
     901             :   print_cond_command (cond);
     902             :   fprintf (stderr, "%s\n", the_printed_command);
     903             : }
     904             : #endif
     905             : 
     906             : void
     907           0 : xtrace_print_cond_term (type, invert, op, arg1, arg2)
     908             :      int type, invert;
     909             :      WORD_DESC *op;
     910             :      char *arg1, *arg2;
     911             : {
     912           0 :   CHECK_XTRACE_FP;
     913           0 :   command_string_index = 0;
     914           0 :   fprintf (xtrace_fp, "%s", indirection_level_string ());
     915           0 :   fprintf (xtrace_fp, "[[ ");
     916           0 :   if (invert)
     917           0 :     fprintf (xtrace_fp, "! ");
     918             : 
     919           0 :   if (type == COND_UNARY)
     920             :     {
     921           0 :       fprintf (xtrace_fp, "%s ", op->word);
     922           0 :       fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
     923             :     }
     924           0 :   else if (type == COND_BINARY)
     925             :     {
     926           0 :       fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
     927           0 :       fprintf (xtrace_fp, " %s ", op->word);
     928           0 :       fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
     929             :     }
     930             : 
     931           0 :   fprintf (xtrace_fp, " ]]\n");
     932             : 
     933           0 :   fflush (xtrace_fp);
     934           0 : }         
     935             : #endif /* COND_COMMAND */
     936             : 
     937             : #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
     938             : /* A function to print the words of an arithmetic command when set -x is on. */
     939             : void
     940           0 : xtrace_print_arith_cmd (list)
     941             :      WORD_LIST *list;
     942             : {
     943           0 :   WORD_LIST *w;
     944             : 
     945           0 :   CHECK_XTRACE_FP;
     946           0 :   fprintf (xtrace_fp, "%s", indirection_level_string ());
     947           0 :   fprintf (xtrace_fp, "(( ");
     948           0 :   for (w = list; w; w = w->next)
     949           0 :     fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
     950           0 :   fprintf (xtrace_fp, " ))\n");
     951             : 
     952           0 :   fflush (xtrace_fp);
     953           0 : }
     954             : #endif
     955             : 
     956             : void
     957    86315600 : print_simple_command (simple_command)
     958             :      SIMPLE_COM *simple_command;
     959             : {
     960    86315600 :   command_print_word_list (simple_command->words, " ");
     961             : 
     962    86315600 :   if (simple_command->redirects)
     963             :     {
     964      154770 :       cprintf (" ");
     965      154770 :       print_redirection_list (simple_command->redirects);
     966             :     }
     967    86315600 : }
     968             : 
     969             : static void
     970         146 : print_heredocs (heredocs)
     971             :      REDIRECT *heredocs;
     972             : {
     973         146 :   REDIRECT *hdtail;
     974             : 
     975         146 :   cprintf (" "); 
     976         292 :   for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
     977             :     {
     978         146 :       print_redirection (hdtail);
     979         146 :       cprintf ("\n");
     980             :     }
     981         146 :   was_heredoc = 1;
     982         146 : }
     983             : 
     984             : /* Print heredocs that are attached to the command before the connector
     985             :    represented by CSTRING.  The parsing semantics require us to print the
     986             :    here-doc delimiters, then the connector (CSTRING), then the here-doc
     987             :    bodies.  We don't print the connector if it's a `;', but we use it to
     988             :    note not to print an extra space after the last heredoc body and
     989             :    newline. */
     990             : static void
     991        3188 : print_deferred_heredocs (cstring)
     992             :      const char *cstring;
     993             : {
     994        3188 :   REDIRECT *hdtail;     
     995             : 
     996        3188 :   for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
     997             :     {
     998           0 :       cprintf (" ");
     999           0 :       print_heredoc_header (hdtail);
    1000             :     }
    1001        3188 :   if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
    1002        3188 :     cprintf ("%s", cstring); 
    1003        3188 :   if (deferred_heredocs)
    1004           0 :     cprintf ("\n");
    1005        3188 :   for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
    1006             :     {
    1007           0 :       print_heredoc_body (hdtail);
    1008           0 :       cprintf ("\n");
    1009             :     }
    1010        3188 :   if (deferred_heredocs)
    1011             :     {
    1012           0 :       if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
    1013           0 :         cprintf (" ");        /* make sure there's at least one space */
    1014           0 :       dispose_redirects (deferred_heredocs);
    1015           0 :       was_heredoc = 1;
    1016             :     }
    1017        3188 :   deferred_heredocs = (REDIRECT *)NULL;
    1018        3188 : }
    1019             :       
    1020             : static void
    1021      154770 : print_redirection_list (redirects)
    1022             :      REDIRECT *redirects;
    1023             : {
    1024      154770 :   REDIRECT *heredocs, *hdtail, *newredir;
    1025      154770 :   char *rw;
    1026             : 
    1027      154770 :   heredocs = (REDIRECT *)NULL;
    1028      154770 :   hdtail = heredocs;
    1029             : 
    1030      154770 :   was_heredoc = 0;
    1031      393234 :   while (redirects)
    1032             :     {
    1033             :       /* Defer printing the here documents until we've printed the
    1034             :          rest of the redirections. */
    1035      238464 :       if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
    1036             :         {
    1037         146 :           newredir = copy_redirect (redirects);
    1038         146 :           newredir->next = (REDIRECT *)NULL;
    1039         146 :           if (heredocs)
    1040             :             {
    1041           0 :               hdtail->next = newredir;
    1042           0 :               hdtail = newredir;
    1043             :             }
    1044             :           else
    1045             :             hdtail = heredocs = newredir;
    1046             :         }
    1047      238318 :       else if (redirects->instruction == r_duplicating_output_word && (redirects->flags & REDIR_VARASSIGN) == 0 && redirects->redirector.dest == 1)
    1048             :         {
    1049             :           /* Temporarily translate it as the execution code does. */
    1050          25 :           rw = redirects->redirectee.filename->word;
    1051          25 :           if (rw && *rw != '-' && DIGIT (*rw) == 0 && EXPCHAR (*rw) == 0)
    1052          25 :             redirects->instruction = r_err_and_out;
    1053          25 :           print_redirection (redirects);
    1054          25 :           redirects->instruction = r_duplicating_output_word;
    1055             :         }
    1056             :       else
    1057      238293 :         print_redirection (redirects);
    1058             : 
    1059      238464 :       redirects = redirects->next;
    1060      238464 :       if (redirects)
    1061       83694 :         cprintf (" ");
    1062             :     }
    1063             : 
    1064             :   /* Now that we've printed all the other redirections (on one line),
    1065             :      print the here documents. */
    1066      154770 :   if (heredocs && printing_connection)
    1067           0 :     deferred_heredocs = heredocs;
    1068      154770 :   else if (heredocs)
    1069             :     {
    1070         146 :       print_heredocs (heredocs);
    1071         146 :       dispose_redirects (heredocs);
    1072             :     }
    1073      154770 : }
    1074             : 
    1075             : static void
    1076         146 : print_heredoc_header (redirect)
    1077             :      REDIRECT *redirect;
    1078             : {
    1079         146 :   int kill_leading;
    1080         146 :   char *x;
    1081             : 
    1082         146 :   kill_leading = redirect->instruction == r_deblank_reading_until;
    1083             : 
    1084             :   /* Here doc header */
    1085         146 :   if (redirect->rflags & REDIR_VARASSIGN)
    1086           0 :     cprintf ("{%s}", redirect->redirector.filename->word);
    1087         146 :   else if (redirect->redirector.dest != 0)
    1088           0 :     cprintf ("%d", redirect->redirector.dest);
    1089             : 
    1090             :   /* If the here document delimiter is quoted, single-quote it. */
    1091         146 :   if (redirect->redirectee.filename->flags & W_QUOTED)
    1092             :     {
    1093          49 :       x = sh_single_quote (redirect->here_doc_eof);
    1094          98 :       cprintf ("<<%s%s", kill_leading ? "-" : "", x);
    1095          49 :       free (x);
    1096             :     }
    1097             :   else
    1098         194 :     cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
    1099         146 : }
    1100             : 
    1101             : static void
    1102           0 : print_heredoc_body (redirect)
    1103             :      REDIRECT *redirect;
    1104             : {
    1105             :   /* Here doc body */
    1106           0 :   cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
    1107           0 : }
    1108             : 
    1109             : static void
    1110      238464 : print_redirection (redirect)
    1111             :      REDIRECT *redirect;
    1112             : {
    1113      238464 :   int redirector, redir_fd;
    1114      238464 :   WORD_DESC *redirectee, *redir_word;
    1115             : 
    1116      238464 :   redirectee = redirect->redirectee.filename;
    1117      238464 :   redir_fd = redirect->redirectee.dest;
    1118             : 
    1119      238464 :   redir_word = redirect->redirector.filename;
    1120      238464 :   redirector = redirect->redirector.dest;
    1121             : 
    1122      238464 :   switch (redirect->instruction)
    1123             :     {
    1124       36526 :     case r_input_direction:
    1125       36526 :       if (redirect->rflags & REDIR_VARASSIGN)
    1126           0 :         cprintf ("{%s}", redir_word->word);
    1127       36526 :       else if (redirector != 0)
    1128          24 :         cprintf ("%d", redirector);
    1129       36526 :       cprintf ("< %s", redirectee->word);
    1130       36526 :       break;
    1131             : 
    1132      121683 :     case r_output_direction:
    1133      121683 :       if (redirect->rflags & REDIR_VARASSIGN)
    1134           0 :         cprintf ("{%s}", redir_word->word);
    1135      121683 :       else if (redirector != 1)
    1136       39237 :         cprintf ("%d", redirector);
    1137      121683 :       cprintf ("> %s", redirectee->word);
    1138      121683 :       break;
    1139             : 
    1140           0 :     case r_inputa_direction:    /* Redirection created by the shell. */
    1141           0 :       cprintf ("&");
    1142           0 :       break;
    1143             : 
    1144           9 :     case r_output_force:
    1145           9 :       if (redirect->rflags & REDIR_VARASSIGN)
    1146           0 :         cprintf ("{%s}", redir_word->word);
    1147           9 :       else if (redirector != 1)
    1148           0 :         cprintf ("%d", redirector);
    1149           9 :       cprintf (">| %s", redirectee->word);
    1150           9 :       break;
    1151             : 
    1152       59556 :     case r_appending_to:
    1153       59556 :       if (redirect->rflags & REDIR_VARASSIGN)
    1154           0 :         cprintf ("{%s}", redir_word->word);
    1155       59556 :       else if (redirector != 1)
    1156           9 :         cprintf ("%d", redirector);
    1157       59556 :       cprintf (">> %s", redirectee->word);
    1158       59556 :       break;
    1159             : 
    1160          68 :     case r_input_output:
    1161          68 :       if (redirect->rflags & REDIR_VARASSIGN)
    1162           0 :         cprintf ("{%s}", redir_word->word);
    1163          68 :       else if (redirector != 1)
    1164          68 :         cprintf ("%d", redirector);
    1165          68 :       cprintf ("<> %s", redirectee->word);
    1166          68 :       break;
    1167             : 
    1168         146 :     case r_deblank_reading_until:
    1169             :     case r_reading_until:
    1170         146 :       print_heredoc_header (redirect);
    1171         146 :       cprintf ("\n");
    1172         146 :       print_heredoc_body (redirect);
    1173             :       break;
    1174             : 
    1175          20 :     case r_reading_string:
    1176          20 :       if (redirect->rflags & REDIR_VARASSIGN)
    1177           0 :         cprintf ("{%s}", redir_word->word);
    1178          20 :       else if (redirector != 0)
    1179           0 :         cprintf ("%d", redirector);
    1180             : #if 0
    1181             :       /* Don't need to check whether or not to requote, since original quotes
    1182             :          are still intact.  The only thing that has happened is that $'...'
    1183             :          has been replaced with 'expanded ...'. */
    1184             :       if (ansic_shouldquote (redirect->redirectee.filename->word))
    1185             :         {
    1186             :           char *x;
    1187             :           x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
    1188             :           cprintf ("<<< %s", x);
    1189             :           free (x);
    1190             :         }
    1191             :       else
    1192             : #endif
    1193          20 :         cprintf ("<<< %s", redirect->redirectee.filename->word);
    1194          20 :       break;
    1195             : 
    1196           0 :     case r_duplicating_input:
    1197           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1198           0 :         cprintf ("{%s}<&%d", redir_word->word, redir_fd);
    1199             :       else
    1200           0 :         cprintf ("%d<&%d", redirector, redir_fd);
    1201             :       break;
    1202             : 
    1203       20407 :     case r_duplicating_output:
    1204       20407 :       if (redirect->rflags & REDIR_VARASSIGN)
    1205           0 :         cprintf ("{%s}>&%d", redir_word->word, redir_fd);
    1206             :       else
    1207       20407 :         cprintf ("%d>&%d", redirector, redir_fd);
    1208             :       break;
    1209             : 
    1210           0 :     case r_duplicating_input_word:
    1211           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1212           0 :         cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
    1213             :       else
    1214           0 :         cprintf ("%d<&%s", redirector, redirectee->word);
    1215             :       break;
    1216             : 
    1217           0 :     case r_duplicating_output_word:
    1218           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1219           0 :         cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
    1220             :       else
    1221           0 :         cprintf ("%d>&%s", redirector, redirectee->word);
    1222             :       break;
    1223             : 
    1224           0 :     case r_move_input:
    1225           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1226           0 :         cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
    1227             :       else
    1228           0 :         cprintf ("%d<&%d-", redirector, redir_fd);
    1229             :       break;
    1230             : 
    1231           0 :     case r_move_output:
    1232           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1233           0 :         cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
    1234             :       else
    1235           0 :         cprintf ("%d>&%d-", redirector, redir_fd);
    1236             :       break;
    1237             : 
    1238           0 :     case r_move_input_word:
    1239           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1240           0 :         cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
    1241             :       else
    1242           0 :         cprintf ("%d<&%s-", redirector, redirectee->word);
    1243             :       break;
    1244             : 
    1245           0 :     case r_move_output_word:
    1246           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1247           0 :         cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
    1248             :       else
    1249           0 :         cprintf ("%d>&%s-", redirector, redirectee->word);
    1250             :       break;
    1251             : 
    1252           0 :     case r_close_this:
    1253           0 :       if (redirect->rflags & REDIR_VARASSIGN)
    1254           0 :         cprintf ("{%s}>&-", redir_word->word);
    1255             :       else
    1256           0 :         cprintf ("%d>&-", redirector);
    1257             :       break;
    1258             : 
    1259          49 :     case r_err_and_out:
    1260          49 :       cprintf ("&> %s", redirectee->word);
    1261          49 :       break;
    1262             : 
    1263           0 :     case r_append_err_and_out:
    1264           0 :       cprintf ("&>> %s", redirectee->word);
    1265           0 :       break;
    1266             :     }
    1267      238464 : }
    1268             : 
    1269             : static void
    1270           0 : reset_locals ()
    1271             : {
    1272           0 :   inside_function_def = 0;
    1273           0 :   indentation = 0;
    1274           0 :   printing_connection = 0;
    1275           0 :   deferred_heredocs = 0;
    1276           0 : }
    1277             : 
    1278             : static void
    1279           0 : print_function_def (func)
    1280             :      FUNCTION_DEF *func;
    1281             : {
    1282           0 :   COMMAND *cmdcopy;
    1283           0 :   REDIRECT *func_redirects;
    1284             : 
    1285           0 :   func_redirects = NULL;
    1286             :   /* When in posix mode, print functions as posix specifies them. */
    1287           0 :   if (posixly_correct == 0)
    1288           0 :     cprintf ("function %s () \n", func->name->word);
    1289             :   else
    1290           0 :     cprintf ("%s () \n", func->name->word);
    1291           0 :   add_unwind_protect (reset_locals, 0);
    1292             : 
    1293           0 :   indent (indentation);
    1294           0 :   cprintf ("{ \n");
    1295             : 
    1296           0 :   inside_function_def++;
    1297           0 :   indentation += indentation_amount;
    1298             : 
    1299           0 :   cmdcopy = copy_command (func->command);
    1300           0 :   if (cmdcopy->type == cm_group)
    1301             :     {
    1302           0 :       func_redirects = cmdcopy->redirects;
    1303           0 :       cmdcopy->redirects = (REDIRECT *)NULL;
    1304             :     }
    1305           0 :   make_command_string_internal (cmdcopy->type == cm_group
    1306           0 :                                         ? cmdcopy->value.Group->command
    1307             :                                         : cmdcopy);
    1308             :   /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
    1309             : 
    1310           0 :   remove_unwind_protect ();
    1311           0 :   indentation -= indentation_amount;
    1312           0 :   inside_function_def--;
    1313             : 
    1314           0 :   if (func_redirects)
    1315             :     { /* { */
    1316           0 :       newline ("} ");
    1317           0 :       print_redirection_list (func_redirects);
    1318           0 :       cmdcopy->redirects = func_redirects;
    1319             :     }
    1320             :   else
    1321           0 :     newline ("}");
    1322             : 
    1323           0 :   dispose_command (cmdcopy);
    1324           0 : }
    1325             : 
    1326             : /* Return the string representation of the named function.
    1327             :    NAME is the name of the function.
    1328             :    COMMAND is the function body.  It should be a GROUP_COM.
    1329             :    flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
    1330             :    flags&FUNC_EXTERNAL means convert from internal to external form
    1331             :   */
    1332             : char *
    1333         143 : named_function_string (name, command, flags)
    1334             :      char *name;
    1335             :      COMMAND *command;
    1336             :      int flags;
    1337             : {
    1338         143 :   char *result;
    1339         143 :   int old_indent, old_amount;
    1340         143 :   COMMAND *cmdcopy;
    1341         143 :   REDIRECT *func_redirects;
    1342             : 
    1343         143 :   old_indent = indentation;
    1344         143 :   old_amount = indentation_amount;
    1345         143 :   command_string_index = was_heredoc = 0;
    1346         143 :   deferred_heredocs = 0;
    1347             : 
    1348         143 :   if (name && *name)
    1349             :     {
    1350           0 :       if (find_reserved_word (name) >= 0)
    1351           0 :         cprintf ("function ");
    1352           0 :       cprintf ("%s ", name);
    1353             :     }
    1354             : 
    1355         143 :   cprintf ("() ");
    1356             : 
    1357         143 :   if ((flags & FUNC_MULTILINE) == 0)
    1358             :     {
    1359           0 :       indentation = 1;
    1360           0 :       indentation_amount = 0;
    1361             :     }
    1362             :   else
    1363             :     {
    1364         143 :       cprintf ("\n");
    1365         143 :       indentation += indentation_amount;
    1366             :     }
    1367             : 
    1368         143 :   inside_function_def++;
    1369             : 
    1370         143 :   cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
    1371             : 
    1372         143 :   cmdcopy = copy_command (command);
    1373             :   /* Take any redirections specified in the function definition (which should
    1374             :      apply to the function as a whole) and save them for printing later. */
    1375         143 :   func_redirects = (REDIRECT *)NULL;
    1376         143 :   if (cmdcopy->type == cm_group)
    1377             :     {
    1378         143 :       func_redirects = cmdcopy->redirects;
    1379         143 :       cmdcopy->redirects = (REDIRECT *)NULL;
    1380             :     }
    1381         286 :   make_command_string_internal (cmdcopy->type == cm_group
    1382         143 :                                         ? cmdcopy->value.Group->command
    1383             :                                         : cmdcopy);
    1384             :   /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
    1385             : 
    1386         143 :   indentation = old_indent;
    1387         143 :   indentation_amount = old_amount;
    1388         143 :   inside_function_def--;
    1389             : 
    1390         143 :   if (func_redirects)
    1391             :     { /* { */
    1392           0 :       newline ("} ");
    1393           0 :       print_redirection_list (func_redirects);
    1394           0 :       cmdcopy->redirects = func_redirects;
    1395             :     }
    1396             :   else
    1397         143 :     newline ("}");
    1398             : 
    1399         143 :   result = the_printed_command;
    1400             : 
    1401         143 :   if ((flags & FUNC_MULTILINE) == 0)
    1402             :     {
    1403             : #if 0
    1404             :       register int i;
    1405             :       for (i = 0; result[i]; i++)
    1406             :         if (result[i] == '\n')
    1407             :           {
    1408             :             strcpy (result + i, result + i + 1);
    1409             :             --i;
    1410             :           }
    1411             : #else
    1412           0 :       if (result[2] == '\n')    /* XXX -- experimental */
    1413           0 :         memmove (result + 2, result + 3, strlen (result) - 2);
    1414             :         
    1415             : #endif
    1416             :     }
    1417             : 
    1418         143 :   dispose_command (cmdcopy);
    1419             : 
    1420         143 :   if (flags & FUNC_EXTERNAL)
    1421         143 :     result = remove_quoted_escapes (result);
    1422             : 
    1423         143 :   return (result);
    1424             : }
    1425             : 
    1426             : static void
    1427        5312 : newline (string)
    1428             :      char *string;
    1429             : {
    1430        5312 :   cprintf ("\n");
    1431        5312 :   indent (indentation);
    1432        5312 :   if (string && *string)
    1433        4492 :     cprintf ("%s", string);
    1434        5312 : }
    1435             : 
    1436             : static char *indentation_string;
    1437             : static int indentation_size;
    1438             : 
    1439             : static void
    1440       14228 : indent (amount)
    1441             :      int amount;
    1442             : {
    1443       14228 :   register int i;
    1444             : 
    1445       21476 :   RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
    1446             : 
    1447       46328 :   for (i = 0; amount > 0; amount--)
    1448       32100 :     indentation_string[i++] = ' ';
    1449       14228 :   indentation_string[i] = '\0';
    1450       14228 :   cprintf ("%s", indentation_string);
    1451       14228 : }
    1452             : 
    1453             : static void
    1454        6205 : semicolon ()
    1455             : {
    1456        6205 :   if (command_string_index > 0 &&
    1457        6205 :        (the_printed_command[command_string_index - 1] == '&' ||
    1458             :         the_printed_command[command_string_index - 1] == '\n'))
    1459             :     return;
    1460        6205 :   cprintf (";");
    1461             : }
    1462             : 
    1463             : /* How to make the string. */
    1464             : static void
    1465             : #if defined (PREFER_STDARG)
    1466   204490201 : cprintf (const char *control, ...)
    1467             : #else
    1468             : cprintf (control, va_alist)
    1469             :      const char *control;
    1470             :      va_dcl
    1471             : #endif
    1472             : {
    1473   204490201 :   register const char *s;
    1474   204490201 :   char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
    1475   204490201 :   int digit_arg, arg_len, c;
    1476   204490201 :   va_list args;
    1477             : 
    1478   204490201 :   SH_VA_START (args, control);
    1479             : 
    1480   204490201 :   arg_len = strlen (control);
    1481   204490201 :   the_printed_command_resize (arg_len + 1);
    1482             : 
    1483   204490201 :   char_arg[1] = '\0';
    1484   204490201 :   s = control;
    1485   658638770 :   while (s && *s)
    1486             :     {
    1487   454148569 :       c = *s++;
    1488   454148569 :       argp = (char *)NULL;
    1489   454148569 :       if (c != '%' || !*s)
    1490             :         {
    1491    51610078 :           char_arg[0] = c;
    1492    51610078 :           argp = char_arg;
    1493    51610078 :           arg_len = 1;
    1494             :         }
    1495             :       else
    1496             :         {
    1497   402538491 :           c = *s++;
    1498   402538491 :           switch (c)
    1499             :             {
    1500           0 :             case '%':
    1501           0 :               char_arg[0] = c;
    1502           0 :               argp = char_arg;
    1503           0 :               arg_len = 1;
    1504           0 :               break;
    1505             : 
    1506   402458339 :             case 's':
    1507   402458339 :               argp = va_arg (args, char *);
    1508   402458339 :               arg_len = strlen (argp);
    1509   402458339 :               break;
    1510             : 
    1511       80152 :             case 'd':
    1512             :               /* Represent an out-of-range file descriptor with an out-of-range
    1513             :                  integer value.  We can do this because the only use of `%d' in
    1514             :                  the calls to cprintf is to output a file descriptor number for
    1515             :                  a redirection. */
    1516       80152 :               digit_arg = va_arg (args, int);
    1517       80152 :               if (digit_arg < 0)
    1518             :                 {
    1519           0 :                   sprintf (intbuf, "%u", (unsigned)-1);
    1520           0 :                   argp = intbuf;
    1521             :                 }
    1522             :               else
    1523       80152 :                 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
    1524       80152 :               arg_len = strlen (argp);
    1525       80152 :               break;
    1526             : 
    1527           0 :             case 'c':
    1528           0 :               char_arg[0] = va_arg (args, int);
    1529           0 :               argp = char_arg;
    1530           0 :               arg_len = 1;
    1531           0 :               break;
    1532             : 
    1533           0 :             default:
    1534           0 :               programming_error (_("cprintf: `%c': invalid format character"), c);
    1535             :               /*NOTREACHED*/
    1536             :             }
    1537             :         }
    1538             : 
    1539   454148569 :       if (argp && arg_len)
    1540             :         {
    1541   367825454 :           the_printed_command_resize (arg_len + 1);
    1542   367825454 :           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
    1543   367825454 :           command_string_index += arg_len;
    1544             :         }
    1545             :     }
    1546             : 
    1547   204490201 :   va_end (args);
    1548             : 
    1549   204490201 :   the_printed_command[command_string_index] = '\0';
    1550   204490201 : }
    1551             : 
    1552             : /* Ensure that there is enough space to stuff LENGTH characters into
    1553             :    THE_PRINTED_COMMAND. */
    1554             : static void
    1555   572315655 : the_printed_command_resize (length)
    1556             :      int length;
    1557             : {
    1558   572315655 :   if (the_printed_command == 0)
    1559             :     {
    1560     9542957 :       the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
    1561     9542957 :       the_printed_command = (char *)xmalloc (the_printed_command_size);
    1562     9542957 :       command_string_index = 0;
    1563             :     }
    1564   562772698 :   else if ((command_string_index + length) >= the_printed_command_size)
    1565             :     {
    1566     5687417 :       int new;
    1567     5687417 :       new = command_string_index + length + 1;
    1568             : 
    1569             :       /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
    1570     5687417 :       new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
    1571     5687417 :       the_printed_command_size = new;
    1572             : 
    1573     5687417 :       the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
    1574             :     }
    1575   572315655 : }
    1576             : 
    1577             : #if defined (HAVE_VPRINTF)
    1578             : /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
    1579             :      also available.'' */
    1580             : 
    1581             : static void
    1582             : #if defined (PREFER_STDARG)
    1583           0 : xprintf (const char *format, ...)
    1584             : #else
    1585             : xprintf (format, va_alist)
    1586             :      const char *format;
    1587             :      va_dcl
    1588             : #endif
    1589             : {
    1590           0 :   va_list args;
    1591             : 
    1592           0 :   SH_VA_START (args, format);
    1593             : 
    1594           0 :   vfprintf (stdout, format, args);
    1595           0 :   va_end (args);
    1596           0 : }
    1597             : 
    1598             : #else
    1599             : 
    1600             : static void
    1601             : xprintf (format, arg1, arg2, arg3, arg4, arg5)
    1602             :      const char *format;
    1603             : {
    1604             :   printf (format, arg1, arg2, arg3, arg4, arg5);
    1605             : }
    1606             : 
    1607             : #endif /* !HAVE_VPRINTF */

Generated by: LCOV version 1.14.0.6.4058