/* print_command -- A way to make readable commands from a command tree. */
-/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
+Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#include "config.h"
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
-# if defined (PREFER_VARARGS)
-# include <varargs.h>
-# endif
+# include <varargs.h>
#endif
#include "bashansi.h"
+#include "bashintl.h"
#include "shell.h"
+#include "flags.h"
#include <y.tab.h> /* use <...> so we pick it up from the build directory */
-#include "stdc.h"
+
+#include "shmbutil.h"
+
#include "builtins/common.h"
-#if !defined (PRINTF_DECLARED)
+#if !HAVE_DECL_PRINTF
extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
#endif
+extern int indirection_level;
+
static int indentation;
static int indentation_amount = 4;
#if defined (PREFER_STDARG)
-static void cprintf __P((char *, ...));
+typedef void PFUNC __P((const char *, ...));
+
+static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
+static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
#else
+#define PFUNC VFunction
static void cprintf ();
-#endif
-
-static void newline (), indent (), the_printed_command_resize ();
-static void semicolon ();
static void xprintf ();
+#endif
-static void make_command_string_internal ();
-static void command_print_word_list ();
-static void print_case_clauses ();
-static void print_redirection_list ();
-static void print_redirection ();
-
-static void print_for_command ();
+static void reset_locals __P((void));
+static void newline __P((char *));
+static void indent __P((int));
+static void semicolon __P((void));
+static void the_printed_command_resize __P((int));
+
+static void make_command_string_internal __P((COMMAND *));
+static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
+static void command_print_word_list __P((WORD_LIST *, char *));
+static void print_case_clauses __P((PATTERN_LIST *));
+static void print_redirection_list __P((REDIRECT *));
+static void print_redirection __P((REDIRECT *));
+
+static void print_for_command __P((FOR_COM *));
+#if defined (ARITH_FOR_COMMAND)
+static void print_arith_for_command __P((ARITH_FOR_COM *));
+#endif
#if defined (SELECT_COMMAND)
-static void print_select_command ();
+static void print_select_command __P((SELECT_COM *));
#endif
-static void print_group_command ();
-static void print_case_command ();
-static void print_while_command ();
-static void print_until_command ();
-static void print_until_or_while ();
-static void print_if_command ();
-static void print_function_def ();
+static void print_group_command __P((GROUP_COM *));
+static void print_case_command __P((CASE_COM *));
+static void print_while_command __P((WHILE_COM *));
+static void print_until_command __P((WHILE_COM *));
+static void print_until_or_while __P((WHILE_COM *, char *));
+static void print_if_command __P((IF_COM *));
+#if defined (COND_COMMAND)
+static void print_cond_node __P((COND_COM *));
+#endif
+static void print_function_def __P((FUNCTION_DEF *));
#define PRINTED_COMMAND_INITIAL_SIZE 64
#define PRINTED_COMMAND_GROW_SIZE 128
includes the group command that is a function body. */
static int group_command_nesting;
+/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
+static char indirection_string[100];
+
/* Print COMMAND (a command tree) on standard output. */
void
print_command (command)
else
indent (indentation);
- if (command->flags & CMD_WANT_SUBSHELL)
- cprintf ("( ");
-
if (command->flags & CMD_TIME_PIPELINE)
{
cprintf ("time ");
print_for_command (command->value.For);
break;
+#if defined (ARITH_FOR_COMMAND)
+ case cm_arith_for:
+ print_arith_for_command (command->value.ArithFor);
+ break;
+#endif
+
#if defined (SELECT_COMMAND)
case cm_select:
print_select_command (command->value.Select);
print_if_command (command->value.If);
break;
+#if defined (DPAREN_ARITHMETIC)
+ case cm_arith:
+ print_arith_command (command->value.Arith->exp);
+ break;
+#endif
+
+#if defined (COND_COMMAND)
+ case cm_cond:
+ print_cond_command (command->value.Cond);
+ break;
+#endif
+
case cm_simple:
print_simple_command (command->value.Simple);
break;
break;
default:
- cprintf ("print_command: bad connector `%d'",
+ cprintf (_("print_command: bad connector `%d'"),
command->value.Connection->connector);
break;
}
print_group_command (command->value.Group);
break;
+ case cm_subshell:
+ cprintf ("( ");
+ skip_this_indent++;
+ make_command_string_internal (command->value.Subshell->command);
+ cprintf (" )");
+ break;
+
default:
- programming_error ("print_command: bad command type `%d'", command->type);
+ command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
break;
}
- if (command->flags & CMD_WANT_SUBSHELL)
- cprintf (" )");
if (command->redirects)
- print_redirection_list (command->redirects);
+ {
+ cprintf (" ");
+ print_redirection_list (command->redirects);
+ }
}
}
_print_word_list (list, separator, pfunc)
WORD_LIST *list;
char *separator;
- VFunction *pfunc;
+ PFUNC *pfunc;
{
WORD_LIST *w;
_print_word_list (list, separator, xprintf);
}
+/* Return a string denoting what our indirection level is. */
+
+char *
+indirection_level_string ()
+{
+ register int i, j;
+ char *ps4;
+ char ps4_firstc[MB_LEN_MAX+1];
+ int ps4_firstc_len, ps4_len;
+
+ indirection_string[0] = '\0';
+ ps4 = get_string_value ("PS4");
+
+ if (ps4 == 0 || *ps4 == '\0')
+ return (indirection_string);
+
+ change_flag ('x', FLAG_OFF);
+ ps4 = decode_prompt_string (ps4);
+ change_flag ('x', FLAG_ON);
+
+ if (ps4 == 0 || *ps4 == '\0')
+ return (indirection_string);
+
+#if defined (HANDLE_MULTIBYTE)
+ ps4_len = strnlen (ps4, MB_CUR_MAX);
+ ps4_firstc_len = MBLEN (ps4, ps4_len);
+ if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
+ {
+ ps4_firstc[0] = ps4[0];
+ ps4_firstc[ps4_firstc_len = 1] = '\0';
+ }
+ else
+ memcpy (ps4_firstc, ps4, ps4_firstc_len);
+#else
+ ps4_firstc[0] = ps4[0];
+ ps4_firstc[ps4_firstc_len = 1] = '\0';
+#endif
+
+ for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
+ {
+ if (ps4_firstc_len == 1)
+ indirection_string[i] = ps4_firstc[0];
+ else
+ memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
+ }
+
+ for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
+ indirection_string[i] = ps4[j];
+
+ indirection_string[i] = '\0';
+ free (ps4);
+ return (indirection_string);
+}
+
+void
+xtrace_print_assignment (name, value, assign_list, xflags)
+ char *name, *value;
+ int assign_list, xflags;
+{
+ char *nval;
+
+ if (xflags)
+ fprintf (stderr, "%s", indirection_level_string ());
+
+ /* VALUE should not be NULL when this is called. */
+ if (*value == '\0' || assign_list)
+ nval = value;
+ else if (sh_contains_shell_metas (value))
+ nval = sh_single_quote (value);
+ else if (ansic_shouldquote (value))
+ nval = ansic_quote (value, 0, (int *)0);
+ else
+ nval = value;
+
+ if (assign_list)
+ fprintf (stderr, "%s=(%s)\n", name, nval);
+ else
+ fprintf (stderr, "%s=%s\n", name, nval);
+
+ if (nval != value)
+ FREE (nval);
+
+ fflush (stderr);
+}
+
/* A function to print the words of a simple command when set -x is on. */
void
-xtrace_print_word_list (list)
+xtrace_print_word_list (list, xtflags)
WORD_LIST *list;
+ int xtflags;
{
WORD_LIST *w;
- char *t;
+ char *t, *x;
+
+ if (xtflags)
+ fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "%s", indirection_level_string ());
for (w = list; w; w = w->next)
{
t = w->word->word;
if (t == 0 || *t == '\0')
- fprintf (stderr, "''%s", w->next ? " " : "");
- else if (contains_shell_metas (t))
- fprintf (stderr, "'%s'%s", t, w->next ? " " : "");
+ fprintf (stderr, "''%s", w->next ? " " : "");
+ else if (sh_contains_shell_metas (t))
+ {
+ x = sh_single_quote (t);
+ fprintf (stderr, "%s%s", x, w->next ? " " : "");
+ free (x);
+ }
+ else if (ansic_shouldquote (t))
+ {
+ x = ansic_quote (t, 0, (int *)0);
+ fprintf (stderr, "%s%s", x, w->next ? " " : "");
+ free (x);
+ }
else
- fprintf (stderr, "%s%s", t, w->next ? " " : "");
+ fprintf (stderr, "%s%s", t, w->next ? " " : "");
}
fprintf (stderr, "\n");
}
_print_word_list (list, separator, cprintf);
}
-static void
-print_for_command (for_command)
+void
+print_for_command_head (for_command)
FOR_COM *for_command;
{
cprintf ("for %s in ", for_command->name->word);
command_print_word_list (for_command->map_list, " ");
+}
+
+void
+xtrace_print_for_command_head (for_command)
+ FOR_COM *for_command;
+{
+ fprintf (stderr, "%s", indirection_level_string ());
+ fprintf (stderr, "for %s in ", for_command->name->word);
+ xtrace_print_word_list (for_command->map_list, 0);
+}
+
+static void
+print_for_command (for_command)
+ FOR_COM *for_command;
+{
+ print_for_command_head (for_command);
+
cprintf (";");
newline ("do\n");
indentation += indentation_amount;
newline ("done");
}
-#if defined (SELECT_COMMAND)
+#if defined (ARITH_FOR_COMMAND)
static void
-print_select_command (select_command)
+print_arith_for_command (arith_for_command)
+ ARITH_FOR_COM *arith_for_command;
+{
+ cprintf ("for ((");
+ command_print_word_list (arith_for_command->init, " ");
+ cprintf ("; ");
+ command_print_word_list (arith_for_command->test, " ");
+ cprintf ("; ");
+ command_print_word_list (arith_for_command->step, " ");
+ cprintf ("))");
+ newline ("do\n");
+ indentation += indentation_amount;
+ make_command_string_internal (arith_for_command->action);
+ semicolon ();
+ indentation -= indentation_amount;
+ newline ("done");
+}
+#endif /* ARITH_FOR_COMMAND */
+
+#if defined (SELECT_COMMAND)
+void
+print_select_command_head (select_command)
SELECT_COM *select_command;
{
cprintf ("select %s in ", select_command->name->word);
command_print_word_list (select_command->map_list, " ");
+}
+
+void
+xtrace_print_select_command_head (select_command)
+ SELECT_COM *select_command;
+{
+ fprintf (stderr, "%s", indirection_level_string ());
+ fprintf (stderr, "select %s in ", select_command->name->word);
+ xtrace_print_word_list (select_command->map_list, 0);
+}
+
+static void
+print_select_command (select_command)
+ SELECT_COM *select_command;
+{
+ print_select_command_head (select_command);
+
cprintf (";");
newline ("do\n");
indentation += indentation_amount;
group_command_nesting--;
}
+void
+print_case_command_head (case_command)
+ CASE_COM *case_command;
+{
+ cprintf ("case %s in ", case_command->word->word);
+}
+
+void
+xtrace_print_case_command_head (case_command)
+ CASE_COM *case_command;
+{
+ fprintf (stderr, "%s", indirection_level_string ());
+ fprintf (stderr, "case %s in\n", case_command->word->word);
+}
+
static void
print_case_command (case_command)
CASE_COM *case_command;
{
- cprintf ("case %s in ", case_command->word->word);
+ print_case_command_head (case_command);
+
if (case_command->clauses)
print_case_clauses (case_command->clauses);
newline ("esac");
newline ("fi");
}
+#if defined (DPAREN_ARITHMETIC)
+void
+print_arith_command (arith_cmd_list)
+ WORD_LIST *arith_cmd_list;
+{
+ cprintf ("((");
+ command_print_word_list (arith_cmd_list, " ");
+ cprintf ("))");
+}
+#endif
+
+#if defined (COND_COMMAND)
+static void
+print_cond_node (cond)
+ COND_COM *cond;
+{
+ if (cond->flags & CMD_INVERT_RETURN)
+ cprintf ("! ");
+
+ if (cond->type == COND_EXPR)
+ {
+ cprintf ("( ");
+ print_cond_node (cond->left);
+ cprintf (" )");
+ }
+ else if (cond->type == COND_AND)
+ {
+ print_cond_node (cond->left);
+ cprintf (" && ");
+ print_cond_node (cond->right);
+ }
+ else if (cond->type == COND_OR)
+ {
+ print_cond_node (cond->left);
+ cprintf (" || ");
+ print_cond_node (cond->right);
+ }
+ else if (cond->type == COND_UNARY)
+ {
+ cprintf ("%s", cond->op->word);
+ cprintf (" ");
+ print_cond_node (cond->left);
+ }
+ else if (cond->type == COND_BINARY)
+ {
+ print_cond_node (cond->left);
+ cprintf (" ");
+ cprintf ("%s", cond->op->word);
+ cprintf (" ");
+ print_cond_node (cond->right);
+ }
+ else if (cond->type == COND_TERM)
+ {
+ cprintf ("%s", cond->op->word); /* need to add quoting here */
+ }
+}
+
+void
+print_cond_command (cond)
+ COND_COM *cond;
+{
+ cprintf ("[[ ");
+ print_cond_node (cond);
+ cprintf (" ]]");
+}
+
+#ifdef DEBUG
+void
+debug_print_cond_command (cond)
+ COND_COM *cond;
+{
+ fprintf (stderr, "DEBUG: ");
+ command_string_index = 0;
+ print_cond_command (cond);
+ fprintf (stderr, "%s\n", the_printed_command);
+}
+#endif
+
+void
+xtrace_print_cond_term (type, invert, op, arg1, arg2)
+ int type, invert;
+ WORD_DESC *op;
+ char *arg1, *arg2;
+{
+ command_string_index = 0;
+ fprintf (stderr, "%s", indirection_level_string ());
+ fprintf (stderr, "[[ ");
+ if (invert)
+ fprintf (stderr, "! ");
+
+ if (type == COND_UNARY)
+ {
+ fprintf (stderr, "%s ", op->word);
+ fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
+ }
+ else if (type == COND_BINARY)
+ {
+ fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
+ fprintf (stderr, " %s ", op->word);
+ fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
+ }
+
+ fprintf (stderr, " ]]\n");
+}
+#endif /* COND_COMMAND */
+
+#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+/* A function to print the words of an arithmetic command when set -x is on. */
+void
+xtrace_print_arith_cmd (list)
+ WORD_LIST *list;
+{
+ WORD_LIST *w;
+
+ fprintf (stderr, "%s", indirection_level_string ());
+ fprintf (stderr, "(( ");
+ for (w = list; w; w = w->next)
+ fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
+ fprintf (stderr, " ))\n");
+}
+#endif
+
void
print_simple_command (simple_command)
SIMPLE_COM *simple_command;
else
hdtail = heredocs = newredir;
}
+ else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
+ {
+ /* Temporarily translate it as the execution code does. */
+ redirects->instruction = r_err_and_out;
+ print_redirection (redirects);
+ redirects->instruction = r_duplicating_output_word;
+ }
else
print_redirection (redirects);
{
cprintf (" ");
for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
- {
+ {
print_redirection (hdtail);
cprintf ("\n");
- }
+ }
dispose_redirects (heredocs);
was_heredoc = 1;
}
cprintf ("%d", redirector);
/* If the here document delimiter is quoted, single-quote it. */
if (redirect->redirectee.filename->flags & W_QUOTED)
- {
- char *x;
- x = single_quote (redirect->here_doc_eof);
+ {
+ char *x;
+ x = sh_single_quote (redirect->here_doc_eof);
cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
- free (x);
- }
+ free (x);
+ }
else
cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
cprintf ("%s%s",
redirect->redirectee.filename->word, redirect->here_doc_eof);
break;
+ case r_reading_string:
+ if (redirector != 0)
+ cprintf ("%d", redirector);
+ if (ansic_shouldquote (redirect->redirectee.filename->word))
+ {
+ char *x;
+ x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
+ cprintf ("<<< %s", x);
+ free (x);
+ }
+ else
+ cprintf ("<<< %s", redirect->redirectee.filename->word);
+ break;
+
case r_duplicating_input:
cprintf ("%d<&%d", redirector, redir_fd);
break;
cprintf ("%d>&%s", redirector, redirectee->word);
break;
+ case r_move_input:
+ cprintf ("%d<&%d-", redirector, redir_fd);
+ break;
+
+ case r_move_output:
+ cprintf ("%d>&%d-", redirector, redir_fd);
+ break;
+
+ case r_move_input_word:
+ cprintf ("%d<&%s-", redirector, redirectee->word);
+ break;
+
+ case r_move_output_word:
+ cprintf ("%d>&%s-", redirector, redirectee->word);
+ break;
+
case r_close_this:
cprintf ("%d>&-", redirector);
break;
print_function_def (func)
FUNCTION_DEF *func;
{
+ COMMAND *cmdcopy;
+ REDIRECT *func_redirects;
+
+ func_redirects = NULL;
cprintf ("function %s () \n", func->name->word);
add_unwind_protect (reset_locals, 0);
inside_function_def++;
indentation += indentation_amount;
- make_command_string_internal (func->command->type == cm_group
- ? func->command->value.Group->command
- : func->command);
+ cmdcopy = copy_command (func->command);
+ if (cmdcopy->type == cm_group)
+ {
+ func_redirects = cmdcopy->redirects;
+ cmdcopy->redirects = (REDIRECT *)NULL;
+ }
+ make_command_string_internal (cmdcopy->type == cm_group
+ ? cmdcopy->value.Group->command
+ : cmdcopy);
remove_unwind_protect ();
indentation -= indentation_amount;
inside_function_def--;
- newline ("}");
+ if (func_redirects)
+ { /* { */
+ newline ("} ");
+ print_redirection_list (func_redirects);
+ cmdcopy->redirects = func_redirects;
+ }
+ else
+ newline ("}");
+
+ dispose_command (cmdcopy);
}
/* Return the string representation of the named function.
{
char *result;
int old_indent, old_amount;
+ COMMAND *cmdcopy;
+ REDIRECT *func_redirects;
old_indent = indentation;
old_amount = indentation_amount;
cprintf (multi_line ? "{ \n" : "{ ");
- make_command_string_internal (command->type == cm_group
- ? command->value.Group->command
- : command);
+ cmdcopy = copy_command (command);
+ /* Take any redirections specified in the function definition (which should
+ apply to the function as a whole) and save them for printing later. */
+ func_redirects = (REDIRECT *)NULL;
+ if (cmdcopy->type == cm_group)
+ {
+ func_redirects = cmdcopy->redirects;
+ cmdcopy->redirects = (REDIRECT *)NULL;
+ }
+ make_command_string_internal (cmdcopy->type == cm_group
+ ? cmdcopy->value.Group->command
+ : cmdcopy);
indentation = old_indent;
indentation_amount = old_amount;
inside_function_def--;
- newline ("}");
+ if (func_redirects)
+ { /* { */
+ newline ("} ");
+ print_redirection_list (func_redirects);
+ cmdcopy->redirects = func_redirects;
+ }
+ else
+ newline ("}");
result = the_printed_command;
}
#else
if (result[2] == '\n') /* XXX -- experimental */
- strcpy (result + 2, result + 3);
+ strcpy (result + 2, result + 3);
#endif
}
+ dispose_command (cmdcopy);
+
return (result);
}
static void
semicolon ()
{
- if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
+ if (command_string_index > 0 &&
+ (the_printed_command[command_string_index - 1] == '&' ||
+ the_printed_command[command_string_index - 1] == '\n'))
return;
cprintf (";");
}
-#if !defined (USE_VARARGS)
-/* How to make the string. */
-static void
-cprintf (format, arg1, arg2)
- char *format, *arg1, *arg2;
-{
- register char *s;
- char char_arg[2], *argp, *args[2];
- int arg_len, c, arg_index;
-
- args[arg_index = 0] = arg1;
- args[1] = arg2;
-
- arg_len = strlen (format);
- the_printed_command_resize (arg_len + 1);
-
- char_arg[1] = '\0';
- s = format;
- while (s && *s)
- {
- int free_argp = 0;
- c = *s++;
- if (c != '%' || !*s)
- {
- argp = s;
- arg_len = 1;
- }
- else
- {
- c = *s++;
- switch (c)
- {
- case '%':
- char_arg[0] = c;
- argp = char_arg;
- arg_len = 1;
- break;
-
- case 's':
- argp = (char *)args[arg_index++];
- arg_len = strlen (argp);
- break;
-
- case 'd':
- argp = itos (pointer_to_int (args[arg_index]));
- arg_index++;
- arg_len = strlen (argp);
- free_argp = 1;
- break;
-
- case 'c':
- char_arg[0] = pointer_to_int (args[arg_index]);
- arg_index++;
- argp = char_arg;
- arg_len = 1;
- break;
-
- default:
- programming_error ("cprintf: bad `%%' argument (%c)", c);
- }
- }
- if (argp)
- {
- the_printed_command_resize (arg_len + 1);
- FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
- command_string_index += arg_len;
- if (free_argp)
- free (argp);
- }
- }
-
- the_printed_command[command_string_index] = '\0';
-}
-
-#else /* We have support for varargs. */
-
/* How to make the string. */
static void
#if defined (PREFER_STDARG)
-cprintf (char *control, ...)
+cprintf (const char *control, ...)
#else
cprintf (control, va_alist)
- char *control;
+ const char *control;
va_dcl
#endif
{
- register char *s;
- char char_arg[2], *argp;
+ register const char *s;
+ char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
int digit_arg, arg_len, c;
va_list args;
-#if defined (PREFER_STDARG)
- va_start (args, control);
-#else
- va_start (args);
-#endif
+ SH_VA_START (args, control);
arg_len = strlen (control);
the_printed_command_resize (arg_len + 1);
s = control;
while (s && *s)
{
- int free_argp;
- free_argp = 0;
c = *s++;
argp = (char *)NULL;
if (c != '%' || !*s)
{
- argp = s - 1;
+ char_arg[0] = c;
+ argp = char_arg;
arg_len = 1;
}
else
break;
case 'd':
+ /* Represent an out-of-range file descriptor with an out-of-range
+ integer value. We can do this because the only use of `%d' in
+ the calls to cprintf is to output a file descriptor number for
+ a redirection. */
digit_arg = va_arg (args, int);
- argp = itos (digit_arg);
+ if (digit_arg < 0)
+ {
+ sprintf (intbuf, "%u", (unsigned)-1);
+ argp = intbuf;
+ }
+ else
+ argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
arg_len = strlen (argp);
- free_argp = 1;
break;
case 'c':
break;
default:
- programming_error ("cprintf: bad `%%' argument (%c)", c);
+ programming_error (_("cprintf: `%c': invalid format character"), c);
/*NOTREACHED*/
}
}
the_printed_command_resize (arg_len + 1);
FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
command_string_index += arg_len;
- if (free_argp)
- free (argp);
}
}
the_printed_command[command_string_index] = '\0';
}
-#endif /* HAVE_VARARGS_H */
/* Ensure that there is enough space to stuff LENGTH characters into
THE_PRINTED_COMMAND. */
if (the_printed_command == 0)
{
the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
- the_printed_command = xmalloc (the_printed_command_size);
+ the_printed_command = (char *)xmalloc (the_printed_command_size);
command_string_index = 0;
}
else if ((command_string_index + length) >= the_printed_command_size)
{
int new;
new = command_string_index + length + 1;
-#if 1
+
/* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
-#else
- new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
- new -= new % PRINTED_COMMAND_GROW_SIZE;
-#endif
the_printed_command_size = new;
- the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
+
+ the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
}
}
-#if defined (HAVE_VFPRINTF)
+#if defined (HAVE_VPRINTF)
+/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
+ also available.'' */
static void
#if defined (PREFER_STDARG)
{
va_list args;
-#if defined (PREFER_STDARG)
- va_start (args, format);
-#else
- va_start (args);
-#endif
+ SH_VA_START (args, format);
vfprintf (stdout, format, args);
va_end (args);
static void
xprintf (format, arg1, arg2, arg3, arg4, arg5)
- char *format;
+ const char *format;
{
printf (format, arg1, arg2, arg3, arg4, arg5);
}
-#endif /* !HAVE_VFPRINTF */
+#endif /* !HAVE_VPRINTF */