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