blob: 285d8fffc8c39d5626ec950529c49a90d6032029 [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 Aalto17345e52009-02-19 22:21:29 +0000153 char s[3], *op;
Jari Aalto31859422009-01-12 13:36:28 +0000154
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 (deferred_heredocs == 0)
Jari Aalto17345e52009-02-19 22:21:29 +0000265 {
266 if (was_heredoc == 0)
267 cprintf (";");
268 else
269 was_heredoc = 0;
270 }
Jari Aalto31859422009-01-12 13:36:28 +0000271 else
Jari Aalto17345e52009-02-19 22:21:29 +0000272 print_deferred_heredocs (inside_function_def ? "" : ";");
Jari Aalto726f6381996-08-26 18:22:31 +0000273
274 if (inside_function_def)
275 cprintf ("\n");
276 else
277 {
278 cprintf (" ");
279 if (command->value.Connection->second)
280 skip_this_indent++;
281 }
282 break;
283
284 default:
Jari Aaltob80f6442004-07-27 13:29:18 +0000285 cprintf (_("print_command: bad connector `%d'"),
Jari Aalto726f6381996-08-26 18:22:31 +0000286 command->value.Connection->connector);
287 break;
288 }
289
290 make_command_string_internal (command->value.Connection->second);
Jari Aalto17345e52009-02-19 22:21:29 +0000291 if (deferred_heredocs)
292 print_deferred_heredocs ("");
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 {
Jari Aalto17345e52009-02-19 22:21:29 +0000887 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
Jari Aalto31859422009-01-12 13:36:28 +0000888 cprintf (" "); /* make sure there's at least one space */
889 dispose_redirects (deferred_heredocs);
Jari Aalto17345e52009-02-19 22:21:29 +0000890 was_heredoc = 1;
Jari Aalto31859422009-01-12 13:36:28 +0000891 }
892 deferred_heredocs = (REDIRECT *)NULL;
893}
894
895static void
Jari Aalto726f6381996-08-26 18:22:31 +0000896print_redirection_list (redirects)
897 REDIRECT *redirects;
898{
Jari Aaltod166f041997-06-05 14:59:13 +0000899 REDIRECT *heredocs, *hdtail, *newredir;
900
901 heredocs = (REDIRECT *)NULL;
902 hdtail = heredocs;
903
904 was_heredoc = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000905 while (redirects)
906 {
Jari Aaltod166f041997-06-05 14:59:13 +0000907 /* Defer printing the here documents until we've printed the
908 rest of the redirections. */
909 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
910 {
911 newredir = copy_redirect (redirects);
912 newredir->next = (REDIRECT *)NULL;
913 if (heredocs)
914 {
915 hdtail->next = newredir;
916 hdtail = newredir;
917 }
918 else
919 hdtail = heredocs = newredir;
920 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000921 else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
922 {
923 /* Temporarily translate it as the execution code does. */
924 redirects->instruction = r_err_and_out;
925 print_redirection (redirects);
926 redirects->instruction = r_duplicating_output_word;
927 }
Jari Aaltod166f041997-06-05 14:59:13 +0000928 else
929 print_redirection (redirects);
930
Jari Aalto726f6381996-08-26 18:22:31 +0000931 redirects = redirects->next;
932 if (redirects)
933 cprintf (" ");
934 }
Jari Aaltod166f041997-06-05 14:59:13 +0000935
936 /* Now that we've printed all the other redirections (on one line),
937 print the here documents. */
Jari Aalto31859422009-01-12 13:36:28 +0000938 if (heredocs && printing_connection)
939 deferred_heredocs = heredocs;
940 else if (heredocs)
Jari Aaltod166f041997-06-05 14:59:13 +0000941 {
Jari Aalto31859422009-01-12 13:36:28 +0000942 print_heredocs (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +0000943 dispose_redirects (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +0000944 }
Jari Aalto726f6381996-08-26 18:22:31 +0000945}
946
947static void
Jari Aalto31859422009-01-12 13:36:28 +0000948print_heredoc_header (redirect)
949 REDIRECT *redirect;
950{
951 int kill_leading;
952 char *x;
953
954 kill_leading = redirect->instruction == r_deblank_reading_until;
955
956 /* Here doc header */
957 if (redirect->redirector != 0)
958 cprintf ("%d", redirect->redirector);
959
960 /* If the here document delimiter is quoted, single-quote it. */
961 if (redirect->redirectee.filename->flags & W_QUOTED)
962 {
963 x = sh_single_quote (redirect->here_doc_eof);
964 cprintf ("<<%s%s", kill_leading ? "-" : "", x);
965 free (x);
966 }
967 else
968 cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
969}
970
971static void
972print_heredoc_body (redirect)
973 REDIRECT *redirect;
974{
975 /* Here doc body */
976 cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
977}
978
979static void
Jari Aalto726f6381996-08-26 18:22:31 +0000980print_redirection (redirect)
981 REDIRECT *redirect;
982{
Jari Aaltod166f041997-06-05 14:59:13 +0000983 int kill_leading, redirector, redir_fd;
984 WORD_DESC *redirectee;
985
986 kill_leading = 0;
987 redirectee = redirect->redirectee.filename;
988 redirector = redirect->redirector;
989 redir_fd = redirect->redirectee.dest;
Jari Aalto726f6381996-08-26 18:22:31 +0000990
991 switch (redirect->instruction)
992 {
993 case r_output_direction:
994 if (redirector != 1)
995 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +0000996 cprintf ("> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +0000997 break;
998
999 case r_input_direction:
1000 if (redirector != 0)
1001 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001002 cprintf ("< %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001003 break;
1004
1005 case r_inputa_direction: /* Redirection created by the shell. */
1006 cprintf ("&");
1007 break;
1008
1009 case r_appending_to:
1010 if (redirector != 1)
1011 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001012 cprintf (">> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001013 break;
1014
1015 case r_deblank_reading_until:
Jari Aalto726f6381996-08-26 18:22:31 +00001016 case r_reading_until:
Jari Aalto31859422009-01-12 13:36:28 +00001017 print_heredoc_header (redirect);
1018 cprintf ("\n");
1019 print_heredoc_body (redirect);
Jari Aalto726f6381996-08-26 18:22:31 +00001020 break;
1021
Jari Aalto7117c2d2002-07-17 14:10:11 +00001022 case r_reading_string:
1023 if (redirector != 0)
1024 cprintf ("%d", redirector);
1025 if (ansic_shouldquote (redirect->redirectee.filename->word))
1026 {
1027 char *x;
1028 x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1029 cprintf ("<<< %s", x);
1030 free (x);
1031 }
1032 else
1033 cprintf ("<<< %s", redirect->redirectee.filename->word);
1034 break;
1035
Jari Aalto726f6381996-08-26 18:22:31 +00001036 case r_duplicating_input:
1037 cprintf ("%d<&%d", redirector, redir_fd);
1038 break;
1039
1040 case r_duplicating_output:
1041 cprintf ("%d>&%d", redirector, redir_fd);
1042 break;
1043
1044 case r_duplicating_input_word:
1045 cprintf ("%d<&%s", redirector, redirectee->word);
1046 break;
1047
1048 case r_duplicating_output_word:
1049 cprintf ("%d>&%s", redirector, redirectee->word);
1050 break;
1051
Jari Aalto7117c2d2002-07-17 14:10:11 +00001052 case r_move_input:
1053 cprintf ("%d<&%d-", redirector, redir_fd);
1054 break;
1055
1056 case r_move_output:
1057 cprintf ("%d>&%d-", redirector, redir_fd);
1058 break;
1059
1060 case r_move_input_word:
1061 cprintf ("%d<&%s-", redirector, redirectee->word);
1062 break;
1063
1064 case r_move_output_word:
1065 cprintf ("%d>&%s-", redirector, redirectee->word);
1066 break;
1067
Jari Aalto726f6381996-08-26 18:22:31 +00001068 case r_close_this:
1069 cprintf ("%d>&-", redirector);
1070 break;
1071
1072 case r_err_and_out:
Jari Aalto31859422009-01-12 13:36:28 +00001073 cprintf ("&>%s", redirectee->word);
1074 break;
1075
1076 case r_append_err_and_out:
1077 cprintf ("&>>%s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001078 break;
1079
1080 case r_input_output:
1081 if (redirector != 1)
1082 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001083 cprintf ("<> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001084 break;
1085
1086 case r_output_force:
1087 if (redirector != 1)
1088 cprintf ("%d", redirector);
1089 cprintf (">|%s", redirectee->word);
1090 break;
1091 }
1092}
1093
1094static void
1095reset_locals ()
1096{
1097 inside_function_def = 0;
1098 indentation = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001099 printing_connection = 0;
1100 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001101}
1102
1103static void
1104print_function_def (func)
1105 FUNCTION_DEF *func;
1106{
Jari Aaltobb706242000-03-17 21:46:59 +00001107 COMMAND *cmdcopy;
1108 REDIRECT *func_redirects;
1109
Jari Aaltof73dda02001-11-13 17:56:06 +00001110 func_redirects = NULL;
Jari Aalto726f6381996-08-26 18:22:31 +00001111 cprintf ("function %s () \n", func->name->word);
1112 add_unwind_protect (reset_locals, 0);
1113
1114 indent (indentation);
1115 cprintf ("{ \n");
1116
1117 inside_function_def++;
1118 indentation += indentation_amount;
1119
Jari Aaltobb706242000-03-17 21:46:59 +00001120 cmdcopy = copy_command (func->command);
1121 if (cmdcopy->type == cm_group)
1122 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001123 func_redirects = cmdcopy->redirects;
1124 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001125 }
1126 make_command_string_internal (cmdcopy->type == cm_group
1127 ? cmdcopy->value.Group->command
1128 : cmdcopy);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001129
Jari Aalto726f6381996-08-26 18:22:31 +00001130 remove_unwind_protect ();
1131 indentation -= indentation_amount;
1132 inside_function_def--;
1133
Jari Aaltobb706242000-03-17 21:46:59 +00001134 if (func_redirects)
1135 { /* { */
1136 newline ("} ");
1137 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001138 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001139 }
1140 else
1141 newline ("}");
1142
1143 dispose_command (cmdcopy);
Jari Aalto726f6381996-08-26 18:22:31 +00001144}
1145
1146/* Return the string representation of the named function.
1147 NAME is the name of the function.
1148 COMMAND is the function body. It should be a GROUP_COM.
Jari Aalto31859422009-01-12 13:36:28 +00001149 flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1150 flags&FUNC_EXTERNAL means convert from internal to external form
Jari Aalto726f6381996-08-26 18:22:31 +00001151 */
1152char *
Jari Aalto31859422009-01-12 13:36:28 +00001153named_function_string (name, command, flags)
Jari Aalto726f6381996-08-26 18:22:31 +00001154 char *name;
1155 COMMAND *command;
Jari Aalto31859422009-01-12 13:36:28 +00001156 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +00001157{
1158 char *result;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001159 int old_indent, old_amount;
Jari Aaltobb706242000-03-17 21:46:59 +00001160 COMMAND *cmdcopy;
1161 REDIRECT *func_redirects;
Jari Aalto726f6381996-08-26 18:22:31 +00001162
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001163 old_indent = indentation;
1164 old_amount = indentation_amount;
Jari Aaltod166f041997-06-05 14:59:13 +00001165 command_string_index = was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001166 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001167
1168 if (name && *name)
1169 cprintf ("%s ", name);
1170
1171 cprintf ("() ");
1172
Jari Aalto31859422009-01-12 13:36:28 +00001173 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001174 {
1175 indentation = 1;
1176 indentation_amount = 0;
1177 }
1178 else
1179 {
1180 cprintf ("\n");
1181 indentation += indentation_amount;
1182 }
1183
1184 inside_function_def++;
1185
Jari Aalto31859422009-01-12 13:36:28 +00001186 cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
Jari Aalto726f6381996-08-26 18:22:31 +00001187
Jari Aaltobb706242000-03-17 21:46:59 +00001188 cmdcopy = copy_command (command);
1189 /* Take any redirections specified in the function definition (which should
1190 apply to the function as a whole) and save them for printing later. */
1191 func_redirects = (REDIRECT *)NULL;
1192 if (cmdcopy->type == cm_group)
1193 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001194 func_redirects = cmdcopy->redirects;
1195 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001196 }
1197 make_command_string_internal (cmdcopy->type == cm_group
1198 ? cmdcopy->value.Group->command
1199 : cmdcopy);
Jari Aalto726f6381996-08-26 18:22:31 +00001200
1201 indentation = old_indent;
1202 indentation_amount = old_amount;
1203 inside_function_def--;
1204
Jari Aaltobb706242000-03-17 21:46:59 +00001205 if (func_redirects)
1206 { /* { */
1207 newline ("} ");
1208 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001209 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001210 }
1211 else
1212 newline ("}");
Jari Aalto726f6381996-08-26 18:22:31 +00001213
1214 result = the_printed_command;
1215
Jari Aalto31859422009-01-12 13:36:28 +00001216 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001217 {
1218#if 0
1219 register int i;
1220 for (i = 0; result[i]; i++)
1221 if (result[i] == '\n')
1222 {
1223 strcpy (result + i, result + i + 1);
1224 --i;
1225 }
1226#else
1227 if (result[2] == '\n') /* XXX -- experimental */
Jari Aalto28ef6c32001-04-06 19:14:31 +00001228 strcpy (result + 2, result + 3);
Jari Aalto726f6381996-08-26 18:22:31 +00001229#endif
1230 }
1231
Jari Aaltobb706242000-03-17 21:46:59 +00001232 dispose_command (cmdcopy);
1233
Jari Aalto31859422009-01-12 13:36:28 +00001234 if (flags & FUNC_EXTERNAL)
1235 result = remove_quoted_escapes (result);
1236
Jari Aalto726f6381996-08-26 18:22:31 +00001237 return (result);
1238}
1239
1240static void
1241newline (string)
1242 char *string;
1243{
1244 cprintf ("\n");
1245 indent (indentation);
1246 if (string && *string)
1247 cprintf ("%s", string);
1248}
1249
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001250static char *indentation_string;
1251static int indentation_size;
1252
Jari Aalto726f6381996-08-26 18:22:31 +00001253static void
1254indent (amount)
1255 int amount;
1256{
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001257 register int i;
1258
1259 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1260
1261 for (i = 0; amount > 0; amount--)
1262 indentation_string[i++] = ' ';
1263 indentation_string[i] = '\0';
1264 cprintf (indentation_string);
Jari Aalto726f6381996-08-26 18:22:31 +00001265}
1266
1267static void
1268semicolon ()
1269{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001270 if (command_string_index > 0 &&
1271 (the_printed_command[command_string_index - 1] == '&' ||
1272 the_printed_command[command_string_index - 1] == '\n'))
Jari Aalto726f6381996-08-26 18:22:31 +00001273 return;
1274 cprintf (";");
1275}
1276
Jari Aalto726f6381996-08-26 18:22:31 +00001277/* How to make the string. */
1278static void
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001279#if defined (PREFER_STDARG)
Jari Aaltof73dda02001-11-13 17:56:06 +00001280cprintf (const char *control, ...)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001281#else
1282cprintf (control, va_alist)
Jari Aaltof73dda02001-11-13 17:56:06 +00001283 const char *control;
Jari Aalto726f6381996-08-26 18:22:31 +00001284 va_dcl
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001285#endif
Jari Aalto726f6381996-08-26 18:22:31 +00001286{
Jari Aaltof73dda02001-11-13 17:56:06 +00001287 register const char *s;
1288 char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
Jari Aalto726f6381996-08-26 18:22:31 +00001289 int digit_arg, arg_len, c;
1290 va_list args;
1291
Jari Aalto7117c2d2002-07-17 14:10:11 +00001292 SH_VA_START (args, control);
Jari Aalto726f6381996-08-26 18:22:31 +00001293
1294 arg_len = strlen (control);
1295 the_printed_command_resize (arg_len + 1);
1296
1297 char_arg[1] = '\0';
1298 s = control;
1299 while (s && *s)
1300 {
Jari Aalto726f6381996-08-26 18:22:31 +00001301 c = *s++;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001302 argp = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +00001303 if (c != '%' || !*s)
1304 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001305 char_arg[0] = c;
1306 argp = char_arg;
Jari Aalto726f6381996-08-26 18:22:31 +00001307 arg_len = 1;
1308 }
1309 else
1310 {
1311 c = *s++;
1312 switch (c)
1313 {
1314 case '%':
1315 char_arg[0] = c;
1316 argp = char_arg;
1317 arg_len = 1;
1318 break;
1319
1320 case 's':
1321 argp = va_arg (args, char *);
1322 arg_len = strlen (argp);
1323 break;
1324
1325 case 'd':
Jari Aaltof73dda02001-11-13 17:56:06 +00001326 /* Represent an out-of-range file descriptor with an out-of-range
1327 integer value. We can do this because the only use of `%d' in
1328 the calls to cprintf is to output a file descriptor number for
1329 a redirection. */
Jari Aalto726f6381996-08-26 18:22:31 +00001330 digit_arg = va_arg (args, int);
Jari Aaltof73dda02001-11-13 17:56:06 +00001331 if (digit_arg < 0)
1332 {
1333 sprintf (intbuf, "%u", (unsigned)-1);
1334 argp = intbuf;
1335 }
1336 else
1337 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
Jari Aalto726f6381996-08-26 18:22:31 +00001338 arg_len = strlen (argp);
Jari Aalto726f6381996-08-26 18:22:31 +00001339 break;
1340
1341 case 'c':
1342 char_arg[0] = va_arg (args, int);
1343 argp = char_arg;
1344 arg_len = 1;
1345 break;
1346
1347 default:
Jari Aaltob80f6442004-07-27 13:29:18 +00001348 programming_error (_("cprintf: `%c': invalid format character"), c);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001349 /*NOTREACHED*/
Jari Aalto726f6381996-08-26 18:22:31 +00001350 }
1351 }
1352
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001353 if (argp && arg_len)
Jari Aalto726f6381996-08-26 18:22:31 +00001354 {
1355 the_printed_command_resize (arg_len + 1);
1356 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1357 command_string_index += arg_len;
Jari Aalto726f6381996-08-26 18:22:31 +00001358 }
1359 }
1360
1361 the_printed_command[command_string_index] = '\0';
1362}
Jari Aalto726f6381996-08-26 18:22:31 +00001363
1364/* Ensure that there is enough space to stuff LENGTH characters into
1365 THE_PRINTED_COMMAND. */
1366static void
1367the_printed_command_resize (length)
1368 int length;
1369{
Jari Aaltod166f041997-06-05 14:59:13 +00001370 if (the_printed_command == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001371 {
Jari Aaltod166f041997-06-05 14:59:13 +00001372 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
Jari Aaltof73dda02001-11-13 17:56:06 +00001373 the_printed_command = (char *)xmalloc (the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001374 command_string_index = 0;
1375 }
1376 else if ((command_string_index + length) >= the_printed_command_size)
1377 {
1378 int new;
1379 new = command_string_index + length + 1;
Jari Aaltobb706242000-03-17 21:46:59 +00001380
Jari Aaltod166f041997-06-05 14:59:13 +00001381 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1382 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
Jari Aalto726f6381996-08-26 18:22:31 +00001383 the_printed_command_size = new;
Jari Aaltobb706242000-03-17 21:46:59 +00001384
Jari Aaltof73dda02001-11-13 17:56:06 +00001385 the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001386 }
1387}
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001388
Jari Aaltof73dda02001-11-13 17:56:06 +00001389#if defined (HAVE_VPRINTF)
1390/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1391 also available.'' */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001392
1393static void
Jari Aaltod166f041997-06-05 14:59:13 +00001394#if defined (PREFER_STDARG)
1395xprintf (const char *format, ...)
1396#else
1397xprintf (format, va_alist)
1398 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001399 va_dcl
Jari Aaltod166f041997-06-05 14:59:13 +00001400#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001401{
1402 va_list args;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001403
Jari Aalto7117c2d2002-07-17 14:10:11 +00001404 SH_VA_START (args, format);
Jari Aaltod166f041997-06-05 14:59:13 +00001405
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001406 vfprintf (stdout, format, args);
1407 va_end (args);
1408}
1409
1410#else
1411
1412static void
1413xprintf (format, arg1, arg2, arg3, arg4, arg5)
Jari Aaltof73dda02001-11-13 17:56:06 +00001414 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001415{
1416 printf (format, arg1, arg2, arg3, arg4, arg5);
1417}
1418
Jari Aaltof73dda02001-11-13 17:56:06 +00001419#endif /* !HAVE_VPRINTF */