convert narrow stderr output to wide forms

On some platforms, notably GNU libc, you cannot mix narrow and wide
stdio functions on a stream like stdout or stderr. Doing so will drop
the output of one or the other. This change makes all output to the
stderr stream consistently use the wide forms.

This change also converts some fprintf(stderr,...) calls to debug()
calls where appropriate.

Fixes #3692
This commit is contained in:
Kurtis Rader 2017-01-02 21:11:53 -08:00
parent dddbdddcff
commit b118ed69d3
21 changed files with 165 additions and 182 deletions

View file

@ -541,9 +541,7 @@ bool should_suppress_stderr_for_tests() {
static bool should_debug(int level) {
if (level > debug_level) return false;
if (should_suppress_stderr_for_tests()) return false;
return true;
}
@ -1534,9 +1532,8 @@ int create_directory(const wcstring &d) {
}
__attribute__((noinline)) void bugreport() {
debug(1, _(L"This is a bug. Break on bugreport to debug. "
L"If you can reproduce it, please send a bug report to %s."),
PACKAGE_BUGREPORT);
debug(0, _(L"This is a bug. Break on bugreport to debug."));
debug(0, _(L"If you can reproduce it, please send a bug report to %s."), PACKAGE_BUGREPORT);
}
wcstring format_size(long long sz) {
@ -1722,28 +1719,24 @@ bool is_main_thread() {
void assert_is_main_thread(const char *who) {
if (!is_main_thread() && !thread_asserts_cfg_for_testing) {
fprintf(stderr,
"Warning: %s called off of main thread. Break on debug_thread_error to debug.\n",
who);
debug(0, "%s called off of main thread.", who);
debug(0, "Break on debug_thread_error to debug.");
debug_thread_error();
}
}
void assert_is_not_forked_child(const char *who) {
if (is_forked_child()) {
fprintf(stderr,
"Warning: %s called in a forked child. Break on debug_thread_error to debug.\n",
who);
debug(0, "%s called in a forked child.", who);
debug(0, "Break on debug_thread_error to debug.");
debug_thread_error();
}
}
void assert_is_background_thread(const char *who) {
if (is_main_thread() && !thread_asserts_cfg_for_testing) {
fprintf(stderr,
"Warning: %s called on the main thread (may block!). Break on debug_thread_error "
"to debug.\n",
who);
debug(0, "%s called on the main thread (may block!).", who);
debug(0, "Break on debug_thread_error to debug.");
debug_thread_error();
}
}
@ -1751,10 +1744,8 @@ void assert_is_background_thread(const char *who) {
void assert_is_locked(void *vmutex, const char *who, const char *caller) {
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(vmutex);
if (0 == pthread_mutex_trylock(mutex)) {
fprintf(stderr,
"Warning: %s is not locked when it should be in '%s'. Break on debug_thread_error "
"to debug.\n",
who, caller);
debug(0, "%s is not locked when it should be in '%s'", who, caller);
debug(0, "Break on debug_thread_error to debug.");
debug_thread_error();
pthread_mutex_unlock(mutex);
}

View file

@ -143,6 +143,26 @@ inline bool selection_direction_is_cardinal(selection_direction_t dir) {
}
}
/// Issue a debug message with printf-style string formating and automatic line breaking. The string
/// will begin with the string \c program_name, followed by a colon and a whitespace.
///
/// Because debug is often called to tell the user about an error, before using wperror to give a
/// specific error message, debug will never ever modify the value of errno.
///
/// \param level the priority of the message. Lower number means higher priority. Messages with a
/// priority_number higher than \c debug_level will be ignored..
/// \param msg the message format string.
///
/// Example:
///
/// <code>debug( 1, L"Pi = %.3f", M_PI );</code>
///
/// will print the string 'fish: Pi = 3.141', given that debug_level is 1 or higher, and that
/// program_name is 'fish'.
void __attribute__((noinline)) debug(int level, const char *msg, ...)
__attribute__((format(printf, 2, 3)));
void __attribute__((noinline)) debug(int level, const wchar_t *msg, ...);
/// Helper macro for errors.
#define VOMIT_ON_FAILURE(a) \
do { \
@ -157,12 +177,12 @@ inline bool selection_direction_is_cardinal(selection_direction_t dir) {
VOMIT_ABORT(err, #a); \
} \
} while (0)
#define VOMIT_ABORT(err, str) \
do { \
int code = (err); \
fprintf(stderr, "%s failed on line %d in file %s: %d (%s)\n", str, __LINE__, __FILE__, \
code, strerror(code)); \
abort(); \
#define VOMIT_ABORT(err, str) \
do { \
int code = (err); \
debug(0, "%s failed on line %d in file %s: %d (%s)", str, __LINE__, __FILE__, code, \
strerror(code)); \
abort(); \
} while (0)
/// Exits without invoking destructors (via _exit), useful for code after fork.
@ -224,11 +244,10 @@ extern bool has_working_tty_timestamps;
}
/// Exit program at once after emitting an error message.
#define DIE(msg) \
{ \
fprintf(stderr, "fish: %s on line %ld of file %s, shutting down fish\n", msg, \
(long)__LINE__, __FILE__); \
FATAL_EXIT(); \
#define DIE(msg) \
{ \
debug(0, "%s on line %ld of file %s, shutting down fish", msg, (long)__LINE__, __FILE__); \
FATAL_EXIT(); \
}
/// Exit program at once, leaving an error message about running out of memory.
@ -659,25 +678,6 @@ ssize_t write_loop(int fd, const char *buff, size_t count);
/// error.
ssize_t read_loop(int fd, void *buff, size_t count);
/// Issue a debug message with printf-style string formating and automatic line breaking. The string
/// will begin with the string \c program_name, followed by a colon and a whitespace.
///
/// Because debug is often called to tell the user about an error, before using wperror to give a
/// specific error message, debug will never ever modify the value of errno.
///
/// \param level the priority of the message. Lower number means higher priority. Messages with a
/// priority_number higher than \c debug_level will be ignored..
/// \param msg the message format string.
///
/// Example:
///
/// <code>debug( 1, L"Pi = %.3f", M_PI );</code>
///
/// will print the string 'fish: Pi = 3.141', given that debug_level is 1 or higher, and that
/// program_name is 'fish'.
void __attribute__((noinline)) debug(int level, const char *msg, ...)
__attribute__((format(printf, 2, 3)));
void __attribute__((noinline)) debug(int level, const wchar_t *msg, ...);
/// Replace special characters with backslash escape sequences. Newline is replaced with \n, etc.
///

View file

@ -95,7 +95,8 @@ static const wcstring default_vars_path() {
return vars_filename_in_directory(path);
}
/// Check, and create if necessary, a secure runtime path Derived from tmux.c in tmux
#if !defined(__APPLE__) && !defined(__CYGWIN__)
/// Check, and create if necessary, a secure runtime path. Derived from tmux.c in tmux
/// (http://tmux.sourceforge.net/).
static int check_runtime_path(const char *path) {
// Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -143,9 +144,8 @@ static wcstring get_runtime_path() {
std::string tmpdir = "/tmp/fish.";
tmpdir.append(uname);
if (check_runtime_path(tmpdir.c_str()) != 0) {
debug(0,
L"Runtime path not available. Try deleting the directory %s and restarting fish.",
tmpdir.c_str());
debug(0, L"Runtime path not available.");
debug(0, L"Try deleting the directory %s and restarting fish.", tmpdir.c_str());
} else {
result = str2wcstring(tmpdir);
}
@ -159,6 +159,7 @@ static wcstring default_named_pipe_path() {
// Note that vars_filename_in_directory returns empty string when passed the empty string.
return vars_filename_in_directory(get_runtime_path());
}
#endif
/// Test if the message msg contains the command cmd.
static bool match(const wchar_t *msg, const wchar_t *cmd) {
@ -1121,10 +1122,8 @@ class universal_notifier_notifyd_t : public universal_notifier_t {
uint32_t status =
notify_register_file_descriptor(name.c_str(), &this->notify_fd, 0, &this->token);
if (status != NOTIFY_STATUS_OK) {
fprintf(stderr,
"Warning: notify_register_file_descriptor() failed with status %u. Universal "
"variable notifications may not be received.",
status);
debug(1, "notify_register_file_descriptor() failed with status %u.", status);
debug(1, "Universal variable notifications may not be received.");
}
if (this->notify_fd >= 0) {
// Mark us for non-blocking reads, and CLO_EXEC.
@ -1184,8 +1183,10 @@ class universal_notifier_notifyd_t : public universal_notifier_t {
#endif
};
#define NAMED_PIPE_FLASH_DURATION_USEC (1000000 / 10)
#define SUSTAINED_READABILITY_CLEANUP_DURATION_USEC (1000000 * 5)
#if !defined(__APPLE__) && !defined(__CYGWIN__)
#define NAMED_PIPE_FLASH_DURATION_USEC (1e5)
#define SUSTAINED_READABILITY_CLEANUP_DURATION_USEC (5 * 1e6)
#endif
// Named-pipe based notifier. All clients open the same named pipe for reading and writing. The
// pipe's readability status is a trigger to enter polling mode.
@ -1347,7 +1348,7 @@ class universal_notifier_named_pipe_t : public universal_notifier_t {
#else // this class isn't valid on this system
public:
universal_notifier_named_pipe_t(const wchar_t *test_path) {
auto x = test_path; // silence "unused parameter" warning
static_cast<void>(test_path);
DIE("universal_notifier_named_pipe_t cannot be used on this system");
}
#endif

View file

@ -1131,16 +1131,12 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst,
const int prev_status = proc_get_last_status();
bool split_output = false;
// fprintf(stderr, "subcmd %ls\n", cmd.c_str());
const env_var_t ifs = env_get_string(L"IFS");
if (!ifs.missing_or_empty()) {
split_output = true;
}
is_subshell = 1;
int subcommand_status = -1; // assume the worst
// IO buffer creation may fail (e.g. if we have too many open files to make a pipe), so this may

View file

@ -491,7 +491,7 @@ int main(int argc, char *argv[]) {
case output_type_file: {
FILE *fh = fopen(output_location, "w");
if (fh) {
fputs(wcs2str(output_wtext), fh);
fputws(output_wtext.c_str(), fh);
fclose(fh);
exit(0);
} else {
@ -511,6 +511,6 @@ int main(int argc, char *argv[]) {
}
}
fputs(colored_output.c_str(), stdout);
fputws(str2wcstring(colored_output).c_str(), stdout);
return 0;
}

View file

@ -34,10 +34,10 @@
struct config_paths_t determine_config_directory_paths(const char *argv0);
static const char *ctrl_symbolic_names[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\a",
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "\\e", NULL, NULL, NULL, NULL};
static const wchar_t *ctrl_symbolic_names[] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, L"\\a", L"\\b", L"\\t", L"\\n",
L"\\v", L"\\f", L"\\r", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, L"\\e", NULL, NULL, NULL, NULL};
static bool keep_running = true;
/// Return true if the recent sequence of characters indicates the user wants to exit the program.
@ -51,12 +51,12 @@ static bool should_exit(wchar_t wc) {
recent_chars[3] = c;
if (c == shell_modes.c_cc[VINTR]) {
if (recent_chars[2] == shell_modes.c_cc[VINTR]) return true;
fprintf(stderr, "Press [ctrl-%c] again to exit\n", shell_modes.c_cc[VINTR] + 0x40);
fwprintf(stderr, L"Press [ctrl-%c] again to exit\n", shell_modes.c_cc[VINTR] + 0x40);
return false;
}
if (c == shell_modes.c_cc[VEOF]) {
if (recent_chars[2] == shell_modes.c_cc[VEOF]) return true;
fprintf(stderr, "Press [ctrl-%c] again to exit\n", shell_modes.c_cc[VEOF] + 0x40);
fwprintf(stderr, L"Press [ctrl-%c] again to exit\n", shell_modes.c_cc[VEOF] + 0x40);
return false;
}
return memcmp(recent_chars, "exit", 4) == 0 || memcmp(recent_chars, "quit", 4) == 0;
@ -116,46 +116,48 @@ static bool must_escape(wchar_t wc) {
}
}
static char *char_to_symbol(wchar_t wc, bool bind_friendly) {
static char buf[128];
static wchar_t *char_to_symbol(wchar_t wc, bool bind_friendly) {
#define BUF_LEN 64
static wchar_t buf[BUF_LEN];
if (wc < ' ') {
if (wc < L' ') {
// ASCII control character.
if (ctrl_symbolic_names[wc]) {
if (bind_friendly) {
snprintf(buf, sizeof(buf), "%s", ctrl_symbolic_names[wc]);
swprintf(buf, BUF_LEN, L"%ls", ctrl_symbolic_names[wc]);
} else {
snprintf(buf, sizeof(buf), "\\c%c (or %s)", wc + 64, ctrl_symbolic_names[wc]);
swprintf(buf, BUF_LEN, L"\\c%c (or %ls)", wc + 0x40, ctrl_symbolic_names[wc]);
}
} else {
snprintf(buf, sizeof(buf), "\\c%c", wc + 64);
swprintf(buf, BUF_LEN, L"\\c%c", wc + 0x40);
}
} else if (wc == ' ') {
} else if (wc == L' ') {
// The "space" character.
if (bind_friendly) {
snprintf(buf, sizeof(buf), "\\x%X", wc);
swprintf(buf, BUF_LEN, L"\\x%X", ' ');
} else {
snprintf(buf, sizeof(buf), "\\x%X (aka \"space\")", wc);
swprintf(buf, BUF_LEN, L"\\x%X (aka \"space\")", ' ');
}
} else if (wc == 0x7F) {
// The "del" character.
if (bind_friendly) {
snprintf(buf, sizeof(buf), "\\x%X", wc);
swprintf(buf, BUF_LEN, L"\\x%X", 0x7F);
} else {
snprintf(buf, sizeof(buf), "\\x%X (aka \"del\")", wc);
swprintf(buf, BUF_LEN, L"\\x%X (aka \"del\")", 0x7F);
}
} else if (wc < 0x80) {
// ASCII characters that are not control characters.
if (bind_friendly && must_escape(wc)) {
snprintf(buf, sizeof(buf), "\\%c", wc);
swprintf(buf, BUF_LEN, L"\\%c", wc);
} else {
snprintf(buf, sizeof(buf), "%c", wc);
swprintf(buf, BUF_LEN, L"%c", wc);
}
} else if (wc <= 0xFFFF) {
snprintf(buf, sizeof(buf), "\\u%04X", wc);
swprintf(buf, BUF_LEN, L"\\u%04X", (int)wc);
} else {
snprintf(buf, sizeof(buf), "\\U%06X", wc);
swprintf(buf, BUF_LEN, L"\\U%06X", (int)wc);
}
return buf;
}
@ -165,17 +167,17 @@ static void add_char_to_bind_command(wchar_t wc, std::vector<wchar_t> &bind_char
static void output_bind_command(std::vector<wchar_t> &bind_chars) {
if (bind_chars.size()) {
fputs("bind ", stdout);
fputws(L"bind ", stdout);
for (size_t i = 0; i < bind_chars.size(); i++) {
fputs(char_to_symbol(bind_chars[i], true), stdout);
fputws(char_to_symbol(bind_chars[i], true), stdout);
}
fputs(" 'do something'\n", stdout);
fputws(L" 'do something'\n", stdout);
bind_chars.clear();
}
}
static void output_info_about_char(wchar_t wc) {
fprintf(stderr, "hex: %4X char: %s\n", wc, char_to_symbol(wc, false));
fwprintf(stderr, L"hex: %4X char: %ls\n", wc, char_to_symbol(wc, false));
}
static bool output_matching_key_name(wchar_t wc) {
@ -193,11 +195,11 @@ static double output_elapsed_time(double prev_tstamp, bool first_char_seen) {
double now = timef();
long long int delta_tstamp_us = 1000000 * (now - prev_tstamp);
if (delta_tstamp_us >= 200000 && first_char_seen) putc('\n', stderr);
if (delta_tstamp_us >= 200000 && first_char_seen) fputwc(L'\n', stderr);
if (delta_tstamp_us >= 1000000) {
fprintf(stderr, " ");
fwprintf(stderr, L" ");
} else {
fprintf(stderr, "(%3lld.%03lld ms) ", delta_tstamp_us / 1000, delta_tstamp_us % 1000);
fwprintf(stderr, L"(%3lld.%03lld ms) ", delta_tstamp_us / 1000, delta_tstamp_us % 1000);
}
return now;
}
@ -208,7 +210,7 @@ static void process_input(bool continuous_mode) {
double prev_tstamp = 0.0;
std::vector<wchar_t> bind_chars;
fprintf(stderr, "Press a key\n\n");
fwprintf(stderr, L"Press a key\n\n");
while (keep_running) {
wchar_t wc;
if (reader_interrupted()) {
@ -232,7 +234,7 @@ static void process_input(bool continuous_mode) {
}
if (should_exit(wc)) {
fprintf(stderr, "\nExiting at your request.\n");
fwprintf(stderr, L"\nExiting at your request.\n");
break;
}
@ -295,11 +297,11 @@ static void setup_and_process_keys(bool continuous_mode) {
install_our_signal_handlers();
if (continuous_mode) {
fprintf(stderr, "\n");
fprintf(stderr, "To terminate this program type \"exit\" or \"quit\" in this window,\n");
fprintf(stderr, "or press [ctrl-%c] or [ctrl-%c] twice in a row.\n",
shell_modes.c_cc[VINTR] + 0x40, shell_modes.c_cc[VEOF] + 0x40);
fprintf(stderr, "\n");
fwprintf(stderr, L"\n");
fwprintf(stderr, L"To terminate this program type \"exit\" or \"quit\" in this window,\n");
fwprintf(stderr, L"or press [ctrl-%c] or [ctrl-%c] twice in a row.\n",
shell_modes.c_cc[VINTR] + 0x40, shell_modes.c_cc[VEOF] + 0x40);
fwprintf(stderr, L"\n");
}
process_input(continuous_mode);
@ -323,7 +325,7 @@ int main(int argc, char **argv) {
while (!error && (opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch (opt) {
case 0: {
fprintf(stderr, "getopt_long() unexpectedly returned zero\n");
fwprintf(stderr, L"getopt_long() unexpectedly returned zero\n");
error = true;
break;
}
@ -378,12 +380,12 @@ int main(int argc, char **argv) {
argc -= optind;
if (argc != 0) {
fprintf(stderr, "Expected no arguments, got %d\n", argc);
fwprintf(stderr, L"Expected no arguments, got %d\n", argc);
return 1;
}
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "Stdin must be attached to a tty.\n");
fwprintf(stderr, L"Stdin must be attached to a tty.\n");
return 1;
}

View file

@ -766,19 +766,10 @@ static void test_cancellation() {
// we cancel we expect no output.
test_1_cancellation(L"echo (while true ; echo blah ; end)");
fprintf(stderr, ".");
// Nasty infinite loop that doesn't actually execute anything.
test_1_cancellation(L"echo (while true ; end) (while true ; end) (while true ; end)");
fprintf(stderr, ".");
test_1_cancellation(L"while true ; end");
fprintf(stderr, ".");
test_1_cancellation(L"for i in (while true ; end) ; end");
fprintf(stderr, ".");
fprintf(stderr, "\n");
// Restore signal handling.
proc_pop_interactive();
@ -1645,8 +1636,8 @@ struct pager_layout_testcase_t {
wcstring text = sd.line(0).to_string();
if (text != expected) {
fprintf(stderr, "width %zu got <%ls>, expected <%ls>\n", this->width, text.c_str(),
expected.c_str());
fwprintf(stderr, L"width %zu got <%ls>, expected <%ls>\n", this->width,
text.c_str(), expected.c_str());
}
do_test(text == expected);
}
@ -2175,8 +2166,8 @@ static void test_1_completion(wcstring line, const wcstring &completion, complet
wcstring result =
completion_apply_to_command_line(completion, flags, line, &cursor_pos, append_only);
if (result != expected) {
fprintf(stderr, "line %ld: %ls + %ls -> [%ls], expected [%ls]\n", source_line, line.c_str(),
completion.c_str(), result.c_str(), expected.c_str());
fwprintf(stderr, L"line %ld: %ls + %ls -> [%ls], expected [%ls]\n", source_line,
line.c_str(), completion.c_str(), result.c_str(), expected.c_str());
}
do_test(result == expected);
do_test(cursor_pos == out_cursor_pos);
@ -2501,7 +2492,7 @@ static void test_universal() {
}
if (system("rm -Rf /tmp/fish_uvars_test")) err(L"rm failed");
putc('\n', stderr);
fputwc(L'\n', stderr);
}
static bool callback_data_less_than(const callback_data_t &a, const callback_data_t &b) {
@ -3225,7 +3216,7 @@ static void test_new_parser_fuzzing(void) {
bool log_it = true;
unsigned long max_len = 5;
for (unsigned long len = 0; len < max_len; len++) {
if (log_it) fprintf(stderr, "%lu / %lu...", len, max_len);
if (log_it) fwprintf(stderr, L"%lu / %lu...", len, max_len);
// We wish to look at all permutations of 4 elements of 'fuzzes' (with replacement).
// Construct an int and keep incrementing it.
@ -3234,7 +3225,7 @@ static void test_new_parser_fuzzing(void) {
&src)) {
parse_tree_from_string(src, parse_flag_continue_after_error, &node_tree, &errors);
}
if (log_it) fprintf(stderr, "done (%lu)\n", permutation);
if (log_it) fwprintf(stderr, L"done (%lu)\n", permutation);
}
double end = timef();
if (log_it) say(L"All fuzzed in %f seconds!", end - start);
@ -4121,8 +4112,8 @@ int main(int argc, char **argv) {
exit(-1);
}
if (!strcmp(wd, "/")) {
fprintf(stderr,
"Unable to find 'tests' directory, which should contain file test.fish\n");
fwprintf(stderr,
L"Unable to find 'tests' directory, which should contain file test.fish\n");
exit(EXIT_FAILURE);
}
if (chdir(dirname(wd)) < 0) {

View file

@ -1031,7 +1031,7 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
#if 0
// Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809.
const wcstring dump = parse_dump_tree(parse_tree, buff);
fprintf(stderr, "%ls\n", dump.c_str());
fwprintf(stderr, L"%ls\n", dump.c_str());
#endif
// Walk the node tree.

View file

@ -374,7 +374,7 @@ int input_init() {
} else {
debug(0, _(L"Using fallback terminal type '%ls'"), DEFAULT_TERM);
}
putc('\n', stderr);
fputwc(L'\n', stderr);
}
input_terminfo_init();

View file

@ -6,6 +6,7 @@
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <wchar.h>
#include "common.h"
#include "exec.h"
@ -15,19 +16,20 @@
io_data_t::~io_data_t() {}
void io_close_t::print() const { fprintf(stderr, "close %d\n", fd); }
void io_close_t::print() const { fwprintf(stderr, L"close %d\n", fd); }
void io_fd_t::print() const { fprintf(stderr, "FD map %d -> %d\n", old_fd, fd); }
void io_fd_t::print() const { fwprintf(stderr, L"FD map %d -> %d\n", old_fd, fd); }
void io_file_t::print() const { fprintf(stderr, "file (%s)\n", filename_cstr); }
void io_file_t::print() const { fwprintf(stderr, L"file (%s)\n", filename_cstr); }
void io_pipe_t::print() const {
fprintf(stderr, "pipe {%d, %d} (input: %s)\n", pipe_fd[0], pipe_fd[1], is_input ? "yes" : "no");
fwprintf(stderr, L"pipe {%d, %d} (input: %s)\n", pipe_fd[0], pipe_fd[1],
is_input ? "yes" : "no");
}
void io_buffer_t::print() const {
fprintf(stderr, "buffer %p (input: %s, size %lu)\n", out_buffer_ptr(), is_input ? "yes" : "no",
(unsigned long)out_buffer_size());
fwprintf(stderr, L"buffer %p (input: %s, size %lu)\n", out_buffer_ptr(),
is_input ? "yes" : "no", (unsigned long)out_buffer_size());
}
void io_buffer_t::read() {
@ -139,21 +141,21 @@ void io_print(const io_chain_t &chain)
{
if (chain.empty())
{
fprintf(stderr, "Empty chain %p\n", &chain);
fwprintf(stderr, L"Empty chain %p\n", &chain);
return;
}
fprintf(stderr, "Chain %p (%ld items):\n", &chain, (long)chain.size());
fwprintf(stderr, L"Chain %p (%ld items):\n", &chain, (long)chain.size());
for (size_t i=0; i < chain.size(); i++)
{
const shared_ptr<io_data_t> &io = chain.at(i);
if (io.get() == NULL)
{
fprintf(stderr, "\t(null)\n");
fwprintf(stderr, L"\t(null)\n");
}
else
{
fprintf(stderr, "\t%lu: fd:%d, ", (unsigned long)i, io->fd);
fwprintf(stderr, L"\t%lu: fd:%d, ", (unsigned long)i, io->fd);
io->print();
}
}

View file

@ -6,7 +6,6 @@
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
@ -228,7 +227,7 @@ void iothread_service_completion(void) {
} else if (wakeup_byte == IO_SERVICE_RESULT_QUEUE) {
iothread_service_result_queue();
} else {
fprintf(stderr, "Unknown wakeup byte %02x in %s\n", wakeup_byte, __FUNCTION__);
debug(0, "Unknown wakeup byte %02x in %s", wakeup_byte, __FUNCTION__);
}
}

View file

@ -6,10 +6,10 @@
#include "config.h"
#define PARSE_ASSERT(a) assert(a)
#define PARSER_DIE() \
do { \
fprintf(stderr, "Parser dying!\n"); \
exit_without_destructors(-1); \
#define PARSER_DIE() \
do { \
debug(0, "Parser dying!"); \
exit_without_destructors(-1); \
} while (0)
// IMPORTANT: If the following enum table is modified you must also update token_enum_map below.

View file

@ -441,7 +441,7 @@ parse_execution_result_t parse_execution_context_t::run_block_statement(
break;
}
default: {
fprintf(stderr, "Unexpected block header: %ls\n", header.describe().c_str());
debug(0, L"Unexpected block header: %ls\n", header.describe().c_str());
PARSER_DIE();
break;
}
@ -700,7 +700,7 @@ parse_execution_result_t parse_execution_context_t::report_errors(
const parse_error_list_t &error_list) const {
if (!parser->cancellation_requested) {
if (error_list.empty()) {
fprintf(stderr, "Bug: Error reported but no error text found.");
debug(0, "Error reported but no error text found.");
}
// Get a backtrace.
@ -708,7 +708,9 @@ parse_execution_result_t parse_execution_context_t::report_errors(
parser->get_backtrace(src, error_list, &backtrace_and_desc);
// Print it.
if (!should_suppress_stderr_for_tests()) fprintf(stderr, "%ls", backtrace_and_desc.c_str());
if (!should_suppress_stderr_for_tests()) {
fwprintf(stderr, L"%ls", backtrace_and_desc.c_str());
}
}
return parse_execution_errored;
}
@ -1034,8 +1036,7 @@ bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement
}
default: {
// Should be unreachable.
fprintf(stderr, "Unexpected redirection type %ld. aborting.\n",
(long)redirect_type);
debug(0, "Unexpected redirection type %ld.", (long)redirect_type);
PARSER_DIE();
break;
}
@ -1133,8 +1134,8 @@ parse_execution_result_t parse_execution_context_t::populate_job_process(
break;
}
default: {
fprintf(stderr, "'%ls' not handled by new parser yet\n",
specific_statement.describe().c_str());
debug(0, L"'%ls' not handled by new parser yet.",
specific_statement.describe().c_str());
PARSER_DIE();
break;
}
@ -1426,8 +1427,7 @@ parse_execution_result_t parse_execution_context_t::eval_node_at_offset(
default: {
// In principle, we could support other node types. However we never expect to be passed
// them - see above.
fprintf(stderr, "Unexpected node %ls found in %s\n", node.describe().c_str(),
__FUNCTION__);
debug(0, "Unexpected node %ls found in %s", node.describe().c_str(), __FUNCTION__);
PARSER_DIE();
break;
}

View file

@ -481,21 +481,21 @@ const production_element_t *parse_productions::production_for_token(parse_token_
case parse_token_type_background:
case parse_token_type_end:
case parse_token_type_terminate: {
fprintf(stderr, "Terminal token type %ls passed to %s\n",
token_type_description(node_type), __FUNCTION__);
debug(0, "Terminal token type %ls passed to %s", token_type_description(node_type),
__FUNCTION__);
PARSER_DIE();
break;
}
case parse_special_type_parse_error:
case parse_special_type_tokenizer_error:
case parse_special_type_comment: {
fprintf(stderr, "Special type %ls passed to %s\n", token_type_description(node_type),
__FUNCTION__);
debug(0, "Special type %ls passed to %s\n", token_type_description(node_type),
__FUNCTION__);
PARSER_DIE();
break;
}
case token_type_invalid: {
fprintf(stderr, "token_type_invalid passed to %s\n", __FUNCTION__);
debug(0, "token_type_invalid passed to %s", __FUNCTION__);
PARSER_DIE();
break;
}

View file

@ -127,6 +127,7 @@ const wchar_t *token_type_description(parse_token_type_t type) {
// This leaks memory but it should never be run unless we have a bug elsewhere in the code.
const wcstring d = format_string(L"unknown_token_type_%ld", static_cast<long>(type));
wchar_t *d2 = new wchar_t[d.size() + 1];
// cppcheck-suppress memleak
return std::wcscpy(d2, d.c_str());
}
@ -137,6 +138,7 @@ const wchar_t *keyword_description(parse_keyword_t type) {
// This leaks memory but it should never be run unless we have a bug elsewhere in the code.
const wcstring d = format_string(L"unknown_keyword_%ld", static_cast<long>(type));
wchar_t *d2 = new wchar_t[d.size() + 1];
// cppcheck-suppress memleak
return std::wcscpy(d2, d.c_str());
}
@ -258,8 +260,7 @@ static inline parse_token_type_t parse_token_type_from_tokenizer_token(
break;
}
default: {
fprintf(stderr, "Bad token type %d passed to %s\n", (int)tokenizer_token_type,
__FUNCTION__);
debug(0, "Bad token type %d passed to %s", (int)tokenizer_token_type, __FUNCTION__);
DIE("bad token type");
break;
}
@ -420,17 +421,17 @@ class parse_ll_t {
bool logit = false;
if (logit) {
int count = 0;
fprintf(stderr, "Applying production:\n");
fwprintf(stderr, L"Applying production:\n");
for (int i = 0;; i++) {
production_element_t elem = production[i];
if (!production_element_is_valid(elem)) break; // all done, bail out
parse_token_type_t type = production_element_type(elem);
parse_keyword_t keyword = production_element_keyword(elem);
fprintf(stderr, "\t%ls <%ls>\n", token_type_description(type),
keyword_description(keyword));
fwprintf(stderr, L"\t%ls <%ls>\n", token_type_description(type),
keyword_description(keyword));
count++;
}
if (!count) fprintf(stderr, "\t<empty>\n");
if (!count) fwprintf(stderr, L"\t<empty>\n");
}
// Get the parent index. But we can't get the parent parse node yet, since it may be made
@ -537,9 +538,9 @@ void parse_ll_t::dump_stack(void) const {
}
}
fprintf(stderr, "Stack dump (%zu elements):\n", symbol_stack.size());
fwprintf(stderr, L"Stack dump (%zu elements):\n", symbol_stack.size());
for (size_t idx = 0; idx < stack_lines.size(); idx++) {
fprintf(stderr, " %ls\n", stack_lines.at(idx).c_str());
fwprintf(stderr, L" %ls\n", stack_lines.at(idx).c_str());
}
}
#endif
@ -927,7 +928,7 @@ bool parse_ll_t::top_node_handle_terminal_types(parse_token_t token) {
void parse_ll_t::accept_tokens(parse_token_t token1, parse_token_t token2) {
bool logit = false;
if (logit) {
fprintf(stderr, "Accept token %ls\n", token1.describe().c_str());
fwprintf(stderr, L"Accept token %ls\n", token1.describe().c_str());
}
PARSE_ASSERT(token1.type >= FIRST_PARSE_TOKEN_TYPE);
@ -964,7 +965,7 @@ void parse_ll_t::accept_tokens(parse_token_t token1, parse_token_t token2) {
if (top_node_handle_terminal_types(token1)) {
if (logit) {
fprintf(stderr, "Consumed token %ls\n", token1.describe().c_str());
fwprintf(stderr, L"Consumed token %ls\n", token1.describe().c_str());
}
// consumed = true;
break;
@ -1184,8 +1185,8 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t parse_flags,
#if 0
//wcstring result = dump_tree(this->parser->nodes, str);
//fprintf(stderr, "Tree (%ld nodes):\n%ls", this->parser->nodes.size(), result.c_str());
fprintf(stderr, "%lu nodes, node size %lu, %lu bytes\n", output->size(), sizeof(parse_node_t),
//fwprintf(stderr, L"Tree (%ld nodes):\n%ls", this->parser->nodes.size(), result.c_str());
fwprintf(stderr, L"%lu nodes, node size %lu, %lu bytes\n", output->size(), sizeof(parse_node_t),
output->size() * sizeof(parse_node_t));
#endif

View file

@ -615,8 +615,7 @@ int parser_t::eval(const wcstring &cmd, const io_chain_t &io, enum block_type_t
this->get_backtrace(cmd, error_list, &backtrace_and_desc);
// Print it.
fprintf(stderr, "%ls", backtrace_and_desc.c_str());
fwprintf(stderr, L"%ls\n", backtrace_and_desc.c_str());
return 1;
}
return this->eval_acquiring_tree(cmd, io, block_type, moved_ref<parse_node_tree_t>(tree));

View file

@ -242,7 +242,7 @@ static void maybe_issue_path_warning(const wcstring &which_dir, const wcstring &
debug(0, _(L"The error was '%s'."), strerror(saved_errno));
debug(0, _(L"Please set $%ls to a directory where you have write access."), env_var);
}
putc('\n', stderr);
fputwc(L'\n', stderr);
}
static void path_create(wcstring &path, const wcstring &xdg_var, const wcstring &which_dir,

View file

@ -11,6 +11,7 @@
#if FISH_USE_POSIX_SPAWN
#include <spawn.h>
#endif
#include <wchar.h>
#include "common.h"
#include "exec.h"
@ -141,7 +142,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
switch (io->io_mode) {
case IO_CLOSE: {
if (log_redirections) fprintf(stderr, "%d: close %d\n", getpid(), io->fd);
if (log_redirections) fwprintf(stderr, L"%d: close %d\n", getpid(), io->fd);
if (close(io->fd)) {
debug_safe_int(0, "Failed to close file descriptor %s", io->fd);
safe_perror("close");
@ -180,7 +181,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
case IO_FD: {
int old_fd = static_cast<const io_fd_t *>(io)->old_fd;
if (log_redirections)
fprintf(stderr, "%d: fd dup %d to %d\n", getpid(), old_fd, io->fd);
fwprintf(stderr, L"%d: fd dup %d to %d\n", getpid(), old_fd, io->fd);
// This call will sometimes fail, but that is ok, this is just a precausion.
close(io->fd);
@ -200,14 +201,14 @@ static int handle_child_io(const io_chain_t &io_chain) {
// fd). If it's 1, we're connecting to the write end (second pipe fd).
unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
#if 0
debug( 0, L"%ls %ls on fd %d (%d %d)", write_pipe?L"write":L"read",
(io->io_mode == IO_BUFFER)?L"buffer":L"pipe", io->fd, io->pipe_fd[0],
io->pipe_fd[1]);
debug(0, L"%ls %ls on fd %d (%d %d)", write_pipe?L"write":L"read",
(io->io_mode == IO_BUFFER)?L"buffer":L"pipe", io->fd, io->pipe_fd[0],
io->pipe_fd[1]);
#endif
if (log_redirections)
fprintf(stderr, "%d: %s dup %d to %d\n", getpid(),
io->io_mode == IO_BUFFER ? "buffer" : "pipe",
io_pipe->pipe_fd[write_pipe_idx], io->fd);
fwprintf(stderr, L"%d: %s dup %d to %d\n", getpid(),
io->io_mode == IO_BUFFER ? "buffer" : "pipe",
io_pipe->pipe_fd[write_pipe_idx], io->fd);
if (dup2(io_pipe->pipe_fd[write_pipe_idx], io->fd) != io->fd) {
debug_safe(1, LOCAL_PIPE_ERROR);
safe_perror("dup2");

View file

@ -280,7 +280,7 @@ static void mark_process_status(process_t *p, int status) {
} else {
// This should never be reached.
p->completed = 1;
fprintf(stderr, "Process %ld exited abnormally\n", (long)p->pid);
debug(1, "Process %ld exited abnormally", (long)p->pid);
}
}

View file

@ -2424,7 +2424,7 @@ const wchar_t *reader_readline(int nchars) {
is_interactive_read = 1;
c = input_readch();
is_interactive_read = was_interactive_read;
// fprintf(stderr, "C: %lx\n", (long)c);
// fwprintf(stderr, L"C: %lx\n", (long)c);
if (((!fish_reserved_codepoint(c))) && (c > 31) && (c != 127) && can_read(0)) {
wchar_t arr[READAHEAD_MAX + 1];
@ -2486,7 +2486,7 @@ const wchar_t *reader_readline(int nchars) {
if (command_ends_paging(c, focused_on_search_field)) {
clear_pager();
}
// fprintf(stderr, "\n\nchar: %ls\n\n", describe_char(c).c_str());
// fwprintf(stderr, L"\n\nchar: %ls\n\n", describe_char(c).c_str());
switch (c) {
// Go to beginning of line.
@ -2607,7 +2607,7 @@ const wchar_t *reader_readline(int nchars) {
// up to the end of the token we're completing.
const wcstring buffcpy = wcstring(cmdsub_begin, token_end);
// fprintf(stderr, "Complete (%ls)\n", buffcpy.c_str());
// fwprintf(stderr, L"Complete (%ls)\n", buffcpy.c_str());
complete_flags_t complete_flags = COMPLETION_REQUEST_DEFAULT |
COMPLETION_REQUEST_DESCRIPTIONS |
COMPLETION_REQUEST_FUZZY_MATCH;

View file

@ -416,7 +416,7 @@ static void s_desired_append_char(screen_t *s, wchar_t b, int c, int indent, siz
if ((s->desired.cursor.x + cw) > screen_width) {
// Current line is soft wrapped (assuming we support it).
s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
// fprintf(stderr, "\n\n1 Soft wrapping %d\n\n", s->desired.cursor.y);
// fwprintf(stderr, L"\n\n1 Soft wrapping %d\n\n", s->desired.cursor.y);
line_no = (int)s->desired.line_count();
s->desired.add_line();