1 /* print_command -- A way to make readable commands from a command tree. */
2 /* Copyright (C) 1989 Free Software Foundation, Inc.
4 This file is part of GNU Bash, the Bourne Again SHell.
6 Bash is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License along
17 with Bash; see the file COPYING. If not, write to the Free Software
18 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
24 #if defined (HAVE_UNISTD_H)
26 # include <sys/types.h>
31 #if defined (PREFER_STDARG)
34 # if defined (PREFER_VARARGS)
42 #include <y.tab.h> /* use <...> so we pick it up from the build directory */
44 #include "builtins/common.h"
46 #if !defined (PRINTF_DECLARED)
47 extern int printf
__P((const char *, ...)); /* Yuck. Double yuck. */
50 static int indentation
;
51 static int indentation_amount
= 4;
53 #if defined (PREFER_STDARG)
54 static void cprintf
__P((char *, ...));
56 static void cprintf ();
59 static void newline (), indent (), the_printed_command_resize ();
60 static void semicolon ();
61 static void xprintf ();
63 static void make_command_string_internal ();
64 static void command_print_word_list ();
65 static void print_case_clauses ();
66 static void print_redirection_list ();
67 static void print_redirection ();
69 static void print_for_command ();
70 #if defined (SELECT_COMMAND)
71 static void print_select_command ();
73 static void print_group_command ();
74 static void print_case_command ();
75 static void print_while_command ();
76 static void print_until_command ();
77 static void print_until_or_while ();
78 static void print_if_command ();
79 static void print_function_def ();
80 #if defined (DPAREN_ARITHMETIC)
81 static void print_arith_command ();
83 #if defined (COND_COMMAND)
84 static void print_cond_node ();
85 static void print_cond_command ();
87 #if defined (ARITH_FOR_COMMAND)
88 static void print_arith_for_command ();
91 #define PRINTED_COMMAND_INITIAL_SIZE 64
92 #define PRINTED_COMMAND_GROW_SIZE 128
94 char *the_printed_command
= (char *)NULL
;
95 int the_printed_command_size
= 0;
96 int command_string_index
= 0;
98 /* Non-zero means the stuff being printed is inside of a function def. */
99 static int inside_function_def
;
100 static int skip_this_indent
;
101 static int was_heredoc
;
103 /* The depth of the group commands that we are currently printing. This
104 includes the group command that is a function body. */
105 static int group_command_nesting
;
107 /* Print COMMAND (a command tree) on standard output. */
109 print_command (command
)
112 command_string_index
= 0;
113 printf ("%s", make_command_string (command
));
116 /* Make a string which is the printed representation of the command
117 tree in COMMAND. We return this string. However, the string is
118 not consed, so you have to do that yourself if you want it to
121 make_command_string (command
)
124 command_string_index
= was_heredoc
= 0;
125 make_command_string_internal (command
);
126 return (the_printed_command
);
129 /* The internal function. This is the real workhorse. */
131 make_command_string_internal (command
)
138 if (skip_this_indent
)
141 indent (indentation
);
143 if (command
->flags
& CMD_TIME_PIPELINE
)
146 if (command
->flags
& CMD_TIME_POSIX
)
150 if (command
->flags
& CMD_INVERT_RETURN
)
153 switch (command
->type
)
156 print_for_command (command
->value
.For
);
159 #if defined (ARITH_FOR_COMMAND)
161 print_arith_for_command (command
->value
.ArithFor
);
165 #if defined (SELECT_COMMAND)
167 print_select_command (command
->value
.Select
);
172 print_case_command (command
->value
.Case
);
176 print_while_command (command
->value
.While
);
180 print_until_command (command
->value
.While
);
184 print_if_command (command
->value
.If
);
187 #if defined (DPAREN_ARITHMETIC)
189 print_arith_command (command
->value
.Arith
);
193 #if defined (COND_COMMAND)
195 print_cond_command (command
->value
.Cond
);
200 print_simple_command (command
->value
.Simple
);
206 make_command_string_internal (command
->value
.Connection
->first
);
208 switch (command
->value
.Connection
->connector
)
213 char c
= command
->value
.Connection
->connector
;
215 if (c
!= '&' || command
->value
.Connection
->second
)
225 if (command
->value
.Connection
->second
)
231 if (command
->value
.Connection
->second
)
236 if (was_heredoc
== 0)
241 if (inside_function_def
)
246 if (command
->value
.Connection
->second
)
252 cprintf ("print_command: bad connector `%d'",
253 command
->value
.Connection
->connector
);
257 make_command_string_internal (command
->value
.Connection
->second
);
260 case cm_function_def
:
261 print_function_def (command
->value
.Function_def
);
265 print_group_command (command
->value
.Group
);
271 make_command_string_internal (command
->value
.Subshell
->command
);
276 command_error ("print_command", CMDERR_BADTYPE
, command
->type
, 0);
281 if (command
->redirects
)
284 print_redirection_list (command
->redirects
);
290 _print_word_list (list
, separator
, pfunc
)
297 for (w
= list
; w
; w
= w
->next
)
298 (*pfunc
) ("%s%s", w
->word
->word
, w
->next
? separator
: "");
302 print_word_list (list
, separator
)
306 _print_word_list (list
, separator
, xprintf
);
309 /* A function to print the words of a simple command when set -x is on. */
311 xtrace_print_word_list (list
)
317 fprintf (stderr
, "%s", indirection_level_string ());
318 for (w
= list
; w
; w
= w
->next
)
321 if (t
== 0 || *t
== '\0')
322 fprintf (stderr
, "''%s", w
->next
? " " : "");
323 else if (contains_shell_metas (t
))
325 x
= single_quote (t
);
326 fprintf (stderr
, "%s%s", x
, w
->next
? " " : "");
330 fprintf (stderr
, "%s%s", t
, w
->next
? " " : "");
332 fprintf (stderr
, "\n");
336 command_print_word_list (list
, separator
)
340 _print_word_list (list
, separator
, cprintf
);
344 print_for_command (for_command
)
345 FOR_COM
*for_command
;
347 cprintf ("for %s in ", for_command
->name
->word
);
348 command_print_word_list (for_command
->map_list
, " ");
351 indentation
+= indentation_amount
;
352 make_command_string_internal (for_command
->action
);
354 indentation
-= indentation_amount
;
358 #if defined (ARITH_FOR_COMMAND)
360 print_arith_for_command (arith_for_command
)
361 ARITH_FOR_COM
*arith_for_command
;
364 command_print_word_list (arith_for_command
->init
, " ");
366 command_print_word_list (arith_for_command
->test
, " ");
368 command_print_word_list (arith_for_command
->step
, " ");
371 indentation
+= indentation_amount
;
372 make_command_string_internal (arith_for_command
->action
);
374 indentation
-= indentation_amount
;
377 #endif /* ARITH_FOR_COMMAND */
379 #if defined (SELECT_COMMAND)
381 print_select_command (select_command
)
382 SELECT_COM
*select_command
;
384 cprintf ("select %s in ", select_command
->name
->word
);
385 command_print_word_list (select_command
->map_list
, " ");
388 indentation
+= indentation_amount
;
389 make_command_string_internal (select_command
->action
);
391 indentation
-= indentation_amount
;
394 #endif /* SELECT_COMMAND */
397 print_group_command (group_command
)
398 GROUP_COM
*group_command
;
400 group_command_nesting
++;
403 if (inside_function_def
== 0)
407 /* This is a group command { ... } inside of a function
408 definition, and should be printed as a multiline group
409 command, using the current indentation. */
411 indentation
+= indentation_amount
;
414 make_command_string_internal (group_command
->command
);
416 if (inside_function_def
)
419 indentation
-= indentation_amount
;
420 indent (indentation
);
430 group_command_nesting
--;
434 print_case_command (case_command
)
435 CASE_COM
*case_command
;
437 cprintf ("case %s in ", case_command
->word
->word
);
438 if (case_command
->clauses
)
439 print_case_clauses (case_command
->clauses
);
444 print_case_clauses (clauses
)
445 PATTERN_LIST
*clauses
;
447 indentation
+= indentation_amount
;
451 command_print_word_list (clauses
->patterns
, " | ");
453 indentation
+= indentation_amount
;
454 make_command_string_internal (clauses
->action
);
455 indentation
-= indentation_amount
;
457 clauses
= clauses
->next
;
459 indentation
-= indentation_amount
;
463 print_while_command (while_command
)
464 WHILE_COM
*while_command
;
466 print_until_or_while (while_command
, "while");
470 print_until_command (while_command
)
471 WHILE_COM
*while_command
;
473 print_until_or_while (while_command
, "until");
477 print_until_or_while (while_command
, which
)
478 WHILE_COM
*while_command
;
481 cprintf ("%s ", which
);
483 make_command_string_internal (while_command
->test
);
485 cprintf (" do\n"); /* was newline ("do\n"); */
486 indentation
+= indentation_amount
;
487 make_command_string_internal (while_command
->action
);
488 indentation
-= indentation_amount
;
494 print_if_command (if_command
)
499 make_command_string_internal (if_command
->test
);
502 indentation
+= indentation_amount
;
503 make_command_string_internal (if_command
->true_case
);
504 indentation
-= indentation_amount
;
506 if (if_command
->false_case
)
510 indentation
+= indentation_amount
;
511 make_command_string_internal (if_command
->false_case
);
512 indentation
-= indentation_amount
;
518 #if defined (DPAREN_ARITHMETIC)
520 print_arith_command (arith_command
)
521 ARITH_COM
*arith_command
;
524 command_print_word_list (arith_command
->exp
, " ");
529 #if defined (COND_COMMAND)
531 print_cond_node (cond
)
534 if (cond
->flags
& CMD_INVERT_RETURN
)
537 if (cond
->type
== COND_EXPR
)
540 print_cond_node (cond
->left
);
543 else if (cond
->type
== COND_AND
)
545 print_cond_node (cond
->left
);
547 print_cond_node (cond
->right
);
549 else if (cond
->type
== COND_OR
)
551 print_cond_node (cond
->left
);
553 print_cond_node (cond
->right
);
555 else if (cond
->type
== COND_UNARY
)
557 cprintf ("%s", cond
->op
->word
);
559 print_cond_node (cond
->left
);
561 else if (cond
->type
== COND_BINARY
)
563 print_cond_node (cond
->left
);
565 cprintf ("%s", cond
->op
->word
);
567 print_cond_node (cond
->right
);
569 else if (cond
->type
== COND_TERM
)
571 cprintf ("%s", cond
->op
->word
); /* need to add quoting here */
576 print_cond_command (cond
)
580 print_cond_node (cond
);
585 debug_print_cond_command (cond
)
588 fprintf (stderr
, "DEBUG: ");
589 command_string_index
= 0;
590 print_cond_command (cond
);
591 fprintf (stderr
, "%s\n", the_printed_command
);
595 xtrace_print_cond_term (type
, invert
, op
, arg1
, arg2
)
600 command_string_index
= 0;
601 fprintf (stderr
, "%s", indirection_level_string ());
602 fprintf (stderr
, "[[ ");
604 fprintf (stderr
, "! ");
606 if (type
== COND_UNARY
)
608 fprintf (stderr
, "%s ", op
->word
);
609 fprintf (stderr
, "%s", (arg1
&& *arg1
) ? arg1
: "''");
611 else if (type
== COND_BINARY
)
613 fprintf (stderr
, "%s", (arg1
&& *arg1
) ? arg1
: "''");
614 fprintf (stderr
, " %s ", op
->word
);
615 fprintf (stderr
, "%s", (arg2
&& *arg2
) ? arg2
: "''");
618 fprintf (stderr
, " ]]\n");
620 #endif /* COND_COMMAND */
622 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
623 /* A function to print the words of an arithmetic command when set -x is on. */
625 xtrace_print_arith_cmd (list
)
630 fprintf (stderr
, "%s", indirection_level_string ());
631 fprintf (stderr
, "(( ");
632 for (w
= list
; w
; w
= w
->next
)
633 fprintf (stderr
, "%s%s", w
->word
->word
, w
->next
? " " : "");
634 fprintf (stderr
, " ))\n");
639 print_simple_command (simple_command
)
640 SIMPLE_COM
*simple_command
;
642 command_print_word_list (simple_command
->words
, " ");
644 if (simple_command
->redirects
)
647 print_redirection_list (simple_command
->redirects
);
652 print_redirection_list (redirects
)
655 REDIRECT
*heredocs
, *hdtail
, *newredir
;
657 heredocs
= (REDIRECT
*)NULL
;
663 /* Defer printing the here documents until we've printed the
664 rest of the redirections. */
665 if (redirects
->instruction
== r_reading_until
|| redirects
->instruction
== r_deblank_reading_until
)
667 newredir
= copy_redirect (redirects
);
668 newredir
->next
= (REDIRECT
*)NULL
;
671 hdtail
->next
= newredir
;
675 hdtail
= heredocs
= newredir
;
678 print_redirection (redirects
);
680 redirects
= redirects
->next
;
685 /* Now that we've printed all the other redirections (on one line),
686 print the here documents. */
690 for (hdtail
= heredocs
; hdtail
; hdtail
= hdtail
->next
)
692 print_redirection (hdtail
);
695 dispose_redirects (heredocs
);
701 print_redirection (redirect
)
704 int kill_leading
, redirector
, redir_fd
;
705 WORD_DESC
*redirectee
;
708 redirectee
= redirect
->redirectee
.filename
;
709 redirector
= redirect
->redirector
;
710 redir_fd
= redirect
->redirectee
.dest
;
712 switch (redirect
->instruction
)
714 case r_output_direction
:
716 cprintf ("%d", redirector
);
717 cprintf (">%s", redirectee
->word
);
720 case r_input_direction
:
722 cprintf ("%d", redirector
);
723 cprintf ("<%s", redirectee
->word
);
726 case r_inputa_direction
: /* Redirection created by the shell. */
732 cprintf ("%d", redirector
);
733 cprintf (">>%s", redirectee
->word
);
736 case r_deblank_reading_until
:
739 case r_reading_until
:
741 cprintf ("%d", redirector
);
742 /* If the here document delimiter is quoted, single-quote it. */
743 if (redirect
->redirectee
.filename
->flags
& W_QUOTED
)
746 x
= single_quote (redirect
->here_doc_eof
);
747 cprintf ("<<%s%s\n", kill_leading
? "-" : "", x
);
751 cprintf ("<<%s%s\n", kill_leading
? "-" : "", redirect
->here_doc_eof
);
753 redirect
->redirectee
.filename
->word
, redirect
->here_doc_eof
);
756 case r_duplicating_input
:
757 cprintf ("%d<&%d", redirector
, redir_fd
);
760 case r_duplicating_output
:
761 cprintf ("%d>&%d", redirector
, redir_fd
);
764 case r_duplicating_input_word
:
765 cprintf ("%d<&%s", redirector
, redirectee
->word
);
768 case r_duplicating_output_word
:
769 cprintf ("%d>&%s", redirector
, redirectee
->word
);
773 cprintf ("%d>&-", redirector
);
777 cprintf (">&%s", redirectee
->word
);
782 cprintf ("%d", redirector
);
783 cprintf ("<>%s", redirectee
->word
);
788 cprintf ("%d", redirector
);
789 cprintf (">|%s", redirectee
->word
);
797 inside_function_def
= 0;
802 print_function_def (func
)
806 REDIRECT
*func_redirects
;
808 cprintf ("function %s () \n", func
->name
->word
);
809 add_unwind_protect (reset_locals
, 0);
811 indent (indentation
);
814 inside_function_def
++;
815 indentation
+= indentation_amount
;
817 func_redirects
= (REDIRECT
*)NULL
;
818 cmdcopy
= copy_command (func
->command
);
819 if (cmdcopy
->type
== cm_group
)
821 func_redirects
= cmdcopy
->value
.Group
->command
->redirects
;
822 cmdcopy
->value
.Group
->command
->redirects
= (REDIRECT
*)NULL
;
824 make_command_string_internal (cmdcopy
->type
== cm_group
825 ? cmdcopy
->value
.Group
->command
828 remove_unwind_protect ();
829 indentation
-= indentation_amount
;
830 inside_function_def
--;
835 print_redirection_list (func_redirects
);
836 cmdcopy
->value
.Group
->command
->redirects
= func_redirects
;
841 dispose_command (cmdcopy
);
844 /* Return the string representation of the named function.
845 NAME is the name of the function.
846 COMMAND is the function body. It should be a GROUP_COM.
847 MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
850 named_function_string (name
, command
, multi_line
)
856 int old_indent
, old_amount
;
858 REDIRECT
*func_redirects
;
860 old_indent
= indentation
;
861 old_amount
= indentation_amount
;
862 command_string_index
= was_heredoc
= 0;
865 cprintf ("%s ", name
);
872 indentation_amount
= 0;
877 indentation
+= indentation_amount
;
880 inside_function_def
++;
882 cprintf (multi_line
? "{ \n" : "{ ");
884 cmdcopy
= copy_command (command
);
885 /* Take any redirections specified in the function definition (which should
886 apply to the function as a whole) and save them for printing later. */
887 func_redirects
= (REDIRECT
*)NULL
;
888 if (cmdcopy
->type
== cm_group
)
890 func_redirects
= cmdcopy
->value
.Group
->command
->redirects
;
891 cmdcopy
->value
.Group
->command
->redirects
= (REDIRECT
*)NULL
;
893 make_command_string_internal (cmdcopy
->type
== cm_group
894 ? cmdcopy
->value
.Group
->command
897 indentation
= old_indent
;
898 indentation_amount
= old_amount
;
899 inside_function_def
--;
904 print_redirection_list (func_redirects
);
905 cmdcopy
->value
.Group
->command
->redirects
= func_redirects
;
910 result
= the_printed_command
;
916 for (i
= 0; result
[i
]; i
++)
917 if (result
[i
] == '\n')
919 strcpy (result
+ i
, result
+ i
+ 1);
923 if (result
[2] == '\n') /* XXX -- experimental */
924 strcpy (result
+ 2, result
+ 3);
928 dispose_command (cmdcopy
);
938 indent (indentation
);
939 if (string
&& *string
)
940 cprintf ("%s", string
);
943 static char *indentation_string
;
944 static int indentation_size
;
952 RESIZE_MALLOCED_BUFFER (indentation_string
, 0, amount
, indentation_size
, 16);
954 for (i
= 0; amount
> 0; amount
--)
955 indentation_string
[i
++] = ' ';
956 indentation_string
[i
] = '\0';
957 cprintf (indentation_string
);
963 if (command_string_index
> 0 && the_printed_command
[command_string_index
- 1] == '&')
968 #if !defined (USE_VARARGS)
969 /* How to make the string. */
971 cprintf (format
, arg1
, arg2
)
972 char *format
, *arg1
, *arg2
;
975 char char_arg
[2], *argp
, *args
[2], intbuf
[32];
976 int arg_len
, c
, arg_index
;
978 args
[arg_index
= 0] = arg1
;
981 arg_len
= strlen (format
);
982 the_printed_command_resize (arg_len
+ 1);
1007 argp
= (char *)args
[arg_index
++];
1008 arg_len
= strlen (argp
);
1012 argp
= inttostr (pointer_to_int (args
[arg_index
]), intbuf
, sizeof (intbuf
));
1014 arg_len
= strlen (argp
);
1018 char_arg
[0] = pointer_to_int (args
[arg_index
]);
1025 programming_error ("cprintf: bad `%%' argument (%c)", c
);
1030 the_printed_command_resize (arg_len
+ 1);
1031 FASTCOPY (argp
, the_printed_command
+ command_string_index
, arg_len
);
1032 command_string_index
+= arg_len
;
1038 the_printed_command
[command_string_index
] = '\0';
1041 #else /* We have support for varargs. */
1043 /* How to make the string. */
1045 #if defined (PREFER_STDARG)
1046 cprintf (char *control
, ...)
1048 cprintf (control
, va_alist
)
1054 char char_arg
[2], *argp
, intbuf
[32];
1055 int digit_arg
, arg_len
, c
;
1058 #if defined (PREFER_STDARG)
1059 va_start (args
, control
);
1064 arg_len
= strlen (control
);
1065 the_printed_command_resize (arg_len
+ 1);
1074 argp
= (char *)NULL
;
1075 if (c
!= '%' || !*s
)
1092 argp
= va_arg (args
, char *);
1093 arg_len
= strlen (argp
);
1097 digit_arg
= va_arg (args
, int);
1098 argp
= inttostr (digit_arg
, intbuf
, sizeof (intbuf
));
1099 arg_len
= strlen (argp
);
1103 char_arg
[0] = va_arg (args
, int);
1109 programming_error ("cprintf: bad `%%' argument (%c)", c
);
1114 if (argp
&& arg_len
)
1116 the_printed_command_resize (arg_len
+ 1);
1117 FASTCOPY (argp
, the_printed_command
+ command_string_index
, arg_len
);
1118 command_string_index
+= arg_len
;
1124 the_printed_command
[command_string_index
] = '\0';
1126 #endif /* HAVE_VARARGS_H */
1128 /* Ensure that there is enough space to stuff LENGTH characters into
1129 THE_PRINTED_COMMAND. */
1131 the_printed_command_resize (length
)
1134 if (the_printed_command
== 0)
1136 the_printed_command_size
= (length
+ PRINTED_COMMAND_INITIAL_SIZE
- 1) & ~(PRINTED_COMMAND_INITIAL_SIZE
- 1);
1137 the_printed_command
= xmalloc (the_printed_command_size
);
1138 command_string_index
= 0;
1140 else if ((command_string_index
+ length
) >= the_printed_command_size
)
1143 new = command_string_index
+ length
+ 1;
1145 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1146 new = (new + PRINTED_COMMAND_GROW_SIZE
- 1) & ~(PRINTED_COMMAND_GROW_SIZE
- 1);
1147 the_printed_command_size
= new;
1149 the_printed_command
= xrealloc (the_printed_command
, the_printed_command_size
);
1153 #if defined (HAVE_VFPRINTF)
1156 #if defined (PREFER_STDARG)
1157 xprintf (const char *format
, ...)
1159 xprintf (format
, va_alist
)
1166 #if defined (PREFER_STDARG)
1167 va_start (args
, format
);
1172 vfprintf (stdout
, format
, args
);
1179 xprintf (format
, arg1
, arg2
, arg3
, arg4
, arg5
)
1182 printf (format
, arg1
, arg2
, arg3
, arg4
, arg5
);
1185 #endif /* !HAVE_VFPRINTF */