]> git.ipfire.org Git - thirdparty/bash.git/blob - print_cmd.c
Imported from ../bash-2.01.1.tar.gz.
[thirdparty/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 */