mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +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/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/signals.cpp src/tinyexpr.cpp
|
||||
src/trace.cpp src/utf8.cpp
|
||||
src/signals.cpp src/tinyexpr.cpp src/utf8.cpp
|
||||
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp
|
||||
src/wutil.cpp src/fds.cpp src/rustffi.cpp
|
||||
)
|
||||
|
|
|
@ -39,6 +39,7 @@ fn main() -> miette::Result<()> {
|
|||
"src/timer.rs",
|
||||
"src/tokenizer.rs",
|
||||
"src/topic_monitor.rs",
|
||||
"src/trace.rs",
|
||||
"src/util.rs",
|
||||
"src/wait_handle.rs",
|
||||
"src/builtins/shared.rs",
|
||||
|
|
|
@ -56,6 +56,7 @@ include_cpp! {
|
|||
generate!("valid_var_name_char")
|
||||
|
||||
generate!("get_flog_file_fd")
|
||||
generate!("log_extra_to_flog_file")
|
||||
|
||||
generate!("parse_util_unescape_wildcards")
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ mod ffi_init;
|
|||
mod ffi_tests;
|
||||
mod flog;
|
||||
mod future_feature_flags;
|
||||
mod global_safety;
|
||||
mod job_group;
|
||||
mod locale;
|
||||
mod nix;
|
||||
|
@ -42,6 +43,7 @@ mod threads;
|
|||
mod timer;
|
||||
mod tokenizer;
|
||||
mod topic_monitor;
|
||||
mod trace;
|
||||
mod util;
|
||||
mod wait_handle;
|
||||
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 "cxxgen.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "ffi.h"
|
||||
#include "flog.h"
|
||||
#include "io.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,
|
||||
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;
|
||||
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) {
|
||||
return status_code;
|
||||
} else {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "reader.h"
|
||||
#include "screen.h"
|
||||
#include "termsize.h"
|
||||
#include "trace.h"
|
||||
#include "trace.rs.h"
|
||||
#include "wcstringutil.h"
|
||||
#include "wutil.h"
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include "trace.rs.h"
|
||||
#ifdef HAVE_SIGINFO_H
|
||||
#include <siginfo.h>
|
||||
#endif
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "exec.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "fds.h"
|
||||
#include "ffi.h"
|
||||
#include "flog.h"
|
||||
#include "function.h"
|
||||
#include "global_safety.h"
|
||||
|
@ -48,7 +50,7 @@
|
|||
#include "reader.h"
|
||||
#include "redirection.h"
|
||||
#include "timer.rs.h"
|
||||
#include "trace.h"
|
||||
#include "trace.rs.h"
|
||||
#include "wcstringutil.h"
|
||||
#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.
|
||||
// TODO: 'and' and 'or' will not show.
|
||||
if (trace_enabled(parser)) {
|
||||
trace_argv(parser, nullptr, p->argv());
|
||||
}
|
||||
trace_if_enabled(parser, L"", p->argv());
|
||||
|
||||
// The IO chain for this process.
|
||||
io_chain_t process_net_io_chain = block_io;
|
||||
|
|
17
src/ffi.h
17
src/ffi.h
|
@ -2,6 +2,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "cxx.h"
|
||||
#include "trace.rs.h"
|
||||
#if INCLUDE_RUST_HEADERS
|
||||
// For some unknown reason, the definition of rust::Box is in this particular header:
|
||||
#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); });
|
||||
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 "timer.rs.h"
|
||||
#include "tokenizer.h"
|
||||
#include "trace.h"
|
||||
#include "trace.rs.h"
|
||||
#include "wildcard.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) {
|
||||
return result;
|
||||
}
|
||||
|
||||
trace_if_enabled(*parser, L"function", arguments);
|
||||
null_output_stream_t outs;
|
||||
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;
|
||||
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());
|
||||
|
||||
// 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; }
|
||||
|
||||
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() {
|
||||
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.
|
||||
const std::deque<block_t> &blocks() const { return block_list; }
|
||||
|
||||
size_t blocks_size() const { return block_list.size(); }
|
||||
|
||||
/// Get the list of jobs.
|
||||
job_list_t &jobs() { 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;
|
||||
library_data_pod_t *ffi_libdata_pod();
|
||||
job_t *ffi_job_get_from_pid(int pid) const;
|
||||
const library_data_pod_t &ffi_libdata_pod_const() const;
|
||||
|
||||
/// autocxx junk.
|
||||
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