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