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