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