aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/builtin.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2015-09-21 11:24:49 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2015-09-22 18:08:00 -0700
commitc1bd3b5824027f23b41bbac77c5e28f856c5dc18 (patch)
treef406ad2f859df99f65c059f8c4019d5a2db1e459 /src/builtin.cpp
parentfb615843b329b4d3c303b9cebe2af134a52b5bfd (diff)
Eliminate global variables associated with builtin IO
This change eliminates global variables like stdout_buffer. Instead we wrap up the IO information into a new struct io_streams_t, and thread that through every builtin. This makes the intent clearer, gives us a place to hang new IO data, and eliminates the ugly global state management like builtin_push_io.
Diffstat (limited to 'src/builtin.cpp')
-rw-r--r--src/builtin.cpp760
1 files changed, 314 insertions, 446 deletions
diff --git a/src/builtin.cpp b/src/builtin.cpp
index e4f14160..a3e5eedb 100644
--- a/src/builtin.cpp
+++ b/src/builtin.cpp
@@ -92,7 +92,7 @@ struct builtin_data_t
/**
Function pointer tothe builtin implementation
*/
- int (*func)(parser_t &parser, wchar_t **argv);
+ int (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv);
/**
Description of what the builtin does
*/
@@ -112,54 +112,6 @@ bool builtin_data_t::operator<(const builtin_data_t *other) const
return wcscmp(this->name, other->name) < 0;
}
-int builtin_out_redirect;
-int builtin_err_redirect;
-
-/* Buffers for storing the output of builtin functions */
-wcstring stdout_buffer, stderr_buffer;
-
-const wcstring &get_stdout_buffer()
-{
- ASSERT_IS_MAIN_THREAD();
- return stdout_buffer;
-}
-
-const wcstring &get_stderr_buffer()
-{
- ASSERT_IS_MAIN_THREAD();
- return stderr_buffer;
-}
-
-void builtin_show_error(const wcstring &err)
-{
- ASSERT_IS_MAIN_THREAD();
- stderr_buffer.append(err);
-}
-
-/**
- Stack containing builtin I/O for recursive builtin calls.
-*/
-struct io_stack_elem_t
-{
- int in;
- wcstring out;
- wcstring err;
-};
-static std::stack<io_stack_elem_t, std::vector<io_stack_elem_t> > io_stack;
-
-/**
- The file from which builtin functions should attempt to read, use
- instead of stdin.
-*/
-int builtin_stdin;
-
-/**
- The underlying IO redirections behind the current builtin. This
- should normally not be used - sb_out and friends are already
- configured to handle everything.
-*/
-static const io_chain_t *real_io;
-
/**
Counts the number of non null pointers in the specified array
*/
@@ -175,23 +127,23 @@ int builtin_count_args(const wchar_t * const * argv)
/**
This function works like wperror, but it prints its result into
- the sb_err string instead of to stderr. Used by the builtin
+ the streams.err string instead of to stderr. Used by the builtin
commands.
*/
-static void builtin_wperror(const wchar_t *s)
+static void builtin_wperror(const wchar_t *s, io_streams_t &streams)
{
- if (s != 0)
+ char *err = strerror(errno);
+ if (s != NULL)
{
- stderr_buffer.append(s);
- stderr_buffer.append(L": ");
+ streams.err.append(s);
+ streams.err.append(L": ");
}
- char *err = strerror(errno);
- if (err)
+ if (err != NULL)
{
const wcstring werr = str2wcstring(err);
- stderr_buffer.append(werr);
- stderr_buffer.push_back(L'\n');
+ streams.err.append(werr);
+ streams.err.push_back(L'\n');
}
}
@@ -208,7 +160,7 @@ static int count_char(const wchar_t *str, wchar_t c)
return res;
}
-wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
+wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name)
{
/* This won't ever work if no_exec is set */
if (no_exec)
@@ -218,7 +170,7 @@ wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
wcstring out;
const wcstring name_esc = escape_string(name, 1);
wcstring cmd = format_string(L"__fish_print_help %ls", name_esc.c_str());
- if (!builtin_out_redirect && isatty(1))
+ if (!streams.out_is_redirected && isatty(STDOUT_FILENO))
{
// since we're using a subshell, __fish_print_help can't tell we're in
// a terminal. Tell it ourselves.
@@ -247,70 +199,71 @@ wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
*/
-void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b)
+void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, output_stream_t &b)
{
- if (&b == &stderr_buffer)
+ bool is_stderr = (&b == &streams.err);
+ if (is_stderr)
{
- stderr_buffer.append(parser.current_line());
+ b.append(parser.current_line());
}
-
- const wcstring h = builtin_help_get(parser, cmd);
-
+
+ const wcstring h = builtin_help_get(parser, streams, cmd);
+
if (!h.size())
return;
-
+
wchar_t *str = wcsdup(h.c_str());
if (str)
{
bool is_short = false;
- if (&b == &stderr_buffer)
+ if (is_stderr)
{
-
+
/*
- Interactive mode help to screen - only print synopsis if
- the rest won't fit
- */
-
+ Interactive mode help to screen - only print synopsis if
+ the rest won't fit
+ */
+
int screen_height, lines;
-
+
screen_height = common_get_height();
lines = count_char(str, L'\n');
- if (!get_is_interactive() || (lines > 2*screen_height/3))
+ if (! get_is_interactive() || (lines > 2*screen_height/3))
{
wchar_t *pos;
int cut=0;
int i;
-
+
is_short = true;
-
+
/*
- First move down 4 lines
- */
-
+ First move down 4 lines
+ */
+
pos = str;
for (i=0; (i<4) && pos && *pos; i++)
{
pos = wcschr(pos+1, L'\n');
}
-
+
if (pos && *pos)
{
-
+
/*
- Then find the next empty line
- */
+ Then find the next empty line
+ */
for (; *pos; pos++)
{
if (*pos == L'\n')
{
wchar_t *pos2;
int is_empty = 1;
-
+
for (pos2 = pos+1; *pos2; pos2++)
{
if (*pos2 == L'\n')
break;
-
+
if (*pos2 != L'\t' && *pos2 !=L' ')
{
is_empty = 0;
@@ -320,8 +273,8 @@ void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b)
if (is_empty)
{
/*
- And cut it
- */
+ And cut it
+ */
*(pos2+1)=L'\0';
cut = 1;
break;
@@ -329,46 +282,47 @@ void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b)
}
}
}
-
+
/*
- We did not find a good place to cut message to
- shorten it - so we make sure we don't print
- anything.
- */
+ We did not find a good place to cut message to
+ shorten it - so we make sure we don't print
+ anything.
+ */
if (!cut)
{
*str = 0;
}
-
+
}
}
-
+
b.append(str);
if (is_short)
{
- append_format(b, _(L"%ls: Type 'help %ls' for related documentation\n\n"), cmd, cmd);
+ b.append_format(_(L"%ls: Type 'help %ls' for related documentation\n\n"), cmd, cmd);
}
-
+
free(str);
}
}
+
/**
Perform error reporting for encounter with unknown option
*/
-static void builtin_unknown_option(parser_t &parser, const wchar_t *cmd, const wchar_t *opt)
+static void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt)
{
- append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, cmd, opt);
- builtin_print_help(parser, cmd, stderr_buffer);
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, opt);
+ builtin_print_help(parser, streams, cmd, streams.err);
}
/**
Perform error reporting for encounter with missing argument
*/
-static void builtin_missing_argument(parser_t &parser, const wchar_t *cmd, const wchar_t *opt)
+static void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt)
{
- append_format(stderr_buffer, BUILTIN_ERR_MISSING, cmd, opt);
- builtin_print_help(parser, cmd, stderr_buffer);
+ streams.err.append_format(BUILTIN_ERR_MISSING, cmd, opt);
+ builtin_print_help(parser, streams, cmd, streams.err);
}
/*
@@ -401,16 +355,16 @@ static void builtin_missing_argument(parser_t &parser, const wchar_t *cmd, const
#include "builtin_printf.cpp"
/* builtin_test lives in builtin_test.cpp */
-int builtin_test(parser_t &parser, wchar_t **argv);
+int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv);
/* builtin_string lives in builtin_string.cpp */
-int builtin_string(parser_t &parser, wchar_t **argv);
+int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv);
/**
List a single key binding.
Returns false if no binding with that sequence and mode exists.
*/
-static bool builtin_bind_list_one(const wcstring& seq, const wcstring& bind_mode)
+static bool builtin_bind_list_one(const wcstring &seq, const wcstring &bind_mode, io_streams_t &streams)
{
std::vector<wcstring> ecmds;
wcstring sets_mode;
@@ -420,20 +374,20 @@ static bool builtin_bind_list_one(const wcstring& seq, const wcstring& bind_mode
return false;
}
- stdout_buffer.append(L"bind");
+ streams.out.append(L"bind");
// Append the mode flags if applicable
if (bind_mode != DEFAULT_BIND_MODE)
{
const wcstring emode = escape_string(bind_mode, ESCAPE_ALL);
- stdout_buffer.append(L" -M ");
- stdout_buffer.append(emode);
+ streams.out.append(L" -M ");
+ streams.out.append(emode);
}
if (sets_mode != bind_mode)
{
const wcstring esets_mode = escape_string(sets_mode, ESCAPE_ALL);
- stdout_buffer.append(L" -m ");
- stdout_buffer.append(esets_mode);
+ streams.out.append(L" -m ");
+ streams.out.append(esets_mode);
}
// Append the name
@@ -441,13 +395,13 @@ static bool builtin_bind_list_one(const wcstring& seq, const wcstring& bind_mode
if (input_terminfo_get_name(seq, &tname))
{
// Note that we show -k here because we have an input key name
- append_format(stdout_buffer, L" -k %ls", tname.c_str());
+ streams.out.append_format( L" -k %ls", tname.c_str());
}
else
{
// No key name, so no -k; we show the escape sequence directly
const wcstring eseq = escape_string(seq, ESCAPE_ALL);
- append_format(stdout_buffer, L" %ls", eseq.c_str());
+ streams.out.append_format( L" %ls", eseq.c_str());
}
// Now show the list of commands
@@ -455,10 +409,10 @@ static bool builtin_bind_list_one(const wcstring& seq, const wcstring& bind_mode
{
const wcstring &ecmd = ecmds.at(i);
const wcstring escaped_ecmd = escape_string(ecmd, ESCAPE_ALL);
- stdout_buffer.push_back(' ');
- stdout_buffer.append(escaped_ecmd);
+ streams.out.push_back(' ');
+ streams.out.append(escaped_ecmd);
}
- stdout_buffer.push_back(L'\n');
+ streams.out.push_back(L'\n');
return true;
}
@@ -466,7 +420,7 @@ static bool builtin_bind_list_one(const wcstring& seq, const wcstring& bind_mode
/**
List all current key bindings
*/
-static void builtin_bind_list(const wchar_t *bind_mode)
+static void builtin_bind_list(const wchar_t *bind_mode, io_streams_t &streams)
{
const std::vector<input_mapping_name_t> lst = input_mapping_get_names();
@@ -479,7 +433,7 @@ static void builtin_bind_list(const wchar_t *bind_mode)
continue;
}
- builtin_bind_list_one(it->seq, it->mode);
+ builtin_bind_list_one(it->seq, it->mode, streams);
}
}
@@ -490,14 +444,14 @@ static void builtin_bind_list(const wchar_t *bind_mode)
printed. If not set, only ones that are defined for this terminal
are printed.
*/
-static void builtin_bind_key_names(int all)
+static void builtin_bind_key_names(int all, io_streams_t &streams)
{
const wcstring_list_t names = input_terminfo_get_names(!all);
for (size_t i=0; i<names.size(); i++)
{
const wcstring &name = names.at(i);
- append_format(stdout_buffer, L"%ls\n", name.c_str());
+ streams.out.append_format( L"%ls\n", name.c_str());
}
}
@@ -505,19 +459,19 @@ static void builtin_bind_key_names(int all)
Print all the special key binding functions to string buffer used for standard output.
*/
-static void builtin_bind_function_names()
+static void builtin_bind_function_names(io_streams_t &streams)
{
wcstring_list_t names = input_function_get_names();
for (size_t i=0; i<names.size(); i++)
{
const wchar_t *seq = names.at(i).c_str();
- append_format(stdout_buffer, L"%ls\n", seq);
+ streams.out.append_format( L"%ls\n", seq);
}
}
// Wraps input_terminfo_get_sequence(), appending the correct error messages as needed.
-static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq)
+static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq, io_streams_t &streams)
{
if (input_terminfo_get_sequence(seq, out_seq))
{
@@ -528,19 +482,19 @@ static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq)
{
case ENOENT:
{
- append_format(stderr_buffer, _(L"%ls: No key with name '%ls' found\n"), L"bind", eseq.c_str());
+ streams.err.append_format(_(L"%ls: No key with name '%ls' found\n"), L"bind", eseq.c_str());
break;
}
case EILSEQ:
{
- append_format(stderr_buffer, _(L"%ls: Key with name '%ls' does not have any mapping\n"), L"bind", eseq.c_str());
+ streams.err.append_format(_(L"%ls: Key with name '%ls' does not have any mapping\n"), L"bind", eseq.c_str());
break;
}
default:
{
- append_format(stderr_buffer, _(L"%ls: Unknown error trying to bind to key named '%ls'\n"), L"bind", eseq.c_str());
+ streams.err.append_format(_(L"%ls: Unknown error trying to bind to key named '%ls'\n"), L"bind", eseq.c_str());
break;
}
}
@@ -550,14 +504,15 @@ static int get_terminfo_sequence(const wchar_t *seq, wcstring *out_seq)
/**
Add specified key binding.
*/
-static int builtin_bind_add(const wchar_t *seq, const wchar_t **cmds, size_t cmds_len,
- const wchar_t *mode, const wchar_t *sets_mode, int terminfo)
+static int builtin_bind_add(const wchar_t *seq, const wchar_t * const *cmds, size_t cmds_len,
+ const wchar_t *mode, const wchar_t *sets_mode, int terminfo,
+ io_streams_t &streams)
{
if (terminfo)
{
wcstring seq2;
- if (get_terminfo_sequence(seq, &seq2))
+ if (get_terminfo_sequence(seq, &seq2, streams))
{
input_mapping_add(seq2.c_str(), cmds, cmds_len, mode, sets_mode);
}
@@ -583,7 +538,7 @@ static int builtin_bind_add(const wchar_t *seq, const wchar_t **cmds, size_t cmd
\param all if specified, _all_ key bindings will be erased
\param mode if specified, only bindings from that mode will be erased. If not given and \c all is \c false, \c DEFAULT_BIND_MODE will be used.
*/
-static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo)
+static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo, io_streams_t &streams)
{
if (all)
{
@@ -611,7 +566,7 @@ static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int u
if (use_terminfo)
{
wcstring seq2;
- if (get_terminfo_sequence(*seq++, &seq2))
+ if (get_terminfo_sequence(*seq++, &seq2, streams))
{
input_mapping_erase(seq2, mode);
}
@@ -634,7 +589,7 @@ static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int u
/**
The bind builtin, used for setting character sequences
*/
-static int builtin_bind(parser_t &parser, wchar_t **argv)
+static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
enum
@@ -689,11 +644,10 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
@@ -706,7 +660,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
break;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 'k':
@@ -732,7 +686,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
@@ -752,7 +706,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
case BIND_ERASE:
{
- if (builtin_bind_erase(&argv[w.woptind], all, bind_mode_given ? bind_mode : NULL, use_terminfo))
+ if (builtin_bind_erase(&argv[w.woptind], all, bind_mode_given ? bind_mode : NULL, use_terminfo, streams))
{
res = STATUS_BUILTIN_ERROR;
}
@@ -765,7 +719,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
{
case 0:
{
- builtin_bind_list(bind_mode_given ? bind_mode : NULL);
+ builtin_bind_list(bind_mode_given ? bind_mode : NULL, streams);
break;
}
@@ -774,7 +728,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
wcstring seq;
if (use_terminfo)
{
- if (!get_terminfo_sequence(argv[w.woptind], &seq))
+ if (!get_terminfo_sequence(argv[w.woptind], &seq, streams))
{
res = STATUS_BUILTIN_ERROR;
// get_terminfo_sequence already printed the error
@@ -785,17 +739,17 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
{
seq = argv[w.woptind];
}
- if (!builtin_bind_list_one(seq, bind_mode))
+ if (!builtin_bind_list_one(seq, bind_mode, streams))
{
res = STATUS_BUILTIN_ERROR;
wcstring eseq = escape_string(argv[w.woptind], 0);
if (use_terminfo)
{
- append_format(stderr_buffer, _(L"%ls: No binding found for key '%ls'\n"), argv[0], eseq.c_str());
+ streams.err.append_format(_(L"%ls: No binding found for key '%ls'\n"), argv[0], eseq.c_str());
}
else
{
- append_format(stderr_buffer, _(L"%ls: No binding found for sequence '%ls'\n"), argv[0], eseq.c_str());
+ streams.err.append_format(_(L"%ls: No binding found for sequence '%ls'\n"), argv[0], eseq.c_str());
}
}
break;
@@ -803,7 +757,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
default:
{
- if (builtin_bind_add(argv[w.woptind], (const wchar_t **)argv + (w.woptind + 1), argc - (w.woptind + 1), bind_mode, sets_bind_mode, use_terminfo))
+ if (builtin_bind_add(argv[w.woptind], argv + (w.woptind + 1), argc - (w.woptind + 1), bind_mode, sets_bind_mode, use_terminfo, streams))
{
res = STATUS_BUILTIN_ERROR;
}
@@ -816,14 +770,14 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
case BIND_KEY_NAMES:
{
- builtin_bind_key_names(all);
+ builtin_bind_key_names(all, streams);
break;
}
case BIND_FUNCTION_NAMES:
{
- builtin_bind_function_names();
+ builtin_bind_function_names(streams);
break;
}
@@ -831,7 +785,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
default:
{
res = STATUS_BUILTIN_ERROR;
- append_format(stderr_buffer, _(L"%ls: Invalid state\n"), argv[0]);
+ streams.err.append_format(_(L"%ls: Invalid state\n"), argv[0]);
break;
}
}
@@ -843,7 +797,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
/**
The block builtin, used for temporarily blocking events
*/
-static int builtin_block(parser_t &parser, wchar_t **argv)
+static int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
enum
@@ -902,15 +856,14 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 'g':
@@ -926,7 +879,7 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -937,13 +890,13 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
{
if (scope != UNSET)
{
- append_format(stderr_buffer, _(L"%ls: Can not specify scope when removing block\n"), argv[0]);
+ streams.err.append_format(_(L"%ls: Can not specify scope when removing block\n"), argv[0]);
return STATUS_BUILTIN_ERROR;
}
if (parser.global_event_blocks.empty())
{
- append_format(stderr_buffer, _(L"%ls: No blocks defined\n"), argv[0]);
+ streams.err.append_format(_(L"%ls: No blocks defined\n"), argv[0]);
return STATUS_BUILTIN_ERROR;
}
parser.global_event_blocks.pop_front();
@@ -1000,7 +953,7 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
additional operational modes, such as printing a list of all
builtins, printing help, etc.
*/
-static int builtin_builtin(parser_t &parser, wchar_t **argv)
+static int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int argc=builtin_count_args(argv);
int list=0;
@@ -1040,16 +993,15 @@ static int builtin_builtin(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 'n':
@@ -1057,7 +1009,7 @@ static int builtin_builtin(parser_t &parser, wchar_t **argv)
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -1073,8 +1025,8 @@ static int builtin_builtin(parser_t &parser, wchar_t **argv)
{
const wchar_t *el = names.at(i).c_str();
- stdout_buffer.append(el);
- stdout_buffer.append(L"\n");
+ streams.out.append(el);
+ streams.out.append(L"\n");
}
}
return STATUS_BUILTIN_OK;
@@ -1083,7 +1035,7 @@ static int builtin_builtin(parser_t &parser, wchar_t **argv)
/**
Implementation of the builtin emit command, used to create events.
*/
-static int builtin_emit(parser_t &parser, wchar_t **argv)
+static int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
int argc=builtin_count_args(argv);
@@ -1118,19 +1070,18 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -1139,7 +1090,7 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
if (!argv[w.woptind])
{
- append_format(stderr_buffer, L"%ls: expected event name\n", argv[0]);
+ streams.err.append_format(L"%ls: expected event name\n", argv[0]);
return STATUS_BUILTIN_ERROR;
}
const wchar_t *eventname = argv[w.woptind];
@@ -1154,7 +1105,7 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
Implementation of the builtin 'command'. Actual command running is handled by
the parser, this just processes the flags.
*/
-static int builtin_command(parser_t &parser, wchar_t **argv)
+static int builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
int argc=builtin_count_args(argv);
@@ -1187,15 +1138,14 @@ static int builtin_command(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 's':
@@ -1204,7 +1154,7 @@ static int builtin_command(parser_t &parser, wchar_t **argv)
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -1213,7 +1163,7 @@ static int builtin_command(parser_t &parser, wchar_t **argv)
if (!print_path)
{
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_ERROR;
}
@@ -1225,7 +1175,7 @@ static int builtin_command(parser_t &parser, wchar_t **argv)
wcstring path;
if (path_get_path(command_name, &path))
{
- append_format(stdout_buffer, L"%ls\n", path.c_str());
+ streams.out.append_format( L"%ls\n", path.c_str());
++found;
}
}
@@ -1237,7 +1187,7 @@ static int builtin_command(parser_t &parser, wchar_t **argv)
only a placeholder that prints the help message. Useful for
commands that live in the parser.
*/
-static int builtin_generic(parser_t &parser, wchar_t **argv)
+static int builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
int argc=builtin_count_args(argv);
@@ -1245,7 +1195,7 @@ static int builtin_generic(parser_t &parser, wchar_t **argv)
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_ERROR;
}
@@ -1273,19 +1223,18 @@ static int builtin_generic(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -1295,12 +1244,12 @@ static int builtin_generic(parser_t &parser, wchar_t **argv)
}
/**
- Output a definition of the specified function to the specified
- string. Used by the functions builtin.
+ Return a definition of the specified function. Used by the functions builtin.
*/
-static void functions_def(const wcstring &name, wcstring &out)
+static wcstring functions_def(const wcstring &name)
{
- CHECK(! name.empty(),);
+ CHECK(! name.empty(), L"");
+ wcstring out;
wcstring desc, def;
function_get_desc(name, &desc);
@@ -1426,13 +1375,14 @@ static void functions_def(const wcstring &name, wcstring &out)
out.push_back(L'\n');
}
out.append(L"end\n");
+ return out;
}
/**
The functions builtin, used for listing and erasing functions.
*/
-static int builtin_functions(parser_t &parser, wchar_t **argv)
+static int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
int i;
@@ -1500,11 +1450,10 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
@@ -1526,7 +1475,7 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
break;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 'q':
@@ -1538,7 +1487,7 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -1550,11 +1499,10 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
*/
if ((erase + (!!desc) + list + query + copy) > 1)
{
- append_format(stderr_buffer,
- _(L"%ls: Invalid combination of options\n"),
+ streams.err.append_format(_(L"%ls: Invalid combination of options\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -1572,22 +1520,20 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
if (argc-w.woptind != 1)
{
- append_format(stderr_buffer,
- _(L"%ls: Expected exactly one function name\n"),
+ streams.err.append_format(_(L"%ls: Expected exactly one function name\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
func = argv[w.woptind];
if (!function_exists(func))
{
- append_format(stderr_buffer,
- _(L"%ls: Function '%ls' does not exist\n"),
+ streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"),
argv[0],
func);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -1598,7 +1544,7 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
}
else if (list || (argc==w.woptind))
{
- int is_screen = !builtin_out_redirect && isatty(1);
+ int is_screen = !streams.out_is_redirected && isatty(STDOUT_FILENO);
size_t i;
wcstring_list_t names = function_get_names(show_hidden);
std::sort(names.begin(), names.end());
@@ -1612,14 +1558,14 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
buff.append(L", ");
}
- write_screen(buff, stdout_buffer);
+ streams.out.append(reformat_for_screen(buff));
}
else
{
for (i=0; i<names.size(); i++)
{
- stdout_buffer.append(names.at(i).c_str());
- stdout_buffer.append(L"\n");
+ streams.out.append(names.at(i).c_str());
+ streams.out.append(L"\n");
}
}
@@ -1632,10 +1578,9 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
if (argc-w.woptind != 2)
{
- append_format(stderr_buffer,
- _(L"%ls: Expected exactly two names (current function name, and new function name)\n"),
+ streams.err.append_format(_(L"%ls: Expected exactly two names (current function name, and new function name)\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -1644,34 +1589,31 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
if (!function_exists(current_func))
{
- append_format(stderr_buffer,
- _(L"%ls: Function '%ls' does not exist\n"),
+ streams.err.append_format(_(L"%ls: Function '%ls' does not exist\n"),
argv[0],
current_func.c_str());
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
if ((wcsfuncname(new_func) != 0) || parser_keywords_is_reserved(new_func))
{
- append_format(stderr_buffer,
- _(L"%ls: Illegal function name '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Illegal function name '%ls'\n"),
argv[0],
new_func.c_str());
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
// keep things simple: don't allow existing names to be copy targets.
if (function_exists(new_func))
{
- append_format(stderr_buffer,
- _(L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n"),
argv[0],
new_func.c_str(),
current_func.c_str());
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -1690,9 +1632,9 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
if (!query)
{
if (i != w.woptind)
- stdout_buffer.append(L"\n");
+ streams.out.append(L"\n");
- functions_def(argv[i], stdout_buffer);
+ streams.out.append(functions_def(argv[i]));
}
}
}
@@ -1812,7 +1754,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
We also support a new option -s to mean "no spaces"
*/
-static int builtin_echo(parser_t &parser, wchar_t **argv)
+static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
/* Skip first arg */
if (! *argv++)
@@ -1878,7 +1820,7 @@ static int builtin_echo(parser_t &parser, wchar_t **argv)
{
if (print_spaces && idx > 0)
{
- stdout_buffer.push_back(' ');
+ streams.out.push_back(' ');
}
const wchar_t *str = args_to_echo[idx];
@@ -1887,7 +1829,7 @@ static int builtin_echo(parser_t &parser, wchar_t **argv)
if (! interpret_special_chars || str[j] != L'\\')
{
/* Not an escape */
- stdout_buffer.push_back(str[j]);
+ streams.out.push_back(str[j]);
}
else
{
@@ -1953,20 +1895,20 @@ static int builtin_echo(parser_t &parser, wchar_t **argv)
if (continue_output)
{
- stdout_buffer.push_back(wc);
+ streams.out.push_back(wc);
}
}
}
}
if (print_newline && continue_output)
{
- stdout_buffer.push_back('\n');
+ streams.out.push_back('\n');
}
return STATUS_BUILTIN_OK;
}
/** The pwd builtin. We don't respect -P to resolve symbolic links because we try to always resolve them. */
-static int builtin_pwd(parser_t &parser, wchar_t **argv)
+static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wchar_t dir_path[4096];
wchar_t *res = wgetcwd(dir_path, 4096);
@@ -1976,14 +1918,14 @@ static int builtin_pwd(parser_t &parser, wchar_t **argv)
}
else
{
- stdout_buffer.append(dir_path);
- stdout_buffer.push_back(L'\n');
+ streams.out.append(dir_path);
+ streams.out.push_back(L'\n');
return STATUS_BUILTIN_OK;
}
}
/** Adds a function to the function set. It calls into function.cpp to perform any heavy lifting. */
-int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstring &contents, int definition_line_offset, wcstring *out_err)
+int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, const wcstring &contents, int definition_line_offset, wcstring *out_err)
{
wgetopter_t w;
assert(out_err != NULL);
@@ -2209,7 +2151,7 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
}
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 1:
@@ -2218,7 +2160,7 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
res = 1;
break;
@@ -2340,7 +2282,7 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
/**
The random builtin. For generating random numbers.
*/
-static int builtin_random(parser_t &parser, wchar_t **argv)
+static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
static int seeded=0;
static struct drand48_data seed_buffer;
@@ -2379,20 +2321,19 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
break;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -2413,7 +2354,7 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
}
lrand48_r(&seed_buffer, &res);
- append_format(stdout_buffer, L"%ld\n", labs(res%32767));
+ streams.out.append_format( L"%ld\n", labs(res%32767));
break;
}
@@ -2426,8 +2367,7 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
foo = wcstol(argv[w.woptind], &end, 10);
if (errno || *end)
{
- append_format(stderr_buffer,
- _(L"%ls: Seed value '%ls' is not a valid number\n"),
+ streams.err.append_format(_(L"%ls: Seed value '%ls' is not a valid number\n"),
argv[0],
argv[w.woptind]);
@@ -2440,11 +2380,10 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
default:
{
- append_format(stderr_buffer,
- _(L"%ls: Expected zero or one argument, got %d\n"),
+ streams.err.append_format(_(L"%ls: Expected zero or one argument, got %d\n"),
argv[0],
argc-w.woptind);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
}
@@ -2455,7 +2394,7 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
/**
The read builtin. Reads from stdin and stores the values in environment variables.
*/
-static int builtin_read(parser_t &parser, wchar_t **argv)
+static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
wcstring buff;
@@ -2554,11 +2493,10 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
@@ -2606,19 +2544,17 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
switch (errno)
{
case ERANGE:
- append_format(stderr_buffer,
- _(L"%ls: Argument '%ls' is out of range\n"),
+ streams.err.append_format( _(L"%ls: Argument '%ls' is out of range\n"),
argv[0],
w.woptarg);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
default:
- append_format(stderr_buffer,
- _(L"%ls: Argument '%ls' must be an integer\n"),
+ streams.err.append_format( _(L"%ls: Argument '%ls' must be an integer\n"),
argv[0],
w.woptarg);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
}
@@ -2637,11 +2573,11 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
break;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case L'?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -2649,29 +2585,27 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
if ((place & ENV_UNEXPORT) && (place & ENV_EXPORT))
{
- append_format(stderr_buffer,
- BUILTIN_ERR_EXPUNEXP,
+ streams.err.append_format(BUILTIN_ERR_EXPUNEXP,
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
if ((place&ENV_LOCAL?1:0) + (place & ENV_GLOBAL?1:0) + (place & ENV_UNIVERSAL?1:0) > 1)
{
- append_format(stderr_buffer,
- BUILTIN_ERR_GLOCAL,
+ streams.err.append_format(BUILTIN_ERR_GLOCAL,
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
if (array && w.woptind+1 != argc)
{
- append_format(stderr_buffer, _(L"%ls: --array option requires a single variable name.\n"), argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ streams.err.append_format(_(L"%ls: --array option requires a single variable name.\n"), argv[0]);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -2685,7 +2619,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
if (!wcslen(argv[i]))
{
- append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0]);
+ streams.err.append_format(BUILTIN_ERR_VARNAME_ZERO, argv[0]);
return STATUS_BUILTIN_ERROR;
}
@@ -2693,8 +2627,8 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
{
if ((!iswalnum(*src)) && (*src != L'_'))
{
- append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *src);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ streams.err.append_format(BUILTIN_ERR_VARCHAR, argv[0], *src);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
}
@@ -2709,7 +2643,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
/*
Check if we should read interactively using \c reader_readline()
*/
- if (isatty(0) && builtin_stdin == 0 && !split_null)
+ if (isatty(0) && streams.stdin_fd == STDIN_FILENO && !split_null)
{
const wchar_t *line;
@@ -2770,7 +2704,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
while (!finished)
{
char b;
- if (read_blocked(builtin_stdin, &b, 1) <= 0)
+ if (read_blocked(streams.stdin_fd, &b, 1) <= 0)
{
eof=1;
break;
@@ -2898,7 +2832,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
/**
The status builtin. Gives various status information on fish.
*/
-static int builtin_status(parser_t &parser, wchar_t **argv)
+static int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
wgetopter_t w;
enum
@@ -2998,11 +2932,10 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
case 0:
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'c':
@@ -3030,7 +2963,7 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
break;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case 'j':
@@ -3042,8 +2975,7 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
job_control_mode = JOB_CONTROL_NONE;
else
{
- append_format(stderr_buffer,
- L"%ls: Invalid job control mode '%ls'\n",
+ streams.err.append_format(L"%ls: Invalid job control mode '%ls'\n",
L"status", w.woptarg);
res = 1;
}
@@ -3056,11 +2988,11 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
case ':':
- builtin_missing_argument(parser, argv[0], argv[w.woptind-1]);
+ builtin_missing_argument(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
@@ -3079,14 +3011,14 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
if (!fn)
fn = _(L"Standard input");
- append_format(stdout_buffer, L"%ls\n", fn);
+ streams.out.append_format( L"%ls\n", fn);
break;
}
case CURRENT_LINE_NUMBER:
{
- append_format(stdout_buffer, L"%d\n", parser.get_lineno());
+ streams.out.append_format( L"%d\n", parser.get_lineno());
break;
}
@@ -3113,22 +3045,21 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
case STACK_TRACE:
{
- parser.stack_trace(0, stdout_buffer);
+ streams.out.append(parser.stack_trace());
break;
}
case NORMAL:
{
if (is_login)
- append_format(stdout_buffer, _(L"This is a login shell\n"));
+ streams.out.append_format( _(L"This is a login shell\n"));
else
- append_format(stdout_buffer, _(L"This is not a login shell\n"));
+ streams.out.append_format( _(L"This is not a login shell\n"));
- append_format(stdout_buffer, _(L"Job control: %ls\n"),
+ streams.out.append_format( _(L"Job control: %ls\n"),
job_control_mode==JOB_CONTROL_INTERACTIVE?_(L"Only on interactive jobs"):
(job_control_mode==JOB_CONTROL_NONE ? _(L"Never") : _(L"Always")));
-
- parser.stack_trace(0, stdout_buffer);
+ streams.out.append(parser.stack_trace());
break;
}
}
@@ -3141,7 +3072,7 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
/**
The exit builtin. Calls reader_exit to exit and returns the value specified.
*/
-static int builtin_exit(parser_t &parser, wchar_t **argv)
+static int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int argc = builtin_count_args(argv);
@@ -3161,11 +3092,10 @@ static int builtin_exit(parser_t &parser, wchar_t **argv)
ec = wcstol(argv[1],&end,10);
if (errno || *end != 0)
{
- append_format(stderr_buffer,
- _(L"%ls: Argument '%ls' must be an integer\n"),
+ streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"),
argv[0],
argv[1]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
break;
@@ -3173,11 +3103,10 @@ static int builtin_exit(parser_t &parser, wchar_t **argv)
default:
{
- append_format(stderr_buffer,
- BUILTIN_ERR_TOO_MANY_ARGUMENTS,
+ streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS,
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -3191,7 +3120,7 @@ static int builtin_exit(parser_t &parser, wchar_t **argv)
or to $HOME if none is specified. The directory can be relative to
any directory in the CDPATH variable.
*/
-static int builtin_cd(parser_t &parser, wchar_t **argv)
+static int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
env_var_t dir_in;
wcstring dir;
@@ -3203,8 +3132,7 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
dir_in = env_get_string(L"HOME");
if (dir_in.missing_or_empty())
{
- append_format(stderr_buffer,
- _(L"%ls: Could not find home directory\n"),
+ streams.err.append_format(_(L"%ls: Could not find home directory\n"),
argv[0]);
}
}
@@ -3223,30 +3151,26 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
{
if (errno == ENOTDIR)
{
- append_format(stderr_buffer,
- _(L"%ls: '%ls' is not a directory\n"),
+ streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"),
argv[0],
dir_in.c_str());
}
else if (errno == ENOENT)
{
- append_format(stderr_buffer,
- _(L"%ls: The directory '%ls' does not exist\n"),
+ streams.err.append_format(_(L"%ls: The directory '%ls' does not exist\n"),
argv[0],
dir_in.c_str());
}
else if (errno == EROTTEN)
{
- append_format(stderr_buffer,
- _(L"%ls: '%ls' is a rotten symlink\n"),
+ streams.err.append_format(_(L"%ls: '%ls' is a rotten symlink\n"),
argv[0],
dir_in.c_str());
}
else
{
- append_format(stderr_buffer,
- _(L"%ls: Unknown error trying to locate directory '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Unknown error trying to locate directory '%ls'\n"),
argv[0],
dir_in.c_str());
@@ -3255,7 +3179,7 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
if (!get_is_interactive())
{
- stderr_buffer.append(parser.current_line());
+ streams.err.append(parser.current_line());
}
res = 1;
@@ -3268,8 +3192,7 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
status = wstat(dir, &buffer);
if (!status && S_ISDIR(buffer.st_mode))
{
- append_format(stderr_buffer,
- _(L"%ls: Permission denied: '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Permission denied: '%ls'\n"),
argv[0],
dir.c_str());
@@ -3277,15 +3200,14 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
else
{
- append_format(stderr_buffer,
- _(L"%ls: '%ls' is not a directory\n"),
+ streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"),
argv[0],
dir.c_str());
}
if (!get_is_interactive())
{
- stderr_buffer.append(parser.current_line());
+ streams.err.append(parser.current_line());
}
res = 1;
@@ -3293,7 +3215,7 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
else if (!env_set_pwd())
{
res=1;
- append_format(stderr_buffer, _(L"%ls: Could not set PWD variable\n"), argv[0]);
+ streams.err.append_format(_(L"%ls: Could not set PWD variable\n"), argv[0]);
}
return res;
@@ -3303,11 +3225,11 @@ static int builtin_cd(parser_t &parser, wchar_t **argv)
Implementation of the builtin count command, used to count the
number of arguments sent to it.
*/
-static int builtin_count(parser_t &parser, wchar_t ** argv)
+static int builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int argc;
argc = builtin_count_args(argv);
- append_format(stdout_buffer, L"%d\n", argc-1);
+ streams.out.append_format( L"%d\n", argc-1);
return !(argc-1);
}
@@ -3315,7 +3237,7 @@ static int builtin_count(parser_t &parser, wchar_t ** argv)
Implementation of the builtin contains command, used to check if a
specified string is part of a list.
*/
-static int builtin_contains(parser_t &parser, wchar_t ** argv)
+static int builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t ** argv)
{
wgetopter_t w;
int argc;
@@ -3348,25 +3270,24 @@ static int builtin_contains(parser_t &parser, wchar_t ** argv)
assert(opt_index >= 0 && (size_t)opt_index < sizeof long_options / sizeof *long_options);
if (long_options[opt_index].flag != 0)
break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
case ':':
- builtin_missing_argument(parser, argv[0], argv[w.woptind-1]);
+ builtin_missing_argument(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
case '?':
- builtin_unknown_option(parser, argv[0], argv[w.woptind-1]);
+ builtin_unknown_option(parser, streams, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
case 'i':
@@ -3379,7 +3300,7 @@ static int builtin_contains(parser_t &parser, wchar_t ** argv)
needle = argv[w.woptind];
if (!needle)
{
- append_format(stderr_buffer, _(L"%ls: Key not specified\n"), argv[0]);
+ streams.err.append_format(_(L"%ls: Key not specified\n"), argv[0]);
}
@@ -3388,7 +3309,7 @@ static int builtin_contains(parser_t &parser, wchar_t ** argv)
if (!wcscmp(needle, argv[i]))
{
- if (should_output_index) append_format(stdout_buffer, L"%d\n", i-w.woptind);
+ if (should_output_index) streams.out.append_format( L"%d\n", i-w.woptind);
return 0;
}
}
@@ -3400,7 +3321,7 @@ static int builtin_contains(parser_t &parser, wchar_t ** argv)
/**
The . (dot) builtin, sometimes called source. Evaluates the contents of a file.
*/
-static int builtin_source(parser_t &parser, wchar_t ** argv)
+static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
ASSERT_IS_MAIN_THREAD();
int fd;
@@ -3416,30 +3337,30 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
{
fn = L"-";
fn_intern = fn;
- fd = dup(builtin_stdin);
+ fd = dup(streams.stdin_fd);
}
else
{
if ((fd = wopen_cloexec(argv[1], O_RDONLY)) == -1)
{
- append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]);
- builtin_wperror(L"source");
+ streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]);
+ builtin_wperror(L"source", streams);
return STATUS_BUILTIN_ERROR;
}
if (fstat(fd, &buf) == -1)
{
close(fd);
- append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]);
- builtin_wperror(L"source");
+ streams.err.append_format(_(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1]);
+ builtin_wperror(L"source", streams);
return STATUS_BUILTIN_ERROR;
}
if (!S_ISREG(buf.st_mode))
{
close(fd);
- append_format(stderr_buffer, _(L"%ls: '%ls' is not a file\n"), argv[0], argv[1]);
+ streams.err.append_format(_(L"%ls: '%ls' is not a file\n"), argv[0], argv[1]);
return STATUS_BUILTIN_ERROR;
}
@@ -3451,14 +3372,13 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
env_set_argv((argc>2)?(argv+2):(argv+1));
- res = reader_read(fd, real_io ? *real_io : io_chain_t());
+ res = reader_read(fd, streams.io_chain ? *streams.io_chain : io_chain_t());
parser.pop_block();
if (res)
{
- append_format(stderr_buffer,
- _(L"%ls: Error while reading file '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Error while reading file '%ls'\n"),
argv[0],
fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern);
}
@@ -3491,7 +3411,7 @@ static void make_first(job_t *j)
/**
Builtin for putting a job in the foreground
*/
-static int builtin_fg(parser_t &parser, wchar_t **argv)
+static int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
job_t *j=NULL;
@@ -3513,8 +3433,7 @@ static int builtin_fg(parser_t &parser, wchar_t **argv)
}
if (!j)
{
- append_format(stderr_buffer,
- _(L"%ls: There are no suitable jobs\n"),
+ streams.err.append_format(_(L"%ls: There are no suitable jobs\n"),
argv[0]);
}
}
@@ -3541,19 +3460,17 @@ static int builtin_fg(parser_t &parser, wchar_t **argv)
if (found_job)
{
- append_format(stderr_buffer,
- _(L"%ls: Ambiguous job\n"),
+ streams.err.append_format(_(L"%ls: Ambiguous job\n"),
argv[0]);
}
else
{
- append_format(stderr_buffer,
- _(L"%ls: '%ls' is not a job\n"),
+ streams.err.append_format(_(L"%ls: '%ls' is not a job\n"),
argv[0],
argv[1]);
}
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
j=0;
@@ -3567,32 +3484,29 @@ static int builtin_fg(parser_t &parser, wchar_t **argv)
if (*end || errno)
{
- append_format(stderr_buffer,
- BUILTIN_ERR_NOT_NUMBER,
+ streams.err.append_format(BUILTIN_ERR_NOT_NUMBER,
argv[0],
argv[1]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
}
else
{
j = job_get_from_pid(pid);
if (!j || !job_get_flag(j, JOB_CONSTRUCTED) || job_is_completed(j))
{
- append_format(stderr_buffer,
- _(L"%ls: No suitable job: %d\n"),
+ streams.err.append_format(_(L"%ls: No suitable job: %d\n"),
argv[0],
pid);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
j=0;
}
else if (!job_get_flag(j, JOB_CONTROL))
{
- append_format(stderr_buffer,
- _(L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n"),
+ streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n"),
argv[0],
pid,
j->command_wcstr());
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
j=0;
}
}
@@ -3600,10 +3514,9 @@ static int builtin_fg(parser_t &parser, wchar_t **argv)
if (j)
{
- if (builtin_err_redirect)
+ if (streams.err_is_redirected)
{
- append_format(stderr_buffer,
- FG_MSG,
+ streams.err.append_format(FG_MSG,
j->job_id,
j->command_wcstr());
}
@@ -3636,31 +3549,28 @@ static int builtin_fg(parser_t &parser, wchar_t **argv)
/**
Helper function for builtin_bg()
*/
-static int send_to_bg(parser_t &parser, job_t *j, const wchar_t *name)
+static int send_to_bg(parser_t &parser, io_streams_t &streams, job_t *j, const wchar_t *name)
{
if (j == 0)
{
- append_format(stderr_buffer,
- _(L"%ls: Unknown job '%ls'\n"),
+ streams.err.append_format(_(L"%ls: Unknown job '%ls'\n"),
L"bg",
name);
- builtin_print_help(parser, L"bg", stderr_buffer);
+ builtin_print_help(parser, streams, L"bg", streams.err);
return STATUS_BUILTIN_ERROR;
}
else if (!job_get_flag(j, JOB_CONTROL))
{
- append_format(stderr_buffer,
- _(L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n"),
+ streams.err.append_format(_(L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n"),
L"bg",
j->job_id,
j->command_wcstr());
- builtin_print_help(parser, L"bg", stderr_buffer);
+ builtin_print_help(parser, streams, L"bg", streams.err);
return STATUS_BUILTIN_ERROR;
}
else
{
- append_format(stderr_buffer,
- _(L"Send job %d '%ls' to background\n"),
+ streams.err.append_format(_(L"Send job %d '%ls' to background\n"),
j->job_id,
j->command_wcstr());
}
@@ -3674,7 +3584,7 @@ static int send_to_bg(parser_t &parser, job_t *j, const wchar_t *name)
/**
Builtin for putting a job in the background
*/
-static int builtin_bg(parser_t &parser, wchar_t **argv)
+static int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int res = STATUS_BUILTIN_OK;
@@ -3692,14 +3602,13 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
if (!j)
{
- append_format(stderr_buffer,
- _(L"%ls: There are no suitable jobs\n"),
+ streams.err.append_format(_(L"%ls: There are no suitable jobs\n"),
argv[0]);
res = 1;
}
else
{
- res = send_to_bg(parser, j, _(L"(default)"));
+ res = send_to_bg(parser, streams, j, _(L"(default)"));
}
}
else
@@ -3715,8 +3624,7 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
pid = fish_wcstoi(argv[i], &end, 10);
if (errno || pid < 0 || *end || !job_get_from_pid(pid))
{
- append_format(stderr_buffer,
- _(L"%ls: '%ls' is not a job\n"),
+ streams.err.append_format(_(L"%ls: '%ls' is not a job\n"),
argv[0],
argv[i]);
err = 1;
@@ -3729,7 +3637,7 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
for (i=1; !res && argv[i]; i++)
{
pid = fish_wcstoi(argv[i], 0, 10);
- res |= send_to_bg(parser, job_get_from_pid(pid), *argv);
+ res |= send_to_bg(parser, streams, job_get_from_pid(pid), *argv);
}
}
}
@@ -3742,7 +3650,7 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
This function handles both the 'continue' and the 'break' builtins
that are used for loop control.
*/
-static int builtin_break_continue(parser_t &parser, wchar_t **argv)
+static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int is_break = (wcscmp(argv[0],L"break")==0);
int argc = builtin_count_args(argv);
@@ -3750,12 +3658,11 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
if (argc != 1)
{
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN,
argv[0],
argv[1]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -3770,10 +3677,9 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
if (loop_idx >= parser.block_count())
{
- append_format(stderr_buffer,
- _(L"%ls: Not inside of loop\n"),
+ streams.err.append_format(_(L"%ls: Not inside of loop\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -3796,11 +3702,11 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
interactive debugger.
*/
-static int builtin_breakpoint(parser_t &parser, wchar_t **argv)
+static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
parser.push_block(new breakpoint_block_t());
- reader_read(STDIN_FILENO, real_io ? *real_io : io_chain_t());
+ reader_read(STDIN_FILENO, streams.io_chain ? *streams.io_chain : io_chain_t());
parser.pop_block();
@@ -3811,7 +3717,7 @@ static int builtin_breakpoint(parser_t &parser, wchar_t **argv)
/**
Function for handling the \c return builtin
*/
-static int builtin_return(parser_t &parser, wchar_t **argv)
+static int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int argc = builtin_count_args(argv);
int status = proc_get_last_status();
@@ -3827,20 +3733,18 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
status = fish_wcstoi(argv[1],&end,10);
if (errno || *end != 0)
{
- append_format(stderr_buffer,
- _(L"%ls: Argument '%ls' must be an integer\n"),
+ streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"),
argv[0],
argv[1]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
break;
}
default:
- append_format(stderr_buffer,
- _(L"%ls: Too many arguments\n"),
+ streams.err.append_format(_(L"%ls: Too many arguments\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -3855,10 +3759,9 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
if (function_block_idx >= parser.block_count())
{
- append_format(stderr_buffer,
- _(L"%ls: Not inside of function\n"),
+ streams.err.append_format(_(L"%ls: Not inside of function\n"),
argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
@@ -3875,7 +3778,7 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
/**
History of commands executed by user
*/
-static int builtin_history(parser_t &parser, wchar_t **argv)
+static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
int argc = builtin_count_args(argv);
@@ -3934,15 +3837,15 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
merge_history = true;
break;
case 'h':
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
break;
case '?':
- append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]);
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
break;
default:
- append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]);
+ streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0], argv[w.woptind-1]);
return STATUS_BUILTIN_ERROR;
}
}
@@ -3954,8 +3857,8 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
{
wcstring full_history;
history->get_string_representation(&full_history, wcstring(L"\n"));
- stdout_buffer.append(full_history);
- stdout_buffer.push_back('\n');
+ streams.out.append(full_history);
+ streams.out.push_back('\n');
return STATUS_BUILTIN_OK;
}
@@ -3972,15 +3875,15 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
const wcstring &search_string = *iter;
if (search_string.empty())
{
- append_format(stderr_buffer, BUILTIN_ERR_COMBO2, argv[0], L"Use --search with either --contains or --prefix");
+ streams.err.append_format(BUILTIN_ERR_COMBO2, argv[0], L"Use --search with either --contains or --prefix");
return res;
}
history_search_t searcher = history_search_t(*history, search_string, search_prefix?HISTORY_SEARCH_TYPE_PREFIX:HISTORY_SEARCH_TYPE_CONTAINS);
while (searcher.go_backwards())
{
- stdout_buffer.append(searcher.current_string());
- stdout_buffer.append(L"\n");
+ streams.out.append(searcher.current_string());
+ streams.out.append(L"\n");
res = STATUS_BUILTIN_OK;
}
}
@@ -4016,7 +3919,7 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
-int builtin_parse(parser_t &parser, wchar_t **argv)
+int builtin_parse(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
struct sigaction act;
sigemptyset(& act.sa_mask);
@@ -4028,7 +3931,7 @@ int builtin_parse(parser_t &parser, wchar_t **argv)
for (;;)
{
char buff[256];
- ssize_t amt = read_loop(builtin_stdin, buff, sizeof buff);
+ ssize_t amt = read_loop(streams.stdin_fd, buff, sizeof buff);
if (amt <= 0) break;
txt.insert(txt.end(), buff, buff + amt);
}
@@ -4040,30 +3943,30 @@ int builtin_parse(parser_t &parser, wchar_t **argv)
bool success = parse_tree_from_string(src, parse_flag_include_comments, &parse_tree, &errors);
if (! success)
{
- stdout_buffer.append(L"Parsing failed:\n");
+ streams.out.append(L"Parsing failed:\n");
for (size_t i=0; i < errors.size(); i++)
{
- stdout_buffer.append(errors.at(i).describe(src));
- stdout_buffer.push_back(L'\n');
+ streams.out.append(errors.at(i).describe(src));
+ streams.out.push_back(L'\n');
}
- stdout_buffer.append(L"(Reparsed with continue after error)\n");
+ streams.out.append(L"(Reparsed with continue after error)\n");
parse_tree.clear();
errors.clear();
parse_tree_from_string(src, parse_flag_continue_after_error | parse_flag_include_comments, &parse_tree, &errors);
}
const wcstring dump = parse_dump_tree(parse_tree, src);
- stdout_buffer.append(dump);
+ streams.out.append(dump);
}
return STATUS_BUILTIN_OK;
}
-int builtin_true(parser_t &parser, wchar_t **argv)
+int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
return STATUS_BUILTIN_OK;
}
-int builtin_false(parser_t &parser, wchar_t **argv)
+int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
return STATUS_BUILTIN_ERROR;
}
@@ -4179,23 +4082,21 @@ static int internal_help(const wchar_t *cmd)
}
-int builtin_run(parser_t &parser, const wchar_t * const *argv, const io_chain_t &io)
+int builtin_run(parser_t &parser, const wchar_t * const *argv, io_streams_t &streams)
{
- int (*cmd)(parser_t &parser, const wchar_t * const *argv)=0;
+ int (*cmd)(parser_t &parser, io_streams_t &streams, const wchar_t * const *argv)=NULL;
- scoped_push<const io_chain_t*> set_real_io(&real_io, &io);
-
CHECK(argv, STATUS_BUILTIN_ERROR);
CHECK(argv[0], STATUS_BUILTIN_ERROR);
const builtin_data_t *data = builtin_lookup(argv[0]);
- cmd = (int (*)(parser_t &parser, const wchar_t * const*))(data ? data->func : NULL);
+ cmd = (int (*)(parser_t &parser, io_streams_t &streams, const wchar_t * const*))(data ? data->func : NULL);
if (argv[1] != 0 && !internal_help(argv[0]))
{
if (argv[2] == 0 && (parse_util_argument_is_help(argv[1], 0)))
{
- builtin_print_help(parser, argv[0], stdout_buffer);
+ builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
}
}
@@ -4204,7 +4105,7 @@ int builtin_run(parser_t &parser, const wchar_t * const *argv, const io_chain_t
{
int status;
- status = cmd(parser, argv);
+ status = cmd(parser, streams, argv);
return status;
}
@@ -4247,36 +4148,3 @@ wcstring builtin_get_desc(const wcstring &name)
}
return result;
}
-
-void builtin_push_io(parser_t &parser, int in)
-{
- ASSERT_IS_MAIN_THREAD();
- if (builtin_stdin != -1)
- {
- struct io_stack_elem_t elem = {builtin_stdin, stdout_buffer, stderr_buffer};
- io_stack.push(elem);
- }
- builtin_stdin = in;
- stdout_buffer.clear();
- stderr_buffer.clear();
-}
-
-void builtin_pop_io(parser_t &parser)
-{
- ASSERT_IS_MAIN_THREAD();
- builtin_stdin = 0;
- if (! io_stack.empty())
- {
- struct io_stack_elem_t &elem = io_stack.top();
- stderr_buffer = elem.err;
- stdout_buffer = elem.out;
- builtin_stdin = elem.in;
- io_stack.pop();
- }
- else
- {
- stdout_buffer.clear();
- stderr_buffer.clear();
- builtin_stdin = 0;
- }
-}