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:
Seth Hillbrand 2022-12-12 19:23:55 -08:00
parent cdcf875ec0
commit 10a3d57193
5 changed files with 93 additions and 34 deletions

View File

@ -90,8 +90,39 @@ SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aR
// May throw an exception. // May throw an exception.
wxString path = ResolveLibraryPath( aLibraryPath, m_project ); wxString path = ResolveLibraryPath( aLibraryPath, m_project );
// May throw an exception. std::function<std::string(const std::string&, const std::string&)> f2 =
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, aReporter ); [&]( 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(); Clear();
m_libraries[path] = std::move( library ); m_libraries[path] = std::move( library );

View File

@ -27,7 +27,8 @@
#include <sim/sim_library_spice.h> #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; 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 = std::make_unique<SIM_LIBRARY_SPICE>();
library->m_reporter = aReporter; library->m_reporter = aReporter;
library->m_pathResolver = aResolver;
library->ReadFile( std::string( aFilePath.c_str() ) ); library->ReadFile( std::string( aFilePath.c_str() ) );
return library; return library;
} }

View File

@ -53,7 +53,8 @@ public:
* @return The library loaded in a newly constructed object. * @return The library loaded in a newly constructed object.
*/ */
static std::unique_ptr<SIM_LIBRARY> Create( const wxString& aFilePath, 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. * 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::string> m_modelNames;
std::vector<std::unique_ptr<SIM_MODEL>> m_models; 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; std::string m_filePath;
REPORTER* m_reporter = nullptr; REPORTER* m_reporter = nullptr;

View File

@ -47,24 +47,25 @@ namespace SIM_LIBRARY_SPICE_PARSER
template <> struct librarySelector<modelUnit> : std::true_type {}; template <> struct librarySelector<modelUnit> : std::true_type {};
template <> struct librarySelector<modelName> : 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. // For debugging.
template <> struct librarySelector<unknownLine> : std::true_type {}; 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 ); tao::pegtl::file_input in( aFilePath );
auto root = tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar, std::unique_ptr<tao::pegtl::parse_tree::node> root =
tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
SIM_LIBRARY_SPICE_PARSER::librarySelector, SIM_LIBRARY_SPICE_PARSER::librarySelector,
tao::pegtl::nothing, tao::pegtl::nothing,
SIM_LIBRARY_SPICE_PARSER::control>( in ); SIM_LIBRARY_SPICE_PARSER::control>( in );
m_library.m_models.clear();
m_library.m_modelNames.clear();
for( const auto& node : root->children ) for( const auto& node : root->children )
{ {
if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() ) if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() )
@ -79,6 +80,15 @@ void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath )
DisplayErrorMessage( nullptr, e.What() ); 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>() ) else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
{ {
// Do nothing. // Do nothing.
@ -89,6 +99,17 @@ void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath )
} }
} }
} }
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 ) catch( const std::filesystem::filesystem_error& e )
{ {
THROW_IO_ERROR( e.what() ); THROW_IO_ERROR( e.what() );

View File

@ -29,7 +29,6 @@
class SIM_LIBRARY_SPICE; class SIM_LIBRARY_SPICE;
class SPICE_LIBRARY_PARSER class SPICE_LIBRARY_PARSER
{ {
public: public:
@ -42,6 +41,9 @@ public:
virtual void ReadFile( const std::string& aFilePath ); virtual void ReadFile( const std::string& aFilePath );
protected:
void readElement( const std::string& aFilePath );
private: private:
SIM_LIBRARY_SPICE& m_library; SIM_LIBRARY_SPICE& m_library;
}; };