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