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