Add sim_lib callback to resolve embeded libs
Also teach parser to look for include directives in libraries We get KiCad variable resolution in include pathnames for free. Fixes https://gitlab.com/kicad/code/kicad/issues/13083
This commit is contained in:
parent
cdcf875ec0
commit
10a3d57193
|
@ -90,8 +90,39 @@ SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aR
|
|||
// May throw an exception.
|
||||
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
|
||||
|
||||
// May throw an exception.
|
||||
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, aReporter );
|
||||
std::function<std::string(const std::string&, const std::string&)> f2 =
|
||||
[&]( const std::string& aLibPath, const std::string& aRelativeLib ) -> std::string
|
||||
{
|
||||
wxFileName testPath( aLibPath );
|
||||
wxString fullPath( aLibPath );
|
||||
|
||||
if( !testPath.IsAbsolute() && !aRelativeLib.empty() )
|
||||
{
|
||||
wxString relLib( aRelativeLib );
|
||||
|
||||
try
|
||||
{
|
||||
relLib = ResolveLibraryPath( relLib, m_project );
|
||||
}
|
||||
catch( ... )
|
||||
{}
|
||||
|
||||
wxFileName fn( relLib );
|
||||
|
||||
fullPath = testPath.GetAbsolutePath( fn.GetPath( true ) );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
fullPath = ResolveLibraryPath( fullPath, m_project );
|
||||
}
|
||||
catch( ... )
|
||||
{}
|
||||
|
||||
return fullPath.ToStdString();
|
||||
};
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, aReporter, &f2 );
|
||||
|
||||
Clear();
|
||||
m_libraries[path] = std::move( library );
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <sim/sim_library_spice.h>
|
||||
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter )
|
||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString &aFilePath, REPORTER *aReporter,
|
||||
std::function<std::string( const std::string&, const std::string& )> *aResolver )
|
||||
{
|
||||
std::unique_ptr<SIM_LIBRARY> library;
|
||||
|
||||
|
@ -37,6 +38,7 @@ std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString& aFilePath, REP
|
|||
library = std::make_unique<SIM_LIBRARY_SPICE>();
|
||||
|
||||
library->m_reporter = aReporter;
|
||||
library->m_pathResolver = aResolver;
|
||||
library->ReadFile( std::string( aFilePath.c_str() ) );
|
||||
return library;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ public:
|
|||
* @return The library loaded in a newly constructed object.
|
||||
*/
|
||||
static std::unique_ptr<SIM_LIBRARY> Create( const wxString& aFilePath,
|
||||
REPORTER* aReporter = nullptr );
|
||||
REPORTER* aReporter = nullptr,
|
||||
std::function<std::string(const std::string&, const std::string&)>* aResolver = nullptr);
|
||||
|
||||
/**
|
||||
* Read library from a source file. Must be in the format appropriate to the subclass, e.g.
|
||||
|
@ -82,6 +83,8 @@ protected:
|
|||
std::vector<std::string> m_modelNames;
|
||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||
|
||||
std::function<std::string( const std::string&, const std::string& )>* m_pathResolver;
|
||||
|
||||
std::string m_filePath;
|
||||
|
||||
REPORTER* m_reporter = nullptr;
|
||||
|
|
|
@ -47,47 +47,68 @@ namespace SIM_LIBRARY_SPICE_PARSER
|
|||
template <> struct librarySelector<modelUnit> : std::true_type {};
|
||||
template <> struct librarySelector<modelName> : std::true_type {};
|
||||
|
||||
template <> struct librarySelector<dotInclude> : std::true_type {};
|
||||
template <> struct librarySelector<dotIncludePathWithoutQuotes> : std::true_type {};
|
||||
template <> struct librarySelector<dotIncludePathWithoutApostrophes> : std::true_type {};
|
||||
template <> struct librarySelector<dotIncludePath> : std::true_type {};
|
||||
|
||||
// For debugging.
|
||||
template <> struct librarySelector<unknownLine> : std::true_type {};
|
||||
};
|
||||
|
||||
|
||||
void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath )
|
||||
void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath )
|
||||
{
|
||||
try
|
||||
tao::pegtl::file_input in( aFilePath );
|
||||
std::unique_ptr<tao::pegtl::parse_tree::node> root =
|
||||
tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
|
||||
SIM_LIBRARY_SPICE_PARSER::librarySelector,
|
||||
tao::pegtl::nothing,
|
||||
SIM_LIBRARY_SPICE_PARSER::control>( in );
|
||||
|
||||
for( const auto& node : root->children )
|
||||
{
|
||||
tao::pegtl::file_input in( aFilePath );
|
||||
auto root = tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
|
||||
SIM_LIBRARY_SPICE_PARSER::librarySelector,
|
||||
tao::pegtl::nothing,
|
||||
SIM_LIBRARY_SPICE_PARSER::control>( in );
|
||||
|
||||
m_library.m_models.clear();
|
||||
m_library.m_modelNames.clear();
|
||||
|
||||
for( const auto& node : root->children )
|
||||
if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() )
|
||||
{
|
||||
if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() )
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
m_library.m_models.push_back( SIM_MODEL_SPICE::Create( m_library, node->string() ) );
|
||||
m_library.m_modelNames.emplace_back( node->children.at( 0 )->string() );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, e.What() );
|
||||
}
|
||||
m_library.m_models.push_back( SIM_MODEL_SPICE::Create( m_library, node->string() ) );
|
||||
m_library.m_modelNames.emplace_back( node->children.at( 0 )->string() );
|
||||
}
|
||||
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( "Unhandled parse tree node" );
|
||||
DisplayErrorMessage( nullptr, e.What() );
|
||||
}
|
||||
}
|
||||
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::dotInclude>() )
|
||||
{
|
||||
std::string lib = node->children.at( 0 )->string();
|
||||
|
||||
if( m_library.m_pathResolver )
|
||||
lib = ( *m_library.m_pathResolver )( lib, aFilePath );
|
||||
|
||||
readElement( lib );
|
||||
}
|
||||
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( "Unhandled parse tree node" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath )
|
||||
{
|
||||
m_library.m_models.clear();
|
||||
m_library.m_modelNames.clear();
|
||||
|
||||
try
|
||||
{
|
||||
readElement( aFilePath );
|
||||
}
|
||||
catch( const std::filesystem::filesystem_error& e )
|
||||
{
|
||||
|
|
|
@ -29,11 +29,10 @@
|
|||
|
||||
class SIM_LIBRARY_SPICE;
|
||||
|
||||
|
||||
class SPICE_LIBRARY_PARSER
|
||||
{
|
||||
public:
|
||||
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE& aLibrary ) :
|
||||
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE &aLibrary ) :
|
||||
m_library( aLibrary )
|
||||
{};
|
||||
|
||||
|
@ -42,6 +41,9 @@ public:
|
|||
|
||||
virtual void ReadFile( const std::string& aFilePath );
|
||||
|
||||
protected:
|
||||
void readElement( const std::string& aFilePath );
|
||||
|
||||
private:
|
||||
SIM_LIBRARY_SPICE& m_library;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue