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