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