mirror of https://github.com/KLayout/klayout.git
Auto-substitution of __FILE__/__LINE__ for include-infested files.
This commit is contained in:
parent
740cef9619
commit
a69d65daa3
|
|
@ -455,6 +455,24 @@ static lym::Macro *macro_by_path (const std::string &path)
|
|||
return lym::MacroCollection::root ().find_macro (path);
|
||||
}
|
||||
|
||||
static std::string real_path (const std::string &path, int line)
|
||||
{
|
||||
if (! path.empty () && path[0] == '@') {
|
||||
return tl::IncludeExpander::from_string (path).translate_to_original (line).first;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
static int real_line (const std::string &path, int line)
|
||||
{
|
||||
if (! path.empty () && path[0] == '@') {
|
||||
return tl::IncludeExpander::from_string (path).translate_to_original (line).second;
|
||||
} else {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
Class<lym::Macro> decl_Macro ("lay", "Macro",
|
||||
gsi::method ("path", &lym::Macro::path,
|
||||
"@brief Gets the path of the macro\n"
|
||||
|
|
@ -551,6 +569,46 @@ Class<lym::Macro> decl_Macro ("lay", "Macro",
|
|||
gsi::method ("menu_path=", &lym::Macro::set_menu_path, gsi::arg ("string"),
|
||||
"@brief Sets the menu path\n"
|
||||
"See \\menu_path for details.\n"
|
||||
) +
|
||||
gsi::method ("real_path", &real_path,
|
||||
"@brief Gets the real path for an include-encoded path and line number\n"
|
||||
"\n"
|
||||
"When using KLayout's include scheme based on '# %include ...', __FILE__ and __LINE__ (Ruby) or __file__ and __line__ (Python) will "
|
||||
"not have the proper values but encoded file names. This method allows retrieving the real file by using\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# Ruby\n"
|
||||
"real_file = RBA::Macro::real_path(__FILE__, __LINE__)\n"
|
||||
"\n"
|
||||
"# Python\n"
|
||||
"real_file = pya::Macro::real_path(__file__, __line__)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This substitution is not required for top-level macros as KLayout's interpreter will automatically use this "
|
||||
"function instead of __FILE__ or __file__. Call this function when you need __FILE__ or __file__ from files "
|
||||
"included through the languages mechanisms such as 'import', 'require' or 'load' where this substitution does not happen.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("real_line", &real_line,
|
||||
"@brief Gets the real line number for an include-encoded path and line number\n"
|
||||
"\n"
|
||||
"When using KLayout's include scheme based on '# %include ...', __FILE__ and __LINE__ (Ruby) or __file__ and __line__ (Python) will "
|
||||
"not have the proper values but encoded file names. This method allows retrieving the real line number by using\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"# Ruby\n"
|
||||
"real_line = RBA::Macro::real_line(__FILE__, __LINE__)\n"
|
||||
"\n"
|
||||
"# Python\n"
|
||||
"real_line = pya::Macro::real_line(__file__, __line__)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This substitution is not required for top-level macros as KLayout's interpreter will automatically use this "
|
||||
"function instead of __LINE__ or __line__. Call this function when you need __LINE__ or __line__ from files "
|
||||
"included through the languages mechanisms such as 'import', 'require' or 'load' where this substitution does not happen.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.27."
|
||||
),
|
||||
"@brief A macro class\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -1025,13 +1025,14 @@ int Macro::run () const
|
|||
gsi::Interpreter *ip = script_interpreter (interpreter ());
|
||||
if (ip) {
|
||||
|
||||
static lym::MacroInterpreter def_interpreter;
|
||||
|
||||
if (! prolog ().empty ()) {
|
||||
ip->eval_string (prolog ().c_str ());
|
||||
}
|
||||
|
||||
std::string expanded_text;
|
||||
tl::IncludeExpander ie = tl::IncludeExpander::expand (path (), text (), expanded_text);
|
||||
ip->eval_string (expanded_text.c_str (), ie.to_string ().c_str (), 1);
|
||||
std::pair<std::string, std::string> ep = def_interpreter.include_expansion (this);
|
||||
ip->eval_string (ep.second.c_str (), ep.first.c_str (), 1);
|
||||
|
||||
if (! epilog ().empty ()) {
|
||||
ip->eval_string (epilog ().c_str ());
|
||||
|
|
|
|||
|
|
@ -54,6 +54,32 @@ MacroInterpreter::include_expansion (const lym::Macro *macro)
|
|||
{
|
||||
std::pair<std::string, std::string> res;
|
||||
res.first = tl::IncludeExpander::expand (macro->path (), macro->text (), res.second).to_string ();
|
||||
|
||||
if (res.first != macro->path ()) {
|
||||
|
||||
// Fix the macro's text such that include expansion does not spoil __FILE__ or __LINE__ variables
|
||||
// NOTE: this will modify the column for syntax errors. Let's hope this tiny error is acceptable.
|
||||
// TODO: this substitution may be somewhat naive ...
|
||||
|
||||
Macro::Interpreter ip = macro->interpreter ();
|
||||
if (macro->interpreter () == Macro::DSLInterpreter) {
|
||||
if (syntax_scheme () == "ruby") {
|
||||
ip = Macro::Ruby;
|
||||
} else if (syntax_scheme () == "python") {
|
||||
ip = Macro::Python;
|
||||
}
|
||||
}
|
||||
|
||||
if (ip == Macro::Ruby) {
|
||||
res.second = tl::replaced (res.second, "__FILE__", "RBA::Macro::real_path(__FILE__, __LINE__)");
|
||||
res.second = tl::replaced (res.second, "__LINE__", "RBA::Macro::real_line(__FILE__, __LINE__)");
|
||||
} else if (ip == Macro::Python) {
|
||||
res.second = tl::replaced (res.second, "__file__", "pya.Macro.real_path(__file__, __line__)");
|
||||
res.second = tl::replaced (res.second, "__line__", "pya.Macro.real_line(__file__, __line__)");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "rba.h"
|
||||
#include "rbaUtils.h"
|
||||
#include "rbaInternal.h"
|
||||
#include "tlInclude.h"
|
||||
|
||||
#if HAVE_RUBY_VERSION_CODE >= 20200
|
||||
# include <ruby/debug.h>
|
||||
|
|
|
|||
Loading…
Reference in New Issue