mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-28 04:35:09 +00:00
trace: Port trace to Rust
This commit is contained in:
parent
bc04abe3ec
commit
3ae16a5b95
14 changed files with 111 additions and 83 deletions
|
@ -123,8 +123,7 @@ set(FISH_SRCS
|
||||||
src/pager.cpp src/parse_execution.cpp src/parse_tree.cpp src/parse_util.cpp
|
src/pager.cpp src/parse_execution.cpp src/parse_tree.cpp src/parse_util.cpp
|
||||||
src/parser.cpp src/parser_keywords.cpp src/path.cpp src/postfork.cpp
|
src/parser.cpp src/parser_keywords.cpp src/path.cpp src/postfork.cpp
|
||||||
src/proc.cpp src/re.cpp src/reader.cpp src/screen.cpp
|
src/proc.cpp src/re.cpp src/reader.cpp src/screen.cpp
|
||||||
src/signals.cpp src/tinyexpr.cpp
|
src/signals.cpp src/tinyexpr.cpp src/utf8.cpp
|
||||||
src/trace.cpp src/utf8.cpp
|
|
||||||
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp
|
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp
|
||||||
src/wutil.cpp src/fds.cpp src/rustffi.cpp
|
src/wutil.cpp src/fds.cpp src/rustffi.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -39,6 +39,7 @@ fn main() -> miette::Result<()> {
|
||||||
"src/timer.rs",
|
"src/timer.rs",
|
||||||
"src/tokenizer.rs",
|
"src/tokenizer.rs",
|
||||||
"src/topic_monitor.rs",
|
"src/topic_monitor.rs",
|
||||||
|
"src/trace.rs",
|
||||||
"src/util.rs",
|
"src/util.rs",
|
||||||
"src/wait_handle.rs",
|
"src/wait_handle.rs",
|
||||||
"src/builtins/shared.rs",
|
"src/builtins/shared.rs",
|
||||||
|
|
|
@ -56,6 +56,7 @@ include_cpp! {
|
||||||
generate!("valid_var_name_char")
|
generate!("valid_var_name_char")
|
||||||
|
|
||||||
generate!("get_flog_file_fd")
|
generate!("get_flog_file_fd")
|
||||||
|
generate!("log_extra_to_flog_file")
|
||||||
|
|
||||||
generate!("parse_util_unescape_wildcards")
|
generate!("parse_util_unescape_wildcards")
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ mod ffi_init;
|
||||||
mod ffi_tests;
|
mod ffi_tests;
|
||||||
mod flog;
|
mod flog;
|
||||||
mod future_feature_flags;
|
mod future_feature_flags;
|
||||||
|
mod global_safety;
|
||||||
mod job_group;
|
mod job_group;
|
||||||
mod locale;
|
mod locale;
|
||||||
mod nix;
|
mod nix;
|
||||||
|
@ -42,6 +43,7 @@ mod threads;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
mod topic_monitor;
|
mod topic_monitor;
|
||||||
|
mod trace;
|
||||||
mod util;
|
mod util;
|
||||||
mod wait_handle;
|
mod wait_handle;
|
||||||
mod wchar;
|
mod wchar;
|
||||||
|
|
74
fish-rust/src/trace.rs
Normal file
74
fish-rust/src/trace.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
use crate::{
|
||||||
|
common::{escape_string, EscapeStringStyle},
|
||||||
|
ffi::{self, parser_t, wcharz_t},
|
||||||
|
global_safety::RelaxedAtomicBool,
|
||||||
|
wchar::{self, wstr, L},
|
||||||
|
wchar_ffi::WCharToFFI,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cxx::bridge]
|
||||||
|
mod trace_ffi {
|
||||||
|
extern "C++" {
|
||||||
|
include!("wutil.h");
|
||||||
|
include!("parser.h");
|
||||||
|
type wcharz_t = super::wcharz_t;
|
||||||
|
type parser_t = super::parser_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "Rust" {
|
||||||
|
fn trace_set_enabled(do_enable: bool);
|
||||||
|
fn trace_enabled(parser: &parser_t) -> bool;
|
||||||
|
#[cxx_name = "trace_argv"]
|
||||||
|
fn trace_argv_ffi(parser: &parser_t, command: wcharz_t, args: &Vec<wcharz_t>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DO_TRACE: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
|
|
||||||
|
pub fn trace_set_enabled(do_enable: bool) {
|
||||||
|
DO_TRACE.store(do_enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return whether tracing is enabled.
|
||||||
|
pub fn trace_enabled(parser: &parser_t) -> bool {
|
||||||
|
let ld = parser.ffi_libdata_pod_const();
|
||||||
|
if ld.suppress_fish_trace {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DO_TRACE.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trace an "argv": a list of arguments where the first is the command.
|
||||||
|
// Allow the `&Vec` parameter as this function only exists temporarily for the FFI
|
||||||
|
#[allow(clippy::ptr_arg)]
|
||||||
|
fn trace_argv_ffi(parser: &parser_t, command: wcharz_t, args: &Vec<wcharz_t>) {
|
||||||
|
let command: wchar::WString = command.into();
|
||||||
|
let args: Vec<wchar::WString> = args.iter().map(Into::into).collect();
|
||||||
|
let args_ref: Vec<&wstr> = args.iter().map(wchar::WString::as_utfstr).collect();
|
||||||
|
trace_argv(parser, command.as_utfstr(), &args_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace_argv(parser: &parser_t, command: &wstr, args: &[&wstr]) {
|
||||||
|
// Format into a string to prevent interleaving with flog in other threads.
|
||||||
|
// Add the + prefix.
|
||||||
|
let mut trace_text = L!("-").repeat(parser.blocks_size() - 1);
|
||||||
|
trace_text.push('>');
|
||||||
|
|
||||||
|
if !command.is_empty() {
|
||||||
|
trace_text.push(' ');
|
||||||
|
trace_text.push_utfstr(command);
|
||||||
|
}
|
||||||
|
for arg in args {
|
||||||
|
trace_text.push(' ');
|
||||||
|
trace_text.push_utfstr(&escape_string(arg, EscapeStringStyle::default()));
|
||||||
|
}
|
||||||
|
trace_text.push('\n');
|
||||||
|
ffi::log_extra_to_flog_file(&trace_text.to_ffi());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience helper to trace a single string if tracing is enabled.
|
||||||
|
pub fn trace_if_enabled(parser: &parser_t, command: &wstr, args: &[&wstr]) {
|
||||||
|
if trace_enabled(parser) {
|
||||||
|
trace_argv(parser, command, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,7 @@
|
||||||
#include "cxx.h"
|
#include "cxx.h"
|
||||||
#include "cxxgen.h"
|
#include "cxxgen.h"
|
||||||
#include "fallback.h" // IWYU pragma: keep
|
#include "fallback.h" // IWYU pragma: keep
|
||||||
|
#include "ffi.h"
|
||||||
#include "flog.h"
|
#include "flog.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "null_terminated_array.h"
|
#include "null_terminated_array.h"
|
||||||
|
@ -565,13 +566,8 @@ static maybe_t<RustBuiltin> try_get_rust_builtin(const wcstring &cmd) {
|
||||||
|
|
||||||
static maybe_t<int> builtin_run_rust(parser_t &parser, io_streams_t &streams,
|
static maybe_t<int> builtin_run_rust(parser_t &parser, io_streams_t &streams,
|
||||||
const wcstring_list_t &argv, RustBuiltin builtin) {
|
const wcstring_list_t &argv, RustBuiltin builtin) {
|
||||||
::rust::Vec<wcharz_t> rust_argv;
|
|
||||||
for (const wcstring &arg : argv) {
|
|
||||||
rust_argv.emplace_back(arg.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
int status_code;
|
int status_code;
|
||||||
bool update_status = rust_run_builtin(parser, streams, rust_argv, builtin, status_code);
|
bool update_status = rust_run_builtin(parser, streams, to_rust_string_vec(argv), builtin, status_code);
|
||||||
if (update_status) {
|
if (update_status) {
|
||||||
return status_code;
|
return status_code;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "termsize.h"
|
#include "termsize.h"
|
||||||
#include "trace.h"
|
#include "trace.rs.h"
|
||||||
#include "wcstringutil.h"
|
#include "wcstringutil.h"
|
||||||
#include "wutil.h"
|
#include "wutil.h"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include "trace.rs.h"
|
||||||
#ifdef HAVE_SIGINFO_H
|
#ifdef HAVE_SIGINFO_H
|
||||||
#include <siginfo.h>
|
#include <siginfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "fallback.h" // IWYU pragma: keep
|
#include "fallback.h" // IWYU pragma: keep
|
||||||
#include "fds.h"
|
#include "fds.h"
|
||||||
|
#include "ffi.h"
|
||||||
#include "flog.h"
|
#include "flog.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "global_safety.h"
|
#include "global_safety.h"
|
||||||
|
@ -48,7 +50,7 @@
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "redirection.h"
|
#include "redirection.h"
|
||||||
#include "timer.rs.h"
|
#include "timer.rs.h"
|
||||||
#include "trace.h"
|
#include "trace.rs.h"
|
||||||
#include "wcstringutil.h"
|
#include "wcstringutil.h"
|
||||||
#include "wutil.h" // IWYU pragma: keep
|
#include "wutil.h" // IWYU pragma: keep
|
||||||
|
|
||||||
|
@ -827,9 +829,7 @@ static launch_result_t exec_process_in_job(parser_t &parser, process_t *p,
|
||||||
|
|
||||||
// Maybe trace this process.
|
// Maybe trace this process.
|
||||||
// TODO: 'and' and 'or' will not show.
|
// TODO: 'and' and 'or' will not show.
|
||||||
if (trace_enabled(parser)) {
|
trace_if_enabled(parser, L"", p->argv());
|
||||||
trace_argv(parser, nullptr, p->argv());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The IO chain for this process.
|
// The IO chain for this process.
|
||||||
io_chain_t process_net_io_chain = block_io;
|
io_chain_t process_net_io_chain = block_io;
|
||||||
|
|
17
src/ffi.h
17
src/ffi.h
|
@ -2,6 +2,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "cxx.h"
|
#include "cxx.h"
|
||||||
|
#include "trace.rs.h"
|
||||||
#if INCLUDE_RUST_HEADERS
|
#if INCLUDE_RUST_HEADERS
|
||||||
// For some unknown reason, the definition of rust::Box is in this particular header:
|
// For some unknown reason, the definition of rust::Box is in this particular header:
|
||||||
#include "parse_constants.rs.h"
|
#include "parse_constants.rs.h"
|
||||||
|
@ -13,3 +14,19 @@ inline std::shared_ptr<T> box_to_shared_ptr(rust::Box<T> &&value) {
|
||||||
std::shared_ptr<T> shared(ptr, [](T *ptr) { rust::Box<T>::from_raw(ptr); });
|
std::shared_ptr<T> shared(ptr, [](T *ptr) { rust::Box<T>::from_raw(ptr); });
|
||||||
return shared;
|
return shared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static rust::Vec<wcharz_t> to_rust_string_vec(const wcstring_list_t &strings) {
|
||||||
|
rust::Vec<wcharz_t> rust_strings;
|
||||||
|
rust_strings.reserve(strings.size());
|
||||||
|
for (const wcstring &string : strings) {
|
||||||
|
rust_strings.emplace_back(string.c_str());
|
||||||
|
}
|
||||||
|
return rust_strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void trace_if_enabled(const parser_t &parser, wcharz_t command,
|
||||||
|
const wcstring_list_t &args = {}) {
|
||||||
|
if (trace_enabled(parser)) {
|
||||||
|
trace_argv(parser, command, to_rust_string_vec(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "timer.rs.h"
|
#include "timer.rs.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include "trace.h"
|
#include "trace.rs.h"
|
||||||
#include "wildcard.h"
|
#include "wildcard.h"
|
||||||
#include "wutil.h"
|
#include "wutil.h"
|
||||||
|
|
||||||
|
@ -390,6 +390,7 @@ end_execution_reason_t parse_execution_context_t::run_function_statement(
|
||||||
if (result != end_execution_reason_t::ok) {
|
if (result != end_execution_reason_t::ok) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_if_enabled(*parser, L"function", arguments);
|
trace_if_enabled(*parser, L"function", arguments);
|
||||||
null_output_stream_t outs;
|
null_output_stream_t outs;
|
||||||
string_output_stream_t errs;
|
string_output_stream_t errs;
|
||||||
|
@ -537,7 +538,8 @@ end_execution_reason_t parse_execution_context_t::run_switch_statement(
|
||||||
}
|
}
|
||||||
|
|
||||||
end_execution_reason_t result = end_execution_reason_t::ok;
|
end_execution_reason_t result = end_execution_reason_t::ok;
|
||||||
if (trace_enabled(*parser)) trace_argv(*parser, L"switch", {switch_value_expanded});
|
|
||||||
|
trace_if_enabled(*parser, L"switch", {switch_value_expanded});
|
||||||
block_t *sb = parser->push_block(block_t::switch_block());
|
block_t *sb = parser->push_block(block_t::switch_block());
|
||||||
|
|
||||||
// Expand case statements.
|
// Expand case statements.
|
||||||
|
|
|
@ -514,6 +514,7 @@ job_t *parser_t::job_get_from_pid(int64_t pid, size_t &job_pos) const {
|
||||||
library_data_pod_t *parser_t::ffi_libdata_pod() { return &library_data; }
|
library_data_pod_t *parser_t::ffi_libdata_pod() { return &library_data; }
|
||||||
|
|
||||||
job_t *parser_t::ffi_job_get_from_pid(int pid) const { return job_get_from_pid(pid); }
|
job_t *parser_t::ffi_job_get_from_pid(int pid) const { return job_get_from_pid(pid); }
|
||||||
|
const library_data_pod_t &parser_t::ffi_libdata_pod_const() const { return library_data; }
|
||||||
|
|
||||||
profile_item_t *parser_t::create_profile_item() {
|
profile_item_t *parser_t::create_profile_item() {
|
||||||
if (g_profiling_active) {
|
if (g_profiling_active) {
|
||||||
|
|
|
@ -383,6 +383,8 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
/// Return the list of blocks. The first block is at the top.
|
/// Return the list of blocks. The first block is at the top.
|
||||||
const std::deque<block_t> &blocks() const { return block_list; }
|
const std::deque<block_t> &blocks() const { return block_list; }
|
||||||
|
|
||||||
|
size_t blocks_size() const { return block_list.size(); }
|
||||||
|
|
||||||
/// Get the list of jobs.
|
/// Get the list of jobs.
|
||||||
job_list_t &jobs() { return job_list; }
|
job_list_t &jobs() { return job_list; }
|
||||||
const job_list_t &jobs() const { return job_list; }
|
const job_list_t &jobs() const { return job_list; }
|
||||||
|
@ -500,6 +502,7 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
RustFFIJobList ffi_jobs() const;
|
RustFFIJobList ffi_jobs() const;
|
||||||
library_data_pod_t *ffi_libdata_pod();
|
library_data_pod_t *ffi_libdata_pod();
|
||||||
job_t *ffi_job_get_from_pid(int pid) const;
|
job_t *ffi_job_get_from_pid(int pid) const;
|
||||||
|
const library_data_pod_t &ffi_libdata_pod_const() const;
|
||||||
|
|
||||||
/// autocxx junk.
|
/// autocxx junk.
|
||||||
bool ffi_has_funtion_block() const;
|
bool ffi_has_funtion_block() const;
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
#include "config.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
#include "trace.h"
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "flog.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
static bool do_trace = false;
|
|
||||||
|
|
||||||
void trace_set_enabled(bool do_enable) { do_trace = do_enable; }
|
|
||||||
|
|
||||||
bool trace_enabled(const parser_t &parser) {
|
|
||||||
const auto &ld = parser.libdata();
|
|
||||||
if (ld.suppress_fish_trace) return false;
|
|
||||||
return do_trace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trace an "argv": a list of arguments where the first is the command.
|
|
||||||
void trace_argv(const parser_t &parser, const wchar_t *command, const wcstring_list_t &argv) {
|
|
||||||
// Format into a string to prevent interleaving with flog in other threads.
|
|
||||||
// Add the + prefix.
|
|
||||||
wcstring trace_text(parser.blocks().size() - 1, L'-');
|
|
||||||
trace_text.push_back(L'>');
|
|
||||||
|
|
||||||
if (command && command[0]) {
|
|
||||||
trace_text.push_back(L' ');
|
|
||||||
trace_text.append(command);
|
|
||||||
}
|
|
||||||
for (const wcstring &arg : argv) {
|
|
||||||
trace_text.push_back(L' ');
|
|
||||||
trace_text.append(escape_string(arg));
|
|
||||||
}
|
|
||||||
trace_text.push_back(L'\n');
|
|
||||||
log_extra_to_flog_file(trace_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void trace_if_enabled(const parser_t &parser, const wchar_t *command, const wcstring_list_t &argv) {
|
|
||||||
if (trace_enabled(parser)) trace_argv(parser, command, argv);
|
|
||||||
}
|
|
25
src/trace.h
25
src/trace.h
|
@ -1,25 +0,0 @@
|
||||||
/// Support for fish_trace.
|
|
||||||
#ifndef FISH_TRACE_H
|
|
||||||
#define FISH_TRACE_H
|
|
||||||
|
|
||||||
#include "config.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
class parser_t;
|
|
||||||
|
|
||||||
/// Trace an "argv": a list of arguments. Each argument is escaped.
|
|
||||||
/// If \p command is not null, it is traced first (and not escaped)
|
|
||||||
void trace_argv(const parser_t &parser, const wchar_t *command, const wcstring_list_t &argv);
|
|
||||||
|
|
||||||
/// \return whether tracing is enabled.
|
|
||||||
bool trace_enabled(const parser_t &parser);
|
|
||||||
|
|
||||||
/// Enable or disable tracing.
|
|
||||||
void trace_set_enabled(bool do_enable);
|
|
||||||
|
|
||||||
/// Convenience helper to trace a single string if tracing is enabled.
|
|
||||||
void trace_if_enabled(const parser_t &parser, const wchar_t *command,
|
|
||||||
const wcstring_list_t &argv = {});
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue