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