]> git.ipfire.org Git - thirdparty/bash.git/blob - print_cmd.c
Imported from ../bash-2.02.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 1, 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, 675 Mass Ave, Cambridge, MA 02139, 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
88 #define PRINTED_COMMAND_INITIAL_SIZE 64
89 #define PRINTED_COMMAND_GROW_SIZE 128
90
91 char *the_printed_command = (char *)NULL;
92 int the_printed_command_size = 0;
93 int command_string_index = 0;
94
95 /* Non-zero means the stuff being printed is inside of a function def. */
96 static int inside_function_def;
97 static int skip_this_indent;
98 static int was_heredoc;
99
100 /* The depth of the group commands that we are currently printing. This
101 includes the group command that is a function body. */
102 static int group_command_nesting;
103
104 /* Print COMMAND (a command tree) on standard output. */
105 void
106 print_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. */
117 char *
118 make_command_string (command)
119 COMMAND *command;
120 {
121 command_string_index = was_heredoc = 0;
122 make_command_string_internal (command);
123 return (the_printed_command);
124 }
125
126 /* The internal function. This is the real workhorse. */
127 static void
128 make_command_string_internal (command)
129 COMMAND *command;
130 {
131 if (command == 0)
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
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 (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
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
193 case cm_simple:
194 print_simple_command (command->value.Simple);
195 break;
196
197 case cm_connection:
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;
228
229 case ';':
230 if (was_heredoc == 0)
231 cprintf (";");
232 else
233 was_heredoc = 0;
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;
253
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:
263 programming_error ("print_command: bad command type `%d'", command->type);
264 break;
265 }
266
267 if (command->flags & CMD_WANT_SUBSHELL)
268 cprintf (" )");
269
270 if (command->redirects)
271 print_redirection_list (command->redirects);
272 }
273 }
274
275 static void
276 _print_word_list (list, separator, pfunc)
277 WORD_LIST *list;
278 char *separator;
279 VFunction *pfunc;
280 {
281 WORD_LIST *w;
282
283 for (w = list; w; w = w->next)
284 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
285 }
286
287 void
288 print_word_list (list, separator)
289 WORD_LIST *list;
290 char *separator;
291 {
292 _print_word_list (list, separator, xprintf);
293 }
294
295 /* A function to print the words of a simple command when set -x is on. */
296 void
297 xtrace_print_word_list (list)
298 WORD_LIST *list;
299 {
300 WORD_LIST *w;
301 char *t, *x;
302
303 fprintf (stderr, "%s", indirection_level_string ());
304 for (w = list; w; w = w->next)
305 {
306 t = w->word->word;
307 if (t == 0 || *t == '\0')
308 fprintf (stderr, "''%s", w->next ? " " : "");
309 else if (contains_shell_metas (t))
310 {
311 x = single_quote (t);
312 fprintf (stderr, "%s%s", x, w->next ? " " : "");
313 free (x);
314 }
315 else
316 fprintf (stderr, "%s%s", t, w->next ? " " : "");
317 }
318 fprintf (stderr, "\n");
319 }
320
321 static void
322 command_print_word_list (list, separator)
323 WORD_LIST *list;
324 char *separator;
325 {
326 _print_word_list (list, separator, cprintf);
327 }
328
329 static void
330 print_for_command (for_command)
331 FOR_COM *for_command;
332 {
333 cprintf ("for %s in ", for_command->name->word);
334 command_print_word_list (for_command->map_list, " ");
335 cprintf (";");
336 newline ("do\n");
337 indentation += indentation_amount;
338 make_command_string_internal (for_command->action);
339 semicolon ();
340 indentation -= indentation_amount;
341 newline ("done");
342 }
343
344 #if defined (SELECT_COMMAND)
345 static void
346 print_select_command (select_command)
347 SELECT_COM *select_command;
348 {
349 cprintf ("select %s in ", select_command->name->word);
350 command_print_word_list (select_command->map_list, " ");
351 cprintf (";");
352 newline ("do\n");
353 indentation += indentation_amount;
354 make_command_string_internal (select_command->action);
355 semicolon ();
356 indentation -= indentation_amount;
357 newline ("done");
358 }
359 #endif /* SELECT_COMMAND */
360
361 static void
362 print_group_command (group_command)
363 GROUP_COM *group_command;
364 {
365 group_command_nesting++;
366 cprintf ("{ ");
367
368 if (inside_function_def == 0)
369 skip_this_indent++;
370 else
371 {
372 /* This is a group command { ... } inside of a function
373 definition, and should be printed as a multiline group
374 command, using the current indentation. */
375 cprintf ("\n");
376 indentation += indentation_amount;
377 }
378
379 make_command_string_internal (group_command->command);
380
381 if (inside_function_def)
382 {
383 cprintf ("\n");
384 indentation -= indentation_amount;
385 indent (indentation);
386 }
387 else
388 {
389 semicolon ();
390 cprintf (" ");
391 }
392
393 cprintf ("}");
394
395 group_command_nesting--;
396 }
397
398 static void
399 print_case_command (case_command)
400 CASE_COM *case_command;
401 {
402 cprintf ("case %s in ", case_command->word->word);
403 if (case_command->clauses)
404 print_case_clauses (case_command->clauses);
405 newline ("esac");
406 }
407
408 static void
409 print_case_clauses (clauses)
410 PATTERN_LIST *clauses;
411 {
412 indentation += indentation_amount;
413 while (clauses)
414 {
415 newline ("");
416 command_print_word_list (clauses->patterns, " | ");
417 cprintf (")\n");
418 indentation += indentation_amount;
419 make_command_string_internal (clauses->action);
420 indentation -= indentation_amount;
421 newline (";;");
422 clauses = clauses->next;
423 }
424 indentation -= indentation_amount;
425 }
426
427 static void
428 print_while_command (while_command)
429 WHILE_COM *while_command;
430 {
431 print_until_or_while (while_command, "while");
432 }
433
434 static void
435 print_until_command (while_command)
436 WHILE_COM *while_command;
437 {
438 print_until_or_while (while_command, "until");
439 }
440
441 static void
442 print_until_or_while (while_command, which)
443 WHILE_COM *while_command;
444 char *which;
445 {
446 cprintf ("%s ", which);
447 skip_this_indent++;
448 make_command_string_internal (while_command->test);
449 semicolon ();
450 cprintf (" do\n"); /* was newline ("do\n"); */
451 indentation += indentation_amount;
452 make_command_string_internal (while_command->action);
453 indentation -= indentation_amount;
454 semicolon ();
455 newline ("done");
456 }
457
458 static void
459 print_if_command (if_command)
460 IF_COM *if_command;
461 {
462 cprintf ("if ");
463 skip_this_indent++;
464 make_command_string_internal (if_command->test);
465 semicolon ();
466 cprintf (" then\n");
467 indentation += indentation_amount;
468 make_command_string_internal (if_command->true_case);
469 indentation -= indentation_amount;
470
471 if (if_command->false_case)
472 {
473 semicolon ();
474 newline ("else\n");
475 indentation += indentation_amount;
476 make_command_string_internal (if_command->false_case);
477 indentation -= indentation_amount;
478 }
479 semicolon ();
480 newline ("fi");
481 }
482
483 #if defined (DPAREN_ARITHMETIC)
484 static void
485 print_arith_command (arith_command)
486 ARITH_COM *arith_command;
487 {
488 cprintf ("(( ");
489 command_print_word_list (arith_command->exp, " ");
490 cprintf (" ))");
491 }
492
493 #if defined (COND_COMMAND)
494 static void
495 print_cond_node (cond)
496 COND_COM *cond;
497 {
498 if (cond->flags & CMD_INVERT_RETURN)
499 cprintf ("! ");
500
501 if (cond->type == COND_EXPR)
502 {
503 cprintf ("( ");
504 print_cond_node (cond->left);
505 cprintf (" )");
506 }
507 else if (cond->type == COND_AND)
508 {
509 print_cond_node (cond->left);
510 cprintf (" && ");
511 print_cond_node (cond->right);
512 }
513 else if (cond->type == COND_OR)
514 {
515 print_cond_node (cond->left);
516 cprintf (" || ");
517 print_cond_node (cond->right);
518 }
519 else if (cond->type == COND_UNARY)
520 {
521 cprintf (cond->op->word);
522 cprintf (" ");
523 print_cond_node (cond->left);
524 }
525 else if (cond->type == COND_BINARY)
526 {
527 print_cond_node (cond->left);
528 cprintf (" ");
529 cprintf (cond->op->word);
530 cprintf (" ");
531 print_cond_node (cond->right);
532 }
533 else if (cond->type == COND_TERM)
534 {
535 cprintf (cond->op->word); /* need to add quoting here */
536 }
537 }
538
539 static void
540 print_cond_command (cond)
541 COND_COM *cond;
542 {
543 cprintf ("[[ ");
544 print_cond_node (cond);
545 cprintf (" ]]");
546 }
547
548 void
549 debug_print_cond_command (cond)
550 COND_COM *cond;
551 {
552 fprintf (stderr, "DEBUG: ");
553 command_string_index = 0;
554 print_cond_command (cond);
555 fprintf (stderr, "%s\n", the_printed_command);
556 }
557
558 void
559 xtrace_print_cond_term (type, invert, op, arg1, arg2)
560 int type, invert;
561 WORD_DESC *op;
562 char *arg1, *arg2;
563 {
564 command_string_index = 0;
565 fprintf (stderr, "%s", indirection_level_string ());
566 fprintf (stderr, "[[ ");
567 if (invert)
568 fprintf (stderr, "! ");
569
570 if (type == COND_UNARY)
571 {
572 fprintf (stderr, "%s ", op->word);
573 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
574 }
575 else if (type == COND_BINARY)
576 {
577 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
578 fprintf (stderr, " %s ", op->word);
579 fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
580 }
581
582 fprintf (stderr, " ]]\n");
583 }
584 #endif /* COND_COMMAND */
585
586 /* A function to print the words of an arithmetic command when set -x is on. */
587 void
588 xtrace_print_arith_cmd (list)
589 WORD_LIST *list;
590 {
591 WORD_LIST *w;
592
593 fprintf (stderr, "%s", indirection_level_string ());
594 fprintf (stderr, "(( ");
595 for (w = list; w; w = w->next)
596 fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
597 fprintf (stderr, " ))\n");
598 }
599 #endif
600
601 void
602 print_simple_command (simple_command)
603 SIMPLE_COM *simple_command;
604 {
605 command_print_word_list (simple_command->words, " ");
606
607 if (simple_command->redirects)
608 {
609 cprintf (" ");
610 print_redirection_list (simple_command->redirects);
611 }
612 }
613
614 static void
615 print_redirection_list (redirects)
616 REDIRECT *redirects;
617 {
618 REDIRECT *heredocs, *hdtail, *newredir;
619
620 heredocs = (REDIRECT *)NULL;
621 hdtail = heredocs;
622
623 was_heredoc = 0;
624 while (redirects)
625 {
626 /* Defer printing the here documents until we've printed the
627 rest of the redirections. */
628 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
629 {
630 newredir = copy_redirect (redirects);
631 newredir->next = (REDIRECT *)NULL;
632 if (heredocs)
633 {
634 hdtail->next = newredir;
635 hdtail = newredir;
636 }
637 else
638 hdtail = heredocs = newredir;
639 }
640 else
641 print_redirection (redirects);
642
643 redirects = redirects->next;
644 if (redirects)
645 cprintf (" ");
646 }
647
648 /* Now that we've printed all the other redirections (on one line),
649 print the here documents. */
650 if (heredocs)
651 {
652 cprintf (" ");
653 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
654 {
655 print_redirection (hdtail);
656 cprintf ("\n");
657 }
658 dispose_redirects (heredocs);
659 was_heredoc = 1;
660 }
661 }
662
663 static void
664 print_redirection (redirect)
665 REDIRECT *redirect;
666 {
667 int kill_leading, redirector, redir_fd;
668 WORD_DESC *redirectee;
669
670 kill_leading = 0;
671 redirectee = redirect->redirectee.filename;
672 redirector = redirect->redirector;
673 redir_fd = redirect->redirectee.dest;
674
675 switch (redirect->instruction)
676 {
677 case r_output_direction:
678 if (redirector != 1)
679 cprintf ("%d", redirector);
680 cprintf (">%s", redirectee->word);
681 break;
682
683 case r_input_direction:
684 if (redirector != 0)
685 cprintf ("%d", redirector);
686 cprintf ("<%s", redirectee->word);
687 break;
688
689 case r_inputa_direction: /* Redirection created by the shell. */
690 cprintf ("&");
691 break;
692
693 case r_appending_to:
694 if (redirector != 1)
695 cprintf ("%d", redirector);
696 cprintf (">>%s", redirectee->word);
697 break;
698
699 case r_deblank_reading_until:
700 kill_leading++;
701 /* ... */
702 case r_reading_until:
703 if (redirector != 0)
704 cprintf ("%d", redirector);
705 /* If the here document delimiter is quoted, single-quote it. */
706 if (redirect->redirectee.filename->flags & W_QUOTED)
707 {
708 char *x;
709 x = single_quote (redirect->here_doc_eof);
710 cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
711 free (x);
712 }
713 else
714 cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
715 cprintf ("%s%s",
716 redirect->redirectee.filename->word, redirect->here_doc_eof);
717 break;
718
719 case r_duplicating_input:
720 cprintf ("%d<&%d", redirector, redir_fd);
721 break;
722
723 case r_duplicating_output:
724 cprintf ("%d>&%d", redirector, redir_fd);
725 break;
726
727 case r_duplicating_input_word:
728 cprintf ("%d<&%s", redirector, redirectee->word);
729 break;
730
731 case r_duplicating_output_word:
732 cprintf ("%d>&%s", redirector, redirectee->word);
733 break;
734
735 case r_close_this:
736 cprintf ("%d>&-", redirector);
737 break;
738
739 case r_err_and_out:
740 cprintf (">&%s", redirectee->word);
741 break;
742
743 case r_input_output:
744 if (redirector != 1)
745 cprintf ("%d", redirector);
746 cprintf ("<>%s", redirectee->word);
747 break;
748
749 case r_output_force:
750 if (redirector != 1)
751 cprintf ("%d", redirector);
752 cprintf (">|%s", redirectee->word);
753 break;
754 }
755 }
756
757 static void
758 reset_locals ()
759 {
760 inside_function_def = 0;
761 indentation = 0;
762 }
763
764 static void
765 print_function_def (func)
766 FUNCTION_DEF *func;
767 {
768 cprintf ("function %s () \n", func->name->word);
769 add_unwind_protect (reset_locals, 0);
770
771 indent (indentation);
772 cprintf ("{ \n");
773
774 inside_function_def++;
775 indentation += indentation_amount;
776
777 make_command_string_internal (func->command->type == cm_group
778 ? func->command->value.Group->command
779 : func->command);
780
781 remove_unwind_protect ();
782 indentation -= indentation_amount;
783 inside_function_def--;
784
785 newline ("}");
786 }
787
788 /* Return the string representation of the named function.
789 NAME is the name of the function.
790 COMMAND is the function body. It should be a GROUP_COM.
791 MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
792 */
793 char *
794 named_function_string (name, command, multi_line)
795 char *name;
796 COMMAND *command;
797 int multi_line;
798 {
799 char *result;
800 int old_indent, old_amount;
801
802 old_indent = indentation;
803 old_amount = indentation_amount;
804 command_string_index = was_heredoc = 0;
805
806 if (name && *name)
807 cprintf ("%s ", name);
808
809 cprintf ("() ");
810
811 if (multi_line == 0)
812 {
813 indentation = 1;
814 indentation_amount = 0;
815 }
816 else
817 {
818 cprintf ("\n");
819 indentation += indentation_amount;
820 }
821
822 inside_function_def++;
823
824 cprintf (multi_line ? "{ \n" : "{ ");
825
826 make_command_string_internal (command->type == cm_group
827 ? command->value.Group->command
828 : command);
829
830 indentation = old_indent;
831 indentation_amount = old_amount;
832 inside_function_def--;
833
834 newline ("}");
835
836 result = the_printed_command;
837
838 if (!multi_line)
839 {
840 #if 0
841 register int i;
842 for (i = 0; result[i]; i++)
843 if (result[i] == '\n')
844 {
845 strcpy (result + i, result + i + 1);
846 --i;
847 }
848 #else
849 if (result[2] == '\n') /* XXX -- experimental */
850 strcpy (result + 2, result + 3);
851 #endif
852 }
853
854 return (result);
855 }
856
857 static void
858 newline (string)
859 char *string;
860 {
861 cprintf ("\n");
862 indent (indentation);
863 if (string && *string)
864 cprintf ("%s", string);
865 }
866
867 static char *indentation_string;
868 static int indentation_size;
869
870 static void
871 indent (amount)
872 int amount;
873 {
874 register int i;
875
876 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
877
878 for (i = 0; amount > 0; amount--)
879 indentation_string[i++] = ' ';
880 indentation_string[i] = '\0';
881 cprintf (indentation_string);
882 }
883
884 static void
885 semicolon ()
886 {
887 if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
888 return;
889 cprintf (";");
890 }
891
892 #if !defined (USE_VARARGS)
893 /* How to make the string. */
894 static void
895 cprintf (format, arg1, arg2)
896 char *format, *arg1, *arg2;
897 {
898 register char *s;
899 char char_arg[2], *argp, *args[2];
900 int arg_len, c, arg_index;
901
902 args[arg_index = 0] = arg1;
903 args[1] = arg2;
904
905 arg_len = strlen (format);
906 the_printed_command_resize (arg_len + 1);
907
908 char_arg[1] = '\0';
909 s = format;
910 while (s && *s)
911 {
912 int free_argp = 0;
913 c = *s++;
914 if (c != '%' || !*s)
915 {
916 argp = s;
917 arg_len = 1;
918 }
919 else
920 {
921 c = *s++;
922 switch (c)
923 {
924 case '%':
925 char_arg[0] = c;
926 argp = char_arg;
927 arg_len = 1;
928 break;
929
930 case 's':
931 argp = (char *)args[arg_index++];
932 arg_len = strlen (argp);
933 break;
934
935 case 'd':
936 argp = itos (pointer_to_int (args[arg_index]));
937 arg_index++;
938 arg_len = strlen (argp);
939 free_argp = 1;
940 break;
941
942 case 'c':
943 char_arg[0] = pointer_to_int (args[arg_index]);
944 arg_index++;
945 argp = char_arg;
946 arg_len = 1;
947 break;
948
949 default:
950 programming_error ("cprintf: bad `%%' argument (%c)", c);
951 }
952 }
953 if (argp)
954 {
955 the_printed_command_resize (arg_len + 1);
956 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
957 command_string_index += arg_len;
958 if (free_argp)
959 free (argp);
960 }
961 }
962
963 the_printed_command[command_string_index] = '\0';
964 }
965
966 #else /* We have support for varargs. */
967
968 /* How to make the string. */
969 static void
970 #if defined (PREFER_STDARG)
971 cprintf (char *control, ...)
972 #else
973 cprintf (control, va_alist)
974 char *control;
975 va_dcl
976 #endif
977 {
978 register char *s;
979 char char_arg[2], *argp;
980 int digit_arg, arg_len, c;
981 va_list args;
982
983 #if defined (PREFER_STDARG)
984 va_start (args, control);
985 #else
986 va_start (args);
987 #endif
988
989 arg_len = strlen (control);
990 the_printed_command_resize (arg_len + 1);
991
992 char_arg[1] = '\0';
993 s = control;
994 while (s && *s)
995 {
996 int free_argp;
997 free_argp = 0;
998 c = *s++;
999 argp = (char *)NULL;
1000 if (c != '%' || !*s)
1001 {
1002 argp = s - 1;
1003 arg_len = 1;
1004 }
1005 else
1006 {
1007 c = *s++;
1008 switch (c)
1009 {
1010 case '%':
1011 char_arg[0] = c;
1012 argp = char_arg;
1013 arg_len = 1;
1014 break;
1015
1016 case 's':
1017 argp = va_arg (args, char *);
1018 arg_len = strlen (argp);
1019 break;
1020
1021 case 'd':
1022 digit_arg = va_arg (args, int);
1023 argp = itos (digit_arg);
1024 arg_len = strlen (argp);
1025 free_argp = 1;
1026 break;
1027
1028 case 'c':
1029 char_arg[0] = va_arg (args, int);
1030 argp = char_arg;
1031 arg_len = 1;
1032 break;
1033
1034 default:
1035 programming_error ("cprintf: bad `%%' argument (%c)", c);
1036 /*NOTREACHED*/
1037 }
1038 }
1039
1040 if (argp && arg_len)
1041 {
1042 the_printed_command_resize (arg_len + 1);
1043 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1044 command_string_index += arg_len;
1045 if (free_argp)
1046 free (argp);
1047 }
1048 }
1049
1050 the_printed_command[command_string_index] = '\0';
1051 }
1052 #endif /* HAVE_VARARGS_H */
1053
1054 /* Ensure that there is enough space to stuff LENGTH characters into
1055 THE_PRINTED_COMMAND. */
1056 static void
1057 the_printed_command_resize (length)
1058 int length;
1059 {
1060 if (the_printed_command == 0)
1061 {
1062 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1063 the_printed_command = xmalloc (the_printed_command_size);
1064 command_string_index = 0;
1065 }
1066 else if ((command_string_index + length) >= the_printed_command_size)
1067 {
1068 int new;
1069 new = command_string_index + length + 1;
1070 #if 1
1071 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1072 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1073 #else
1074 new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
1075 new -= new % PRINTED_COMMAND_GROW_SIZE;
1076 #endif
1077 the_printed_command_size = new;
1078 the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
1079 }
1080 }
1081
1082 #if defined (HAVE_VFPRINTF)
1083
1084 static void
1085 #if defined (PREFER_STDARG)
1086 xprintf (const char *format, ...)
1087 #else
1088 xprintf (format, va_alist)
1089 const char *format;
1090 va_dcl
1091 #endif
1092 {
1093 va_list args;
1094
1095 #if defined (PREFER_STDARG)
1096 va_start (args, format);
1097 #else
1098 va_start (args);
1099 #endif
1100
1101 vfprintf (stdout, format, args);
1102 va_end (args);
1103 }
1104
1105 #else
1106
1107 static void
1108 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1109 char *format;
1110 {
1111 printf (format, arg1, arg2, arg3, arg4, arg5);
1112 }
1113
1114 #endif /* !HAVE_VFPRINTF */