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