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