mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-11 20:48:49 +00:00
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:
parent
dddbdddcff
commit
b118ed69d3
21 changed files with 165 additions and 182 deletions
|
@ -541,9 +541,7 @@ bool should_suppress_stderr_for_tests() {
|
||||||
|
|
||||||
static bool should_debug(int level) {
|
static bool should_debug(int level) {
|
||||||
if (level > debug_level) return false;
|
if (level > debug_level) return false;
|
||||||
|
|
||||||
if (should_suppress_stderr_for_tests()) return false;
|
if (should_suppress_stderr_for_tests()) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1534,9 +1532,8 @@ int create_directory(const wcstring &d) {
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline)) void bugreport() {
|
__attribute__((noinline)) void bugreport() {
|
||||||
debug(1, _(L"This is a bug. Break on bugreport to debug. "
|
debug(0, _(L"This is a bug. Break on bugreport to debug."));
|
||||||
L"If you can reproduce it, please send a bug report to %s."),
|
debug(0, _(L"If you can reproduce it, please send a bug report to %s."), PACKAGE_BUGREPORT);
|
||||||
PACKAGE_BUGREPORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wcstring format_size(long long sz) {
|
wcstring format_size(long long sz) {
|
||||||
|
@ -1722,28 +1719,24 @@ bool is_main_thread() {
|
||||||
|
|
||||||
void assert_is_main_thread(const char *who) {
|
void assert_is_main_thread(const char *who) {
|
||||||
if (!is_main_thread() && !thread_asserts_cfg_for_testing) {
|
if (!is_main_thread() && !thread_asserts_cfg_for_testing) {
|
||||||
fprintf(stderr,
|
debug(0, "%s called off of main thread.", who);
|
||||||
"Warning: %s called off of main thread. Break on debug_thread_error to debug.\n",
|
debug(0, "Break on debug_thread_error to debug.");
|
||||||
who);
|
|
||||||
debug_thread_error();
|
debug_thread_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void assert_is_not_forked_child(const char *who) {
|
void assert_is_not_forked_child(const char *who) {
|
||||||
if (is_forked_child()) {
|
if (is_forked_child()) {
|
||||||
fprintf(stderr,
|
debug(0, "%s called in a forked child.", who);
|
||||||
"Warning: %s called in a forked child. Break on debug_thread_error to debug.\n",
|
debug(0, "Break on debug_thread_error to debug.");
|
||||||
who);
|
|
||||||
debug_thread_error();
|
debug_thread_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void assert_is_background_thread(const char *who) {
|
void assert_is_background_thread(const char *who) {
|
||||||
if (is_main_thread() && !thread_asserts_cfg_for_testing) {
|
if (is_main_thread() && !thread_asserts_cfg_for_testing) {
|
||||||
fprintf(stderr,
|
debug(0, "%s called on the main thread (may block!).", who);
|
||||||
"Warning: %s called on the main thread (may block!). Break on debug_thread_error "
|
debug(0, "Break on debug_thread_error to debug.");
|
||||||
"to debug.\n",
|
|
||||||
who);
|
|
||||||
debug_thread_error();
|
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) {
|
void assert_is_locked(void *vmutex, const char *who, const char *caller) {
|
||||||
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(vmutex);
|
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(vmutex);
|
||||||
if (0 == pthread_mutex_trylock(mutex)) {
|
if (0 == pthread_mutex_trylock(mutex)) {
|
||||||
fprintf(stderr,
|
debug(0, "%s is not locked when it should be in '%s'", who, caller);
|
||||||
"Warning: %s is not locked when it should be in '%s'. Break on debug_thread_error "
|
debug(0, "Break on debug_thread_error to debug.");
|
||||||
"to debug.\n",
|
|
||||||
who, caller);
|
|
||||||
debug_thread_error();
|
debug_thread_error();
|
||||||
pthread_mutex_unlock(mutex);
|
pthread_mutex_unlock(mutex);
|
||||||
}
|
}
|
||||||
|
|
60
src/common.h
60
src/common.h
|
@ -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.
|
/// Helper macro for errors.
|
||||||
#define VOMIT_ON_FAILURE(a) \
|
#define VOMIT_ON_FAILURE(a) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -157,12 +177,12 @@ inline bool selection_direction_is_cardinal(selection_direction_t dir) {
|
||||||
VOMIT_ABORT(err, #a); \
|
VOMIT_ABORT(err, #a); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define VOMIT_ABORT(err, str) \
|
#define VOMIT_ABORT(err, str) \
|
||||||
do { \
|
do { \
|
||||||
int code = (err); \
|
int code = (err); \
|
||||||
fprintf(stderr, "%s failed on line %d in file %s: %d (%s)\n", str, __LINE__, __FILE__, \
|
debug(0, "%s failed on line %d in file %s: %d (%s)", str, __LINE__, __FILE__, code, \
|
||||||
code, strerror(code)); \
|
strerror(code)); \
|
||||||
abort(); \
|
abort(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/// Exits without invoking destructors (via _exit), useful for code after fork.
|
/// 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.
|
/// Exit program at once after emitting an error message.
|
||||||
#define DIE(msg) \
|
#define DIE(msg) \
|
||||||
{ \
|
{ \
|
||||||
fprintf(stderr, "fish: %s on line %ld of file %s, shutting down fish\n", msg, \
|
debug(0, "%s on line %ld of file %s, shutting down fish", msg, (long)__LINE__, __FILE__); \
|
||||||
(long)__LINE__, __FILE__); \
|
FATAL_EXIT(); \
|
||||||
FATAL_EXIT(); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exit program at once, leaving an error message about running out of memory.
|
/// 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.
|
/// error.
|
||||||
ssize_t read_loop(int fd, void *buff, size_t count);
|
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.
|
/// Replace special characters with backslash escape sequences. Newline is replaced with \n, etc.
|
||||||
///
|
///
|
||||||
|
|
|
@ -95,7 +95,8 @@ static const wcstring default_vars_path() {
|
||||||
return vars_filename_in_directory(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/).
|
/// (http://tmux.sourceforge.net/).
|
||||||
static int check_runtime_path(const char *path) {
|
static int check_runtime_path(const char *path) {
|
||||||
// Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
// Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
@ -143,9 +144,8 @@ static wcstring get_runtime_path() {
|
||||||
std::string tmpdir = "/tmp/fish.";
|
std::string tmpdir = "/tmp/fish.";
|
||||||
tmpdir.append(uname);
|
tmpdir.append(uname);
|
||||||
if (check_runtime_path(tmpdir.c_str()) != 0) {
|
if (check_runtime_path(tmpdir.c_str()) != 0) {
|
||||||
debug(0,
|
debug(0, L"Runtime path not available.");
|
||||||
L"Runtime path not available. Try deleting the directory %s and restarting fish.",
|
debug(0, L"Try deleting the directory %s and restarting fish.", tmpdir.c_str());
|
||||||
tmpdir.c_str());
|
|
||||||
} else {
|
} else {
|
||||||
result = str2wcstring(tmpdir);
|
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.
|
// Note that vars_filename_in_directory returns empty string when passed the empty string.
|
||||||
return vars_filename_in_directory(get_runtime_path());
|
return vars_filename_in_directory(get_runtime_path());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Test if the message msg contains the command cmd.
|
/// Test if the message msg contains the command cmd.
|
||||||
static bool match(const wchar_t *msg, const wchar_t *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 =
|
uint32_t status =
|
||||||
notify_register_file_descriptor(name.c_str(), &this->notify_fd, 0, &this->token);
|
notify_register_file_descriptor(name.c_str(), &this->notify_fd, 0, &this->token);
|
||||||
if (status != NOTIFY_STATUS_OK) {
|
if (status != NOTIFY_STATUS_OK) {
|
||||||
fprintf(stderr,
|
debug(1, "notify_register_file_descriptor() failed with status %u.", status);
|
||||||
"Warning: notify_register_file_descriptor() failed with status %u. Universal "
|
debug(1, "Universal variable notifications may not be received.");
|
||||||
"variable notifications may not be received.",
|
|
||||||
status);
|
|
||||||
}
|
}
|
||||||
if (this->notify_fd >= 0) {
|
if (this->notify_fd >= 0) {
|
||||||
// Mark us for non-blocking reads, and CLO_EXEC.
|
// Mark us for non-blocking reads, and CLO_EXEC.
|
||||||
|
@ -1184,8 +1183,10 @@ class universal_notifier_notifyd_t : public universal_notifier_t {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NAMED_PIPE_FLASH_DURATION_USEC (1000000 / 10)
|
#if !defined(__APPLE__) && !defined(__CYGWIN__)
|
||||||
#define SUSTAINED_READABILITY_CLEANUP_DURATION_USEC (1000000 * 5)
|
#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
|
// 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.
|
// 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
|
#else // this class isn't valid on this system
|
||||||
public:
|
public:
|
||||||
universal_notifier_named_pipe_t(const wchar_t *test_path) {
|
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");
|
DIE("universal_notifier_named_pipe_t cannot be used on this system");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1131,16 +1131,12 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst,
|
||||||
const int prev_status = proc_get_last_status();
|
const int prev_status = proc_get_last_status();
|
||||||
bool split_output = false;
|
bool split_output = false;
|
||||||
|
|
||||||
// fprintf(stderr, "subcmd %ls\n", cmd.c_str());
|
|
||||||
|
|
||||||
const env_var_t ifs = env_get_string(L"IFS");
|
const env_var_t ifs = env_get_string(L"IFS");
|
||||||
|
|
||||||
if (!ifs.missing_or_empty()) {
|
if (!ifs.missing_or_empty()) {
|
||||||
split_output = true;
|
split_output = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_subshell = 1;
|
is_subshell = 1;
|
||||||
|
|
||||||
int subcommand_status = -1; // assume the worst
|
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
|
// IO buffer creation may fail (e.g. if we have too many open files to make a pipe), so this may
|
||||||
|
|
|
@ -491,7 +491,7 @@ int main(int argc, char *argv[]) {
|
||||||
case output_type_file: {
|
case output_type_file: {
|
||||||
FILE *fh = fopen(output_location, "w");
|
FILE *fh = fopen(output_location, "w");
|
||||||
if (fh) {
|
if (fh) {
|
||||||
fputs(wcs2str(output_wtext), fh);
|
fputws(output_wtext.c_str(), fh);
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else {
|
} 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
|
|
||||||
struct config_paths_t determine_config_directory_paths(const char *argv0);
|
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",
|
static const wchar_t *ctrl_symbolic_names[] = {
|
||||||
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, L"\\a", L"\\b", L"\\t", L"\\n",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
L"\\v", L"\\f", L"\\r", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, "\\e", NULL, NULL, NULL, NULL};
|
NULL, NULL, NULL, NULL, NULL, L"\\e", NULL, NULL, NULL, NULL};
|
||||||
static bool keep_running = true;
|
static bool keep_running = true;
|
||||||
|
|
||||||
/// Return true if the recent sequence of characters indicates the user wants to exit the program.
|
/// 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;
|
recent_chars[3] = c;
|
||||||
if (c == shell_modes.c_cc[VINTR]) {
|
if (c == shell_modes.c_cc[VINTR]) {
|
||||||
if (recent_chars[2] == shell_modes.c_cc[VINTR]) return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (c == shell_modes.c_cc[VEOF]) {
|
if (c == shell_modes.c_cc[VEOF]) {
|
||||||
if (recent_chars[2] == shell_modes.c_cc[VEOF]) return true;
|
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 false;
|
||||||
}
|
}
|
||||||
return memcmp(recent_chars, "exit", 4) == 0 || memcmp(recent_chars, "quit", 4) == 0;
|
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 wchar_t *char_to_symbol(wchar_t wc, bool bind_friendly) {
|
||||||
static char buf[128];
|
#define BUF_LEN 64
|
||||||
|
static wchar_t buf[BUF_LEN];
|
||||||
|
|
||||||
if (wc < ' ') {
|
if (wc < L' ') {
|
||||||
// ASCII control character.
|
// ASCII control character.
|
||||||
if (ctrl_symbolic_names[wc]) {
|
if (ctrl_symbolic_names[wc]) {
|
||||||
if (bind_friendly) {
|
if (bind_friendly) {
|
||||||
snprintf(buf, sizeof(buf), "%s", ctrl_symbolic_names[wc]);
|
swprintf(buf, BUF_LEN, L"%ls", ctrl_symbolic_names[wc]);
|
||||||
} else {
|
} 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 {
|
} 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.
|
// The "space" character.
|
||||||
if (bind_friendly) {
|
if (bind_friendly) {
|
||||||
snprintf(buf, sizeof(buf), "\\x%X", wc);
|
swprintf(buf, BUF_LEN, L"\\x%X", ' ');
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), "\\x%X (aka \"space\")", wc);
|
swprintf(buf, BUF_LEN, L"\\x%X (aka \"space\")", ' ');
|
||||||
}
|
}
|
||||||
} else if (wc == 0x7F) {
|
} else if (wc == 0x7F) {
|
||||||
// The "del" character.
|
// The "del" character.
|
||||||
if (bind_friendly) {
|
if (bind_friendly) {
|
||||||
snprintf(buf, sizeof(buf), "\\x%X", wc);
|
swprintf(buf, BUF_LEN, L"\\x%X", 0x7F);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), "\\x%X (aka \"del\")", wc);
|
swprintf(buf, BUF_LEN, L"\\x%X (aka \"del\")", 0x7F);
|
||||||
}
|
}
|
||||||
} else if (wc < 0x80) {
|
} else if (wc < 0x80) {
|
||||||
// ASCII characters that are not control characters.
|
// ASCII characters that are not control characters.
|
||||||
if (bind_friendly && must_escape(wc)) {
|
if (bind_friendly && must_escape(wc)) {
|
||||||
snprintf(buf, sizeof(buf), "\\%c", wc);
|
swprintf(buf, BUF_LEN, L"\\%c", wc);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), "%c", wc);
|
swprintf(buf, BUF_LEN, L"%c", wc);
|
||||||
}
|
}
|
||||||
} else if (wc <= 0xFFFF) {
|
} else if (wc <= 0xFFFF) {
|
||||||
snprintf(buf, sizeof(buf), "\\u%04X", wc);
|
swprintf(buf, BUF_LEN, L"\\u%04X", (int)wc);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), "\\U%06X", wc);
|
swprintf(buf, BUF_LEN, L"\\U%06X", (int)wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
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) {
|
static void output_bind_command(std::vector<wchar_t> &bind_chars) {
|
||||||
if (bind_chars.size()) {
|
if (bind_chars.size()) {
|
||||||
fputs("bind ", stdout);
|
fputws(L"bind ", stdout);
|
||||||
for (size_t i = 0; i < bind_chars.size(); i++) {
|
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();
|
bind_chars.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_info_about_char(wchar_t wc) {
|
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) {
|
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();
|
double now = timef();
|
||||||
long long int delta_tstamp_us = 1000000 * (now - prev_tstamp);
|
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) {
|
if (delta_tstamp_us >= 1000000) {
|
||||||
fprintf(stderr, " ");
|
fwprintf(stderr, L" ");
|
||||||
} else {
|
} 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;
|
return now;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +210,7 @@ static void process_input(bool continuous_mode) {
|
||||||
double prev_tstamp = 0.0;
|
double prev_tstamp = 0.0;
|
||||||
std::vector<wchar_t> bind_chars;
|
std::vector<wchar_t> bind_chars;
|
||||||
|
|
||||||
fprintf(stderr, "Press a key\n\n");
|
fwprintf(stderr, L"Press a key\n\n");
|
||||||
while (keep_running) {
|
while (keep_running) {
|
||||||
wchar_t wc;
|
wchar_t wc;
|
||||||
if (reader_interrupted()) {
|
if (reader_interrupted()) {
|
||||||
|
@ -232,7 +234,7 @@ static void process_input(bool continuous_mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_exit(wc)) {
|
if (should_exit(wc)) {
|
||||||
fprintf(stderr, "\nExiting at your request.\n");
|
fwprintf(stderr, L"\nExiting at your request.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,11 +297,11 @@ static void setup_and_process_keys(bool continuous_mode) {
|
||||||
install_our_signal_handlers();
|
install_our_signal_handlers();
|
||||||
|
|
||||||
if (continuous_mode) {
|
if (continuous_mode) {
|
||||||
fprintf(stderr, "\n");
|
fwprintf(stderr, L"\n");
|
||||||
fprintf(stderr, "To terminate this program type \"exit\" or \"quit\" in this window,\n");
|
fwprintf(stderr, L"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",
|
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);
|
shell_modes.c_cc[VINTR] + 0x40, shell_modes.c_cc[VEOF] + 0x40);
|
||||||
fprintf(stderr, "\n");
|
fwprintf(stderr, L"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
process_input(continuous_mode);
|
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) {
|
while (!error && (opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 0: {
|
case 0: {
|
||||||
fprintf(stderr, "getopt_long() unexpectedly returned zero\n");
|
fwprintf(stderr, L"getopt_long() unexpectedly returned zero\n");
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -378,12 +380,12 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
if (argc != 0) {
|
if (argc != 0) {
|
||||||
fprintf(stderr, "Expected no arguments, got %d\n", argc);
|
fwprintf(stderr, L"Expected no arguments, got %d\n", argc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isatty(STDIN_FILENO)) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -766,19 +766,10 @@ static void test_cancellation() {
|
||||||
// we cancel we expect no output.
|
// we cancel we expect no output.
|
||||||
test_1_cancellation(L"echo (while true ; echo blah ; end)");
|
test_1_cancellation(L"echo (while true ; echo blah ; end)");
|
||||||
|
|
||||||
fprintf(stderr, ".");
|
|
||||||
|
|
||||||
// Nasty infinite loop that doesn't actually execute anything.
|
// Nasty infinite loop that doesn't actually execute anything.
|
||||||
test_1_cancellation(L"echo (while true ; end) (while true ; end) (while true ; end)");
|
test_1_cancellation(L"echo (while true ; end) (while true ; end) (while true ; end)");
|
||||||
fprintf(stderr, ".");
|
|
||||||
|
|
||||||
test_1_cancellation(L"while true ; end");
|
test_1_cancellation(L"while true ; end");
|
||||||
fprintf(stderr, ".");
|
|
||||||
|
|
||||||
test_1_cancellation(L"for i in (while true ; end) ; end");
|
test_1_cancellation(L"for i in (while true ; end) ; end");
|
||||||
fprintf(stderr, ".");
|
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
// Restore signal handling.
|
// Restore signal handling.
|
||||||
proc_pop_interactive();
|
proc_pop_interactive();
|
||||||
|
@ -1645,8 +1636,8 @@ struct pager_layout_testcase_t {
|
||||||
|
|
||||||
wcstring text = sd.line(0).to_string();
|
wcstring text = sd.line(0).to_string();
|
||||||
if (text != expected) {
|
if (text != expected) {
|
||||||
fprintf(stderr, "width %zu got <%ls>, expected <%ls>\n", this->width, text.c_str(),
|
fwprintf(stderr, L"width %zu got <%ls>, expected <%ls>\n", this->width,
|
||||||
expected.c_str());
|
text.c_str(), expected.c_str());
|
||||||
}
|
}
|
||||||
do_test(text == expected);
|
do_test(text == expected);
|
||||||
}
|
}
|
||||||
|
@ -2175,8 +2166,8 @@ static void test_1_completion(wcstring line, const wcstring &completion, complet
|
||||||
wcstring result =
|
wcstring result =
|
||||||
completion_apply_to_command_line(completion, flags, line, &cursor_pos, append_only);
|
completion_apply_to_command_line(completion, flags, line, &cursor_pos, append_only);
|
||||||
if (result != expected) {
|
if (result != expected) {
|
||||||
fprintf(stderr, "line %ld: %ls + %ls -> [%ls], expected [%ls]\n", source_line, line.c_str(),
|
fwprintf(stderr, L"line %ld: %ls + %ls -> [%ls], expected [%ls]\n", source_line,
|
||||||
completion.c_str(), result.c_str(), expected.c_str());
|
line.c_str(), completion.c_str(), result.c_str(), expected.c_str());
|
||||||
}
|
}
|
||||||
do_test(result == expected);
|
do_test(result == expected);
|
||||||
do_test(cursor_pos == out_cursor_pos);
|
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");
|
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) {
|
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;
|
bool log_it = true;
|
||||||
unsigned long max_len = 5;
|
unsigned long max_len = 5;
|
||||||
for (unsigned long len = 0; len < max_len; len++) {
|
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).
|
// We wish to look at all permutations of 4 elements of 'fuzzes' (with replacement).
|
||||||
// Construct an int and keep incrementing it.
|
// Construct an int and keep incrementing it.
|
||||||
|
@ -3234,7 +3225,7 @@ static void test_new_parser_fuzzing(void) {
|
||||||
&src)) {
|
&src)) {
|
||||||
parse_tree_from_string(src, parse_flag_continue_after_error, &node_tree, &errors);
|
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();
|
double end = timef();
|
||||||
if (log_it) say(L"All fuzzed in %f seconds!", end - start);
|
if (log_it) say(L"All fuzzed in %f seconds!", end - start);
|
||||||
|
@ -4121,8 +4112,8 @@ int main(int argc, char **argv) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
if (!strcmp(wd, "/")) {
|
if (!strcmp(wd, "/")) {
|
||||||
fprintf(stderr,
|
fwprintf(stderr,
|
||||||
"Unable to find 'tests' directory, which should contain file test.fish\n");
|
L"Unable to find 'tests' directory, which should contain file test.fish\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (chdir(dirname(wd)) < 0) {
|
if (chdir(dirname(wd)) < 0) {
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
|
||||||
#if 0
|
#if 0
|
||||||
// Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809.
|
// 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);
|
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
|
#endif
|
||||||
|
|
||||||
// Walk the node tree.
|
// Walk the node tree.
|
||||||
|
|
|
@ -374,7 +374,7 @@ int input_init() {
|
||||||
} else {
|
} else {
|
||||||
debug(0, _(L"Using fallback terminal type '%ls'"), DEFAULT_TERM);
|
debug(0, _(L"Using fallback terminal type '%ls'"), DEFAULT_TERM);
|
||||||
}
|
}
|
||||||
putc('\n', stderr);
|
fputwc(L'\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_terminfo_init();
|
input_terminfo_init();
|
||||||
|
|
22
src/io.cpp
22
src/io.cpp
|
@ -6,6 +6,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
|
@ -15,19 +16,20 @@
|
||||||
|
|
||||||
io_data_t::~io_data_t() {}
|
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 {
|
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 {
|
void io_buffer_t::print() const {
|
||||||
fprintf(stderr, "buffer %p (input: %s, size %lu)\n", out_buffer_ptr(), is_input ? "yes" : "no",
|
fwprintf(stderr, L"buffer %p (input: %s, size %lu)\n", out_buffer_ptr(),
|
||||||
(unsigned long)out_buffer_size());
|
is_input ? "yes" : "no", (unsigned long)out_buffer_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_buffer_t::read() {
|
void io_buffer_t::read() {
|
||||||
|
@ -139,21 +141,21 @@ void io_print(const io_chain_t &chain)
|
||||||
{
|
{
|
||||||
if (chain.empty())
|
if (chain.empty())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Empty chain %p\n", &chain);
|
fwprintf(stderr, L"Empty chain %p\n", &chain);
|
||||||
return;
|
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++)
|
for (size_t i=0; i < chain.size(); i++)
|
||||||
{
|
{
|
||||||
const shared_ptr<io_data_t> &io = chain.at(i);
|
const shared_ptr<io_data_t> &io = chain.at(i);
|
||||||
if (io.get() == NULL)
|
if (io.get() == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\t(null)\n");
|
fwprintf(stderr, L"\t(null)\n");
|
||||||
}
|
}
|
||||||
else
|
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();
|
io->print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -228,7 +227,7 @@ void iothread_service_completion(void) {
|
||||||
} else if (wakeup_byte == IO_SERVICE_RESULT_QUEUE) {
|
} else if (wakeup_byte == IO_SERVICE_RESULT_QUEUE) {
|
||||||
iothread_service_result_queue();
|
iothread_service_result_queue();
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown wakeup byte %02x in %s\n", wakeup_byte, __FUNCTION__);
|
debug(0, "Unknown wakeup byte %02x in %s", wakeup_byte, __FUNCTION__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define PARSE_ASSERT(a) assert(a)
|
#define PARSE_ASSERT(a) assert(a)
|
||||||
#define PARSER_DIE() \
|
#define PARSER_DIE() \
|
||||||
do { \
|
do { \
|
||||||
fprintf(stderr, "Parser dying!\n"); \
|
debug(0, "Parser dying!"); \
|
||||||
exit_without_destructors(-1); \
|
exit_without_destructors(-1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// IMPORTANT: If the following enum table is modified you must also update token_enum_map below.
|
// IMPORTANT: If the following enum table is modified you must also update token_enum_map below.
|
||||||
|
|
|
@ -441,7 +441,7 @@ parse_execution_result_t parse_execution_context_t::run_block_statement(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
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();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +700,7 @@ parse_execution_result_t parse_execution_context_t::report_errors(
|
||||||
const parse_error_list_t &error_list) const {
|
const parse_error_list_t &error_list) const {
|
||||||
if (!parser->cancellation_requested) {
|
if (!parser->cancellation_requested) {
|
||||||
if (error_list.empty()) {
|
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.
|
// 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);
|
parser->get_backtrace(src, error_list, &backtrace_and_desc);
|
||||||
|
|
||||||
// Print it.
|
// 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;
|
return parse_execution_errored;
|
||||||
}
|
}
|
||||||
|
@ -1034,8 +1036,7 @@ bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
// Should be unreachable.
|
// Should be unreachable.
|
||||||
fprintf(stderr, "Unexpected redirection type %ld. aborting.\n",
|
debug(0, "Unexpected redirection type %ld.", (long)redirect_type);
|
||||||
(long)redirect_type);
|
|
||||||
PARSER_DIE();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1133,8 +1134,8 @@ parse_execution_result_t parse_execution_context_t::populate_job_process(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "'%ls' not handled by new parser yet\n",
|
debug(0, L"'%ls' not handled by new parser yet.",
|
||||||
specific_statement.describe().c_str());
|
specific_statement.describe().c_str());
|
||||||
PARSER_DIE();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1426,8 +1427,7 @@ parse_execution_result_t parse_execution_context_t::eval_node_at_offset(
|
||||||
default: {
|
default: {
|
||||||
// In principle, we could support other node types. However we never expect to be passed
|
// In principle, we could support other node types. However we never expect to be passed
|
||||||
// them - see above.
|
// them - see above.
|
||||||
fprintf(stderr, "Unexpected node %ls found in %s\n", node.describe().c_str(),
|
debug(0, "Unexpected node %ls found in %s", node.describe().c_str(), __FUNCTION__);
|
||||||
__FUNCTION__);
|
|
||||||
PARSER_DIE();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,21 +481,21 @@ const production_element_t *parse_productions::production_for_token(parse_token_
|
||||||
case parse_token_type_background:
|
case parse_token_type_background:
|
||||||
case parse_token_type_end:
|
case parse_token_type_end:
|
||||||
case parse_token_type_terminate: {
|
case parse_token_type_terminate: {
|
||||||
fprintf(stderr, "Terminal token type %ls passed to %s\n",
|
debug(0, "Terminal token type %ls passed to %s", token_type_description(node_type),
|
||||||
token_type_description(node_type), __FUNCTION__);
|
__FUNCTION__);
|
||||||
PARSER_DIE();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case parse_special_type_parse_error:
|
case parse_special_type_parse_error:
|
||||||
case parse_special_type_tokenizer_error:
|
case parse_special_type_tokenizer_error:
|
||||||
case parse_special_type_comment: {
|
case parse_special_type_comment: {
|
||||||
fprintf(stderr, "Special type %ls passed to %s\n", token_type_description(node_type),
|
debug(0, "Special type %ls passed to %s\n", token_type_description(node_type),
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
PARSER_DIE();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case token_type_invalid: {
|
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();
|
PARSER_DIE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
// 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));
|
const wcstring d = format_string(L"unknown_token_type_%ld", static_cast<long>(type));
|
||||||
wchar_t *d2 = new wchar_t[d.size() + 1];
|
wchar_t *d2 = new wchar_t[d.size() + 1];
|
||||||
|
// cppcheck-suppress memleak
|
||||||
return std::wcscpy(d2, d.c_str());
|
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.
|
// 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));
|
const wcstring d = format_string(L"unknown_keyword_%ld", static_cast<long>(type));
|
||||||
wchar_t *d2 = new wchar_t[d.size() + 1];
|
wchar_t *d2 = new wchar_t[d.size() + 1];
|
||||||
|
// cppcheck-suppress memleak
|
||||||
return std::wcscpy(d2, d.c_str());
|
return std::wcscpy(d2, d.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,8 +260,7 @@ static inline parse_token_type_t parse_token_type_from_tokenizer_token(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "Bad token type %d passed to %s\n", (int)tokenizer_token_type,
|
debug(0, "Bad token type %d passed to %s", (int)tokenizer_token_type, __FUNCTION__);
|
||||||
__FUNCTION__);
|
|
||||||
DIE("bad token type");
|
DIE("bad token type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -420,17 +421,17 @@ class parse_ll_t {
|
||||||
bool logit = false;
|
bool logit = false;
|
||||||
if (logit) {
|
if (logit) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
fprintf(stderr, "Applying production:\n");
|
fwprintf(stderr, L"Applying production:\n");
|
||||||
for (int i = 0;; i++) {
|
for (int i = 0;; i++) {
|
||||||
production_element_t elem = production[i];
|
production_element_t elem = production[i];
|
||||||
if (!production_element_is_valid(elem)) break; // all done, bail out
|
if (!production_element_is_valid(elem)) break; // all done, bail out
|
||||||
parse_token_type_t type = production_element_type(elem);
|
parse_token_type_t type = production_element_type(elem);
|
||||||
parse_keyword_t keyword = production_element_keyword(elem);
|
parse_keyword_t keyword = production_element_keyword(elem);
|
||||||
fprintf(stderr, "\t%ls <%ls>\n", token_type_description(type),
|
fwprintf(stderr, L"\t%ls <%ls>\n", token_type_description(type),
|
||||||
keyword_description(keyword));
|
keyword_description(keyword));
|
||||||
count++;
|
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
|
// 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++) {
|
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
|
#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) {
|
void parse_ll_t::accept_tokens(parse_token_t token1, parse_token_t token2) {
|
||||||
bool logit = false;
|
bool logit = false;
|
||||||
if (logit) {
|
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);
|
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 (top_node_handle_terminal_types(token1)) {
|
||||||
if (logit) {
|
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;
|
// consumed = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1184,8 +1185,8 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t parse_flags,
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//wcstring result = dump_tree(this->parser->nodes, str);
|
//wcstring result = dump_tree(this->parser->nodes, str);
|
||||||
//fprintf(stderr, "Tree (%ld nodes):\n%ls", this->parser->nodes.size(), result.c_str());
|
//fwprintf(stderr, L"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"%lu nodes, node size %lu, %lu bytes\n", output->size(), sizeof(parse_node_t),
|
||||||
output->size() * sizeof(parse_node_t));
|
output->size() * sizeof(parse_node_t));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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);
|
this->get_backtrace(cmd, error_list, &backtrace_and_desc);
|
||||||
|
|
||||||
// Print it.
|
// Print it.
|
||||||
fprintf(stderr, "%ls", backtrace_and_desc.c_str());
|
fwprintf(stderr, L"%ls\n", backtrace_and_desc.c_str());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return this->eval_acquiring_tree(cmd, io, block_type, moved_ref<parse_node_tree_t>(tree));
|
return this->eval_acquiring_tree(cmd, io, block_type, moved_ref<parse_node_tree_t>(tree));
|
||||||
|
|
|
@ -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"The error was '%s'."), strerror(saved_errno));
|
||||||
debug(0, _(L"Please set $%ls to a directory where you have write access."), env_var);
|
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,
|
static void path_create(wcstring &path, const wcstring &xdg_var, const wcstring &which_dir,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#if FISH_USE_POSIX_SPAWN
|
#if FISH_USE_POSIX_SPAWN
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
|
@ -141,7 +142,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
|
||||||
|
|
||||||
switch (io->io_mode) {
|
switch (io->io_mode) {
|
||||||
case IO_CLOSE: {
|
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)) {
|
if (close(io->fd)) {
|
||||||
debug_safe_int(0, "Failed to close file descriptor %s", io->fd);
|
debug_safe_int(0, "Failed to close file descriptor %s", io->fd);
|
||||||
safe_perror("close");
|
safe_perror("close");
|
||||||
|
@ -180,7 +181,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
|
||||||
case IO_FD: {
|
case IO_FD: {
|
||||||
int old_fd = static_cast<const io_fd_t *>(io)->old_fd;
|
int old_fd = static_cast<const io_fd_t *>(io)->old_fd;
|
||||||
if (log_redirections)
|
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.
|
// This call will sometimes fail, but that is ok, this is just a precausion.
|
||||||
close(io->fd);
|
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).
|
// 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);
|
unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
|
||||||
#if 0
|
#if 0
|
||||||
debug( 0, L"%ls %ls on fd %d (%d %d)", write_pipe?L"write":L"read",
|
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->io_mode == IO_BUFFER)?L"buffer":L"pipe", io->fd, io->pipe_fd[0],
|
||||||
io->pipe_fd[1]);
|
io->pipe_fd[1]);
|
||||||
#endif
|
#endif
|
||||||
if (log_redirections)
|
if (log_redirections)
|
||||||
fprintf(stderr, "%d: %s dup %d to %d\n", getpid(),
|
fwprintf(stderr, L"%d: %s dup %d to %d\n", getpid(),
|
||||||
io->io_mode == IO_BUFFER ? "buffer" : "pipe",
|
io->io_mode == IO_BUFFER ? "buffer" : "pipe",
|
||||||
io_pipe->pipe_fd[write_pipe_idx], io->fd);
|
io_pipe->pipe_fd[write_pipe_idx], io->fd);
|
||||||
if (dup2(io_pipe->pipe_fd[write_pipe_idx], io->fd) != io->fd) {
|
if (dup2(io_pipe->pipe_fd[write_pipe_idx], io->fd) != io->fd) {
|
||||||
debug_safe(1, LOCAL_PIPE_ERROR);
|
debug_safe(1, LOCAL_PIPE_ERROR);
|
||||||
safe_perror("dup2");
|
safe_perror("dup2");
|
||||||
|
|
|
@ -280,7 +280,7 @@ static void mark_process_status(process_t *p, int status) {
|
||||||
} else {
|
} else {
|
||||||
// This should never be reached.
|
// This should never be reached.
|
||||||
p->completed = 1;
|
p->completed = 1;
|
||||||
fprintf(stderr, "Process %ld exited abnormally\n", (long)p->pid);
|
debug(1, "Process %ld exited abnormally", (long)p->pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2424,7 +2424,7 @@ const wchar_t *reader_readline(int nchars) {
|
||||||
is_interactive_read = 1;
|
is_interactive_read = 1;
|
||||||
c = input_readch();
|
c = input_readch();
|
||||||
is_interactive_read = was_interactive_read;
|
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)) {
|
if (((!fish_reserved_codepoint(c))) && (c > 31) && (c != 127) && can_read(0)) {
|
||||||
wchar_t arr[READAHEAD_MAX + 1];
|
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)) {
|
if (command_ends_paging(c, focused_on_search_field)) {
|
||||||
clear_pager();
|
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) {
|
switch (c) {
|
||||||
// Go to beginning of line.
|
// 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.
|
// up to the end of the token we're completing.
|
||||||
const wcstring buffcpy = wcstring(cmdsub_begin, token_end);
|
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 |
|
complete_flags_t complete_flags = COMPLETION_REQUEST_DEFAULT |
|
||||||
COMPLETION_REQUEST_DESCRIPTIONS |
|
COMPLETION_REQUEST_DESCRIPTIONS |
|
||||||
COMPLETION_REQUEST_FUZZY_MATCH;
|
COMPLETION_REQUEST_FUZZY_MATCH;
|
||||||
|
|
|
@ -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) {
|
if ((s->desired.cursor.x + cw) > screen_width) {
|
||||||
// Current line is soft wrapped (assuming we support it).
|
// Current line is soft wrapped (assuming we support it).
|
||||||
s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
|
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();
|
line_no = (int)s->desired.line_count();
|
||||||
s->desired.add_line();
|
s->desired.add_line();
|
||||||
|
|
Loading…
Reference in a new issue