Add various FFI-interop-functions

- `libc::setlinebuf` is not available through Rust's libc it appears.
- autocxx fails to generate bindings using `*mut FILE`, instead go through
  `void*`
- rust_main needs `parse_util_detect_errors_in_ast`, which is _partially_
  ported, instead add FFI interop for C++.
- We need to set the filename if we are sourcing a file
This commit is contained in:
Henrik Hørlück Berg 2023-08-18 07:12:50 +02:00 committed by Fabian Boehm
parent 25d207a8ce
commit 55302629cd
10 changed files with 48 additions and 1 deletions

View file

@ -81,6 +81,7 @@ static relaxed_atomic_t<wchar_t> obfuscation_read_char;
wchar_t get_obfuscation_read_char() { return obfuscation_read_char; }
bool g_profiling_active = false;
void set_profiling_active(bool val) { g_profiling_active = val; }
const wchar_t *program_name;

View file

@ -188,6 +188,7 @@ wchar_t get_obfuscation_read_char();
/// Profiling flag. True if commands should be profiled.
extern bool g_profiling_active;
void set_profiling_active(bool val);
/// Name of the current program. Should be set at startup. Used by the debug function.
extern const wchar_t *program_name;

View file

@ -172,6 +172,21 @@ void activate_flog_categories_by_pattern(wcstring wc) {
}
}
// autocxx fails with FILE*
void set_flog_output_file_ffi(void* fp) {
auto f = static_cast<FILE *>(fp);
set_flog_output_file(f);
}
// Rust libc does not contain setlinebuf
void flog_setlinebuf_ffi(void *f) {
auto fp = static_cast<FILE *>(f);
if (fp == nullptr) {
return;
}
setlinebuf(fp);
}
void set_flog_output_file(FILE *f) {
assert(f && "Null file");
g_logger.acquire()->set_file(f);

View file

@ -185,6 +185,8 @@ extern owning_lock<logger_t> g_logger;
/// Set the active flog categories according to the given wildcard \p wc.
void activate_flog_categories_by_pattern(wcstring wc);
void set_flog_output_file_ffi(void *fp);
void flog_setlinebuf_ffi(void *f);
/// Set the file that flog should output to.
/// flog does not close this file.
void set_flog_output_file(FILE *f);

View file

@ -1068,6 +1068,11 @@ static bool detect_errors_in_block_redirection_list(
return false;
}
parser_test_error_bits_t parse_util_detect_errors_ffi(const ast::ast_t* ast, const wcstring &buff_src,
parse_error_list_t *out_errors) {
return parse_util_detect_errors(*ast, buff_src, out_errors);
}
parser_test_error_bits_t parse_util_detect_errors(const ast::ast_t &ast, const wcstring &buff_src,
parse_error_list_t *out_errors) {
using namespace ast;

View file

@ -126,6 +126,9 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
parse_error_list_t *out_errors = nullptr,
bool allow_incomplete = false);
parser_test_error_bits_t parse_util_detect_errors_ffi(const ast::ast_t *ast,
const wcstring &buff_src,
parse_error_list_t *out_errors);
/// Like parse_util_detect_errors but accepts an already-parsed ast.
/// The top of the ast is assumed to be a job list.
parser_test_error_bits_t parse_util_detect_errors(const ast::ast_t &ast, const wcstring &buff_src,

View file

@ -417,6 +417,10 @@ filename_ref_t parser_t::current_filename() const {
return libdata().current_filename;
}
void parser_t::set_filename_ffi(wcstring filename) {
libdata().current_filename = std::make_shared<wcstring>(filename);
}
// FFI glue
wcstring parser_t::current_filename_ffi() const {
auto filename = current_filename();
@ -586,6 +590,10 @@ eval_res_t parser_t::eval_with(const wcstring &cmd, const io_chain_t &io,
eval_res_t parser_t::eval_string_ffi1(const wcstring &cmd) { return eval(cmd, io_chain_t()); }
eval_res_t parser_t::eval_parsed_source_ffi1(const parsed_source_ref_t* ps, enum block_type_t block_type) {
return eval_parsed_source(*ps, io_chain_t(), {}, block_type);
}
eval_res_t parser_t::eval_parsed_source(const parsed_source_ref_t &ps, const io_chain_t &io,
const job_group_ref_t &job_group,
enum block_type_t block_type) {
@ -690,6 +698,10 @@ template eval_res_t parser_t::eval_node(const parsed_source_ref_t &, const ast::
template eval_res_t parser_t::eval_node(const parsed_source_ref_t &, const ast::job_list_t &,
const io_chain_t &, const job_group_ref_t &, block_type_t);
void parser_t::get_backtrace_ffi(const wcstring &src, const parse_error_list_t* errors,
wcstring &output) const {
return get_backtrace(src, *errors, output);
};
void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &errors,
wcstring &output) const {
if (!errors.empty()) {

View file

@ -349,7 +349,7 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
eval_res_t eval_parsed_source(const parsed_source_ref_t &ps, const io_chain_t &io,
const job_group_ref_t &job_group = {},
block_type_t block_type = block_type_t::top);
eval_res_t eval_parsed_source_ffi1(const parsed_source_ref_t* ps, block_type_t block_type);
/// Evaluates a node.
/// The node type must be ast_t::statement_t or ast::job_list_t.
template <typename T>
@ -466,6 +466,8 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
/// Output profiling data to the given filename.
void emit_profiling(const char *path) const;
void get_backtrace_ffi(const wcstring &src, const parse_error_list_t* errors,
wcstring &output) const;
void get_backtrace(const wcstring &src, const parse_error_list_t &errors,
wcstring &output) const;
@ -474,6 +476,7 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
/// than the one currently read.
filename_ref_t current_filename() const;
wcstring current_filename_ffi() const;
void set_filename_ffi(wcstring filename);
/// Return if we are interactive, which means we are executing a command that the user typed in
/// (and not, say, a prompt).

View file

@ -4842,6 +4842,10 @@ static int read_ni(parser_t &parser, int fd, const io_chain_t &io) {
}
}
int reader_read_ffi(parser_t &parser, int fd) {
return reader_read(parser, fd, {});
}
int reader_read(parser_t &parser, int fd, const io_chain_t &io) {
int res;

View file

@ -139,6 +139,7 @@ class editable_line_t {
uint32_t edit_group_id_ = -1;
};
int reader_read_ffi(parser_t &parser, int fd);
/// Read commands from \c fd until encountering EOF.
/// The fd is not closed.
int reader_read(parser_t &parser, int fd, const io_chain_t &io);