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