init version.
[bush.git] / src / print_cmd.c
blobe2b7b5d9db3aba58755cc1e2b977389cf57af55f
1 /* print_command -- A way to make readable commands from a command tree. */
3 /* Copyright (C) 1989-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #include "config.h"
23 #include <stdio.h>
25 #if defined (HAVE_UNISTD_H)
26 # ifdef _MINIX
27 # include <sys/types.h>
28 # endif
29 # include <unistd.h>
30 #endif
32 #if defined (PREFER_STDARG)
33 # include <stdarg.h>
34 #else
35 # include <varargs.h>
36 #endif
38 #include "bushansi.h"
39 #include "bushintl.h"
41 #define NEED_XTRACE_SET_DECL
43 #include "shell.h"
44 #include "flags.h"
45 #include <y.tab.h> /* use <...> so we pick it up from the build directory */
46 #include "input.h"
48 #include "shmbutil.h"
50 #include "builtins/common.h"
52 #if !HAVE_DECL_PRINTF
53 extern int printf PARAMS((const char *, ...)); /* Yuck. Double yuck. */
54 #endif
56 static int indentation;
57 static int indentation_amount = 4;
59 #if defined (PREFER_STDARG)
60 typedef void PFUNC PARAMS((const char *, ...));
62 static void cprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
63 static void xprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
64 #else
65 #define PFUNC VFunction
66 static void cprintf ();
67 static void xprintf ();
68 #endif
70 static void reset_locals PARAMS((void));
71 static void newline PARAMS((char *));
72 static void indent PARAMS((int));
73 static void semicolon PARAMS((void));
74 static void the_printed_command_resize PARAMS((int));
76 static void make_command_string_internal PARAMS((COMMAND *));
77 static void _print_word_list PARAMS((WORD_LIST *, char *, PFUNC *));
78 static void command_print_word_list PARAMS((WORD_LIST *, char *));
79 static void print_case_clauses PARAMS((PATTERN_LIST *));
80 static void print_redirection_list PARAMS((REDIRECT *));
81 static void print_redirection PARAMS((REDIRECT *));
82 static void print_heredoc_header PARAMS((REDIRECT *));
83 static void print_heredoc_body PARAMS((REDIRECT *));
84 static void print_heredocs PARAMS((REDIRECT *));
85 static void print_heredoc_bodies PARAMS((REDIRECT *));
86 static void print_deferred_heredocs PARAMS((const char *));
88 static void print_for_command PARAMS((FOR_COM *));
89 #if defined (ARITH_FOR_COMMAND)
90 static void print_arith_for_command PARAMS((ARITH_FOR_COM *));
91 #endif
92 #if defined (SELECT_COMMAND)
93 static void print_select_command PARAMS((SELECT_COM *));
94 #endif
95 static void print_group_command PARAMS((GROUP_COM *));
96 static void print_case_command PARAMS((CASE_COM *));
97 static void print_while_command PARAMS((WHILE_COM *));
98 static void print_until_command PARAMS((WHILE_COM *));
99 static void print_until_or_while PARAMS((WHILE_COM *, char *));
100 static void print_if_command PARAMS((IF_COM *));
101 #if defined (COND_COMMAND)
102 static void print_cond_node PARAMS((COND_COM *));
103 #endif
104 static void print_function_def PARAMS((FUNCTION_DEF *));
106 #define PRINTED_COMMAND_INITIAL_SIZE 64
107 #define PRINTED_COMMAND_GROW_SIZE 128
109 char *the_printed_command = (char *)NULL;
110 int the_printed_command_size = 0;
111 int command_string_index = 0;
113 int xtrace_fd = -1;
114 FILE *xtrace_fp = 0;
116 #define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
118 /* shell expansion characters: used in print_redirection_list */
119 #define EXPCHAR(c) ((c) == '{' || (c) == '~' || (c) == '$' || (c) == '`')
121 #define PRINT_DEFERRED_HEREDOCS(x) \
122 do { \
123 if (deferred_heredocs) \
124 print_deferred_heredocs (x); \
125 } while (0)
127 /* Non-zero means the stuff being printed is inside of a function def. */
128 static int inside_function_def;
129 static int skip_this_indent;
130 static int was_heredoc;
131 static int printing_connection;
132 static REDIRECT *deferred_heredocs;
134 /* The depth of the group commands that we are currently printing. This
135 includes the group command that is a function body. */
136 static int group_command_nesting;
138 /* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
139 static char *indirection_string = 0;
140 static int indirection_stringsiz = 0;
142 /* Print COMMAND (a command tree) on standard output. */
143 void
144 print_command (command)
145 COMMAND *command;
147 command_string_index = 0;
148 printf ("%s", make_command_string (command));
151 /* Make a string which is the printed representation of the command
152 tree in COMMAND. We return this string. However, the string is
153 not consed, so you have to do that yourself if you want it to
154 remain around. */
155 char *
156 make_command_string (command)
157 COMMAND *command;
159 command_string_index = was_heredoc = 0;
160 deferred_heredocs = 0;
161 make_command_string_internal (command);
162 return (the_printed_command);
165 /* The internal function. This is the real workhorse. */
166 static void
167 make_command_string_internal (command)
168 COMMAND *command;
170 char s[3];
172 if (command == 0)
173 cprintf ("");
174 else
176 if (skip_this_indent)
177 skip_this_indent--;
178 else
179 indent (indentation);
181 if (command->flags & CMD_TIME_PIPELINE)
183 cprintf ("time ");
184 if (command->flags & CMD_TIME_POSIX)
185 cprintf ("-p ");
188 if (command->flags & CMD_INVERT_RETURN)
189 cprintf ("! ");
191 switch (command->type)
193 case cm_for:
194 print_for_command (command->value.For);
195 break;
197 #if defined (ARITH_FOR_COMMAND)
198 case cm_arith_for:
199 print_arith_for_command (command->value.ArithFor);
200 break;
201 #endif
203 #if defined (SELECT_COMMAND)
204 case cm_select:
205 print_select_command (command->value.Select);
206 break;
207 #endif
209 case cm_case:
210 print_case_command (command->value.Case);
211 break;
213 case cm_while:
214 print_while_command (command->value.While);
215 break;
217 case cm_until:
218 print_until_command (command->value.While);
219 break;
221 case cm_if:
222 print_if_command (command->value.If);
223 break;
225 #if defined (DPAREN_ARITHMETIC)
226 case cm_arith:
227 print_arith_command (command->value.Arith->exp);
228 break;
229 #endif
231 #if defined (COND_COMMAND)
232 case cm_cond:
233 print_cond_command (command->value.Cond);
234 break;
235 #endif
237 case cm_simple:
238 print_simple_command (command->value.Simple);
239 break;
241 case cm_connection:
243 skip_this_indent++;
244 printing_connection++;
245 make_command_string_internal (command->value.Connection->first);
247 switch (command->value.Connection->connector)
249 case '&':
250 case '|':
252 char c = command->value.Connection->connector;
254 s[0] = ' ';
255 s[1] = c;
256 s[2] = '\0';
258 print_deferred_heredocs (s);
260 if (c != '&' || command->value.Connection->second)
262 cprintf (" ");
263 skip_this_indent++;
266 break;
268 case AND_AND:
269 print_deferred_heredocs (" && ");
270 if (command->value.Connection->second)
271 skip_this_indent++;
272 break;
274 case OR_OR:
275 print_deferred_heredocs (" || ");
276 if (command->value.Connection->second)
277 skip_this_indent++;
278 break;
280 case ';':
281 if (deferred_heredocs == 0)
283 if (was_heredoc == 0)
284 cprintf (";");
285 else
286 was_heredoc = 0;
288 else
289 print_deferred_heredocs (inside_function_def ? "" : ";");
291 if (inside_function_def)
292 cprintf ("\n");
293 else
295 cprintf (" ");
296 if (command->value.Connection->second)
297 skip_this_indent++;
299 break;
301 default:
302 cprintf (_("print_command: bad connector `%d'"),
303 command->value.Connection->connector);
304 break;
307 make_command_string_internal (command->value.Connection->second);
308 PRINT_DEFERRED_HEREDOCS ("");
309 printing_connection--;
310 break;
312 case cm_function_def:
313 print_function_def (command->value.Function_def);
314 break;
316 case cm_group:
317 print_group_command (command->value.Group);
318 break;
320 case cm_subshell:
321 cprintf ("( ");
322 skip_this_indent++;
323 make_command_string_internal (command->value.Subshell->command);
324 PRINT_DEFERRED_HEREDOCS ("");
325 cprintf (" )");
326 break;
328 case cm_coproc:
329 cprintf ("coproc %s ", command->value.Coproc->name);
330 skip_this_indent++;
331 make_command_string_internal (command->value.Coproc->command);
332 break;
334 default:
335 command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
336 break;
340 if (command->redirects)
342 cprintf (" ");
343 print_redirection_list (command->redirects);
348 static void
349 _print_word_list (list, separator, pfunc)
350 WORD_LIST *list;
351 char *separator;
352 PFUNC *pfunc;
354 WORD_LIST *w;
356 for (w = list; w; w = w->next)
357 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
360 void
361 print_word_list (list, separator)
362 WORD_LIST *list;
363 char *separator;
365 _print_word_list (list, separator, xprintf);
368 void
369 xtrace_set (fd, fp)
370 int fd;
371 FILE *fp;
373 if (fd >= 0 && sh_validfd (fd) == 0)
375 internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
376 return;
378 if (fp == 0)
380 internal_error (_("xtrace_set: NULL file pointer"));
381 return;
383 if (fd >= 0 && fileno (fp) != fd)
384 internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
386 xtrace_fd = fd;
387 xtrace_fp = fp;
390 void
391 xtrace_init ()
393 xtrace_set (-1, stderr);
396 void
397 xtrace_reset ()
399 if (xtrace_fd >= 0 && xtrace_fp)
401 fflush (xtrace_fp);
402 fclose (xtrace_fp);
404 else if (xtrace_fd >= 0)
405 close (xtrace_fd);
407 xtrace_fd = -1;
408 xtrace_fp = stderr;
411 void
412 xtrace_fdchk (fd)
413 int fd;
415 if (fd == xtrace_fd)
416 xtrace_reset ();
419 /* Return a string denoting what our indirection level is. */
421 char *
422 indirection_level_string ()
424 register int i, j;
425 char *ps4;
426 char ps4_firstc[MB_LEN_MAX+1];
427 int ps4_firstc_len, ps4_len, ineed, old;
429 ps4 = get_string_value ("PS4");
430 if (indirection_string == 0)
431 indirection_string = xmalloc (indirection_stringsiz = 100);
432 indirection_string[0] = '\0';
434 if (ps4 == 0 || *ps4 == '\0')
435 return (indirection_string);
437 old = change_flag ('x', FLAG_OFF);
438 ps4 = decode_prompt_string (ps4);
439 if (old)
440 change_flag ('x', FLAG_ON);
442 if (ps4 == 0 || *ps4 == '\0')
443 return (indirection_string);
445 #if defined (HANDLE_MULTIBYTE)
446 ps4_len = strnlen (ps4, MB_CUR_MAX);
447 ps4_firstc_len = MBLEN (ps4, ps4_len);
448 if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || ps4_firstc_len < 0)
450 ps4_firstc[0] = ps4[0];
451 ps4_firstc[ps4_firstc_len = 1] = '\0';
453 else
454 memcpy (ps4_firstc, ps4, ps4_firstc_len);
455 #else
456 ps4_firstc[0] = ps4[0];
457 ps4_firstc[ps4_firstc_len = 1] = '\0';
458 #endif
460 /* Dynamically resize indirection_string so we have room for everything
461 and we don't have to truncate ps4 */
462 ineed = (ps4_firstc_len * indirection_level) + strlen (ps4);
463 if (ineed > indirection_stringsiz - 1)
465 indirection_stringsiz = ineed + 1;
466 indirection_string = xrealloc (indirection_string, indirection_stringsiz);
469 for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < indirection_stringsiz - 1; i += ps4_firstc_len, j++)
471 if (ps4_firstc_len == 1)
472 indirection_string[i] = ps4_firstc[0];
473 else
474 memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
477 for (j = ps4_firstc_len; *ps4 && ps4[j] && i < indirection_stringsiz - 1; i++, j++)
478 indirection_string[i] = ps4[j];
480 indirection_string[i] = '\0';
481 free (ps4);
482 return (indirection_string);
485 void
486 xtrace_print_assignment (name, value, assign_list, xflags)
487 char *name, *value;
488 int assign_list, xflags;
490 char *nval;
492 CHECK_XTRACE_FP;
494 if (xflags)
495 fprintf (xtrace_fp, "%s", indirection_level_string ());
497 /* VALUE should not be NULL when this is called. */
498 if (*value == '\0' || assign_list)
499 nval = value;
500 else if (sh_contains_shell_metas (value))
501 nval = sh_single_quote (value);
502 else if (ansic_shouldquote (value))
503 nval = ansic_quote (value, 0, (int *)0);
504 else
505 nval = value;
507 if (assign_list)
508 fprintf (xtrace_fp, "%s=(%s)\n", name, nval);
509 else
510 fprintf (xtrace_fp, "%s=%s\n", name, nval);
512 if (nval != value)
513 FREE (nval);
515 fflush (xtrace_fp);
518 /* A function to print the words of a simple command when set -x is on. Also used to
519 print the word list in a for or select command header; in that case, we suppress
520 quoting the words because they haven't been expanded yet. XTFLAGS&1 means to
521 print $PS4; XTFLAGS&2 means to suppress quoting the words in LIST. */
522 void
523 xtrace_print_word_list (list, xtflags)
524 WORD_LIST *list;
525 int xtflags;
527 WORD_LIST *w;
528 char *t, *x;
530 CHECK_XTRACE_FP;
532 if (xtflags&1)
533 fprintf (xtrace_fp, "%s", indirection_level_string ());
535 for (w = list; w; w = w->next)
537 t = w->word->word;
538 if (t == 0 || *t == '\0')
539 fprintf (xtrace_fp, "''%s", w->next ? " " : "");
540 else if (xtflags & 2)
541 fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
542 else if (sh_contains_shell_metas (t))
544 x = sh_single_quote (t);
545 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
546 free (x);
548 else if (ansic_shouldquote (t))
550 x = ansic_quote (t, 0, (int *)0);
551 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
552 free (x);
554 else
555 fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
557 fprintf (xtrace_fp, "\n");
558 fflush (xtrace_fp);
561 static void
562 command_print_word_list (list, separator)
563 WORD_LIST *list;
564 char *separator;
566 _print_word_list (list, separator, cprintf);
569 void
570 print_for_command_head (for_command)
571 FOR_COM *for_command;
573 cprintf ("for %s in ", for_command->name->word);
574 command_print_word_list (for_command->map_list, " ");
577 void
578 xtrace_print_for_command_head (for_command)
579 FOR_COM *for_command;
581 CHECK_XTRACE_FP;
582 fprintf (xtrace_fp, "%s", indirection_level_string ());
583 fprintf (xtrace_fp, "for %s in ", for_command->name->word);
584 xtrace_print_word_list (for_command->map_list, 2);
587 static void
588 print_for_command (for_command)
589 FOR_COM *for_command;
591 print_for_command_head (for_command);
592 cprintf (";");
593 newline ("do\n");
595 indentation += indentation_amount;
596 make_command_string_internal (for_command->action);
597 PRINT_DEFERRED_HEREDOCS ("");
598 semicolon ();
599 indentation -= indentation_amount;
601 newline ("done");
604 #if defined (ARITH_FOR_COMMAND)
605 static void
606 print_arith_for_command (arith_for_command)
607 ARITH_FOR_COM *arith_for_command;
609 cprintf ("for ((");
610 command_print_word_list (arith_for_command->init, " ");
611 cprintf ("; ");
612 command_print_word_list (arith_for_command->test, " ");
613 cprintf ("; ");
614 command_print_word_list (arith_for_command->step, " ");
615 cprintf ("))");
616 newline ("do\n");
617 indentation += indentation_amount;
618 make_command_string_internal (arith_for_command->action);
619 PRINT_DEFERRED_HEREDOCS ("");
620 semicolon ();
621 indentation -= indentation_amount;
622 newline ("done");
624 #endif /* ARITH_FOR_COMMAND */
626 #if defined (SELECT_COMMAND)
627 void
628 print_select_command_head (select_command)
629 SELECT_COM *select_command;
631 cprintf ("select %s in ", select_command->name->word);
632 command_print_word_list (select_command->map_list, " ");
635 void
636 xtrace_print_select_command_head (select_command)
637 SELECT_COM *select_command;
639 CHECK_XTRACE_FP;
640 fprintf (xtrace_fp, "%s", indirection_level_string ());
641 fprintf (xtrace_fp, "select %s in ", select_command->name->word);
642 xtrace_print_word_list (select_command->map_list, 2);
645 static void
646 print_select_command (select_command)
647 SELECT_COM *select_command;
649 print_select_command_head (select_command);
651 cprintf (";");
652 newline ("do\n");
653 indentation += indentation_amount;
654 make_command_string_internal (select_command->action);
655 PRINT_DEFERRED_HEREDOCS ("");
656 semicolon ();
657 indentation -= indentation_amount;
658 newline ("done");
660 #endif /* SELECT_COMMAND */
662 static void
663 print_group_command (group_command)
664 GROUP_COM *group_command;
666 group_command_nesting++;
667 cprintf ("{ ");
669 if (inside_function_def == 0)
670 skip_this_indent++;
671 else
673 /* This is a group command { ... } inside of a function
674 definition, and should be printed as a multiline group
675 command, using the current indentation. */
676 cprintf ("\n");
677 indentation += indentation_amount;
680 make_command_string_internal (group_command->command);
681 PRINT_DEFERRED_HEREDOCS ("");
683 if (inside_function_def)
685 cprintf ("\n");
686 indentation -= indentation_amount;
687 indent (indentation);
689 else
691 semicolon ();
692 cprintf (" ");
695 cprintf ("}");
697 group_command_nesting--;
700 void
701 print_case_command_head (case_command)
702 CASE_COM *case_command;
704 cprintf ("case %s in ", case_command->word->word);
707 void
708 xtrace_print_case_command_head (case_command)
709 CASE_COM *case_command;
711 CHECK_XTRACE_FP;
712 fprintf (xtrace_fp, "%s", indirection_level_string ());
713 fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
716 static void
717 print_case_command (case_command)
718 CASE_COM *case_command;
720 print_case_command_head (case_command);
722 if (case_command->clauses)
723 print_case_clauses (case_command->clauses);
724 newline ("esac");
727 static void
728 print_case_clauses (clauses)
729 PATTERN_LIST *clauses;
731 indentation += indentation_amount;
732 while (clauses)
734 newline ("");
735 command_print_word_list (clauses->patterns, " | ");
736 cprintf (")\n");
737 indentation += indentation_amount;
738 make_command_string_internal (clauses->action);
739 indentation -= indentation_amount;
740 PRINT_DEFERRED_HEREDOCS ("");
741 if (clauses->flags & CASEPAT_FALLTHROUGH)
742 newline (";&");
743 else if (clauses->flags & CASEPAT_TESTNEXT)
744 newline (";;&");
745 else
746 newline (";;");
747 clauses = clauses->next;
749 indentation -= indentation_amount;
752 static void
753 print_while_command (while_command)
754 WHILE_COM *while_command;
756 print_until_or_while (while_command, "while");
759 static void
760 print_until_command (while_command)
761 WHILE_COM *while_command;
763 print_until_or_while (while_command, "until");
766 static void
767 print_until_or_while (while_command, which)
768 WHILE_COM *while_command;
769 char *which;
771 cprintf ("%s ", which);
772 skip_this_indent++;
773 make_command_string_internal (while_command->test);
774 PRINT_DEFERRED_HEREDOCS ("");
775 semicolon ();
776 cprintf (" do\n"); /* was newline ("do\n"); */
777 indentation += indentation_amount;
778 make_command_string_internal (while_command->action);
779 PRINT_DEFERRED_HEREDOCS ("");
780 indentation -= indentation_amount;
781 semicolon ();
782 newline ("done");
785 static void
786 print_if_command (if_command)
787 IF_COM *if_command;
789 cprintf ("if ");
790 skip_this_indent++;
791 make_command_string_internal (if_command->test);
792 semicolon ();
793 cprintf (" then\n");
794 indentation += indentation_amount;
795 make_command_string_internal (if_command->true_case);
796 PRINT_DEFERRED_HEREDOCS ("");
797 indentation -= indentation_amount;
799 if (if_command->false_case)
801 semicolon ();
802 newline ("else\n");
803 indentation += indentation_amount;
804 make_command_string_internal (if_command->false_case);
805 PRINT_DEFERRED_HEREDOCS ("");
806 indentation -= indentation_amount;
808 semicolon ();
809 newline ("fi");
812 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
813 void
814 print_arith_command (arith_cmd_list)
815 WORD_LIST *arith_cmd_list;
817 cprintf ("((");
818 command_print_word_list (arith_cmd_list, " ");
819 cprintf ("))");
821 #endif
823 #if defined (COND_COMMAND)
824 static void
825 print_cond_node (cond)
826 COND_COM *cond;
828 if (cond->flags & CMD_INVERT_RETURN)
829 cprintf ("! ");
831 if (cond->type == COND_EXPR)
833 cprintf ("( ");
834 print_cond_node (cond->left);
835 cprintf (" )");
837 else if (cond->type == COND_AND)
839 print_cond_node (cond->left);
840 cprintf (" && ");
841 print_cond_node (cond->right);
843 else if (cond->type == COND_OR)
845 print_cond_node (cond->left);
846 cprintf (" || ");
847 print_cond_node (cond->right);
849 else if (cond->type == COND_UNARY)
851 cprintf ("%s", cond->op->word);
852 cprintf (" ");
853 print_cond_node (cond->left);
855 else if (cond->type == COND_BINARY)
857 print_cond_node (cond->left);
858 cprintf (" ");
859 cprintf ("%s", cond->op->word);
860 cprintf (" ");
861 print_cond_node (cond->right);
863 else if (cond->type == COND_TERM)
865 cprintf ("%s", cond->op->word); /* need to add quoting here */
869 void
870 print_cond_command (cond)
871 COND_COM *cond;
873 cprintf ("[[ ");
874 print_cond_node (cond);
875 cprintf (" ]]");
878 #ifdef DEBUG
879 void
880 debug_print_word_list (s, list, sep)
881 char *s;
882 WORD_LIST *list;
883 char *sep;
885 WORD_LIST *w;
887 if (s)
888 fprintf (stderr, "%s: ", s);
889 for (w = list; w; w = w->next)
890 fprintf (stderr, "%s%s", w->word->word, w->next ? sep : "");
891 fprintf (stderr, "\n");
894 void
895 debug_print_cond_command (cond)
896 COND_COM *cond;
898 fprintf (stderr, "DEBUG: ");
899 command_string_index = 0;
900 print_cond_command (cond);
901 fprintf (stderr, "%s\n", the_printed_command);
903 #endif
905 void
906 xtrace_print_cond_term (type, invert, op, arg1, arg2)
907 int type, invert;
908 WORD_DESC *op;
909 char *arg1, *arg2;
911 CHECK_XTRACE_FP;
912 command_string_index = 0;
913 fprintf (xtrace_fp, "%s", indirection_level_string ());
914 fprintf (xtrace_fp, "[[ ");
915 if (invert)
916 fprintf (xtrace_fp, "! ");
918 if (type == COND_UNARY)
920 fprintf (xtrace_fp, "%s ", op->word);
921 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
923 else if (type == COND_BINARY)
925 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
926 fprintf (xtrace_fp, " %s ", op->word);
927 fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
930 fprintf (xtrace_fp, " ]]\n");
932 fflush (xtrace_fp);
934 #endif /* COND_COMMAND */
936 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
937 /* A function to print the words of an arithmetic command when set -x is on. */
938 void
939 xtrace_print_arith_cmd (list)
940 WORD_LIST *list;
942 WORD_LIST *w;
944 CHECK_XTRACE_FP;
945 fprintf (xtrace_fp, "%s", indirection_level_string ());
946 fprintf (xtrace_fp, "(( ");
947 for (w = list; w; w = w->next)
948 fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
949 fprintf (xtrace_fp, " ))\n");
951 fflush (xtrace_fp);
953 #endif
955 void
956 print_simple_command (simple_command)
957 SIMPLE_COM *simple_command;
959 command_print_word_list (simple_command->words, " ");
961 if (simple_command->redirects)
963 cprintf (" ");
964 print_redirection_list (simple_command->redirects);
968 static void
969 print_heredocs (heredocs)
970 REDIRECT *heredocs;
972 REDIRECT *hdtail;
974 cprintf (" ");
975 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
977 print_redirection (hdtail);
978 cprintf ("\n");
980 was_heredoc = 1;
983 static void
984 print_heredoc_bodies (heredocs)
985 REDIRECT *heredocs;
987 REDIRECT *hdtail;
989 cprintf ("\n");
990 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
992 print_heredoc_body (hdtail);
993 cprintf ("\n");
995 was_heredoc = 1;
998 /* Print heredocs that are attached to the command before the connector
999 represented by CSTRING. The parsing semantics require us to print the
1000 here-doc delimiters, then the connector (CSTRING), then the here-doc
1001 bodies. We print the here-doc delimiters in print_redirection_list
1002 and print the connector and the bodies here. We don't print the connector
1003 if it's a `;', but we use it to note not to print an extra space after the
1004 last heredoc body and newline. */
1005 static void
1006 print_deferred_heredocs (cstring)
1007 const char *cstring;
1009 /* We now print the heredoc headers in print_redirection_list */
1010 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
1011 cprintf ("%s", cstring);
1012 if (deferred_heredocs)
1014 print_heredoc_bodies (deferred_heredocs);
1015 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
1016 cprintf (" "); /* make sure there's at least one space */
1017 dispose_redirects (deferred_heredocs);
1018 was_heredoc = 1;
1020 deferred_heredocs = (REDIRECT *)NULL;
1023 static void
1024 print_redirection_list (redirects)
1025 REDIRECT *redirects;
1027 REDIRECT *heredocs, *hdtail, *newredir;
1028 char *rw;
1030 heredocs = (REDIRECT *)NULL;
1031 hdtail = heredocs;
1033 was_heredoc = 0;
1034 while (redirects)
1036 /* Defer printing the here document bodiess until we've printed the rest of the
1037 redirections, but print the headers in the order they're given. */
1038 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
1040 newredir = copy_redirect (redirects);
1041 newredir->next = (REDIRECT *)NULL;
1043 print_heredoc_header (newredir);
1045 if (heredocs)
1047 hdtail->next = newredir;
1048 hdtail = newredir;
1050 else
1051 hdtail = heredocs = newredir;
1053 else if (redirects->instruction == r_duplicating_output_word && (redirects->flags & REDIR_VARASSIGN) == 0 && redirects->redirector.dest == 1)
1055 /* Temporarily translate it as the execution code does. */
1056 rw = redirects->redirectee.filename->word;
1057 if (rw && *rw != '-' && DIGIT (*rw) == 0 && EXPCHAR (*rw) == 0)
1058 redirects->instruction = r_err_and_out;
1059 print_redirection (redirects);
1060 redirects->instruction = r_duplicating_output_word;
1062 else
1063 print_redirection (redirects);
1065 redirects = redirects->next;
1066 if (redirects)
1067 cprintf (" ");
1070 /* Now that we've printed all the other redirections (on one line),
1071 print the here documents. If we're printing a connection, we wait until
1072 we print the connector symbol, then we print the here document bodies */
1073 if (heredocs && printing_connection)
1074 deferred_heredocs = heredocs;
1075 else if (heredocs)
1077 print_heredoc_bodies (heredocs);
1078 dispose_redirects (heredocs);
1082 static void
1083 print_heredoc_header (redirect)
1084 REDIRECT *redirect;
1086 int kill_leading;
1087 char *x;
1089 kill_leading = redirect->instruction == r_deblank_reading_until;
1091 /* Here doc header */
1092 if (redirect->rflags & REDIR_VARASSIGN)
1093 cprintf ("{%s}", redirect->redirector.filename->word);
1094 else if (redirect->redirector.dest != 0)
1095 cprintf ("%d", redirect->redirector.dest);
1097 /* If the here document delimiter is quoted, single-quote it. */
1098 if (redirect->redirectee.filename->flags & W_QUOTED)
1100 x = sh_single_quote (redirect->here_doc_eof);
1101 cprintf ("<<%s%s", kill_leading ? "-" : "", x);
1102 free (x);
1104 else
1105 cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
1108 static void
1109 print_heredoc_body (redirect)
1110 REDIRECT *redirect;
1112 /* Here doc body */
1113 cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
1116 static void
1117 print_redirection (redirect)
1118 REDIRECT *redirect;
1120 int redirector, redir_fd;
1121 WORD_DESC *redirectee, *redir_word;
1123 redirectee = redirect->redirectee.filename;
1124 redir_fd = redirect->redirectee.dest;
1126 redir_word = redirect->redirector.filename;
1127 redirector = redirect->redirector.dest;
1129 switch (redirect->instruction)
1131 case r_input_direction:
1132 if (redirect->rflags & REDIR_VARASSIGN)
1133 cprintf ("{%s}", redir_word->word);
1134 else if (redirector != 0)
1135 cprintf ("%d", redirector);
1136 cprintf ("< %s", redirectee->word);
1137 break;
1139 case r_output_direction:
1140 if (redirect->rflags & REDIR_VARASSIGN)
1141 cprintf ("{%s}", redir_word->word);
1142 else if (redirector != 1)
1143 cprintf ("%d", redirector);
1144 cprintf ("> %s", redirectee->word);
1145 break;
1147 case r_inputa_direction: /* Redirection created by the shell. */
1148 cprintf ("&");
1149 break;
1151 case r_output_force:
1152 if (redirect->rflags & REDIR_VARASSIGN)
1153 cprintf ("{%s}", redir_word->word);
1154 else if (redirector != 1)
1155 cprintf ("%d", redirector);
1156 cprintf (">| %s", redirectee->word);
1157 break;
1159 case r_appending_to:
1160 if (redirect->rflags & REDIR_VARASSIGN)
1161 cprintf ("{%s}", redir_word->word);
1162 else if (redirector != 1)
1163 cprintf ("%d", redirector);
1164 cprintf (">> %s", redirectee->word);
1165 break;
1167 case r_input_output:
1168 if (redirect->rflags & REDIR_VARASSIGN)
1169 cprintf ("{%s}", redir_word->word);
1170 else if (redirector != 1)
1171 cprintf ("%d", redirector);
1172 cprintf ("<> %s", redirectee->word);
1173 break;
1175 case r_deblank_reading_until:
1176 case r_reading_until:
1177 print_heredoc_header (redirect);
1178 cprintf ("\n");
1179 print_heredoc_body (redirect);
1180 break;
1182 case r_reading_string:
1183 if (redirect->rflags & REDIR_VARASSIGN)
1184 cprintf ("{%s}", redir_word->word);
1185 else if (redirector != 0)
1186 cprintf ("%d", redirector);
1187 #if 0
1188 /* Don't need to check whether or not to requote, since original quotes
1189 are still intact. The only thing that has happened is that $'...'
1190 has been replaced with 'expanded ...'. */
1191 if (ansic_shouldquote (redirect->redirectee.filename->word))
1193 char *x;
1194 x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1195 cprintf ("<<< %s", x);
1196 free (x);
1198 else
1199 #endif
1200 cprintf ("<<< %s", redirect->redirectee.filename->word);
1201 break;
1203 case r_duplicating_input:
1204 if (redirect->rflags & REDIR_VARASSIGN)
1205 cprintf ("{%s}<&%d", redir_word->word, redir_fd);
1206 else
1207 cprintf ("%d<&%d", redirector, redir_fd);
1208 break;
1210 case r_duplicating_output:
1211 if (redirect->rflags & REDIR_VARASSIGN)
1212 cprintf ("{%s}>&%d", redir_word->word, redir_fd);
1213 else
1214 cprintf ("%d>&%d", redirector, redir_fd);
1215 break;
1217 case r_duplicating_input_word:
1218 if (redirect->rflags & REDIR_VARASSIGN)
1219 cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
1220 else
1221 cprintf ("%d<&%s", redirector, redirectee->word);
1222 break;
1224 case r_duplicating_output_word:
1225 if (redirect->rflags & REDIR_VARASSIGN)
1226 cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
1227 else
1228 cprintf ("%d>&%s", redirector, redirectee->word);
1229 break;
1231 case r_move_input:
1232 if (redirect->rflags & REDIR_VARASSIGN)
1233 cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
1234 else
1235 cprintf ("%d<&%d-", redirector, redir_fd);
1236 break;
1238 case r_move_output:
1239 if (redirect->rflags & REDIR_VARASSIGN)
1240 cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
1241 else
1242 cprintf ("%d>&%d-", redirector, redir_fd);
1243 break;
1245 case r_move_input_word:
1246 if (redirect->rflags & REDIR_VARASSIGN)
1247 cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
1248 else
1249 cprintf ("%d<&%s-", redirector, redirectee->word);
1250 break;
1252 case r_move_output_word:
1253 if (redirect->rflags & REDIR_VARASSIGN)
1254 cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
1255 else
1256 cprintf ("%d>&%s-", redirector, redirectee->word);
1257 break;
1259 case r_close_this:
1260 if (redirect->rflags & REDIR_VARASSIGN)
1261 cprintf ("{%s}>&-", redir_word->word);
1262 else
1263 cprintf ("%d>&-", redirector);
1264 break;
1266 case r_err_and_out:
1267 cprintf ("&> %s", redirectee->word);
1268 break;
1270 case r_append_err_and_out:
1271 cprintf ("&>> %s", redirectee->word);
1272 break;
1276 static void
1277 reset_locals ()
1279 inside_function_def = 0;
1280 indentation = 0;
1281 printing_connection = 0;
1282 deferred_heredocs = 0;
1285 static void
1286 print_function_def (func)
1287 FUNCTION_DEF *func;
1289 COMMAND *cmdcopy;
1290 REDIRECT *func_redirects;
1292 func_redirects = NULL;
1293 /* When in posix mode, print functions as posix specifies them. */
1294 if (posixly_correct == 0)
1295 cprintf ("function %s () \n", func->name->word);
1296 else
1297 cprintf ("%s () \n", func->name->word);
1298 add_unwind_protect (reset_locals, 0);
1300 indent (indentation);
1301 cprintf ("{ \n");
1303 inside_function_def++;
1304 indentation += indentation_amount;
1306 cmdcopy = copy_command (func->command);
1307 if (cmdcopy->type == cm_group)
1309 func_redirects = cmdcopy->redirects;
1310 cmdcopy->redirects = (REDIRECT *)NULL;
1312 make_command_string_internal (cmdcopy->type == cm_group
1313 ? cmdcopy->value.Group->command
1314 : cmdcopy);
1315 PRINT_DEFERRED_HEREDOCS ("");
1317 remove_unwind_protect ();
1318 indentation -= indentation_amount;
1319 inside_function_def--;
1321 if (func_redirects)
1322 { /* { */
1323 newline ("} ");
1324 print_redirection_list (func_redirects);
1325 cmdcopy->redirects = func_redirects;
1327 else
1328 newline ("}");
1330 dispose_command (cmdcopy);
1333 /* Return the string representation of the named function.
1334 NAME is the name of the function.
1335 COMMAND is the function body. It should be a GROUP_COM.
1336 flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1337 flags&FUNC_EXTERNAL means convert from internal to external form
1339 char *
1340 named_function_string (name, command, flags)
1341 char *name;
1342 COMMAND *command;
1343 int flags;
1345 char *result;
1346 int old_indent, old_amount;
1347 COMMAND *cmdcopy;
1348 REDIRECT *func_redirects;
1350 old_indent = indentation;
1351 old_amount = indentation_amount;
1352 command_string_index = was_heredoc = 0;
1353 deferred_heredocs = 0;
1355 if (name && *name)
1357 if (find_reserved_word (name) >= 0)
1358 cprintf ("function ");
1359 cprintf ("%s ", name);
1362 cprintf ("() ");
1364 if ((flags & FUNC_MULTILINE) == 0)
1366 indentation = 1;
1367 indentation_amount = 0;
1369 else
1371 cprintf ("\n");
1372 indentation += indentation_amount;
1375 inside_function_def++;
1377 cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
1379 cmdcopy = copy_command (command);
1380 /* Take any redirections specified in the function definition (which should
1381 apply to the function as a whole) and save them for printing later. */
1382 func_redirects = (REDIRECT *)NULL;
1383 if (cmdcopy->type == cm_group)
1385 func_redirects = cmdcopy->redirects;
1386 cmdcopy->redirects = (REDIRECT *)NULL;
1388 make_command_string_internal (cmdcopy->type == cm_group
1389 ? cmdcopy->value.Group->command
1390 : cmdcopy);
1391 PRINT_DEFERRED_HEREDOCS ("");
1393 indentation = old_indent;
1394 indentation_amount = old_amount;
1395 inside_function_def--;
1397 if (func_redirects)
1398 { /* { */
1399 newline ("} ");
1400 print_redirection_list (func_redirects);
1401 cmdcopy->redirects = func_redirects;
1403 else
1404 newline ("}");
1406 result = the_printed_command;
1408 if ((flags & FUNC_MULTILINE) == 0)
1410 #if 0
1411 register int i;
1412 for (i = 0; result[i]; i++)
1413 if (result[i] == '\n')
1415 strcpy (result + i, result + i + 1);
1416 --i;
1418 #else
1419 if (result[2] == '\n') /* XXX -- experimental */
1420 memmove (result + 2, result + 3, strlen (result) - 2);
1421 #endif
1424 dispose_command (cmdcopy);
1426 if (flags & FUNC_EXTERNAL)
1427 result = remove_quoted_escapes (result);
1429 return (result);
1432 static void
1433 newline (string)
1434 char *string;
1436 cprintf ("\n");
1437 indent (indentation);
1438 if (string && *string)
1439 cprintf ("%s", string);
1442 static char *indentation_string;
1443 static int indentation_size;
1445 static void
1446 indent (amount)
1447 int amount;
1449 register int i;
1451 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1453 for (i = 0; amount > 0; amount--)
1454 indentation_string[i++] = ' ';
1455 indentation_string[i] = '\0';
1456 cprintf ("%s", indentation_string);
1459 static void
1460 semicolon ()
1462 if (command_string_index > 0 &&
1463 (the_printed_command[command_string_index - 1] == '&' ||
1464 the_printed_command[command_string_index - 1] == '\n'))
1465 return;
1466 cprintf (";");
1469 /* How to make the string. */
1470 static void
1471 #if defined (PREFER_STDARG)
1472 cprintf (const char *control, ...)
1473 #else
1474 cprintf (control, va_alist)
1475 const char *control;
1476 va_dcl
1477 #endif
1479 register const char *s;
1480 char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (unsigned int) + 1];
1481 int digit_arg, arg_len, c;
1482 va_list args;
1484 SH_VA_START (args, control);
1486 arg_len = strlen (control);
1487 the_printed_command_resize (arg_len + 1);
1489 char_arg[1] = '\0';
1490 s = control;
1491 while (s && *s)
1493 c = *s++;
1494 argp = (char *)NULL;
1495 if (c != '%' || !*s)
1497 char_arg[0] = c;
1498 argp = char_arg;
1499 arg_len = 1;
1501 else
1503 c = *s++;
1504 switch (c)
1506 case '%':
1507 char_arg[0] = c;
1508 argp = char_arg;
1509 arg_len = 1;
1510 break;
1512 case 's':
1513 argp = va_arg (args, char *);
1514 arg_len = strlen (argp);
1515 break;
1517 case 'd':
1518 /* Represent an out-of-range file descriptor with an out-of-range
1519 integer value. We can do this because the only use of `%d' in
1520 the calls to cprintf is to output a file descriptor number for
1521 a redirection. */
1522 digit_arg = va_arg (args, int);
1523 if (digit_arg < 0)
1525 sprintf (intbuf, "%u", (unsigned int)-1);
1526 argp = intbuf;
1528 else
1529 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1530 arg_len = strlen (argp);
1531 break;
1533 case 'c':
1534 char_arg[0] = va_arg (args, int);
1535 argp = char_arg;
1536 arg_len = 1;
1537 break;
1539 default:
1540 programming_error (_("cprintf: `%c': invalid format character"), c);
1541 /*NOTREACHED*/
1545 if (argp && arg_len)
1547 the_printed_command_resize (arg_len + 1);
1548 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1549 command_string_index += arg_len;
1553 va_end (args);
1555 the_printed_command[command_string_index] = '\0';
1558 /* Ensure that there is enough space to stuff LENGTH characters into
1559 THE_PRINTED_COMMAND. */
1560 static void
1561 the_printed_command_resize (length)
1562 int length;
1564 if (the_printed_command == 0)
1566 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1567 the_printed_command = (char *)xmalloc (the_printed_command_size);
1568 command_string_index = 0;
1570 else if ((command_string_index + length) >= the_printed_command_size)
1572 int new;
1573 new = command_string_index + length + 1;
1575 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1576 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1577 the_printed_command_size = new;
1579 the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
1583 #if defined (HAVE_VPRINTF)
1584 /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1585 also available.'' */
1587 static void
1588 #if defined (PREFER_STDARG)
1589 xprintf (const char *format, ...)
1590 #else
1591 xprintf (format, va_alist)
1592 const char *format;
1593 va_dcl
1594 #endif
1596 va_list args;
1598 SH_VA_START (args, format);
1600 vfprintf (stdout, format, args);
1601 va_end (args);
1604 #else
1606 static void
1607 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1608 const char *format;
1610 printf (format, arg1, arg2, arg3, arg4, arg5);
1613 #endif /* !HAVE_VPRINTF */