blob: 3c8c2d8fff892d82664caee0bb840d8affd5cbd4 [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
Chet Ramey8868eda2020-12-06 15:51:17 -05003/* Copyright (C) 1989-2020 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
Chet Rameyd233b482019-01-07 09:27:52 -050041#define NEED_XTRACE_SET_DECL
42
Jari Aalto726f6381996-08-26 18:22:31 +000043#include "shell.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000044#include "flags.h"
Jari Aaltod166f041997-06-05 14:59:13 +000045#include <y.tab.h> /* use <...> so we pick it up from the build directory */
Chet Rameya0c0a002016-09-15 16:59:08 -040046#include "input.h"
Jari Aalto95732b42005-12-07 14:08:12 +000047
48#include "shmbutil.h"
49
Jari Aalto726f6381996-08-26 18:22:31 +000050#include "builtins/common.h"
51
Jari Aaltof73dda02001-11-13 17:56:06 +000052#if !HAVE_DECL_PRINTF
Chet Ramey8868eda2020-12-06 15:51:17 -050053extern int printf PARAMS((const char *, ...)); /* Yuck. Double yuck. */
Jari Aalto726f6381996-08-26 18:22:31 +000054#endif
55
Jari Aaltoccc6cda1996-12-23 17:02:34 +000056static int indentation;
Jari Aalto726f6381996-08-26 18:22:31 +000057static int indentation_amount = 4;
58
Jari Aaltod166f041997-06-05 14:59:13 +000059#if defined (PREFER_STDARG)
Chet Ramey8868eda2020-12-06 15:51:17 -050060typedef void PFUNC PARAMS((const char *, ...));
Jari Aaltof73dda02001-11-13 17:56:06 +000061
Chet Ramey8868eda2020-12-06 15:51:17 -050062static void cprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
63static void xprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
Jari Aaltod166f041997-06-05 14:59:13 +000064#else
Jari Aaltof73dda02001-11-13 17:56:06 +000065#define PFUNC VFunction
Jari Aaltod166f041997-06-05 14:59:13 +000066static void cprintf ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +000067static void xprintf ();
Jari Aalto726f6381996-08-26 18:22:31 +000068#endif
Jari Aaltof73dda02001-11-13 17:56:06 +000069
Chet Ramey8868eda2020-12-06 15:51:17 -050070static void reset_locals PARAMS((void));
71static void newline PARAMS((char *));
72static void indent PARAMS((int));
73static void semicolon PARAMS((void));
74static void the_printed_command_resize PARAMS((int));
Jari Aaltof73dda02001-11-13 17:56:06 +000075
Chet Ramey8868eda2020-12-06 15:51:17 -050076static void make_command_string_internal PARAMS((COMMAND *));
77static void _print_word_list PARAMS((WORD_LIST *, char *, PFUNC *));
78static void command_print_word_list PARAMS((WORD_LIST *, char *));
79static void print_case_clauses PARAMS((PATTERN_LIST *));
80static void print_redirection_list PARAMS((REDIRECT *));
81static void print_redirection PARAMS((REDIRECT *));
82static void print_heredoc_header PARAMS((REDIRECT *));
83static void print_heredoc_body PARAMS((REDIRECT *));
84static void print_heredocs PARAMS((REDIRECT *));
85static void print_heredoc_bodies PARAMS((REDIRECT *));
86static void print_deferred_heredocs PARAMS((const char *));
Jari Aaltof73dda02001-11-13 17:56:06 +000087
Chet Ramey8868eda2020-12-06 15:51:17 -050088static void print_for_command PARAMS((FOR_COM *));
Jari Aaltof73dda02001-11-13 17:56:06 +000089#if defined (ARITH_FOR_COMMAND)
Chet Ramey8868eda2020-12-06 15:51:17 -050090static void print_arith_for_command PARAMS((ARITH_FOR_COM *));
Jari Aaltof73dda02001-11-13 17:56:06 +000091#endif
92#if defined (SELECT_COMMAND)
Chet Ramey8868eda2020-12-06 15:51:17 -050093static void print_select_command PARAMS((SELECT_COM *));
Jari Aaltof73dda02001-11-13 17:56:06 +000094#endif
Chet Ramey8868eda2020-12-06 15:51:17 -050095static void print_group_command PARAMS((GROUP_COM *));
96static void print_case_command PARAMS((CASE_COM *));
97static void print_while_command PARAMS((WHILE_COM *));
98static void print_until_command PARAMS((WHILE_COM *));
99static void print_until_or_while PARAMS((WHILE_COM *, char *));
100static void print_if_command PARAMS((IF_COM *));
Jari Aaltocce855b1998-04-17 19:52:44 +0000101#if defined (COND_COMMAND)
Chet Ramey8868eda2020-12-06 15:51:17 -0500102static void print_cond_node PARAMS((COND_COM *));
Jari Aaltocce855b1998-04-17 19:52:44 +0000103#endif
Chet Ramey8868eda2020-12-06 15:51:17 -0500104static void print_function_def PARAMS((FUNCTION_DEF *));
Jari Aalto726f6381996-08-26 18:22:31 +0000105
Jari Aaltod166f041997-06-05 14:59:13 +0000106#define PRINTED_COMMAND_INITIAL_SIZE 64
107#define PRINTED_COMMAND_GROW_SIZE 128
Jari Aalto726f6381996-08-26 18:22:31 +0000108
109char *the_printed_command = (char *)NULL;
110int the_printed_command_size = 0;
111int command_string_index = 0;
112
Chet Ramey00018032011-11-21 20:51:19 -0500113int xtrace_fd = -1;
114FILE *xtrace_fp = 0;
115
116#define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
117
Chet Rameyac50fba2014-02-26 09:36:43 -0500118/* shell expansion characters: used in print_redirection_list */
119#define EXPCHAR(c) ((c) == '{' || (c) == '~' || (c) == '$' || (c) == '`')
120
Chet Ramey30d188c2011-11-21 20:57:16 -0500121#define PRINT_DEFERRED_HEREDOCS(x) \
122 do { \
123 if (deferred_heredocs) \
124 print_deferred_heredocs (x); \
125 } while (0)
126
Jari Aalto726f6381996-08-26 18:22:31 +0000127/* Non-zero means the stuff being printed is inside of a function def. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000128static int inside_function_def;
129static int skip_this_indent;
Jari Aaltod166f041997-06-05 14:59:13 +0000130static int was_heredoc;
Jari Aalto31859422009-01-12 13:36:28 +0000131static int printing_connection;
132static REDIRECT *deferred_heredocs;
Jari Aalto726f6381996-08-26 18:22:31 +0000133
134/* The depth of the group commands that we are currently printing. This
135 includes the group command that is a function body. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000136static int group_command_nesting;
Jari Aalto726f6381996-08-26 18:22:31 +0000137
Jari Aalto7117c2d2002-07-17 14:10:11 +0000138/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500139static char *indirection_string = 0;
140static int indirection_stringsiz = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000141
Jari Aalto726f6381996-08-26 18:22:31 +0000142/* Print COMMAND (a command tree) on standard output. */
143void
144print_command (command)
145 COMMAND *command;
146{
147 command_string_index = 0;
148 printf ("%s", make_command_string (command));
149}
150
151/* Make a string which is the printed representation of the command
152 tree in COMMAND. We return this string. However, the string is
153 not consed, so you have to do that yourself if you want it to
154 remain around. */
155char *
156make_command_string (command)
157 COMMAND *command;
158{
Jari Aaltod166f041997-06-05 14:59:13 +0000159 command_string_index = was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000160 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000161 make_command_string_internal (command);
162 return (the_printed_command);
163}
164
165/* The internal function. This is the real workhorse. */
166static void
167make_command_string_internal (command)
168 COMMAND *command;
169{
Chet Ramey495aee42011-11-22 19:11:26 -0500170 char s[3];
Jari Aalto31859422009-01-12 13:36:28 +0000171
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000172 if (command == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000173 cprintf ("");
174 else
175 {
176 if (skip_this_indent)
177 skip_this_indent--;
178 else
179 indent (indentation);
180
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000181 if (command->flags & CMD_TIME_PIPELINE)
Jari Aaltod166f041997-06-05 14:59:13 +0000182 {
183 cprintf ("time ");
184 if (command->flags & CMD_TIME_POSIX)
185 cprintf ("-p ");
186 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000187
Jari Aalto726f6381996-08-26 18:22:31 +0000188 if (command->flags & CMD_INVERT_RETURN)
189 cprintf ("! ");
190
191 switch (command->type)
192 {
193 case cm_for:
194 print_for_command (command->value.For);
195 break;
196
Jari Aaltobb706242000-03-17 21:46:59 +0000197#if defined (ARITH_FOR_COMMAND)
198 case cm_arith_for:
199 print_arith_for_command (command->value.ArithFor);
200 break;
201#endif
202
Jari Aalto726f6381996-08-26 18:22:31 +0000203#if defined (SELECT_COMMAND)
204 case cm_select:
205 print_select_command (command->value.Select);
206 break;
207#endif
208
209 case cm_case:
210 print_case_command (command->value.Case);
211 break;
212
213 case cm_while:
214 print_while_command (command->value.While);
215 break;
216
217 case cm_until:
218 print_until_command (command->value.While);
219 break;
220
221 case cm_if:
222 print_if_command (command->value.If);
223 break;
224
Jari Aaltocce855b1998-04-17 19:52:44 +0000225#if defined (DPAREN_ARITHMETIC)
226 case cm_arith:
Jari Aaltob80f6442004-07-27 13:29:18 +0000227 print_arith_command (command->value.Arith->exp);
Jari Aaltocce855b1998-04-17 19:52:44 +0000228 break;
229#endif
230
231#if defined (COND_COMMAND)
232 case cm_cond:
233 print_cond_command (command->value.Cond);
234 break;
235#endif
236
Jari Aalto726f6381996-08-26 18:22:31 +0000237 case cm_simple:
238 print_simple_command (command->value.Simple);
239 break;
240
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000241 case cm_connection:
Jari Aalto726f6381996-08-26 18:22:31 +0000242
243 skip_this_indent++;
Jari Aalto31859422009-01-12 13:36:28 +0000244 printing_connection++;
Jari Aalto726f6381996-08-26 18:22:31 +0000245 make_command_string_internal (command->value.Connection->first);
246
247 switch (command->value.Connection->connector)
248 {
249 case '&':
250 case '|':
251 {
252 char c = command->value.Connection->connector;
Jari Aalto31859422009-01-12 13:36:28 +0000253
254 s[0] = ' ';
255 s[1] = c;
256 s[2] = '\0';
257
258 print_deferred_heredocs (s);
259
Jari Aalto726f6381996-08-26 18:22:31 +0000260 if (c != '&' || command->value.Connection->second)
261 {
262 cprintf (" ");
263 skip_this_indent++;
264 }
265 }
266 break;
267
268 case AND_AND:
Jari Aalto31859422009-01-12 13:36:28 +0000269 print_deferred_heredocs (" && ");
Jari Aalto726f6381996-08-26 18:22:31 +0000270 if (command->value.Connection->second)
271 skip_this_indent++;
272 break;
273
274 case OR_OR:
Jari Aalto31859422009-01-12 13:36:28 +0000275 print_deferred_heredocs (" || ");
Jari Aalto726f6381996-08-26 18:22:31 +0000276 if (command->value.Connection->second)
277 skip_this_indent++;
278 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000279
Jari Aalto726f6381996-08-26 18:22:31 +0000280 case ';':
Jari Aalto31859422009-01-12 13:36:28 +0000281 if (deferred_heredocs == 0)
Jari Aalto17345e52009-02-19 22:21:29 +0000282 {
283 if (was_heredoc == 0)
284 cprintf (";");
285 else
286 was_heredoc = 0;
287 }
Jari Aalto31859422009-01-12 13:36:28 +0000288 else
Jari Aalto17345e52009-02-19 22:21:29 +0000289 print_deferred_heredocs (inside_function_def ? "" : ";");
Jari Aalto726f6381996-08-26 18:22:31 +0000290
291 if (inside_function_def)
292 cprintf ("\n");
293 else
294 {
295 cprintf (" ");
296 if (command->value.Connection->second)
297 skip_this_indent++;
298 }
299 break;
300
301 default:
Jari Aaltob80f6442004-07-27 13:29:18 +0000302 cprintf (_("print_command: bad connector `%d'"),
Jari Aalto726f6381996-08-26 18:22:31 +0000303 command->value.Connection->connector);
304 break;
305 }
306
307 make_command_string_internal (command->value.Connection->second);
Chet Ramey495aee42011-11-22 19:11:26 -0500308 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto31859422009-01-12 13:36:28 +0000309 printing_connection--;
Jari Aalto726f6381996-08-26 18:22:31 +0000310 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000311
Jari Aalto726f6381996-08-26 18:22:31 +0000312 case cm_function_def:
313 print_function_def (command->value.Function_def);
314 break;
315
316 case cm_group:
317 print_group_command (command->value.Group);
318 break;
319
Jari Aaltobb706242000-03-17 21:46:59 +0000320 case cm_subshell:
321 cprintf ("( ");
322 skip_this_indent++;
323 make_command_string_internal (command->value.Subshell->command);
Chet Ramey680d15e2011-11-22 20:01:00 -0500324 PRINT_DEFERRED_HEREDOCS ("");
Jari Aaltobb706242000-03-17 21:46:59 +0000325 cprintf (" )");
326 break;
327
Jari Aalto31859422009-01-12 13:36:28 +0000328 case cm_coproc:
329 cprintf ("coproc %s ", command->value.Coproc->name);
330 skip_this_indent++;
331 make_command_string_internal (command->value.Coproc->command);
332 break;
333
Jari Aalto726f6381996-08-26 18:22:31 +0000334 default:
Jari Aaltob72432f1999-02-19 17:11:39 +0000335 command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000336 break;
337 }
338
Jari Aalto726f6381996-08-26 18:22:31 +0000339
340 if (command->redirects)
Jari Aaltob72432f1999-02-19 17:11:39 +0000341 {
342 cprintf (" ");
343 print_redirection_list (command->redirects);
344 }
Jari Aalto726f6381996-08-26 18:22:31 +0000345 }
346}
347
348static void
349_print_word_list (list, separator, pfunc)
350 WORD_LIST *list;
351 char *separator;
Jari Aaltof73dda02001-11-13 17:56:06 +0000352 PFUNC *pfunc;
Jari Aalto726f6381996-08-26 18:22:31 +0000353{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000354 WORD_LIST *w;
355
356 for (w = list; w; w = w->next)
357 (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
Jari Aalto726f6381996-08-26 18:22:31 +0000358}
359
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000360void
361print_word_list (list, separator)
Jari Aalto726f6381996-08-26 18:22:31 +0000362 WORD_LIST *list;
363 char *separator;
364{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000365 _print_word_list (list, separator, xprintf);
366}
367
Chet Ramey00018032011-11-21 20:51:19 -0500368void
369xtrace_set (fd, fp)
370 int fd;
371 FILE *fp;
372{
373 if (fd >= 0 && sh_validfd (fd) == 0)
374 {
375 internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
376 return;
377 }
378 if (fp == 0)
379 {
380 internal_error (_("xtrace_set: NULL file pointer"));
381 return;
382 }
383 if (fd >= 0 && fileno (fp) != fd)
384 internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
385
386 xtrace_fd = fd;
387 xtrace_fp = fp;
388}
389
390void
391xtrace_init ()
392{
393 xtrace_set (-1, stderr);
394}
395
396void
397xtrace_reset ()
398{
399 if (xtrace_fd >= 0 && xtrace_fp)
400 {
401 fflush (xtrace_fp);
402 fclose (xtrace_fp);
403 }
404 else if (xtrace_fd >= 0)
405 close (xtrace_fd);
406
407 xtrace_fd = -1;
408 xtrace_fp = stderr;
409}
410
411void
412xtrace_fdchk (fd)
413 int fd;
414{
415 if (fd == xtrace_fd)
416 xtrace_reset ();
417}
418
Jari Aalto7117c2d2002-07-17 14:10:11 +0000419/* Return a string denoting what our indirection level is. */
420
421char *
422indirection_level_string ()
423{
424 register int i, j;
425 char *ps4;
Jari Aalto95732b42005-12-07 14:08:12 +0000426 char ps4_firstc[MB_LEN_MAX+1];
Chet Rameyac50fba2014-02-26 09:36:43 -0500427 int ps4_firstc_len, ps4_len, ineed, old;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000428
Jari Aalto7117c2d2002-07-17 14:10:11 +0000429 ps4 = get_string_value ("PS4");
Chet Rameyac50fba2014-02-26 09:36:43 -0500430 if (indirection_string == 0)
431 indirection_string = xmalloc (indirection_stringsiz = 100);
432 indirection_string[0] = '\0';
Jari Aalto7117c2d2002-07-17 14:10:11 +0000433
434 if (ps4 == 0 || *ps4 == '\0')
435 return (indirection_string);
436
Chet Rameyac50fba2014-02-26 09:36:43 -0500437 old = change_flag ('x', FLAG_OFF);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000438 ps4 = decode_prompt_string (ps4);
Chet Rameyac50fba2014-02-26 09:36:43 -0500439 if (old)
440 change_flag ('x', FLAG_ON);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000441
Jari Aaltob80f6442004-07-27 13:29:18 +0000442 if (ps4 == 0 || *ps4 == '\0')
443 return (indirection_string);
444
Jari Aalto95732b42005-12-07 14:08:12 +0000445#if defined (HANDLE_MULTIBYTE)
446 ps4_len = strnlen (ps4, MB_CUR_MAX);
447 ps4_firstc_len = MBLEN (ps4, ps4_len);
Chet Rameyac50fba2014-02-26 09:36:43 -0500448 if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || ps4_firstc_len < 0)
Jari Aalto95732b42005-12-07 14:08:12 +0000449 {
450 ps4_firstc[0] = ps4[0];
451 ps4_firstc[ps4_firstc_len = 1] = '\0';
452 }
453 else
454 memcpy (ps4_firstc, ps4, ps4_firstc_len);
455#else
456 ps4_firstc[0] = ps4[0];
457 ps4_firstc[ps4_firstc_len = 1] = '\0';
458#endif
Chet Rameyac50fba2014-02-26 09:36:43 -0500459
460 /* Dynamically resize indirection_string so we have room for everything
461 and we don't have to truncate ps4 */
462 ineed = (ps4_firstc_len * indirection_level) + strlen (ps4);
463 if (ineed > indirection_stringsiz - 1)
464 {
465 indirection_stringsiz = ineed + 1;
466 indirection_string = xrealloc (indirection_string, indirection_stringsiz);
467 }
468
469 for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < indirection_stringsiz - 1; i += ps4_firstc_len, j++)
Jari Aalto95732b42005-12-07 14:08:12 +0000470 {
471 if (ps4_firstc_len == 1)
472 indirection_string[i] = ps4_firstc[0];
473 else
474 memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
475 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000476
Chet Rameyac50fba2014-02-26 09:36:43 -0500477 for (j = ps4_firstc_len; *ps4 && ps4[j] && i < indirection_stringsiz - 1; i++, j++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000478 indirection_string[i] = ps4[j];
479
480 indirection_string[i] = '\0';
481 free (ps4);
482 return (indirection_string);
483}
484
Jari Aaltob80f6442004-07-27 13:29:18 +0000485void
486xtrace_print_assignment (name, value, assign_list, xflags)
487 char *name, *value;
488 int assign_list, xflags;
489{
490 char *nval;
491
Chet Ramey00018032011-11-21 20:51:19 -0500492 CHECK_XTRACE_FP;
493
Jari Aaltob80f6442004-07-27 13:29:18 +0000494 if (xflags)
Chet Ramey00018032011-11-21 20:51:19 -0500495 fprintf (xtrace_fp, "%s", indirection_level_string ());
Jari Aaltob80f6442004-07-27 13:29:18 +0000496
497 /* VALUE should not be NULL when this is called. */
498 if (*value == '\0' || assign_list)
499 nval = value;
500 else if (sh_contains_shell_metas (value))
501 nval = sh_single_quote (value);
502 else if (ansic_shouldquote (value))
503 nval = ansic_quote (value, 0, (int *)0);
504 else
505 nval = value;
506
507 if (assign_list)
Chet Ramey00018032011-11-21 20:51:19 -0500508 fprintf (xtrace_fp, "%s=(%s)\n", name, nval);
Jari Aaltob80f6442004-07-27 13:29:18 +0000509 else
Chet Ramey00018032011-11-21 20:51:19 -0500510 fprintf (xtrace_fp, "%s=%s\n", name, nval);
Jari Aaltob80f6442004-07-27 13:29:18 +0000511
512 if (nval != value)
513 FREE (nval);
514
Chet Ramey00018032011-11-21 20:51:19 -0500515 fflush (xtrace_fp);
Jari Aaltob80f6442004-07-27 13:29:18 +0000516}
517
Chet Rameyd233b482019-01-07 09:27:52 -0500518/* A function to print the words of a simple command when set -x is on. Also used to
519 print the word list in a for or select command header; in that case, we suppress
520 quoting the words because they haven't been expanded yet. XTFLAGS&1 means to
521 print $PS4; XTFLAGS&2 means to suppress quoting the words in LIST. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000522void
Jari Aaltob80f6442004-07-27 13:29:18 +0000523xtrace_print_word_list (list, xtflags)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000524 WORD_LIST *list;
Jari Aaltob80f6442004-07-27 13:29:18 +0000525 int xtflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000526{
527 WORD_LIST *w;
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000528 char *t, *x;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000529
Chet Ramey00018032011-11-21 20:51:19 -0500530 CHECK_XTRACE_FP;
531
Chet Rameya0c0a002016-09-15 16:59:08 -0400532 if (xtflags&1)
Chet Ramey00018032011-11-21 20:51:19 -0500533 fprintf (xtrace_fp, "%s", indirection_level_string ());
Jari Aaltob80f6442004-07-27 13:29:18 +0000534
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000535 for (w = list; w; w = w->next)
536 {
537 t = w->word->word;
538 if (t == 0 || *t == '\0')
Chet Ramey00018032011-11-21 20:51:19 -0500539 fprintf (xtrace_fp, "''%s", w->next ? " " : "");
Chet Rameya0c0a002016-09-15 16:59:08 -0400540 else if (xtflags & 2)
541 fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
Jari Aalto28ef6c32001-04-06 19:14:31 +0000542 else if (sh_contains_shell_metas (t))
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000543 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000544 x = sh_single_quote (t);
Chet Ramey00018032011-11-21 20:51:19 -0500545 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000546 free (x);
547 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000548 else if (ansic_shouldquote (t))
549 {
550 x = ansic_quote (t, 0, (int *)0);
Chet Ramey00018032011-11-21 20:51:19 -0500551 fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
Jari Aalto7117c2d2002-07-17 14:10:11 +0000552 free (x);
553 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000554 else
Chet Ramey00018032011-11-21 20:51:19 -0500555 fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000556 }
Chet Ramey00018032011-11-21 20:51:19 -0500557 fprintf (xtrace_fp, "\n");
558 fflush (xtrace_fp);
Jari Aalto726f6381996-08-26 18:22:31 +0000559}
560
561static void
562command_print_word_list (list, separator)
563 WORD_LIST *list;
564 char *separator;
565{
566 _print_word_list (list, separator, cprintf);
567}
568
Jari Aaltob80f6442004-07-27 13:29:18 +0000569void
570print_for_command_head (for_command)
Jari Aalto726f6381996-08-26 18:22:31 +0000571 FOR_COM *for_command;
572{
573 cprintf ("for %s in ", for_command->name->word);
574 command_print_word_list (for_command->map_list, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000575}
576
577void
578xtrace_print_for_command_head (for_command)
579 FOR_COM *for_command;
580{
Chet Ramey00018032011-11-21 20:51:19 -0500581 CHECK_XTRACE_FP;
582 fprintf (xtrace_fp, "%s", indirection_level_string ());
583 fprintf (xtrace_fp, "for %s in ", for_command->name->word);
Chet Rameya0c0a002016-09-15 16:59:08 -0400584 xtrace_print_word_list (for_command->map_list, 2);
Jari Aaltob80f6442004-07-27 13:29:18 +0000585}
586
587static void
588print_for_command (for_command)
589 FOR_COM *for_command;
590{
591 print_for_command_head (for_command);
Jari Aalto726f6381996-08-26 18:22:31 +0000592 cprintf (";");
593 newline ("do\n");
Chet Ramey30d188c2011-11-21 20:57:16 -0500594
Jari Aalto726f6381996-08-26 18:22:31 +0000595 indentation += indentation_amount;
596 make_command_string_internal (for_command->action);
Chet Ramey30d188c2011-11-21 20:57:16 -0500597 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000598 semicolon ();
599 indentation -= indentation_amount;
Chet Ramey30d188c2011-11-21 20:57:16 -0500600
Jari Aalto726f6381996-08-26 18:22:31 +0000601 newline ("done");
602}
603
Jari Aaltobb706242000-03-17 21:46:59 +0000604#if defined (ARITH_FOR_COMMAND)
605static void
606print_arith_for_command (arith_for_command)
607 ARITH_FOR_COM *arith_for_command;
608{
Jari Aaltob80f6442004-07-27 13:29:18 +0000609 cprintf ("for ((");
Jari Aaltobb706242000-03-17 21:46:59 +0000610 command_print_word_list (arith_for_command->init, " ");
Jari Aalto95732b42005-12-07 14:08:12 +0000611 cprintf ("; ");
Jari Aaltobb706242000-03-17 21:46:59 +0000612 command_print_word_list (arith_for_command->test, " ");
Jari Aalto95732b42005-12-07 14:08:12 +0000613 cprintf ("; ");
Jari Aaltobb706242000-03-17 21:46:59 +0000614 command_print_word_list (arith_for_command->step, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000615 cprintf ("))");
Jari Aaltobb706242000-03-17 21:46:59 +0000616 newline ("do\n");
617 indentation += indentation_amount;
618 make_command_string_internal (arith_for_command->action);
Chet Ramey680d15e2011-11-22 20:01:00 -0500619 PRINT_DEFERRED_HEREDOCS ("");
Jari Aaltobb706242000-03-17 21:46:59 +0000620 semicolon ();
621 indentation -= indentation_amount;
622 newline ("done");
623}
624#endif /* ARITH_FOR_COMMAND */
625
Jari Aalto726f6381996-08-26 18:22:31 +0000626#if defined (SELECT_COMMAND)
Jari Aaltob80f6442004-07-27 13:29:18 +0000627void
628print_select_command_head (select_command)
Jari Aalto726f6381996-08-26 18:22:31 +0000629 SELECT_COM *select_command;
630{
631 cprintf ("select %s in ", select_command->name->word);
632 command_print_word_list (select_command->map_list, " ");
Jari Aaltob80f6442004-07-27 13:29:18 +0000633}
634
635void
636xtrace_print_select_command_head (select_command)
637 SELECT_COM *select_command;
638{
Chet Ramey00018032011-11-21 20:51:19 -0500639 CHECK_XTRACE_FP;
640 fprintf (xtrace_fp, "%s", indirection_level_string ());
641 fprintf (xtrace_fp, "select %s in ", select_command->name->word);
Chet Rameya0c0a002016-09-15 16:59:08 -0400642 xtrace_print_word_list (select_command->map_list, 2);
Jari Aaltob80f6442004-07-27 13:29:18 +0000643}
644
645static void
646print_select_command (select_command)
647 SELECT_COM *select_command;
648{
649 print_select_command_head (select_command);
650
Jari Aalto726f6381996-08-26 18:22:31 +0000651 cprintf (";");
652 newline ("do\n");
653 indentation += indentation_amount;
654 make_command_string_internal (select_command->action);
Chet Ramey495aee42011-11-22 19:11:26 -0500655 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000656 semicolon ();
657 indentation -= indentation_amount;
658 newline ("done");
659}
660#endif /* SELECT_COMMAND */
661
662static void
663print_group_command (group_command)
664 GROUP_COM *group_command;
665{
666 group_command_nesting++;
667 cprintf ("{ ");
668
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000669 if (inside_function_def == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000670 skip_this_indent++;
671 else
672 {
673 /* This is a group command { ... } inside of a function
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000674 definition, and should be printed as a multiline group
Jari Aalto726f6381996-08-26 18:22:31 +0000675 command, using the current indentation. */
676 cprintf ("\n");
677 indentation += indentation_amount;
678 }
679
680 make_command_string_internal (group_command->command);
Chet Ramey680d15e2011-11-22 20:01:00 -0500681 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000682
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000683 if (inside_function_def)
Jari Aalto726f6381996-08-26 18:22:31 +0000684 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000685 cprintf ("\n");
Jari Aalto726f6381996-08-26 18:22:31 +0000686 indentation -= indentation_amount;
687 indent (indentation);
Jari Aalto726f6381996-08-26 18:22:31 +0000688 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000689 else
690 {
691 semicolon ();
692 cprintf (" ");
693 }
694
Jari Aalto726f6381996-08-26 18:22:31 +0000695 cprintf ("}");
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000696
Jari Aalto726f6381996-08-26 18:22:31 +0000697 group_command_nesting--;
698}
699
Jari Aaltob80f6442004-07-27 13:29:18 +0000700void
701print_case_command_head (case_command)
702 CASE_COM *case_command;
703{
704 cprintf ("case %s in ", case_command->word->word);
705}
706
707void
708xtrace_print_case_command_head (case_command)
709 CASE_COM *case_command;
710{
Chet Ramey00018032011-11-21 20:51:19 -0500711 CHECK_XTRACE_FP;
712 fprintf (xtrace_fp, "%s", indirection_level_string ());
713 fprintf (xtrace_fp, "case %s in\n", case_command->word->word);
Jari Aaltob80f6442004-07-27 13:29:18 +0000714}
715
Jari Aalto726f6381996-08-26 18:22:31 +0000716static void
717print_case_command (case_command)
718 CASE_COM *case_command;
719{
Jari Aaltob80f6442004-07-27 13:29:18 +0000720 print_case_command_head (case_command);
721
Jari Aalto726f6381996-08-26 18:22:31 +0000722 if (case_command->clauses)
723 print_case_clauses (case_command->clauses);
724 newline ("esac");
725}
726
727static void
728print_case_clauses (clauses)
729 PATTERN_LIST *clauses;
730{
731 indentation += indentation_amount;
732 while (clauses)
733 {
734 newline ("");
735 command_print_word_list (clauses->patterns, " | ");
736 cprintf (")\n");
737 indentation += indentation_amount;
738 make_command_string_internal (clauses->action);
739 indentation -= indentation_amount;
Chet Ramey495aee42011-11-22 19:11:26 -0500740 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto31859422009-01-12 13:36:28 +0000741 if (clauses->flags & CASEPAT_FALLTHROUGH)
742 newline (";&");
743 else if (clauses->flags & CASEPAT_TESTNEXT)
744 newline (";;&");
745 else
746 newline (";;");
Jari Aalto726f6381996-08-26 18:22:31 +0000747 clauses = clauses->next;
748 }
749 indentation -= indentation_amount;
750}
751
752static void
753print_while_command (while_command)
754 WHILE_COM *while_command;
755{
756 print_until_or_while (while_command, "while");
757}
758
759static void
760print_until_command (while_command)
761 WHILE_COM *while_command;
762{
763 print_until_or_while (while_command, "until");
764}
765
766static void
767print_until_or_while (while_command, which)
768 WHILE_COM *while_command;
769 char *which;
770{
771 cprintf ("%s ", which);
772 skip_this_indent++;
773 make_command_string_internal (while_command->test);
Chet Ramey495aee42011-11-22 19:11:26 -0500774 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000775 semicolon ();
776 cprintf (" do\n"); /* was newline ("do\n"); */
777 indentation += indentation_amount;
778 make_command_string_internal (while_command->action);
Chet Ramey495aee42011-11-22 19:11:26 -0500779 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000780 indentation -= indentation_amount;
781 semicolon ();
782 newline ("done");
783}
784
785static void
786print_if_command (if_command)
787 IF_COM *if_command;
788{
789 cprintf ("if ");
790 skip_this_indent++;
791 make_command_string_internal (if_command->test);
792 semicolon ();
793 cprintf (" then\n");
794 indentation += indentation_amount;
795 make_command_string_internal (if_command->true_case);
Chet Ramey495aee42011-11-22 19:11:26 -0500796 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000797 indentation -= indentation_amount;
798
799 if (if_command->false_case)
800 {
801 semicolon ();
802 newline ("else\n");
803 indentation += indentation_amount;
804 make_command_string_internal (if_command->false_case);
Chet Ramey495aee42011-11-22 19:11:26 -0500805 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +0000806 indentation -= indentation_amount;
807 }
808 semicolon ();
809 newline ("fi");
810}
811
Chet Rameya0c0a002016-09-15 16:59:08 -0400812#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
Jari Aaltob80f6442004-07-27 13:29:18 +0000813void
814print_arith_command (arith_cmd_list)
815 WORD_LIST *arith_cmd_list;
Jari Aaltocce855b1998-04-17 19:52:44 +0000816{
Jari Aaltob80f6442004-07-27 13:29:18 +0000817 cprintf ("((");
818 command_print_word_list (arith_cmd_list, " ");
819 cprintf ("))");
Jari Aaltocce855b1998-04-17 19:52:44 +0000820}
Jari Aaltobb706242000-03-17 21:46:59 +0000821#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000822
823#if defined (COND_COMMAND)
824static void
825print_cond_node (cond)
826 COND_COM *cond;
827{
828 if (cond->flags & CMD_INVERT_RETURN)
829 cprintf ("! ");
830
831 if (cond->type == COND_EXPR)
832 {
833 cprintf ("( ");
834 print_cond_node (cond->left);
835 cprintf (" )");
836 }
837 else if (cond->type == COND_AND)
838 {
839 print_cond_node (cond->left);
840 cprintf (" && ");
841 print_cond_node (cond->right);
842 }
843 else if (cond->type == COND_OR)
844 {
845 print_cond_node (cond->left);
846 cprintf (" || ");
847 print_cond_node (cond->right);
848 }
849 else if (cond->type == COND_UNARY)
850 {
Jari Aaltob72432f1999-02-19 17:11:39 +0000851 cprintf ("%s", cond->op->word);
Jari Aaltocce855b1998-04-17 19:52:44 +0000852 cprintf (" ");
853 print_cond_node (cond->left);
854 }
855 else if (cond->type == COND_BINARY)
856 {
857 print_cond_node (cond->left);
858 cprintf (" ");
Jari Aaltob72432f1999-02-19 17:11:39 +0000859 cprintf ("%s", cond->op->word);
Jari Aaltocce855b1998-04-17 19:52:44 +0000860 cprintf (" ");
861 print_cond_node (cond->right);
862 }
863 else if (cond->type == COND_TERM)
864 {
Jari Aaltob72432f1999-02-19 17:11:39 +0000865 cprintf ("%s", cond->op->word); /* need to add quoting here */
Jari Aaltocce855b1998-04-17 19:52:44 +0000866 }
867}
868
Jari Aaltob80f6442004-07-27 13:29:18 +0000869void
Jari Aaltocce855b1998-04-17 19:52:44 +0000870print_cond_command (cond)
871 COND_COM *cond;
872{
873 cprintf ("[[ ");
874 print_cond_node (cond);
875 cprintf (" ]]");
876}
877
Jari Aalto28ef6c32001-04-06 19:14:31 +0000878#ifdef DEBUG
Jari Aaltocce855b1998-04-17 19:52:44 +0000879void
Chet Rameyac50fba2014-02-26 09:36:43 -0500880debug_print_word_list (s, list, sep)
881 char *s;
882 WORD_LIST *list;
883 char *sep;
884{
885 WORD_LIST *w;
886
887 if (s)
888 fprintf (stderr, "%s: ", s);
889 for (w = list; w; w = w->next)
890 fprintf (stderr, "%s%s", w->word->word, w->next ? sep : "");
891 fprintf (stderr, "\n");
892}
893
894void
Jari Aaltocce855b1998-04-17 19:52:44 +0000895debug_print_cond_command (cond)
896 COND_COM *cond;
897{
898 fprintf (stderr, "DEBUG: ");
899 command_string_index = 0;
900 print_cond_command (cond);
901 fprintf (stderr, "%s\n", the_printed_command);
902}
Jari Aalto28ef6c32001-04-06 19:14:31 +0000903#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000904
905void
906xtrace_print_cond_term (type, invert, op, arg1, arg2)
907 int type, invert;
908 WORD_DESC *op;
909 char *arg1, *arg2;
910{
Chet Ramey00018032011-11-21 20:51:19 -0500911 CHECK_XTRACE_FP;
Jari Aaltocce855b1998-04-17 19:52:44 +0000912 command_string_index = 0;
Chet Ramey00018032011-11-21 20:51:19 -0500913 fprintf (xtrace_fp, "%s", indirection_level_string ());
914 fprintf (xtrace_fp, "[[ ");
Jari Aaltocce855b1998-04-17 19:52:44 +0000915 if (invert)
Chet Ramey00018032011-11-21 20:51:19 -0500916 fprintf (xtrace_fp, "! ");
Jari Aaltocce855b1998-04-17 19:52:44 +0000917
918 if (type == COND_UNARY)
919 {
Chet Ramey00018032011-11-21 20:51:19 -0500920 fprintf (xtrace_fp, "%s ", op->word);
921 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
Jari Aaltocce855b1998-04-17 19:52:44 +0000922 }
923 else if (type == COND_BINARY)
924 {
Chet Ramey00018032011-11-21 20:51:19 -0500925 fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
926 fprintf (xtrace_fp, " %s ", op->word);
927 fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
Jari Aaltocce855b1998-04-17 19:52:44 +0000928 }
929
Chet Ramey00018032011-11-21 20:51:19 -0500930 fprintf (xtrace_fp, " ]]\n");
931
932 fflush (xtrace_fp);
Jari Aaltocce855b1998-04-17 19:52:44 +0000933}
934#endif /* COND_COMMAND */
935
Jari Aaltobb706242000-03-17 21:46:59 +0000936#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
Jari Aaltocce855b1998-04-17 19:52:44 +0000937/* A function to print the words of an arithmetic command when set -x is on. */
938void
939xtrace_print_arith_cmd (list)
940 WORD_LIST *list;
941{
942 WORD_LIST *w;
943
Chet Ramey00018032011-11-21 20:51:19 -0500944 CHECK_XTRACE_FP;
945 fprintf (xtrace_fp, "%s", indirection_level_string ());
946 fprintf (xtrace_fp, "(( ");
Jari Aaltocce855b1998-04-17 19:52:44 +0000947 for (w = list; w; w = w->next)
Chet Ramey00018032011-11-21 20:51:19 -0500948 fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
949 fprintf (xtrace_fp, " ))\n");
950
951 fflush (xtrace_fp);
Jari Aaltocce855b1998-04-17 19:52:44 +0000952}
953#endif
954
Jari Aalto726f6381996-08-26 18:22:31 +0000955void
956print_simple_command (simple_command)
957 SIMPLE_COM *simple_command;
958{
959 command_print_word_list (simple_command->words, " ");
960
961 if (simple_command->redirects)
962 {
963 cprintf (" ");
964 print_redirection_list (simple_command->redirects);
965 }
966}
967
968static void
Jari Aalto31859422009-01-12 13:36:28 +0000969print_heredocs (heredocs)
970 REDIRECT *heredocs;
971{
972 REDIRECT *hdtail;
973
974 cprintf (" ");
975 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
976 {
977 print_redirection (hdtail);
978 cprintf ("\n");
979 }
980 was_heredoc = 1;
981}
982
Jari Aalto31859422009-01-12 13:36:28 +0000983static void
Chet Rameyd233b482019-01-07 09:27:52 -0500984print_heredoc_bodies (heredocs)
985 REDIRECT *heredocs;
Jari Aalto31859422009-01-12 13:36:28 +0000986{
Chet Rameyd233b482019-01-07 09:27:52 -0500987 REDIRECT *hdtail;
Jari Aalto31859422009-01-12 13:36:28 +0000988
Chet Rameyd233b482019-01-07 09:27:52 -0500989 cprintf ("\n");
990 for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
Jari Aalto31859422009-01-12 13:36:28 +0000991 {
992 print_heredoc_body (hdtail);
993 cprintf ("\n");
994 }
Chet Rameyd233b482019-01-07 09:27:52 -0500995 was_heredoc = 1;
996}
997
998/* Print heredocs that are attached to the command before the connector
999 represented by CSTRING. The parsing semantics require us to print the
1000 here-doc delimiters, then the connector (CSTRING), then the here-doc
1001 bodies. We print the here-doc delimiters in print_redirection_list
1002 and print the connector and the bodies here. We don't print the connector
1003 if it's a `;', but we use it to note not to print an extra space after the
1004 last heredoc body and newline. */
1005static void
1006print_deferred_heredocs (cstring)
1007 const char *cstring;
1008{
1009 /* We now print the heredoc headers in print_redirection_list */
1010 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
1011 cprintf ("%s", cstring);
Jari Aalto31859422009-01-12 13:36:28 +00001012 if (deferred_heredocs)
1013 {
Chet Rameyd233b482019-01-07 09:27:52 -05001014 print_heredoc_bodies (deferred_heredocs);
Jari Aalto17345e52009-02-19 22:21:29 +00001015 if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
Jari Aalto31859422009-01-12 13:36:28 +00001016 cprintf (" "); /* make sure there's at least one space */
1017 dispose_redirects (deferred_heredocs);
Jari Aalto17345e52009-02-19 22:21:29 +00001018 was_heredoc = 1;
Jari Aalto31859422009-01-12 13:36:28 +00001019 }
1020 deferred_heredocs = (REDIRECT *)NULL;
1021}
1022
1023static void
Jari Aalto726f6381996-08-26 18:22:31 +00001024print_redirection_list (redirects)
1025 REDIRECT *redirects;
1026{
Jari Aaltod166f041997-06-05 14:59:13 +00001027 REDIRECT *heredocs, *hdtail, *newredir;
Chet Rameyac50fba2014-02-26 09:36:43 -05001028 char *rw;
Jari Aaltod166f041997-06-05 14:59:13 +00001029
1030 heredocs = (REDIRECT *)NULL;
1031 hdtail = heredocs;
1032
1033 was_heredoc = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001034 while (redirects)
1035 {
Chet Rameyd233b482019-01-07 09:27:52 -05001036 /* Defer printing the here document bodiess until we've printed the rest of the
1037 redirections, but print the headers in the order they're given. */
Jari Aaltod166f041997-06-05 14:59:13 +00001038 if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
1039 {
1040 newredir = copy_redirect (redirects);
1041 newredir->next = (REDIRECT *)NULL;
Chet Rameyd233b482019-01-07 09:27:52 -05001042
1043 print_heredoc_header (newredir);
1044
Jari Aaltod166f041997-06-05 14:59:13 +00001045 if (heredocs)
1046 {
1047 hdtail->next = newredir;
1048 hdtail = newredir;
1049 }
1050 else
1051 hdtail = heredocs = newredir;
1052 }
Chet Rameyac50fba2014-02-26 09:36:43 -05001053 else if (redirects->instruction == r_duplicating_output_word && (redirects->flags & REDIR_VARASSIGN) == 0 && redirects->redirector.dest == 1)
Jari Aaltob80f6442004-07-27 13:29:18 +00001054 {
1055 /* Temporarily translate it as the execution code does. */
Chet Rameyac50fba2014-02-26 09:36:43 -05001056 rw = redirects->redirectee.filename->word;
1057 if (rw && *rw != '-' && DIGIT (*rw) == 0 && EXPCHAR (*rw) == 0)
1058 redirects->instruction = r_err_and_out;
Jari Aaltob80f6442004-07-27 13:29:18 +00001059 print_redirection (redirects);
1060 redirects->instruction = r_duplicating_output_word;
1061 }
Jari Aaltod166f041997-06-05 14:59:13 +00001062 else
1063 print_redirection (redirects);
1064
Jari Aalto726f6381996-08-26 18:22:31 +00001065 redirects = redirects->next;
1066 if (redirects)
1067 cprintf (" ");
1068 }
Jari Aaltod166f041997-06-05 14:59:13 +00001069
1070 /* Now that we've printed all the other redirections (on one line),
Chet Rameyd233b482019-01-07 09:27:52 -05001071 print the here documents. If we're printing a connection, we wait until
1072 we print the connector symbol, then we print the here document bodies */
Jari Aalto31859422009-01-12 13:36:28 +00001073 if (heredocs && printing_connection)
1074 deferred_heredocs = heredocs;
1075 else if (heredocs)
Jari Aaltod166f041997-06-05 14:59:13 +00001076 {
Chet Rameyd233b482019-01-07 09:27:52 -05001077 print_heredoc_bodies (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +00001078 dispose_redirects (heredocs);
Jari Aaltod166f041997-06-05 14:59:13 +00001079 }
Jari Aalto726f6381996-08-26 18:22:31 +00001080}
1081
1082static void
Jari Aalto31859422009-01-12 13:36:28 +00001083print_heredoc_header (redirect)
1084 REDIRECT *redirect;
1085{
1086 int kill_leading;
1087 char *x;
1088
1089 kill_leading = redirect->instruction == r_deblank_reading_until;
1090
1091 /* Here doc header */
Chet Ramey00018032011-11-21 20:51:19 -05001092 if (redirect->rflags & REDIR_VARASSIGN)
1093 cprintf ("{%s}", redirect->redirector.filename->word);
1094 else if (redirect->redirector.dest != 0)
1095 cprintf ("%d", redirect->redirector.dest);
Jari Aalto31859422009-01-12 13:36:28 +00001096
1097 /* If the here document delimiter is quoted, single-quote it. */
1098 if (redirect->redirectee.filename->flags & W_QUOTED)
1099 {
1100 x = sh_single_quote (redirect->here_doc_eof);
1101 cprintf ("<<%s%s", kill_leading ? "-" : "", x);
1102 free (x);
1103 }
1104 else
1105 cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
1106}
1107
1108static void
1109print_heredoc_body (redirect)
1110 REDIRECT *redirect;
1111{
1112 /* Here doc body */
1113 cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
1114}
1115
1116static void
Jari Aalto726f6381996-08-26 18:22:31 +00001117print_redirection (redirect)
1118 REDIRECT *redirect;
1119{
Chet Ramey495aee42011-11-22 19:11:26 -05001120 int redirector, redir_fd;
Chet Ramey00018032011-11-21 20:51:19 -05001121 WORD_DESC *redirectee, *redir_word;
Jari Aaltod166f041997-06-05 14:59:13 +00001122
Jari Aaltod166f041997-06-05 14:59:13 +00001123 redirectee = redirect->redirectee.filename;
Jari Aaltod166f041997-06-05 14:59:13 +00001124 redir_fd = redirect->redirectee.dest;
Jari Aalto726f6381996-08-26 18:22:31 +00001125
Chet Ramey00018032011-11-21 20:51:19 -05001126 redir_word = redirect->redirector.filename;
1127 redirector = redirect->redirector.dest;
1128
Jari Aalto726f6381996-08-26 18:22:31 +00001129 switch (redirect->instruction)
1130 {
Jari Aalto726f6381996-08-26 18:22:31 +00001131 case r_input_direction:
Chet Ramey00018032011-11-21 20:51:19 -05001132 if (redirect->rflags & REDIR_VARASSIGN)
1133 cprintf ("{%s}", redir_word->word);
1134 else if (redirector != 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001135 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001136 cprintf ("< %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001137 break;
1138
Chet Ramey00018032011-11-21 20:51:19 -05001139 case r_output_direction:
1140 if (redirect->rflags & REDIR_VARASSIGN)
1141 cprintf ("{%s}", redir_word->word);
1142 else if (redirector != 1)
1143 cprintf ("%d", redirector);
1144 cprintf ("> %s", redirectee->word);
1145 break;
1146
Jari Aalto726f6381996-08-26 18:22:31 +00001147 case r_inputa_direction: /* Redirection created by the shell. */
1148 cprintf ("&");
1149 break;
1150
Chet Ramey00018032011-11-21 20:51:19 -05001151 case r_output_force:
1152 if (redirect->rflags & REDIR_VARASSIGN)
1153 cprintf ("{%s}", redir_word->word);
1154 else if (redirector != 1)
1155 cprintf ("%d", redirector);
Chet Rameyac50fba2014-02-26 09:36:43 -05001156 cprintf (">| %s", redirectee->word);
Chet Ramey00018032011-11-21 20:51:19 -05001157 break;
1158
Jari Aalto726f6381996-08-26 18:22:31 +00001159 case r_appending_to:
Chet Ramey00018032011-11-21 20:51:19 -05001160 if (redirect->rflags & REDIR_VARASSIGN)
1161 cprintf ("{%s}", redir_word->word);
1162 else if (redirector != 1)
Jari Aalto726f6381996-08-26 18:22:31 +00001163 cprintf ("%d", redirector);
Jari Aalto06285672006-10-10 14:15:34 +00001164 cprintf (">> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001165 break;
1166
Chet Ramey00018032011-11-21 20:51:19 -05001167 case r_input_output:
1168 if (redirect->rflags & REDIR_VARASSIGN)
1169 cprintf ("{%s}", redir_word->word);
1170 else if (redirector != 1)
1171 cprintf ("%d", redirector);
1172 cprintf ("<> %s", redirectee->word);
1173 break;
1174
Jari Aalto726f6381996-08-26 18:22:31 +00001175 case r_deblank_reading_until:
Jari Aalto726f6381996-08-26 18:22:31 +00001176 case r_reading_until:
Jari Aalto31859422009-01-12 13:36:28 +00001177 print_heredoc_header (redirect);
1178 cprintf ("\n");
1179 print_heredoc_body (redirect);
Jari Aalto726f6381996-08-26 18:22:31 +00001180 break;
1181
Jari Aalto7117c2d2002-07-17 14:10:11 +00001182 case r_reading_string:
Chet Ramey00018032011-11-21 20:51:19 -05001183 if (redirect->rflags & REDIR_VARASSIGN)
1184 cprintf ("{%s}", redir_word->word);
1185 else if (redirector != 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001186 cprintf ("%d", redirector);
Chet Ramey495aee42011-11-22 19:11:26 -05001187#if 0
1188 /* Don't need to check whether or not to requote, since original quotes
1189 are still intact. The only thing that has happened is that $'...'
1190 has been replaced with 'expanded ...'. */
Jari Aalto7117c2d2002-07-17 14:10:11 +00001191 if (ansic_shouldquote (redirect->redirectee.filename->word))
1192 {
1193 char *x;
1194 x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
1195 cprintf ("<<< %s", x);
1196 free (x);
1197 }
1198 else
Chet Ramey495aee42011-11-22 19:11:26 -05001199#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +00001200 cprintf ("<<< %s", redirect->redirectee.filename->word);
1201 break;
1202
Jari Aalto726f6381996-08-26 18:22:31 +00001203 case r_duplicating_input:
Chet Ramey00018032011-11-21 20:51:19 -05001204 if (redirect->rflags & REDIR_VARASSIGN)
1205 cprintf ("{%s}<&%d", redir_word->word, redir_fd);
1206 else
1207 cprintf ("%d<&%d", redirector, redir_fd);
Jari Aalto726f6381996-08-26 18:22:31 +00001208 break;
1209
1210 case r_duplicating_output:
Chet Ramey00018032011-11-21 20:51:19 -05001211 if (redirect->rflags & REDIR_VARASSIGN)
1212 cprintf ("{%s}>&%d", redir_word->word, redir_fd);
1213 else
1214 cprintf ("%d>&%d", redirector, redir_fd);
Jari Aalto726f6381996-08-26 18:22:31 +00001215 break;
1216
1217 case r_duplicating_input_word:
Chet Ramey00018032011-11-21 20:51:19 -05001218 if (redirect->rflags & REDIR_VARASSIGN)
1219 cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
1220 else
1221 cprintf ("%d<&%s", redirector, redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001222 break;
1223
1224 case r_duplicating_output_word:
Chet Ramey00018032011-11-21 20:51:19 -05001225 if (redirect->rflags & REDIR_VARASSIGN)
1226 cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
1227 else
1228 cprintf ("%d>&%s", redirector, redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001229 break;
1230
Jari Aalto7117c2d2002-07-17 14:10:11 +00001231 case r_move_input:
Chet Ramey00018032011-11-21 20:51:19 -05001232 if (redirect->rflags & REDIR_VARASSIGN)
1233 cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
1234 else
1235 cprintf ("%d<&%d-", redirector, redir_fd);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001236 break;
1237
1238 case r_move_output:
Chet Ramey00018032011-11-21 20:51:19 -05001239 if (redirect->rflags & REDIR_VARASSIGN)
1240 cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
1241 else
1242 cprintf ("%d>&%d-", redirector, redir_fd);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001243 break;
1244
1245 case r_move_input_word:
Chet Ramey00018032011-11-21 20:51:19 -05001246 if (redirect->rflags & REDIR_VARASSIGN)
1247 cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
1248 else
1249 cprintf ("%d<&%s-", redirector, redirectee->word);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001250 break;
1251
1252 case r_move_output_word:
Chet Ramey00018032011-11-21 20:51:19 -05001253 if (redirect->rflags & REDIR_VARASSIGN)
1254 cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
1255 else
1256 cprintf ("%d>&%s-", redirector, redirectee->word);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001257 break;
1258
Jari Aalto726f6381996-08-26 18:22:31 +00001259 case r_close_this:
Chet Ramey00018032011-11-21 20:51:19 -05001260 if (redirect->rflags & REDIR_VARASSIGN)
1261 cprintf ("{%s}>&-", redir_word->word);
1262 else
1263 cprintf ("%d>&-", redirector);
Jari Aalto726f6381996-08-26 18:22:31 +00001264 break;
1265
1266 case r_err_and_out:
Chet Rameyac50fba2014-02-26 09:36:43 -05001267 cprintf ("&> %s", redirectee->word);
Jari Aalto31859422009-01-12 13:36:28 +00001268 break;
1269
1270 case r_append_err_and_out:
Chet Rameyac50fba2014-02-26 09:36:43 -05001271 cprintf ("&>> %s", redirectee->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001272 break;
Jari Aalto726f6381996-08-26 18:22:31 +00001273 }
1274}
1275
1276static void
1277reset_locals ()
1278{
1279 inside_function_def = 0;
1280 indentation = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001281 printing_connection = 0;
1282 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001283}
1284
1285static void
1286print_function_def (func)
1287 FUNCTION_DEF *func;
1288{
Jari Aaltobb706242000-03-17 21:46:59 +00001289 COMMAND *cmdcopy;
1290 REDIRECT *func_redirects;
1291
Jari Aaltof73dda02001-11-13 17:56:06 +00001292 func_redirects = NULL;
Chet Rameya0c0a002016-09-15 16:59:08 -04001293 /* When in posix mode, print functions as posix specifies them. */
1294 if (posixly_correct == 0)
1295 cprintf ("function %s () \n", func->name->word);
1296 else
1297 cprintf ("%s () \n", func->name->word);
Jari Aalto726f6381996-08-26 18:22:31 +00001298 add_unwind_protect (reset_locals, 0);
1299
1300 indent (indentation);
1301 cprintf ("{ \n");
1302
1303 inside_function_def++;
1304 indentation += indentation_amount;
1305
Jari Aaltobb706242000-03-17 21:46:59 +00001306 cmdcopy = copy_command (func->command);
1307 if (cmdcopy->type == cm_group)
1308 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001309 func_redirects = cmdcopy->redirects;
1310 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001311 }
1312 make_command_string_internal (cmdcopy->type == cm_group
1313 ? cmdcopy->value.Group->command
1314 : cmdcopy);
Chet Ramey8868eda2020-12-06 15:51:17 -05001315 PRINT_DEFERRED_HEREDOCS ("");
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001316
Jari Aalto726f6381996-08-26 18:22:31 +00001317 remove_unwind_protect ();
1318 indentation -= indentation_amount;
1319 inside_function_def--;
1320
Jari Aaltobb706242000-03-17 21:46:59 +00001321 if (func_redirects)
1322 { /* { */
1323 newline ("} ");
1324 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001325 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001326 }
1327 else
1328 newline ("}");
1329
1330 dispose_command (cmdcopy);
Jari Aalto726f6381996-08-26 18:22:31 +00001331}
1332
1333/* Return the string representation of the named function.
1334 NAME is the name of the function.
1335 COMMAND is the function body. It should be a GROUP_COM.
Jari Aalto31859422009-01-12 13:36:28 +00001336 flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
1337 flags&FUNC_EXTERNAL means convert from internal to external form
Jari Aalto726f6381996-08-26 18:22:31 +00001338 */
1339char *
Jari Aalto31859422009-01-12 13:36:28 +00001340named_function_string (name, command, flags)
Jari Aalto726f6381996-08-26 18:22:31 +00001341 char *name;
1342 COMMAND *command;
Jari Aalto31859422009-01-12 13:36:28 +00001343 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +00001344{
1345 char *result;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001346 int old_indent, old_amount;
Jari Aaltobb706242000-03-17 21:46:59 +00001347 COMMAND *cmdcopy;
1348 REDIRECT *func_redirects;
Jari Aalto726f6381996-08-26 18:22:31 +00001349
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001350 old_indent = indentation;
1351 old_amount = indentation_amount;
Jari Aaltod166f041997-06-05 14:59:13 +00001352 command_string_index = was_heredoc = 0;
Jari Aalto31859422009-01-12 13:36:28 +00001353 deferred_heredocs = 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001354
1355 if (name && *name)
Chet Rameya0c0a002016-09-15 16:59:08 -04001356 {
1357 if (find_reserved_word (name) >= 0)
1358 cprintf ("function ");
1359 cprintf ("%s ", name);
1360 }
Jari Aalto726f6381996-08-26 18:22:31 +00001361
1362 cprintf ("() ");
1363
Jari Aalto31859422009-01-12 13:36:28 +00001364 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001365 {
1366 indentation = 1;
1367 indentation_amount = 0;
1368 }
1369 else
1370 {
1371 cprintf ("\n");
1372 indentation += indentation_amount;
1373 }
1374
1375 inside_function_def++;
1376
Jari Aalto31859422009-01-12 13:36:28 +00001377 cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
Jari Aalto726f6381996-08-26 18:22:31 +00001378
Jari Aaltobb706242000-03-17 21:46:59 +00001379 cmdcopy = copy_command (command);
1380 /* Take any redirections specified in the function definition (which should
1381 apply to the function as a whole) and save them for printing later. */
1382 func_redirects = (REDIRECT *)NULL;
1383 if (cmdcopy->type == cm_group)
1384 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001385 func_redirects = cmdcopy->redirects;
1386 cmdcopy->redirects = (REDIRECT *)NULL;
Jari Aaltobb706242000-03-17 21:46:59 +00001387 }
1388 make_command_string_internal (cmdcopy->type == cm_group
1389 ? cmdcopy->value.Group->command
1390 : cmdcopy);
Chet Ramey8868eda2020-12-06 15:51:17 -05001391 PRINT_DEFERRED_HEREDOCS ("");
Jari Aalto726f6381996-08-26 18:22:31 +00001392
1393 indentation = old_indent;
1394 indentation_amount = old_amount;
1395 inside_function_def--;
1396
Jari Aaltobb706242000-03-17 21:46:59 +00001397 if (func_redirects)
1398 { /* { */
1399 newline ("} ");
1400 print_redirection_list (func_redirects);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001401 cmdcopy->redirects = func_redirects;
Jari Aaltobb706242000-03-17 21:46:59 +00001402 }
1403 else
1404 newline ("}");
Jari Aalto726f6381996-08-26 18:22:31 +00001405
1406 result = the_printed_command;
1407
Jari Aalto31859422009-01-12 13:36:28 +00001408 if ((flags & FUNC_MULTILINE) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001409 {
1410#if 0
1411 register int i;
1412 for (i = 0; result[i]; i++)
1413 if (result[i] == '\n')
1414 {
1415 strcpy (result + i, result + i + 1);
1416 --i;
1417 }
1418#else
1419 if (result[2] == '\n') /* XXX -- experimental */
Chet Rameyd233b482019-01-07 09:27:52 -05001420 memmove (result + 2, result + 3, strlen (result) - 2);
Jari Aalto726f6381996-08-26 18:22:31 +00001421#endif
1422 }
1423
Jari Aaltobb706242000-03-17 21:46:59 +00001424 dispose_command (cmdcopy);
1425
Jari Aalto31859422009-01-12 13:36:28 +00001426 if (flags & FUNC_EXTERNAL)
1427 result = remove_quoted_escapes (result);
1428
Jari Aalto726f6381996-08-26 18:22:31 +00001429 return (result);
1430}
1431
1432static void
1433newline (string)
1434 char *string;
1435{
1436 cprintf ("\n");
1437 indent (indentation);
1438 if (string && *string)
1439 cprintf ("%s", string);
1440}
1441
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001442static char *indentation_string;
1443static int indentation_size;
1444
Jari Aalto726f6381996-08-26 18:22:31 +00001445static void
1446indent (amount)
1447 int amount;
1448{
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001449 register int i;
1450
1451 RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
1452
1453 for (i = 0; amount > 0; amount--)
1454 indentation_string[i++] = ' ';
1455 indentation_string[i] = '\0';
Chet Rameyac50fba2014-02-26 09:36:43 -05001456 cprintf ("%s", indentation_string);
Jari Aalto726f6381996-08-26 18:22:31 +00001457}
1458
1459static void
1460semicolon ()
1461{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001462 if (command_string_index > 0 &&
1463 (the_printed_command[command_string_index - 1] == '&' ||
Chet Ramey00018032011-11-21 20:51:19 -05001464 the_printed_command[command_string_index - 1] == '\n'))
Jari Aalto726f6381996-08-26 18:22:31 +00001465 return;
1466 cprintf (";");
1467}
1468
Jari Aalto726f6381996-08-26 18:22:31 +00001469/* How to make the string. */
1470static void
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001471#if defined (PREFER_STDARG)
Jari Aaltof73dda02001-11-13 17:56:06 +00001472cprintf (const char *control, ...)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001473#else
1474cprintf (control, va_alist)
Jari Aaltof73dda02001-11-13 17:56:06 +00001475 const char *control;
Jari Aalto726f6381996-08-26 18:22:31 +00001476 va_dcl
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001477#endif
Jari Aalto726f6381996-08-26 18:22:31 +00001478{
Jari Aaltof73dda02001-11-13 17:56:06 +00001479 register const char *s;
Chet Rameyd233b482019-01-07 09:27:52 -05001480 char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (unsigned int) + 1];
Jari Aalto726f6381996-08-26 18:22:31 +00001481 int digit_arg, arg_len, c;
1482 va_list args;
1483
Jari Aalto7117c2d2002-07-17 14:10:11 +00001484 SH_VA_START (args, control);
Jari Aalto726f6381996-08-26 18:22:31 +00001485
1486 arg_len = strlen (control);
1487 the_printed_command_resize (arg_len + 1);
1488
1489 char_arg[1] = '\0';
1490 s = control;
1491 while (s && *s)
1492 {
Jari Aalto726f6381996-08-26 18:22:31 +00001493 c = *s++;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001494 argp = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +00001495 if (c != '%' || !*s)
1496 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001497 char_arg[0] = c;
1498 argp = char_arg;
Jari Aalto726f6381996-08-26 18:22:31 +00001499 arg_len = 1;
1500 }
1501 else
1502 {
1503 c = *s++;
1504 switch (c)
1505 {
1506 case '%':
1507 char_arg[0] = c;
1508 argp = char_arg;
1509 arg_len = 1;
1510 break;
1511
1512 case 's':
1513 argp = va_arg (args, char *);
1514 arg_len = strlen (argp);
1515 break;
1516
1517 case 'd':
Jari Aaltof73dda02001-11-13 17:56:06 +00001518 /* Represent an out-of-range file descriptor with an out-of-range
1519 integer value. We can do this because the only use of `%d' in
1520 the calls to cprintf is to output a file descriptor number for
1521 a redirection. */
Jari Aalto726f6381996-08-26 18:22:31 +00001522 digit_arg = va_arg (args, int);
Jari Aaltof73dda02001-11-13 17:56:06 +00001523 if (digit_arg < 0)
1524 {
Chet Rameyd233b482019-01-07 09:27:52 -05001525 sprintf (intbuf, "%u", (unsigned int)-1);
Jari Aaltof73dda02001-11-13 17:56:06 +00001526 argp = intbuf;
1527 }
1528 else
Chet Ramey00018032011-11-21 20:51:19 -05001529 argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
Jari Aalto726f6381996-08-26 18:22:31 +00001530 arg_len = strlen (argp);
Jari Aalto726f6381996-08-26 18:22:31 +00001531 break;
1532
1533 case 'c':
1534 char_arg[0] = va_arg (args, int);
1535 argp = char_arg;
1536 arg_len = 1;
1537 break;
1538
1539 default:
Jari Aaltob80f6442004-07-27 13:29:18 +00001540 programming_error (_("cprintf: `%c': invalid format character"), c);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001541 /*NOTREACHED*/
Jari Aalto726f6381996-08-26 18:22:31 +00001542 }
1543 }
1544
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001545 if (argp && arg_len)
Jari Aalto726f6381996-08-26 18:22:31 +00001546 {
1547 the_printed_command_resize (arg_len + 1);
1548 FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
1549 command_string_index += arg_len;
Jari Aalto726f6381996-08-26 18:22:31 +00001550 }
1551 }
1552
Chet Rameyac50fba2014-02-26 09:36:43 -05001553 va_end (args);
1554
Jari Aalto726f6381996-08-26 18:22:31 +00001555 the_printed_command[command_string_index] = '\0';
1556}
Jari Aalto726f6381996-08-26 18:22:31 +00001557
1558/* Ensure that there is enough space to stuff LENGTH characters into
1559 THE_PRINTED_COMMAND. */
1560static void
1561the_printed_command_resize (length)
1562 int length;
1563{
Jari Aaltod166f041997-06-05 14:59:13 +00001564 if (the_printed_command == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001565 {
Jari Aaltod166f041997-06-05 14:59:13 +00001566 the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
Jari Aaltof73dda02001-11-13 17:56:06 +00001567 the_printed_command = (char *)xmalloc (the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001568 command_string_index = 0;
1569 }
1570 else if ((command_string_index + length) >= the_printed_command_size)
1571 {
1572 int new;
1573 new = command_string_index + length + 1;
Jari Aaltobb706242000-03-17 21:46:59 +00001574
Jari Aaltod166f041997-06-05 14:59:13 +00001575 /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
1576 new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
Jari Aalto726f6381996-08-26 18:22:31 +00001577 the_printed_command_size = new;
Jari Aaltobb706242000-03-17 21:46:59 +00001578
Jari Aaltof73dda02001-11-13 17:56:06 +00001579 the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
Jari Aalto726f6381996-08-26 18:22:31 +00001580 }
1581}
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001582
Jari Aaltof73dda02001-11-13 17:56:06 +00001583#if defined (HAVE_VPRINTF)
1584/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
1585 also available.'' */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001586
1587static void
Jari Aaltod166f041997-06-05 14:59:13 +00001588#if defined (PREFER_STDARG)
1589xprintf (const char *format, ...)
1590#else
1591xprintf (format, va_alist)
1592 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001593 va_dcl
Jari Aaltod166f041997-06-05 14:59:13 +00001594#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001595{
1596 va_list args;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001597
Jari Aalto7117c2d2002-07-17 14:10:11 +00001598 SH_VA_START (args, format);
Jari Aaltod166f041997-06-05 14:59:13 +00001599
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001600 vfprintf (stdout, format, args);
1601 va_end (args);
1602}
1603
1604#else
1605
1606static void
1607xprintf (format, arg1, arg2, arg3, arg4, arg5)
Jari Aaltof73dda02001-11-13 17:56:06 +00001608 const char *format;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001609{
1610 printf (format, arg1, arg2, arg3, arg4, arg5);
1611}
1612
Jari Aaltof73dda02001-11-13 17:56:06 +00001613#endif /* !HAVE_VPRINTF */