blob: 50b26a3fae1666cdc264c0c225eeb09b8ad39b8f [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001/* print_command -- A way to make readable commands from a command tree. */
Jari Aaltob80f6442004-07-27 13:29:18 +00002
Jari Aalto31859422009-01-12 13:36:28 +00003/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00004
Jari Aalto31859422009-01-12 13:36:28 +00005 This file is part of GNU Bash, the Bourne Again SHell.
Jari Aalto726f6381996-08-26 18:22:31 +00006
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aalto726f6381996-08-26 18:22:31 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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.
Jari Aalto726f6381996-08-26 18:22:31 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 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*/
Jari Aalto726f6381996-08-26 18:22:31 +000020
Jari Aaltoccc6cda1996-12-23 17:02:34 +000021#include "config.h"
22
Jari Aalto726f6381996-08-26 18:22:31 +000023#include <stdio.h>
24
Jari Aaltoccc6cda1996-12-23 17:02:34 +000025#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000026# ifdef _MINIX
27# include <sys/types.h>
28# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000029# include <unistd.h>
Jari Aalto726f6381996-08-26 18:22:31 +000030#endif
31
Jari Aaltoccc6cda1996-12-23 17:02:34 +000032#if defined (PREFER_STDARG)
33# include <stdarg.h>
34#else
Jari Aalto7117c2d2002-07-17 14:10:11 +000035# include <varargs.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000036#endif
37
38#include "bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000039#include "bashintl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000040
41#include "shell.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000042#include "flags.h"
Jari Aaltod166f041997-06-05 14:59:13 +000043#include <y.tab.h> /* use <...> so we pick it up from the build directory */
Jari Aalto95732b42005-12-07 14:08:12 +000044
45#include "shmbutil.h"
46
Jari Aalto726f6381996-08-26 18:22:31 +000047#include "builtins/common.h"
48
Jari Aaltof73dda02001-11-13 17:56:06 +000049#if !HAVE_DECL_PRINTF
Jari Aalto726f6381996-08-26 18:22:31 +000050extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
51#endif
52
Jari Aalto7117c2d2002-07-17 14:10:11 +000053extern int indirection_level;
54
Jari Aaltoccc6cda1996-12-23 17:02:34 +000055static int indentation;
Jari Aalto726f6381996-08-26 18:22:31 +000056static int indentation_amount = 4;
57
Jari Aaltod166f041997-06-05 14:59:13 +000058#if defined (PREFER_STDARG)
Jari Aaltof73dda02001-11-13 17:56:06 +000059typedef 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)));
Jari Aaltod166f041997-06-05 14:59:13 +000063#else
Jari Aaltof73dda02001-11-13 17:56:06 +000064#define PFUNC VFunction
Jari Aaltod166f041997-06-05 14:59:13 +000065static void cprintf ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +000066static void xprintf ();
Jari Aalto726f6381996-08-26 18:22:31 +000067#endif
Jari Aaltof73dda02001-11-13 17:56:06 +000068
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));
74
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 *));
Jari Aalto31859422009-01-12 13:36:28 +000081static void print_heredoc_header __P((REDIRECT *));
82static void print_heredoc_body __P((REDIRECT *));
83static void print_heredocs __P((REDIRECT *));
84static void print_deferred_heredocs __P((const char *));
Jari Aaltof73dda02001-11-13 17:56:06 +000085
86static void print_for_command __P((FOR_COM *));
87#if defined (ARITH_FOR_COMMAND)
88static void print_arith_for_command __P((ARITH_FOR_COM *));
89#endif
90#if defined (SELECT_COMMAND)
91static void print_select_command __P((SELECT_COM *));
92#endif
93static void print_group_command __P((GROUP_COM *));
94static void print_case_command __P((CASE_COM *));
95static void print_while_command __P((WHILE_COM *));
96static void print_until_command __P((WHILE_COM *));
97static void print_until_or_while __P((WHILE_COM *, char *));
98static void print_if_command __P((IF_COM *));
Jari Aaltocce855b1998-04-17 19:52:44 +000099#if defined (COND_COMMAND)
Jari Aaltof73dda02001-11-13 17:56:06 +0000100static void print_cond_node __P((COND_COM *));
Jari Aaltocce855b1998-04-17 19:52:44 +0000101#endif
Jari Aaltof73dda02001-11-13 17:56:06 +0000102static void print_function_def __P((FUNCTION_DEF *));
Jari Aalto726f6381996-08-26 18:22:31 +0000103
Jari Aaltod166f041997-06-05 14:59:13 +0000104#define PRINTED_COMMAND_INITIAL_SIZE 64
105#define PRINTED_COMMAND_GROW_SIZE 128
Jari Aalto726f6381996-08-26 18:22:31 +0000106
107char *the_printed_command = (char *)NULL;
108int the_printed_command_size = 0;
109int command_string_index = 0;
110
111/* Non-zero means the stuff being printed is inside of a function def. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000112static int inside_function_def;
113static int skip_this_indent;
Jari Aaltod166f041997-06-05 14:59:13 +0000114static int was_heredoc;
Jari Aalto31859422009-01-12 13:36:28 +0000115static int printing_connection;
116static REDIRECT *deferred_heredocs;
Jari Aalto726f6381996-08-26 18:22:31 +0000117
118/* The depth of the group commands that we are currently printing. This
119 includes the group command that is a function body. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000120static int group_command_nesting;
Jari Aalto726f6381996-08-26 18:22:31 +0000121
Jari Aalto7117c2d2002-07-17 14:10:11 +0000122/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
123static char indirection_string[100];
124
Jari Aalto726f6381996-08-26 18:22:31 +0000125/* Print COMMAND (a command tree) on standard output. */
126void
127print_command (command)
128 COMMAND *command;
129{
130 command_string_index = 0;
131 printf ("%s", make_command_string (command));
132}
133
134/* Make a string which is the printed representation of the command
135 tree in COMMAND. We return this string. However, the string is
136 not consed, so you have to do that yourself if you want it to
137 remain around. */
138char *
139make_command_string (command)
140 COMMAND *command;
141{
Jari Aaltod166f041997-06-05 14:59:13 +0000142 command_string_index = was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000143 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000144 make_command_string_internal (command);
145 return (the_printed_command);
146}
147
148/* The internal function. This is the real workhorse. */
149static void
150make_command_string_internal (command)
151 COMMAND *command;
152{
Jari Aalto31859422009-01-12 13:36:28 +0000153 char s[3];
154
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000155 if (command == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000156 cprintf ("");
157 else
158 {
159 if (skip_this_indent)
160 skip_this_indent--;
161 else
162 indent (indentation);
163
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000164 if (command->flags & CMD_TIME_PIPELINE)
Jari Aaltod166f041997-06-05 14:59:13 +0000165 {
166 cprintf ("time ");
167 if (command->flags & CMD_TIME_POSIX)
168 cprintf ("-p ");
169 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000170
Jari Aalto726f6381996-08-26 18:22:31 +0000171 if (command->flags & CMD_INVERT_RETURN)
172 cprintf ("! ");
173
174 switch (command->type)
175 {
176 case cm_for:
177 print_for_command (command->value.For);
178 break;
179
Jari Aaltobb706242000-03-17 21:46:59 +0000180#if defined (ARITH_FOR_COMMAND)
181 case cm_arith_for:
182 print_arith_for_command (command->value.ArithFor);
183 break;
184#endif
185
Jari Aalto726f6381996-08-26 18:22:31 +0000186#if defined (SELECT_COMMAND)
187 case cm_select:
188 print_select_command (command->value.Select);
189 break;
190#endif
191
192 case cm_case:
193 print_case_command (command->value.Case);
194 break;
195
196 case cm_while:
197 print_while_command (command->value.While);
198 break;
199
200 case cm_until:
201 print_until_command (command->value.While);
202 break;
203
204 case cm_if:
205 print_if_command (command->value.If);
206 break;
207
Jari Aaltocce855b1998-04-17 19:52:44 +0000208#if defined (DPAREN_ARITHMETIC)
209 case cm_arith:
Jari Aaltob80f6442004-07-27 13:29:18 +0000210 print_arith_command (command->value.Arith->exp);
Jari Aaltocce855b1998-04-17 19:52:44 +0000211 break;
212#endif
213
214#if defined (COND_COMMAND)
215 case cm_cond:
216 print_cond_command (command->value.Cond);
217 break;
218#endif
219
Jari Aalto726f6381996-08-26 18:22:31 +0000220 case cm_simple:
221 print_simple_command (command->value.Simple);
222 break;
223
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000224 case cm_connection:
Jari Aalto726f6381996-08-26 18:22:31 +0000225
226 skip_this_indent++;
Jari Aalto31859422009-01-12 13:36:28 +0000227 printing_connection++;
Jari Aalto726f6381996-08-26 18:22:31 +0000228 make_command_string_internal (command->value.Connection->first);
229
230 switch (command->value.Connection->connector)
231 {
232 case '&':
233 case '|':
234 {
235 char c = command->value.Connection->connector;
Jari Aalto31859422009-01-12 13:36:28 +0000236
237 s[0] = ' ';
238 s[1] = c;
239 s[2] = '\0';
240
241 print_deferred_heredocs (s);
242
Jari Aalto726f6381996-08-26 18:22:31 +0000243 if (c != '&' || command->value.Connection->second)
244 {
245 cprintf (" ");
246 skip_this_indent++;
247 }
248 }
249 break;
250
251 case AND_AND:
Jari Aalto31859422009-01-12 13:36:28 +0000252 print_deferred_heredocs (" && ");
Jari Aalto726f6381996-08-26 18:22:31 +0000253 if (command->value.Connection->second)
254 skip_this_indent++;
255 break;
256
257 case OR_OR:
Jari Aalto31859422009-01-12 13:36:28 +0000258 print_deferred_heredocs (" || ");
Jari Aalto726f6381996-08-26 18:22:31 +0000259 if (command->value.Connection->second)
260 skip_this_indent++;
261 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000262
Jari Aalto726f6381996-08-26 18:22:31 +0000263 case ';':
Jari Aalto31859422009-01-12 13:36:28 +0000264#if 0
Jari Aaltod166f041997-06-05 14:59:13 +0000265 if (was_heredoc == 0)
266 cprintf (";");
267 else
268 was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000269#else
270 if (deferred_heredocs == 0)
271 cprintf (";");
272 else
273 print_deferred_heredocs (";");
274#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000275
276 if (inside_function_def)
277 cprintf ("\n");
278 else
279 {
280 cprintf (" ");
281 if (command->value.Connection->second)
282 skip_this_indent++;
283 }
284 break;
285
286 default:
Jari Aaltob80f6442004-07-27 13:29:18 +0000287 cprintf (_("print_command: bad connector `%d'"),
Jari Aalto726f6381996-08-26 18:22:31 +0000288 command->value.Connection->connector);
289 break;
290 }
291
292 make_command_string_internal (command->value.Connection->second);
Jari Aalto31859422009-01-12 13:36:28 +0000293 printing_connection--;
Jari Aalto726f6381996-08-26 18:22:31 +0000294 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000295
Jari Aalto726f6381996-08-26 18:22:31 +0000296 case cm_function_def:
297 print_function_def (command->value.Function_def);
298 break;
299
300 case cm_group:
301 print_group_command (command->value.Group);
302 break;
303
Jari Aaltobb706242000-03-17 21:46:59 +0000304 case cm_subshell:
305 cprintf ("( ");
306 skip_this_indent++;
307 make_command_string_internal (command->value.Subshell->command);
308 cprintf (" )");
309 break;
310
Jari Aalto31859422009-01-12 13:36:28 +0000311 case cm_coproc:
312 cprintf ("coproc %s ", command->value.Coproc->name);
313 skip_this_indent++;
314 make_command_string_internal (command->value.Coproc->command);
315 break;
316
Jari Aalto726f6381996-08-26 18:22:31 +0000317 default:
Jari Aaltob72432f1999-02-19 17:11:39 +0000318 command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000319 break;
320 }
321
Jari Aalto726f6381996-08-26 18:22:31 +0000322
323 if (command->redirects)
Jari Aaltob72432f1999-02-19 17:11:39 +0000324 {
325 cprintf (" ");
326 print_redirection_list (command->redirects);
327 }
Jari Aalto726f6381996-08-26 18:22:31 +0000328 }
329}
330
331static void
332_print_word_list (list, separator, pfunc)
333 WORD_LIST *list;
334 char *separator;
Jari Aaltof73dda02001-11-13 17:56:06 +0000335 PFUNC *pfunc;
Jari Aalto726f6381996-08-26 18:22:31 +0000336{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000337 WORD_LIST *w;
338
339 for (w = list; w; w = w->next)
340 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
Jari Aalto726f6381996-08-26 18:22:31 +0000341}
342
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000343void
344print_word_list (list, separator)
Jari Aalto726f6381996-08-26 18:22:31 +0000345 WORD_LIST *list;
346 char *separator;
347{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000348 _print_word_list (list, separator, xprintf);
349}
350
Jari Aalto7117c2d2002-07-17 14:10:11 +0000351/* Return a string denoting what our indirection level is. */
352
353char *
354indirection_level_string ()
355{
356 register int i, j;
357 char *ps4;
Jari Aalto95732b42005-12-07 14:08:12 +0000358 char ps4_firstc[MB_LEN_MAX+1];
359 int ps4_firstc_len, ps4_len;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000360
361 indirection_string[0] = '\0';
362 ps4 = get_string_value ("PS4");
363
364 if (ps4 == 0 || *ps4 == '\0')
365 return (indirection_string);
366
367 change_flag ('x', FLAG_OFF);
368 ps4 = decode_prompt_string (ps4);
369 change_flag ('x', FLAG_ON);
370
Jari Aaltob80f6442004-07-27 13:29:18 +0000371 if (ps4 == 0 || *ps4 == '\0')
372 return (indirection_string);
373
Jari Aalto95732b42005-12-07 14:08:12 +0000374#if defined (HANDLE_MULTIBYTE)
375 ps4_len = strnlen (ps4, MB_CUR_MAX);
376 ps4_firstc_len = MBLEN (ps4, ps4_len);
377 if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
378 {
379 ps4_firstc[0] = ps4[0];
380 ps4_firstc[ps4_firstc_len = 1] = '\0';
381 }
382 else
383 memcpy (ps4_firstc, ps4, ps4_firstc_len);
384#else
385 ps4_firstc[0] = ps4[0];
386 ps4_firstc[ps4_firstc_len = 1] = '\0';
387#endif
388
389 for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
390 {
391 if (ps4_firstc_len == 1)
392 indirection_string[i] = ps4_firstc[0];
393 else
394 memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
395 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000396
Jari Aalto95732b42005-12-07 14:08:12 +0000397 for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000398 indirection_string[i] = ps4[j];
399
400 indirection_string[i] = '\0';
401 free (ps4);
402 return (indirection_string);
403}
404
Jari Aaltob80f6442004-07-27 13:29:18 +0000405void
406xtrace_print_assignment (name, value, assign_list, xflags)
407 char *name, *value;
408 int assign_list, xflags;
409{
410 char *nval;
411
412 if (xflags)
413 fprintf (stderr, "%s", indirection_level_string ());
414
415 /* VALUE should not be NULL when this is called. */
416 if (*value == '\0' || assign_list)
417 nval = value;
418 else if (sh_contains_shell_metas (value))
419 nval = sh_single_quote (value);
420 else if (ansic_shouldquote (value))
421 nval = ansic_quote (value, 0, (int *)0);
422 else
423 nval = value;
424
425 if (assign_list)
426 fprintf (stderr, "%s=(%s)\n", name, nval);
427 else
428 fprintf (stderr, "%s=%s\n", name, nval);
429
430 if (nval != value)
431 FREE (nval);
432
433 fflush (stderr);
434}
435
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000436/* A function to print the words of a simple command when set -x is on. */
437void
Jari Aaltob80f6442004-07-27 13:29:18 +0000438xtrace_print_word_list (list, xtflags)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000439 WORD_LIST *list;
Jari Aaltob80f6442004-07-27 13:29:18 +0000440 int xtflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000441{
442 WORD_LIST *w;
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000443 char *t, *x;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000444
Jari Aaltob80f6442004-07-27 13:29:18 +0000445 if (xtflags)
446 fprintf (stderr, "%s", indirection_level_string ());
447
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000448 for (w = list; w; w = w->next)
449 {
450 t = w->word->word;
451 if (t == 0 || *t == '\0')
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000452 fprintf (stderr, "''%s", w->next ? " " : "");
Jari Aalto28ef6c32001-04-06 19:14:31 +0000453 else if (sh_contains_shell_metas (t))
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000454 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000455 x = sh_single_quote (t);
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000456 fprintf (stderr, "%s%s", x, w->next ? " " : "");
457 free (x);
458 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000459 else if (ansic_shouldquote (t))
460 {
461 x = ansic_quote (t, 0, (int *)0);
462 fprintf (stderr, "%s%s", x, w->next ? " " : "");
463 free (x);
464 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000465 else
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000466 fprintf (stderr, "%s%s", t, w->next ? " " : "");
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000467 }
468 fprintf (stderr, "\n");
Jari Aalto726f6381996-08-26 18:22:31 +0000469}
470
471static void
472command_print_word_list (list, separator)
473 WORD_LIST *list;
474 char *separator;
475{
476 _print_word_list (list, separator, cprintf);
477}
478
Jari Aaltob80f6442004-07-27 13:29:18 +0000479void
480print_for_command_head (for_command)
Jari Aalto726f6381996-08-26 18:22:31 +0000481 FOR_COM *for_command;
482{
483 cprintf ("for %s in ", for_command->name->word);
484 command_print_word_list (for_command->map_list, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000485}
486
487void
488xtrace_print_for_command_head (for_command)
489 FOR_COM *for_command;
490{
491 fprintf (stderr, "%s", indirection_level_string ());
492 fprintf (stderr, "for %s in ", for_command->name->word);
493 xtrace_print_word_list (for_command->map_list, 0);
494}
495
496static void
497print_for_command (for_command)
498 FOR_COM *for_command;
499{
500 print_for_command_head (for_command);
501
Jari Aalto726f6381996-08-26 18:22:31 +0000502 cprintf (";");
503 newline ("do\n");
504 indentation += indentation_amount;
505 make_command_string_internal (for_command->action);
506 semicolon ();
507 indentation -= indentation_amount;
508 newline ("done");
509}
510
Jari Aaltobb706242000-03-17 21:46:59 +0000511#if defined (ARITH_FOR_COMMAND)
512static void
513print_arith_for_command (arith_for_command)
514 ARITH_FOR_COM *arith_for_command;
515{
Jari Aaltob80f6442004-07-27 13:29:18 +0000516 cprintf ("for ((");
Jari Aaltobb706242000-03-17 21:46:59 +0000517 command_print_word_list (arith_for_command->init, " ");
Jari Aalto95732b42005-12-07 14:08:12 +0000518 cprintf ("; ");
Jari Aaltobb706242000-03-17 21:46:59 +0000519 command_print_word_list (arith_for_command->test, " ");
Jari Aalto95732b42005-12-07 14:08:12 +0000520 cprintf ("; ");
Jari Aaltobb706242000-03-17 21:46:59 +0000521 command_print_word_list (arith_for_command->step, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000522 cprintf ("))");
Jari Aaltobb706242000-03-17 21:46:59 +0000523 newline ("do\n");
524 indentation += indentation_amount;
525 make_command_string_internal (arith_for_command->action);
526 semicolon ();
527 indentation -= indentation_amount;
528 newline ("done");
529}
530#endif /* ARITH_FOR_COMMAND */
531
Jari Aalto726f6381996-08-26 18:22:31 +0000532#if defined (SELECT_COMMAND)
Jari Aaltob80f6442004-07-27 13:29:18 +0000533void
534print_select_command_head (select_command)
Jari Aalto726f6381996-08-26 18:22:31 +0000535 SELECT_COM *select_command;
536{
537 cprintf ("select %s in ", select_command->name->word);
538 command_print_word_list (select_command->map_list, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000539}
540
541void
542xtrace_print_select_command_head (select_command)
543 SELECT_COM *select_command;
544{
545 fprintf (stderr, "%s", indirection_level_string ());
546 fprintf (stderr, "select %s in ", select_command->name->word);
547 xtrace_print_word_list (select_command->map_list, 0);
548}
549
550static void
551print_select_command (select_command)
552 SELECT_COM *select_command;
553{
554 print_select_command_head (select_command);
555
Jari Aalto726f6381996-08-26 18:22:31 +0000556 cprintf (";");
557 newline ("do\n");
558 indentation += indentation_amount;
559 make_command_string_internal (select_command->action);
560 semicolon ();
561 indentation -= indentation_amount;
562 newline ("done");
563}
564#endif /* SELECT_COMMAND */
565
566static void
567print_group_command (group_command)
568 GROUP_COM *group_command;
569{
570 group_command_nesting++;
571 cprintf ("{ ");
572
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000573 if (inside_function_def == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000574 skip_this_indent++;
575 else
576 {
577 /* This is a group command { ... } inside of a function
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000578 definition, and should be printed as a multiline group
Jari Aalto726f6381996-08-26 18:22:31 +0000579 command, using the current indentation. */
580 cprintf ("\n");
581 indentation += indentation_amount;
582 }
583
584 make_command_string_internal (group_command->command);
585
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000586 if (inside_function_def)
Jari Aalto726f6381996-08-26 18:22:31 +0000587 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000588 cprintf ("\n");
Jari Aalto726f6381996-08-26 18:22:31 +0000589 indentation -= indentation_amount;
590 indent (indentation);
Jari Aalto726f6381996-08-26 18:22:31 +0000591 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000592 else
593 {
594 semicolon ();
595 cprintf (" ");
596 }
597
Jari Aalto726f6381996-08-26 18:22:31 +0000598 cprintf ("}");
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000599
Jari Aalto726f6381996-08-26 18:22:31 +0000600 group_command_nesting--;
601}
602
Jari Aaltob80f6442004-07-27 13:29:18 +0000603void
604print_case_command_head (case_command)
605 CASE_COM *case_command;
606{
607 cprintf ("case %s in ", case_command->word->word);
608}
609
610void
611xtrace_print_case_command_head (case_command)
612 CASE_COM *case_command;
613{
614 fprintf (stderr, "%s", indirection_level_string ());
615 fprintf (stderr, "case %s in\n", case_command->word->word);
616}
617
Jari Aalto726f6381996-08-26 18:22:31 +0000618static void
619print_case_command (case_command)
620 CASE_COM *case_command;
621{
Jari Aaltob80f6442004-07-27 13:29:18 +0000622 print_case_command_head (case_command);
623
Jari Aalto726f6381996-08-26 18:22:31 +0000624 if (case_command->clauses)
625 print_case_clauses (case_command->clauses);
626 newline ("esac");
627}
628
629static void
630print_case_clauses (clauses)
631 PATTERN_LIST *clauses;
632{
633 indentation += indentation_amount;
634 while (clauses)
635 {
636 newline ("");
637 command_print_word_list (clauses->patterns, " | ");
638 cprintf (")\n");
639 indentation += indentation_amount;
640 make_command_string_internal (clauses->action);
641 indentation -= indentation_amount;
Jari Aalto31859422009-01-12 13:36:28 +0000642 if (clauses->flags & CASEPAT_FALLTHROUGH)
643 newline (";&");
644 else if (clauses->flags & CASEPAT_TESTNEXT)
645 newline (";;&");
646 else
647 newline (";;");
Jari Aalto726f6381996-08-26 18:22:31 +0000648 clauses = clauses->next;
649 }
650 indentation -= indentation_amount;
651}
652
653static void
654print_while_command (while_command)
655 WHILE_COM *while_command;
656{
657 print_until_or_while (while_command, "while");
658}
659
660static void
661print_until_command (while_command)
662 WHILE_COM *while_command;
663{
664 print_until_or_while (while_command, "until");
665}
666
667static void
668print_until_or_while (while_command, which)
669 WHILE_COM *while_command;
670 char *which;
671{
672 cprintf ("%s ", which);
673 skip_this_indent++;
674 make_command_string_internal (while_command->test);
675 semicolon ();
676 cprintf (" do\n"); /* was newline ("do\n"); */
677 indentation += indentation_amount;
678 make_command_string_internal (while_command->action);
679 indentation -= indentation_amount;
680 semicolon ();
681 newline ("done");
682}
683
684static void
685print_if_command (if_command)
686 IF_COM *if_command;
687{
688 cprintf ("if ");
689 skip_this_indent++;
690 make_command_string_internal (if_command->test);
691 semicolon ();
692 cprintf (" then\n");
693 indentation += indentation_amount;
694 make_command_string_internal (if_command->true_case);
695 indentation -= indentation_amount;
696
697 if (if_command->false_case)
698 {
699 semicolon ();
700 newline ("else\n");
701 indentation += indentation_amount;
702 make_command_string_internal (if_command->false_case);
703 indentation -= indentation_amount;
704 }
705 semicolon ();
706 newline ("fi");
707}
708
Jari Aaltocce855b1998-04-17 19:52:44 +0000709#if defined (DPAREN_ARITHMETIC)
Jari Aaltob80f6442004-07-27 13:29:18 +0000710void
711print_arith_command (arith_cmd_list)
712 WORD_LIST *arith_cmd_list;
Jari Aaltocce855b1998-04-17 19:52:44 +0000713{
Jari Aaltob80f6442004-07-27 13:29:18 +0000714 cprintf ("((");
715 command_print_word_list (arith_cmd_list, " ");
716 cprintf ("))");
Jari Aaltocce855b1998-04-17 19:52:44 +0000717}
Jari Aaltobb706242000-03-17 21:46:59 +0000718#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000719
720#if defined (COND_COMMAND)
721static void
722print_cond_node (cond)
723 COND_COM *cond;
724{
725 if (cond->flags & CMD_INVERT_RETURN)
726 cprintf ("! ");
727
728 if (cond->type == COND_EXPR)
729 {
730 cprintf ("( ");
731 print_cond_node (cond->left);
732 cprintf (" )");
733 }
734 else if (cond->type == COND_AND)
735 {
736 print_cond_node (cond->left);
737 cprintf (" && ");
738 print_cond_node (cond->right);
739 }
740 else if (cond->type == COND_OR)
741 {
742 print_cond_node (cond->left);
743 cprintf (" || ");
744 print_cond_node (cond->right);
745 }
746 else if (cond->type == COND_UNARY)
747 {
Jari Aaltob72432f1999-02-19 17:11:39 +0000748 cprintf ("%s", cond->op->word);
Jari Aaltocce855b1998-04-17 19:52:44 +0000749 cprintf (" ");
750 print_cond_node (cond->left);
751 }
752 else if (cond->type == COND_BINARY)
753 {
754 print_cond_node (cond->left);
755 cprintf (" ");
Jari Aaltob72432f1999-02-19 17:11:39 +0000756 cprintf ("%s", cond->op->word);
Jari Aaltocce855b1998-04-17 19:52:44 +0000757 cprintf (" ");
758 print_cond_node (cond->right);
759 }
760 else if (cond->type == COND_TERM)
761 {
Jari Aaltob72432f1999-02-19 17:11:39 +0000762 cprintf ("%s", cond->op->word); /* need to add quoting here */
Jari Aaltocce855b1998-04-17 19:52:44 +0000763 }
764}
765
Jari Aaltob80f6442004-07-27 13:29:18 +0000766void
Jari Aaltocce855b1998-04-17 19:52:44 +0000767print_cond_command (cond)
768 COND_COM *cond;
769{
770 cprintf ("[[ ");
771 print_cond_node (cond);
772 cprintf (" ]]");
773}
774
Jari Aalto28ef6c32001-04-06 19:14:31 +0000775#ifdef DEBUG
Jari Aaltocce855b1998-04-17 19:52:44 +0000776void
777debug_print_cond_command (cond)
778 COND_COM *cond;
779{
780 fprintf (stderr, "DEBUG: ");
781 command_string_index = 0;
782 print_cond_command (cond);
783 fprintf (stderr, "%s\n", the_printed_command);
784}
Jari Aalto28ef6c32001-04-06 19:14:31 +0000785#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000786
787void
788xtrace_print_cond_term (type, invert, op, arg1, arg2)
789 int type, invert;
790 WORD_DESC *op;
791 char *arg1, *arg2;
792{
793 command_string_index = 0;
794 fprintf (stderr, "%s", indirection_level_string ());
795 fprintf (stderr, "[[ ");
796 if (invert)
797 fprintf (stderr, "! ");
798
799 if (type == COND_UNARY)
800 {
801 fprintf (stderr, "%s ", op->word);
802 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
803 }
804 else if (type == COND_BINARY)
805 {
806 fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
807 fprintf (stderr, " %s ", op->word);
808 fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
809 }
810
811 fprintf (stderr, " ]]\n");
812}
813#endif /* COND_COMMAND */
814
Jari Aaltobb706242000-03-17 21:46:59 +0000815#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
Jari Aaltocce855b1998-04-17 19:52:44 +0000816/* A function to print the words of an arithmetic command when set -x is on. */
817void
818xtrace_print_arith_cmd (list)
819 WORD_LIST *list;
820{
821 WORD_LIST *w;
822
823 fprintf (stderr, "%s", indirection_level_string ());
824 fprintf (stderr, "(( ");
825 for (w = list; w; w = w->next)
826 fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
827 fprintf (stderr, " ))\n");
828}
829#endif
830
Jari Aalto726f6381996-08-26 18:22:31 +0000831void
832print_simple_command (simple_command)
833 SIMPLE_COM *simple_command;
834{
835 command_print_word_list (simple_command->words, " ");
836
837 if (simple_command->redirects)
838 {
839 cprintf (" ");
840 print_redirection_list (simple_command->redirects);
841 }
842}
843
844static void
Jari Aalto31859422009-01-12 13:36:28 +0000845print_heredocs (heredocs)
846 REDIRECT *heredocs;
847{
848 REDIRECT *hdtail;
849
850 cprintf (" ");
851 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
852 {
853 print_redirection (hdtail);
854 cprintf ("\n");
855 }
856 was_heredoc = 1;
857}
858
859/* Print heredocs that are attached to the command before the connector
860 represented by CSTRING. The parsing semantics require us to print the
861 here-doc delimiters, then the connector (CSTRING), then the here-doc
862 bodies. We don't print the connector if it's a `;', but we use it to
863 note not to print an extra space after the last heredoc body and
864 newline. */
865static void
866print_deferred_heredocs (cstring)
867 const char *cstring;
868{
869 REDIRECT *hdtail;
870
871 for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
872 {
873 cprintf (" ");
874 print_heredoc_header (hdtail);
875 }
876 if (cstring[0] != ';' || cstring[1])
877 cprintf ("%s", cstring);
878 if (deferred_heredocs)
879 cprintf ("\n");
880 for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
881 {
882 print_heredoc_body (hdtail);
883 cprintf ("\n");
884 }
885 if (deferred_heredocs)
886 {
887 if (cstring[0] != ';' || cstring[1])
888 cprintf (" "); /* make sure there's at least one space */
889 dispose_redirects (deferred_heredocs);
890 }
891 deferred_heredocs = (REDIRECT *)NULL;
892}
893
894static void
Jari Aalto726f6381996-08-26 18:22:31 +0000895print_redirection_list (redirects)
896 REDIRECT *redirects;
897{
Jari Aaltod166f041997-06-05 14:59:13 +0000898 REDIRECT *heredocs, *hdtail, *newredir;
899
900 heredocs = (REDIRECT *)NULL;
901 hdtail = heredocs;
902
903 was_heredoc = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000904 while (redirects)
905 {
Jari Aaltod166f041997-06-05 14:59:13 +0000906 /* Defer printing the here documents until we've printed the
907 rest of the redirections. */
908 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
909 {
910 newredir = copy_redirect (redirects);
911 newredir->next = (REDIRECT *)NULL;
912 if (heredocs)
913 {
914 hdtail->next = newredir;
915 hdtail = newredir;
916 }
917 else
918 hdtail = heredocs = newredir;
919 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000920 else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
921 {
922 /* Temporarily translate it as the execution code does. */
923 redirects->instruction = r_err_and_out;
924 print_redirection (redirects);
925 redirects->instruction = r_duplicating_output_word;
926 }
Jari Aaltod166f041997-06-05 14:59:13 +0000927 else
928 print_redirection (redirects);
929
Jari Aalto726f6381996-08-26 18:22:31 +0000930 redirects = redirects->next;
931 if (redirects)
932 cprintf (" ");
933 }
Jari Aaltod166f041997-06-05 14:59:13 +0000934
935 /* Now that we've printed all the other redirections (on one line),
936 print the here documents. */
Jari Aalto31859422009-01-12 13:36:28 +0000937 if (heredocs && printing_connection)
938 deferred_heredocs = heredocs;
939 else if (heredocs)
Jari Aaltod166f041997-06-05 14:59:13 +0000940 {
Jari Aalto31859422009-01-12 13:36:28 +0000941 print_heredocs (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +0000942 dispose_redirects (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +0000943 }
Jari Aalto726f6381996-08-26 18:22:31 +0000944}
945
946static void
Jari Aalto31859422009-01-12 13:36:28 +0000947print_heredoc_header (redirect)
948 REDIRECT *redirect;
949{
950 int kill_leading;
951 char *x;
952
953 kill_leading = redirect->instruction == r_deblank_reading_until;
954
955 /* Here doc header */
956 if (redirect->redirector != 0)
957 cprintf ("%d", redirect->redirector);
958
959 /* If the here document delimiter is quoted, single-quote it. */
960 if (redirect->redirectee.filename->flags & W_QUOTED)
961 {
962 x = sh_single_quote (redirect->here_doc_eof);
963 cprintf ("<<%s%s", kill_leading ? "-" : "", x);
964 free (x);
965 }
966 else
967 cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
968}
969
970static void
971print_heredoc_body (redirect)
972 REDIRECT *redirect;
973{
974 /* Here doc body */
975 cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
976}
977
978static void
Jari Aalto726f6381996-08-26 18:22:31 +0000979print_redirection (redirect)
980 REDIRECT *redirect;
981{
Jari Aaltod166f041997-06-05 14:59:13 +0000982 int kill_leading, redirector, redir_fd;
983 WORD_DESC *redirectee;
984
985 kill_leading = 0;
986 redirectee = redirect->redirectee.filename;
987 redirector = redirect->redirector;
988 redir_fd = redirect->redirectee.dest;
Jari Aalto726f6381996-08-26 18:22:31 +0000989
990 switch (redirect->instruction)
991 {
992 case r_output_direction:
993 if (redirector != 1)
994 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +0000995 cprintf ("> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +0000996 break;
997
998 case r_input_direction:
999 if (redirector != 0)
1000 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001001 cprintf ("< %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001002 break;
1003
1004 case r_inputa_direction: /* Redirection created by the shell. */
1005 cprintf ("&");
1006 break;
1007
1008 case r_appending_to:
1009 if (redirector != 1)
1010 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001011 cprintf (">> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001012 break;
1013
1014 case r_deblank_reading_until:
Jari Aalto726f6381996-08-26 18:22:31 +00001015 case r_reading_until:
Jari Aalto31859422009-01-12 13:36:28 +00001016 print_heredoc_header (redirect);
1017 cprintf ("\n");
1018 print_heredoc_body (redirect);
Jari Aalto726f6381996-08-26 18:22:31 +00001019 break;
1020
Jari Aalto7117c2d2002-07-17 14:10:11 +00001021 case r_reading_string:
1022 if (redirector != 0)
1023 cprintf ("%d", redirector);
1024 if (ansic_shouldquote (redirect->redirectee.filename->word))
1025 {
1026 char *x;
1027 x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1028 cprintf ("<<< %s", x);
1029 free (x);
1030 }
1031 else
1032 cprintf ("<<< %s", redirect->redirectee.filename->word);
1033 break;
1034
Jari Aalto726f6381996-08-26 18:22:31 +00001035 case r_duplicating_input:
1036 cprintf ("%d<&%d", redirector, redir_fd);
1037 break;
1038
1039 case r_duplicating_output:
1040 cprintf ("%d>&%d", redirector, redir_fd);
1041 break;
1042
1043 case r_duplicating_input_word:
1044 cprintf ("%d<&%s", redirector, redirectee->word);
1045 break;
1046
1047 case r_duplicating_output_word:
1048 cprintf ("%d>&%s", redirector, redirectee->word);
1049 break;
1050
Jari Aalto7117c2d2002-07-17 14:10:11 +00001051 case r_move_input:
1052 cprintf ("%d<&%d-", redirector, redir_fd);
1053 break;
1054
1055 case r_move_output:
1056 cprintf ("%d>&%d-", redirector, redir_fd);
1057 break;
1058
1059 case r_move_input_word:
1060 cprintf ("%d<&%s-", redirector, redirectee->word);
1061 break;
1062
1063 case r_move_output_word:
1064 cprintf ("%d>&%s-", redirector, redirectee->word);
1065 break;
1066
Jari Aalto726f6381996-08-26 18:22:31 +00001067 case r_close_this:
1068 cprintf ("%d>&-", redirector);
1069 break;
1070
1071 case r_err_and_out:
Jari Aalto31859422009-01-12 13:36:28 +00001072 cprintf ("&>%s", redirectee->word);
1073 break;
1074
1075 case r_append_err_and_out:
1076 cprintf ("&>>%s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001077 break;
1078
1079 case r_input_output:
1080 if (redirector != 1)
1081 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001082 cprintf ("<> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001083 break;
1084
1085 case r_output_force:
1086 if (redirector != 1)
1087 cprintf ("%d", redirector);
1088 cprintf (">|%s", redirectee->word);
1089 break;
1090 }
1091}
1092
1093static void
1094reset_locals ()
1095{
1096 inside_function_def = 0;
1097 indentation = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001098 printing_connection = 0;
1099 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001100}
1101
1102static void
1103print_function_def (func)
1104 FUNCTION_DEF *func;
1105{
Jari Aaltobb706242000-03-17 21:46:59 +00001106 COMMAND *cmdcopy;
1107 REDIRECT *func_redirects;
1108
Jari Aaltof73dda02001-11-13 17:56:06 +00001109 func_redirects = NULL;
Jari Aalto726f6381996-08-26 18:22:31 +00001110 cprintf ("function %s () \n", func->name->word);
1111 add_unwind_protect (reset_locals, 0);
1112
1113 indent (indentation);
1114 cprintf ("{ \n");
1115
1116 inside_function_def++;
1117 indentation += indentation_amount;
1118
Jari Aaltobb706242000-03-17 21:46:59 +00001119 cmdcopy = copy_command (func->command);
1120 if (cmdcopy->type == cm_group)
1121 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001122 func_redirects = cmdcopy->redirects;
1123 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001124 }
1125 make_command_string_internal (cmdcopy->type == cm_group
1126 ? cmdcopy->value.Group->command
1127 : cmdcopy);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001128
Jari Aalto726f6381996-08-26 18:22:31 +00001129 remove_unwind_protect ();
1130 indentation -= indentation_amount;
1131 inside_function_def--;
1132
Jari Aaltobb706242000-03-17 21:46:59 +00001133 if (func_redirects)
1134 { /* { */
1135 newline ("} ");
1136 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001137 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001138 }
1139 else
1140 newline ("}");
1141
1142 dispose_command (cmdcopy);
Jari Aalto726f6381996-08-26 18:22:31 +00001143}
1144
1145/* Return the string representation of the named function.
1146 NAME is the name of the function.
1147 COMMAND is the function body. It should be a GROUP_COM.
Jari Aalto31859422009-01-12 13:36:28 +00001148 flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1149 flags&FUNC_EXTERNAL means convert from internal to external form
Jari Aalto726f6381996-08-26 18:22:31 +00001150 */
1151char *
Jari Aalto31859422009-01-12 13:36:28 +00001152named_function_string (name, command, flags)
Jari Aalto726f6381996-08-26 18:22:31 +00001153 char *name;
1154 COMMAND *command;
Jari Aalto31859422009-01-12 13:36:28 +00001155 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +00001156{
1157 char *result;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001158 int old_indent, old_amount;
Jari Aaltobb706242000-03-17 21:46:59 +00001159 COMMAND *cmdcopy;
1160 REDIRECT *func_redirects;
Jari Aalto726f6381996-08-26 18:22:31 +00001161
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001162 old_indent = indentation;
1163 old_amount = indentation_amount;
Jari Aaltod166f041997-06-05 14:59:13 +00001164 command_string_index = was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001165 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001166
1167 if (name && *name)
1168 cprintf ("%s ", name);
1169
1170 cprintf ("() ");
1171
Jari Aalto31859422009-01-12 13:36:28 +00001172 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001173 {
1174 indentation = 1;
1175 indentation_amount = 0;
1176 }
1177 else
1178 {
1179 cprintf ("\n");
1180 indentation += indentation_amount;
1181 }
1182
1183 inside_function_def++;
1184
Jari Aalto31859422009-01-12 13:36:28 +00001185 cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
Jari Aalto726f6381996-08-26 18:22:31 +00001186
Jari Aaltobb706242000-03-17 21:46:59 +00001187 cmdcopy = copy_command (command);
1188 /* Take any redirections specified in the function definition (which should
1189 apply to the function as a whole) and save them for printing later. */
1190 func_redirects = (REDIRECT *)NULL;
1191 if (cmdcopy->type == cm_group)
1192 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001193 func_redirects = cmdcopy->redirects;
1194 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001195 }
1196 make_command_string_internal (cmdcopy->type == cm_group
1197 ? cmdcopy->value.Group->command
1198 : cmdcopy);
Jari Aalto726f6381996-08-26 18:22:31 +00001199
1200 indentation = old_indent;
1201 indentation_amount = old_amount;
1202 inside_function_def--;
1203
Jari Aaltobb706242000-03-17 21:46:59 +00001204 if (func_redirects)
1205 { /* { */
1206 newline ("} ");
1207 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001208 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001209 }
1210 else
1211 newline ("}");
Jari Aalto726f6381996-08-26 18:22:31 +00001212
1213 result = the_printed_command;
1214
Jari Aalto31859422009-01-12 13:36:28 +00001215 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001216 {
1217#if 0
1218 register int i;
1219 for (i = 0; result[i]; i++)
1220 if (result[i] == '\n')
1221 {
1222 strcpy (result + i, result + i + 1);
1223 --i;
1224 }
1225#else
1226 if (result[2] == '\n') /* XXX -- experimental */
Jari Aalto28ef6c32001-04-06 19:14:31 +00001227 strcpy (result + 2, result + 3);
Jari Aalto726f6381996-08-26 18:22:31 +00001228#endif
1229 }
1230
Jari Aaltobb706242000-03-17 21:46:59 +00001231 dispose_command (cmdcopy);
1232
Jari Aalto31859422009-01-12 13:36:28 +00001233 if (flags & FUNC_EXTERNAL)
1234 result = remove_quoted_escapes (result);
1235
Jari Aalto726f6381996-08-26 18:22:31 +00001236 return (result);
1237}
1238
1239static void
1240newline (string)
1241 char *string;
1242{
1243 cprintf ("\n");
1244 indent (indentation);
1245 if (string && *string)
1246 cprintf ("%s", string);
1247}
1248
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001249static char *indentation_string;
1250static int indentation_size;
1251
Jari Aalto726f6381996-08-26 18:22:31 +00001252static void
1253indent (amount)
1254 int amount;
1255{
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001256 register int i;
1257
1258 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1259
1260 for (i = 0; amount > 0; amount--)
1261 indentation_string[i++] = ' ';
1262 indentation_string[i] = '\0';
1263 cprintf (indentation_string);
Jari Aalto726f6381996-08-26 18:22:31 +00001264}
1265
1266static void
1267semicolon ()
1268{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001269 if (command_string_index > 0 &&
1270 (the_printed_command[command_string_index - 1] == '&' ||
1271 the_printed_command[command_string_index - 1] == '\n'))
Jari Aalto726f6381996-08-26 18:22:31 +00001272 return;
1273 cprintf (";");
1274}
1275
Jari Aalto726f6381996-08-26 18:22:31 +00001276/* How to make the string. */
1277static void
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001278#if defined (PREFER_STDARG)
Jari Aaltof73dda02001-11-13 17:56:06 +00001279cprintf (const char *control, ...)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001280#else
1281cprintf (control, va_alist)
Jari Aaltof73dda02001-11-13 17:56:06 +00001282 const char *control;
Jari Aalto726f6381996-08-26 18:22:31 +00001283 va_dcl
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001284#endif
Jari Aalto726f6381996-08-26 18:22:31 +00001285{
Jari Aaltof73dda02001-11-13 17:56:06 +00001286 register const char *s;
1287 char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
Jari Aalto726f6381996-08-26 18:22:31 +00001288 int digit_arg, arg_len, c;
1289 va_list args;
1290
Jari Aalto7117c2d2002-07-17 14:10:11 +00001291 SH_VA_START (args, control);
Jari Aalto726f6381996-08-26 18:22:31 +00001292
1293 arg_len = strlen (control);
1294 the_printed_command_resize (arg_len + 1);
1295
1296 char_arg[1] = '\0';
1297 s = control;
1298 while (s && *s)
1299 {
Jari Aalto726f6381996-08-26 18:22:31 +00001300 c = *s++;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001301 argp = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +00001302 if (c != '%' || !*s)
1303 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001304 char_arg[0] = c;
1305 argp = char_arg;
Jari Aalto726f6381996-08-26 18:22:31 +00001306 arg_len = 1;
1307 }
1308 else
1309 {
1310 c = *s++;
1311 switch (c)
1312 {
1313 case '%':
1314 char_arg[0] = c;
1315 argp = char_arg;
1316 arg_len = 1;
1317 break;
1318
1319 case 's':
1320 argp = va_arg (args, char *);
1321 arg_len = strlen (argp);
1322 break;
1323
1324 case 'd':
Jari Aaltof73dda02001-11-13 17:56:06 +00001325 /* Represent an out-of-range file descriptor with an out-of-range
1326 integer value. We can do this because the only use of `%d' in
1327 the calls to cprintf is to output a file descriptor number for
1328 a redirection. */
Jari Aalto726f6381996-08-26 18:22:31 +00001329 digit_arg = va_arg (args, int);
Jari Aaltof73dda02001-11-13 17:56:06 +00001330 if (digit_arg < 0)
1331 {
1332 sprintf (intbuf, "%u", (unsigned)-1);
1333 argp = intbuf;
1334 }
1335 else
1336 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
Jari Aalto726f6381996-08-26 18:22:31 +00001337 arg_len = strlen (argp);
Jari Aalto726f6381996-08-26 18:22:31 +00001338 break;
1339
1340 case 'c':
1341 char_arg[0] = va_arg (args, int);
1342 argp = char_arg;
1343 arg_len = 1;
1344 break;
1345
1346 default:
Jari Aaltob80f6442004-07-27 13:29:18 +00001347 programming_error (_("cprintf: `%c': invalid format character"), c);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001348 /*NOTREACHED*/
Jari Aalto726f6381996-08-26 18:22:31 +00001349 }
1350 }
1351
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001352 if (argp && arg_len)
Jari Aalto726f6381996-08-26 18:22:31 +00001353 {
1354 the_printed_command_resize (arg_len + 1);
1355 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1356 command_string_index += arg_len;
Jari Aalto726f6381996-08-26 18:22:31 +00001357 }
1358 }
1359
1360 the_printed_command[command_string_index] = '\0';
1361}
Jari Aalto726f6381996-08-26 18:22:31 +00001362
1363/* Ensure that there is enough space to stuff LENGTH characters into
1364 THE_PRINTED_COMMAND. */
1365static void
1366the_printed_command_resize (length)
1367 int length;
1368{
Jari Aaltod166f041997-06-05 14:59:13 +00001369 if (the_printed_command == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001370 {
Jari Aaltod166f041997-06-05 14:59:13 +00001371 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
Jari Aaltof73dda02001-11-13 17:56:06 +00001372 the_printed_command = (char *)xmalloc (the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001373 command_string_index = 0;
1374 }
1375 else if ((command_string_index + length) >= the_printed_command_size)
1376 {
1377 int new;
1378 new = command_string_index + length + 1;
Jari Aaltobb706242000-03-17 21:46:59 +00001379
Jari Aaltod166f041997-06-05 14:59:13 +00001380 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1381 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
Jari Aalto726f6381996-08-26 18:22:31 +00001382 the_printed_command_size = new;
Jari Aaltobb706242000-03-17 21:46:59 +00001383
Jari Aaltof73dda02001-11-13 17:56:06 +00001384 the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001385 }
1386}
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001387
Jari Aaltof73dda02001-11-13 17:56:06 +00001388#if defined (HAVE_VPRINTF)
1389/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1390 also available.'' */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001391
1392static void
Jari Aaltod166f041997-06-05 14:59:13 +00001393#if defined (PREFER_STDARG)
1394xprintf (const char *format, ...)
1395#else
1396xprintf (format, va_alist)
1397 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001398 va_dcl
Jari Aaltod166f041997-06-05 14:59:13 +00001399#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001400{
1401 va_list args;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001402
Jari Aalto7117c2d2002-07-17 14:10:11 +00001403 SH_VA_START (args, format);
Jari Aaltod166f041997-06-05 14:59:13 +00001404
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001405 vfprintf (stdout, format, args);
1406 va_end (args);
1407}
1408
1409#else
1410
1411static void
1412xprintf (format, arg1, arg2, arg3, arg4, arg5)
Jari Aaltof73dda02001-11-13 17:56:06 +00001413 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001414{
1415 printf (format, arg1, arg2, arg3, arg4, arg5);
1416}
1417
Jari Aaltof73dda02001-11-13 17:56:06 +00001418#endif /* !HAVE_VPRINTF */