diff --git a/src/buddies/src/bd/bd.pro b/src/buddies/src/bd/bd.pro index 11a85c0b2..2abbb6d1e 100644 --- a/src/buddies/src/bd/bd.pro +++ b/src/buddies/src/bd/bd.pro @@ -20,6 +20,7 @@ SOURCES = \ strm2txt.cc \ strmcmp.cc \ strmxor.cc \ + strmrun.cc \ HEADERS = \ bdCommon.h \ @@ -30,7 +31,7 @@ HEADERS = \ RESOURCES = \ -INCLUDEPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC -DEPENDPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC -LIBS += -L$$DESTDIR -lklayout_tl -lklayout_db -lklayout_gsi +INCLUDEPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC $$RBA_INC $$PYA_INC $$LIB_INC $$RDB_INC +DEPENDPATH += $$TL_INC $$GSI_INC $$VERSION_INC $$DB_INC $$RBA_INC $$PYA_INC $$LIB_INC $$RDB_INC +LIBS += -L$$DESTDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_rba -lklayout_pya -lklayout_lib -lklayout_rdb diff --git a/src/buddies/src/bd/main.cc b/src/buddies/src/bd/main.cc index f850d4275..6778b4b3a 100644 --- a/src/buddies/src/bd/main.cc +++ b/src/buddies/src/bd/main.cc @@ -21,9 +21,22 @@ */ #include "bdInit.h" +#include "tlStaticObjects.h" +#include "rba.h" + +#include BD_PUBLIC int BD_TARGET (int argc, char *argv []); +/** + * @brief The continuation function to support Ruby's special top-level hook + */ +static int main_cont (int argc, char **argv) +{ + QCoreApplication app (argc, argv); + return bd::_main_impl (&BD_TARGET, argc, argv); +} + /** * @brief Provides a main () implementation * @@ -35,5 +48,13 @@ BD_PUBLIC int BD_TARGET (int argc, char *argv []); */ int main (int argc, char *argv []) { - return bd::_main_impl (&BD_TARGET, argc, argv); + // This special initialization is required by the Ruby interpreter because it wants to mark the stack + int ret = rba::RubyInterpreter::initialize (argc, argv, &main_cont); + + // clean up all static data now, since we don't trust the static destructors. + // NOTE: this needs to happen after the Ruby interpreter went down since otherwise the GC will + // access objects that are already cleaned up. + tl::StaticObjects::cleanup (); + + return ret; } diff --git a/src/buddies/src/bd/strmrun.cc b/src/buddies/src/bd/strmrun.cc new file mode 100644 index 000000000..d11b8ac4b --- /dev/null +++ b/src/buddies/src/bd/strmrun.cc @@ -0,0 +1,108 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "bdReaderOptions.h" +#include "bdWriterOptions.h" +#include "gsiInterpreter.h" +#include "dbLayout.h" +#include "dbGDS2Writer.h" +#include "dbOASISWriter.h" +#include "dbReader.h" +#include "tlLog.h" +#include "tlCommandLineParser.h" +#include "rba.h" +#include "pya.h" +#include "gsi.h" +#include "gsiExpression.h" +#include "libForceLink.h" +#include "rdbForceLink.h" + +#include + +struct RunnerData +{ + std::string script; + std::vector > vars; + + void add_var (const std::string &def) + { + std::string var_name, var_value; + tl::Extractor ex (def.c_str ()); + ex.read_word (var_name); + if (ex.test ("=")) { + var_value = ex.get (); + } + + vars.push_back (std::make_pair (var_name, var_value)); + } +}; + +BD_PUBLIC int strmrun (int argc, char *argv[]) +{ + tl::CommandLineOptions cmd; + RunnerData data; + + cmd << tl::arg ("script", &data.script, "The script to execute", + "This script will be executed by the script interpreter. " + "The script can be either Ruby (\".rb\") or Python (\".py\")." + ) + << tl::arg ("*-v|--var=\"name=value\"", &data, &RunnerData::add_var, "Defines a variable", + "When using this option, a global variable with name \"var\" will be defined with the string value \"value\"." + ) + ; + + cmd.brief ("This program runs Ruby or Python scripts with a subset of KLayout's API."); + + cmd.parse (argc, argv); + + // initialize the GSI class system (Variant binding, Expression support) + // We have to do this now since plugins may register GSI classes and before the + // ruby interpreter, because it depends on a proper class system. + gsi::initialize (); + + // initialize the tl::Expression subsystem with GSI-bound classes + gsi::initialize_expressions (); + + // create the ruby and python interpreter instances now. + // Hint: we do this after load_plugin, because that way the plugins can register GSI classes and methods. + // TODO: do this through some auto-registration + rba::RubyInterpreter ruby; + pya::PythonInterpreter python; + + for (std::vector< std::pair >::const_iterator v = data.vars.begin (); v != data.vars.end (); ++v) { + ruby.define_variable (v->first, v->second); + python.define_variable (v->first, v->second); + } + + std::string script = tl::to_string (QFileInfo (tl::to_qstring (data.script)).absoluteFilePath ()); + + std::string ext = tl::to_string (QFileInfo (tl::to_qstring (data.script)).suffix ()); + if (ext == "py") { + python.load_file (script); + } else if (ext == "rb") { + ruby.load_file (script); + } else { + throw tl::Exception (tl::to_string (QObject::tr ("Unknown suffix \"%1\" - must be either .rb or .py").arg (tl::to_qstring (ext)))); + } + + return 0; +} diff --git a/src/buddies/src/buddy_app.pri b/src/buddies/src/buddy_app.pri index 56970dd9f..483be0dea 100644 --- a/src/buddies/src/buddy_app.pri +++ b/src/buddies/src/buddy_app.pri @@ -11,8 +11,8 @@ include($$PWD/../../app.pri) # place - it's not part of the bd sources. SOURCES = $$PWD/bd/main.cc -INCLUDEPATH += $$BD_INC -DEPENDPATH += $$BD_INC -LIBS += -L$$DESTDIR -lklayout_bd -lklayout_db -lklayout_tl -lklayout_gsi +INCLUDEPATH += $$BD_INC $$TL_INC $$RBA_INC $$GSI_INC +DEPENDPATH += $$BD_INC $$TL_INC $$RBA_INC $$GSI_INC +LIBS += -L$$DESTDIR -lklayout_bd -lklayout_db -lklayout_tl -lklayout_gsi -lklayout_pya -lklayout_rba -lklayout_lib -lklayout_rdb DEFINES += BD_TARGET=$$TARGET diff --git a/src/buddies/src/src.pro b/src/buddies/src/src.pro index 2dcaa2e9a..3cf2321ba 100644 --- a/src/buddies/src/src.pro +++ b/src/buddies/src/src.pro @@ -12,6 +12,7 @@ SUBDIRS = \ strmclip \ strmcmp \ strmxor \ + strmrun \ strm2cif.depends += bd strm2dxf.depends += bd @@ -22,3 +23,4 @@ strm2txt.depends += bd strmclip.depends += bd strmcmp.depends += bd strmxor.depends += bd +strmrun.depends += bd diff --git a/src/buddies/src/strmrun/strmrun.pro b/src/buddies/src/strmrun/strmrun.pro new file mode 100644 index 000000000..e04ca961a --- /dev/null +++ b/src/buddies/src/strmrun/strmrun.pro @@ -0,0 +1,2 @@ + +include($$PWD/../buddy_app.pri) diff --git a/src/klayout.pro b/src/klayout.pro index cdadbb11d..03e7bf0b0 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -62,7 +62,7 @@ lym.depends += gsi $$LANG_DEPENDS lay.depends += laybasic ant img edt lym ext.depends += lay lib.depends += db -buddies.depends += db +buddies.depends += rdb lib rba pya equals(HAVE_QTBINDINGS, "1") { SUBDIRS += gsiqt