From fe2ea1788024ab88f9deee1bff1e04114f87cf61 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Sun, 1 Mar 2020 12:15:26 -0600 Subject: [PATCH] change DF version add -maxerrors and -failfast to check-structures-sanity --- CMakeLists.txt | 4 +- plugins/devel/check-structures-sanity.cpp | 127 ++++++++++++---------- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58bce6dc3..a5a1b2579 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,8 +173,8 @@ if(NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhack endif() # set up versioning. -set(DF_VERSION "0.47.03") -set(DFHACK_RELEASE "beta1") +set(DF_VERSION "0.47.04") +set(DFHACK_RELEASE "alpha0") set(DFHACK_PRERELEASE TRUE) set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}") diff --git a/plugins/devel/check-structures-sanity.cpp b/plugins/devel/check-structures-sanity.cpp index 6b439692f..68a26ba30 100644 --- a/plugins/devel/check-structures-sanity.cpp +++ b/plugins/devel/check-structures-sanity.cpp @@ -40,11 +40,13 @@ DFhackCExport command_result plugin_init(color_ostream &, std::vectorgetKeys()[index]; } -static const struct_field_info *find_union_tag(const struct_field_info *fields, const struct_field_info *union_field) +static const struct_field_info *find_union_tag_field(const struct_field_info *fields, const struct_field_info *union_field) { - if (union_field->mode != struct_field_info::SUBSTRUCT || - !union_field->type || - union_field->type->type() != IDTYPE_UNION) - { - // not a union - return nullptr; - } - - const struct_field_info *tag_field = union_field + 1; - std::string name(union_field->name); if (name.length() >= 4 && name.substr(name.length() - 4) == "data") { name.erase(name.length() - 4, 4); name += "type"; - if (tag_field->mode != struct_field_info::END && tag_field->name == name) - { - // fast path; we already have the correct field - } - else + for (auto field = fields; field->mode != struct_field_info::END; field++) { - for (auto field = fields; field->mode != struct_field_info::END; field++) + if (field->name == name) { - if (field->name == name) - { - tag_field = field; - break; - } + return field; } } } - else if (name.length() > 7 && name.substr(name.length() - 7) == "_target" && fields != union_field && (union_field - 1)->name == name.substr(0, name.length() - 7)) + + if (name.length() > 7 && + name.substr(name.length() - 7) == "_target" && + fields != union_field && + (union_field - 1)->name == name.substr(0, name.length() - 7)) + { + return union_field - 1; + } + + return union_field + 1; +} + +static const struct_field_info *find_union_tag(const struct_field_info *fields, const struct_field_info *union_field) +{ + if (union_field->mode != struct_field_info::SUBSTRUCT || + !union_field->type || + union_field->type->type() != IDTYPE_UNION) { - tag_field = union_field - 1; + // not a union + return nullptr; } + + const struct_field_info *tag_field = find_union_tag_field(fields, union_field); if (tag_field->mode != struct_field_info::PRIMITIVE || !tag_field->type || tag_field->type->type() != IDTYPE_ENUM) @@ -145,35 +148,7 @@ static const struct_field_info *find_union_vector_tag_vector(const struct_field_ return nullptr; } - const struct_field_info *tag_field = union_field + 1; - - std::string name(union_field->name); - if (name.length() >= 4 && name.substr(name.length() - 4) == "data") - { - name.erase(name.length() - 4, 4); - name += "type"; - - if (tag_field->mode != struct_field_info::END && tag_field->name == name) - { - // fast path; we already have the correct field - } - else - { - for (auto field = fields; field->mode != struct_field_info::END; field++) - { - if (field->name == name) - { - tag_field = field; - break; - } - } - } - } - else if (name.length() > 7 && name.substr(name.length() - 7) == "_target" && fields != union_field && (union_field - 1)->name == name.substr(0, name.length() - 7)) - { - tag_field = union_field - 1; - } - + const struct_field_info *tag_field = find_union_tag_field(fields, union_field); if (tag_field->mode != struct_field_info::CONTAINER || !tag_field->type || tag_field->type->type() != IDTYPE_CONTAINER) @@ -230,6 +205,8 @@ public: bool enums; bool sizes; bool lowmem; + bool failfast; + size_t maxerrors; private: bool ok; @@ -272,9 +249,34 @@ static command_result command(color_ostream & out, std::vector & pa Checker checker(out); + // check parameters with values first +#define VAL_PARAM(name, expr_using_value) \ + auto name ## _idx = std::find(parameters.begin(), parameters.end(), "-" #name); \ + if (name ## _idx != parameters.end()) \ + { \ + if (name ## _idx + 1 == parameters.end()) \ + { \ + return CR_WRONG_USAGE; \ + } \ + try \ + { \ + auto value = std::move(*(name ## _idx + 1)); \ + parameters.erase((name ## _idx + 1)); \ + parameters.erase(name ## _idx); \ + checker.name = (expr_using_value); \ + } \ + catch (std::exception & ex) \ + { \ + out.printerr("check-structures-sanity: argument to -%s: %s\n", #name, ex.what()); \ + return CR_WRONG_USAGE; \ + } \ + } + VAL_PARAM(maxerrors, std::stoul(value)); +#undef VAL_PARAM + #define BOOL_PARAM(name) \ auto name ## _idx = std::find(parameters.begin(), parameters.end(), "-" #name); \ - if (name ## _idx != parameters.cend()) \ + if (name ## _idx != parameters.end()) \ { \ checker.name = true; \ parameters.erase(name ## _idx); \ @@ -282,6 +284,7 @@ static command_result command(color_ostream & out, std::vector & pa BOOL_PARAM(enums); BOOL_PARAM(sizes); BOOL_PARAM(lowmem); + BOOL_PARAM(failfast); #undef BOOL_PARAM if (parameters.size() > 1) @@ -342,6 +345,8 @@ Checker::Checker(color_ostream & out) : enums = false; sizes = false; lowmem = false; + failfast = false; + maxerrors = ~size_t(0); } bool Checker::check() @@ -352,6 +357,12 @@ bool Checker::check() while (!queue.empty()) { + if (!maxerrors) + { + out << "hit max error count. bailing out with " << queue.size() << " fields in queue." << std::endl; + break; + } + ToCheck current; if (lowmem) { @@ -388,6 +399,10 @@ bool Checker::check() out << "): "; \ out << COLOR_YELLOW << message; \ out << COLOR_RESET << std::endl; \ + if (maxerrors && maxerrors != ~size_t(0)) \ + maxerrors--; \ + if (failfast) \ + UNEXPECTED; \ } while (false) #define PTR_ADD(base, offset) (reinterpret_cast(reinterpret_cast((base)) + static_cast((offset))))