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