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