mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-12 12:15:34 +00:00
Fixes many bugs in PkgC by incorporating the 0.0.7 changes from llpkgc. These include: * Variable substitution fixes * Better whitespace handling * Correct handling of single and double quotes * Dedicated parsers for fragment and dependency lists Also adds support for pcfiledir, which was blocked on incorrect whitespace handling in the old parser. Fixes: #27652, #27683
265 lines
7.3 KiB
C++
265 lines
7.3 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
|
|
#pragma once
|
|
|
|
#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
|
#include <cstddef>
|
|
#include <set>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include <cmllpkgc/llpkgc.h>
|
|
|
|
struct cmPkgConfigValueItem
|
|
{
|
|
cmPkgConfigValueItem() = default;
|
|
cmPkgConfigValueItem(std::string text, bool isSubstitution);
|
|
|
|
std::string Text;
|
|
bool IsSubstitution = false;
|
|
};
|
|
|
|
enum class cmPkgConfigEntryKind
|
|
{
|
|
Property,
|
|
Variable,
|
|
Barewords,
|
|
};
|
|
|
|
struct cmPkgConfigEntry
|
|
{
|
|
cmPkgConfigEntry() = default;
|
|
cmPkgConfigEntry(std::vector<cmPkgConfigValueItem> value, std::string ident,
|
|
cmPkgConfigEntryKind kind);
|
|
|
|
std::vector<cmPkgConfigValueItem> Value;
|
|
std::string Ident;
|
|
cmPkgConfigEntryKind Kind = cmPkgConfigEntryKind::Barewords;
|
|
};
|
|
|
|
class cmPkgConfigFileParser : private llpkgc_file_t
|
|
{
|
|
friend class cmPkgConfigParser;
|
|
|
|
public:
|
|
cmPkgConfigFileParser();
|
|
cmPkgConfigFileParser(cmPkgConfigFileParser const& other);
|
|
cmPkgConfigFileParser(cmPkgConfigFileParser&& other) noexcept;
|
|
cmPkgConfigFileParser& operator=(cmPkgConfigFileParser const& other);
|
|
cmPkgConfigFileParser& operator=(cmPkgConfigFileParser&& other) noexcept;
|
|
|
|
llpkgc_file_errno_t Parse(char const* input, std::size_t len);
|
|
llpkgc_file_errno_t Finish();
|
|
void Resume();
|
|
|
|
llpkgc_file_errno_t GetErrno() const;
|
|
char const* ErrorReason() const;
|
|
std::ptrdiff_t ErrorOffset(char const* base) const;
|
|
|
|
private:
|
|
void ResetCallbacks();
|
|
|
|
int OnIdentNext(char const* at, std::size_t len);
|
|
static int OnIdentNextTr(llpkgc_file_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
void AppendValue(std::string text, bool isSubstitution);
|
|
|
|
int OnSpanNext(char const*, std::size_t len);
|
|
static int OnSpanNextTr(llpkgc_file_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnIdent(char const* at, std::size_t len);
|
|
static int OnIdentTr(llpkgc_file_t* parser, char const* at, std::size_t len);
|
|
|
|
int OnPropertyComplete();
|
|
static int OnPropertyCompleteTr(llpkgc_file_t* parser);
|
|
|
|
int OnVariableComplete();
|
|
static int OnVariableCompleteTr(llpkgc_file_t* parser);
|
|
|
|
int OnBarewordsComplete();
|
|
static int OnBarewordsCompleteTr(llpkgc_file_t* parser);
|
|
|
|
int OnValueLiteral(char const* at, std::size_t len);
|
|
static int OnValueLiteralTr(llpkgc_file_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnValueLiteralComplete();
|
|
static int OnValueLiteralCompleteTr(llpkgc_file_t* parser);
|
|
|
|
int OnValueSubstitution(char const* at, std::size_t len);
|
|
static int OnValueSubstitutionTr(llpkgc_file_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnValueSubstitutionComplete();
|
|
static int OnValueSubstitutionCompleteTr(llpkgc_file_t* parser);
|
|
|
|
int OnValueComplete();
|
|
static int OnValueCompleteTr(llpkgc_file_t* parser);
|
|
|
|
llpkgc_file_settings_t Settings_{
|
|
OnIdentTr,
|
|
OnValueLiteralTr,
|
|
OnValueSubstitutionTr,
|
|
nullptr, // on_line_begin
|
|
OnPropertyCompleteTr,
|
|
OnVariableCompleteTr,
|
|
OnBarewordsCompleteTr,
|
|
OnValueLiteralCompleteTr,
|
|
OnValueSubstitutionCompleteTr,
|
|
OnValueCompleteTr,
|
|
nullptr, // on_pkgc_complete
|
|
};
|
|
|
|
char const* Ptr_ = nullptr;
|
|
std::size_t Len_ = 0;
|
|
std::string Ident_;
|
|
std::vector<cmPkgConfigEntry> Data_;
|
|
};
|
|
|
|
class cmPkgConfigFragmentParser : private llpkgc_frag_t
|
|
{
|
|
public:
|
|
cmPkgConfigFragmentParser();
|
|
|
|
llpkgc_frag_errno_t Parse(char const* input, std::size_t len);
|
|
llpkgc_frag_errno_t Finish();
|
|
|
|
llpkgc_frag_errno_t GetErrno() const;
|
|
char const* ErrorReason() const;
|
|
|
|
std::vector<std::string> const& Fragments() const { return Fragments_; }
|
|
|
|
private:
|
|
int OnFragmentText(char const* at, std::size_t len);
|
|
static int OnFragmentTextTr(llpkgc_frag_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnFragmentComplete();
|
|
static int OnFragmentCompleteTr(llpkgc_frag_t* parser);
|
|
|
|
llpkgc_frag_settings_t Settings_{
|
|
OnFragmentTextTr, OnFragmentCompleteTr,
|
|
nullptr, // on_fraglist_complete
|
|
};
|
|
|
|
std::string CurrentFragment_;
|
|
std::vector<std::string> Fragments_;
|
|
};
|
|
|
|
enum class cmPkgConfigDependencyOperation
|
|
{
|
|
None,
|
|
LessThan,
|
|
LessThanEqual,
|
|
Equal,
|
|
NotEqual,
|
|
GreaterThan,
|
|
GreaterThanEqual,
|
|
};
|
|
|
|
struct cmPkgConfigDependencySpec
|
|
{
|
|
std::string Name;
|
|
cmPkgConfigDependencyOperation Operation =
|
|
cmPkgConfigDependencyOperation::None;
|
|
std::string Version;
|
|
};
|
|
|
|
class cmPkgConfigDependencyParser : private llpkgc_dep_t
|
|
{
|
|
public:
|
|
cmPkgConfigDependencyParser();
|
|
|
|
llpkgc_dep_errno_t Parse(char const* input, std::size_t len);
|
|
llpkgc_dep_errno_t Finish();
|
|
|
|
llpkgc_dep_errno_t GetErrno() const;
|
|
char const* ErrorReason() const;
|
|
|
|
std::vector<cmPkgConfigDependencySpec> const& Dependencies() const
|
|
{
|
|
return Dependencies_;
|
|
}
|
|
|
|
private:
|
|
int OnDependencyName(char const* at, std::size_t len);
|
|
static int OnDependencyNameTr(llpkgc_dep_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnDependencyOperator(char const* at, std::size_t len);
|
|
static int OnDependencyOperatorTr(llpkgc_dep_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnDependencyVersion(char const* at, std::size_t len);
|
|
static int OnDependencyVersionTr(llpkgc_dep_t* parser, char const* at,
|
|
std::size_t len);
|
|
|
|
int OnDependencyComplete();
|
|
static int OnDependencyCompleteTr(llpkgc_dep_t* parser);
|
|
|
|
llpkgc_dep_settings_t Settings_{
|
|
OnDependencyNameTr,
|
|
OnDependencyOperatorTr,
|
|
OnDependencyVersionTr,
|
|
OnDependencyCompleteTr,
|
|
nullptr, // on_dep_list_complete
|
|
};
|
|
|
|
cmPkgConfigDependencySpec Current_;
|
|
std::vector<cmPkgConfigDependencySpec> Dependencies_;
|
|
};
|
|
|
|
struct cmPkgConfigResolvedValue
|
|
{
|
|
std::vector<std::string> Fragments;
|
|
std::vector<cmPkgConfigDependencySpec> Dependencies;
|
|
std::string Literal;
|
|
};
|
|
|
|
class cmPkgConfigParser
|
|
{
|
|
public:
|
|
cmPkgConfigParser() = default;
|
|
|
|
llpkgc_file_errno_t Parse(char const* input, std::size_t len);
|
|
llpkgc_file_errno_t Finish();
|
|
llpkgc_file_errno_t Finish(char const* data, std::size_t len);
|
|
|
|
llpkgc_file_errno_t GetErrno() const;
|
|
char const* ErrorReason() const;
|
|
std::ptrdiff_t ErrorOffset(char const* base) const;
|
|
|
|
void SetVariable(std::string name, std::string value);
|
|
std::string GetVariable(std::string const& name);
|
|
bool HasProperty(std::string const& name) const;
|
|
std::vector<std::string> GetFragments(std::string const& name);
|
|
std::vector<cmPkgConfigDependencySpec> GetDependencies(
|
|
std::string const& name);
|
|
std::string GetLiteral(std::string const& name);
|
|
|
|
void ParseComplete();
|
|
|
|
private:
|
|
using ValueItems = std::vector<cmPkgConfigValueItem>;
|
|
|
|
std::string ResolveValue(ValueItems const& items);
|
|
std::string ResolveValueImpl(ValueItems const& items,
|
|
std::set<std::string> resolving);
|
|
|
|
bool ResolveAndParse(std::string const& name,
|
|
cmPkgConfigResolvedValue& cache);
|
|
|
|
static bool IsFragmentProperty(std::string const& lower);
|
|
static bool IsDependencyProperty(std::string const& lower);
|
|
|
|
cmPkgConfigFileParser File_;
|
|
std::unordered_map<std::string, ValueItems> StoredVariables_;
|
|
std::vector<cmPkgConfigEntry> StoredProperties_;
|
|
std::unordered_map<std::string, cmPkgConfigResolvedValue> Cache_;
|
|
};
|