]> git.ipfire.org Git - thirdparty/bash.git/blob - print_cmd.c
Imported from ../bash-2.05.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 (sh_contains_shell_metas (t))
324 {
325 x = sh_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 #ifdef DEBUG
585 void
586 debug_print_cond_command (cond)
587 COND_COM *cond;
588 {
589 fprintf (stderr, "DEBUG: ");
590 command_string_index = 0;
591 print_cond_command (cond);
592 fprintf (stderr, "%s\n", the_printed_command);
593 }
594 #endif
595
596 void
597 xtrace_print_cond_term (type, invert, op, arg1, arg2)
598 int type, invert;
599 WORD_DESC *op;
600 char *arg1, *arg2;
601 {
602 command_string_index = 0;
603 fprintf (stderr, "%s", indirection_level_string ());
604 fprintf (stderr, "[[ ");
605 if (invert)
606 fprintf (stderr, "! ");
607
608 if (type == COND_UNARY)
609 {
610 fprintf (stderr, "%s ", op->word);
611 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
612 }
613 else if (type == COND_BINARY)
614 {
615 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
616 fprintf (stderr, " %s ", op->word);
617 fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
618 }
619
620 fprintf (stderr, " ]]\n");
621 }
622 #endif /* COND_COMMAND */
623
624 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
625 /* A function to print the words of an arithmetic command when set -x is on. */
626 void
627 xtrace_print_arith_cmd (list)
628 WORD_LIST *list;
629 {
630 WORD_LIST *w;
631
632 fprintf (stderr, "%s", indirection_level_string ());
633 fprintf (stderr, "(( ");
634 for (w = list; w; w = w->next)
635 fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
636 fprintf (stderr, " ))\n");
637 }
638 #endif
639
640 void
641 print_simple_command (simple_command)
642 SIMPLE_COM *simple_command;
643 {
644 command_print_word_list (simple_command->words, " ");
645
646 if (simple_command->redirects)
647 {
648 cprintf (" ");
649 print_redirection_list (simple_command->redirects);
650 }
651 }
652
653 static void
654 print_redirection_list (redirects)
655 REDIRECT *redirects;
656 {
657 REDIRECT *heredocs, *hdtail, *newredir;
658
659 heredocs = (REDIRECT *)NULL;
660 hdtail = heredocs;
661
662 was_heredoc = 0;
663 while (redirects)
664 {
665 /* Defer printing the here documents until we've printed the
666 rest of the redirections. */
667 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
668 {
669 newredir = copy_redirect (redirects);
670 newredir->next = (REDIRECT *)NULL;
671 if (heredocs)
672 {
673 hdtail->next = newredir;
674 hdtail = newredir;
675 }
676 else
677 hdtail = heredocs = newredir;
678 }
679 else
680 print_redirection (redirects);
681
682 redirects = redirects->next;
683 if (redirects)
684 cprintf (" ");
685 }
686
687 /* Now that we've printed all the other redirections (on one line),
688 print the here documents. */
689 if (heredocs)
690 {
691 cprintf (" ");
692 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
693 {
694 print_redirection (hdtail);
695 cprintf ("\n");
696 }
697 dispose_redirects (heredocs);
698 was_heredoc = 1;
699 }
700 }
701
702 static void
703 print_redirection (redirect)
704 REDIRECT *redirect;
705 {
706 int kill_leading, redirector, redir_fd;
707 WORD_DESC *redirectee;
708
709 kill_leading = 0;
710 redirectee = redirect->redirectee.filename;
711 redirector = redirect->redirector;
712 redir_fd = redirect->redirectee.dest;
713
714 switch (redirect->instruction)
715 {
716 case r_output_direction:
717 if (redirector != 1)
718 cprintf ("%d", redirector);
719 cprintf (">%s", redirectee->word);
720 break;
721
722 case r_input_direction:
723 if (redirector != 0)
724 cprintf ("%d", redirector);
725 cprintf ("<%s", redirectee->word);
726 break;
727
728 case r_inputa_direction: /* Redirection created by the shell. */
729 cprintf ("&");
730 break;
731
732 case r_appending_to:
733 if (redirector != 1)
734 cprintf ("%d", redirector);
735 cprintf (">>%s", redirectee->word);
736 break;
737
738 case r_deblank_reading_until:
739 kill_leading++;
740 /* ... */
741 case r_reading_until:
742 if (redirector != 0)
743 cprintf ("%d", redirector);
744 /* If the here document delimiter is quoted, single-quote it. */
745 if (redirect->redirectee.filename->flags & W_QUOTED)
746 {
747 char *x;
748 x = sh_single_quote (redirect->here_doc_eof);
749 cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
750 free (x);
751 }
752 else
753 cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
754 cprintf ("%s%s",
755 redirect->redirectee.filename->word, redirect->here_doc_eof);
756 break;
757
758 case r_duplicating_input:
759 cprintf ("%d<&%d", redirector, redir_fd);
760 break;
761
762 case r_duplicating_output:
763 cprintf ("%d>&%d", redirector, redir_fd);
764 break;
765
766 case r_duplicating_input_word:
767 cprintf ("%d<&%s", redirector, redirectee->word);
768 break;
769
770 case r_duplicating_output_word:
771 cprintf ("%d>&%s", redirector, redirectee->word);
772 break;
773
774 case r_close_this:
775 cprintf ("%d>&-", redirector);
776 break;
777
778 case r_err_and_out:
779 cprintf (">&%s", redirectee->word);
780 break;
781
782 case r_input_output:
783 if (redirector != 1)
784 cprintf ("%d", redirector);
785 cprintf ("<>%s", redirectee->word);
786 break;
787
788 case r_output_force:
789 if (redirector != 1)
790 cprintf ("%d", redirector);
791 cprintf (">|%s", redirectee->word);
792 break;
793 }
794 }
795
796 static void
797 reset_locals ()
798 {
799 inside_function_def = 0;
800 indentation = 0;
801 }
802
803 static void
804 print_function_def (func)
805 FUNCTION_DEF *func;
806 {
807 COMMAND *cmdcopy;
808 REDIRECT *func_redirects;
809
810 cprintf ("function %s () \n", func->name->word);
811 add_unwind_protect (reset_locals, 0);
812
813 indent (indentation);
814 cprintf ("{ \n");
815
816 inside_function_def++;
817 indentation += indentation_amount;
818
819 cmdcopy = copy_command (func->command);
820 if (cmdcopy->type == cm_group)
821 {
822 func_redirects = cmdcopy->redirects;
823 cmdcopy->redirects = (REDIRECT *)NULL;
824 }
825 make_command_string_internal (cmdcopy->type == cm_group
826 ? cmdcopy->value.Group->command
827 : cmdcopy);
828
829 remove_unwind_protect ();
830 indentation -= indentation_amount;
831 inside_function_def--;
832
833 if (func_redirects)
834 { /* { */
835 newline ("} ");
836 print_redirection_list (func_redirects);
837 cmdcopy->redirects = func_redirects;
838 }
839 else
840 newline ("}");
841
842 dispose_command (cmdcopy);
843 }
844
845 /* Return the string representation of the named function.
846 NAME is the name of the function.
847 COMMAND is the function body. It should be a GROUP_COM.
848 MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
849 */
850 char *
851 named_function_string (name, command, multi_line)
852 char *name;
853 COMMAND *command;
854 int multi_line;
855 {
856 char *result;
857 int old_indent, old_amount;
858 COMMAND *cmdcopy;
859 REDIRECT *func_redirects;
860
861 old_indent = indentation;
862 old_amount = indentation_amount;
863 command_string_index = was_heredoc = 0;
864
865 if (name && *name)
866 cprintf ("%s ", name);
867
868 cprintf ("() ");
869
870 if (multi_line == 0)
871 {
872 indentation = 1;
873 indentation_amount = 0;
874 }
875 else
876 {
877 cprintf ("\n");
878 indentation += indentation_amount;
879 }
880
881 inside_function_def++;
882
883 cprintf (multi_line ? "{ \n" : "{ ");
884
885 cmdcopy = copy_command (command);
886 /* Take any redirections specified in the function definition (which should
887 apply to the function as a whole) and save them for printing later. */
888 func_redirects = (REDIRECT *)NULL;
889 if (cmdcopy->type == cm_group)
890 {
891 func_redirects = cmdcopy->redirects;
892 cmdcopy->redirects = (REDIRECT *)NULL;
893 }
894 make_command_string_internal (cmdcopy->type == cm_group
895 ? cmdcopy->value.Group->command
896 : cmdcopy);
897
898 indentation = old_indent;
899 indentation_amount = old_amount;
900 inside_function_def--;
901
902 if (func_redirects)
903 { /* { */
904 newline ("} ");
905 print_redirection_list (func_redirects);
906 cmdcopy->redirects = func_redirects;
907 }
908 else
909 newline ("}");
910
911 result = the_printed_command;
912
913 if (!multi_line)
914 {
915 #if 0
916 register int i;
917 for (i = 0; result[i]; i++)
918 if (result[i] == '\n')
919 {
920 strcpy (result + i, result + i + 1);
921 --i;
922 }
923 #else
924 if (result[2] == '\n') /* XXX -- experimental */
925 strcpy (result + 2, result + 3);
926 #endif
927 }
928
929 dispose_command (cmdcopy);
930
931 return (result);
932 }
933
934 static void
935 newline (string)
936 char *string;
937 {
938 cprintf ("\n");
939 indent (indentation);
940 if (string && *string)
941 cprintf ("%s", string);
942 }
943
944 static char *indentation_string;
945 static int indentation_size;
946
947 static void
948 indent (amount)
949 int amount;
950 {
951 register int i;
952
953 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
954
955 for (i = 0; amount > 0; amount--)
956 indentation_string[i++] = ' ';
957 indentation_string[i] = '\0';
958 cprintf (indentation_string);
959 }
960
961 static void
962 semicolon ()
963 {
964 if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
965 return;
966 cprintf (";");
967 }
968
969 #if !defined (USE_VARARGS)
970 /* How to make the string. */
971 static void
972 cprintf (format, arg1, arg2)
973 char *format, *arg1, *arg2;
974 {
975 register char *s;
976 char char_arg[2], *argp, *args[2], intbuf[32];
977 int arg_len, c, arg_index;
978
979 args[arg_index = 0] = arg1;
980 args[1] = arg2;
981
982 arg_len = strlen (format);
983 the_printed_command_resize (arg_len + 1);
984
985 char_arg[1] = '\0';
986 s = format;
987 while (s && *s)
988 {
989 int free_argp = 0;
990 c = *s++;
991 if (c != '%' || !*s)
992 {
993 argp = s;
994 arg_len = 1;
995 }
996 else
997 {
998 c = *s++;
999 switch (c)
1000 {
1001 case '%':
1002 char_arg[0] = c;
1003 argp = char_arg;
1004 arg_len = 1;
1005 break;
1006
1007 case 's':
1008 argp = (char *)args[arg_index++];
1009 arg_len = strlen (argp);
1010 break;
1011
1012 case 'd':
1013 argp = inttostr (pointer_to_int (args[arg_index]), intbuf, sizeof (intbuf));
1014 arg_index++;
1015 arg_len = strlen (argp);
1016 break;
1017
1018 case 'c':
1019 char_arg[0] = pointer_to_int (args[arg_index]);
1020 arg_index++;
1021 argp = char_arg;
1022 arg_len = 1;
1023 break;
1024
1025 default:
1026 programming_error ("cprintf: bad `%%' argument (%c)", c);
1027 }
1028 }
1029 if (argp)
1030 {
1031 the_printed_command_resize (arg_len + 1);
1032 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1033 command_string_index += arg_len;
1034 if (free_argp)
1035 free (argp);
1036 }
1037 }
1038
1039 the_printed_command[command_string_index] = '\0';
1040 }
1041
1042 #else /* We have support for varargs. */
1043
1044 /* How to make the string. */
1045 static void
1046 #if defined (PREFER_STDARG)
1047 cprintf (char *control, ...)
1048 #else
1049 cprintf (control, va_alist)
1050 char *control;
1051 va_dcl
1052 #endif
1053 {
1054 register char *s;
1055 char char_arg[2], *argp, intbuf[32];
1056 int digit_arg, arg_len, c;
1057 va_list args;
1058
1059 #if defined (PREFER_STDARG)
1060 va_start (args, control);
1061 #else
1062 va_start (args);
1063 #endif
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 int free_argp;
1073 free_argp = 0;
1074 c = *s++;
1075 argp = (char *)NULL;
1076 if (c != '%' || !*s)
1077 {
1078 argp = s - 1;
1079 arg_len = 1;
1080 }
1081 else
1082 {
1083 c = *s++;
1084 switch (c)
1085 {
1086 case '%':
1087 char_arg[0] = c;
1088 argp = char_arg;
1089 arg_len = 1;
1090 break;
1091
1092 case 's':
1093 argp = va_arg (args, char *);
1094 arg_len = strlen (argp);
1095 break;
1096
1097 case 'd':
1098 digit_arg = va_arg (args, int);
1099 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1100 arg_len = strlen (argp);
1101 break;
1102
1103 case 'c':
1104 char_arg[0] = va_arg (args, int);
1105 argp = char_arg;
1106 arg_len = 1;
1107 break;
1108
1109 default:
1110 programming_error ("cprintf: bad `%%' argument (%c)", c);
1111 /*NOTREACHED*/
1112 }
1113 }
1114
1115 if (argp && arg_len)
1116 {
1117 the_printed_command_resize (arg_len + 1);
1118 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1119 command_string_index += arg_len;
1120 if (free_argp)
1121 free (argp);
1122 }
1123 }
1124
1125 the_printed_command[command_string_index] = '\0';
1126 }
1127 #endif /* HAVE_VARARGS_H */
1128
1129 /* Ensure that there is enough space to stuff LENGTH characters into
1130 THE_PRINTED_COMMAND. */
1131 static void
1132 the_printed_command_resize (length)
1133 int length;
1134 {
1135 if (the_printed_command == 0)
1136 {
1137 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1138 the_printed_command = xmalloc (the_printed_command_size);
1139 command_string_index = 0;
1140 }
1141 else if ((command_string_index + length) >= the_printed_command_size)
1142 {
1143 int new;
1144 new = command_string_index + length + 1;
1145
1146 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1147 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1148 the_printed_command_size = new;
1149
1150 the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
1151 }
1152 }
1153
1154 #if defined (HAVE_VFPRINTF)
1155
1156 static void
1157 #if defined (PREFER_STDARG)
1158 xprintf (const char *format, ...)
1159 #else
1160 xprintf (format, va_alist)
1161 const char *format;
1162 va_dcl
1163 #endif
1164 {
1165 va_list args;
1166
1167 #if defined (PREFER_STDARG)
1168 va_start (args, format);
1169 #else
1170 va_start (args);
1171 #endif
1172
1173 vfprintf (stdout, format, args);
1174 va_end (args);
1175 }
1176
1177 #else
1178
1179 static void
1180 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1181 char *format;
1182 {
1183 printf (format, arg1, arg2, arg3, arg4, arg5);
1184 }
1185
1186 #endif /* !HAVE_VFPRINTF */