1/* print_command -- A way to make readable commands from a command tree. */
2
3/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
4
5This file is part of GNU Bash, the Bourne Again SHell.
6
7Bash is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License along
18with Bash; see the file COPYING.  If not, write to the Free Software
19Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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
45#include "shmbutil.h"
46
47#include "builtins/common.h"
48
49#if !HAVE_DECL_PRINTF
50extern int printf __P((const char *, ...));	/* Yuck.  Double yuck. */
51#endif
52
53extern int indirection_level;
54
55static int indentation;
56static int indentation_amount = 4;
57
58#if defined (PREFER_STDARG)
59typedef void PFUNC __P((const char *, ...));
60
61static void cprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
62static void xprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
63#else
64#define PFUNC VFunction
65static void cprintf ();
66static void xprintf ();
67#endif
68
69static void reset_locals __P((void));
70static void newline __P((char *));
71static void indent __P((int));
72static void semicolon __P((void));
73static void the_printed_command_resize __P((int));
74
75static void make_command_string_internal __P((COMMAND *));
76static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
77static void command_print_word_list __P((WORD_LIST *, char *));
78static void print_case_clauses __P((PATTERN_LIST *));
79static void print_redirection_list __P((REDIRECT *));
80static void print_redirection __P((REDIRECT *));
81
82static void print_for_command __P((FOR_COM *));
83#if defined (ARITH_FOR_COMMAND)
84static void print_arith_for_command __P((ARITH_FOR_COM *));
85#endif
86#if defined (SELECT_COMMAND)
87static void print_select_command __P((SELECT_COM *));
88#endif
89static void print_group_command __P((GROUP_COM *));
90static void print_case_command __P((CASE_COM *));
91static void print_while_command __P((WHILE_COM *));
92static void print_until_command __P((WHILE_COM *));
93static void print_until_or_while __P((WHILE_COM *, char *));
94static void print_if_command __P((IF_COM *));
95#if defined (COND_COMMAND)
96static void print_cond_node __P((COND_COM *));
97#endif
98static void print_function_def __P((FUNCTION_DEF *));
99
100#define PRINTED_COMMAND_INITIAL_SIZE 64
101#define PRINTED_COMMAND_GROW_SIZE 128
102
103char *the_printed_command = (char *)NULL;
104int the_printed_command_size = 0;
105int command_string_index = 0;
106
107/* Non-zero means the stuff being printed is inside of a function def. */
108static int inside_function_def;
109static int skip_this_indent;
110static int was_heredoc;
111
112/* The depth of the group commands that we are currently printing.  This
113   includes the group command that is a function body. */
114static int group_command_nesting;
115
116/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
117static char indirection_string[100];
118
119/* Print COMMAND (a command tree) on standard output. */
120void
121print_command (command)
122     COMMAND *command;
123{
124  command_string_index = 0;
125  printf ("%s", make_command_string (command));
126}
127
128/* Make a string which is the printed representation of the command
129   tree in COMMAND.  We return this string.  However, the string is
130   not consed, so you have to do that yourself if you want it to
131   remain around. */
132char *
133make_command_string (command)
134     COMMAND *command;
135{
136  command_string_index = was_heredoc = 0;
137  make_command_string_internal (command);
138  return (the_printed_command);
139}
140
141/* The internal function.  This is the real workhorse. */
142static void
143make_command_string_internal (command)
144     COMMAND *command;
145{
146  if (command == 0)
147    cprintf ("");
148  else
149    {
150      if (skip_this_indent)
151	skip_this_indent--;
152      else
153	indent (indentation);
154
155      if (command->flags & CMD_TIME_PIPELINE)
156	{
157	  cprintf ("time ");
158	  if (command->flags & CMD_TIME_POSIX)
159	    cprintf ("-p ");
160	}
161
162      if (command->flags & CMD_INVERT_RETURN)
163	cprintf ("! ");
164
165      switch (command->type)
166	{
167	case cm_for:
168	  print_for_command (command->value.For);
169	  break;
170
171#if defined (ARITH_FOR_COMMAND)
172	case cm_arith_for:
173	  print_arith_for_command (command->value.ArithFor);
174	  break;
175#endif
176
177#if defined (SELECT_COMMAND)
178	case cm_select:
179	  print_select_command (command->value.Select);
180	  break;
181#endif
182
183	case cm_case:
184	  print_case_command (command->value.Case);
185	  break;
186
187	case cm_while:
188	  print_while_command (command->value.While);
189	  break;
190
191	case cm_until:
192	  print_until_command (command->value.While);
193	  break;
194
195	case cm_if:
196	  print_if_command (command->value.If);
197	  break;
198
199#if defined (DPAREN_ARITHMETIC)
200	case cm_arith:
201	  print_arith_command (command->value.Arith->exp);
202	  break;
203#endif
204
205#if defined (COND_COMMAND)
206	case cm_cond:
207	  print_cond_command (command->value.Cond);
208	  break;
209#endif
210
211	case cm_simple:
212	  print_simple_command (command->value.Simple);
213	  break;
214
215	case cm_connection:
216
217	  skip_this_indent++;
218	  make_command_string_internal (command->value.Connection->first);
219
220	  switch (command->value.Connection->connector)
221	    {
222	    case '&':
223	    case '|':
224	      {
225		char c = command->value.Connection->connector;
226		cprintf (" %c", c);
227		if (c != '&' || command->value.Connection->second)
228		  {
229		    cprintf (" ");
230		    skip_this_indent++;
231		  }
232	      }
233	      break;
234
235	    case AND_AND:
236	      cprintf (" && ");
237	      if (command->value.Connection->second)
238		skip_this_indent++;
239	      break;
240
241	    case OR_OR:
242	      cprintf (" || ");
243	      if (command->value.Connection->second)
244		skip_this_indent++;
245	      break;
246
247	    case ';':
248	      if (was_heredoc == 0)
249		cprintf (";");
250	      else
251		was_heredoc = 0;
252
253	      if (inside_function_def)
254		cprintf ("\n");
255	      else
256		{
257		  cprintf (" ");
258		  if (command->value.Connection->second)
259		    skip_this_indent++;
260		}
261	      break;
262
263	    default:
264	      cprintf (_("print_command: bad connector `%d'"),
265		       command->value.Connection->connector);
266	      break;
267	    }
268
269	  make_command_string_internal (command->value.Connection->second);
270	  break;
271
272	case cm_function_def:
273	  print_function_def (command->value.Function_def);
274	  break;
275
276	case cm_group:
277	  print_group_command (command->value.Group);
278	  break;
279
280	case cm_subshell:
281	  cprintf ("( ");
282	  skip_this_indent++;
283	  make_command_string_internal (command->value.Subshell->command);
284	  cprintf (" )");
285	  break;
286
287	default:
288	  command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
289	  break;
290	}
291
292
293      if (command->redirects)
294	{
295	  cprintf (" ");
296	  print_redirection_list (command->redirects);
297	}
298    }
299}
300
301static void
302_print_word_list (list, separator, pfunc)
303     WORD_LIST *list;
304     char *separator;
305     PFUNC *pfunc;
306{
307  WORD_LIST *w;
308
309  for (w = list; w; w = w->next)
310    (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
311}
312
313void
314print_word_list (list, separator)
315     WORD_LIST *list;
316     char *separator;
317{
318  _print_word_list (list, separator, xprintf);
319}
320
321/* Return a string denoting what our indirection level is. */
322
323char *
324indirection_level_string ()
325{
326  register int i, j;
327  char *ps4;
328  char ps4_firstc[MB_LEN_MAX+1];
329  int ps4_firstc_len, ps4_len;
330
331  indirection_string[0] = '\0';
332  ps4 = get_string_value ("PS4");
333
334  if (ps4 == 0 || *ps4 == '\0')
335    return (indirection_string);
336
337  change_flag ('x', FLAG_OFF);
338  ps4 = decode_prompt_string (ps4);
339  change_flag ('x', FLAG_ON);
340
341  if (ps4 == 0 || *ps4 == '\0')
342    return (indirection_string);
343
344#if defined (HANDLE_MULTIBYTE)
345  ps4_len = strnlen (ps4, MB_CUR_MAX);
346  ps4_firstc_len = MBLEN (ps4, ps4_len);
347  if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
348    {
349      ps4_firstc[0] = ps4[0];
350      ps4_firstc[ps4_firstc_len = 1] = '\0';
351    }
352  else
353    memcpy (ps4_firstc, ps4, ps4_firstc_len);
354#else
355  ps4_firstc[0] = ps4[0];
356  ps4_firstc[ps4_firstc_len = 1] = '\0';
357#endif
358
359  for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
360    {
361      if (ps4_firstc_len == 1)
362	indirection_string[i] = ps4_firstc[0];
363      else
364	memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
365    }
366
367  for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
368    indirection_string[i] = ps4[j];
369
370  indirection_string[i] = '\0';
371  free (ps4);
372  return (indirection_string);
373}
374
375void
376xtrace_print_assignment (name, value, assign_list, xflags)
377     char *name, *value;
378     int assign_list, xflags;
379{
380  char *nval;
381
382  if (xflags)
383    fprintf (stderr, "%s", indirection_level_string ());
384
385  /* VALUE should not be NULL when this is called. */
386  if (*value == '\0' || assign_list)
387    nval = value;
388  else if (sh_contains_shell_metas (value))
389    nval = sh_single_quote (value);
390  else if (ansic_shouldquote (value))
391    nval = ansic_quote (value, 0, (int *)0);
392  else
393    nval = value;
394
395  if (assign_list)
396    fprintf (stderr, "%s=(%s)\n", name, nval);
397  else
398    fprintf (stderr, "%s=%s\n", name, nval);
399
400  if (nval != value)
401    FREE (nval);
402
403  fflush (stderr);
404}
405
406/* A function to print the words of a simple command when set -x is on. */
407void
408xtrace_print_word_list (list, xtflags)
409     WORD_LIST *list;
410     int xtflags;
411{
412  WORD_LIST *w;
413  char *t, *x;
414
415  if (xtflags)
416    fprintf (stderr, "%s", indirection_level_string ());
417
418  for (w = list; w; w = w->next)
419    {
420      t = w->word->word;
421      if (t == 0 || *t == '\0')
422	fprintf (stderr, "''%s", w->next ? " " : "");
423      else if (sh_contains_shell_metas (t))
424	{
425	  x = sh_single_quote (t);
426	  fprintf (stderr, "%s%s", x, w->next ? " " : "");
427	  free (x);
428	}
429      else if (ansic_shouldquote (t))
430	{
431	  x = ansic_quote (t, 0, (int *)0);
432	  fprintf (stderr, "%s%s", x, w->next ? " " : "");
433	  free (x);
434	}
435      else
436	fprintf (stderr, "%s%s", t, w->next ? " " : "");
437    }
438  fprintf (stderr, "\n");
439}
440
441static void
442command_print_word_list (list, separator)
443     WORD_LIST *list;
444     char *separator;
445{
446  _print_word_list (list, separator, cprintf);
447}
448
449void
450print_for_command_head (for_command)
451     FOR_COM *for_command;
452{
453  cprintf ("for %s in ", for_command->name->word);
454  command_print_word_list (for_command->map_list, " ");
455}
456
457void
458xtrace_print_for_command_head (for_command)
459     FOR_COM *for_command;
460{
461  fprintf (stderr, "%s", indirection_level_string ());
462  fprintf (stderr, "for %s in ", for_command->name->word);
463  xtrace_print_word_list (for_command->map_list, 0);
464}
465
466static void
467print_for_command (for_command)
468     FOR_COM *for_command;
469{
470  print_for_command_head (for_command);
471
472  cprintf (";");
473  newline ("do\n");
474  indentation += indentation_amount;
475  make_command_string_internal (for_command->action);
476  semicolon ();
477  indentation -= indentation_amount;
478  newline ("done");
479}
480
481#if defined (ARITH_FOR_COMMAND)
482static void
483print_arith_for_command (arith_for_command)
484     ARITH_FOR_COM *arith_for_command;
485{
486  cprintf ("for ((");
487  command_print_word_list (arith_for_command->init, " ");
488  cprintf ("; ");
489  command_print_word_list (arith_for_command->test, " ");
490  cprintf ("; ");
491  command_print_word_list (arith_for_command->step, " ");
492  cprintf ("))");
493  newline ("do\n");
494  indentation += indentation_amount;
495  make_command_string_internal (arith_for_command->action);
496  semicolon ();
497  indentation -= indentation_amount;
498  newline ("done");
499}
500#endif /* ARITH_FOR_COMMAND */
501
502#if defined (SELECT_COMMAND)
503void
504print_select_command_head (select_command)
505     SELECT_COM *select_command;
506{
507  cprintf ("select %s in ", select_command->name->word);
508  command_print_word_list (select_command->map_list, " ");
509}
510
511void
512xtrace_print_select_command_head (select_command)
513     SELECT_COM *select_command;
514{
515  fprintf (stderr, "%s", indirection_level_string ());
516  fprintf (stderr, "select %s in ", select_command->name->word);
517  xtrace_print_word_list (select_command->map_list, 0);
518}
519
520static void
521print_select_command (select_command)
522     SELECT_COM *select_command;
523{
524  print_select_command_head (select_command);
525
526  cprintf (";");
527  newline ("do\n");
528  indentation += indentation_amount;
529  make_command_string_internal (select_command->action);
530  semicolon ();
531  indentation -= indentation_amount;
532  newline ("done");
533}
534#endif /* SELECT_COMMAND */
535
536static void
537print_group_command (group_command)
538     GROUP_COM *group_command;
539{
540  group_command_nesting++;
541  cprintf ("{ ");
542
543  if (inside_function_def == 0)
544    skip_this_indent++;
545  else
546    {
547      /* This is a group command { ... } inside of a function
548	 definition, and should be printed as a multiline group
549	 command, using the current indentation. */
550      cprintf ("\n");
551      indentation += indentation_amount;
552    }
553
554  make_command_string_internal (group_command->command);
555
556  if (inside_function_def)
557    {
558      cprintf ("\n");
559      indentation -= indentation_amount;
560      indent (indentation);
561    }
562  else
563    {
564      semicolon ();
565      cprintf (" ");
566    }
567
568  cprintf ("}");
569
570  group_command_nesting--;
571}
572
573void
574print_case_command_head (case_command)
575     CASE_COM *case_command;
576{
577  cprintf ("case %s in ", case_command->word->word);
578}
579
580void
581xtrace_print_case_command_head (case_command)
582     CASE_COM *case_command;
583{
584  fprintf (stderr, "%s", indirection_level_string ());
585  fprintf (stderr, "case %s in\n", case_command->word->word);
586}
587
588static void
589print_case_command (case_command)
590     CASE_COM *case_command;
591{
592  print_case_command_head (case_command);
593
594  if (case_command->clauses)
595    print_case_clauses (case_command->clauses);
596  newline ("esac");
597}
598
599static void
600print_case_clauses (clauses)
601     PATTERN_LIST *clauses;
602{
603  indentation += indentation_amount;
604  while (clauses)
605    {
606      newline ("");
607      command_print_word_list (clauses->patterns, " | ");
608      cprintf (")\n");
609      indentation += indentation_amount;
610      make_command_string_internal (clauses->action);
611      indentation -= indentation_amount;
612      newline (";;");
613      clauses = clauses->next;
614    }
615  indentation -= indentation_amount;
616}
617
618static void
619print_while_command (while_command)
620     WHILE_COM *while_command;
621{
622  print_until_or_while (while_command, "while");
623}
624
625static void
626print_until_command (while_command)
627     WHILE_COM *while_command;
628{
629  print_until_or_while (while_command, "until");
630}
631
632static void
633print_until_or_while (while_command, which)
634     WHILE_COM *while_command;
635     char *which;
636{
637  cprintf ("%s ", which);
638  skip_this_indent++;
639  make_command_string_internal (while_command->test);
640  semicolon ();
641  cprintf (" do\n");	/* was newline ("do\n"); */
642  indentation += indentation_amount;
643  make_command_string_internal (while_command->action);
644  indentation -= indentation_amount;
645  semicolon ();
646  newline ("done");
647}
648
649static void
650print_if_command (if_command)
651     IF_COM *if_command;
652{
653  cprintf ("if ");
654  skip_this_indent++;
655  make_command_string_internal (if_command->test);
656  semicolon ();
657  cprintf (" then\n");
658  indentation += indentation_amount;
659  make_command_string_internal (if_command->true_case);
660  indentation -= indentation_amount;
661
662  if (if_command->false_case)
663    {
664      semicolon ();
665      newline ("else\n");
666      indentation += indentation_amount;
667      make_command_string_internal (if_command->false_case);
668      indentation -= indentation_amount;
669    }
670  semicolon ();
671  newline ("fi");
672}
673
674#if defined (DPAREN_ARITHMETIC)
675void
676print_arith_command (arith_cmd_list)
677     WORD_LIST *arith_cmd_list;
678{
679  cprintf ("((");
680  command_print_word_list (arith_cmd_list, " ");
681  cprintf ("))");
682}
683#endif
684
685#if defined (COND_COMMAND)
686static void
687print_cond_node (cond)
688     COND_COM *cond;
689{
690  if (cond->flags & CMD_INVERT_RETURN)
691    cprintf ("! ");
692
693  if (cond->type == COND_EXPR)
694    {
695      cprintf ("( ");
696      print_cond_node (cond->left);
697      cprintf (" )");
698    }
699  else if (cond->type == COND_AND)
700    {
701      print_cond_node (cond->left);
702      cprintf (" && ");
703      print_cond_node (cond->right);
704    }
705  else if (cond->type == COND_OR)
706    {
707      print_cond_node (cond->left);
708      cprintf (" || ");
709      print_cond_node (cond->right);
710    }
711  else if (cond->type == COND_UNARY)
712    {
713      cprintf ("%s", cond->op->word);
714      cprintf (" ");
715      print_cond_node (cond->left);
716    }
717  else if (cond->type == COND_BINARY)
718    {
719      print_cond_node (cond->left);
720      cprintf (" ");
721      cprintf ("%s", cond->op->word);
722      cprintf (" ");
723      print_cond_node (cond->right);
724    }
725  else if (cond->type == COND_TERM)
726    {
727      cprintf ("%s", cond->op->word);		/* need to add quoting here */
728    }
729}
730
731void
732print_cond_command (cond)
733     COND_COM *cond;
734{
735  cprintf ("[[ ");
736  print_cond_node (cond);
737  cprintf (" ]]");
738}
739
740#ifdef DEBUG
741void
742debug_print_cond_command (cond)
743     COND_COM *cond;
744{
745  fprintf (stderr, "DEBUG: ");
746  command_string_index = 0;
747  print_cond_command (cond);
748  fprintf (stderr, "%s\n", the_printed_command);
749}
750#endif
751
752void
753xtrace_print_cond_term (type, invert, op, arg1, arg2)
754     int type, invert;
755     WORD_DESC *op;
756     char *arg1, *arg2;
757{
758  command_string_index = 0;
759  fprintf (stderr, "%s", indirection_level_string ());
760  fprintf (stderr, "[[ ");
761  if (invert)
762    fprintf (stderr, "! ");
763
764  if (type == COND_UNARY)
765    {
766      fprintf (stderr, "%s ", op->word);
767      fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
768    }
769  else if (type == COND_BINARY)
770    {
771      fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
772      fprintf (stderr, " %s ", op->word);
773      fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
774    }
775
776  fprintf (stderr, " ]]\n");
777}
778#endif /* COND_COMMAND */
779
780#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
781/* A function to print the words of an arithmetic command when set -x is on. */
782void
783xtrace_print_arith_cmd (list)
784     WORD_LIST *list;
785{
786  WORD_LIST *w;
787
788  fprintf (stderr, "%s", indirection_level_string ());
789  fprintf (stderr, "(( ");
790  for (w = list; w; w = w->next)
791    fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
792  fprintf (stderr, " ))\n");
793}
794#endif
795
796void
797print_simple_command (simple_command)
798     SIMPLE_COM *simple_command;
799{
800  command_print_word_list (simple_command->words, " ");
801
802  if (simple_command->redirects)
803    {
804      cprintf (" ");
805      print_redirection_list (simple_command->redirects);
806    }
807}
808
809static void
810print_redirection_list (redirects)
811     REDIRECT *redirects;
812{
813  REDIRECT *heredocs, *hdtail, *newredir;
814
815  heredocs = (REDIRECT *)NULL;
816  hdtail = heredocs;
817
818  was_heredoc = 0;
819  while (redirects)
820    {
821      /* Defer printing the here documents until we've printed the
822	 rest of the redirections. */
823      if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
824	{
825	  newredir = copy_redirect (redirects);
826	  newredir->next = (REDIRECT *)NULL;
827	  if (heredocs)
828	    {
829	      hdtail->next = newredir;
830	      hdtail = newredir;
831	    }
832	  else
833	    hdtail = heredocs = newredir;
834	}
835      else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
836	{
837	  /* Temporarily translate it as the execution code does. */
838	  redirects->instruction = r_err_and_out;
839	  print_redirection (redirects);
840	  redirects->instruction = r_duplicating_output_word;
841	}
842      else
843	print_redirection (redirects);
844
845      redirects = redirects->next;
846      if (redirects)
847	cprintf (" ");
848    }
849
850  /* Now that we've printed all the other redirections (on one line),
851     print the here documents. */
852  if (heredocs)
853    {
854      cprintf (" ");
855      for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
856	{
857	  print_redirection (hdtail);
858	  cprintf ("\n");
859	}
860      dispose_redirects (heredocs);
861      was_heredoc = 1;
862    }
863}
864
865static void
866print_redirection (redirect)
867     REDIRECT *redirect;
868{
869  int kill_leading, redirector, redir_fd;
870  WORD_DESC *redirectee;
871
872  kill_leading = 0;
873  redirectee = redirect->redirectee.filename;
874  redirector = redirect->redirector;
875  redir_fd = redirect->redirectee.dest;
876
877  switch (redirect->instruction)
878    {
879    case r_output_direction:
880      if (redirector != 1)
881	cprintf ("%d", redirector);
882      cprintf ("> %s", redirectee->word);
883      break;
884
885    case r_input_direction:
886      if (redirector != 0)
887	cprintf ("%d", redirector);
888      cprintf ("< %s", redirectee->word);
889      break;
890
891    case r_inputa_direction:	/* Redirection created by the shell. */
892      cprintf ("&");
893      break;
894
895    case r_appending_to:
896      if (redirector != 1)
897	cprintf ("%d", redirector);
898      cprintf (">> %s", redirectee->word);
899      break;
900
901    case r_deblank_reading_until:
902      kill_leading++;
903      /* ... */
904    case r_reading_until:
905      if (redirector != 0)
906	cprintf ("%d", redirector);
907      /* If the here document delimiter is quoted, single-quote it. */
908      if (redirect->redirectee.filename->flags & W_QUOTED)
909	{
910	  char *x;
911	  x = sh_single_quote (redirect->here_doc_eof);
912	  cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
913	  free (x);
914	}
915      else
916	cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
917      cprintf ("%s%s",
918	       redirect->redirectee.filename->word, redirect->here_doc_eof);
919      break;
920
921    case r_reading_string:
922      if (redirector != 0)
923	cprintf ("%d", redirector);
924      if (ansic_shouldquote (redirect->redirectee.filename->word))
925	{
926	  char *x;
927	  x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
928	  cprintf ("<<< %s", x);
929	  free (x);
930	}
931      else
932	cprintf ("<<< %s", redirect->redirectee.filename->word);
933      break;
934
935    case r_duplicating_input:
936      cprintf ("%d<&%d", redirector, redir_fd);
937      break;
938
939    case r_duplicating_output:
940      cprintf ("%d>&%d", redirector, redir_fd);
941      break;
942
943    case r_duplicating_input_word:
944      cprintf ("%d<&%s", redirector, redirectee->word);
945      break;
946
947    case r_duplicating_output_word:
948      cprintf ("%d>&%s", redirector, redirectee->word);
949      break;
950
951    case r_move_input:
952      cprintf ("%d<&%d-", redirector, redir_fd);
953      break;
954
955    case r_move_output:
956      cprintf ("%d>&%d-", redirector, redir_fd);
957      break;
958
959    case r_move_input_word:
960      cprintf ("%d<&%s-", redirector, redirectee->word);
961      break;
962
963    case r_move_output_word:
964      cprintf ("%d>&%s-", redirector, redirectee->word);
965      break;
966
967    case r_close_this:
968      cprintf ("%d>&-", redirector);
969      break;
970
971    case r_err_and_out:
972      cprintf (">&%s", redirectee->word);
973      break;
974
975    case r_input_output:
976      if (redirector != 1)
977	cprintf ("%d", redirector);
978      cprintf ("<> %s", redirectee->word);
979      break;
980
981    case r_output_force:
982      if (redirector != 1)
983	cprintf ("%d", redirector);
984      cprintf (">|%s", redirectee->word);
985      break;
986    }
987}
988
989static void
990reset_locals ()
991{
992  inside_function_def = 0;
993  indentation = 0;
994}
995
996static void
997print_function_def (func)
998     FUNCTION_DEF *func;
999{
1000  COMMAND *cmdcopy;
1001  REDIRECT *func_redirects;
1002
1003  func_redirects = NULL;
1004  cprintf ("function %s () \n", func->name->word);
1005  add_unwind_protect (reset_locals, 0);
1006
1007  indent (indentation);
1008  cprintf ("{ \n");
1009
1010  inside_function_def++;
1011  indentation += indentation_amount;
1012
1013  cmdcopy = copy_command (func->command);
1014  if (cmdcopy->type == cm_group)
1015    {
1016      func_redirects = cmdcopy->redirects;
1017      cmdcopy->redirects = (REDIRECT *)NULL;
1018    }
1019  make_command_string_internal (cmdcopy->type == cm_group
1020					? cmdcopy->value.Group->command
1021					: cmdcopy);
1022
1023  remove_unwind_protect ();
1024  indentation -= indentation_amount;
1025  inside_function_def--;
1026
1027  if (func_redirects)
1028    { /* { */
1029      newline ("} ");
1030      print_redirection_list (func_redirects);
1031      cmdcopy->redirects = func_redirects;
1032    }
1033  else
1034    newline ("}");
1035
1036  dispose_command (cmdcopy);
1037}
1038
1039/* Return the string representation of the named function.
1040   NAME is the name of the function.
1041   COMMAND is the function body.  It should be a GROUP_COM.
1042   MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
1043  */
1044char *
1045named_function_string (name, command, multi_line)
1046     char *name;
1047     COMMAND *command;
1048     int multi_line;
1049{
1050  char *result;
1051  int old_indent, old_amount;
1052  COMMAND *cmdcopy;
1053  REDIRECT *func_redirects;
1054
1055  old_indent = indentation;
1056  old_amount = indentation_amount;
1057  command_string_index = was_heredoc = 0;
1058
1059  if (name && *name)
1060    cprintf ("%s ", name);
1061
1062  cprintf ("() ");
1063
1064  if (multi_line == 0)
1065    {
1066      indentation = 1;
1067      indentation_amount = 0;
1068    }
1069  else
1070    {
1071      cprintf ("\n");
1072      indentation += indentation_amount;
1073    }
1074
1075  inside_function_def++;
1076
1077  cprintf (multi_line ? "{ \n" : "{ ");
1078
1079  cmdcopy = copy_command (command);
1080  /* Take any redirections specified in the function definition (which should
1081     apply to the function as a whole) and save them for printing later. */
1082  func_redirects = (REDIRECT *)NULL;
1083  if (cmdcopy->type == cm_group)
1084    {
1085      func_redirects = cmdcopy->redirects;
1086      cmdcopy->redirects = (REDIRECT *)NULL;
1087    }
1088  make_command_string_internal (cmdcopy->type == cm_group
1089					? cmdcopy->value.Group->command
1090					: cmdcopy);
1091
1092  indentation = old_indent;
1093  indentation_amount = old_amount;
1094  inside_function_def--;
1095
1096  if (func_redirects)
1097    { /* { */
1098      newline ("} ");
1099      print_redirection_list (func_redirects);
1100      cmdcopy->redirects = func_redirects;
1101    }
1102  else
1103    newline ("}");
1104
1105  result = the_printed_command;
1106
1107  if (!multi_line)
1108    {
1109#if 0
1110      register int i;
1111      for (i = 0; result[i]; i++)
1112	if (result[i] == '\n')
1113	  {
1114	    strcpy (result + i, result + i + 1);
1115	    --i;
1116	  }
1117#else
1118      if (result[2] == '\n')	/* XXX -- experimental */
1119	memmove(result + 2, result + 3, strlen(result+3)+1);
1120#endif
1121    }
1122
1123  dispose_command (cmdcopy);
1124
1125  return (result);
1126}
1127
1128static void
1129newline (string)
1130     char *string;
1131{
1132  cprintf ("\n");
1133  indent (indentation);
1134  if (string && *string)
1135    cprintf ("%s", string);
1136}
1137
1138static char *indentation_string;
1139static int indentation_size;
1140
1141static void
1142indent (amount)
1143     int amount;
1144{
1145  register int i;
1146
1147  RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1148
1149  for (i = 0; amount > 0; amount--)
1150    indentation_string[i++] = ' ';
1151  indentation_string[i] = '\0';
1152  cprintf (indentation_string);
1153}
1154
1155static void
1156semicolon ()
1157{
1158  if (command_string_index > 0 &&
1159       (the_printed_command[command_string_index - 1] == '&' ||
1160        the_printed_command[command_string_index - 1] == '\n'))
1161    return;
1162  cprintf (";");
1163}
1164
1165/* How to make the string. */
1166static void
1167#if defined (PREFER_STDARG)
1168cprintf (const char *control, ...)
1169#else
1170cprintf (control, va_alist)
1171     const char *control;
1172     va_dcl
1173#endif
1174{
1175  register const char *s;
1176  char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
1177  int digit_arg, arg_len, c;
1178  va_list args;
1179
1180  SH_VA_START (args, control);
1181
1182  arg_len = strlen (control);
1183  the_printed_command_resize (arg_len + 1);
1184
1185  char_arg[1] = '\0';
1186  s = control;
1187  while (s && *s)
1188    {
1189      c = *s++;
1190      argp = (char *)NULL;
1191      if (c != '%' || !*s)
1192	{
1193	  char_arg[0] = c;
1194	  argp = char_arg;
1195	  arg_len = 1;
1196	}
1197      else
1198	{
1199	  c = *s++;
1200	  switch (c)
1201	    {
1202	    case '%':
1203	      char_arg[0] = c;
1204	      argp = char_arg;
1205	      arg_len = 1;
1206	      break;
1207
1208	    case 's':
1209	      argp = va_arg (args, char *);
1210	      arg_len = strlen (argp);
1211	      break;
1212
1213	    case 'd':
1214	      /* Represent an out-of-range file descriptor with an out-of-range
1215		 integer value.  We can do this because the only use of `%d' in
1216		 the calls to cprintf is to output a file descriptor number for
1217		 a redirection. */
1218	      digit_arg = va_arg (args, int);
1219	      if (digit_arg < 0)
1220		{
1221		  sprintf (intbuf, "%u", (unsigned)-1);
1222		  argp = intbuf;
1223		}
1224	      else
1225	        argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1226	      arg_len = strlen (argp);
1227	      break;
1228
1229	    case 'c':
1230	      char_arg[0] = va_arg (args, int);
1231	      argp = char_arg;
1232	      arg_len = 1;
1233	      break;
1234
1235	    default:
1236	      programming_error (_("cprintf: `%c': invalid format character"), c);
1237	      /*NOTREACHED*/
1238	    }
1239	}
1240
1241      if (argp && arg_len)
1242	{
1243	  the_printed_command_resize (arg_len + 1);
1244	  FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1245	  command_string_index += arg_len;
1246	}
1247    }
1248
1249  the_printed_command[command_string_index] = '\0';
1250}
1251
1252/* Ensure that there is enough space to stuff LENGTH characters into
1253   THE_PRINTED_COMMAND. */
1254static void
1255the_printed_command_resize (length)
1256     int length;
1257{
1258  if (the_printed_command == 0)
1259    {
1260      the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1261      the_printed_command = (char *)xmalloc (the_printed_command_size);
1262      command_string_index = 0;
1263    }
1264  else if ((command_string_index + length) >= the_printed_command_size)
1265    {
1266      int new;
1267      new = command_string_index + length + 1;
1268
1269      /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1270      new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1271      the_printed_command_size = new;
1272
1273      the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
1274    }
1275}
1276
1277#if defined (HAVE_VPRINTF)
1278/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1279     also available.'' */
1280
1281static void
1282#if defined (PREFER_STDARG)
1283xprintf (const char *format, ...)
1284#else
1285xprintf (format, va_alist)
1286     const char *format;
1287     va_dcl
1288#endif
1289{
1290  va_list args;
1291
1292  SH_VA_START (args, format);
1293
1294  vfprintf (stdout, format, args);
1295  va_end (args);
1296}
1297
1298#else
1299
1300static void
1301xprintf (format, arg1, arg2, arg3, arg4, arg5)
1302     const char *format;
1303{
1304  printf (format, arg1, arg2, arg3, arg4, arg5);
1305}
1306
1307#endif /* !HAVE_VPRINTF */
1308