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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #if defined (HAVE_VARARGS_H)
26 #if defined (HAVE_STRING_H)
28 #else /* !HAVE_STRING_H */
30 #endif /* !HAVE_STRING_H */
35 #include "builtins/common.h"
37 #if defined (__GNUC__) || defined (ardent)
38 extern int printf
__P((const char *, ...)); /* Yuck. Double yuck. */
41 static int indentation
= 0;
42 static int indentation_amount
= 4;
44 static void cprintf (), newline (), indent (), the_printed_command_resize ();
45 static void semicolon ();
47 static void make_command_string_internal ();
48 static void command_print_word_list ();
49 static void print_case_clauses ();
50 static void print_redirection_list ();
51 static void print_redirection ();
53 static void print_for_command ();
54 #if defined (SELECT_COMMAND)
55 static void print_select_command ();
57 static void print_group_command ();
58 static void print_case_command ();
59 static void print_while_command ();
60 static void print_until_command ();
61 static void print_until_or_while ();
62 static void print_if_command ();
63 static void print_function_def ();
65 #define PRINTED_COMMAND_GROW_SIZE 1024
67 char *the_printed_command
= (char *)NULL
;
68 int the_printed_command_size
= 0;
69 int command_string_index
= 0;
71 /* Non-zero means the stuff being printed is inside of a function def. */
72 static int inside_function_def
= 0;
73 static int skip_this_indent
= 0;
75 /* The depth of the group commands that we are currently printing. This
76 includes the group command that is a function body. */
77 static int group_command_nesting
= 0;
79 /* Print COMMAND (a command tree) on standard output. */
81 print_command (command
)
84 command_string_index
= 0;
85 printf ("%s", make_command_string (command
));
88 /* Make a string which is the printed representation of the command
89 tree in COMMAND. We return this string. However, the string is
90 not consed, so you have to do that yourself if you want it to
93 make_command_string (command
)
96 command_string_index
= 0;
97 make_command_string_internal (command
);
98 return (the_printed_command
);
101 /* The internal function. This is the real workhorse. */
103 make_command_string_internal (command
)
110 if (skip_this_indent
)
113 indent (indentation
);
115 if (command
->flags
& CMD_WANT_SUBSHELL
)
118 if (command
->flags
& CMD_INVERT_RETURN
)
121 switch (command
->type
)
124 print_for_command (command
->value
.For
);
127 #if defined (SELECT_COMMAND)
129 print_select_command (command
->value
.Select
);
134 print_case_command (command
->value
.Case
);
138 print_while_command (command
->value
.While
);
142 print_until_command (command
->value
.While
);
146 print_if_command (command
->value
.If
);
150 print_simple_command (command
->value
.Simple
);
156 make_command_string_internal (command
->value
.Connection
->first
);
158 switch (command
->value
.Connection
->connector
)
163 char c
= command
->value
.Connection
->connector
;
165 if (c
!= '&' || command
->value
.Connection
->second
)
175 if (command
->value
.Connection
->second
)
181 if (command
->value
.Connection
->second
)
188 if (inside_function_def
)
193 if (command
->value
.Connection
->second
)
199 cprintf ("print_command: bad connector `%d'",
200 command
->value
.Connection
->connector
);
204 make_command_string_internal (command
->value
.Connection
->second
);
207 case cm_function_def
:
208 print_function_def (command
->value
.Function_def
);
212 print_group_command (command
->value
.Group
);
216 programming_error ("print_command: bad command type `%d'", command
->type
);
220 if (command
->flags
& CMD_WANT_SUBSHELL
)
223 if (command
->redirects
)
224 print_redirection_list (command
->redirects
);
229 _print_word_list (list
, separator
, pfunc
)
236 (*pfunc
) ("%s", list
->word
->word
);
239 (*pfunc
) ("%s", separator
);
243 void print_word_list (list
, separator
)
247 _print_word_list (list
, separator
, (VFunction
*)printf
);
251 command_print_word_list (list
, separator
)
255 _print_word_list (list
, separator
, cprintf
);
259 print_for_command (for_command
)
260 FOR_COM
*for_command
;
262 cprintf ("for %s in ", for_command
->name
->word
);
263 command_print_word_list (for_command
->map_list
, " ");
266 indentation
+= indentation_amount
;
267 make_command_string_internal (for_command
->action
);
269 indentation
-= indentation_amount
;
273 #if defined (SELECT_COMMAND)
275 print_select_command (select_command
)
276 SELECT_COM
*select_command
;
278 cprintf ("select %s in ", select_command
->name
->word
);
279 command_print_word_list (select_command
->map_list
, " ");
282 indentation
+= indentation_amount
;
283 make_command_string_internal (select_command
->action
);
285 indentation
-= indentation_amount
;
288 #endif /* SELECT_COMMAND */
291 print_group_command (group_command
)
292 GROUP_COM
*group_command
;
294 group_command_nesting
++;
297 if (!inside_function_def
)
301 /* This is a group command { ... } inside of a function
302 definition, and should be handled as a `normal' group
303 command, using the current indentation. */
305 indentation
+= indentation_amount
;
308 make_command_string_internal (group_command
->command
);
312 if (group_command_nesting
)
314 indentation
-= indentation_amount
;
315 indent (indentation
);
321 group_command_nesting
--;
325 print_case_command (case_command
)
326 CASE_COM
*case_command
;
328 cprintf ("case %s in ", case_command
->word
->word
);
329 if (case_command
->clauses
)
330 print_case_clauses (case_command
->clauses
);
335 print_case_clauses (clauses
)
336 PATTERN_LIST
*clauses
;
338 indentation
+= indentation_amount
;
342 command_print_word_list (clauses
->patterns
, " | ");
344 indentation
+= indentation_amount
;
345 make_command_string_internal (clauses
->action
);
346 indentation
-= indentation_amount
;
348 clauses
= clauses
->next
;
350 indentation
-= indentation_amount
;
354 print_while_command (while_command
)
355 WHILE_COM
*while_command
;
357 print_until_or_while (while_command
, "while");
361 print_until_command (while_command
)
362 WHILE_COM
*while_command
;
364 print_until_or_while (while_command
, "until");
368 print_until_or_while (while_command
, which
)
369 WHILE_COM
*while_command
;
372 cprintf ("%s ", which
);
374 make_command_string_internal (while_command
->test
);
376 cprintf (" do\n"); /* was newline ("do\n"); */
377 indentation
+= indentation_amount
;
378 make_command_string_internal (while_command
->action
);
379 indentation
-= indentation_amount
;
385 print_if_command (if_command
)
390 make_command_string_internal (if_command
->test
);
393 indentation
+= indentation_amount
;
394 make_command_string_internal (if_command
->true_case
);
395 indentation
-= indentation_amount
;
397 if (if_command
->false_case
)
401 indentation
+= indentation_amount
;
402 make_command_string_internal (if_command
->false_case
);
403 indentation
-= indentation_amount
;
410 print_simple_command (simple_command
)
411 SIMPLE_COM
*simple_command
;
413 command_print_word_list (simple_command
->words
, " ");
415 if (simple_command
->redirects
)
418 print_redirection_list (simple_command
->redirects
);
423 print_redirection_list (redirects
)
428 print_redirection (redirects
);
429 redirects
= redirects
->next
;
436 print_redirection (redirect
)
439 int kill_leading
= 0;
440 int redirector
= redirect
->redirector
;
441 WORD_DESC
*redirectee
= redirect
->redirectee
.filename
;
442 int redir_fd
= redirect
->redirectee
.dest
;
444 switch (redirect
->instruction
)
446 case r_output_direction
:
448 cprintf ("%d", redirector
);
449 cprintf (">%s", redirectee
->word
);
452 case r_input_direction
:
454 cprintf ("%d", redirector
);
455 cprintf ("<%s", redirectee
->word
);
458 case r_inputa_direction
: /* Redirection created by the shell. */
464 cprintf ("%d", redirector
);
465 cprintf (">>%s", redirectee
->word
);
468 case r_deblank_reading_until
:
471 case r_reading_until
:
473 cprintf ("%d", redirector
);
474 /* If the here document delimiter is quoted, single-quote it. */
475 if (redirect
->redirectee
.filename
->quoted
)
478 x
= single_quote (redirect
->here_doc_eof
);
479 cprintf ("<<%s%s\n", kill_leading
? "-" : "", x
);
483 cprintf ("<<%s%s\n", kill_leading
? "-" : "", redirect
->here_doc_eof
);
485 redirect
->redirectee
.filename
->word
, redirect
->here_doc_eof
);
488 case r_duplicating_input
:
489 cprintf ("%d<&%d", redirector
, redir_fd
);
492 case r_duplicating_output
:
493 cprintf ("%d>&%d", redirector
, redir_fd
);
496 case r_duplicating_input_word
:
497 cprintf ("%d<&%s", redirector
, redirectee
->word
);
500 case r_duplicating_output_word
:
501 cprintf ("%d>&%s", redirector
, redirectee
->word
);
505 cprintf ("%d>&-", redirector
);
509 cprintf (">&%s", redirectee
->word
);
514 cprintf ("%d", redirector
);
515 cprintf ("<>%s", redirectee
->word
);
520 cprintf ("%d", redirector
);
521 cprintf (">|%s", redirectee
->word
);
529 inside_function_def
= 0;
534 print_function_def (func
)
537 cprintf ("function %s () \n", func
->name
->word
);
538 add_unwind_protect (reset_locals
, 0);
540 indent (indentation
);
543 inside_function_def
++;
544 indentation
+= indentation_amount
;
546 if (func
->command
->type
== cm_group
)
547 make_command_string_internal (func
->command
->value
.Group
->command
);
549 make_command_string_internal (func
->command
);
551 remove_unwind_protect ();
552 indentation
-= indentation_amount
;
553 inside_function_def
--;
558 /* Return the string representation of the named function.
559 NAME is the name of the function.
560 COMMAND is the function body. It should be a GROUP_COM.
561 MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
564 named_function_string (name
, command
, multi_line
)
570 int old_indent
= indentation
, old_amount
= indentation_amount
;
572 command_string_index
= 0;
575 cprintf ("%s ", name
);
582 indentation_amount
= 0;
587 indentation
+= indentation_amount
;
590 inside_function_def
++;
597 if (command
->type
== cm_group
)
598 make_command_string_internal (command
->value
.Group
->command
);
600 make_command_string_internal (command
);
602 indentation
= old_indent
;
603 indentation_amount
= old_amount
;
604 inside_function_def
--;
608 result
= the_printed_command
;
614 for (i
= 0; result
[i
]; i
++)
615 if (result
[i
] == '\n')
617 strcpy (result
+ i
, result
+ i
+ 1);
621 if (result
[2] == '\n') /* XXX -- experimental */
622 strcpy (result
+ 2, result
+ 3);
634 indent (indentation
);
635 if (string
&& *string
)
636 cprintf ("%s", string
);
650 if (command_string_index
> 0 && the_printed_command
[command_string_index
- 1] == '&')
655 #if !defined (HAVE_VARARGS_H)
656 /* How to make the string. */
658 cprintf (format
, arg1
, arg2
)
659 char *format
, *arg1
, *arg2
;
662 char char_arg
[2], *argp
, *args
[2];
663 int arg_len
, c
, arg_index
;
665 args
[arg_index
= 0] = arg1
;
668 arg_len
= strlen (format
);
669 the_printed_command_resize (arg_len
+ 1);
694 argp
= (char *)args
[arg_index
++];
695 arg_len
= strlen (argp
);
699 argp
= itos (pointer_to_int (args
[arg_index
]));
701 arg_len
= strlen (argp
);
706 char_arg
[0] = pointer_to_int (args
[arg_index
]);
713 programming_error ("cprintf: bad `%%' argument (%c)", c
);
718 the_printed_command_resize (arg_len
+ 1);
719 FASTCOPY (argp
, the_printed_command
+ command_string_index
, arg_len
);
720 command_string_index
+= arg_len
;
726 the_printed_command
[command_string_index
] = '\0';
729 #else /* We have support for varargs. */
731 /* How to make the string. */
737 char *control
, char_arg
[2], *argp
;
738 int digit_arg
, arg_len
, c
;
742 control
= va_arg (args
, char *);
744 arg_len
= strlen (control
);
745 the_printed_command_resize (arg_len
+ 1);
770 argp
= va_arg (args
, char *);
771 arg_len
= strlen (argp
);
775 digit_arg
= va_arg (args
, int);
776 argp
= itos (digit_arg
);
777 arg_len
= strlen (argp
);
782 char_arg
[0] = va_arg (args
, int);
788 programming_error ("cprintf: bad `%%' argument (%c)", c
);
794 the_printed_command_resize (arg_len
+ 1);
795 FASTCOPY (argp
, the_printed_command
+ command_string_index
, arg_len
);
796 command_string_index
+= arg_len
;
802 the_printed_command
[command_string_index
] = '\0';
804 #endif /* HAVE_VARARGS_H */
806 /* Ensure that there is enough space to stuff LENGTH characters into
807 THE_PRINTED_COMMAND. */
809 the_printed_command_resize (length
)
812 if (!the_printed_command
)
814 the_printed_command_size
= length
+ 1;
815 the_printed_command
= xmalloc (the_printed_command_size
);
816 command_string_index
= 0;
818 else if ((command_string_index
+ length
) >= the_printed_command_size
)
821 new = command_string_index
+ length
+ 1;
822 new = new + 2 * PRINTED_COMMAND_GROW_SIZE
- 1;
823 new -= new % PRINTED_COMMAND_GROW_SIZE
;
824 the_printed_command_size
= new;
825 the_printed_command
= xrealloc (the_printed_command
, the_printed_command_size
);