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