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