4aee8d3c52830346d954b47f40fc8a7e44f651af
[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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
19
20 #include "config.h"
21
22 #include <stdio.h>
23
24 #if defined (HAVE_UNISTD_H)
25 #  ifdef _MINIX
26 #    include <sys/types.h>
27 #  endif
28 #  include <unistd.h>
29 #endif
30
31 #if defined (PREFER_STDARG)
32 #  include <stdarg.h>
33 #else
34 #  if defined (PREFER_VARARGS)
35 #    include <varargs.h>
36 #  endif
37 #endif
38
39 #include "bashansi.h"
40
41 #include "shell.h"
42 #include <y.tab.h>      /* use <...> so we pick it up from the build directory */
43 #include "stdc.h"
44 #include "builtins/common.h"
45
46 #if !HAVE_DECL_PRINTF
47 extern int printf __P((const char *, ...));     /* Yuck.  Double yuck. */
48 #endif
49
50 static int indentation;
51 static int indentation_amount = 4;
52
53 #if defined (PREFER_STDARG)
54 typedef void PFUNC __P((const char *, ...));
55
56 static void cprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
57 static void xprintf __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
58 #else
59 #define PFUNC VFunction
60 static void cprintf ();
61 static void xprintf ();
62 #endif
63
64 static void reset_locals __P((void));
65 static void newline __P((char *));
66 static void indent __P((int));
67 static void semicolon __P((void));
68 static void the_printed_command_resize __P((int));
69
70 static void make_command_string_internal __P((COMMAND *));
71 static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
72 static void command_print_word_list __P((WORD_LIST *, char *));
73 static void print_case_clauses __P((PATTERN_LIST *));
74 static void print_redirection_list __P((REDIRECT *));
75 static void print_redirection __P((REDIRECT *));
76
77 static void print_for_command __P((FOR_COM *));
78 #if defined (ARITH_FOR_COMMAND)
79 static void print_arith_for_command __P((ARITH_FOR_COM *));
80 #endif
81 #if defined (SELECT_COMMAND)
82 static void print_select_command __P((SELECT_COM *));
83 #endif
84 static void print_group_command __P((GROUP_COM *));
85 static void print_case_command __P((CASE_COM *));
86 static void print_while_command __P((WHILE_COM *));
87 static void print_until_command __P((WHILE_COM *));
88 static void print_until_or_while __P((WHILE_COM *, char *));
89 static void print_if_command __P((IF_COM *));
90 #if defined (DPAREN_ARITHMETIC)
91 static void print_arith_command __P((ARITH_COM *));
92 #endif
93 #if defined (COND_COMMAND)
94 static void print_cond_node __P((COND_COM *));
95 static void print_cond_command __P((COND_COM *));
96 #endif
97 static void print_function_def __P((FUNCTION_DEF *));
98
99 #define PRINTED_COMMAND_INITIAL_SIZE 64
100 #define PRINTED_COMMAND_GROW_SIZE 128
101
102 char *the_printed_command = (char *)NULL;
103 int the_printed_command_size = 0;
104 int command_string_index = 0;
105
106 /* Non-zero means the stuff being printed is inside of a function def. */
107 static int inside_function_def;
108 static int skip_this_indent;
109 static int was_heredoc;
110
111 /* The depth of the group commands that we are currently printing.  This
112    includes the group command that is a function body. */
113 static int group_command_nesting;
114
115 /* Print COMMAND (a command tree) on standard output. */
116 void
117 print_command (command)
118      COMMAND *command;
119 {
120   command_string_index = 0;
121   printf ("%s", make_command_string (command));
122 }
123
124 /* Make a string which is the printed representation of the command
125    tree in COMMAND.  We return this string.  However, the string is
126    not consed, so you have to do that yourself if you want it to
127    remain around. */
128 char *
129 make_command_string (command)
130      COMMAND *command;
131 {
132   command_string_index = was_heredoc = 0;
133   make_command_string_internal (command);
134   return (the_printed_command);
135 }
136
137 /* The internal function.  This is the real workhorse. */
138 static void
139 make_command_string_internal (command)
140      COMMAND *command;
141 {
142   if (command == 0)
143     cprintf ("");
144   else
145     {
146       if (skip_this_indent)
147         skip_this_indent--;
148       else
149         indent (indentation);
150
151       if (command->flags & CMD_TIME_PIPELINE)
152         {
153           cprintf ("time ");
154           if (command->flags & CMD_TIME_POSIX)
155             cprintf ("-p ");
156         }
157
158       if (command->flags & CMD_INVERT_RETURN)
159         cprintf ("! ");
160
161       switch (command->type)
162         {
163         case cm_for:
164           print_for_command (command->value.For);
165           break;
166
167 #if defined (ARITH_FOR_COMMAND)
168         case cm_arith_for:
169           print_arith_for_command (command->value.ArithFor);
170           break;
171 #endif
172
173 #if defined (SELECT_COMMAND)
174         case cm_select:
175           print_select_command (command->value.Select);
176           break;
177 #endif
178
179         case cm_case:
180           print_case_command (command->value.Case);
181           break;
182
183         case cm_while:
184           print_while_command (command->value.While);
185           break;
186
187         case cm_until:
188           print_until_command (command->value.While);
189           break;
190
191         case cm_if:
192           print_if_command (command->value.If);
193           break;
194
195 #if defined (DPAREN_ARITHMETIC)
196         case cm_arith:
197           print_arith_command (command->value.Arith);
198           break;
199 #endif
200
201 #if defined (COND_COMMAND)
202         case cm_cond:
203           print_cond_command (command->value.Cond);
204           break;
205 #endif
206
207         case cm_simple:
208           print_simple_command (command->value.Simple);
209           break;
210
211         case cm_connection:
212
213           skip_this_indent++;
214           make_command_string_internal (command->value.Connection->first);
215
216           switch (command->value.Connection->connector)
217             {
218             case '&':
219             case '|':
220               {
221                 char c = command->value.Connection->connector;
222                 cprintf (" %c", c);
223                 if (c != '&' || command->value.Connection->second)
224                   {
225                     cprintf (" ");
226                     skip_this_indent++;
227                   }
228               }
229               break;
230
231             case AND_AND:
232               cprintf (" && ");
233               if (command->value.Connection->second)
234                 skip_this_indent++;
235               break;
236
237             case OR_OR:
238               cprintf (" || ");
239               if (command->value.Connection->second)
240                 skip_this_indent++;
241               break;
242
243             case ';':
244               if (was_heredoc == 0)
245                 cprintf (";");
246               else
247                 was_heredoc = 0;
248
249               if (inside_function_def)
250                 cprintf ("\n");
251               else
252                 {
253                   cprintf (" ");
254                   if (command->value.Connection->second)
255                     skip_this_indent++;
256                 }
257               break;
258
259             default:
260               cprintf ("print_command: bad connector `%d'",
261                        command->value.Connection->connector);
262               break;
263             }
264
265           make_command_string_internal (command->value.Connection->second);
266           break;
267
268         case cm_function_def:
269           print_function_def (command->value.Function_def);
270           break;
271
272         case cm_group:
273           print_group_command (command->value.Group);
274           break;
275
276         case cm_subshell:
277           cprintf ("( ");
278           skip_this_indent++;
279           make_command_string_internal (command->value.Subshell->command);
280           cprintf (" )");
281           break;
282
283         default:
284           command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
285           break;
286         }
287
288
289       if (command->redirects)
290         {
291           cprintf (" ");
292           print_redirection_list (command->redirects);
293         }
294     }
295 }
296
297 static void
298 _print_word_list (list, separator, pfunc)
299      WORD_LIST *list;
300      char *separator;
301      PFUNC *pfunc;
302 {
303   WORD_LIST *w;
304
305   for (w = list; w; w = w->next)
306     (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
307 }
308
309 void
310 print_word_list (list, separator)
311      WORD_LIST *list;
312      char *separator;
313 {
314   _print_word_list (list, separator, xprintf);
315 }
316
317 /* A function to print the words of a simple command when set -x is on. */
318 void
319 xtrace_print_word_list (list)
320      WORD_LIST *list;
321 {
322   WORD_LIST *w;
323   char *t, *x;
324
325   fprintf (stderr, "%s", indirection_level_string ());
326   for (w = list; w; w = w->next)
327     {
328       t = w->word->word;
329       if (t == 0 || *t == '\0')
330         fprintf (stderr, "''%s", w->next ? " " : "");
331       else if (sh_contains_shell_metas (t))
332         {
333           x = sh_single_quote (t);
334           fprintf (stderr, "%s%s", x, w->next ? " " : "");
335           free (x);
336         }
337       else
338         fprintf (stderr, "%s%s", t, w->next ? " " : "");
339     }
340   fprintf (stderr, "\n");
341 }
342
343 static void
344 command_print_word_list (list, separator)
345      WORD_LIST *list;
346      char *separator;
347 {
348   _print_word_list (list, separator, cprintf);
349 }
350
351 static void
352 print_for_command (for_command)
353      FOR_COM *for_command;
354 {
355   cprintf ("for %s in ", for_command->name->word);
356   command_print_word_list (for_command->map_list, " ");
357   cprintf (";");
358   newline ("do\n");
359   indentation += indentation_amount;
360   make_command_string_internal (for_command->action);
361   semicolon ();
362   indentation -= indentation_amount;
363   newline ("done");
364 }
365
366 #if defined (ARITH_FOR_COMMAND)
367 static void
368 print_arith_for_command (arith_for_command)
369      ARITH_FOR_COM *arith_for_command;
370 {
371   cprintf ("for (( ");
372   command_print_word_list (arith_for_command->init, " ");
373   cprintf (" ; ");
374   command_print_word_list (arith_for_command->test, " ");
375   cprintf (" ; ");
376   command_print_word_list (arith_for_command->step, " ");
377   cprintf (" ))");
378   newline ("do\n");
379   indentation += indentation_amount;
380   make_command_string_internal (arith_for_command->action);
381   semicolon ();
382   indentation -= indentation_amount;
383   newline ("done");
384 }
385 #endif /* ARITH_FOR_COMMAND */
386
387 #if defined (SELECT_COMMAND)
388 static void
389 print_select_command (select_command)
390      SELECT_COM *select_command;
391 {
392   cprintf ("select %s in ", select_command->name->word);
393   command_print_word_list (select_command->map_list, " ");
394   cprintf (";");
395   newline ("do\n");
396   indentation += indentation_amount;
397   make_command_string_internal (select_command->action);
398   semicolon ();
399   indentation -= indentation_amount;
400   newline ("done");
401 }
402 #endif /* SELECT_COMMAND */
403
404 static void
405 print_group_command (group_command)
406      GROUP_COM *group_command;
407 {
408   group_command_nesting++;
409   cprintf ("{ ");
410
411   if (inside_function_def == 0)
412     skip_this_indent++;
413   else
414     {
415       /* This is a group command { ... } inside of a function
416          definition, and should be printed as a multiline group
417          command, using the current indentation. */
418       cprintf ("\n");
419       indentation += indentation_amount;
420     }
421
422   make_command_string_internal (group_command->command);
423
424   if (inside_function_def)
425     {
426       cprintf ("\n");
427       indentation -= indentation_amount;
428       indent (indentation);
429     }
430   else
431     {
432       semicolon ();
433       cprintf (" ");
434     }
435
436   cprintf ("}");
437
438   group_command_nesting--;
439 }
440
441 static void
442 print_case_command (case_command)
443      CASE_COM *case_command;
444 {
445   cprintf ("case %s in ", case_command->word->word);
446   if (case_command->clauses)
447     print_case_clauses (case_command->clauses);
448   newline ("esac");
449 }
450
451 static void
452 print_case_clauses (clauses)
453      PATTERN_LIST *clauses;
454 {
455   indentation += indentation_amount;
456   while (clauses)
457     {
458       newline ("");
459       command_print_word_list (clauses->patterns, " | ");
460       cprintf (")\n");
461       indentation += indentation_amount;
462       make_command_string_internal (clauses->action);
463       indentation -= indentation_amount;
464       newline (";;");
465       clauses = clauses->next;
466     }
467   indentation -= indentation_amount;
468 }
469
470 static void
471 print_while_command (while_command)
472      WHILE_COM *while_command;
473 {
474   print_until_or_while (while_command, "while");
475 }
476
477 static void
478 print_until_command (while_command)
479      WHILE_COM *while_command;
480 {
481   print_until_or_while (while_command, "until");
482 }
483
484 static void
485 print_until_or_while (while_command, which)
486      WHILE_COM *while_command;
487      char *which;
488 {
489   cprintf ("%s ", which);
490   skip_this_indent++;
491   make_command_string_internal (while_command->test);
492   semicolon ();
493   cprintf (" do\n");    /* was newline ("do\n"); */
494   indentation += indentation_amount;
495   make_command_string_internal (while_command->action);
496   indentation -= indentation_amount;
497   semicolon ();
498   newline ("done");
499 }
500
501 static void
502 print_if_command (if_command)
503      IF_COM *if_command;
504 {
505   cprintf ("if ");
506   skip_this_indent++;
507   make_command_string_internal (if_command->test);
508   semicolon ();
509   cprintf (" then\n");
510   indentation += indentation_amount;
511   make_command_string_internal (if_command->true_case);
512   indentation -= indentation_amount;
513
514   if (if_command->false_case)
515     {
516       semicolon ();
517       newline ("else\n");
518       indentation += indentation_amount;
519       make_command_string_internal (if_command->false_case);
520       indentation -= indentation_amount;
521     }
522   semicolon ();
523   newline ("fi");
524 }
525
526 #if defined (DPAREN_ARITHMETIC)
527 static void
528 print_arith_command (arith_command)
529      ARITH_COM *arith_command;
530 {
531   cprintf ("(( ");
532   command_print_word_list (arith_command->exp, " ");
533   cprintf (" ))");
534 }
535 #endif
536
537 #if defined (COND_COMMAND)
538 static void
539 print_cond_node (cond)
540      COND_COM *cond;
541 {
542   if (cond->flags & CMD_INVERT_RETURN)
543     cprintf ("! ");
544
545   if (cond->type == COND_EXPR)
546     {
547       cprintf ("( ");
548       print_cond_node (cond->left);
549       cprintf (" )");
550     }
551   else if (cond->type == COND_AND)
552     {
553       print_cond_node (cond->left);
554       cprintf (" && ");
555       print_cond_node (cond->right);
556     }
557   else if (cond->type == COND_OR)
558     {
559       print_cond_node (cond->left);
560       cprintf (" || ");
561       print_cond_node (cond->right);
562     }
563   else if (cond->type == COND_UNARY)
564     {
565       cprintf ("%s", cond->op->word);
566       cprintf (" ");
567       print_cond_node (cond->left);
568     }
569   else if (cond->type == COND_BINARY)
570     {
571       print_cond_node (cond->left);
572       cprintf (" ");
573       cprintf ("%s", cond->op->word);
574       cprintf (" ");
575       print_cond_node (cond->right);
576     }
577   else if (cond->type == COND_TERM)
578     {
579       cprintf ("%s", cond->op->word);           /* need to add quoting here */
580     }
581 }
582
583 static void
584 print_cond_command (cond)
585      COND_COM *cond;
586 {
587   cprintf ("[[ ");
588   print_cond_node (cond);
589   cprintf (" ]]");
590 }
591
592 #ifdef DEBUG
593 void
594 debug_print_cond_command (cond)
595      COND_COM *cond;
596 {
597   fprintf (stderr, "DEBUG: ");
598   command_string_index = 0;
599   print_cond_command (cond);
600   fprintf (stderr, "%s\n", the_printed_command);
601 }
602 #endif
603
604 void
605 xtrace_print_cond_term (type, invert, op, arg1, arg2)
606      int type, invert;
607      WORD_DESC *op;
608      char *arg1, *arg2;
609 {
610   command_string_index = 0;
611   fprintf (stderr, "%s", indirection_level_string ());
612   fprintf (stderr, "[[ ");
613   if (invert)
614     fprintf (stderr, "! ");
615
616   if (type == COND_UNARY)
617     {
618       fprintf (stderr, "%s ", op->word);
619       fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
620     }
621   else if (type == COND_BINARY)
622     {
623       fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
624       fprintf (stderr, " %s ", op->word);
625       fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
626     }
627
628   fprintf (stderr, " ]]\n");
629 }         
630 #endif /* COND_COMMAND */
631
632 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
633 /* A function to print the words of an arithmetic command when set -x is on. */
634 void
635 xtrace_print_arith_cmd (list)
636      WORD_LIST *list;
637 {
638   WORD_LIST *w;
639
640   fprintf (stderr, "%s", indirection_level_string ());
641   fprintf (stderr, "(( ");
642   for (w = list; w; w = w->next)
643     fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
644   fprintf (stderr, " ))\n");
645 }
646 #endif
647
648 void
649 print_simple_command (simple_command)
650      SIMPLE_COM *simple_command;
651 {
652   command_print_word_list (simple_command->words, " ");
653
654   if (simple_command->redirects)
655     {
656       cprintf (" ");
657       print_redirection_list (simple_command->redirects);
658     }
659 }
660
661 static void
662 print_redirection_list (redirects)
663      REDIRECT *redirects;
664 {
665   REDIRECT *heredocs, *hdtail, *newredir;
666
667   heredocs = (REDIRECT *)NULL;
668   hdtail = heredocs;
669
670   was_heredoc = 0;
671   while (redirects)
672     {
673       /* Defer printing the here documents until we've printed the
674          rest of the redirections. */
675       if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
676         {
677           newredir = copy_redirect (redirects);
678           newredir->next = (REDIRECT *)NULL;
679           if (heredocs)
680             {
681               hdtail->next = newredir;
682               hdtail = newredir;
683             }
684           else
685             hdtail = heredocs = newredir;
686         }
687       else
688         print_redirection (redirects);
689
690       redirects = redirects->next;
691       if (redirects)
692         cprintf (" ");
693     }
694
695   /* Now that we've printed all the other redirections (on one line),
696      print the here documents. */
697   if (heredocs)
698     {
699       cprintf (" "); 
700       for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
701         {
702           print_redirection (hdtail);
703           cprintf ("\n");
704         }
705       dispose_redirects (heredocs);
706       was_heredoc = 1;
707     }
708 }
709
710 static void
711 print_redirection (redirect)
712      REDIRECT *redirect;
713 {
714   int kill_leading, redirector, redir_fd;
715   WORD_DESC *redirectee;
716
717   kill_leading = 0;
718   redirectee = redirect->redirectee.filename;
719   redirector = redirect->redirector;
720   redir_fd = redirect->redirectee.dest;
721
722   switch (redirect->instruction)
723     {
724     case r_output_direction:
725       if (redirector != 1)
726         cprintf ("%d", redirector);
727       cprintf (">%s", redirectee->word);
728       break;
729
730     case r_input_direction:
731       if (redirector != 0)
732         cprintf ("%d", redirector);
733       cprintf ("<%s", redirectee->word);
734       break;
735
736     case r_inputa_direction:    /* Redirection created by the shell. */
737       cprintf ("&");
738       break;
739
740     case r_appending_to:
741       if (redirector != 1)
742         cprintf ("%d", redirector);
743       cprintf (">>%s", redirectee->word);
744       break;
745
746     case r_deblank_reading_until:
747       kill_leading++;
748       /* ... */
749     case r_reading_until:
750       if (redirector != 0)
751         cprintf ("%d", redirector);
752       /* If the here document delimiter is quoted, single-quote it. */
753       if (redirect->redirectee.filename->flags & W_QUOTED)
754         {
755           char *x;
756           x = sh_single_quote (redirect->here_doc_eof);
757           cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
758           free (x);
759         }
760       else
761         cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
762       cprintf ("%s%s",
763                redirect->redirectee.filename->word, redirect->here_doc_eof);
764       break;
765
766     case r_duplicating_input:
767       cprintf ("%d<&%d", redirector, redir_fd);
768       break;
769
770     case r_duplicating_output:
771       cprintf ("%d>&%d", redirector, redir_fd);
772       break;
773
774     case r_duplicating_input_word:
775       cprintf ("%d<&%s", redirector, redirectee->word);
776       break;
777
778     case r_duplicating_output_word:
779       cprintf ("%d>&%s", redirector, redirectee->word);
780       break;
781
782     case r_close_this:
783       cprintf ("%d>&-", redirector);
784       break;
785
786     case r_err_and_out:
787       cprintf (">&%s", redirectee->word);
788       break;
789
790     case r_input_output:
791       if (redirector != 1)
792         cprintf ("%d", redirector);
793       cprintf ("<>%s", redirectee->word);
794       break;
795
796     case r_output_force:
797       if (redirector != 1)
798         cprintf ("%d", redirector);
799       cprintf (">|%s", redirectee->word);
800       break;
801     }
802 }
803
804 static void
805 reset_locals ()
806 {
807   inside_function_def = 0;
808   indentation = 0;
809 }
810
811 static void
812 print_function_def (func)
813      FUNCTION_DEF *func;
814 {
815   COMMAND *cmdcopy;
816   REDIRECT *func_redirects;
817
818   func_redirects = NULL;
819   cprintf ("function %s () \n", func->name->word);
820   add_unwind_protect (reset_locals, 0);
821
822   indent (indentation);
823   cprintf ("{ \n");
824
825   inside_function_def++;
826   indentation += indentation_amount;
827
828   cmdcopy = copy_command (func->command);
829   if (cmdcopy->type == cm_group)
830     {
831       func_redirects = cmdcopy->redirects;
832       cmdcopy->redirects = (REDIRECT *)NULL;
833     }
834   make_command_string_internal (cmdcopy->type == cm_group
835                                         ? cmdcopy->value.Group->command
836                                         : cmdcopy);
837
838   remove_unwind_protect ();
839   indentation -= indentation_amount;
840   inside_function_def--;
841
842   if (func_redirects)
843     { /* { */
844       newline ("} ");
845       print_redirection_list (func_redirects);
846       cmdcopy->redirects = func_redirects;
847     }
848   else
849     newline ("}");
850
851   dispose_command (cmdcopy);
852 }
853
854 /* Return the string representation of the named function.
855    NAME is the name of the function.
856    COMMAND is the function body.  It should be a GROUP_COM.
857    MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
858   */
859 char *
860 named_function_string (name, command, multi_line)
861      char *name;
862      COMMAND *command;
863      int multi_line;
864 {
865   char *result;
866   int old_indent, old_amount;
867   COMMAND *cmdcopy;
868   REDIRECT *func_redirects;
869
870   old_indent = indentation;
871   old_amount = indentation_amount;
872   command_string_index = was_heredoc = 0;
873
874   if (name && *name)
875     cprintf ("%s ", name);
876
877   cprintf ("() ");
878
879   if (multi_line == 0)
880     {
881       indentation = 1;
882       indentation_amount = 0;
883     }
884   else
885     {
886       cprintf ("\n");
887       indentation += indentation_amount;
888     }
889
890   inside_function_def++;
891
892   cprintf (multi_line ? "{ \n" : "{ ");
893
894   cmdcopy = copy_command (command);
895   /* Take any redirections specified in the function definition (which should
896      apply to the function as a whole) and save them for printing later. */
897   func_redirects = (REDIRECT *)NULL;
898   if (cmdcopy->type == cm_group)
899     {
900       func_redirects = cmdcopy->redirects;
901       cmdcopy->redirects = (REDIRECT *)NULL;
902     }
903   make_command_string_internal (cmdcopy->type == cm_group
904                                         ? cmdcopy->value.Group->command
905                                         : cmdcopy);
906
907   indentation = old_indent;
908   indentation_amount = old_amount;
909   inside_function_def--;
910
911   if (func_redirects)
912     { /* { */
913       newline ("} ");
914       print_redirection_list (func_redirects);
915       cmdcopy->redirects = func_redirects;
916     }
917   else
918     newline ("}");
919
920   result = the_printed_command;
921
922   if (!multi_line)
923     {
924 #if 0
925       register int i;
926       for (i = 0; result[i]; i++)
927         if (result[i] == '\n')
928           {
929             strcpy (result + i, result + i + 1);
930             --i;
931           }
932 #else
933       if (result[2] == '\n')    /* XXX -- experimental */
934         strcpy (result + 2, result + 3);
935 #endif
936     }
937
938   dispose_command (cmdcopy);
939
940   return (result);
941 }
942
943 static void
944 newline (string)
945      char *string;
946 {
947   cprintf ("\n");
948   indent (indentation);
949   if (string && *string)
950     cprintf ("%s", string);
951 }
952
953 static char *indentation_string;
954 static int indentation_size;
955
956 static void
957 indent (amount)
958      int amount;
959 {
960   register int i;
961
962   RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
963
964   for (i = 0; amount > 0; amount--)
965     indentation_string[i++] = ' ';
966   indentation_string[i] = '\0';
967   cprintf (indentation_string);
968 }
969
970 static void
971 semicolon ()
972 {
973   if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
974     return;
975   cprintf (";");
976 }
977
978 #if !defined (USE_VARARGS)
979 /* How to make the string. */
980 static void
981 cprintf (format, arg1, arg2)
982      const char *format;
983      char *arg1, *arg2;
984 {
985   register const char *s;
986   char char_arg[2], *argp, *args[2], intbuf[INT_STRLEN_BOUND(int) + 1];
987   int arg_len, c, arg_index, digit_arg;
988
989   args[arg_index = 0] = arg1;
990   args[1] = arg2;
991
992   arg_len = strlen (format);
993   the_printed_command_resize (arg_len + 1);
994
995   char_arg[1] = '\0';
996   s = format;
997   while (s && *s)
998     {
999       int free_argp = 0;
1000       c = *s++;
1001       if (c != '%' || !*s)
1002         {
1003           char_arg[0] = c;
1004           argp = char_arg;
1005           arg_len = 1;
1006         }
1007       else
1008         {
1009           c = *s++;
1010           switch (c)
1011             {
1012             case '%':
1013               char_arg[0] = c;
1014               argp = char_arg;
1015               arg_len = 1;
1016               break;
1017
1018             case 's':
1019               argp = (char *)args[arg_index++];
1020               arg_len = strlen (argp);
1021               break;
1022
1023             case 'd':
1024               /* Represent an out-of-range file descriptor with an out-of-range
1025                  integer value.  We can do this because the only use of `%d' in
1026                  the calls to cprintf is to output a file descriptor number for
1027                  a redirection. */
1028               digit_arg = pointer_to_int (args[arg_index]);
1029               if (digit_arg < 0)
1030                 {
1031                   sprintf (intbuf, "%u", (unsigned)-1);
1032                   argp = intbuf;
1033                 }
1034               else
1035                 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1036               arg_index++;
1037               arg_len = strlen (argp);
1038               break;
1039
1040             case 'c':
1041               char_arg[0] = pointer_to_int (args[arg_index]);
1042               arg_index++;
1043               argp = char_arg;
1044               arg_len = 1;
1045               break;
1046
1047             default:
1048               programming_error ("cprintf: bad `%%' argument (%c)", c);
1049             }
1050         }
1051       if (argp)
1052         {
1053           the_printed_command_resize (arg_len + 1);
1054           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1055           command_string_index += arg_len;
1056           if (free_argp)
1057             free (argp);
1058         }
1059     }
1060
1061   the_printed_command[command_string_index] = '\0';
1062 }
1063
1064 #else /* We have support for varargs. */
1065
1066 /* How to make the string. */
1067 static void
1068 #if defined (PREFER_STDARG)
1069 cprintf (const char *control, ...)
1070 #else
1071 cprintf (control, va_alist)
1072      const char *control;
1073      va_dcl
1074 #endif
1075 {
1076   register const char *s;
1077   char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
1078   int digit_arg, arg_len, c;
1079   va_list args;
1080
1081 #if defined (PREFER_STDARG)
1082   va_start (args, control);
1083 #else
1084   va_start (args);
1085 #endif
1086
1087   arg_len = strlen (control);
1088   the_printed_command_resize (arg_len + 1);
1089
1090   char_arg[1] = '\0';
1091   s = control;
1092   while (s && *s)
1093     {
1094       int free_argp;
1095       free_argp = 0;
1096       c = *s++;
1097       argp = (char *)NULL;
1098       if (c != '%' || !*s)
1099         {
1100           char_arg[0] = c;
1101           argp = char_arg;
1102           arg_len = 1;
1103         }
1104       else
1105         {
1106           c = *s++;
1107           switch (c)
1108             {
1109             case '%':
1110               char_arg[0] = c;
1111               argp = char_arg;
1112               arg_len = 1;
1113               break;
1114
1115             case 's':
1116               argp = va_arg (args, char *);
1117               arg_len = strlen (argp);
1118               break;
1119
1120             case 'd':
1121               /* Represent an out-of-range file descriptor with an out-of-range
1122                  integer value.  We can do this because the only use of `%d' in
1123                  the calls to cprintf is to output a file descriptor number for
1124                  a redirection. */
1125               digit_arg = va_arg (args, int);
1126               if (digit_arg < 0)
1127                 {
1128                   sprintf (intbuf, "%u", (unsigned)-1);
1129                   argp = intbuf;
1130                 }
1131               else
1132                 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1133               arg_len = strlen (argp);
1134               break;
1135
1136             case 'c':
1137               char_arg[0] = va_arg (args, int);
1138               argp = char_arg;
1139               arg_len = 1;
1140               break;
1141
1142             default:
1143               programming_error ("cprintf: bad `%%' argument (%c)", c);
1144               /*NOTREACHED*/
1145             }
1146         }
1147
1148       if (argp && arg_len)
1149         {
1150           the_printed_command_resize (arg_len + 1);
1151           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1152           command_string_index += arg_len;
1153           if (free_argp)
1154             free (argp);
1155         }
1156     }
1157
1158   the_printed_command[command_string_index] = '\0';
1159 }
1160 #endif /* HAVE_VARARGS_H */
1161
1162 /* Ensure that there is enough space to stuff LENGTH characters into
1163    THE_PRINTED_COMMAND. */
1164 static void
1165 the_printed_command_resize (length)
1166      int length;
1167 {
1168   if (the_printed_command == 0)
1169     {
1170       the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1171       the_printed_command = (char *)xmalloc (the_printed_command_size);
1172       command_string_index = 0;
1173     }
1174   else if ((command_string_index + length) >= the_printed_command_size)
1175     {
1176       int new;
1177       new = command_string_index + length + 1;
1178
1179       /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1180       new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1181       the_printed_command_size = new;
1182
1183       the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
1184     }
1185 }
1186
1187 #if defined (HAVE_VPRINTF)
1188 /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1189      also available.'' */
1190
1191 static void
1192 #if defined (PREFER_STDARG)
1193 xprintf (const char *format, ...)
1194 #else
1195 xprintf (format, va_alist)
1196      const char *format;
1197      va_dcl
1198 #endif
1199 {
1200   va_list args;
1201
1202 #if defined (PREFER_STDARG)
1203   va_start (args, format);
1204 #else
1205   va_start (args);
1206 #endif
1207
1208   vfprintf (stdout, format, args);
1209   va_end (args);
1210 }
1211
1212 #else
1213
1214 static void
1215 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1216      const char *format;
1217 {
1218   printf (format, arg1, arg2, arg3, arg4, arg5);
1219 }
1220
1221 #endif /* !HAVE_VPRINTF */