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