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