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