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