4b95d8f575bf293bbcda88e5478d515e40576304
[platform/upstream/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 */