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