From 8db6db5dac70c25b04cd4dd84392484dee822fbe Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 7 Feb 2020 11:24:35 -0800 Subject: [vcpkg] Further parser improvements (#9895) * [vcpkg] Consolidate several internal parsers together (packagespecs + logicexpression + control) and enhance error messages * [vcpkg] Migrate Build-Depends parsing to new framework * [vcpkg] Fix tests. Re-enable underscores in feature names due to libwebp[vwebp_sdl] -- todo: rename this feature and remove underscores. --- toolsrc/include/vcpkg-test/mockcmakevarprovider.h | 4 +- toolsrc/include/vcpkg-test/util.h | 4 +- toolsrc/include/vcpkg/base/expected.h | 105 ++++++++++++++-- toolsrc/include/vcpkg/base/optional.h | 41 ++++++ toolsrc/include/vcpkg/binaryparagraph.h | 6 +- toolsrc/include/vcpkg/build.h | 8 +- toolsrc/include/vcpkg/cmakevars.h | 8 +- toolsrc/include/vcpkg/commands.h | 14 +-- toolsrc/include/vcpkg/dependencies.h | 2 +- toolsrc/include/vcpkg/export.h | 2 +- toolsrc/include/vcpkg/input.h | 6 +- toolsrc/include/vcpkg/install.h | 2 +- toolsrc/include/vcpkg/packagespec.h | 54 ++++---- toolsrc/include/vcpkg/packagespecparseresult.h | 35 ------ toolsrc/include/vcpkg/paragraphparser.h | 45 +++++++ toolsrc/include/vcpkg/paragraphs.h | 10 +- toolsrc/include/vcpkg/parse.h | 147 +++++++++++++++++++--- toolsrc/include/vcpkg/portfileprovider.h | 8 +- toolsrc/include/vcpkg/remove.h | 2 +- toolsrc/include/vcpkg/sourceparagraph.h | 25 +--- toolsrc/include/vcpkg/statusparagraphs.h | 6 +- toolsrc/include/vcpkg/textrowcol.h | 12 ++ toolsrc/include/vcpkg/triplet.h | 8 +- toolsrc/include/vcpkg/vcpkgpaths.h | 6 +- 24 files changed, 405 insertions(+), 155 deletions(-) delete mode 100644 toolsrc/include/vcpkg/packagespecparseresult.h create mode 100644 toolsrc/include/vcpkg/paragraphparser.h create mode 100644 toolsrc/include/vcpkg/textrowcol.h (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h index 03defdcdd..21207c856 100644 --- a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h +++ b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h @@ -6,7 +6,7 @@ namespace vcpkg::Test { struct MockCMakeVarProvider : CMakeVars::CMakeVarProvider { - void load_generic_triplet_vars(const Triplet& triplet) const override { generic_triplet_vars[triplet] = {}; } + void load_generic_triplet_vars(Triplet triplet) const override { generic_triplet_vars[triplet] = {}; } void load_dep_info_vars(Span specs) const override { @@ -23,7 +23,7 @@ namespace vcpkg::Test } Optional&> get_generic_triplet_vars( - const Triplet& triplet) const override; + Triplet triplet) const override; Optional&> get_dep_info_vars( const PackageSpec& spec) const override; diff --git a/toolsrc/include/vcpkg-test/util.h b/toolsrc/include/vcpkg-test/util.h index 088a39b7d..d8ecc51ea 100644 --- a/toolsrc/include/vcpkg-test/util.h +++ b/toolsrc/include/vcpkg-test/util.h @@ -40,7 +40,7 @@ namespace vcpkg::Test { std::unordered_map map; Triplet triplet; - PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} + PackageSpecMap(Triplet t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} PackageSpec emplace(const char* name, const char* depends = "", @@ -50,8 +50,6 @@ namespace vcpkg::Test PackageSpec emplace(vcpkg::SourceControlFileLocation&& scfl); }; - vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS); - template T&& unwrap(vcpkg::ExpectedT&& p) { diff --git a/toolsrc/include/vcpkg/base/expected.h b/toolsrc/include/vcpkg/base/expected.h index c273d71e6..2b19bad2a 100644 --- a/toolsrc/include/vcpkg/base/expected.h +++ b/toolsrc/include/vcpkg/base/expected.h @@ -75,6 +75,30 @@ namespace vcpkg constexpr ExpectedLeftTag expected_left_tag; constexpr ExpectedRightTag expected_right_tag; + template + struct ExpectedHolder + { + ExpectedHolder() = default; + ExpectedHolder(const T& t) : t(t) {} + ExpectedHolder(T&& t) : t(std::move(t)) {} + using pointer = T*; + using const_pointer = const T*; + T* get() { return &t; } + const T* get() const { return &t; } + T t; + }; + template + struct ExpectedHolder + { + ExpectedHolder(T& t) : t(&t) {} + ExpectedHolder() : t(nullptr) {} + using pointer = T*; + using const_pointer = T*; + T* get() { return t; } + T* get() const { return t; } + T* t; + }; + template class ExpectedT { @@ -87,7 +111,10 @@ namespace vcpkg ExpectedT(S&& s, ExpectedRightTag = {}) : m_s(std::move(s)) {} ExpectedT(const T& t, ExpectedLeftTag = {}) : m_t(t) {} - ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) {} + template>> + ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) + { + } ExpectedT(const ExpectedT&) = default; ExpectedT(ExpectedT&&) = default; @@ -100,35 +127,94 @@ namespace vcpkg T&& value_or_exit(const LineInfo& line_info) && { exit_if_error(line_info); - return std::move(this->m_t); + return std::move(*this->m_t.get()); } const T& value_or_exit(const LineInfo& line_info) const& { exit_if_error(line_info); - return this->m_t; + return *this->m_t.get(); } const S& error() const& { return this->m_s.error(); } S&& error() && { return std::move(this->m_s.error()); } - const T* get() const + typename ExpectedHolder::const_pointer get() const { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); } - T* get() + typename ExpectedHolder::pointer get() { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); + } + + template + using map_t = decltype(std::declval()(*std::declval::const_pointer>())); + + template> + ExpectedT map(F f) const& + { + if (has_value()) + { + return {f(*m_t.get()), expected_left_tag}; + } + else + { + return {error(), expected_right_tag}; + } + } + + template + using move_map_t = + decltype(std::declval()(std::move(*std::declval::pointer>()))); + + template> + ExpectedT map(F f) && + { + if (has_value()) + { + return {f(std::move(*m_t.get())), expected_left_tag}; + } + else + { + return {std::move(error()), expected_right_tag}; + } + } + + template> + U then(F f) const& + { + if (has_value()) + { + return f(*m_t.get()); + } + else + { + return U{error(), expected_right_tag}; + } + } + + template> + U then(F f) && + { + if (has_value()) + { + return f(std::move(*m_t.get())); + } + else + { + return U{std::move(error()), expected_right_tag}; + } } private: @@ -143,9 +229,12 @@ namespace vcpkg } ErrorHolder m_s; - T m_t; + ExpectedHolder m_t; }; template using Expected = ExpectedT; + + template + using ExpectedS = ExpectedT; } diff --git a/toolsrc/include/vcpkg/base/optional.h b/toolsrc/include/vcpkg/base/optional.h index 2d8c126c6..fc3733ead 100644 --- a/toolsrc/include/vcpkg/base/optional.h +++ b/toolsrc/include/vcpkg/base/optional.h @@ -228,12 +228,21 @@ namespace vcpkg return this->m_base.has_value() ? this->m_base.value() : static_cast(std::forward(default_value)); } + T value_or(T&& default_value) const& + { + return this->m_base.has_value() ? this->m_base.value() : static_cast(default_value); + } + template T value_or(U&& default_value) && { return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast(std::forward(default_value)); } + T value_or(T&& default_value) && + { + return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast(default_value); + } typename std::add_pointer::type get() const { @@ -242,6 +251,38 @@ namespace vcpkg typename std::add_pointer::type get() { return this->m_base.has_value() ? &this->m_base.value() : nullptr; } + template + using map_t = decltype(std::declval()(std::declval())); + + template> + U then(F f) const& + { + if (has_value()) + { + return f(this->m_base.value()); + } + else + { + return nullopt; + } + } + + template + using move_map_t = decltype(std::declval()(std::declval())); + + template> + U then(F f) && + { + if (has_value()) + { + return f(std::move(this->m_base.value())); + } + else + { + return nullopt; + } + } + private: details::OptionalStorage m_base; }; diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h index 223a1fb86..05c42dee4 100644 --- a/toolsrc/include/vcpkg/binaryparagraph.h +++ b/toolsrc/include/vcpkg/binaryparagraph.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include namespace vcpkg @@ -14,12 +14,12 @@ namespace vcpkg BinaryParagraph(); explicit BinaryParagraph(Parse::RawParagraph fields); BinaryParagraph(const SourceParagraph& spgh, - const Triplet& triplet, + Triplet triplet, const std::string& abi_tag, const std::vector& deps); BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, - const Triplet& triplet, + Triplet triplet, const std::vector& deps); std::string displayname() const; diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index b7b7475ef..9d555ae25 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -26,7 +26,7 @@ namespace vcpkg::Build const ParsedArguments& options, const VcpkgPaths& paths); - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } enum class UseHeadVersion @@ -140,7 +140,7 @@ namespace vcpkg::Build struct PreBuildInfo { PreBuildInfo(const VcpkgPaths& paths, - const Triplet& triplet, + Triplet triplet, const std::unordered_map& cmakevars); std::string triplet_abi_tag; @@ -197,7 +197,7 @@ namespace vcpkg::Build struct BuildPackageConfig { BuildPackageConfig(const SourceControlFileLocation& scfl, - const Triplet& triplet, + Triplet triplet, const BuildPackageOptions& build_package_options, const CMakeVars::CMakeVarProvider& var_provider, const std::unordered_map>& feature_dependencies, @@ -217,7 +217,7 @@ namespace vcpkg::Build const SourceControlFileLocation& scfl; const SourceControlFile& scf; - const Triplet& triplet; + Triplet triplet; const fs::path& port_dir; const BuildPackageOptions& build_package_options; const CMakeVars::CMakeVarProvider& var_provider; diff --git a/toolsrc/include/vcpkg/cmakevars.h b/toolsrc/include/vcpkg/cmakevars.h index c634866d0..8d131d45e 100644 --- a/toolsrc/include/vcpkg/cmakevars.h +++ b/toolsrc/include/vcpkg/cmakevars.h @@ -11,7 +11,7 @@ namespace vcpkg::CMakeVars struct CMakeVarProvider { virtual Optional&> get_generic_triplet_vars( - const Triplet& triplet) const = 0; + Triplet triplet) const = 0; virtual Optional&> get_dep_info_vars( const PackageSpec& spec) const = 0; @@ -19,7 +19,7 @@ namespace vcpkg::CMakeVars virtual Optional&> get_tag_vars( const PackageSpec& spec) const = 0; - virtual void load_generic_triplet_vars(const Triplet& triplet) const = 0; + virtual void load_generic_triplet_vars(Triplet triplet) const = 0; virtual void load_dep_info_vars(Span specs) const = 0; @@ -41,7 +41,7 @@ namespace vcpkg::CMakeVars public: explicit TripletCMakeVarProvider(const vcpkg::VcpkgPaths& paths) : paths(paths) {} - void load_generic_triplet_vars(const Triplet& triplet) const override; + void load_generic_triplet_vars(Triplet triplet) const override; void load_dep_info_vars(Span specs) const override; @@ -49,7 +49,7 @@ namespace vcpkg::CMakeVars const PortFileProvider::PortFileProvider& port_provider) const override; Optional&> get_generic_triplet_vars( - const Triplet& triplet) const override; + Triplet triplet) const override; Optional&> get_dep_info_vars( const PackageSpec& spec) const override; diff --git a/toolsrc/include/vcpkg/commands.h b/toolsrc/include/vcpkg/commands.h index e73077e1d..9d2d0b6c6 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -12,27 +12,25 @@ namespace vcpkg::Commands { - using CommandTypeA = void (*)(const VcpkgCmdArguments& args, - const VcpkgPaths& paths, - const Triplet& default_triplet); + using CommandTypeA = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); using CommandTypeB = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths); using CommandTypeC = void (*)(const VcpkgCmdArguments& args); namespace BuildExternal { - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace CI { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Env { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Create @@ -44,7 +42,7 @@ namespace vcpkg::Commands namespace Upgrade { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Edit @@ -56,7 +54,7 @@ namespace vcpkg::Commands namespace DependInfo { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Search diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index eb9d42b6d..1f92ee63c 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -121,7 +121,7 @@ namespace vcpkg::Dependencies RequestType request_type; Optional core_paragraph() const; - std::vector dependencies(const Triplet& triplet) const; + std::vector dependencies(Triplet triplet) const; private: Optional m_installed_package; diff --git a/toolsrc/include/vcpkg/export.h b/toolsrc/include/vcpkg/export.h index eb99b4fb1..3605081e3 100644 --- a/toolsrc/include/vcpkg/export.h +++ b/toolsrc/include/vcpkg/export.h @@ -6,7 +6,7 @@ namespace vcpkg::Export { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/input.h b/toolsrc/include/vcpkg/input.h index ef481bf52..917b5af10 100644 --- a/toolsrc/include/vcpkg/input.h +++ b/toolsrc/include/vcpkg/input.h @@ -5,11 +5,11 @@ namespace vcpkg::Input { PackageSpec check_and_get_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); FullPackageSpec check_and_get_full_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); - void check_triplet(const Triplet& t, const VcpkgPaths& paths); + void check_triplet(Triplet t, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h index e020c8653..1c42cc102 100644 --- a/toolsrc/include/vcpkg/install.h +++ b/toolsrc/include/vcpkg/install.h @@ -83,5 +83,5 @@ namespace vcpkg::Install extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } diff --git a/toolsrc/include/vcpkg/packagespec.h b/toolsrc/include/vcpkg/packagespec.h index 628352cdb..a37dc99b3 100644 --- a/toolsrc/include/vcpkg/packagespec.h +++ b/toolsrc/include/vcpkg/packagespec.h @@ -1,20 +1,16 @@ #pragma once #include -#include +#include #include -namespace vcpkg +namespace vcpkg::Parse { - struct ParsedSpecifier - { - std::string name; - std::vector features; - std::string triplet; - - static ExpectedT from_string(const std::string& input); - }; + struct ParserBase; +} +namespace vcpkg +{ /// /// /// Full specification of a package. Contains all information to reference @@ -26,14 +22,11 @@ namespace vcpkg PackageSpec() noexcept = default; PackageSpec(std::string name, Triplet triplet) : m_name(std::move(name)), m_triplet(triplet) {} - static ExpectedT from_name_and_triplet(const std::string& name, - const Triplet& triplet); - - static std::vector to_package_specs(const std::vector& ports, const Triplet& triplet); + static std::vector to_package_specs(const std::vector& ports, Triplet triplet); const std::string& name() const; - const Triplet& triplet() const; + Triplet triplet() const; std::string dir() const; @@ -64,16 +57,13 @@ namespace vcpkg const std::string& name() const { return m_spec.name(); } const std::string& feature() const { return m_feature; } - const Triplet& triplet() const { return m_spec.triplet(); } + Triplet triplet() const { return m_spec.triplet(); } const PackageSpec& spec() const { return m_spec; } std::string to_string() const; void to_string(std::string& out) const; - static std::vector from_strings_and_triplet(const std::vector& depends, - const Triplet& t); - bool operator<(const FeatureSpec& other) const { if (name() < other.name()) return true; @@ -115,8 +105,7 @@ namespace vcpkg std::vector to_feature_specs(const std::vector& default_features, const std::vector& all_features) const; - static ExpectedT from_string(const std::string& spec_as_string, - const Triplet& default_triplet); + static ExpectedS from_string(const std::string& spec_as_string, Triplet default_triplet); }; /// @@ -129,9 +118,30 @@ namespace vcpkg std::string name; std::vector features; - static ExpectedT from_string(const std::string& input); + static ExpectedS from_string(const std::string& input); + }; + + struct Dependency + { + Features depend; + std::string qualifier; + + static ExpectedS from_string(const std::string& input); }; + struct ParsedQualifiedSpecifier + { + std::string name; + Optional> features; + Optional triplet; + Optional qualifier; + }; + + Optional parse_feature_name(Parse::ParserBase& parser); + Optional parse_package_name(Parse::ParserBase& parser); + ExpectedS parse_qualified_specifier(CStringView input); + Optional parse_qualified_specifier(Parse::ParserBase& parser); + bool operator==(const PackageSpec& left, const PackageSpec& right); bool operator!=(const PackageSpec& left, const PackageSpec& right); } diff --git a/toolsrc/include/vcpkg/packagespecparseresult.h b/toolsrc/include/vcpkg/packagespecparseresult.h deleted file mode 100644 index 4c99c84c7..000000000 --- a/toolsrc/include/vcpkg/packagespecparseresult.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -namespace vcpkg -{ - enum class PackageSpecParseResult - { - SUCCESS = 0, - TOO_MANY_COLONS, - INVALID_CHARACTERS - }; - - void to_string(std::string& out, ::vcpkg::PackageSpecParseResult p); - - CStringView to_string(PackageSpecParseResult ev) noexcept; - - template<> - struct ErrorHolder - { - ErrorHolder() noexcept : m_err(PackageSpecParseResult::SUCCESS) {} - ErrorHolder(PackageSpecParseResult err) : m_err(err) {} - - bool has_error() const { return m_err != PackageSpecParseResult::SUCCESS; } - - const PackageSpecParseResult& error() const { return m_err; } - PackageSpecParseResult& error() { return m_err; } - - CStringView to_string() const { return vcpkg::to_string(m_err); } - - private: - PackageSpecParseResult m_err; - }; -} diff --git a/toolsrc/include/vcpkg/paragraphparser.h b/toolsrc/include/vcpkg/paragraphparser.h new file mode 100644 index 000000000..86c3d0228 --- /dev/null +++ b/toolsrc/include/vcpkg/paragraphparser.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace vcpkg::Parse +{ + struct ParseControlErrorInfo + { + std::string name; + std::vector missing_fields; + std::vector extra_fields; + std::string error; + }; + + template + using ParseExpected = vcpkg::ExpectedT, std::unique_ptr>; + + using RawParagraph = std::unordered_map; + + struct ParagraphParser + { + ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + + void required_field(const std::string& fieldname, std::string& out); + std::string optional_field(const std::string& fieldname) const; + std::unique_ptr error_info(const std::string& name) const; + + private: + RawParagraph&& fields; + std::vector missing_fields; + }; + + ExpectedS> parse_default_features_list(const std::string& str, + CStringView origin = ""); + ExpectedS> parse_qualified_specifier_list(const std::string& str, + CStringView origin = ""); + ExpectedS> parse_dependencies_list(const std::string& str, + CStringView origin = ""); +} diff --git a/toolsrc/include/vcpkg/paragraphs.h b/toolsrc/include/vcpkg/paragraphs.h index 7e2410aef..cffe85af7 100644 --- a/toolsrc/include/vcpkg/paragraphs.h +++ b/toolsrc/include/vcpkg/paragraphs.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -10,13 +10,13 @@ namespace vcpkg::Paragraphs { using RawParagraph = Parse::RawParagraph; - Expected get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); - Expected> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); - Expected> parse_paragraphs(const std::string& str); + ExpectedS get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS> parse_paragraphs(const std::string& str, const std::string& origin); Parse::ParseExpected try_load_port(const Files::Filesystem& fs, const fs::path& control_path); - Expected try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); + ExpectedS try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); struct LoadResults { diff --git a/toolsrc/include/vcpkg/parse.h b/toolsrc/include/vcpkg/parse.h index 4b33e302e..3214305bf 100644 --- a/toolsrc/include/vcpkg/parse.h +++ b/toolsrc/include/vcpkg/parse.h @@ -1,38 +1,147 @@ #pragma once -#include +#include #include +#include +#include #include -#include +#include namespace vcpkg::Parse { - struct ParseControlErrorInfo + struct IParseError { - std::string name; - std::vector missing_fields; - std::vector extra_fields; - std::error_code error; + virtual ~IParseError() = default; + virtual std::string format() const = 0; }; - template - using ParseExpected = ExpectedT, std::unique_ptr>; + struct ParseError : IParseError + { + ParseError(std::string origin, int row, int column, std::string line, std::string message) + : origin(std::move(origin)), row(row), column(column), line(std::move(line)), message(std::move(message)) + { + } + + const std::string origin; + const int row; + const int column; + const std::string line; + const std::string message; - using RawParagraph = std::unordered_map; + virtual std::string format() const override; + }; - struct ParagraphParser + struct ParserBase { - ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + struct SourceLoc + { + const char* it; + int row; + int column; + }; + + void init(CStringView text, CStringView origin, TextRowCol init_rowcol = {}) + { + m_text = text; + m_origin = origin; + m_it = text.c_str(); + row = init_rowcol.row ? init_rowcol.row : 1; + column = init_rowcol.column ? init_rowcol.column : 1; + } + + static constexpr bool is_whitespace(char ch) { return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; } + static constexpr bool is_lower_alpha(char ch) { return ch >= 'a' && ch <= 'z'; } + static constexpr bool is_upper_alpha(char ch) { return ch >= 'A' && ch <= 'Z'; } + static constexpr bool is_ascii_digit(char ch) { return ch >= '0' && ch <= '9'; } + static constexpr bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == '\0'; } + static constexpr bool is_alphanum(char ch) + { + return is_upper_alpha(ch) || is_lower_alpha(ch) || is_ascii_digit(ch); + } + static constexpr bool is_alphanumdash(char ch) { return is_alphanum(ch) || ch == '-'; } + + StringView skip_whitespace() { return match_zero_or_more(is_whitespace); } + StringView skip_tabs_spaces() + { + return match_zero_or_more([](char ch) { return ch == ' ' || ch == '\t'; }); + } + void skip_to_eof() + { + while (cur()) + ++m_it; + } + void skip_newline() + { + if (cur() == '\r') next(); + if (cur() == '\n') next(); + } + void skip_line() + { + match_until(is_lineend); + skip_newline(); + } - void required_field(const std::string& fieldname, std::string& out); - std::string optional_field(const std::string& fieldname) const; - std::unique_ptr error_info(const std::string& name) const; + template + StringView match_zero_or_more(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && p(ch)) + ch = next(); + return {start, m_it}; + } + template + StringView match_until(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && !p(ch)) + ch = next(); + return {start, m_it}; + } + + CStringView text() const { return m_text; } + const char* it() const { return m_it; } + char cur() const { return *m_it; } + SourceLoc cur_loc() const { return {m_it, row, column}; } + char next() + { + char ch = *m_it; + // See https://www.gnu.org/prep/standards/standards.html#Errors + if (ch == '\t') + column = (column + 7) / 8 * 8 + 1; // round to next 8-width tab stop + else if (ch == '\n') + { + row++; + column = 1; + } + else if (ch == '\0') + { + return '\0'; + } + else + { + ++column; + } + return *++m_it; + } + bool at_eof() const { return *m_it == 0; } + + void add_error(std::string message) { add_error(std::move(message), cur_loc()); } + void add_error(std::string message, const SourceLoc& loc); + + const Parse::IParseError* get_error() const { return m_err.get(); } + std::unique_ptr extract_error() { return std::move(m_err); } private: - RawParagraph&& fields; - std::vector missing_fields; - }; + const char* m_it; + int row; + int column; + + CStringView m_text; + CStringView m_origin; - std::vector parse_comma_list(const std::string& str); + std::unique_ptr m_err; + }; } diff --git a/toolsrc/include/vcpkg/portfileprovider.h b/toolsrc/include/vcpkg/portfileprovider.h index 79f69d9ae..36cdba589 100644 --- a/toolsrc/include/vcpkg/portfileprovider.h +++ b/toolsrc/include/vcpkg/portfileprovider.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -9,14 +9,14 @@ namespace vcpkg::PortFileProvider { struct PortFileProvider { - virtual Optional get_control_file(const std::string& src_name) const = 0; + virtual ExpectedS get_control_file(const std::string& src_name) const = 0; virtual std::vector load_all_control_files() const = 0; }; struct MapPortFileProvider : Util::ResourceBase, PortFileProvider { explicit MapPortFileProvider(const std::unordered_map& map); - Optional get_control_file(const std::string& src_name) const override; + ExpectedS get_control_file(const std::string& src_name) const override; std::vector load_all_control_files() const override; private: @@ -27,7 +27,7 @@ namespace vcpkg::PortFileProvider { explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths, const std::vector* ports_dirs_paths); - Optional get_control_file(const std::string& src_name) const override; + ExpectedS get_control_file(const std::string& src_name) const override; std::vector load_all_control_files() const override; private: diff --git a/toolsrc/include/vcpkg/remove.h b/toolsrc/include/vcpkg/remove.h index 36aeda2ad..c43bc73c2 100644 --- a/toolsrc/include/vcpkg/remove.h +++ b/toolsrc/include/vcpkg/remove.h @@ -21,6 +21,6 @@ namespace vcpkg::Remove extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db); } diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 0574afe74..bdb75fc58 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -1,37 +1,20 @@ #pragma once -#include -#include - +#include #include #include #include - #include - -#include +#include +#include #include namespace vcpkg { - struct Dependency - { - Features depend; - std::string qualifier; - - std::string name() const; - static Dependency parse_dependency(std::string name, std::string qualifier); - }; - std::vector filter_dependencies(const std::vector& deps, - const Triplet& t, + Triplet t, const std::unordered_map& cmake_vars); - // zlib[uwp] becomes Dependency{"zlib", "uwp"} - std::vector expand_qualified_dependencies(const std::vector& depends); - - std::string to_string(const Dependency& dep); - struct Type { enum diff --git a/toolsrc/include/vcpkg/statusparagraphs.h b/toolsrc/include/vcpkg/statusparagraphs.h index fa064de7e..7fcf0e916 100644 --- a/toolsrc/include/vcpkg/statusparagraphs.h +++ b/toolsrc/include/vcpkg/statusparagraphs.h @@ -35,10 +35,10 @@ namespace vcpkg /// Triplet /// Feature name /// Iterator for found spec - iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = ""); - const_iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = "") const; + iterator find(const std::string& name, Triplet triplet, const std::string& feature = ""); + const_iterator find(const std::string& name, Triplet triplet, const std::string& feature = "") const; - std::vector*> find_all(const std::string& name, const Triplet& triplet); + std::vector*> find_all(const std::string& name, Triplet triplet); Optional find_all_installed(const PackageSpec& spec) const; diff --git a/toolsrc/include/vcpkg/textrowcol.h b/toolsrc/include/vcpkg/textrowcol.h new file mode 100644 index 000000000..5bbf6a899 --- /dev/null +++ b/toolsrc/include/vcpkg/textrowcol.h @@ -0,0 +1,12 @@ +#pragma once + +namespace vcpkg::Parse +{ + struct TextRowCol + { + /// '0' indicates uninitialized; '1' is the first row. + int row = 0; + /// '0' indicates uninitialized; '1' is the first column. + int column = 0; + }; +} diff --git a/toolsrc/include/vcpkg/triplet.h b/toolsrc/include/vcpkg/triplet.h index f33f40fd5..8d8c3e879 100644 --- a/toolsrc/include/vcpkg/triplet.h +++ b/toolsrc/include/vcpkg/triplet.h @@ -27,8 +27,8 @@ namespace vcpkg void to_string(std::string& out) const; size_t hash_code() const; - bool operator==(const Triplet& other) const; - bool operator<(const Triplet& other) const { return canonical_name() < other.canonical_name(); } + bool operator==(Triplet other) const { return this->m_instance == other.m_instance; } + bool operator<(Triplet other) const { return canonical_name() < other.canonical_name(); } private: static const TripletInstance DEFAULT_INSTANCE; @@ -38,7 +38,7 @@ namespace vcpkg const TripletInstance* m_instance; }; - bool operator!=(const Triplet& left, const Triplet& right); + inline bool operator!=(Triplet left, Triplet right) { return !(left == right); } } namespace std @@ -46,6 +46,6 @@ namespace std template<> struct hash { - size_t operator()(const vcpkg::Triplet& t) const { return t.hash_code(); } + size_t operator()(vcpkg::Triplet t) const { return t.hash_code(); } }; } diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index 52d77d283..63d19af2c 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -52,7 +52,7 @@ namespace vcpkg std::string name; fs::path location; - TripletFile(const std::string& name, const fs::path& location) : name(name), location(location){} + TripletFile(const std::string& name, const fs::path& location) : name(name), location(location) {} }; static Expected create(const fs::path& vcpkg_root_dir, @@ -64,10 +64,10 @@ namespace vcpkg fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; - bool is_valid_triplet(const Triplet& t) const; + bool is_valid_triplet(Triplet t) const; const std::vector get_available_triplets_names() const; const std::vector& get_available_triplets() const; - const fs::path get_triplet_file_path(const Triplet& triplet) const; + const fs::path get_triplet_file_path(Triplet triplet) const; fs::path root; fs::path packages; -- cgit v1.2.3