Imported from ../bash-2.01.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;
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         fprintf (stderr, "'%s'%s", t, w->next ? " " : "");
289       else
290         fprintf (stderr, "%s%s", t, w->next ? " " : "");
291     }
292   fprintf (stderr, "\n");
293 }
294
295 static void
296 command_print_word_list (list, separator)
297      WORD_LIST *list;
298      char *separator;
299 {
300   _print_word_list (list, separator, cprintf);
301 }
302
303 static void
304 print_for_command (for_command)
305      FOR_COM *for_command;
306 {
307   cprintf ("for %s in ", for_command->name->word);
308   command_print_word_list (for_command->map_list, " ");
309   cprintf (";");
310   newline ("do\n");
311   indentation += indentation_amount;
312   make_command_string_internal (for_command->action);
313   semicolon ();
314   indentation -= indentation_amount;
315   newline ("done");
316 }
317
318 #if defined (SELECT_COMMAND)
319 static void
320 print_select_command (select_command)
321      SELECT_COM *select_command;
322 {
323   cprintf ("select %s in ", select_command->name->word);
324   command_print_word_list (select_command->map_list, " ");
325   cprintf (";");
326   newline ("do\n");
327   indentation += indentation_amount;
328   make_command_string_internal (select_command->action);
329   semicolon ();
330   indentation -= indentation_amount;
331   newline ("done");
332 }
333 #endif /* SELECT_COMMAND */
334
335 static void
336 print_group_command (group_command)
337      GROUP_COM *group_command;
338 {
339   group_command_nesting++;
340   cprintf ("{ ");
341
342   if (inside_function_def == 0)
343     skip_this_indent++;
344   else
345     {
346       /* This is a group command { ... } inside of a function
347          definition, and should be printed as a multiline group
348          command, using the current indentation. */
349       cprintf ("\n");
350       indentation += indentation_amount;
351     }
352
353   make_command_string_internal (group_command->command);
354
355   if (inside_function_def)
356     {
357       cprintf ("\n");
358       indentation -= indentation_amount;
359       indent (indentation);
360     }
361   else
362     {
363       semicolon ();
364       cprintf (" ");
365     }
366
367   cprintf ("}");
368
369   group_command_nesting--;
370 }
371
372 static void
373 print_case_command (case_command)
374      CASE_COM *case_command;
375 {
376   cprintf ("case %s in ", case_command->word->word);
377   if (case_command->clauses)
378     print_case_clauses (case_command->clauses);
379   newline ("esac");
380 }
381
382 static void
383 print_case_clauses (clauses)
384      PATTERN_LIST *clauses;
385 {
386   indentation += indentation_amount;
387   while (clauses)
388     {
389       newline ("");
390       command_print_word_list (clauses->patterns, " | ");
391       cprintf (")\n");
392       indentation += indentation_amount;
393       make_command_string_internal (clauses->action);
394       indentation -= indentation_amount;
395       newline (";;");
396       clauses = clauses->next;
397     }
398   indentation -= indentation_amount;
399 }
400
401 static void
402 print_while_command (while_command)
403      WHILE_COM *while_command;
404 {
405   print_until_or_while (while_command, "while");
406 }
407
408 static void
409 print_until_command (while_command)
410      WHILE_COM *while_command;
411 {
412   print_until_or_while (while_command, "until");
413 }
414
415 static void
416 print_until_or_while (while_command, which)
417      WHILE_COM *while_command;
418      char *which;
419 {
420   cprintf ("%s ", which);
421   skip_this_indent++;
422   make_command_string_internal (while_command->test);
423   semicolon ();
424   cprintf (" do\n");    /* was newline ("do\n"); */
425   indentation += indentation_amount;
426   make_command_string_internal (while_command->action);
427   indentation -= indentation_amount;
428   semicolon ();
429   newline ("done");
430 }
431
432 static void
433 print_if_command (if_command)
434      IF_COM *if_command;
435 {
436   cprintf ("if ");
437   skip_this_indent++;
438   make_command_string_internal (if_command->test);
439   semicolon ();
440   cprintf (" then\n");
441   indentation += indentation_amount;
442   make_command_string_internal (if_command->true_case);
443   indentation -= indentation_amount;
444
445   if (if_command->false_case)
446     {
447       semicolon ();
448       newline ("else\n");
449       indentation += indentation_amount;
450       make_command_string_internal (if_command->false_case);
451       indentation -= indentation_amount;
452     }
453   semicolon ();
454   newline ("fi");
455 }
456
457 void
458 print_simple_command (simple_command)
459      SIMPLE_COM *simple_command;
460 {
461   command_print_word_list (simple_command->words, " ");
462
463   if (simple_command->redirects)
464     {
465       cprintf (" ");
466       print_redirection_list (simple_command->redirects);
467     }
468 }
469
470 static void
471 print_redirection_list (redirects)
472      REDIRECT *redirects;
473 {
474   REDIRECT *heredocs, *hdtail, *newredir;
475
476   heredocs = (REDIRECT *)NULL;
477   hdtail = heredocs;
478
479   was_heredoc = 0;
480   while (redirects)
481     {
482       /* Defer printing the here documents until we've printed the
483          rest of the redirections. */
484       if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
485         {
486           newredir = copy_redirect (redirects);
487           newredir->next = (REDIRECT *)NULL;
488           if (heredocs)
489             {
490               hdtail->next = newredir;
491               hdtail = newredir;
492             }
493           else
494             hdtail = heredocs = newredir;
495         }
496       else
497         print_redirection (redirects);
498
499       redirects = redirects->next;
500       if (redirects)
501         cprintf (" ");
502     }
503
504   /* Now that we've printed all the other redirections (on one line),
505      print the here documents. */
506   if (heredocs)
507     {
508       cprintf (" "); 
509       for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
510         {
511           print_redirection (hdtail);
512           cprintf ("\n");
513         }
514       dispose_redirects (heredocs);
515       was_heredoc = 1;
516     }
517 }
518
519 static void
520 print_redirection (redirect)
521      REDIRECT *redirect;
522 {
523   int kill_leading, redirector, redir_fd;
524   WORD_DESC *redirectee;
525
526   kill_leading = 0;
527   redirectee = redirect->redirectee.filename;
528   redirector = redirect->redirector;
529   redir_fd = redirect->redirectee.dest;
530
531   switch (redirect->instruction)
532     {
533     case r_output_direction:
534       if (redirector != 1)
535         cprintf ("%d", redirector);
536       cprintf (">%s", redirectee->word);
537       break;
538
539     case r_input_direction:
540       if (redirector != 0)
541         cprintf ("%d", redirector);
542       cprintf ("<%s", redirectee->word);
543       break;
544
545     case r_inputa_direction:    /* Redirection created by the shell. */
546       cprintf ("&");
547       break;
548
549     case r_appending_to:
550       if (redirector != 1)
551         cprintf ("%d", redirector);
552       cprintf (">>%s", redirectee->word);
553       break;
554
555     case r_deblank_reading_until:
556       kill_leading++;
557       /* ... */
558     case r_reading_until:
559       if (redirector != 0)
560         cprintf ("%d", redirector);
561       /* If the here document delimiter is quoted, single-quote it. */
562       if (redirect->redirectee.filename->flags & W_QUOTED)
563         {
564           char *x;
565           x = single_quote (redirect->here_doc_eof);
566           cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
567           free (x);
568         }
569       else
570         cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
571       cprintf ("%s%s",
572                redirect->redirectee.filename->word, redirect->here_doc_eof);
573       break;
574
575     case r_duplicating_input:
576       cprintf ("%d<&%d", redirector, redir_fd);
577       break;
578
579     case r_duplicating_output:
580       cprintf ("%d>&%d", redirector, redir_fd);
581       break;
582
583     case r_duplicating_input_word:
584       cprintf ("%d<&%s", redirector, redirectee->word);
585       break;
586
587     case r_duplicating_output_word:
588       cprintf ("%d>&%s", redirector, redirectee->word);
589       break;
590
591     case r_close_this:
592       cprintf ("%d>&-", redirector);
593       break;
594
595     case r_err_and_out:
596       cprintf (">&%s", redirectee->word);
597       break;
598
599     case r_input_output:
600       if (redirector != 1)
601         cprintf ("%d", redirector);
602       cprintf ("<>%s", redirectee->word);
603       break;
604
605     case r_output_force:
606       if (redirector != 1)
607         cprintf ("%d", redirector);
608       cprintf (">|%s", redirectee->word);
609       break;
610     }
611 }
612
613 static void
614 reset_locals ()
615 {
616   inside_function_def = 0;
617   indentation = 0;
618 }
619
620 static void
621 print_function_def (func)
622      FUNCTION_DEF *func;
623 {
624   cprintf ("function %s () \n", func->name->word);
625   add_unwind_protect (reset_locals, 0);
626
627   indent (indentation);
628   cprintf ("{ \n");
629
630   inside_function_def++;
631   indentation += indentation_amount;
632
633   make_command_string_internal (func->command->type == cm_group
634                                         ? func->command->value.Group->command
635                                         : func->command);
636
637   remove_unwind_protect ();
638   indentation -= indentation_amount;
639   inside_function_def--;
640
641   newline ("}");
642 }
643
644 /* Return the string representation of the named function.
645    NAME is the name of the function.
646    COMMAND is the function body.  It should be a GROUP_COM.
647    MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
648   */
649 char *
650 named_function_string (name, command, multi_line)
651      char *name;
652      COMMAND *command;
653      int multi_line;
654 {
655   char *result;
656   int old_indent, old_amount;
657
658   old_indent = indentation;
659   old_amount = indentation_amount;
660   command_string_index = was_heredoc = 0;
661
662   if (name && *name)
663     cprintf ("%s ", name);
664
665   cprintf ("() ");
666
667   if (multi_line == 0)
668     {
669       indentation = 1;
670       indentation_amount = 0;
671     }
672   else
673     {
674       cprintf ("\n");
675       indentation += indentation_amount;
676     }
677
678   inside_function_def++;
679
680   cprintf (multi_line ? "{ \n" : "{ ");
681
682   make_command_string_internal (command->type == cm_group
683                                         ? command->value.Group->command
684                                         : command);
685
686   indentation = old_indent;
687   indentation_amount = old_amount;
688   inside_function_def--;
689
690   newline ("}");
691
692   result = the_printed_command;
693
694   if (!multi_line)
695     {
696 #if 0
697       register int i;
698       for (i = 0; result[i]; i++)
699         if (result[i] == '\n')
700           {
701             strcpy (result + i, result + i + 1);
702             --i;
703           }
704 #else
705       if (result[2] == '\n')    /* XXX -- experimental */
706         strcpy (result + 2, result + 3);
707 #endif
708     }
709
710   return (result);
711 }
712
713 static void
714 newline (string)
715      char *string;
716 {
717   cprintf ("\n");
718   indent (indentation);
719   if (string && *string)
720     cprintf ("%s", string);
721 }
722
723 static char *indentation_string;
724 static int indentation_size;
725
726 static void
727 indent (amount)
728      int amount;
729 {
730   register int i;
731
732   RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
733
734   for (i = 0; amount > 0; amount--)
735     indentation_string[i++] = ' ';
736   indentation_string[i] = '\0';
737   cprintf (indentation_string);
738 }
739
740 static void
741 semicolon ()
742 {
743   if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
744     return;
745   cprintf (";");
746 }
747
748 #if !defined (USE_VARARGS)
749 /* How to make the string. */
750 static void
751 cprintf (format, arg1, arg2)
752      char *format, *arg1, *arg2;
753 {
754   register char *s;
755   char char_arg[2], *argp, *args[2];
756   int arg_len, c, arg_index;
757
758   args[arg_index = 0] = arg1;
759   args[1] = arg2;
760
761   arg_len = strlen (format);
762   the_printed_command_resize (arg_len + 1);
763
764   char_arg[1] = '\0';
765   s = format;
766   while (s && *s)
767     {
768       int free_argp = 0;
769       c = *s++;
770       if (c != '%' || !*s)
771         {
772           argp = s;
773           arg_len = 1;
774         }
775       else
776         {
777           c = *s++;
778           switch (c)
779             {
780             case '%':
781               char_arg[0] = c;
782               argp = char_arg;
783               arg_len = 1;
784               break;
785
786             case 's':
787               argp = (char *)args[arg_index++];
788               arg_len = strlen (argp);
789               break;
790
791             case 'd':
792               argp = itos (pointer_to_int (args[arg_index]));
793               arg_index++;
794               arg_len = strlen (argp);
795               free_argp = 1;
796               break;
797
798             case 'c':
799               char_arg[0] = pointer_to_int (args[arg_index]);
800               arg_index++;
801               argp = char_arg;
802               arg_len = 1;
803               break;
804
805             default:
806               programming_error ("cprintf: bad `%%' argument (%c)", c);
807             }
808         }
809       if (argp)
810         {
811           the_printed_command_resize (arg_len + 1);
812           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
813           command_string_index += arg_len;
814           if (free_argp)
815             free (argp);
816         }
817     }
818
819   the_printed_command[command_string_index] = '\0';
820 }
821
822 #else /* We have support for varargs. */
823
824 /* How to make the string. */
825 static void
826 #if defined (PREFER_STDARG)
827 cprintf (char *control, ...)
828 #else
829 cprintf (control, va_alist)
830      char *control;
831      va_dcl
832 #endif
833 {
834   register char *s;
835   char char_arg[2], *argp;
836   int digit_arg, arg_len, c;
837   va_list args;
838
839 #if defined (PREFER_STDARG)
840   va_start (args, control);
841 #else
842   va_start (args);
843 #endif
844
845   arg_len = strlen (control);
846   the_printed_command_resize (arg_len + 1);
847
848   char_arg[1] = '\0';
849   s = control;
850   while (s && *s)
851     {
852       int free_argp;
853       free_argp = 0;
854       c = *s++;
855       argp = (char *)NULL;
856       if (c != '%' || !*s)
857         {
858           argp = s - 1;
859           arg_len = 1;
860         }
861       else
862         {
863           c = *s++;
864           switch (c)
865             {
866             case '%':
867               char_arg[0] = c;
868               argp = char_arg;
869               arg_len = 1;
870               break;
871
872             case 's':
873               argp = va_arg (args, char *);
874               arg_len = strlen (argp);
875               break;
876
877             case 'd':
878               digit_arg = va_arg (args, int);
879               argp = itos (digit_arg);
880               arg_len = strlen (argp);
881               free_argp = 1;
882               break;
883
884             case 'c':
885               char_arg[0] = va_arg (args, int);
886               argp = char_arg;
887               arg_len = 1;
888               break;
889
890             default:
891               programming_error ("cprintf: bad `%%' argument (%c)", c);
892               /*NOTREACHED*/
893             }
894         }
895
896       if (argp && arg_len)
897         {
898           the_printed_command_resize (arg_len + 1);
899           FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
900           command_string_index += arg_len;
901           if (free_argp)
902             free (argp);
903         }
904     }
905
906   the_printed_command[command_string_index] = '\0';
907 }
908 #endif /* HAVE_VARARGS_H */
909
910 /* Ensure that there is enough space to stuff LENGTH characters into
911    THE_PRINTED_COMMAND. */
912 static void
913 the_printed_command_resize (length)
914      int length;
915 {
916   if (the_printed_command == 0)
917     {
918       the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
919       the_printed_command = xmalloc (the_printed_command_size);
920       command_string_index = 0;
921     }
922   else if ((command_string_index + length) >= the_printed_command_size)
923     {
924       int new;
925       new = command_string_index + length + 1;
926 #if 1
927       /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
928       new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
929 #else
930       new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
931       new -= new % PRINTED_COMMAND_GROW_SIZE;
932 #endif
933       the_printed_command_size = new;
934       the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
935     }
936 }
937
938 #if defined (HAVE_VFPRINTF)
939
940 static void
941 #if defined (PREFER_STDARG)
942 xprintf (const char *format, ...)
943 #else
944 xprintf (format, va_alist)
945      const char *format;
946      va_dcl
947 #endif
948 {
949   va_list args;
950
951 #if defined (PREFER_STDARG)
952   va_start (args, format);
953 #else
954   va_start (args);
955 #endif
956
957   vfprintf (stdout, format, args);
958   va_end (args);
959 }
960
961 #else
962
963 static void
964 xprintf (format, arg1, arg2, arg3, arg4, arg5)
965      char *format;
966 {
967   printf (format, arg1, arg2, arg3, arg4, arg5);
968 }
969
970 #endif /* !HAVE_VFPRINTF */