diff options
-rw-r--r-- | src/func.cc | 24 | ||||
-rw-r--r-- | src/module.cc | 5 | ||||
-rw-r--r-- | src/module.h | 6 | ||||
-rw-r--r-- | src/openscad.cc | 30 | ||||
-rw-r--r-- | src/parsersettings.cc | 9 | ||||
-rw-r--r-- | src/parsersettings.h | 2 | ||||
-rw-r--r-- | testdata/scad/misc/parent_module-tests.scad | 26 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 18 | ||||
-rw-r--r-- | tests/cgalcachetest.cc | 2 | ||||
-rw-r--r-- | tests/csgtexttest.cc | 2 | ||||
-rw-r--r-- | tests/modulecachetest.cc | 2 | ||||
-rw-r--r-- | tests/regression/echotest/parent_module-tests-expected.echo | 9 |
12 files changed, 111 insertions, 24 deletions
diff --git a/src/func.cc b/src/func.cc index 20f487a..865a2b4 100644 --- a/src/func.cc +++ b/src/func.cc @@ -528,6 +528,29 @@ Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) return Value(y * 10000 + m * 100 + d); } +Value builtin_parent_module(const Context *, const EvalContext *evalctx) +{ + int n; + double d; + int s = Module::stack_size(); + if (evalctx->numArgs() == 0) + d=1; // parent module + else if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + evalctx->getArgValue(0).getDouble(d); + else + return Value(); + n=trunc(d); + if (n < 0) { + PRINTB("WARNING: Negative parent module index (%d) not allowed", n); + return Value(); + } + if (n >= s) { + PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n); + return Value(); + } + return Value(Module::stack_element(s - 1 - n)); +} + void register_builtin_functions() { Builtins::init("abs", new BuiltinFunction(&builtin_abs)); @@ -556,4 +579,5 @@ void register_builtin_functions() Builtins::init("search", new BuiltinFunction(&builtin_search)); Builtins::init("version", new BuiltinFunction(&builtin_version)); Builtins::init("version_num", new BuiltinFunction(&builtin_version_num)); + Builtins::init("parent_module", new BuiltinFunction(&builtin_parent_module)); } diff --git a/src/module.cc b/src/module.cc index f66c8ef..1f4059e 100644 --- a/src/module.cc +++ b/src/module.cc @@ -153,6 +153,8 @@ std::vector<AbstractNode*> IfElseModuleInstantiation::instantiateElseChildren(co return this->else_scope.instantiateChildren(evalctx); } +std::deque<std::string> Module::module_stack; + Module::~Module() { } @@ -182,6 +184,8 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation ModuleContext c(ctx, evalctx); // set $children first since we might have variables depending on it c.set_variable("$children", Value(double(inst->scope.children.size()))); + module_stack.push_back(inst->name()); + c.set_variable("$parent_modules", Value(double(module_stack.size()))); c.initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG @@ -191,6 +195,7 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation AbstractNode *node = new AbstractNode(inst); std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); + module_stack.pop_back(); return node; } diff --git a/src/module.h b/src/module.h index b5c58af..8414706 100644 --- a/src/module.h +++ b/src/module.h @@ -4,6 +4,7 @@ #include <string> #include <vector> #include <list> +#include <deque> #include <boost/unordered_map.hpp> #include <boost/unordered_set.hpp> #include <time.h> @@ -73,10 +74,15 @@ public: virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; + static const std::string& stack_element(int n) { return module_stack[n]; }; + static int stack_size() { return module_stack.size(); }; AssignmentList definition_arguments; LocalScope scope; + +private: + static std::deque<std::string> module_stack; }; // FIXME: A FileModule doesn't have definition arguments, so we shouldn't really diff --git a/src/openscad.cc b/src/openscad.cc index f4f4014..e5eb69f 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -190,9 +190,9 @@ Camera get_camera( po::variables_map vm ) return camera; } -int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv ) +int cmdline(const std::string &application_path, const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv ) { - parser_init(boosty::stringy(boost::filesystem::path( argv[0] ).parent_path())); + parser_init(application_path, false); Tree tree; #ifdef ENABLE_CGAL CGALEvaluator cgalevaluator(tree); @@ -454,7 +454,7 @@ bool QtUseGUI() return useGUI; } -int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +int gui(const std::string &application_path, vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) { QApplication app(argc, argv, true); //useGUI); #ifdef Q_WS_MAC @@ -465,7 +465,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha QCoreApplication::setOrganizationDomain("openscad.org"); QCoreApplication::setApplicationName("OpenSCAD"); QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); - + QDir exdir(QApplication::instance()->applicationDirPath()); QString qexamplesdir; #ifdef Q_WS_MAC @@ -486,8 +486,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha qexamplesdir = exdir.path(); } MainWindow::setExamplesDir(qexamplesdir); - - parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); + parser_init(application_path, true); #ifdef Q_WS_MAC installAppleEventHandlers(); @@ -520,7 +519,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha } #else // OPENSCAD_QTGUI bool QtUseGUI() { return false; } -int gui(const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +int gui(const std::string &application_path, const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) { fprintf(stderr,"Error: compiled without QT, but trying to run GUI\n"); return 1; @@ -641,12 +640,23 @@ int main(int argc, char **argv) NodeCache nodecache; NodeDumper dumper(nodecache); - if (output_file) { + bool cmdlinemode = false; + if (output_file) { // cmd-line mode + cmdlinemode = true; if (!inputFiles.size()) help(argv[0]); - rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv); + } + const std::string application_path = +#ifdef OPENSCAD_QTGUI + QApplication::instance()->applicationDirPath().toLocal8Bit().constData(); +#else + boosty::stringy(boosty::absolute(boost::filesystem::path(argv[0]).parent_path())); +#endif + + if (cmdlinemode) { + rc = cmdline(application_path, deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv); } else if (QtUseGUI()) { - rc = gui(inputFiles, original_path, argc, argv); + rc = gui(application_path, inputFiles, original_path, argc, argv); } else { fprintf(stderr, "Requested GUI mode but can't open display!\n"); diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 63a7713..de1ff98 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -88,7 +88,7 @@ fs::path find_valid_path(const fs::path &sourcepath, return fs::path(); } -void parser_init(const std::string &applicationpath) +void parser_init(const std::string &applicationpath, bool isgui) { // Add paths from OPENSCADPATH before adding built-in paths const char *openscadpaths = getenv("OPENSCADPATH"); @@ -116,8 +116,11 @@ void parser_init(const std::string &applicationpath) fs::path libdir(applicationpath); fs::path tmpdir; #ifdef __APPLE__ - libdir /= "../Resources"; // Libraries can be bundled - if (!is_directory(libdir / "libraries")) libdir /= "../../.."; + // Libraries can be bundled on Mac. If not, fall back to development layout + if (isgui) { + libdir /= "../Resources"; + if (!is_directory(libdir / "libraries")) libdir /= "../../.."; + } #elif !defined(WIN32) if (is_directory(tmpdir = libdir / "../share/openscad/libraries")) { librarydir = boosty::stringy(tmpdir); diff --git a/src/parsersettings.h b/src/parsersettings.h index 52172b6..2aef85b 100644 --- a/src/parsersettings.h +++ b/src/parsersettings.h @@ -6,7 +6,7 @@ extern int parser_error_pos; -void parser_init(const std::string &applicationpath); +void parser_init(const std::string &applicationpath, bool isgui); void add_librarydir(const std::string &libdir); fs::path search_libs(const fs::path &localpath); fs::path find_valid_path(const fs::path &sourcepath, diff --git a/testdata/scad/misc/parent_module-tests.scad b/testdata/scad/misc/parent_module-tests.scad new file mode 100644 index 0000000..3777645 --- /dev/null +++ b/testdata/scad/misc/parent_module-tests.scad @@ -0,0 +1,26 @@ +/* + $parent_modules should return the number of module in the module + instantiation stack. The stack is independent on where the modules + are defined. It's where they're instantiated that counts. + + parent_module(N) returns the Nth module name in the stack +*/ +module print(name) { + echo("name: ", name); + for (i=[1:$parent_modules-1]) echo(parent_module(i)); +} + +module yyy() { + print("yyy"); +} + +module test() { + module xxx() { + print("xxx"); + yyy(); + } + print("test"); + xxx(); +} + +test(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d9aef2e..2957240 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -437,6 +437,9 @@ include_directories(../src) add_definitions(-DOPENSCAD_VERSION=test -DOPENSCAD_YEAR=2011 -DOPENSCAD_MONTH=10) add_definitions(-DOPENSCAD_TESTING) +# Search for MCAD in correct place +set(CTEST_ENVIRONMENT "${CTEST_ENVIRONMENT};OPENSCADPATH=${CMAKE_CURRENT_SOURCE_DIR}/../libraries") + # Platform specific settings if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -773,6 +776,7 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/lookup-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/expression-shortcircuit-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parent_module-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/children-tests.scad) list(APPEND DUMPTEST_FILES ${FEATURES_FILES} ${EXAMPLE_FILES}) @@ -938,31 +942,31 @@ add_cmdline_test(openscad-imgstretch2 EXE ${OPENSCAD_BINPATH} SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-camdist EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=0,0,0,90,0,90,300 examples/example001.scad -o + ARGS --imgsize=500,500 --camera=0,0,0,90,0,90,300 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-camrot EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=0,0,0,440,337.5,315,300 examples/example001.scad -o + ARGS --imgsize=500,500 --camera=0,0,0,440,337.5,315,300 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-camtrans EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 examples/example001.scad -o + ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-camortho EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 examples/example001.scad --projection=o -o + ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 --projection=o -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-cameye EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=60,40,30,0,0,0 examples/example001.scad -o + ARGS --imgsize=500,500 --camera=60,40,30,0,0,0 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-cameye2 EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 examples/example001.scad -o + ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-cameyeortho EXE ${OPENSCAD_BINPATH} - ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 examples/example001.scad --projection=o -o + ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 --projection=o -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) add_cmdline_test(openscad-camcenter EXE ${OPENSCAD_BINPATH} diff --git a/tests/cgalcachetest.cc b/tests/cgalcachetest.cc index 67d3313..598879c 100644 --- a/tests/cgalcachetest.cc +++ b/tests/cgalcachetest.cc @@ -126,7 +126,7 @@ int main(int argc, char **argv) currentdir = boosty::stringy(fs::current_path()); - parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path()), false); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); ModuleContext top_ctx; diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc index 97902f6..0be3123 100644 --- a/tests/csgtexttest.cc +++ b/tests/csgtexttest.cc @@ -77,7 +77,7 @@ int main(int argc, char **argv) currentdir = boosty::stringy( fs::current_path() ); - parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path()), false); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); ModuleContext top_ctx; diff --git a/tests/modulecachetest.cc b/tests/modulecachetest.cc index 5531461..423cffc 100644 --- a/tests/modulecachetest.cc +++ b/tests/modulecachetest.cc @@ -73,7 +73,7 @@ int main(int argc, char **argv) currentdir = boosty::stringy( fs::current_path() ); - parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path()), false); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); ModuleContext top_ctx; diff --git a/tests/regression/echotest/parent_module-tests-expected.echo b/tests/regression/echotest/parent_module-tests-expected.echo new file mode 100644 index 0000000..666b259 --- /dev/null +++ b/tests/regression/echotest/parent_module-tests-expected.echo @@ -0,0 +1,9 @@ +ECHO: "name: ", "test" +ECHO: "test" +ECHO: "name: ", "xxx" +ECHO: "xxx" +ECHO: "test" +ECHO: "name: ", "yyy" +ECHO: "yyy" +ECHO: "xxx" +ECHO: "test" |