Line data Source code
1 : /* print_command -- A way to make readable commands from a command tree. */
2 :
3 : /* Copyright (C) 1989-2016 Free Software Foundation, Inc.
4 :
5 : This file is part of GNU Bash, the Bourne Again SHell.
6 :
7 : Bash is free software: you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation, either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : Bash is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include <stdio.h>
24 :
25 : #if defined (HAVE_UNISTD_H)
26 : # ifdef _MINIX
27 : # include <sys/types.h>
28 : # endif
29 : # include <unistd.h>
30 : #endif
31 :
32 : #if defined (PREFER_STDARG)
33 : # include <stdarg.h>
34 : #else
35 : # include <varargs.h>
36 : #endif
37 :
38 : #include "bashansi.h"
39 : #include "bashintl.h"
40 :
41 : #include "shell.h"
42 : #include "flags.h"
43 : #include <y.tab.h> /* use <...> so we pick it up from the build directory */
44 : #include "input.h"
45 :
46 : #include "shmbutil.h"
47 :
48 : #include "builtins/common.h"
49 :
50 : #if !HAVE_DECL_PRINTF
51 : extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
52 : #endif
53 :
54 : extern int indirection_level;
55 : extern int posixly_correct;
56 :
57 : static int indentation;
58 : static int indentation_amount = 4;
59 :
60 : #if defined (PREFER_STDARG)
61 : typedef void PFUNC __P((const char *, ...));
62 :
63 : static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
64 : static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
65 : #else
66 : #define PFUNC VFunction
67 : static void cprintf ();
68 : static void xprintf ();
69 : #endif
70 :
71 : static void reset_locals __P((void));
72 : static void newline __P((char *));
73 : static void indent __P((int));
74 : static void semicolon __P((void));
75 : static void the_printed_command_resize __P((int));
76 :
77 : static void make_command_string_internal __P((COMMAND *));
78 : static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
79 : static void command_print_word_list __P((WORD_LIST *, char *));
80 : static void print_case_clauses __P((PATTERN_LIST *));
81 : static void print_redirection_list __P((REDIRECT *));
82 : static void print_redirection __P((REDIRECT *));
83 : static void print_heredoc_header __P((REDIRECT *));
84 : static void print_heredoc_body __P((REDIRECT *));
85 : static void print_heredocs __P((REDIRECT *));
86 : static void print_deferred_heredocs __P((const char *));
87 :
88 : static void print_for_command __P((FOR_COM *));
89 : #if defined (ARITH_FOR_COMMAND)
90 : static void print_arith_for_command __P((ARITH_FOR_COM *));
91 : #endif
92 : #if defined (SELECT_COMMAND)
93 : static void print_select_command __P((SELECT_COM *));
94 : #endif
95 : static void print_group_command __P((GROUP_COM *));
96 : static void print_case_command __P((CASE_COM *));
97 : static void print_while_command __P((WHILE_COM *));
98 : static void print_until_command __P((WHILE_COM *));
99 : static void print_until_or_while __P((WHILE_COM *, char *));
100 : static void print_if_command __P((IF_COM *));
101 : #if defined (COND_COMMAND)
102 : static void print_cond_node __P((COND_COM *));
103 : #endif
104 : static void print_function_def __P((FUNCTION_DEF *));
105 :
106 : #define PRINTED_COMMAND_INITIAL_SIZE 64
107 : #define PRINTED_COMMAND_GROW_SIZE 128
108 :
109 : char *the_printed_command = (char *)NULL;
110 : int the_printed_command_size = 0;
111 : int command_string_index = 0;
112 :
113 : int xtrace_fd = -1;
114 : FILE *xtrace_fp = 0;
115 :
116 : #define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
117 :
118 : /* shell expansion characters: used in print_redirection_list */
119 : #define EXPCHAR(c) ((c) == '{' || (c) == '~' || (c) == '$' || (c) == '`')
120 :
121 : #define PRINT_DEFERRED_HEREDOCS(x) \
122 : do { \
123 : if (deferred_heredocs) \
124 : print_deferred_heredocs (x); \
125 : } while (0)
126 :
127 : /* Non-zero means the stuff being printed is inside of a function def. */
128 : static int inside_function_def;
129 : static int skip_this_indent;
130 : static int was_heredoc;
131 : static int printing_connection;
132 : static REDIRECT *deferred_heredocs;
133 :
134 : /* The depth of the group commands that we are currently printing. This
135 : includes the group command that is a function body. */
136 : static int group_command_nesting;
137 :
138 : /* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
139 : static char *indirection_string = 0;
140 : static int indirection_stringsiz = 0;
141 :
142 : /* Print COMMAND (a command tree) on standard output. */
143 : void
144 0 : print_command (command)
145 : COMMAND *command;
146 : {
147 0 : command_string_index = 0;
148 0 : printf ("%s", make_command_string (command));
149 0 : }
150 :
151 : /* Make a string which is the printed representation of the command
152 : tree in COMMAND. We return this string. However, the string is
153 : not consed, so you have to do that yourself if you want it to
154 : remain around. */
155 : char *
156 3601 : make_command_string (command)
157 : COMMAND *command;
158 : {
159 3601 : command_string_index = was_heredoc = 0;
160 3601 : deferred_heredocs = 0;
161 3601 : make_command_string_internal (command);
162 0 : return (the_printed_command);
163 : }
164 :
165 : /* The internal function. This is the real workhorse. */
166 : static void
167 19715 : make_command_string_internal (command)
168 : COMMAND *command;
169 : {
170 19715 : char s[3];
171 :
172 19715 : if (command == 0)
173 41 : cprintf ("");
174 : else
175 : {
176 19674 : if (skip_this_indent)
177 11061 : skip_this_indent--;
178 : else
179 8613 : indent (indentation);
180 :
181 19674 : if (command->flags & CMD_TIME_PIPELINE)
182 : {
183 0 : cprintf ("time ");
184 0 : if (command->flags & CMD_TIME_POSIX)
185 0 : cprintf ("-p ");
186 : }
187 :
188 19674 : if (command->flags & CMD_INVERT_RETURN)
189 0 : cprintf ("! ");
190 :
191 19674 : switch (command->type)
192 : {
193 0 : case cm_for:
194 0 : print_for_command (command->value.For);
195 0 : break;
196 :
197 : #if defined (ARITH_FOR_COMMAND)
198 0 : case cm_arith_for:
199 0 : print_arith_for_command (command->value.ArithFor);
200 0 : break;
201 : #endif
202 :
203 : #if defined (SELECT_COMMAND)
204 0 : case cm_select:
205 0 : print_select_command (command->value.Select);
206 0 : break;
207 : #endif
208 :
209 123 : case cm_case:
210 123 : print_case_command (command->value.Case);
211 123 : break;
212 :
213 2938 : case cm_while:
214 2938 : print_while_command (command->value.While);
215 2938 : break;
216 :
217 0 : case cm_until:
218 0 : print_until_command (command->value.While);
219 0 : break;
220 :
221 155 : case cm_if:
222 155 : print_if_command (command->value.If);
223 155 : break;
224 :
225 : #if defined (DPAREN_ARITHMETIC)
226 0 : case cm_arith:
227 0 : print_arith_command (command->value.Arith->exp);
228 0 : break;
229 : #endif
230 :
231 : #if defined (COND_COMMAND)
232 0 : case cm_cond:
233 0 : print_cond_command (command->value.Cond);
234 0 : break;
235 : #endif
236 :
237 11772 : case cm_simple:
238 11772 : print_simple_command (command->value.Simple);
239 11772 : break;
240 :
241 4269 : case cm_connection:
242 :
243 4269 : skip_this_indent++;
244 4269 : printing_connection++;
245 4269 : make_command_string_internal (command->value.Connection->first);
246 :
247 4269 : switch (command->value.Connection->connector)
248 : {
249 73 : case '&':
250 : case '|':
251 : {
252 73 : char c = command->value.Connection->connector;
253 :
254 73 : s[0] = ' ';
255 73 : s[1] = c;
256 73 : s[2] = '\0';
257 :
258 73 : print_deferred_heredocs (s);
259 :
260 73 : if (c != '&' || command->value.Connection->second)
261 : {
262 73 : cprintf (" ");
263 73 : skip_this_indent++;
264 : }
265 : }
266 : break;
267 :
268 0 : case AND_AND:
269 0 : print_deferred_heredocs (" && ");
270 0 : if (command->value.Connection->second)
271 0 : skip_this_indent++;
272 : break;
273 :
274 3115 : case OR_OR:
275 3115 : print_deferred_heredocs (" || ");
276 3115 : if (command->value.Connection->second)
277 3115 : skip_this_indent++;
278 : break;
279 :
280 1081 : case ';':
281 1081 : if (deferred_heredocs == 0)
282 : {
283 1081 : if (was_heredoc == 0)
284 1081 : cprintf (";");
285 : else
286 0 : was_heredoc = 0;
287 : }
288 : else
289 0 : print_deferred_heredocs (inside_function_def ? "" : ";");
290 :
291 1081 : if (inside_function_def)
292 684 : cprintf ("\n");
293 : else
294 : {
295 397 : cprintf (" ");
296 397 : if (command->value.Connection->second)
297 397 : skip_this_indent++;
298 : }
299 : break;
300 :
301 0 : default:
302 0 : cprintf (_("print_command: bad connector `%d'"),
303 : command->value.Connection->connector);
304 0 : break;
305 : }
306 :
307 4269 : make_command_string_internal (command->value.Connection->second);
308 4269 : PRINT_DEFERRED_HEREDOCS ("");
309 4269 : printing_connection--;
310 4269 : break;
311 :
312 303 : case cm_function_def:
313 303 : print_function_def (command->value.Function_def);
314 303 : break;
315 :
316 9 : case cm_group:
317 9 : print_group_command (command->value.Group);
318 9 : break;
319 :
320 105 : case cm_subshell:
321 105 : cprintf ("( ");
322 105 : skip_this_indent++;
323 105 : make_command_string_internal (command->value.Subshell->command);
324 105 : PRINT_DEFERRED_HEREDOCS ("");
325 105 : cprintf (" )");
326 105 : break;
327 :
328 0 : case cm_coproc:
329 0 : cprintf ("coproc %s ", command->value.Coproc->name);
330 0 : skip_this_indent++;
331 0 : make_command_string_internal (command->value.Coproc->command);
332 0 : break;
333 :
334 0 : default:
335 0 : command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
336 0 : break;
337 : }
338 :
339 :
340 19674 : if (command->redirects)
341 : {
342 0 : cprintf (" ");
343 0 : print_redirection_list (command->redirects);
344 : }
345 : }
346 19715 : }
347 :
348 : static void
349 : _print_word_list (list, separator, pfunc)
350 : WORD_LIST *list;
351 : char *separator;
352 : PFUNC *pfunc;
353 : {
354 86316420 : WORD_LIST *w;
355 :
356 284601743 : for (w = list; w; w = w->next)
357 284600805 : (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
358 : }
359 :
360 : void
361 0 : print_word_list (list, separator)
362 : WORD_LIST *list;
363 : char *separator;
364 : {
365 0 : _print_word_list (list, separator, xprintf);
366 0 : }
367 :
368 : void
369 9542957 : xtrace_set (fd, fp)
370 : int fd;
371 : FILE *fp;
372 : {
373 9542957 : if (fd >= 0 && sh_validfd (fd) == 0)
374 : {
375 0 : internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
376 0 : return;
377 : }
378 9542957 : if (fp == 0)
379 : {
380 0 : internal_error (_("xtrace_set: NULL file pointer"));
381 0 : return;
382 : }
383 9542957 : if (fd >= 0 && fileno (fp) != fd)
384 0 : internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
385 :
386 9542957 : xtrace_fd = fd;
387 9542957 : xtrace_fp = fp;
388 : }
389 :
390 : void
391 9542957 : xtrace_init ()
392 : {
393 9542957 : xtrace_set (-1, stderr);
394 9542957 : }
395 :
396 : void
397 0 : xtrace_reset ()
398 : {
399 0 : if (xtrace_fd >= 0 && xtrace_fp)
400 : {
401 0 : fflush (xtrace_fp);
402 0 : fclose (xtrace_fp);
403 : }
404 0 : else if (xtrace_fd >= 0)
405 0 : close (xtrace_fd);
406 :
407 0 : xtrace_fd = -1;
408 0 : xtrace_fp = stderr;
409 0 : }
410 :
411 : void
412 699 : xtrace_fdchk (fd)
413 : int fd;
414 : {
415 699 : if (fd == xtrace_fd)
416 0 : xtrace_reset ();
417 699 : }
418 :
419 : /* Return a string denoting what our indirection level is. */
420 :
421 : char *
422 0 : indirection_level_string ()
423 : {
424 0 : register int i, j;
425 0 : char *ps4;
426 0 : char ps4_firstc[MB_LEN_MAX+1];
427 0 : int ps4_firstc_len, ps4_len, ineed, old;
428 :
429 0 : ps4 = get_string_value ("PS4");
430 0 : if (indirection_string == 0)
431 0 : indirection_string = xmalloc (indirection_stringsiz = 100);
432 0 : indirection_string[0] = '\0';
433 :
434 0 : if (ps4 == 0 || *ps4 == '\0')
435 : return (indirection_string);
436 :
437 0 : old = change_flag ('x', FLAG_OFF);
438 0 : ps4 = decode_prompt_string (ps4);
439 0 : if (old)
440 0 : change_flag ('x', FLAG_ON);
441 :
442 0 : if (ps4 == 0 || *ps4 == '\0')
443 0 : return (indirection_string);
444 :
445 : #if defined (HANDLE_MULTIBYTE)
446 0 : ps4_len = strnlen (ps4, MB_CUR_MAX);
447 0 : ps4_firstc_len = MBLEN (ps4, ps4_len);
448 0 : if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || ps4_firstc_len < 0)
449 : {
450 0 : ps4_firstc[0] = ps4[0];
451 0 : ps4_firstc[ps4_firstc_len = 1] = '\0';
452 : }
453 : else
454 0 : memcpy (ps4_firstc, ps4, ps4_firstc_len);
455 : #else
456 : ps4_firstc[0] = ps4[0];
457 : ps4_firstc[ps4_firstc_len = 1] = '\0';
458 : #endif
459 :
460 : /* Dynamically resize indirection_string so we have room for everything
461 : and we don't have to truncate ps4 */
462 0 : ineed = (ps4_firstc_len * indirection_level) + strlen (ps4);
463 0 : if (ineed > indirection_stringsiz - 1)
464 : {
465 0 : indirection_stringsiz = ineed + 1;
466 0 : indirection_string = xrealloc (indirection_string, indirection_stringsiz);
467 : }
468 :
469 0 : for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < indirection_stringsiz - 1; i += ps4_firstc_len, j++)
470 : {
471 0 : if (ps4_firstc_len == 1)
472 0 : indirection_string[i] = ps4_firstc[0];
473 : else
474 0 : memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
475 : }
476 :
477 0 : for (j = ps4_firstc_len; *ps4 && ps4[j] && i < indirection_stringsiz - 1; i++, j++)
478 0 : indirection_string[i] = ps4[j];
479 :
480 0 : indirection_string[i] = '\0';
481 0 : free (ps4);
482 0 : return (indirection_string);
483 : }
484 :
485 : void
486 0 : xtrace_print_assignment (name, value, assign_list, xflags)
487 : char *name, *value;
488 : int assign_list, xflags;
489 : {
490 0 : char *nval;
491 :
492 0 : CHECK_XTRACE_FP;
493 :
494 0 : if (xflags)
495 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
496 :
497 : /* VALUE should not be NULL when this is called. */
498 0 : if (*value == '\0' || assign_list)
499 : nval = value;
500 0 : else if (sh_contains_shell_metas (value))
501 0 : nval = sh_single_quote (value);
502 0 : else if (ansic_shouldquote (value))
503 0 : nval = ansic_quote (value, 0, (int *)0);
504 : else
505 : nval = value;
506 :
507 0 : if (assign_list)
508 0 : fprintf (xtrace_fp, "%s=(%s)\n", name, nval);
509 : else
510 0 : fprintf (xtrace_fp, "%s=%s\n", name, nval);
511 :
512 0 : if (nval != value)
513 0 : FREE (nval);
514 :
515 0 : fflush (xtrace_fp);
516 0 : }
517 :
518 : /* A function to print the words of a simple command when set -x is on. Also
519 : used to print the word list in a for or select command header; in that case,
520 : we suppress quoting the words because they haven't been expanded yet.
521 : XTFLAGS&1 means to print $PS4; XTFLAGS&2 means to suppress quoting the
522 : words in LIST. */
523 : void
524 0 : xtrace_print_word_list (list, xtflags)
525 : WORD_LIST *list;
526 : int xtflags;
527 : {
528 0 : WORD_LIST *w;
529 0 : char *t, *x;
530 :
531 0 : CHECK_XTRACE_FP;
532 :
533 0 : if (xtflags&1)
534 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
535 :
536 0 : for (w = list; w; w = w->next)
537 : {
538 0 : t = w->word->word;
539 0 : if (t == 0 || *t == '\0')
540 0 : fprintf (xtrace_fp, "''%s", w->next ? " " : "");
541 0 : else if (xtflags & 2)
542 0 : fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
543 0 : else if (sh_contains_shell_metas (t))
544 : {
545 0 : x = sh_single_quote (t);
546 0 : fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
547 0 : free (x);
548 : }
549 0 : else if (ansic_shouldquote (t))
550 : {
551 0 : x = ansic_quote (t, 0, (int *)0);
552 0 : fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
553 0 : free (x);
554 : }
555 : else
556 0 : fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
557 : }
558 0 : fprintf (xtrace_fp, "\n");
559 0 : fflush (xtrace_fp);
560 0 : }
561 :
562 : static void
563 86316420 : command_print_word_list (list, separator)
564 : WORD_LIST *list;
565 : char *separator;
566 : {
567 86316420 : _print_word_list (list, separator, cprintf);
568 86316420 : }
569 :
570 : void
571 0 : print_for_command_head (for_command)
572 : FOR_COM *for_command;
573 : {
574 0 : cprintf ("for %s in ", for_command->name->word);
575 0 : command_print_word_list (for_command->map_list, " ");
576 0 : }
577 :
578 : void
579 0 : xtrace_print_for_command_head (for_command)
580 : FOR_COM *for_command;
581 : {
582 0 : CHECK_XTRACE_FP;
583 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
584 0 : fprintf (xtrace_fp, "for %s in ", for_command->name->word);
585 0 : xtrace_print_word_list (for_command->map_list, 2);
586 0 : }
587 :
588 : static void
589 0 : print_for_command (for_command)
590 : FOR_COM *for_command;
591 : {
592 0 : print_for_command_head (for_command);
593 0 : cprintf (";");
594 0 : newline ("do\n");
595 :
596 0 : indentation += indentation_amount;
597 0 : make_command_string_internal (for_command->action);
598 0 : PRINT_DEFERRED_HEREDOCS ("");
599 0 : semicolon ();
600 0 : indentation -= indentation_amount;
601 :
602 0 : newline ("done");
603 0 : }
604 :
605 : #if defined (ARITH_FOR_COMMAND)
606 : static void
607 0 : print_arith_for_command (arith_for_command)
608 : ARITH_FOR_COM *arith_for_command;
609 : {
610 0 : cprintf ("for ((");
611 0 : command_print_word_list (arith_for_command->init, " ");
612 0 : cprintf ("; ");
613 0 : command_print_word_list (arith_for_command->test, " ");
614 0 : cprintf ("; ");
615 0 : command_print_word_list (arith_for_command->step, " ");
616 0 : cprintf ("))");
617 0 : newline ("do\n");
618 0 : indentation += indentation_amount;
619 0 : make_command_string_internal (arith_for_command->action);
620 0 : PRINT_DEFERRED_HEREDOCS ("");
621 0 : semicolon ();
622 0 : indentation -= indentation_amount;
623 0 : newline ("done");
624 0 : }
625 : #endif /* ARITH_FOR_COMMAND */
626 :
627 : #if defined (SELECT_COMMAND)
628 : void
629 0 : print_select_command_head (select_command)
630 : SELECT_COM *select_command;
631 : {
632 0 : cprintf ("select %s in ", select_command->name->word);
633 0 : command_print_word_list (select_command->map_list, " ");
634 0 : }
635 :
636 : void
637 0 : xtrace_print_select_command_head (select_command)
638 : SELECT_COM *select_command;
639 : {
640 0 : CHECK_XTRACE_FP;
641 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
642 0 : fprintf (xtrace_fp, "select %s in ", select_command->name->word);
643 0 : xtrace_print_word_list (select_command->map_list, 2);
644 0 : }
645 :
646 : static void
647 0 : print_select_command (select_command)
648 : SELECT_COM *select_command;
649 : {
650 0 : print_select_command_head (select_command);
651 :
652 0 : cprintf (";");
653 0 : newline ("do\n");
654 0 : indentation += indentation_amount;
655 0 : make_command_string_internal (select_command->action);
656 0 : PRINT_DEFERRED_HEREDOCS ("");
657 0 : semicolon ();
658 0 : indentation -= indentation_amount;
659 0 : newline ("done");
660 0 : }
661 : #endif /* SELECT_COMMAND */
662 :
663 : static void
664 0 : print_group_command (group_command)
665 : GROUP_COM *group_command;
666 : {
667 0 : group_command_nesting++;
668 0 : cprintf ("{ ");
669 :
670 0 : if (inside_function_def == 0)
671 0 : skip_this_indent++;
672 : else
673 : {
674 : /* This is a group command { ... } inside of a function
675 : definition, and should be printed as a multiline group
676 : command, using the current indentation. */
677 0 : cprintf ("\n");
678 0 : indentation += indentation_amount;
679 : }
680 :
681 0 : make_command_string_internal (group_command->command);
682 0 : PRINT_DEFERRED_HEREDOCS ("");
683 :
684 0 : if (inside_function_def)
685 : {
686 0 : cprintf ("\n");
687 0 : indentation -= indentation_amount;
688 0 : indent (indentation);
689 : }
690 : else
691 : {
692 0 : semicolon ();
693 0 : cprintf (" ");
694 : }
695 :
696 0 : cprintf ("}");
697 :
698 0 : group_command_nesting--;
699 0 : }
700 :
701 : void
702 5643926 : print_case_command_head (case_command)
703 : CASE_COM *case_command;
704 : {
705 5643926 : cprintf ("case %s in ", case_command->word->word);
706 5643926 : }
707 :
708 : void
709 0 : xtrace_print_case_command_head (case_command)
710 : CASE_COM *case_command;
711 : {
712 0 : CHECK_XTRACE_FP;
713 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
714 0 : fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
715 0 : }
716 :
717 : static void
718 0 : print_case_command (case_command)
719 : CASE_COM *case_command;
720 : {
721 0 : print_case_command_head (case_command);
722 :
723 0 : if (case_command->clauses)
724 0 : print_case_clauses (case_command->clauses);
725 0 : newline ("esac");
726 0 : }
727 :
728 : static void
729 123 : print_case_clauses (clauses)
730 : PATTERN_LIST *clauses;
731 : {
732 123 : indentation += indentation_amount;
733 943 : while (clauses)
734 : {
735 820 : newline ("");
736 820 : command_print_word_list (clauses->patterns, " | ");
737 820 : cprintf (")\n");
738 820 : indentation += indentation_amount;
739 820 : make_command_string_internal (clauses->action);
740 820 : indentation -= indentation_amount;
741 820 : PRINT_DEFERRED_HEREDOCS ("");
742 820 : if (clauses->flags & CASEPAT_FALLTHROUGH)
743 0 : newline (";&");
744 820 : else if (clauses->flags & CASEPAT_TESTNEXT)
745 0 : newline (";;&");
746 : else
747 820 : newline (";;");
748 820 : clauses = clauses->next;
749 : }
750 123 : indentation -= indentation_amount;
751 123 : }
752 :
753 : static void
754 2938 : print_while_command (while_command)
755 : WHILE_COM *while_command;
756 : {
757 2938 : print_until_or_while (while_command, "while");
758 2938 : }
759 :
760 : static void
761 0 : print_until_command (while_command)
762 : WHILE_COM *while_command;
763 : {
764 0 : print_until_or_while (while_command, "until");
765 0 : }
766 :
767 : static void
768 0 : print_until_or_while (while_command, which)
769 : WHILE_COM *while_command;
770 : char *which;
771 : {
772 0 : cprintf ("%s ", which);
773 0 : skip_this_indent++;
774 0 : make_command_string_internal (while_command->test);
775 0 : PRINT_DEFERRED_HEREDOCS ("");
776 0 : semicolon ();
777 0 : cprintf (" do\n"); /* was newline ("do\n"); */
778 0 : indentation += indentation_amount;
779 0 : make_command_string_internal (while_command->action);
780 0 : PRINT_DEFERRED_HEREDOCS ("");
781 0 : indentation -= indentation_amount;
782 0 : semicolon ();
783 0 : newline ("done");
784 0 : }
785 :
786 : static void
787 155 : print_if_command (if_command)
788 : IF_COM *if_command;
789 : {
790 155 : cprintf ("if ");
791 155 : skip_this_indent++;
792 155 : make_command_string_internal (if_command->test);
793 155 : semicolon ();
794 155 : cprintf (" then\n");
795 155 : indentation += indentation_amount;
796 155 : make_command_string_internal (if_command->true_case);
797 155 : PRINT_DEFERRED_HEREDOCS ("");
798 155 : indentation -= indentation_amount;
799 :
800 155 : if (if_command->false_case)
801 : {
802 10 : semicolon ();
803 10 : newline ("else\n");
804 10 : indentation += indentation_amount;
805 10 : make_command_string_internal (if_command->false_case);
806 10 : PRINT_DEFERRED_HEREDOCS ("");
807 10 : indentation -= indentation_amount;
808 : }
809 155 : semicolon ();
810 155 : newline ("fi");
811 155 : }
812 :
813 : #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
814 : void
815 0 : print_arith_command (arith_cmd_list)
816 : WORD_LIST *arith_cmd_list;
817 : {
818 0 : cprintf ("((");
819 0 : command_print_word_list (arith_cmd_list, " ");
820 0 : cprintf ("))");
821 0 : }
822 : #endif
823 :
824 : #if defined (COND_COMMAND)
825 : static void
826 0 : print_cond_node (cond)
827 : COND_COM *cond;
828 : {
829 0 : if (cond->flags & CMD_INVERT_RETURN)
830 0 : cprintf ("! ");
831 :
832 0 : if (cond->type == COND_EXPR)
833 : {
834 0 : cprintf ("( ");
835 0 : print_cond_node (cond->left);
836 0 : cprintf (" )");
837 : }
838 0 : else if (cond->type == COND_AND)
839 : {
840 0 : print_cond_node (cond->left);
841 0 : cprintf (" && ");
842 0 : print_cond_node (cond->right);
843 : }
844 0 : else if (cond->type == COND_OR)
845 : {
846 0 : print_cond_node (cond->left);
847 0 : cprintf (" || ");
848 0 : print_cond_node (cond->right);
849 : }
850 0 : else if (cond->type == COND_UNARY)
851 : {
852 0 : cprintf ("%s", cond->op->word);
853 0 : cprintf (" ");
854 0 : print_cond_node (cond->left);
855 : }
856 0 : else if (cond->type == COND_BINARY)
857 : {
858 0 : print_cond_node (cond->left);
859 0 : cprintf (" ");
860 0 : cprintf ("%s", cond->op->word);
861 0 : cprintf (" ");
862 0 : print_cond_node (cond->right);
863 : }
864 0 : else if (cond->type == COND_TERM)
865 : {
866 0 : cprintf ("%s", cond->op->word); /* need to add quoting here */
867 : }
868 0 : }
869 :
870 : void
871 0 : print_cond_command (cond)
872 : COND_COM *cond;
873 : {
874 0 : cprintf ("[[ ");
875 0 : print_cond_node (cond);
876 0 : cprintf (" ]]");
877 0 : }
878 :
879 : #ifdef DEBUG
880 : void
881 : debug_print_word_list (s, list, sep)
882 : char *s;
883 : WORD_LIST *list;
884 : char *sep;
885 : {
886 : WORD_LIST *w;
887 :
888 : if (s)
889 : fprintf (stderr, "%s: ", s);
890 : for (w = list; w; w = w->next)
891 : fprintf (stderr, "%s%s", w->word->word, w->next ? sep : "");
892 : fprintf (stderr, "\n");
893 : }
894 :
895 : void
896 : debug_print_cond_command (cond)
897 : COND_COM *cond;
898 : {
899 : fprintf (stderr, "DEBUG: ");
900 : command_string_index = 0;
901 : print_cond_command (cond);
902 : fprintf (stderr, "%s\n", the_printed_command);
903 : }
904 : #endif
905 :
906 : void
907 0 : xtrace_print_cond_term (type, invert, op, arg1, arg2)
908 : int type, invert;
909 : WORD_DESC *op;
910 : char *arg1, *arg2;
911 : {
912 0 : CHECK_XTRACE_FP;
913 0 : command_string_index = 0;
914 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
915 0 : fprintf (xtrace_fp, "[[ ");
916 0 : if (invert)
917 0 : fprintf (xtrace_fp, "! ");
918 :
919 0 : if (type == COND_UNARY)
920 : {
921 0 : fprintf (xtrace_fp, "%s ", op->word);
922 0 : fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
923 : }
924 0 : else if (type == COND_BINARY)
925 : {
926 0 : fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
927 0 : fprintf (xtrace_fp, " %s ", op->word);
928 0 : fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
929 : }
930 :
931 0 : fprintf (xtrace_fp, " ]]\n");
932 :
933 0 : fflush (xtrace_fp);
934 0 : }
935 : #endif /* COND_COMMAND */
936 :
937 : #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
938 : /* A function to print the words of an arithmetic command when set -x is on. */
939 : void
940 0 : xtrace_print_arith_cmd (list)
941 : WORD_LIST *list;
942 : {
943 0 : WORD_LIST *w;
944 :
945 0 : CHECK_XTRACE_FP;
946 0 : fprintf (xtrace_fp, "%s", indirection_level_string ());
947 0 : fprintf (xtrace_fp, "(( ");
948 0 : for (w = list; w; w = w->next)
949 0 : fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
950 0 : fprintf (xtrace_fp, " ))\n");
951 :
952 0 : fflush (xtrace_fp);
953 0 : }
954 : #endif
955 :
956 : void
957 86315600 : print_simple_command (simple_command)
958 : SIMPLE_COM *simple_command;
959 : {
960 86315600 : command_print_word_list (simple_command->words, " ");
961 :
962 86315600 : if (simple_command->redirects)
963 : {
964 154770 : cprintf (" ");
965 154770 : print_redirection_list (simple_command->redirects);
966 : }
967 86315600 : }
968 :
969 : static void
970 146 : print_heredocs (heredocs)
971 : REDIRECT *heredocs;
972 : {
973 146 : REDIRECT *hdtail;
974 :
975 146 : cprintf (" ");
976 292 : for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
977 : {
978 146 : print_redirection (hdtail);
979 146 : cprintf ("\n");
980 : }
981 146 : was_heredoc = 1;
982 146 : }
983 :
984 : /* Print heredocs that are attached to the command before the connector
985 : represented by CSTRING. The parsing semantics require us to print the
986 : here-doc delimiters, then the connector (CSTRING), then the here-doc
987 : bodies. We don't print the connector if it's a `;', but we use it to
988 : note not to print an extra space after the last heredoc body and
989 : newline. */
990 : static void
991 3188 : print_deferred_heredocs (cstring)
992 : const char *cstring;
993 : {
994 3188 : REDIRECT *hdtail;
995 :
996 3188 : for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
997 : {
998 0 : cprintf (" ");
999 0 : print_heredoc_header (hdtail);
1000 : }
1001 3188 : if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
1002 3188 : cprintf ("%s", cstring);
1003 3188 : if (deferred_heredocs)
1004 0 : cprintf ("\n");
1005 3188 : for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
1006 : {
1007 0 : print_heredoc_body (hdtail);
1008 0 : cprintf ("\n");
1009 : }
1010 3188 : if (deferred_heredocs)
1011 : {
1012 0 : if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
1013 0 : cprintf (" "); /* make sure there's at least one space */
1014 0 : dispose_redirects (deferred_heredocs);
1015 0 : was_heredoc = 1;
1016 : }
1017 3188 : deferred_heredocs = (REDIRECT *)NULL;
1018 3188 : }
1019 :
1020 : static void
1021 154770 : print_redirection_list (redirects)
1022 : REDIRECT *redirects;
1023 : {
1024 154770 : REDIRECT *heredocs, *hdtail, *newredir;
1025 154770 : char *rw;
1026 :
1027 154770 : heredocs = (REDIRECT *)NULL;
1028 154770 : hdtail = heredocs;
1029 :
1030 154770 : was_heredoc = 0;
1031 393234 : while (redirects)
1032 : {
1033 : /* Defer printing the here documents until we've printed the
1034 : rest of the redirections. */
1035 238464 : if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
1036 : {
1037 146 : newredir = copy_redirect (redirects);
1038 146 : newredir->next = (REDIRECT *)NULL;
1039 146 : if (heredocs)
1040 : {
1041 0 : hdtail->next = newredir;
1042 0 : hdtail = newredir;
1043 : }
1044 : else
1045 : hdtail = heredocs = newredir;
1046 : }
1047 238318 : else if (redirects->instruction == r_duplicating_output_word && (redirects->flags & REDIR_VARASSIGN) == 0 && redirects->redirector.dest == 1)
1048 : {
1049 : /* Temporarily translate it as the execution code does. */
1050 25 : rw = redirects->redirectee.filename->word;
1051 25 : if (rw && *rw != '-' && DIGIT (*rw) == 0 && EXPCHAR (*rw) == 0)
1052 25 : redirects->instruction = r_err_and_out;
1053 25 : print_redirection (redirects);
1054 25 : redirects->instruction = r_duplicating_output_word;
1055 : }
1056 : else
1057 238293 : print_redirection (redirects);
1058 :
1059 238464 : redirects = redirects->next;
1060 238464 : if (redirects)
1061 83694 : cprintf (" ");
1062 : }
1063 :
1064 : /* Now that we've printed all the other redirections (on one line),
1065 : print the here documents. */
1066 154770 : if (heredocs && printing_connection)
1067 0 : deferred_heredocs = heredocs;
1068 154770 : else if (heredocs)
1069 : {
1070 146 : print_heredocs (heredocs);
1071 146 : dispose_redirects (heredocs);
1072 : }
1073 154770 : }
1074 :
1075 : static void
1076 146 : print_heredoc_header (redirect)
1077 : REDIRECT *redirect;
1078 : {
1079 146 : int kill_leading;
1080 146 : char *x;
1081 :
1082 146 : kill_leading = redirect->instruction == r_deblank_reading_until;
1083 :
1084 : /* Here doc header */
1085 146 : if (redirect->rflags & REDIR_VARASSIGN)
1086 0 : cprintf ("{%s}", redirect->redirector.filename->word);
1087 146 : else if (redirect->redirector.dest != 0)
1088 0 : cprintf ("%d", redirect->redirector.dest);
1089 :
1090 : /* If the here document delimiter is quoted, single-quote it. */
1091 146 : if (redirect->redirectee.filename->flags & W_QUOTED)
1092 : {
1093 49 : x = sh_single_quote (redirect->here_doc_eof);
1094 98 : cprintf ("<<%s%s", kill_leading ? "-" : "", x);
1095 49 : free (x);
1096 : }
1097 : else
1098 194 : cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
1099 146 : }
1100 :
1101 : static void
1102 0 : print_heredoc_body (redirect)
1103 : REDIRECT *redirect;
1104 : {
1105 : /* Here doc body */
1106 0 : cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
1107 0 : }
1108 :
1109 : static void
1110 238464 : print_redirection (redirect)
1111 : REDIRECT *redirect;
1112 : {
1113 238464 : int redirector, redir_fd;
1114 238464 : WORD_DESC *redirectee, *redir_word;
1115 :
1116 238464 : redirectee = redirect->redirectee.filename;
1117 238464 : redir_fd = redirect->redirectee.dest;
1118 :
1119 238464 : redir_word = redirect->redirector.filename;
1120 238464 : redirector = redirect->redirector.dest;
1121 :
1122 238464 : switch (redirect->instruction)
1123 : {
1124 36526 : case r_input_direction:
1125 36526 : if (redirect->rflags & REDIR_VARASSIGN)
1126 0 : cprintf ("{%s}", redir_word->word);
1127 36526 : else if (redirector != 0)
1128 24 : cprintf ("%d", redirector);
1129 36526 : cprintf ("< %s", redirectee->word);
1130 36526 : break;
1131 :
1132 121683 : case r_output_direction:
1133 121683 : if (redirect->rflags & REDIR_VARASSIGN)
1134 0 : cprintf ("{%s}", redir_word->word);
1135 121683 : else if (redirector != 1)
1136 39237 : cprintf ("%d", redirector);
1137 121683 : cprintf ("> %s", redirectee->word);
1138 121683 : break;
1139 :
1140 0 : case r_inputa_direction: /* Redirection created by the shell. */
1141 0 : cprintf ("&");
1142 0 : break;
1143 :
1144 9 : case r_output_force:
1145 9 : if (redirect->rflags & REDIR_VARASSIGN)
1146 0 : cprintf ("{%s}", redir_word->word);
1147 9 : else if (redirector != 1)
1148 0 : cprintf ("%d", redirector);
1149 9 : cprintf (">| %s", redirectee->word);
1150 9 : break;
1151 :
1152 59556 : case r_appending_to:
1153 59556 : if (redirect->rflags & REDIR_VARASSIGN)
1154 0 : cprintf ("{%s}", redir_word->word);
1155 59556 : else if (redirector != 1)
1156 9 : cprintf ("%d", redirector);
1157 59556 : cprintf (">> %s", redirectee->word);
1158 59556 : break;
1159 :
1160 68 : case r_input_output:
1161 68 : if (redirect->rflags & REDIR_VARASSIGN)
1162 0 : cprintf ("{%s}", redir_word->word);
1163 68 : else if (redirector != 1)
1164 68 : cprintf ("%d", redirector);
1165 68 : cprintf ("<> %s", redirectee->word);
1166 68 : break;
1167 :
1168 146 : case r_deblank_reading_until:
1169 : case r_reading_until:
1170 146 : print_heredoc_header (redirect);
1171 146 : cprintf ("\n");
1172 146 : print_heredoc_body (redirect);
1173 : break;
1174 :
1175 20 : case r_reading_string:
1176 20 : if (redirect->rflags & REDIR_VARASSIGN)
1177 0 : cprintf ("{%s}", redir_word->word);
1178 20 : else if (redirector != 0)
1179 0 : cprintf ("%d", redirector);
1180 : #if 0
1181 : /* Don't need to check whether or not to requote, since original quotes
1182 : are still intact. The only thing that has happened is that $'...'
1183 : has been replaced with 'expanded ...'. */
1184 : if (ansic_shouldquote (redirect->redirectee.filename->word))
1185 : {
1186 : char *x;
1187 : x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1188 : cprintf ("<<< %s", x);
1189 : free (x);
1190 : }
1191 : else
1192 : #endif
1193 20 : cprintf ("<<< %s", redirect->redirectee.filename->word);
1194 20 : break;
1195 :
1196 0 : case r_duplicating_input:
1197 0 : if (redirect->rflags & REDIR_VARASSIGN)
1198 0 : cprintf ("{%s}<&%d", redir_word->word, redir_fd);
1199 : else
1200 0 : cprintf ("%d<&%d", redirector, redir_fd);
1201 : break;
1202 :
1203 20407 : case r_duplicating_output:
1204 20407 : if (redirect->rflags & REDIR_VARASSIGN)
1205 0 : cprintf ("{%s}>&%d", redir_word->word, redir_fd);
1206 : else
1207 20407 : cprintf ("%d>&%d", redirector, redir_fd);
1208 : break;
1209 :
1210 0 : case r_duplicating_input_word:
1211 0 : if (redirect->rflags & REDIR_VARASSIGN)
1212 0 : cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
1213 : else
1214 0 : cprintf ("%d<&%s", redirector, redirectee->word);
1215 : break;
1216 :
1217 0 : case r_duplicating_output_word:
1218 0 : if (redirect->rflags & REDIR_VARASSIGN)
1219 0 : cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
1220 : else
1221 0 : cprintf ("%d>&%s", redirector, redirectee->word);
1222 : break;
1223 :
1224 0 : case r_move_input:
1225 0 : if (redirect->rflags & REDIR_VARASSIGN)
1226 0 : cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
1227 : else
1228 0 : cprintf ("%d<&%d-", redirector, redir_fd);
1229 : break;
1230 :
1231 0 : case r_move_output:
1232 0 : if (redirect->rflags & REDIR_VARASSIGN)
1233 0 : cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
1234 : else
1235 0 : cprintf ("%d>&%d-", redirector, redir_fd);
1236 : break;
1237 :
1238 0 : case r_move_input_word:
1239 0 : if (redirect->rflags & REDIR_VARASSIGN)
1240 0 : cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
1241 : else
1242 0 : cprintf ("%d<&%s-", redirector, redirectee->word);
1243 : break;
1244 :
1245 0 : case r_move_output_word:
1246 0 : if (redirect->rflags & REDIR_VARASSIGN)
1247 0 : cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
1248 : else
1249 0 : cprintf ("%d>&%s-", redirector, redirectee->word);
1250 : break;
1251 :
1252 0 : case r_close_this:
1253 0 : if (redirect->rflags & REDIR_VARASSIGN)
1254 0 : cprintf ("{%s}>&-", redir_word->word);
1255 : else
1256 0 : cprintf ("%d>&-", redirector);
1257 : break;
1258 :
1259 49 : case r_err_and_out:
1260 49 : cprintf ("&> %s", redirectee->word);
1261 49 : break;
1262 :
1263 0 : case r_append_err_and_out:
1264 0 : cprintf ("&>> %s", redirectee->word);
1265 0 : break;
1266 : }
1267 238464 : }
1268 :
1269 : static void
1270 0 : reset_locals ()
1271 : {
1272 0 : inside_function_def = 0;
1273 0 : indentation = 0;
1274 0 : printing_connection = 0;
1275 0 : deferred_heredocs = 0;
1276 0 : }
1277 :
1278 : static void
1279 0 : print_function_def (func)
1280 : FUNCTION_DEF *func;
1281 : {
1282 0 : COMMAND *cmdcopy;
1283 0 : REDIRECT *func_redirects;
1284 :
1285 0 : func_redirects = NULL;
1286 : /* When in posix mode, print functions as posix specifies them. */
1287 0 : if (posixly_correct == 0)
1288 0 : cprintf ("function %s () \n", func->name->word);
1289 : else
1290 0 : cprintf ("%s () \n", func->name->word);
1291 0 : add_unwind_protect (reset_locals, 0);
1292 :
1293 0 : indent (indentation);
1294 0 : cprintf ("{ \n");
1295 :
1296 0 : inside_function_def++;
1297 0 : indentation += indentation_amount;
1298 :
1299 0 : cmdcopy = copy_command (func->command);
1300 0 : if (cmdcopy->type == cm_group)
1301 : {
1302 0 : func_redirects = cmdcopy->redirects;
1303 0 : cmdcopy->redirects = (REDIRECT *)NULL;
1304 : }
1305 0 : make_command_string_internal (cmdcopy->type == cm_group
1306 0 : ? cmdcopy->value.Group->command
1307 : : cmdcopy);
1308 : /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
1309 :
1310 0 : remove_unwind_protect ();
1311 0 : indentation -= indentation_amount;
1312 0 : inside_function_def--;
1313 :
1314 0 : if (func_redirects)
1315 : { /* { */
1316 0 : newline ("} ");
1317 0 : print_redirection_list (func_redirects);
1318 0 : cmdcopy->redirects = func_redirects;
1319 : }
1320 : else
1321 0 : newline ("}");
1322 :
1323 0 : dispose_command (cmdcopy);
1324 0 : }
1325 :
1326 : /* Return the string representation of the named function.
1327 : NAME is the name of the function.
1328 : COMMAND is the function body. It should be a GROUP_COM.
1329 : flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1330 : flags&FUNC_EXTERNAL means convert from internal to external form
1331 : */
1332 : char *
1333 143 : named_function_string (name, command, flags)
1334 : char *name;
1335 : COMMAND *command;
1336 : int flags;
1337 : {
1338 143 : char *result;
1339 143 : int old_indent, old_amount;
1340 143 : COMMAND *cmdcopy;
1341 143 : REDIRECT *func_redirects;
1342 :
1343 143 : old_indent = indentation;
1344 143 : old_amount = indentation_amount;
1345 143 : command_string_index = was_heredoc = 0;
1346 143 : deferred_heredocs = 0;
1347 :
1348 143 : if (name && *name)
1349 : {
1350 0 : if (find_reserved_word (name) >= 0)
1351 0 : cprintf ("function ");
1352 0 : cprintf ("%s ", name);
1353 : }
1354 :
1355 143 : cprintf ("() ");
1356 :
1357 143 : if ((flags & FUNC_MULTILINE) == 0)
1358 : {
1359 0 : indentation = 1;
1360 0 : indentation_amount = 0;
1361 : }
1362 : else
1363 : {
1364 143 : cprintf ("\n");
1365 143 : indentation += indentation_amount;
1366 : }
1367 :
1368 143 : inside_function_def++;
1369 :
1370 143 : cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
1371 :
1372 143 : cmdcopy = copy_command (command);
1373 : /* Take any redirections specified in the function definition (which should
1374 : apply to the function as a whole) and save them for printing later. */
1375 143 : func_redirects = (REDIRECT *)NULL;
1376 143 : if (cmdcopy->type == cm_group)
1377 : {
1378 143 : func_redirects = cmdcopy->redirects;
1379 143 : cmdcopy->redirects = (REDIRECT *)NULL;
1380 : }
1381 286 : make_command_string_internal (cmdcopy->type == cm_group
1382 143 : ? cmdcopy->value.Group->command
1383 : : cmdcopy);
1384 : /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
1385 :
1386 143 : indentation = old_indent;
1387 143 : indentation_amount = old_amount;
1388 143 : inside_function_def--;
1389 :
1390 143 : if (func_redirects)
1391 : { /* { */
1392 0 : newline ("} ");
1393 0 : print_redirection_list (func_redirects);
1394 0 : cmdcopy->redirects = func_redirects;
1395 : }
1396 : else
1397 143 : newline ("}");
1398 :
1399 143 : result = the_printed_command;
1400 :
1401 143 : if ((flags & FUNC_MULTILINE) == 0)
1402 : {
1403 : #if 0
1404 : register int i;
1405 : for (i = 0; result[i]; i++)
1406 : if (result[i] == '\n')
1407 : {
1408 : strcpy (result + i, result + i + 1);
1409 : --i;
1410 : }
1411 : #else
1412 0 : if (result[2] == '\n') /* XXX -- experimental */
1413 0 : memmove (result + 2, result + 3, strlen (result) - 2);
1414 :
1415 : #endif
1416 : }
1417 :
1418 143 : dispose_command (cmdcopy);
1419 :
1420 143 : if (flags & FUNC_EXTERNAL)
1421 143 : result = remove_quoted_escapes (result);
1422 :
1423 143 : return (result);
1424 : }
1425 :
1426 : static void
1427 5312 : newline (string)
1428 : char *string;
1429 : {
1430 5312 : cprintf ("\n");
1431 5312 : indent (indentation);
1432 5312 : if (string && *string)
1433 4492 : cprintf ("%s", string);
1434 5312 : }
1435 :
1436 : static char *indentation_string;
1437 : static int indentation_size;
1438 :
1439 : static void
1440 14228 : indent (amount)
1441 : int amount;
1442 : {
1443 14228 : register int i;
1444 :
1445 21476 : RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1446 :
1447 46328 : for (i = 0; amount > 0; amount--)
1448 32100 : indentation_string[i++] = ' ';
1449 14228 : indentation_string[i] = '\0';
1450 14228 : cprintf ("%s", indentation_string);
1451 14228 : }
1452 :
1453 : static void
1454 6205 : semicolon ()
1455 : {
1456 6205 : if (command_string_index > 0 &&
1457 6205 : (the_printed_command[command_string_index - 1] == '&' ||
1458 : the_printed_command[command_string_index - 1] == '\n'))
1459 : return;
1460 6205 : cprintf (";");
1461 : }
1462 :
1463 : /* How to make the string. */
1464 : static void
1465 : #if defined (PREFER_STDARG)
1466 204490201 : cprintf (const char *control, ...)
1467 : #else
1468 : cprintf (control, va_alist)
1469 : const char *control;
1470 : va_dcl
1471 : #endif
1472 : {
1473 204490201 : register const char *s;
1474 204490201 : char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
1475 204490201 : int digit_arg, arg_len, c;
1476 204490201 : va_list args;
1477 :
1478 204490201 : SH_VA_START (args, control);
1479 :
1480 204490201 : arg_len = strlen (control);
1481 204490201 : the_printed_command_resize (arg_len + 1);
1482 :
1483 204490201 : char_arg[1] = '\0';
1484 204490201 : s = control;
1485 658638770 : while (s && *s)
1486 : {
1487 454148569 : c = *s++;
1488 454148569 : argp = (char *)NULL;
1489 454148569 : if (c != '%' || !*s)
1490 : {
1491 51610078 : char_arg[0] = c;
1492 51610078 : argp = char_arg;
1493 51610078 : arg_len = 1;
1494 : }
1495 : else
1496 : {
1497 402538491 : c = *s++;
1498 402538491 : switch (c)
1499 : {
1500 0 : case '%':
1501 0 : char_arg[0] = c;
1502 0 : argp = char_arg;
1503 0 : arg_len = 1;
1504 0 : break;
1505 :
1506 402458339 : case 's':
1507 402458339 : argp = va_arg (args, char *);
1508 402458339 : arg_len = strlen (argp);
1509 402458339 : break;
1510 :
1511 80152 : case 'd':
1512 : /* Represent an out-of-range file descriptor with an out-of-range
1513 : integer value. We can do this because the only use of `%d' in
1514 : the calls to cprintf is to output a file descriptor number for
1515 : a redirection. */
1516 80152 : digit_arg = va_arg (args, int);
1517 80152 : if (digit_arg < 0)
1518 : {
1519 0 : sprintf (intbuf, "%u", (unsigned)-1);
1520 0 : argp = intbuf;
1521 : }
1522 : else
1523 80152 : argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
1524 80152 : arg_len = strlen (argp);
1525 80152 : break;
1526 :
1527 0 : case 'c':
1528 0 : char_arg[0] = va_arg (args, int);
1529 0 : argp = char_arg;
1530 0 : arg_len = 1;
1531 0 : break;
1532 :
1533 0 : default:
1534 0 : programming_error (_("cprintf: `%c': invalid format character"), c);
1535 : /*NOTREACHED*/
1536 : }
1537 : }
1538 :
1539 454148569 : if (argp && arg_len)
1540 : {
1541 367825454 : the_printed_command_resize (arg_len + 1);
1542 367825454 : FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1543 367825454 : command_string_index += arg_len;
1544 : }
1545 : }
1546 :
1547 204490201 : va_end (args);
1548 :
1549 204490201 : the_printed_command[command_string_index] = '\0';
1550 204490201 : }
1551 :
1552 : /* Ensure that there is enough space to stuff LENGTH characters into
1553 : THE_PRINTED_COMMAND. */
1554 : static void
1555 572315655 : the_printed_command_resize (length)
1556 : int length;
1557 : {
1558 572315655 : if (the_printed_command == 0)
1559 : {
1560 9542957 : the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
1561 9542957 : the_printed_command = (char *)xmalloc (the_printed_command_size);
1562 9542957 : command_string_index = 0;
1563 : }
1564 562772698 : else if ((command_string_index + length) >= the_printed_command_size)
1565 : {
1566 5687417 : int new;
1567 5687417 : new = command_string_index + length + 1;
1568 :
1569 : /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1570 5687417 : new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
1571 5687417 : the_printed_command_size = new;
1572 :
1573 5687417 : the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
1574 : }
1575 572315655 : }
1576 :
1577 : #if defined (HAVE_VPRINTF)
1578 : /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1579 : also available.'' */
1580 :
1581 : static void
1582 : #if defined (PREFER_STDARG)
1583 0 : xprintf (const char *format, ...)
1584 : #else
1585 : xprintf (format, va_alist)
1586 : const char *format;
1587 : va_dcl
1588 : #endif
1589 : {
1590 0 : va_list args;
1591 :
1592 0 : SH_VA_START (args, format);
1593 :
1594 0 : vfprintf (stdout, format, args);
1595 0 : va_end (args);
1596 0 : }
1597 :
1598 : #else
1599 :
1600 : static void
1601 : xprintf (format, arg1, arg2, arg3, arg4, arg5)
1602 : const char *format;
1603 : {
1604 : printf (format, arg1, arg2, arg3, arg4, arg5);
1605 : }
1606 :
1607 : #endif /* !HAVE_VPRINTF */
|