]> git.ipfire.org Git - thirdparty/bash.git/blame - print_cmd.c
commit bash-20090910 snapshot
[thirdparty/bash.git] / print_cmd.c
CommitLineData
726f6388 1/* print_command -- A way to make readable commands from a command tree. */
4931aca6 2
012bac39 3/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
726f6388 4
2e4498b3 5 This file is part of GNU Bash, the Bourne Again SHell.
726f6388 6
2e4498b3
CR
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
726f6388 11
2e4498b3
CR
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
726f6388 16
2e4498b3
CR
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
726f6388 20
ccc6cda3
JA
21#include "config.h"
22
726f6388
JA
23#include <stdio.h>
24
ccc6cda3 25#if defined (HAVE_UNISTD_H)
cce855bc
JA
26# ifdef _MINIX
27# include <sys/types.h>
28# endif
ccc6cda3
JA
29# include <unistd.h>
30#endif
31
32#if defined (PREFER_STDARG)
33# include <stdarg.h>
34#else
7117c2d2 35# include <varargs.h>
726f6388
JA
36#endif
37
ccc6cda3 38#include "bashansi.h"
5e13499c 39#include "bashintl.h"
726f6388
JA
40
41#include "shell.h"
7117c2d2 42#include "flags.h"
d166f048 43#include <y.tab.h> /* use <...> so we pick it up from the build directory */
6e70dbff
CR
44
45#include "shmbutil.h"
46
726f6388
JA
47#include "builtins/common.h"
48
f73dda09 49#if !HAVE_DECL_PRINTF
726f6388
JA
50extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
51#endif
52
7117c2d2
JA
53extern int indirection_level;
54
ccc6cda3 55static int indentation;
726f6388
JA
56static int indentation_amount = 4;
57
d166f048 58#if defined (PREFER_STDARG)
f73dda09
JA
59typedef void PFUNC __P((const char *, ...));
60
61static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
62static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
d166f048 63#else
f73dda09 64#define PFUNC VFunction
d166f048 65static void cprintf ();
f73dda09 66static void xprintf ();
d166f048 67#endif
ccc6cda3 68
f73dda09
JA
69static void reset_locals __P((void));
70static void newline __P((char *));
71static void indent __P((int));
72static void semicolon __P((void));
73static void the_printed_command_resize __P((int));
726f6388 74
f73dda09
JA
75static void make_command_string_internal __P((COMMAND *));
76static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
77static void command_print_word_list __P((WORD_LIST *, char *));
78static void print_case_clauses __P((PATTERN_LIST *));
79static void print_redirection_list __P((REDIRECT *));
80static void print_redirection __P((REDIRECT *));
30915f17
CR
81static void print_heredoc_header __P((REDIRECT *));
82static void print_heredoc_body __P((REDIRECT *));
83static void print_heredocs __P((REDIRECT *));
84static void print_deferred_heredocs __P((const char *));
726f6388 85
f73dda09
JA
86static void print_for_command __P((FOR_COM *));
87#if defined (ARITH_FOR_COMMAND)
88static void print_arith_for_command __P((ARITH_FOR_COM *));
89#endif
726f6388 90#if defined (SELECT_COMMAND)
f73dda09 91static void print_select_command __P((SELECT_COM *));
726f6388 92#endif
f73dda09
JA
93static void print_group_command __P((GROUP_COM *));
94static void print_case_command __P((CASE_COM *));
95static void print_while_command __P((WHILE_COM *));
96static void print_until_command __P((WHILE_COM *));
97static void print_until_or_while __P((WHILE_COM *, char *));
98static void print_if_command __P((IF_COM *));
cce855bc 99#if defined (COND_COMMAND)
f73dda09 100static void print_cond_node __P((COND_COM *));
bb70624e 101#endif
f73dda09 102static void print_function_def __P((FUNCTION_DEF *));
726f6388 103
d166f048
JA
104#define PRINTED_COMMAND_INITIAL_SIZE 64
105#define PRINTED_COMMAND_GROW_SIZE 128
726f6388
JA
106
107char *the_printed_command = (char *)NULL;
108int the_printed_command_size = 0;
109int command_string_index = 0;
110
691aebcb
CR
111int xtrace_fd = -1;
112FILE *xtrace_fp = 0;
113
114#define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
115
726f6388 116/* Non-zero means the stuff being printed is inside of a function def. */
ccc6cda3
JA
117static int inside_function_def;
118static int skip_this_indent;
d166f048 119static int was_heredoc;
30915f17
CR
120static int printing_connection;
121static REDIRECT *deferred_heredocs;
726f6388
JA
122
123/* The depth of the group commands that we are currently printing. This
124 includes the group command that is a function body. */
ccc6cda3 125static int group_command_nesting;
726f6388 126
7117c2d2
JA
127/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
128static char indirection_string[100];
129
726f6388
JA
130/* Print COMMAND (a command tree) on standard output. */
131void
132print_command (command)
133 COMMAND *command;
134{
135 command_string_index = 0;
136 printf ("%s", make_command_string (command));
137}
138
139/* Make a string which is the printed representation of the command
140 tree in COMMAND. We return this string. However, the string is
141 not consed, so you have to do that yourself if you want it to
142 remain around. */
143char *
144make_command_string (command)
145 COMMAND *command;
146{
c40a57dd 147 command_string_index = was_heredoc = 0;
30915f17 148 deferred_heredocs = 0;
726f6388
JA
149 make_command_string_internal (command);
150 return (the_printed_command);
151}
152
153/* The internal function. This is the real workhorse. */
154static void
155make_command_string_internal (command)
156 COMMAND *command;
157{
4b9cc222 158 char s[3], *op;
30915f17 159
ccc6cda3 160 if (command == 0)
726f6388
JA
161 cprintf ("");
162 else
163 {
164 if (skip_this_indent)
165 skip_this_indent--;
166 else
167 indent (indentation);
168
ccc6cda3 169 if (command->flags & CMD_TIME_PIPELINE)
d166f048
JA
170 {
171 cprintf ("time ");
172 if (command->flags & CMD_TIME_POSIX)
173 cprintf ("-p ");
174 }
ccc6cda3 175
726f6388
JA
176 if (command->flags & CMD_INVERT_RETURN)
177 cprintf ("! ");
178
179 switch (command->type)
180 {
181 case cm_for:
182 print_for_command (command->value.For);
183 break;
184
bb70624e
JA
185#if defined (ARITH_FOR_COMMAND)
186 case cm_arith_for:
187 print_arith_for_command (command->value.ArithFor);
188 break;
189#endif
190
726f6388
JA
191#if defined (SELECT_COMMAND)
192 case cm_select:
193 print_select_command (command->value.Select);
194 break;
195#endif
196
197 case cm_case:
198 print_case_command (command->value.Case);
199 break;
200
201 case cm_while:
202 print_while_command (command->value.While);
203 break;
204
205 case cm_until:
206 print_until_command (command->value.While);
207 break;
208
209 case cm_if:
210 print_if_command (command->value.If);
211 break;
212
cce855bc
JA
213#if defined (DPAREN_ARITHMETIC)
214 case cm_arith:
d3a24ed2 215 print_arith_command (command->value.Arith->exp);
cce855bc
JA
216 break;
217#endif
218
219#if defined (COND_COMMAND)
220 case cm_cond:
221 print_cond_command (command->value.Cond);
222 break;
223#endif
224
726f6388
JA
225 case cm_simple:
226 print_simple_command (command->value.Simple);
227 break;
228
ccc6cda3 229 case cm_connection:
726f6388
JA
230
231 skip_this_indent++;
30915f17 232 printing_connection++;
726f6388
JA
233 make_command_string_internal (command->value.Connection->first);
234
235 switch (command->value.Connection->connector)
236 {
237 case '&':
238 case '|':
239 {
240 char c = command->value.Connection->connector;
30915f17
CR
241
242 s[0] = ' ';
243 s[1] = c;
244 s[2] = '\0';
245
246 print_deferred_heredocs (s);
247
726f6388
JA
248 if (c != '&' || command->value.Connection->second)
249 {
250 cprintf (" ");
251 skip_this_indent++;
252 }
253 }
254 break;
255
256 case AND_AND:
30915f17 257 print_deferred_heredocs (" && ");
726f6388
JA
258 if (command->value.Connection->second)
259 skip_this_indent++;
260 break;
261
262 case OR_OR:
30915f17 263 print_deferred_heredocs (" || ");
726f6388
JA
264 if (command->value.Connection->second)
265 skip_this_indent++;
266 break;
ccc6cda3 267
726f6388 268 case ';':
30915f17 269 if (deferred_heredocs == 0)
4b9cc222
CR
270 {
271 if (was_heredoc == 0)
272 cprintf (";");
273 else
274 was_heredoc = 0;
275 }
30915f17 276 else
4b9cc222 277 print_deferred_heredocs (inside_function_def ? "" : ";");
726f6388
JA
278
279 if (inside_function_def)
280 cprintf ("\n");
281 else
282 {
283 cprintf (" ");
284 if (command->value.Connection->second)
285 skip_this_indent++;
286 }
287 break;
288
289 default:
5e13499c 290 cprintf (_("print_command: bad connector `%d'"),
726f6388
JA
291 command->value.Connection->connector);
292 break;
293 }
294
295 make_command_string_internal (command->value.Connection->second);
4b9cc222
CR
296 if (deferred_heredocs)
297 print_deferred_heredocs ("");
30915f17 298 printing_connection--;
726f6388 299 break;
ccc6cda3 300
726f6388
JA
301 case cm_function_def:
302 print_function_def (command->value.Function_def);
303 break;
304
305 case cm_group:
306 print_group_command (command->value.Group);
307 break;
308
bb70624e
JA
309 case cm_subshell:
310 cprintf ("( ");
311 skip_this_indent++;
312 make_command_string_internal (command->value.Subshell->command);
313 cprintf (" )");
314 break;
315
09767ff0
CR
316 case cm_coproc:
317 cprintf ("coproc %s ", command->value.Coproc->name);
318 skip_this_indent++;
319 make_command_string_internal (command->value.Coproc->command);
320 break;
321
726f6388 322 default:
b72432fd 323 command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
726f6388
JA
324 break;
325 }
326
726f6388
JA
327
328 if (command->redirects)
b72432fd
JA
329 {
330 cprintf (" ");
331 print_redirection_list (command->redirects);
332 }
726f6388
JA
333 }
334}
335
336static void
337_print_word_list (list, separator, pfunc)
338 WORD_LIST *list;
339 char *separator;
f73dda09 340 PFUNC *pfunc;
726f6388 341{
ccc6cda3
JA
342 WORD_LIST *w;
343
344 for (w = list; w; w = w->next)
345 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
726f6388
JA
346}
347
ccc6cda3
JA
348void
349print_word_list (list, separator)
726f6388
JA
350 WORD_LIST *list;
351 char *separator;
352{
ccc6cda3
JA
353 _print_word_list (list, separator, xprintf);
354}
355
691aebcb
CR
356void
357xtrace_set (fd, fp)
358 int fd;
359 FILE *fp;
360{
361 if (fd >= 0 && sh_validfd (fd) == 0)
362 {
8f714a7c 363 internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
691aebcb
CR
364 return;
365 }
366 if (fp == 0)
367 {
8f714a7c 368 internal_error (_("xtrace_set: NULL file pointer"));
691aebcb
CR
369 return;
370 }
371 if (fd >= 0 && fileno (fp) != fd)
8f714a7c 372 internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
691aebcb
CR
373
374 xtrace_fd = fd;
375 xtrace_fp = fp;
376}
377
378void
379xtrace_init ()
380{
381 xtrace_set (-1, stderr);
382}
383
384void
385xtrace_reset ()
386{
8f714a7c
CR
387 if (xtrace_fd >= 0 && xtrace_fp)
388 {
389 fflush (xtrace_fp);
390 fclose (xtrace_fp);
391 }
392 else if (xtrace_fd >= 0)
691aebcb 393 close (xtrace_fd);
8f714a7c 394
691aebcb 395 xtrace_fd = -1;
691aebcb
CR
396 xtrace_fp = stderr;
397}
398
8f714a7c
CR
399void
400xtrace_fdchk (fd)
401 int fd;
402{
403 if (fd == xtrace_fd)
404 xtrace_reset ();
405}
406
7117c2d2
JA
407/* Return a string denoting what our indirection level is. */
408
409char *
410indirection_level_string ()
411{
412 register int i, j;
413 char *ps4;
6e70dbff
CR
414 char ps4_firstc[MB_LEN_MAX+1];
415 int ps4_firstc_len, ps4_len;
7117c2d2
JA
416
417 indirection_string[0] = '\0';
418 ps4 = get_string_value ("PS4");
419
420 if (ps4 == 0 || *ps4 == '\0')
421 return (indirection_string);
422
423 change_flag ('x', FLAG_OFF);
424 ps4 = decode_prompt_string (ps4);
425 change_flag ('x', FLAG_ON);
426
d3a24ed2
CR
427 if (ps4 == 0 || *ps4 == '\0')
428 return (indirection_string);
429
6e70dbff
CR
430#if defined (HANDLE_MULTIBYTE)
431 ps4_len = strnlen (ps4, MB_CUR_MAX);
432 ps4_firstc_len = MBLEN (ps4, ps4_len);
433 if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
434 {
435 ps4_firstc[0] = ps4[0];
436 ps4_firstc[ps4_firstc_len = 1] = '\0';
437 }
438 else
439 memcpy (ps4_firstc, ps4, ps4_firstc_len);
440#else
441 ps4_firstc[0] = ps4[0];
442 ps4_firstc[ps4_firstc_len = 1] = '\0';
443#endif
444
445 for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
446 {
447 if (ps4_firstc_len == 1)
448 indirection_string[i] = ps4_firstc[0];
449 else
450 memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
451 }
7117c2d2 452
6e70dbff 453 for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
7117c2d2
JA
454 indirection_string[i] = ps4[j];
455
456 indirection_string[i] = '\0';
457 free (ps4);
458 return (indirection_string);
459}
460
1d7ecd77
CR
461void
462xtrace_print_assignment (name, value, assign_list, xflags)
463 char *name, *value;
464 int assign_list, xflags;
465{
466 char *nval;
467
691aebcb
CR
468 CHECK_XTRACE_FP;
469
1d7ecd77 470 if (xflags)
691aebcb 471 fprintf (xtrace_fp, "%s", indirection_level_string ());
1d7ecd77
CR
472
473 /* VALUE should not be NULL when this is called. */
474 if (*value == '\0' || assign_list)
475 nval = value;
476 else if (sh_contains_shell_metas (value))
477 nval = sh_single_quote (value);
478 else if (ansic_shouldquote (value))
479 nval = ansic_quote (value, 0, (int *)0);
480 else
481 nval = value;
482
483 if (assign_list)
691aebcb 484 fprintf (xtrace_fp, "%s=(%s)\n", name, nval);
1d7ecd77 485 else
691aebcb 486 fprintf (xtrace_fp, "%s=%s\n", name, nval);
1d7ecd77
CR
487
488 if (nval != value)
489 FREE (nval);
490
691aebcb 491 fflush (xtrace_fp);
1d7ecd77
CR
492}
493
ccc6cda3
JA
494/* A function to print the words of a simple command when set -x is on. */
495void
d3a24ed2 496xtrace_print_word_list (list, xtflags)
ccc6cda3 497 WORD_LIST *list;
d3a24ed2 498 int xtflags;
ccc6cda3
JA
499{
500 WORD_LIST *w;
e8ce775d 501 char *t, *x;
ccc6cda3 502
691aebcb
CR
503 CHECK_XTRACE_FP;
504
d3a24ed2 505 if (xtflags)
691aebcb 506 fprintf (xtrace_fp, "%s", indirection_level_string ());
d3a24ed2 507
ccc6cda3
JA
508 for (w = list; w; w = w->next)
509 {
510 t = w->word->word;
511 if (t == 0 || *t == '\0')
691aebcb 512 fprintf (xtrace_fp, "''%s", w->next ? " " : "");
28ef6c31 513 else if (sh_contains_shell_metas (t))
e8ce775d 514 {
28ef6c31 515 x = sh_single_quote (t);
691aebcb 516 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
e8ce775d
JA
517 free (x);
518 }
7117c2d2
JA
519 else if (ansic_shouldquote (t))
520 {
521 x = ansic_quote (t, 0, (int *)0);
691aebcb 522 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
7117c2d2
JA
523 free (x);
524 }
ccc6cda3 525 else
691aebcb 526 fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
ccc6cda3 527 }
691aebcb
CR
528 fprintf (xtrace_fp, "\n");
529 fflush (xtrace_fp);
726f6388
JA
530}
531
532static void
533command_print_word_list (list, separator)
534 WORD_LIST *list;
535 char *separator;
536{
537 _print_word_list (list, separator, cprintf);
538}
539
d3a24ed2
CR
540void
541print_for_command_head (for_command)
726f6388
JA
542 FOR_COM *for_command;
543{
544 cprintf ("for %s in ", for_command->name->word);
545 command_print_word_list (for_command->map_list, " ");
d3a24ed2
CR
546}
547
548void
549xtrace_print_for_command_head (for_command)
550 FOR_COM *for_command;
551{
691aebcb
CR
552 CHECK_XTRACE_FP;
553 fprintf (xtrace_fp, "%s", indirection_level_string ());
554 fprintf (xtrace_fp, "for %s in ", for_command->name->word);
d3a24ed2
CR
555 xtrace_print_word_list (for_command->map_list, 0);
556}
557
558static void
559print_for_command (for_command)
560 FOR_COM *for_command;
561{
562 print_for_command_head (for_command);
563
726f6388
JA
564 cprintf (";");
565 newline ("do\n");
566 indentation += indentation_amount;
567 make_command_string_internal (for_command->action);
568 semicolon ();
569 indentation -= indentation_amount;
570 newline ("done");
571}
572
bb70624e
JA
573#if defined (ARITH_FOR_COMMAND)
574static void
575print_arith_for_command (arith_for_command)
576 ARITH_FOR_COM *arith_for_command;
577{
d3a24ed2 578 cprintf ("for ((");
bb70624e 579 command_print_word_list (arith_for_command->init, " ");
da719982 580 cprintf ("; ");
bb70624e 581 command_print_word_list (arith_for_command->test, " ");
da719982 582 cprintf ("; ");
bb70624e 583 command_print_word_list (arith_for_command->step, " ");
d3a24ed2 584 cprintf ("))");
bb70624e
JA
585 newline ("do\n");
586 indentation += indentation_amount;
587 make_command_string_internal (arith_for_command->action);
588 semicolon ();
589 indentation -= indentation_amount;
590 newline ("done");
591}
592#endif /* ARITH_FOR_COMMAND */
593
726f6388 594#if defined (SELECT_COMMAND)
d3a24ed2
CR
595void
596print_select_command_head (select_command)
726f6388
JA
597 SELECT_COM *select_command;
598{
599 cprintf ("select %s in ", select_command->name->word);
600 command_print_word_list (select_command->map_list, " ");
d3a24ed2
CR
601}
602
603void
604xtrace_print_select_command_head (select_command)
605 SELECT_COM *select_command;
606{
691aebcb
CR
607 CHECK_XTRACE_FP;
608 fprintf (xtrace_fp, "%s", indirection_level_string ());
609 fprintf (xtrace_fp, "select %s in ", select_command->name->word);
d3a24ed2
CR
610 xtrace_print_word_list (select_command->map_list, 0);
611}
612
613static void
614print_select_command (select_command)
615 SELECT_COM *select_command;
616{
617 print_select_command_head (select_command);
618
726f6388
JA
619 cprintf (";");
620 newline ("do\n");
621 indentation += indentation_amount;
622 make_command_string_internal (select_command->action);
623 semicolon ();
624 indentation -= indentation_amount;
625 newline ("done");
626}
627#endif /* SELECT_COMMAND */
628
629static void
630print_group_command (group_command)
631 GROUP_COM *group_command;
632{
633 group_command_nesting++;
634 cprintf ("{ ");
635
ccc6cda3 636 if (inside_function_def == 0)
726f6388
JA
637 skip_this_indent++;
638 else
639 {
640 /* This is a group command { ... } inside of a function
ccc6cda3 641 definition, and should be printed as a multiline group
726f6388
JA
642 command, using the current indentation. */
643 cprintf ("\n");
644 indentation += indentation_amount;
645 }
646
647 make_command_string_internal (group_command->command);
648
ccc6cda3 649 if (inside_function_def)
726f6388 650 {
ccc6cda3 651 cprintf ("\n");
726f6388
JA
652 indentation -= indentation_amount;
653 indent (indentation);
726f6388 654 }
ccc6cda3
JA
655 else
656 {
657 semicolon ();
658 cprintf (" ");
659 }
660
726f6388 661 cprintf ("}");
ccc6cda3 662
726f6388
JA
663 group_command_nesting--;
664}
665
d3a24ed2
CR
666void
667print_case_command_head (case_command)
668 CASE_COM *case_command;
669{
670 cprintf ("case %s in ", case_command->word->word);
671}
672
673void
674xtrace_print_case_command_head (case_command)
675 CASE_COM *case_command;
676{
691aebcb
CR
677 CHECK_XTRACE_FP;
678 fprintf (xtrace_fp, "%s", indirection_level_string ());
679 fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
d3a24ed2
CR
680}
681
726f6388
JA
682static void
683print_case_command (case_command)
684 CASE_COM *case_command;
685{
d3a24ed2
CR
686 print_case_command_head (case_command);
687
726f6388
JA
688 if (case_command->clauses)
689 print_case_clauses (case_command->clauses);
690 newline ("esac");
691}
692
693static void
694print_case_clauses (clauses)
695 PATTERN_LIST *clauses;
696{
697 indentation += indentation_amount;
698 while (clauses)
699 {
700 newline ("");
701 command_print_word_list (clauses->patterns, " | ");
702 cprintf (")\n");
703 indentation += indentation_amount;
704 make_command_string_internal (clauses->action);
705 indentation -= indentation_amount;
8943768b
CR
706 if (clauses->flags & CASEPAT_FALLTHROUGH)
707 newline (";&");
708 else if (clauses->flags & CASEPAT_TESTNEXT)
709 newline (";;&");
710 else
711 newline (";;");
726f6388
JA
712 clauses = clauses->next;
713 }
714 indentation -= indentation_amount;
715}
716
717static void
718print_while_command (while_command)
719 WHILE_COM *while_command;
720{
721 print_until_or_while (while_command, "while");
722}
723
724static void
725print_until_command (while_command)
726 WHILE_COM *while_command;
727{
728 print_until_or_while (while_command, "until");
729}
730
731static void
732print_until_or_while (while_command, which)
733 WHILE_COM *while_command;
734 char *which;
735{
736 cprintf ("%s ", which);
737 skip_this_indent++;
738 make_command_string_internal (while_command->test);
739 semicolon ();
740 cprintf (" do\n"); /* was newline ("do\n"); */
741 indentation += indentation_amount;
742 make_command_string_internal (while_command->action);
743 indentation -= indentation_amount;
744 semicolon ();
745 newline ("done");
746}
747
748static void
749print_if_command (if_command)
750 IF_COM *if_command;
751{
752 cprintf ("if ");
753 skip_this_indent++;
754 make_command_string_internal (if_command->test);
755 semicolon ();
756 cprintf (" then\n");
757 indentation += indentation_amount;
758 make_command_string_internal (if_command->true_case);
759 indentation -= indentation_amount;
760
761 if (if_command->false_case)
762 {
763 semicolon ();
764 newline ("else\n");
765 indentation += indentation_amount;
766 make_command_string_internal (if_command->false_case);
767 indentation -= indentation_amount;
768 }
769 semicolon ();
770 newline ("fi");
771}
772
cce855bc 773#if defined (DPAREN_ARITHMETIC)
d3a24ed2
CR
774void
775print_arith_command (arith_cmd_list)
776 WORD_LIST *arith_cmd_list;
cce855bc 777{
d3a24ed2
CR
778 cprintf ("((");
779 command_print_word_list (arith_cmd_list, " ");
780 cprintf ("))");
cce855bc 781}
bb70624e 782#endif
cce855bc
JA
783
784#if defined (COND_COMMAND)
785static void
786print_cond_node (cond)
787 COND_COM *cond;
788{
789 if (cond->flags & CMD_INVERT_RETURN)
790 cprintf ("! ");
791
792 if (cond->type == COND_EXPR)
793 {
794 cprintf ("( ");
795 print_cond_node (cond->left);
796 cprintf (" )");
797 }
798 else if (cond->type == COND_AND)
799 {
800 print_cond_node (cond->left);
801 cprintf (" && ");
802 print_cond_node (cond->right);
803 }
804 else if (cond->type == COND_OR)
805 {
806 print_cond_node (cond->left);
807 cprintf (" || ");
808 print_cond_node (cond->right);
809 }
810 else if (cond->type == COND_UNARY)
811 {
b72432fd 812 cprintf ("%s", cond->op->word);
cce855bc
JA
813 cprintf (" ");
814 print_cond_node (cond->left);
815 }
816 else if (cond->type == COND_BINARY)
817 {
818 print_cond_node (cond->left);
819 cprintf (" ");
b72432fd 820 cprintf ("%s", cond->op->word);
cce855bc
JA
821 cprintf (" ");
822 print_cond_node (cond->right);
823 }
824 else if (cond->type == COND_TERM)
825 {
b72432fd 826 cprintf ("%s", cond->op->word); /* need to add quoting here */
cce855bc
JA
827 }
828}
829
d3a24ed2 830void
cce855bc
JA
831print_cond_command (cond)
832 COND_COM *cond;
833{
834 cprintf ("[[ ");
835 print_cond_node (cond);
836 cprintf (" ]]");
837}
838
28ef6c31 839#ifdef DEBUG
cce855bc
JA
840void
841debug_print_cond_command (cond)
842 COND_COM *cond;
843{
844 fprintf (stderr, "DEBUG: ");
845 command_string_index = 0;
846 print_cond_command (cond);
847 fprintf (stderr, "%s\n", the_printed_command);
848}
28ef6c31 849#endif
cce855bc
JA
850
851void
852xtrace_print_cond_term (type, invert, op, arg1, arg2)
853 int type, invert;
854 WORD_DESC *op;
855 char *arg1, *arg2;
856{
691aebcb 857 CHECK_XTRACE_FP;
cce855bc 858 command_string_index = 0;
691aebcb
CR
859 fprintf (xtrace_fp, "%s", indirection_level_string ());
860 fprintf (xtrace_fp, "[[ ");
cce855bc 861 if (invert)
691aebcb 862 fprintf (xtrace_fp, "! ");
cce855bc
JA
863
864 if (type == COND_UNARY)
865 {
691aebcb
CR
866 fprintf (xtrace_fp, "%s ", op->word);
867 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
cce855bc
JA
868 }
869 else if (type == COND_BINARY)
870 {
691aebcb
CR
871 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
872 fprintf (xtrace_fp, " %s ", op->word);
873 fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
cce855bc
JA
874 }
875
691aebcb
CR
876 fprintf (xtrace_fp, " ]]\n");
877
878 fflush (xtrace_fp);
cce855bc
JA
879}
880#endif /* COND_COMMAND */
881
bb70624e 882#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
cce855bc
JA
883/* A function to print the words of an arithmetic command when set -x is on. */
884void
885xtrace_print_arith_cmd (list)
886 WORD_LIST *list;
887{
888 WORD_LIST *w;
889
691aebcb
CR
890 CHECK_XTRACE_FP;
891 fprintf (xtrace_fp, "%s", indirection_level_string ());
892 fprintf (xtrace_fp, "(( ");
cce855bc 893 for (w = list; w; w = w->next)
691aebcb
CR
894 fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
895 fprintf (xtrace_fp, " ))\n");
896
897 fflush (xtrace_fp);
cce855bc
JA
898}
899#endif
900
726f6388
JA
901void
902print_simple_command (simple_command)
903 SIMPLE_COM *simple_command;
904{
905 command_print_word_list (simple_command->words, " ");
906
907 if (simple_command->redirects)
908 {
909 cprintf (" ");
910 print_redirection_list (simple_command->redirects);
911 }
912}
913
30915f17
CR
914static void
915print_heredocs (heredocs)
916 REDIRECT *heredocs;
917{
918 REDIRECT *hdtail;
919
920 cprintf (" ");
921 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
922 {
923 print_redirection (hdtail);
924 cprintf ("\n");
925 }
926 was_heredoc = 1;
927}
928
929/* Print heredocs that are attached to the command before the connector
930 represented by CSTRING. The parsing semantics require us to print the
931 here-doc delimiters, then the connector (CSTRING), then the here-doc
932 bodies. We don't print the connector if it's a `;', but we use it to
933 note not to print an extra space after the last heredoc body and
934 newline. */
935static void
936print_deferred_heredocs (cstring)
937 const char *cstring;
938{
939 REDIRECT *hdtail;
940
941 for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
942 {
943 cprintf (" ");
944 print_heredoc_header (hdtail);
945 }
946 if (cstring[0] != ';' || cstring[1])
947 cprintf ("%s", cstring);
948 if (deferred_heredocs)
949 cprintf ("\n");
950 for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
951 {
952 print_heredoc_body (hdtail);
953 cprintf ("\n");
954 }
955 if (deferred_heredocs)
956 {
4b9cc222 957 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
30915f17
CR
958 cprintf (" "); /* make sure there's at least one space */
959 dispose_redirects (deferred_heredocs);
4b9cc222 960 was_heredoc = 1;
30915f17
CR
961 }
962 deferred_heredocs = (REDIRECT *)NULL;
963}
964
726f6388
JA
965static void
966print_redirection_list (redirects)
967 REDIRECT *redirects;
968{
d166f048
JA
969 REDIRECT *heredocs, *hdtail, *newredir;
970
971 heredocs = (REDIRECT *)NULL;
972 hdtail = heredocs;
973
974 was_heredoc = 0;
726f6388
JA
975 while (redirects)
976 {
d166f048
JA
977 /* Defer printing the here documents until we've printed the
978 rest of the redirections. */
979 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
980 {
981 newredir = copy_redirect (redirects);
982 newredir->next = (REDIRECT *)NULL;
983 if (heredocs)
984 {
985 hdtail->next = newredir;
986 hdtail = newredir;
987 }
988 else
989 hdtail = heredocs = newredir;
990 }
e6dfa717 991 else if (redirects->instruction == r_duplicating_output_word && redirects->redirector.dest == 1)
f9732a04
CR
992 {
993 /* Temporarily translate it as the execution code does. */
994 redirects->instruction = r_err_and_out;
995 print_redirection (redirects);
996 redirects->instruction = r_duplicating_output_word;
997 }
d166f048
JA
998 else
999 print_redirection (redirects);
1000
726f6388
JA
1001 redirects = redirects->next;
1002 if (redirects)
1003 cprintf (" ");
1004 }
d166f048
JA
1005
1006 /* Now that we've printed all the other redirections (on one line),
1007 print the here documents. */
30915f17
CR
1008 if (heredocs && printing_connection)
1009 deferred_heredocs = heredocs;
1010 else if (heredocs)
d166f048 1011 {
30915f17 1012 print_heredocs (heredocs);
d166f048 1013 dispose_redirects (heredocs);
d166f048 1014 }
726f6388
JA
1015}
1016
30915f17
CR
1017static void
1018print_heredoc_header (redirect)
1019 REDIRECT *redirect;
1020{
1021 int kill_leading;
1022 char *x;
1023
1024 kill_leading = redirect->instruction == r_deblank_reading_until;
1025
1026 /* Here doc header */
e6dfa717
CR
1027 if (redirect->redirector.dest != 0)
1028 cprintf ("%d", redirect->redirector.dest);
30915f17
CR
1029
1030 /* If the here document delimiter is quoted, single-quote it. */
1031 if (redirect->redirectee.filename->flags & W_QUOTED)
1032 {
1033 x = sh_single_quote (redirect->here_doc_eof);
1034 cprintf ("<<%s%s", kill_leading ? "-" : "", x);
1035 free (x);
1036 }
1037 else
1038 cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
1039}
1040
1041static void
1042print_heredoc_body (redirect)
1043 REDIRECT *redirect;
1044{
1045 /* Here doc body */
1046 cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
1047}
1048
726f6388
JA
1049static void
1050print_redirection (redirect)
1051 REDIRECT *redirect;
1052{
d166f048
JA
1053 int kill_leading, redirector, redir_fd;
1054 WORD_DESC *redirectee;
1055
1056 kill_leading = 0;
1057 redirectee = redirect->redirectee.filename;
e6dfa717 1058 redirector = redirect->redirector.dest;
d166f048 1059 redir_fd = redirect->redirectee.dest;
726f6388
JA
1060
1061 switch (redirect->instruction)
1062 {
1063 case r_output_direction:
1064 if (redirector != 1)
1065 cprintf ("%d", redirector);
d3ad40de 1066 cprintf ("> %s", redirectee->word);
726f6388
JA
1067 break;
1068
1069 case r_input_direction:
1070 if (redirector != 0)
1071 cprintf ("%d", redirector);
d3ad40de 1072 cprintf ("< %s", redirectee->word);
726f6388
JA
1073 break;
1074
1075 case r_inputa_direction: /* Redirection created by the shell. */
1076 cprintf ("&");
1077 break;
1078
1079 case r_appending_to:
1080 if (redirector != 1)
1081 cprintf ("%d", redirector);
d3ad40de 1082 cprintf (">> %s", redirectee->word);
726f6388
JA
1083 break;
1084
1085 case r_deblank_reading_until:
726f6388 1086 case r_reading_until:
30915f17
CR
1087 print_heredoc_header (redirect);
1088 cprintf ("\n");
1089 print_heredoc_body (redirect);
726f6388
JA
1090 break;
1091
7117c2d2
JA
1092 case r_reading_string:
1093 if (redirector != 0)
1094 cprintf ("%d", redirector);
1095 if (ansic_shouldquote (redirect->redirectee.filename->word))
1096 {
1097 char *x;
1098 x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1099 cprintf ("<<< %s", x);
1100 free (x);
1101 }
1102 else
1103 cprintf ("<<< %s", redirect->redirectee.filename->word);
1104 break;
1105
726f6388
JA
1106 case r_duplicating_input:
1107 cprintf ("%d<&%d", redirector, redir_fd);
1108 break;
1109
1110 case r_duplicating_output:
1111 cprintf ("%d>&%d", redirector, redir_fd);
1112 break;
1113
1114 case r_duplicating_input_word:
1115 cprintf ("%d<&%s", redirector, redirectee->word);
1116 break;
1117
1118 case r_duplicating_output_word:
1119 cprintf ("%d>&%s", redirector, redirectee->word);
1120 break;
1121
7117c2d2
JA
1122 case r_move_input:
1123 cprintf ("%d<&%d-", redirector, redir_fd);
1124 break;
1125
1126 case r_move_output:
1127 cprintf ("%d>&%d-", redirector, redir_fd);
1128 break;
1129
1130 case r_move_input_word:
1131 cprintf ("%d<&%s-", redirector, redirectee->word);
1132 break;
1133
1134 case r_move_output_word:
1135 cprintf ("%d>&%s-", redirector, redirectee->word);
1136 break;
1137
726f6388
JA
1138 case r_close_this:
1139 cprintf ("%d>&-", redirector);
1140 break;
1141
1142 case r_err_and_out:
6a8fd0ed 1143 cprintf ("&>%s", redirectee->word);
726f6388
JA
1144 break;
1145
8943768b
CR
1146 case r_append_err_and_out:
1147 cprintf ("&>>%s", redirectee->word);
1148 break;
1149
726f6388
JA
1150 case r_input_output:
1151 if (redirector != 1)
1152 cprintf ("%d", redirector);
d3ad40de 1153 cprintf ("<> %s", redirectee->word);
726f6388
JA
1154 break;
1155
1156 case r_output_force:
1157 if (redirector != 1)
1158 cprintf ("%d", redirector);
1159 cprintf (">|%s", redirectee->word);
1160 break;
1161 }
1162}
1163
1164static void
1165reset_locals ()
1166{
1167 inside_function_def = 0;
1168 indentation = 0;
30915f17
CR
1169 printing_connection = 0;
1170 deferred_heredocs = 0;
726f6388
JA
1171}
1172
1173static void
1174print_function_def (func)
1175 FUNCTION_DEF *func;
1176{
bb70624e
JA
1177 COMMAND *cmdcopy;
1178 REDIRECT *func_redirects;
1179
f73dda09 1180 func_redirects = NULL;
726f6388
JA
1181 cprintf ("function %s () \n", func->name->word);
1182 add_unwind_protect (reset_locals, 0);
1183
1184 indent (indentation);
1185 cprintf ("{ \n");
1186
1187 inside_function_def++;
1188 indentation += indentation_amount;
1189
c40a57dd 1190 cmdcopy = copy_command (func->command);
bb70624e
JA
1191 if (cmdcopy->type == cm_group)
1192 {
28ef6c31
JA
1193 func_redirects = cmdcopy->redirects;
1194 cmdcopy->redirects = (REDIRECT *)NULL;
bb70624e
JA
1195 }
1196 make_command_string_internal (cmdcopy->type == cm_group
1197 ? cmdcopy->value.Group->command
1198 : cmdcopy);
ccc6cda3 1199
726f6388
JA
1200 remove_unwind_protect ();
1201 indentation -= indentation_amount;
1202 inside_function_def--;
1203
bb70624e
JA
1204 if (func_redirects)
1205 { /* { */
1206 newline ("} ");
1207 print_redirection_list (func_redirects);
28ef6c31 1208 cmdcopy->redirects = func_redirects;
bb70624e
JA
1209 }
1210 else
1211 newline ("}");
1212
1213 dispose_command (cmdcopy);
726f6388
JA
1214}
1215
1216/* Return the string representation of the named function.
1217 NAME is the name of the function.
1218 COMMAND is the function body. It should be a GROUP_COM.
b0c16657
CR
1219 flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1220 flags&FUNC_EXTERNAL means convert from internal to external form
726f6388
JA
1221 */
1222char *
b0c16657 1223named_function_string (name, command, flags)
726f6388
JA
1224 char *name;
1225 COMMAND *command;
b0c16657 1226 int flags;
726f6388
JA
1227{
1228 char *result;
ccc6cda3 1229 int old_indent, old_amount;
bb70624e
JA
1230 COMMAND *cmdcopy;
1231 REDIRECT *func_redirects;
726f6388 1232
ccc6cda3
JA
1233 old_indent = indentation;
1234 old_amount = indentation_amount;
d166f048 1235 command_string_index = was_heredoc = 0;
30915f17 1236 deferred_heredocs = 0;
726f6388
JA
1237
1238 if (name && *name)
1239 cprintf ("%s ", name);
1240
1241 cprintf ("() ");
1242
b0c16657 1243 if ((flags & FUNC_MULTILINE) == 0)
726f6388
JA
1244 {
1245 indentation = 1;
1246 indentation_amount = 0;
1247 }
1248 else
1249 {
1250 cprintf ("\n");
1251 indentation += indentation_amount;
1252 }
1253
1254 inside_function_def++;
1255
b0c16657 1256 cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
726f6388 1257
bb70624e
JA
1258 cmdcopy = copy_command (command);
1259 /* Take any redirections specified in the function definition (which should
1260 apply to the function as a whole) and save them for printing later. */
1261 func_redirects = (REDIRECT *)NULL;
1262 if (cmdcopy->type == cm_group)
1263 {
28ef6c31
JA
1264 func_redirects = cmdcopy->redirects;
1265 cmdcopy->redirects = (REDIRECT *)NULL;
bb70624e
JA
1266 }
1267 make_command_string_internal (cmdcopy->type == cm_group
1268 ? cmdcopy->value.Group->command
1269 : cmdcopy);
726f6388
JA
1270
1271 indentation = old_indent;
1272 indentation_amount = old_amount;
1273 inside_function_def--;
1274
bb70624e
JA
1275 if (func_redirects)
1276 { /* { */
1277 newline ("} ");
1278 print_redirection_list (func_redirects);
28ef6c31 1279 cmdcopy->redirects = func_redirects;
bb70624e
JA
1280 }
1281 else
1282 newline ("}");
726f6388
JA
1283
1284 result = the_printed_command;
1285
b0c16657 1286 if ((flags & FUNC_MULTILINE) == 0)
726f6388
JA
1287 {
1288#if 0
1289 register int i;
1290 for (i = 0; result[i]; i++)
1291 if (result[i] == '\n')
1292 {
1293 strcpy (result + i, result + i + 1);
1294 --i;
1295 }
1296#else
1297 if (result[2] == '\n') /* XXX -- experimental */
28ef6c31 1298 strcpy (result + 2, result + 3);
726f6388
JA
1299#endif
1300 }
1301
bb70624e
JA
1302 dispose_command (cmdcopy);
1303
b0c16657
CR
1304 if (flags & FUNC_EXTERNAL)
1305 result = remove_quoted_escapes (result);
1306
726f6388
JA
1307 return (result);
1308}
1309
1310static void
1311newline (string)
1312 char *string;
1313{
1314 cprintf ("\n");
1315 indent (indentation);
1316 if (string && *string)
1317 cprintf ("%s", string);
1318}
1319
ccc6cda3
JA
1320static char *indentation_string;
1321static int indentation_size;
1322
726f6388
JA
1323static void
1324indent (amount)
1325 int amount;
1326{
ccc6cda3
JA
1327 register int i;
1328
1329 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1330
1331 for (i = 0; amount > 0; amount--)
1332 indentation_string[i++] = ' ';
1333 indentation_string[i] = '\0';
1334 cprintf (indentation_string);
726f6388
JA
1335}
1336
1337static void
1338semicolon ()
1339{
7117c2d2
JA
1340 if (command_string_index > 0 &&
1341 (the_printed_command[command_string_index - 1] == '&' ||
1342 the_printed_command[command_string_index - 1] == '\n'))
726f6388
JA
1343 return;
1344 cprintf (";");
1345}
1346
726f6388
JA
1347/* How to make the string. */
1348static void
ccc6cda3 1349#if defined (PREFER_STDARG)
f73dda09 1350cprintf (const char *control, ...)
ccc6cda3
JA
1351#else
1352cprintf (control, va_alist)
f73dda09 1353 const char *control;
726f6388 1354 va_dcl
ccc6cda3 1355#endif
726f6388 1356{
f73dda09
JA
1357 register const char *s;
1358 char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
726f6388
JA
1359 int digit_arg, arg_len, c;
1360 va_list args;
1361
7117c2d2 1362 SH_VA_START (args, control);
726f6388
JA
1363
1364 arg_len = strlen (control);
1365 the_printed_command_resize (arg_len + 1);
1366
1367 char_arg[1] = '\0';
1368 s = control;
1369 while (s && *s)
1370 {
726f6388 1371 c = *s++;
ccc6cda3 1372 argp = (char *)NULL;
726f6388
JA
1373 if (c != '%' || !*s)
1374 {
f73dda09
JA
1375 char_arg[0] = c;
1376 argp = char_arg;
726f6388
JA
1377 arg_len = 1;
1378 }
1379 else
1380 {
1381 c = *s++;
1382 switch (c)
1383 {
1384 case '%':
1385 char_arg[0] = c;
1386 argp = char_arg;
1387 arg_len = 1;
1388 break;
1389
1390 case 's':
1391 argp = va_arg (args, char *);
1392 arg_len = strlen (argp);
1393 break;
1394
1395 case 'd':
f73dda09
JA
1396 /* Represent an out-of-range file descriptor with an out-of-range
1397 integer value. We can do this because the only use of `%d' in
1398 the calls to cprintf is to output a file descriptor number for
1399 a redirection. */
726f6388 1400 digit_arg = va_arg (args, int);
f73dda09
JA
1401 if (digit_arg < 0)
1402 {
1403 sprintf (intbuf, "%u", (unsigned)-1);
1404 argp = intbuf;
1405 }
1406 else
1407 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
726f6388 1408 arg_len = strlen (argp);
726f6388
JA
1409 break;
1410
1411 case 'c':
1412 char_arg[0] = va_arg (args, int);
1413 argp = char_arg;
1414 arg_len = 1;
1415 break;
1416
1417 default:
5e13499c 1418 programming_error (_("cprintf: `%c': invalid format character"), c);
ccc6cda3 1419 /*NOTREACHED*/
726f6388
JA
1420 }
1421 }
1422
ccc6cda3 1423 if (argp && arg_len)
726f6388
JA
1424 {
1425 the_printed_command_resize (arg_len + 1);
1426 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1427 command_string_index += arg_len;
726f6388
JA
1428 }
1429 }
1430
1431 the_printed_command[command_string_index] = '\0';
1432}
726f6388
JA
1433
1434/* Ensure that there is enough space to stuff LENGTH characters into
1435 THE_PRINTED_COMMAND. */
1436static void
1437the_printed_command_resize (length)
1438 int length;
1439{
d166f048 1440 if (the_printed_command == 0)
726f6388 1441 {
d166f048 1442 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
f73dda09 1443 the_printed_command = (char *)xmalloc (the_printed_command_size);
726f6388
JA
1444 command_string_index = 0;
1445 }
1446 else if ((command_string_index + length) >= the_printed_command_size)
1447 {
1448 int new;
1449 new = command_string_index + length + 1;
bb70624e 1450
d166f048
JA
1451 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1452 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
726f6388 1453 the_printed_command_size = new;
bb70624e 1454
f73dda09 1455 the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
726f6388
JA
1456 }
1457}
ccc6cda3 1458
f73dda09
JA
1459#if defined (HAVE_VPRINTF)
1460/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1461 also available.'' */
ccc6cda3
JA
1462
1463static void
d166f048
JA
1464#if defined (PREFER_STDARG)
1465xprintf (const char *format, ...)
1466#else
1467xprintf (format, va_alist)
1468 const char *format;
ccc6cda3 1469 va_dcl
d166f048 1470#endif
ccc6cda3
JA
1471{
1472 va_list args;
ccc6cda3 1473
7117c2d2 1474 SH_VA_START (args, format);
d166f048 1475
ccc6cda3
JA
1476 vfprintf (stdout, format, args);
1477 va_end (args);
1478}
1479
1480#else
1481
1482static void
1483xprintf (format, arg1, arg2, arg3, arg4, arg5)
f73dda09 1484 const char *format;
ccc6cda3
JA
1485{
1486 printf (format, arg1, arg2, arg3, arg4, arg5);
1487}
1488
f73dda09 1489#endif /* !HAVE_VPRINTF */