diff --git a/test/test_fuzz/test_fuzz_common.hpp b/test/test_fuzz/test_fuzz_common.hpp index c4927256..650253ab 100644 --- a/test/test_fuzz/test_fuzz_common.hpp +++ b/test/test_fuzz/test_fuzz_common.hpp @@ -7,6 +7,7 @@ #else #include #include +#include #include #include #include diff --git a/tools/parse_emit.cpp b/tools/parse_emit.cpp index 88ea138d..d7ddb689 100644 --- a/tools/parse_emit.cpp +++ b/tools/parse_emit.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #endif #include @@ -88,7 +89,13 @@ bool timing_enabled = false; bool parse_args(int argc, const char *argv[], Args &args) { args = {}; - for(int i = 1; i < argc; ++i) + if(argc < 2) + { + print_usage(argv[0]); + _RYML_ERR_BASIC("missing filename (use - to read from stdin)"); + } + args.filename = c4::to_csubstr(argv[argc - 1]); + for(int i = 1; i+1 < argc; ++i) { c4::csubstr arg = c4::to_csubstr(argv[i]); auto arg0_is = [&](c4::csubstr argshort, c4::csubstr arglong){ @@ -98,7 +105,7 @@ bool parse_args(int argc, const char *argv[], Args &args) if(arg0_is(argshort, arglong)) { if(i + 1 >= argc) - c4::yml::error("missing argument value"); + _RYML_ERR_BASIC("missing argument value: {}", arg); return true; } return false; @@ -120,14 +127,14 @@ bool parse_args(int argc, const char *argv[], Args &args) else if(i+1 < argc) { print_usage(argv[0]); - c4::yml::error("unknown argument"); + _RYML_ERR_BASIC("unknown argument: {}", arg); } } timing_enabled = args.timed_sections; if(argc < 2) { print_usage(argv[0]); - c4::yml::error("missing filename (use - to read from stdin)"); + _RYML_ERR_BASIC("missing filename (use - to read from stdin)"); } args.filename = c4::to_csubstr(argv[argc - 1]); return true; @@ -147,11 +154,7 @@ void read_file(csubstr filename, std::string *buf) } else { - if(!fs::path_exists(filename.str)) - { - std::fprintf(stderr, "cannot find file: %s (cwd=%s)\n", filename.str, fs::cwd().c_str()); // NOLINT - yml::error("file not found"); - } + _RYML_CHECK_BASIC_MSG(fs::path_exists(filename.str), "file not found: {} (cwd={})", filename, fs::cwd()); fs::file_get_contents(filename.str, buf); } } @@ -192,37 +195,41 @@ void emit_json_docs(yml::Tree const& tree, FILE *output) emitnode(doc); } -void report_error(const char* msg, size_t length, yml::Location loc, FILE *f) +void dump2stderr(csubstr s) { - if(!loc.name.empty()) + if(s.len) { - fwrite(loc.name.str, 1, loc.name.len, f); // NOLINT - fputc(':', f); // NOLINT + fwrite(s.str, 1, s.len, stderr); // NOLINT + fflush(stderr); // NOLINT } - fprintf(f, "%zu:", loc.line); // NOLINT - if(loc.col) - fprintf(f, "%zu:", loc.col); // NOLINT - if(loc.offset) - fprintf(f, " (%zuB):", loc.offset); // NOLINT - fputc(' ', f); // NOLINT - fprintf(f, "%.*s\n", static_cast(length), msg); // NOLINT - fflush(f); // NOLINT +} + +[[noreturn]] void throwerr(csubstr msg) +{ + C4_IF_EXCEPTIONS( + throw std::runtime_error({msg.str, msg.len}); + , + jmp_msg.assign(msg.str, msg.len); + std::longjmp(jmp_env, 1); + ); + C4_UNREACHABLE_AFTER_ERR(); } yml::Callbacks create_custom_callbacks() { - yml::Callbacks callbacks = {}; - callbacks.m_error = [](const char *msg, size_t msg_len, yml::Location location, void *) - { - report_error(msg, msg_len, location, stderr); - C4_IF_EXCEPTIONS( - throw std::runtime_error({msg, msg_len}); - , - jmp_msg.assign(msg, msg_len); - std::longjmp(jmp_env, 1); - ); - }; - return callbacks; + return yml::Callbacks{} + .set_error_basic([](csubstr msg, yml::ErrorDataBasic const& errdata, void *){ + yml::err_basic_format(dump2stderr, msg, errdata); + throwerr(msg); + }) + .set_error_parse([](csubstr msg, yml::ErrorDataParse const& errdata, void *){ + yml::err_parse_format(dump2stderr, msg, errdata); + throwerr(msg); + }) + .set_error_visit([](csubstr msg, yml::ErrorDataVisit const& errdata, void *){ + yml::err_visit_format(dump2stderr, msg, errdata); + throwerr(msg); + }); } #define TS(name) timed_section C4_XCAT(__, C4_XCAT(name, __LINE__))(#name) @@ -254,14 +261,13 @@ struct timed_section //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void process_file(Args const& args) +void process_file(Args const& args, std::string *contents) { TS(objects); - std::string contents; yml::Tree tree(yml::get_callbacks()); { TS(read_file); - read_file(args.filename, &contents); + read_file(args.filename, contents); } if(args.reserve_size) { @@ -270,15 +276,15 @@ void process_file(Args const& args) if(args.reserve_size) { TS(estimate_capacity); - cap = yml::estimate_tree_capacity(to_csubstr(contents)); + cap = yml::estimate_tree_capacity(to_csubstr(*contents)); } - if(timing_enabled) + if(args.timed_sections) fprintf(stderr, "reserving capacity=%zu\n", (size_t)cap); // NOLINT tree.reserve(cap); } { TS(parse_yml); - yml::parse_in_place(args.filename, to_substr(contents), &tree); + yml::parse_in_place(args.filename, to_substr(*contents), &tree); } if(args.print_tree) { @@ -298,7 +304,7 @@ void process_file(Args const& args) std::string output; { TS(emit_to_buffer); - output.resize(contents.size()); // resize, not just reserve + output.resize(contents->size()); // resize, not just reserve if(!args.emit_as_json) yml::emitrs_yaml(tree, &output); else @@ -323,7 +329,8 @@ void process_file(Args const& args) else { FILE *output = fopen(args.output.str, "wb"); - if (!output) c4::yml::error("could not open file"); + if (!output) + _RYML_ERR_BASIC("could not open file: {}", args.output.str); { TS(emit_to_file); if(!args.emit_as_json) @@ -344,12 +351,19 @@ int main(int argc, const char *argv[]) return 0; TS(TOTAL); set_callbacks(create_custom_callbacks()); + TS(TOTAL); + std::string yaml; C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0)) { - process_file(args); + process_file(args, &yaml); } - C4_IF_EXCEPTIONS_(catch(std::exception const&), else) // LCOV_EXCL_LINE + C4_IF_EXCEPTIONS_(catch(std::exception const& exc), else) // LCOV_EXCL_LINE { + C4_IF_EXCEPTIONS( + dump2stderr(to_csubstr(exc.what())); // LCOV_EXCL_LINE + , + dump2stderr(to_csubstr(jmp_msg)); // LCOV_EXCL_LINE + ); return 1; // LCOV_EXCL_LINE } return 0; diff --git a/tools/yaml_events.cpp b/tools/yaml_events.cpp index a6780fbe..100c3529 100644 --- a/tools/yaml_events.cpp +++ b/tools/yaml_events.cpp @@ -2,7 +2,9 @@ #include #else #include +#include #include +#include #include #include #endif @@ -309,7 +311,10 @@ csubstr parse_events_ints(csubstr filename, substr filecontents, std::string &pa if(timing_enabled) fprintf(stderr, "current_size=%zu vs needed_size=%zu. arena_size=%zu\n", evts.size(), sz, arena.size()); if (!handler.fits_buffers()) { - RYML_CHECK(!fail_size); + if(fail_size) + { + _RYML_ERR_BASIC("buffers too small"); + } { STOPWATCH("resize"); evts.resize(sz); @@ -325,7 +330,7 @@ csubstr parse_events_ints(csubstr filename, substr filecontents, std::string &pa STOPWATCH("redo_parse"); parser.parse_in_place_ev(filename, src); } - RYML_CHECK((size_t)handler.m_evt_pos == sz); + _RYML_CHECK_BASIC((size_t)handler.m_evt_pos == sz); } evts.resize(sz); return src; @@ -472,41 +477,45 @@ std::string load_file(csubstr filename) } else if(!fs::path_exists(filename.str)) { - std::fprintf(stderr, "%s: file not found (cwd=%s)\n", filename.str, fs::cwd().c_str()); - error("file not found"); + std::fprintf(stderr, "%s: file not found (cwd=%s)\n", filename.str, fs::cwd().c_str()); // LCOV_EXCL_LINE + err_basic(RYML_LOC_HERE(), "file not found"); // LCOV_EXCL_LINE } return fs::file_get_contents(filename.str); } -void report_error(const char* msg, size_t length, Location loc, FILE *f) +[[noreturn]] C4_NO_INLINE void throwerr(csubstr msg) { - if(!loc.name.empty()) + C4_IF_EXCEPTIONS( + throw std::runtime_error({msg.str, msg.len}); + , + jmp_msg.assign(msg.str, msg.len); + std::longjmp(jmp_env, 1); + ); + C4_UNREACHABLE_AFTER_ERR(); +} + +void dump2stderr(csubstr s) +{ + if(s.len) { - fwrite(loc.name.str, 1, loc.name.len, f); - fputc(':', f); + fwrite(s.str, 1, s.len, stderr); // NOLINT + fflush(stderr); // NOLINT } - fprintf(f, "%zu:", loc.line); - if(loc.col) - fprintf(f, "%zu:", loc.col); - if(loc.offset) - fprintf(f, " (%zuB):", loc.offset); - fputc(' ', f); - fprintf(f, "%.*s\n", static_cast(length), msg); - fflush(f); } Callbacks create_custom_callbacks() { - Callbacks callbacks = {}; - callbacks.m_error = [](const char *msg, size_t msg_len, Location location, void *) - { - report_error(msg, msg_len, location, stderr); - C4_IF_EXCEPTIONS( - throw std::runtime_error({msg, msg_len}); - , - jmp_msg.assign(msg, msg_len); - std::longjmp(jmp_env, 1); - ); - }; - return callbacks; + return Callbacks{} + .set_error_basic([](csubstr msg, yml::ErrorDataBasic const& errdata, void *){ + yml::err_basic_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE + throwerr(msg); // LCOV_EXCL_LINE + }) + .set_error_parse([](csubstr msg, yml::ErrorDataParse const& errdata, void *){ + yml::err_parse_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE + throwerr(msg); // LCOV_EXCL_LINE + }) + .set_error_visit([](csubstr msg, yml::ErrorDataVisit const& errdata, void *){ + yml::err_visit_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE + throwerr(msg); // LCOV_EXCL_LINE + }); }