Bash-4.2 patch 40
[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           PRINT_DEFERRED_HEREDOCS ("");
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   PRINT_DEFERRED_HEREDOCS ("");
597   semicolon ();
598   indentation -= indentation_amount;
599   newline ("done");
600 }
601 #endif /* ARITH_FOR_COMMAND */
602
603 #if defined (SELECT_COMMAND)
604 void
605 print_select_command_head (select_command)
606      SELECT_COM *select_command;
607 {
608   cprintf ("select %s in ", select_command->name->word);
609   command_print_word_list (select_command->map_list, " ");
610 }
611
612 void
613 xtrace_print_select_command_head (select_command)
614      SELECT_COM *select_command;
615 {
616   CHECK_XTRACE_FP;
617   fprintf (xtrace_fp, "%s", indirection_level_string ());
618   fprintf (xtrace_fp, "select %s in ", select_command->name->word);
619   xtrace_print_word_list (select_command->map_list, 0);
620 }
621
622 static void
623 print_select_command (select_command)
624      SELECT_COM *select_command;
625 {
626   print_select_command_head (select_command);
627
628   cprintf (";");
629   newline ("do\n");
630   indentation += indentation_amount;
631   make_command_string_internal (select_command->action);
632   PRINT_DEFERRED_HEREDOCS ("");
633   semicolon ();
634   indentation -= indentation_amount;
635   newline ("done");
636 }
637 #endif /* SELECT_COMMAND */
638
639 static void
640 print_group_command (group_command)
641      GROUP_COM *group_command;
642 {
643   group_command_nesting++;
644   cprintf ("{ ");
645
646   if (inside_function_def == 0)
647     skip_this_indent++;
648   else
649     {
650       /* This is a group command { ... } inside of a function
651          definition, and should be printed as a multiline group
652          command, using the current indentation. */
653       cprintf ("\n");
654       indentation += indentation_amount;
655     }
656
657   make_command_string_internal (group_command->command);
658   PRINT_DEFERRED_HEREDOCS ("");
659
660   if (inside_function_def)
661     {
662       cprintf ("\n");
663       indentation -= indentation_amount;
664       indent (indentation);
665     }
666   else
667     {
668       semicolon ();
669       cprintf (" ");
670     }
671
672   cprintf ("}");
673
674   group_command_nesting--;
675 }
676
677 void
678 print_case_command_head (case_command)
679      CASE_COM *case_command;
680 {
681   cprintf ("case %s in ", case_command->word->word);
682 }
683
684 void
685 xtrace_print_case_command_head (case_command)
686      CASE_COM *case_command;
687 {
688   CHECK_XTRACE_FP;
689   fprintf (xtrace_fp, "%s", indirection_level_string ());
690   fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
691 }
692
693 static void
694 print_case_command (case_command)
695      CASE_COM *case_command;
696 {
697   print_case_command_head (case_command);
698
699   if (case_command->clauses)
700     print_case_clauses (case_command->clauses);
701   newline ("esac");
702 }
703
704 static void
705 print_case_clauses (clauses)
706      PATTERN_LIST *clauses;
707 {
708   indentation += indentation_amount;
709   while (clauses)
710     {
711       newline ("");
712       command_print_word_list (clauses->patterns, " | ");
713       cprintf (")\n");
714       indentation += indentation_amount;
715       make_command_string_internal (clauses->action);
716       indentation -= indentation_amount;
717       PRINT_DEFERRED_HEREDOCS ("");
718       if (clauses->flags & CASEPAT_FALLTHROUGH)
719         newline (";&");
720       else if (clauses->flags & CASEPAT_TESTNEXT)
721         newline (";;&");
722       else
723         newline (";;");
724       clauses = clauses->next;
725     }
726   indentation -= indentation_amount;
727 }
728
729 static void
730 print_while_command (while_command)
731      WHILE_COM *while_command;
732 {
733   print_until_or_while (while_command, "while");
734 }
735
736 static void
737 print_until_command (while_command)
738      WHILE_COM *while_command;
739 {
740   print_until_or_while (while_command, "until");
741 }
742
743 static void
744 print_until_or_while (while_command, which)
745      WHILE_COM *while_command;
746      char *which;
747 {
748   cprintf ("%s ", which);
749   skip_this_indent++;
750   make_command_string_internal (while_command->test);
751   PRINT_DEFERRED_HEREDOCS ("");
752   semicolon ();
753   cprintf (" do\n");    /* was newline ("do\n"); */
754   indentation += indentation_amount;
755   make_command_string_internal (while_command->action);
756   PRINT_DEFERRED_HEREDOCS ("");
757   indentation -= indentation_amount;
758   semicolon ();
759   newline ("done");
760 }
761
762 static void
763 print_if_command (if_command)
764      IF_COM *if_command;
765 {
766   cprintf ("if ");
767   skip_this_indent++;
768   make_command_string_internal (if_command->test);
769   semicolon ();
770   cprintf (" then\n");
771   indentation += indentation_amount;
772   make_command_string_internal (if_command->true_case);
773   PRINT_DEFERRED_HEREDOCS ("");
774   indentation -= indentation_amount;
775
776   if (if_command->false_case)
777     {
778       semicolon ();
779       newline ("else\n");
780       indentation += indentation_amount;
781       make_command_string_internal (if_command->false_case);
782       PRINT_DEFERRED_HEREDOCS ("");
783       indentation -= indentation_amount;
784     }
785   semicolon ();
786   newline ("fi");
787 }
788
789 #if defined (DPAREN_ARITHMETIC)
790 void
791 print_arith_command (arith_cmd_list)
792      WORD_LIST *arith_cmd_list;
793 {
794   cprintf ("((");
795   command_print_word_list (arith_cmd_list, " ");
796   cprintf ("))");
797 }
798 #endif
799
800 #if defined (COND_COMMAND)
801 static void
802 print_cond_node (cond)
803      COND_COM *cond;
804 {
805   if (cond->flags & CMD_INVERT_RETURN)
806     cprintf ("! ");
807
808   if (cond->type == COND_EXPR)
809     {
810       cprintf ("( ");
811       print_cond_node (cond->left);
812       cprintf (" )");
813     }
814   else if (cond->type == COND_AND)
815     {
816       print_cond_node (cond->left);
817       cprintf (" && ");
818       print_cond_node (cond->right);
819     }
820   else if (cond->type == COND_OR)
821     {
822       print_cond_node (cond->left);
823       cprintf (" || ");
824       print_cond_node (cond->right);
825     }
826   else if (cond->type == COND_UNARY)
827     {
828       cprintf ("%s", cond->op->word);
829       cprintf (" ");
830       print_cond_node (cond->left);
831     }
832   else if (cond->type == COND_BINARY)
833     {
834       print_cond_node (cond->left);
835       cprintf (" ");
836       cprintf ("%s", cond->op->word);
837       cprintf (" ");
838       print_cond_node (cond->right);
839     }
840   else if (cond->type == COND_TERM)
841     {
842       cprintf ("%s", cond->op->word);           /* need to add quoting here */
843     }
844 }
845
846 void
847 print_cond_command (cond)
848      COND_COM *cond;
849 {
850   cprintf ("[[ ");
851   print_cond_node (cond);
852   cprintf (" ]]");
853 }
854
855 #ifdef DEBUG
856 void
857 debug_print_cond_command (cond)
858      COND_COM *cond;
859 {
860   fprintf (stderr, "DEBUG: ");
861   command_string_index = 0;
862   print_cond_command (cond);
863   fprintf (stderr, "%s\n", the_printed_command);
864 }
865 #endif
866
867 void
868 xtrace_print_cond_term (type, invert, op, arg1, arg2)
869      int type, invert;
870      WORD_DESC *op;
871      char *arg1, *arg2;
872 {
873   CHECK_XTRACE_FP;
874   command_string_index = 0;
875   fprintf (xtrace_fp, "%s", indirection_level_string ());
876   fprintf (xtrace_fp, "[[ ");
877   if (invert)
878     fprintf (xtrace_fp, "! ");
879
880   if (type == COND_UNARY)
881     {
882       fprintf (xtrace_fp, "%s ", op->word);
883       fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
884     }
885   else if (type == COND_BINARY)
886     {
887       fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
888       fprintf (xtrace_fp, " %s ", op->word);
889       fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
890     }
891
892   fprintf (xtrace_fp, " ]]\n");
893
894   fflush (xtrace_fp);
895 }         
896 #endif /* COND_COMMAND */
897
898 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
899 /* A function to print the words of an arithmetic command when set -x is on. */
900 void
901 xtrace_print_arith_cmd (list)
902      WORD_LIST *list;
903 {
904   WORD_LIST *w;
905
906   CHECK_XTRACE_FP;
907   fprintf (xtrace_fp, "%s", indirection_level_string ());
908   fprintf (xtrace_fp, "(( ");
909   for (w = list; w; w = w->next)
910     fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
911   fprintf (xtrace_fp, " ))\n");
912
913   fflush (xtrace_fp);
914 }
915 #endif
916
917 void
918 print_simple_command (simple_command)
919      SIMPLE_COM *simple_command;
920 {
921   command_print_word_list (simple_command->words, " ");
922
923   if (simple_command->redirects)
924     {
925       cprintf (" ");
926       print_redirection_list (simple_command->redirects);
927     }
928 }
929
930 static void
931 print_heredocs (heredocs)
932      REDIRECT *heredocs;
933 {
934   REDIRECT *hdtail;
935
936   cprintf (" "); 
937   for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
938     {
939       print_redirection (hdtail);
940       cprintf ("\n");
941     }
942   was_heredoc = 1;
943 }
944
945 /* Print heredocs that are attached to the command before the connector
946    represented by CSTRING.  The parsing semantics require us to print the
947    here-doc delimiters, then the connector (CSTRING), then the here-doc
948    bodies.  We don't print the connector if it's a `;', but we use it to
949    note not to print an extra space after the last heredoc body and
950    newline. */
951 static void
952 print_deferred_heredocs (cstring)
953      const char *cstring;
954 {
955   REDIRECT *hdtail;     
956
957   for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
958     {
959       cprintf (" ");
960       print_heredoc_header (hdtail);
961     }
962   if (cstring[0] && (cstring[0] != ';' || cstring[1]))
963     cprintf ("%s", cstring); 
964   if (deferred_heredocs)
965     cprintf ("\n");
966   for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
967     {
968       print_heredoc_body (hdtail);
969       cprintf ("\n");
970     }
971   if (deferred_heredocs)
972     {
973       if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
974         cprintf (" ");  /* make sure there's at least one space */
975       dispose_redirects (deferred_heredocs);
976       was_heredoc = 1;
977     }
978   deferred_heredocs = (REDIRECT *)NULL;
979 }
980       
981 static void
982 print_redirection_list (redirects)
983      REDIRECT *redirects;
984 {
985   REDIRECT *heredocs, *hdtail, *newredir;
986
987   heredocs = (REDIRECT *)NULL;
988   hdtail = heredocs;
989
990   was_heredoc = 0;
991   while (redirects)
992     {
993       /* Defer printing the here documents until we've printed the
994          rest of the redirections. */
995       if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
996         {
997           newredir = copy_redirect (redirects);
998           newredir->next = (REDIRECT *)NULL;
999           if (heredocs)
1000             {
1001               hdtail->next = newredir;
1002               hdtail = newredir;
1003             }
1004           else
1005             hdtail = heredocs = newredir;
1006         }
1007       else if (redirects->instruction == r_duplicating_output_word && redirects->redirector.dest == 1)
1008         {
1009           /* Temporarily translate it as the execution code does. */
1010           redirects->instruction = r_err_and_out;
1011           print_redirection (redirects);
1012           redirects->instruction = r_duplicating_output_word;
1013         }
1014       else
1015         print_redirection (redirects);
1016
1017       redirects = redirects->next;
1018       if (redirects)
1019         cprintf (" ");
1020     }
1021
1022   /* Now that we've printed all the other redirections (on one line),
1023      print the here documents. */
1024   if (heredocs && printing_connection)
1025     deferred_heredocs = heredocs;
1026   else if (heredocs)
1027     {
1028       print_heredocs (heredocs);
1029       dispose_redirects (heredocs);
1030     }
1031 }
1032
1033 static void
1034 print_heredoc_header (redirect)
1035      REDIRECT *redirect;
1036 {
1037   int kill_leading;
1038   char *x;
1039
1040   kill_leading = redirect->instruction == r_deblank_reading_until;
1041
1042   /* Here doc header */
1043   if (redirect->rflags & REDIR_VARASSIGN)
1044     cprintf ("{%s}", redirect->redirector.filename->word);
1045   else if (redirect->redirector.dest != 0)
1046     cprintf ("%d", redirect->redirector.dest);
1047
1048   /* If the here document delimiter is quoted, single-quote it. */
1049   if (redirect->redirectee.filename->flags & W_QUOTED)
1050     {
1051       x = sh_single_quote (redirect->here_doc_eof);
1052       cprintf ("<<%s%s", kill_leading ? "-" : "", x);
1053       free (x);
1054     }
1055   else
1056     cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
1057 }
1058
1059 static void
1060 print_heredoc_body (redirect)
1061      REDIRECT *redirect;
1062 {
1063   /* Here doc body */
1064   cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
1065 }
1066
1067 static void
1068 print_redirection (redirect)
1069      REDIRECT *redirect;
1070 {
1071   int redirector, redir_fd;
1072   WORD_DESC *redirectee, *redir_word;
1073
1074   redirectee = redirect->redirectee.filename;
1075   redir_fd = redirect->redirectee.dest;
1076
1077   redir_word = redirect->redirector.filename;
1078   redirector = redirect->redirector.dest;
1079
1080   switch (redirect->instruction)
1081     {
1082     case r_input_direction:
1083       if (redirect->rflags & REDIR_VARASSIGN)
1084         cprintf ("{%s}", redir_word->word);
1085       else if (redirector != 0)
1086         cprintf ("%d", redirector);
1087       cprintf ("< %s", redirectee->word);
1088       break;
1089
1090     case r_output_direction:
1091       if (redirect->rflags & REDIR_VARASSIGN)
1092         cprintf ("{%s}", redir_word->word);
1093       else if (redirector != 1)
1094         cprintf ("%d", redirector);
1095       cprintf ("> %s", redirectee->word);
1096       break;
1097
1098     case r_inputa_direction:    /* Redirection created by the shell. */
1099       cprintf ("&");
1100       break;
1101
1102     case r_output_force:
1103       if (redirect->rflags & REDIR_VARASSIGN)
1104         cprintf ("{%s}", redir_word->word);
1105       else if (redirector != 1)
1106         cprintf ("%d", redirector);
1107       cprintf (">|%s", redirectee->word);
1108       break;
1109
1110     case r_appending_to:
1111       if (redirect->rflags & REDIR_VARASSIGN)
1112         cprintf ("{%s}", redir_word->word);
1113       else if (redirector != 1)
1114         cprintf ("%d", redirector);
1115       cprintf (">> %s", redirectee->word);
1116       break;
1117
1118     case r_input_output:
1119       if (redirect->rflags & REDIR_VARASSIGN)
1120         cprintf ("{%s}", redir_word->word);
1121       else if (redirector != 1)
1122         cprintf ("%d", redirector);
1123       cprintf ("<> %s", redirectee->word);
1124       break;
1125
1126     case r_deblank_reading_until:
1127     case r_reading_until:
1128       print_heredoc_header (redirect);
1129       cprintf ("\n");
1130       print_heredoc_body (redirect);
1131       break;
1132
1133     case r_reading_string:
1134       if (redirect->rflags & REDIR_VARASSIGN)
1135         cprintf ("{%s}", redir_word->word);
1136       else if (redirector != 0)
1137         cprintf ("%d", redirector);
1138 #if 0
1139       /* Don't need to check whether or not to requote, since original quotes
1140          are still intact.  The only thing that has happened is that $'...'
1141          has been replaced with 'expanded ...'. */
1142       if (ansic_shouldquote (redirect->redirectee.filename->word))
1143         {
1144           char *x;
1145           x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1146           cprintf ("<<< %s", x);
1147           free (x);
1148         }
1149       else
1150 #endif
1151         cprintf ("<<< %s", redirect->redirectee.filename->word);
1152       break;
1153
1154     case r_duplicating_input:
1155       if (redirect->rflags & REDIR_VARASSIGN)
1156         cprintf ("{%s}<&%d", redir_word->word, redir_fd);
1157       else
1158         cprintf ("%d<&%d", redirector, redir_fd);
1159       break;
1160
1161     case r_duplicating_output:
1162       if (redirect->rflags & REDIR_VARASSIGN)
1163         cprintf ("{%s}>&%d", redir_word->word, redir_fd);
1164       else
1165         cprintf ("%d>&%d", redirector, redir_fd);
1166       break;
1167
1168     case r_duplicating_input_word:
1169       if (redirect->rflags & REDIR_VARASSIGN)
1170         cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
1171       else
1172         cprintf ("%d<&%s", redirector, redirectee->word);
1173       break;
1174
1175     case r_duplicating_output_word:
1176       if (redirect->rflags & REDIR_VARASSIGN)
1177         cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
1178       else
1179         cprintf ("%d>&%s", redirector, redirectee->word);
1180       break;
1181
1182     case r_move_input:
1183       if (redirect->rflags & REDIR_VARASSIGN)
1184         cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
1185       else
1186         cprintf ("%d<&%d-", redirector, redir_fd);
1187       break;
1188
1189     case r_move_output:
1190       if (redirect->rflags & REDIR_VARASSIGN)
1191         cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
1192       else
1193         cprintf ("%d>&%d-", redirector, redir_fd);
1194       break;
1195
1196     case r_move_input_word:
1197       if (redirect->rflags & REDIR_VARASSIGN)
1198         cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
1199       else
1200         cprintf ("%d<&%s-", redirector, redirectee->word);
1201       break;
1202
1203     case r_move_output_word:
1204       if (redirect->rflags & REDIR_VARASSIGN)
1205         cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
1206       else
1207         cprintf ("%d>&%s-", redirector, redirectee->word);
1208       break;
1209
1210     case r_close_this:
1211       if (redirect->rflags & REDIR_VARASSIGN)
1212         cprintf ("{%s}>&-", redir_word->word);
1213       else
1214         cprintf ("%d>&-", redirector);
1215       break;
1216
1217     case r_err_and_out:
1218       cprintf ("&>%s", redirectee->word);
1219       break;
1220
1221     case r_append_err_and_out:
1222       cprintf ("&>>%s", redirectee->word);
1223       break;
1224     }
1225 }
1226
1227 static void
1228 reset_locals ()
1229 {
1230   inside_function_def = 0;
1231   indentation = 0;
1232   printing_connection = 0;
1233   deferred_heredocs = 0;
1234 }
1235
1236 static void
1237 print_function_def (func)
1238      FUNCTION_DEF *func;
1239 {
1240   COMMAND *cmdcopy;
1241   REDIRECT *func_redirects;
1242
1243   func_redirects = NULL;
1244   cprintf ("function %s () \n", func->name->word);
1245   add_unwind_protect (reset_locals, 0);
1246
1247   indent (indentation);
1248   cprintf ("{ \n");
1249
1250   inside_function_def++;
1251   indentation += indentation_amount;
1252
1253   cmdcopy = copy_command (func->command);
1254   if (cmdcopy->type == cm_group)
1255     {
1256       func_redirects = cmdcopy->redirects;
1257       cmdcopy->redirects = (REDIRECT *)NULL;
1258     }
1259   make_command_string_internal (cmdcopy->type == cm_group
1260                                         ? cmdcopy->value.Group->command
1261                                         : cmdcopy);
1262
1263   remove_unwind_protect ();
1264   indentation -= indentation_amount;
1265   inside_function_def--;
1266
1267   if (func_redirects)
1268     { /* { */
1269       newline ("} ");
1270       print_redirection_list (func_redirects);
1271       cmdcopy->redirects = func_redirects;
1272     }
1273   else
1274     newline ("}");
1275
1276   dispose_command (cmdcopy);
1277 }
1278
1279 /* Return the string representation of the named function.
1280    NAME is the name of the function.
1281    COMMAND is the function body.  It should be a GROUP_COM.
1282    flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1283    flags&FUNC_EXTERNAL means convert from internal to external form
1284   */
1285 char *
1286 named_function_string (name, command, flags)
1287      char *name;
1288      COMMAND *command;
1289      int flags;
1290 {
1291   char *result;
1292   int old_indent, old_amount;
1293   COMMAND *cmdcopy;
1294   REDIRECT *func_redirects;
1295
1296   old_indent = indentation;
1297   old_amount = indentation_amount;
1298   command_string_index = was_heredoc = 0;
1299   deferred_heredocs = 0;
1300
1301   if (name && *name)
1302     cprintf ("%s ", name);
1303
1304   cprintf ("() ");
1305
1306   if ((flags & FUNC_MULTILINE) == 0)
1307     {
1308       indentation = 1;
1309       indentation_amount = 0;
1310     }
1311   else
1312     {
1313       cprintf ("\n");
1314       indentation += indentation_amount;
1315     }
1316
1317   inside_function_def++;
1318
1319   cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
1320
1321   cmdcopy = copy_command (command);
1322   /* Take any redirections specified in the function definition (which should
1323      apply to the function as a whole) and save them for printing later. */
1324   func_redirects = (REDIRECT *)NULL;
1325   if (cmdcopy->type == cm_group)
1326     {
1327       func_redirects = cmdcopy->redirects;
1328       cmdcopy->redirects = (REDIRECT *)NULL;
1329     }
1330   make_command_string_internal (cmdcopy->type == cm_group
1331                                         ? cmdcopy->value.Group->command
1332                                         : cmdcopy);
1333
1334   indentation = old_indent;
1335   indentation_amount = old_amount;
1336   inside_function_def--;
1337
1338   if (func_redirects)
1339     { /* { */
1340       newline ("} ");
1341       print_redirection_list (func_redirects);
1342       cmdcopy->redirects = func_redirects;
1343     }
1344   else
1345     newline ("}");
1346
1347   result = the_printed_command;
1348
1349   if ((flags & FUNC_MULTILINE) == 0)
1350     {
1351 #if 0
1352       register int i;
1353       for (i = 0; result[i]; i++)
1354         if (result[i] == '\n')
1355           {
1356             strcpy (result + i, result + i + 1);
1357             --i;
1358           }
1359 #else
1360       if (result[2] == '\n')    /* XXX -- experimental */
1361         strcpy (result + 2, result + 3);
1362 #endif
1363     }
1364
1365   dispose_command (cmdcopy);
1366
1367   if (flags & FUNC_EXTERNAL)
1368     result = remove_quoted_escapes (result);
1369
1370   return (result);
1371 }
1372
1373 static void
1374 newline (string)
1375      char *string;
1376 {
1377   cprintf ("\n");
1378   indent (indentation);
1379   if (string && *string)
1380     cprintf ("%s", string);
1381 }
1382
1383 static char *indentation_string;
1384 static int indentation_size;
1385
1386 static void
1387 indent (amount)
1388      int amount;
1389 {
1390   register int i;
1391
1392   RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1393
1394   for (i = 0; amount > 0; amount--)
1395     indentation_string[i++] = ' ';
1396   indentation_string[i] = '\0';
1397   cprintf (indentation_string);
1398 }
1399
1400 static void
1401 semicolon ()
1402 {
1403   if (command_string_index > 0 &&
1404        (the_printed_command[command_string_index - 1] == '&' ||
1405         the_printed_command[command_string_index - 1] == '\n'))
1406     return;
1407   cprintf (";");
1408 }
1409
1410 /* How to make the string. */
1411 static void
1412 #if defined (PREFER_STDARG)
1413 cprintf (const char *control, ...)
1414 #else
1415 cprintf (control, va_alist)
1416      const char *control;
1417      va_dcl
1418 #endif
1419 {
1420   register const char *s;
1421   char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
1422   int digit_arg, arg_len, c;
1423   va_list args;
1424
1425   SH_VA_START (args, control);
1426
1427   arg_len = strlen (control);
1428   the_printed_command_resize (arg_len + 1);
1429
1430   char_arg[1] = '\0';
1431   s = control;
1432   while (s && *s)
1433     {
1434       c = *s++;
1435       argp = (char *)NULL;
1436       if (c != '%' || !*s)
1437         {
1438           char_arg[0] = c;
1439           argp = char_arg;
1440           arg_len = 1;
1441         }
1442       else
1443         {
1444           c = *s++;
1445           switch (c)
1446             {
1447             case '%':
1448               char_arg[0] = c;
1449               argp = char_arg;
1450               arg_len = 1;
1451               break;
1452
1453             case 's':
1454               argp = va_arg (args, char *);
1455               arg_len = strlen (argp);
1456               break;
1457
1458             case 'd':
1459               /* Represent an out-of-range file descriptor with an out-of-range
1460                  integer value.  We can do this because the only use of `%d' in
1461                  the calls to cprintf is to output a file descriptor number for
1462                  a redirection. */
1463               digit_arg = va_arg (args, int);
1464               if (digit_arg < 0)
1465                 {
1466                   sprintf (intbuf, "%u", (unsigned)-1);
1467                   argp = intbuf;
1468                 }
1469               else
1470                 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1471               arg_len = strlen (argp);
1472               break;
1473
1474             case 'c':
1475               char_arg[0] = va_arg (args, int);
1476               argp = char_arg;
1477               arg_len = 1;
1478               break;
1479
1480             default:
1481               programming_error (_("cprintf: `%c': invalid format character"), c);
1482               /*NOTREACHED*/
1483             }
1484         }
1485
1486       if (argp && arg_len)
1487         {
1488           the_printed_command_resize (arg_len + 1);
1489           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1490           command_string_index += arg_len;
1491         }
1492     }
1493
1494   the_printed_command[command_string_index] = '\0';
1495 }
1496
1497 /* Ensure that there is enough space to stuff LENGTH characters into
1498    THE_PRINTED_COMMAND. */
1499 static void
1500 the_printed_command_resize (length)
1501      int length;
1502 {
1503   if (the_printed_command == 0)
1504     {
1505       the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1506       the_printed_command = (char *)xmalloc (the_printed_command_size);
1507       command_string_index = 0;
1508     }
1509   else if ((command_string_index + length) >= the_printed_command_size)
1510     {
1511       int new;
1512       new = command_string_index + length + 1;
1513
1514       /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1515       new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1516       the_printed_command_size = new;
1517
1518       the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
1519     }
1520 }
1521
1522 #if defined (HAVE_VPRINTF)
1523 /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1524      also available.'' */
1525
1526 static void
1527 #if defined (PREFER_STDARG)
1528 xprintf (const char *format, ...)
1529 #else
1530 xprintf (format, va_alist)
1531      const char *format;
1532      va_dcl
1533 #endif
1534 {
1535   va_list args;
1536
1537   SH_VA_START (args, format);
1538
1539   vfprintf (stdout, format, args);
1540   va_end (args);
1541 }
1542
1543 #else
1544
1545 static void
1546 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1547      const char *format;
1548 {
1549   printf (format, arg1, arg2, arg3, arg4, arg5);
1550 }
1551
1552 #endif /* !HAVE_VPRINTF */