]> git.ipfire.org Git - thirdparty/bash.git/blob - print_cmd.c
Imported from ../bash-2.0.tar.gz.
[thirdparty/bash.git] / print_cmd.c
1 /* print_command -- A way to make readable commands from a command tree. */
2 /* Copyright (C) 1989 Free Software Foundation, Inc.
3
4 This file is part of GNU Bash, the Bourne Again SHell.
5
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
9 version.
10
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
14 for more details.
15
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. */
19
20 #include "config.h"
21
22 #include <stdio.h>
23
24 #if defined (HAVE_UNISTD_H)
25 # include <unistd.h>
26 #endif
27
28 #if defined (PREFER_STDARG)
29 # include <stdarg.h>
30 #else
31 # if defined (PREFER_VARARGS)
32 # include <varargs.h>
33 # endif
34 #endif
35
36 #include "bashansi.h"
37
38 #include "shell.h"
39 #include "y.tab.h"
40 #include "stdc.h"
41 #include "builtins/common.h"
42
43 #if !defined (PRINTF_DECLARED)
44 extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
45 #endif
46
47 static int indentation;
48 static int indentation_amount = 4;
49
50 static void cprintf __P((char *, ...));
51
52 static void newline (), indent (), the_printed_command_resize ();
53 static void semicolon ();
54 static void xprintf ();
55
56 static void make_command_string_internal ();
57 static void command_print_word_list ();
58 static void print_case_clauses ();
59 static void print_redirection_list ();
60 static void print_redirection ();
61
62 static void print_for_command ();
63 #if defined (SELECT_COMMAND)
64 static void print_select_command ();
65 #endif
66 static void print_group_command ();
67 static void print_case_command ();
68 static void print_while_command ();
69 static void print_until_command ();
70 static void print_until_or_while ();
71 static void print_if_command ();
72 static void print_function_def ();
73
74 #define PRINTED_COMMAND_GROW_SIZE 1024
75
76 char *the_printed_command = (char *)NULL;
77 int the_printed_command_size = 0;
78 int command_string_index = 0;
79
80 /* Non-zero means the stuff being printed is inside of a function def. */
81 static int inside_function_def;
82 static int skip_this_indent;
83
84 /* The depth of the group commands that we are currently printing. This
85 includes the group command that is a function body. */
86 static int group_command_nesting;
87
88 /* Print COMMAND (a command tree) on standard output. */
89 void
90 print_command (command)
91 COMMAND *command;
92 {
93 command_string_index = 0;
94 printf ("%s", make_command_string (command));
95 }
96
97 /* Make a string which is the printed representation of the command
98 tree in COMMAND. We return this string. However, the string is
99 not consed, so you have to do that yourself if you want it to
100 remain around. */
101 char *
102 make_command_string (command)
103 COMMAND *command;
104 {
105 command_string_index = 0;
106 make_command_string_internal (command);
107 return (the_printed_command);
108 }
109
110 /* The internal function. This is the real workhorse. */
111 static void
112 make_command_string_internal (command)
113 COMMAND *command;
114 {
115 if (command == 0)
116 cprintf ("");
117 else
118 {
119 if (skip_this_indent)
120 skip_this_indent--;
121 else
122 indent (indentation);
123
124 if (command->flags & CMD_WANT_SUBSHELL)
125 cprintf ("( ");
126
127 if (command->flags & CMD_TIME_PIPELINE)
128 cprintf ("time ");
129
130 if (command->flags & CMD_INVERT_RETURN)
131 cprintf ("! ");
132
133 switch (command->type)
134 {
135 case cm_for:
136 print_for_command (command->value.For);
137 break;
138
139 #if defined (SELECT_COMMAND)
140 case cm_select:
141 print_select_command (command->value.Select);
142 break;
143 #endif
144
145 case cm_case:
146 print_case_command (command->value.Case);
147 break;
148
149 case cm_while:
150 print_while_command (command->value.While);
151 break;
152
153 case cm_until:
154 print_until_command (command->value.While);
155 break;
156
157 case cm_if:
158 print_if_command (command->value.If);
159 break;
160
161 case cm_simple:
162 print_simple_command (command->value.Simple);
163 break;
164
165 case cm_connection:
166
167 skip_this_indent++;
168 make_command_string_internal (command->value.Connection->first);
169
170 switch (command->value.Connection->connector)
171 {
172 case '&':
173 case '|':
174 {
175 char c = command->value.Connection->connector;
176 cprintf (" %c", c);
177 if (c != '&' || command->value.Connection->second)
178 {
179 cprintf (" ");
180 skip_this_indent++;
181 }
182 }
183 break;
184
185 case AND_AND:
186 cprintf (" && ");
187 if (command->value.Connection->second)
188 skip_this_indent++;
189 break;
190
191 case OR_OR:
192 cprintf (" || ");
193 if (command->value.Connection->second)
194 skip_this_indent++;
195 break;
196
197 case ';':
198 cprintf (";");
199
200 if (inside_function_def)
201 cprintf ("\n");
202 else
203 {
204 cprintf (" ");
205 if (command->value.Connection->second)
206 skip_this_indent++;
207 }
208 break;
209
210 default:
211 cprintf ("print_command: bad connector `%d'",
212 command->value.Connection->connector);
213 break;
214 }
215
216 make_command_string_internal (command->value.Connection->second);
217 break;
218
219 case cm_function_def:
220 print_function_def (command->value.Function_def);
221 break;
222
223 case cm_group:
224 print_group_command (command->value.Group);
225 break;
226
227 default:
228 programming_error ("print_command: bad command type `%d'", command->type);
229 break;
230 }
231
232 if (command->flags & CMD_WANT_SUBSHELL)
233 cprintf (" )");
234
235 if (command->redirects)
236 print_redirection_list (command->redirects);
237 }
238 }
239
240 static void
241 _print_word_list (list, separator, pfunc)
242 WORD_LIST *list;
243 char *separator;
244 VFunction *pfunc;
245 {
246 WORD_LIST *w;
247
248 for (w = list; w; w = w->next)
249 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
250 }
251
252 void
253 print_word_list (list, separator)
254 WORD_LIST *list;
255 char *separator;
256 {
257 _print_word_list (list, separator, xprintf);
258 }
259
260 /* A function to print the words of a simple command when set -x is on. */
261 void
262 xtrace_print_word_list (list)
263 WORD_LIST *list;
264 {
265 WORD_LIST *w;
266 char *t;
267
268 fprintf (stderr, "%s", indirection_level_string ());
269 for (w = list; w; w = w->next)
270 {
271 t = w->word->word;
272 if (t == 0 || *t == '\0')
273 fprintf (stderr, "''%s", w->next ? " " : "");
274 else if (contains_shell_metas (t))
275 fprintf (stderr, "'%s'%s", t, w->next ? " " : "");
276 else
277 fprintf (stderr, "%s%s", t, w->next ? " " : "");
278 }
279 fprintf (stderr, "\n");
280 }
281
282 static void
283 command_print_word_list (list, separator)
284 WORD_LIST *list;
285 char *separator;
286 {
287 _print_word_list (list, separator, cprintf);
288 }
289
290 static void
291 print_for_command (for_command)
292 FOR_COM *for_command;
293 {
294 cprintf ("for %s in ", for_command->name->word);
295 command_print_word_list (for_command->map_list, " ");
296 cprintf (";");
297 newline ("do\n");
298 indentation += indentation_amount;
299 make_command_string_internal (for_command->action);
300 semicolon ();
301 indentation -= indentation_amount;
302 newline ("done");
303 }
304
305 #if defined (SELECT_COMMAND)
306 static void
307 print_select_command (select_command)
308 SELECT_COM *select_command;
309 {
310 cprintf ("select %s in ", select_command->name->word);
311 command_print_word_list (select_command->map_list, " ");
312 cprintf (";");
313 newline ("do\n");
314 indentation += indentation_amount;
315 make_command_string_internal (select_command->action);
316 semicolon ();
317 indentation -= indentation_amount;
318 newline ("done");
319 }
320 #endif /* SELECT_COMMAND */
321
322 static void
323 print_group_command (group_command)
324 GROUP_COM *group_command;
325 {
326 group_command_nesting++;
327 cprintf ("{ ");
328
329 if (inside_function_def == 0)
330 skip_this_indent++;
331 else
332 {
333 /* This is a group command { ... } inside of a function
334 definition, and should be printed as a multiline group
335 command, using the current indentation. */
336 cprintf ("\n");
337 indentation += indentation_amount;
338 }
339
340 make_command_string_internal (group_command->command);
341
342 if (inside_function_def)
343 {
344 cprintf ("\n");
345 indentation -= indentation_amount;
346 indent (indentation);
347 }
348 else
349 {
350 semicolon ();
351 cprintf (" ");
352 }
353
354 cprintf ("}");
355
356 group_command_nesting--;
357 }
358
359 static void
360 print_case_command (case_command)
361 CASE_COM *case_command;
362 {
363 cprintf ("case %s in ", case_command->word->word);
364 if (case_command->clauses)
365 print_case_clauses (case_command->clauses);
366 newline ("esac");
367 }
368
369 static void
370 print_case_clauses (clauses)
371 PATTERN_LIST *clauses;
372 {
373 indentation += indentation_amount;
374 while (clauses)
375 {
376 newline ("");
377 command_print_word_list (clauses->patterns, " | ");
378 cprintf (")\n");
379 indentation += indentation_amount;
380 make_command_string_internal (clauses->action);
381 indentation -= indentation_amount;
382 newline (";;");
383 clauses = clauses->next;
384 }
385 indentation -= indentation_amount;
386 }
387
388 static void
389 print_while_command (while_command)
390 WHILE_COM *while_command;
391 {
392 print_until_or_while (while_command, "while");
393 }
394
395 static void
396 print_until_command (while_command)
397 WHILE_COM *while_command;
398 {
399 print_until_or_while (while_command, "until");
400 }
401
402 static void
403 print_until_or_while (while_command, which)
404 WHILE_COM *while_command;
405 char *which;
406 {
407 cprintf ("%s ", which);
408 skip_this_indent++;
409 make_command_string_internal (while_command->test);
410 semicolon ();
411 cprintf (" do\n"); /* was newline ("do\n"); */
412 indentation += indentation_amount;
413 make_command_string_internal (while_command->action);
414 indentation -= indentation_amount;
415 semicolon ();
416 newline ("done");
417 }
418
419 static void
420 print_if_command (if_command)
421 IF_COM *if_command;
422 {
423 cprintf ("if ");
424 skip_this_indent++;
425 make_command_string_internal (if_command->test);
426 semicolon ();
427 cprintf (" then\n");
428 indentation += indentation_amount;
429 make_command_string_internal (if_command->true_case);
430 indentation -= indentation_amount;
431
432 if (if_command->false_case)
433 {
434 semicolon ();
435 newline ("else\n");
436 indentation += indentation_amount;
437 make_command_string_internal (if_command->false_case);
438 indentation -= indentation_amount;
439 }
440 semicolon ();
441 newline ("fi");
442 }
443
444 void
445 print_simple_command (simple_command)
446 SIMPLE_COM *simple_command;
447 {
448 command_print_word_list (simple_command->words, " ");
449
450 if (simple_command->redirects)
451 {
452 cprintf (" ");
453 print_redirection_list (simple_command->redirects);
454 }
455 }
456
457 static void
458 print_redirection_list (redirects)
459 REDIRECT *redirects;
460 {
461 while (redirects)
462 {
463 print_redirection (redirects);
464 redirects = redirects->next;
465 if (redirects)
466 cprintf (" ");
467 }
468 }
469
470 static void
471 print_redirection (redirect)
472 REDIRECT *redirect;
473 {
474 int kill_leading = 0;
475 int redirector = redirect->redirector;
476 WORD_DESC *redirectee = redirect->redirectee.filename;
477 int redir_fd = redirect->redirectee.dest;
478
479 switch (redirect->instruction)
480 {
481 case r_output_direction:
482 if (redirector != 1)
483 cprintf ("%d", redirector);
484 cprintf (">%s", redirectee->word);
485 break;
486
487 case r_input_direction:
488 if (redirector != 0)
489 cprintf ("%d", redirector);
490 cprintf ("<%s", redirectee->word);
491 break;
492
493 case r_inputa_direction: /* Redirection created by the shell. */
494 cprintf ("&");
495 break;
496
497 case r_appending_to:
498 if (redirector != 1)
499 cprintf ("%d", redirector);
500 cprintf (">>%s", redirectee->word);
501 break;
502
503 case r_deblank_reading_until:
504 kill_leading++;
505 /* ... */
506 case r_reading_until:
507 if (redirector != 0)
508 cprintf ("%d", redirector);
509 /* If the here document delimiter is quoted, single-quote it. */
510 if (redirect->redirectee.filename->flags & W_QUOTED)
511 {
512 char *x;
513 x = single_quote (redirect->here_doc_eof);
514 cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
515 free (x);
516 }
517 else
518 cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
519 cprintf ("%s%s",
520 redirect->redirectee.filename->word, redirect->here_doc_eof);
521 break;
522
523 case r_duplicating_input:
524 cprintf ("%d<&%d", redirector, redir_fd);
525 break;
526
527 case r_duplicating_output:
528 cprintf ("%d>&%d", redirector, redir_fd);
529 break;
530
531 case r_duplicating_input_word:
532 cprintf ("%d<&%s", redirector, redirectee->word);
533 break;
534
535 case r_duplicating_output_word:
536 cprintf ("%d>&%s", redirector, redirectee->word);
537 break;
538
539 case r_close_this:
540 cprintf ("%d>&-", redirector);
541 break;
542
543 case r_err_and_out:
544 cprintf (">&%s", redirectee->word);
545 break;
546
547 case r_input_output:
548 if (redirector != 1)
549 cprintf ("%d", redirector);
550 cprintf ("<>%s", redirectee->word);
551 break;
552
553 case r_output_force:
554 if (redirector != 1)
555 cprintf ("%d", redirector);
556 cprintf (">|%s", redirectee->word);
557 break;
558 }
559 }
560
561 static void
562 reset_locals ()
563 {
564 inside_function_def = 0;
565 indentation = 0;
566 }
567
568 static void
569 print_function_def (func)
570 FUNCTION_DEF *func;
571 {
572 cprintf ("function %s () \n", func->name->word);
573 add_unwind_protect (reset_locals, 0);
574
575 indent (indentation);
576 cprintf ("{ \n");
577
578 inside_function_def++;
579 indentation += indentation_amount;
580
581 make_command_string_internal (func->command->type == cm_group
582 ? func->command->value.Group->command
583 : func->command);
584
585 remove_unwind_protect ();
586 indentation -= indentation_amount;
587 inside_function_def--;
588
589 newline ("}");
590 }
591
592 /* Return the string representation of the named function.
593 NAME is the name of the function.
594 COMMAND is the function body. It should be a GROUP_COM.
595 MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
596 */
597 char *
598 named_function_string (name, command, multi_line)
599 char *name;
600 COMMAND *command;
601 int multi_line;
602 {
603 char *result;
604 int old_indent, old_amount;
605
606 old_indent = indentation;
607 old_amount = indentation_amount;
608 command_string_index = 0;
609
610 if (name && *name)
611 cprintf ("%s ", name);
612
613 cprintf ("() ");
614
615 if (multi_line == 0)
616 {
617 indentation = 1;
618 indentation_amount = 0;
619 }
620 else
621 {
622 cprintf ("\n");
623 indentation += indentation_amount;
624 }
625
626 inside_function_def++;
627
628 cprintf (multi_line ? "{ \n" : "{ ");
629
630 make_command_string_internal (command->type == cm_group
631 ? command->value.Group->command
632 : command);
633
634 indentation = old_indent;
635 indentation_amount = old_amount;
636 inside_function_def--;
637
638 newline ("}");
639
640 result = the_printed_command;
641
642 if (!multi_line)
643 {
644 #if 0
645 register int i;
646 for (i = 0; result[i]; i++)
647 if (result[i] == '\n')
648 {
649 strcpy (result + i, result + i + 1);
650 --i;
651 }
652 #else
653 if (result[2] == '\n') /* XXX -- experimental */
654 strcpy (result + 2, result + 3);
655 #endif
656 }
657
658 return (result);
659 }
660
661 static void
662 newline (string)
663 char *string;
664 {
665 cprintf ("\n");
666 indent (indentation);
667 if (string && *string)
668 cprintf ("%s", string);
669 }
670
671 static char *indentation_string;
672 static int indentation_size;
673
674 static void
675 indent (amount)
676 int amount;
677 {
678 register int i;
679
680 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
681
682 for (i = 0; amount > 0; amount--)
683 indentation_string[i++] = ' ';
684 indentation_string[i] = '\0';
685 cprintf (indentation_string);
686 }
687
688 static void
689 semicolon ()
690 {
691 if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
692 return;
693 cprintf (";");
694 }
695
696 #if !defined (USE_VARARGS)
697 /* How to make the string. */
698 static void
699 cprintf (format, arg1, arg2)
700 char *format, *arg1, *arg2;
701 {
702 register char *s;
703 char char_arg[2], *argp, *args[2];
704 int arg_len, c, arg_index;
705
706 args[arg_index = 0] = arg1;
707 args[1] = arg2;
708
709 arg_len = strlen (format);
710 the_printed_command_resize (arg_len + 1);
711
712 char_arg[1] = '\0';
713 s = format;
714 while (s && *s)
715 {
716 int free_argp = 0;
717 c = *s++;
718 if (c != '%' || !*s)
719 {
720 argp = s;
721 arg_len = 1;
722 }
723 else
724 {
725 c = *s++;
726 switch (c)
727 {
728 case '%':
729 char_arg[0] = c;
730 argp = char_arg;
731 arg_len = 1;
732 break;
733
734 case 's':
735 argp = (char *)args[arg_index++];
736 arg_len = strlen (argp);
737 break;
738
739 case 'd':
740 argp = itos (pointer_to_int (args[arg_index]));
741 arg_index++;
742 arg_len = strlen (argp);
743 free_argp = 1;
744 break;
745
746 case 'c':
747 char_arg[0] = pointer_to_int (args[arg_index]);
748 arg_index++;
749 argp = char_arg;
750 arg_len = 1;
751 break;
752
753 default:
754 programming_error ("cprintf: bad `%%' argument (%c)", c);
755 }
756 }
757 if (argp)
758 {
759 the_printed_command_resize (arg_len + 1);
760 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
761 command_string_index += arg_len;
762 if (free_argp)
763 free (argp);
764 }
765 }
766
767 the_printed_command[command_string_index] = '\0';
768 }
769
770 #else /* We have support for varargs. */
771
772 /* How to make the string. */
773 static void
774 #if defined (PREFER_STDARG)
775 cprintf (char *control, ...)
776 #else
777 cprintf (control, va_alist)
778 char *control;
779 va_dcl
780 #endif
781 {
782 register char *s;
783 char char_arg[2], *argp;
784 int digit_arg, arg_len, c;
785 va_list args;
786
787 #if defined (PREFER_STDARG)
788 va_start (args, control);
789 #else
790 va_start (args);
791 #endif
792
793 arg_len = strlen (control);
794 the_printed_command_resize (arg_len + 1);
795
796 char_arg[1] = '\0';
797 s = control;
798 while (s && *s)
799 {
800 int free_argp;
801 free_argp = 0;
802 c = *s++;
803 argp = (char *)NULL;
804 if (c != '%' || !*s)
805 {
806 argp = s - 1;
807 arg_len = 1;
808 }
809 else
810 {
811 c = *s++;
812 switch (c)
813 {
814 case '%':
815 char_arg[0] = c;
816 argp = char_arg;
817 arg_len = 1;
818 break;
819
820 case 's':
821 argp = va_arg (args, char *);
822 arg_len = strlen (argp);
823 break;
824
825 case 'd':
826 digit_arg = va_arg (args, int);
827 argp = itos (digit_arg);
828 arg_len = strlen (argp);
829 free_argp = 1;
830 break;
831
832 case 'c':
833 char_arg[0] = va_arg (args, int);
834 argp = char_arg;
835 arg_len = 1;
836 break;
837
838 default:
839 programming_error ("cprintf: bad `%%' argument (%c)", c);
840 /*NOTREACHED*/
841 }
842 }
843
844 if (argp && arg_len)
845 {
846 the_printed_command_resize (arg_len + 1);
847 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
848 command_string_index += arg_len;
849 if (free_argp)
850 free (argp);
851 }
852 }
853
854 the_printed_command[command_string_index] = '\0';
855 }
856 #endif /* HAVE_VARARGS_H */
857
858 /* Ensure that there is enough space to stuff LENGTH characters into
859 THE_PRINTED_COMMAND. */
860 static void
861 the_printed_command_resize (length)
862 int length;
863 {
864 if (!the_printed_command)
865 {
866 the_printed_command_size = length + 1;
867 the_printed_command = xmalloc (the_printed_command_size);
868 command_string_index = 0;
869 }
870 else if ((command_string_index + length) >= the_printed_command_size)
871 {
872 int new;
873 new = command_string_index + length + 1;
874 new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
875 new -= new % PRINTED_COMMAND_GROW_SIZE;
876 the_printed_command_size = new;
877 the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
878 }
879 }
880
881 #if defined (HAVE_VFPRINTF)
882
883 static void
884 xprintf (va_alist)
885 va_dcl
886 {
887 va_list args;
888 char *format;
889
890 va_start (args);
891 format = va_arg (args, char *);
892 vfprintf (stdout, format, args);
893 va_end (args);
894 }
895
896 #else
897
898 static void
899 xprintf (format, arg1, arg2, arg3, arg4, arg5)
900 char *format;
901 {
902 printf (format, arg1, arg2, arg3, arg4, arg5);
903 }
904
905 #endif /* !HAVE_VFPRINTF */