]> git.ipfire.org Git - thirdparty/bash.git/blob - print_cmd.c
472470156e66836bcf87c195540f99f9e989ba29
[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 command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
264 break;
265 }
266
267 if (command->flags & CMD_WANT_SUBSHELL)
268 cprintf (" )");
269
270 if (command->redirects)
271 {
272 cprintf (" ");
273 print_redirection_list (command->redirects);
274 }
275 }
276 }
277
278 static void
279 _print_word_list (list, separator, pfunc)
280 WORD_LIST *list;
281 char *separator;
282 VFunction *pfunc;
283 {
284 WORD_LIST *w;
285
286 for (w = list; w; w = w->next)
287 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
288 }
289
290 void
291 print_word_list (list, separator)
292 WORD_LIST *list;
293 char *separator;
294 {
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. */
299 void
300 xtrace_print_word_list (list)
301 WORD_LIST *list;
302 {
303 WORD_LIST *w;
304 char *t, *x;
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')
311 fprintf (stderr, "''%s", w->next ? " " : "");
312 else if (contains_shell_metas (t))
313 {
314 x = single_quote (t);
315 fprintf (stderr, "%s%s", x, w->next ? " " : "");
316 free (x);
317 }
318 else
319 fprintf (stderr, "%s%s", t, w->next ? " " : "");
320 }
321 fprintf (stderr, "\n");
322 }
323
324 static void
325 command_print_word_list (list, separator)
326 WORD_LIST *list;
327 char *separator;
328 {
329 _print_word_list (list, separator, cprintf);
330 }
331
332 static void
333 print_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)
348 static void
349 print_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
364 static void
365 print_group_command (group_command)
366 GROUP_COM *group_command;
367 {
368 group_command_nesting++;
369 cprintf ("{ ");
370
371 if (inside_function_def == 0)
372 skip_this_indent++;
373 else
374 {
375 /* This is a group command { ... } inside of a function
376 definition, and should be printed as a multiline group
377 command, using the current indentation. */
378 cprintf ("\n");
379 indentation += indentation_amount;
380 }
381
382 make_command_string_internal (group_command->command);
383
384 if (inside_function_def)
385 {
386 cprintf ("\n");
387 indentation -= indentation_amount;
388 indent (indentation);
389 }
390 else
391 {
392 semicolon ();
393 cprintf (" ");
394 }
395
396 cprintf ("}");
397
398 group_command_nesting--;
399 }
400
401 static void
402 print_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
411 static void
412 print_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
430 static void
431 print_while_command (while_command)
432 WHILE_COM *while_command;
433 {
434 print_until_or_while (while_command, "while");
435 }
436
437 static void
438 print_until_command (while_command)
439 WHILE_COM *while_command;
440 {
441 print_until_or_while (while_command, "until");
442 }
443
444 static void
445 print_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
461 static void
462 print_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
486 #if defined (DPAREN_ARITHMETIC)
487 static void
488 print_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)
497 static void
498 print_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 {
524 cprintf ("%s", cond->op->word);
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 (" ");
532 cprintf ("%s", cond->op->word);
533 cprintf (" ");
534 print_cond_node (cond->right);
535 }
536 else if (cond->type == COND_TERM)
537 {
538 cprintf ("%s", cond->op->word); /* need to add quoting here */
539 }
540 }
541
542 static void
543 print_cond_command (cond)
544 COND_COM *cond;
545 {
546 cprintf ("[[ ");
547 print_cond_node (cond);
548 cprintf (" ]]");
549 }
550
551 void
552 debug_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
561 void
562 xtrace_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. */
590 void
591 xtrace_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
604 void
605 print_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
617 static void
618 print_redirection_list (redirects)
619 REDIRECT *redirects;
620 {
621 REDIRECT *heredocs, *hdtail, *newredir;
622
623 heredocs = (REDIRECT *)NULL;
624 hdtail = heredocs;
625
626 was_heredoc = 0;
627 while (redirects)
628 {
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
646 redirects = redirects->next;
647 if (redirects)
648 cprintf (" ");
649 }
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 }
664 }
665
666 static void
667 print_redirection (redirect)
668 REDIRECT *redirect;
669 {
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;
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. */
709 if (redirect->redirectee.filename->flags & W_QUOTED)
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
760 static void
761 reset_locals ()
762 {
763 inside_function_def = 0;
764 indentation = 0;
765 }
766
767 static void
768 print_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
780 make_command_string_internal (func->command->type == cm_group
781 ? func->command->value.Group->command
782 : func->command);
783
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 */
796 char *
797 named_function_string (name, command, multi_line)
798 char *name;
799 COMMAND *command;
800 int multi_line;
801 {
802 char *result;
803 int old_indent, old_amount;
804
805 old_indent = indentation;
806 old_amount = indentation_amount;
807 command_string_index = was_heredoc = 0;
808
809 if (name && *name)
810 cprintf ("%s ", name);
811
812 cprintf ("() ");
813
814 if (multi_line == 0)
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
827 cprintf (multi_line ? "{ \n" : "{ ");
828
829 make_command_string_internal (command->type == cm_group
830 ? command->value.Group->command
831 : command);
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
860 static void
861 newline (string)
862 char *string;
863 {
864 cprintf ("\n");
865 indent (indentation);
866 if (string && *string)
867 cprintf ("%s", string);
868 }
869
870 static char *indentation_string;
871 static int indentation_size;
872
873 static void
874 indent (amount)
875 int amount;
876 {
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);
885 }
886
887 static void
888 semicolon ()
889 {
890 if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
891 return;
892 cprintf (";");
893 }
894
895 #if !defined (USE_VARARGS)
896 /* How to make the string. */
897 static void
898 cprintf (format, arg1, arg2)
899 char *format, *arg1, *arg2;
900 {
901 register char *s;
902 char char_arg[2], *argp, *args[2], intbuf[32];
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':
939 argp = inttostr (pointer_to_int (args[arg_index]), intbuf, sizeof (intbuf));
940 arg_index++;
941 arg_len = strlen (argp);
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. */
971 static void
972 #if defined (PREFER_STDARG)
973 cprintf (char *control, ...)
974 #else
975 cprintf (control, va_alist)
976 char *control;
977 va_dcl
978 #endif
979 {
980 register char *s;
981 char char_arg[2], *argp, intbuf[32];
982 int digit_arg, arg_len, c;
983 va_list args;
984
985 #if defined (PREFER_STDARG)
986 va_start (args, control);
987 #else
988 va_start (args);
989 #endif
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 {
998 int free_argp;
999 free_argp = 0;
1000 c = *s++;
1001 argp = (char *)NULL;
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);
1025 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1026 arg_len = strlen (argp);
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);
1037 /*NOTREACHED*/
1038 }
1039 }
1040
1041 if (argp && arg_len)
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. */
1057 static void
1058 the_printed_command_resize (length)
1059 int length;
1060 {
1061 if (the_printed_command == 0)
1062 {
1063 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
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;
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
1075 new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
1076 new -= new % PRINTED_COMMAND_GROW_SIZE;
1077 #endif
1078 the_printed_command_size = new;
1079 the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
1080 }
1081 }
1082
1083 #if defined (HAVE_VFPRINTF)
1084
1085 static void
1086 #if defined (PREFER_STDARG)
1087 xprintf (const char *format, ...)
1088 #else
1089 xprintf (format, va_alist)
1090 const char *format;
1091 va_dcl
1092 #endif
1093 {
1094 va_list args;
1095
1096 #if defined (PREFER_STDARG)
1097 va_start (args, format);
1098 #else
1099 va_start (args);
1100 #endif
1101
1102 vfprintf (stdout, format, args);
1103 va_end (args);
1104 }
1105
1106 #else
1107
1108 static void
1109 xprintf (format, arg1, arg2, arg3, arg4, arg5)
1110 char *format;
1111 {
1112 printf (format, arg1, arg2, arg3, arg4, arg5);
1113 }
1114
1115 #endif /* !HAVE_VFPRINTF */