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