From dccc039211eebe3f69c935557bd56abae323c26f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 12 Mar 2013 01:14:58 -0400 Subject: Got rid of remaining Qt dependencies. The test framework should now be Qt-free diff --git a/openscad.pro b/openscad.pro index d9442d4..42b8ef0 100644 --- a/openscad.pro +++ b/openscad.pro @@ -247,6 +247,7 @@ HEADERS += src/version_check.h \ src/Camera.h \ src/system-gl.h \ src/stl-utils.h \ + src/boost-utils.h \ src/svg.h \ \ src/lodepng.h \ @@ -291,6 +292,7 @@ SOURCES += src/version_check.cc \ src/progress.cc \ src/parsersettings.cc \ src/stl-utils.cc \ + src/boost-utils.cc \ \ src/nodedumper.cc \ src/traverser.cc \ diff --git a/src/boost-utils.cc b/src/boost-utils.cc new file mode 100644 index 0000000..f81917a --- /dev/null +++ b/src/boost-utils.cc @@ -0,0 +1,42 @@ +#include "boost-utils.h" +#include +#include + +fs::path relativePath(const fs::path &path, const fs::path &relative_to) +{ + // create absolute paths + fs::path p = fs::absolute(path); + fs::path r = fs::absolute(relative_to); + + // if root paths are different, return absolute path + if (p.root_path() != r.root_path()) + return p; + + // initialize relative path + fs::path result; + + // find out where the two paths diverge + fs::path::const_iterator itr_path = p.begin(); + fs::path::const_iterator itr_relative_to = r.begin(); + while (*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end()) { + ++itr_path; + ++itr_relative_to; + } + + // add "../" for each remaining token in relative_to + if (itr_relative_to != r.end()) { + ++itr_relative_to; + while (itr_relative_to != r.end()) { + result /= ".."; + ++itr_relative_to; + } + } + + // add remaining path + while (itr_path != p.end()) { + result /= *itr_path; + ++itr_path; + } + + return result; +} diff --git a/src/boost-utils.h b/src/boost-utils.h new file mode 100644 index 0000000..c431857 --- /dev/null +++ b/src/boost-utils.h @@ -0,0 +1,8 @@ +#ifndef BOOST_UTILS_H_ +#define BOOST_UTILS_H_ + +#include +namespace fs = boost::filesystem; +fs::path relativePath(const fs::path &path, const fs::path &relative_to); + +#endif diff --git a/src/dxfdata.cc b/src/dxfdata.cc index f34af51..be982ff 100644 --- a/src/dxfdata.cc +++ b/src/dxfdata.cc @@ -41,8 +41,9 @@ #include #include -#include #include "value.h" +#include "boost-utils.h" +#include "boosty.h" /*! \class DxfData @@ -389,10 +390,10 @@ DxfData::DxfData(double fn, double fs, double fa, BOOST_FOREACH(const EntityList::value_type &i, unsupported_entities_list) { if (layername.empty()) { PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in %s.", - i.first % i.second % QuotedString(QDir::current().relativeFilePath(QString::fromLocal8Bit(filename.c_str())).toLocal8Bit().constData())); + i.first % i.second % QuotedString(boosty::stringy(relativePath(filename, fs::current_path())))); } else { PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in layer '%s' of %s.", - i.first % i.second % layername % QuotedString(QDir::current().relativeFilePath(QString::fromLocal8Bit(filename.c_str())).toLocal8Bit().constData())); + i.first % i.second % layername % QuotedString(boosty::stringy(relativePath(filename, fs::current_path())))); } } diff --git a/src/dxftess-glu.cc b/src/dxftess-glu.cc index 1a8bfa5..941dbed 100644 --- a/src/dxftess-glu.cc +++ b/src/dxftess-glu.cc @@ -3,14 +3,11 @@ #include "polyset.h" #include "grid.h" #include +#include #include "system-gl.h" #include "mathc99.h" -#include -#include -#include - #ifdef WIN32 # define STDCALL __stdcall #else @@ -31,7 +28,7 @@ struct tess_triangle { static GLenum tess_type; static int tess_count; -static QVector tess_tri; +static std::vector tess_tri; static GLdouble *tess_p1, *tess_p2; static void STDCALL tess_vertex(void *vertex_data) @@ -48,7 +45,7 @@ static void STDCALL tess_vertex(void *vertex_data) tess_p2 = p; } if (tess_count > 1) { - tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); + tess_tri.push_back(tess_triangle(tess_p1, tess_p2, p)); tess_p2 = p; } } @@ -61,9 +58,9 @@ static void STDCALL tess_vertex(void *vertex_data) } if (tess_count > 1) { if (tess_count % 2 == 1) { - tess_tri.append(tess_triangle(tess_p2, tess_p1, p)); + tess_tri.push_back(tess_triangle(tess_p2, tess_p1, p)); } else { - tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); + tess_tri.push_back(tess_triangle(tess_p1, tess_p2, p)); } tess_p1 = tess_p2; tess_p2 = p; @@ -77,7 +74,7 @@ static void STDCALL tess_vertex(void *vertex_data) tess_p2 = p; } if (tess_count == 2) { - tess_tri.append(tess_triangle(tess_p1, tess_p2, p)); + tess_tri.push_back(tess_triangle(tess_p1, tess_p2, p)); tess_count = -1; } } @@ -214,7 +211,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian tess_tri.clear(); - QList vl; + std::list vl; gluTessBeginPolygon(tobj, NULL); @@ -225,7 +222,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian gluTessNormal(tobj, 0, 0, +1); } - Grid3d< QPair > point_to_path(GRID_COARSE); + Grid3d< std::pair > point_to_path(GRID_COARSE); for (int i = 0; i < dxf.paths.size(); i++) { if (!dxf.paths[i].is_closed) @@ -234,12 +231,12 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian for (int j = 1; j < dxf.paths[i].indices.size(); j++) { point_to_path.data(dxf.points[dxf.paths[i].indices[j]][0], dxf.points[dxf.paths[i].indices[j]][1], - h) = QPair(i, j); - vl.append(tess_vdata()); - vl.last().v[0] = dxf.points[dxf.paths[i].indices[j]][0]; - vl.last().v[1] = dxf.points[dxf.paths[i].indices[j]][1]; - vl.last().v[2] = h; - gluTessVertex(tobj, vl.last().v, vl.last().v); + h) = std::pair(i, j); + vl.push_back(tess_vdata()); + vl.back().v[0] = dxf.points[dxf.paths[i].indices[j]][0]; + vl.back().v[1] = dxf.points[dxf.paths[i].indices[j]][1]; + vl.back().v[2] = h; + gluTessVertex(tobj, vl.back().v, vl.back().v); } gluTessEndContour(tobj); } @@ -263,7 +260,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian point_on_line(tess_tri[i].p[1], tess_tri[i].p[2], tess_tri[i].p[0]) || point_on_line(tess_tri[i].p[2], tess_tri[i].p[0], tess_tri[i].p[1])) { // printf("DEBUG: Removed triangle\n"); - tess_tri.remove(i--); + tess_tri.erase(tess_tri.begin() + i--); } } @@ -277,13 +274,13 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian if (do_triangle_splitting) { bool added_triangles = true; - typedef QPair QPair_ii; - QHash tri_by_atan2; + typedef std::pair pair_ii; + boost::unordered_multimap tri_by_atan2; for (int i = 0; i < tess_tri.size(); i++) for (int j = 0; j < 3; j++) { int ai = (int)round(atan2(fabs(tess_tri[i].p[(j+1)%3][0] - tess_tri[i].p[j][0]), fabs(tess_tri[i].p[(j+1)%3][1] - tess_tri[i].p[j][1])) / 0.001); - tri_by_atan2.insertMulti(ai, QPair(i, j)); + tri_by_atan2.emplace(ai, std::pair(i, j)); } while (added_triangles) { @@ -294,20 +291,23 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian for (int i = 0; i < tess_tri.size(); i++) for (int k = 0; k < 3; k++) { - QHash possible_neigh; + boost::unordered_map possible_neigh; int ai = (int)floor(atan2(fabs(tess_tri[i].p[(k+1)%3][0] - tess_tri[i].p[k][0]), fabs(tess_tri[i].p[(k+1)%3][1] - tess_tri[i].p[k][1])) / 0.001 - 0.5); for (int j = 0; j < 2; j++) { - foreach (const QPair_ii &jl, tri_by_atan2.values(ai+j)) - if (i != jl.first) - possible_neigh[jl] = jl; + for (boost::unordered_multimap::iterator it = tri_by_atan2.find(ai+j); + it != tri_by_atan2.end(); + it++) { + if (i != it->first) possible_neigh[it->second] = it->second; + } } #ifdef DEBUG_TRIANGLE_SPLITTING printf("%d/%d: %d\n", i, k, possible_neigh.size()); #endif - foreach (const QPair_ii &jl, possible_neigh) { - int j = jl.first; - for (int l = jl.second; l != (jl.second + 2) % 3; l = (l + 1) % 3) + typedef std::pair ElemPair; + BOOST_FOREACH (const ElemPair &elem, possible_neigh) { + int j = elem.first.first; + for (int l = elem.first.second; l != (elem.first.second + 2) % 3; l = (l + 1) % 3) if (point_on_line(tess_tri[i].p[k], tess_tri[j].p[l], tess_tri[i].p[(k+1)%3])) { #ifdef DEBUG_TRIANGLE_SPLITTING printf("%% %f %f %f %f %f %f [%d %d]\n", @@ -316,18 +316,18 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian tess_tri[i].p[(k+1)%3][0], tess_tri[i].p[(k+1)%3][1], i, j); #endif - tess_tri.append(tess_triangle(tess_tri[j].p[l], + tess_tri.push_back(tess_triangle(tess_tri[j].p[l], tess_tri[i].p[(k+1)%3], tess_tri[i].p[(k+2)%3])); for (int m = 0; m < 2; m++) { - int ai = (int)round(atan2(fabs(tess_tri.last().p[(m+1)%3][0] - tess_tri.last().p[m][0]), - fabs(tess_tri.last().p[(m+1)%3][1] - tess_tri.last().p[m][1])) / 0.001 ); - tri_by_atan2.insertMulti(ai, QPair(tess_tri.size()-1, m)); + int ai = (int)round(atan2(fabs(tess_tri.back().p[(m+1)%3][0] - tess_tri.back().p[m][0]), + fabs(tess_tri.back().p[(m+1)%3][1] - tess_tri.back().p[m][1])) / 0.001 ); + tri_by_atan2.emplace(ai, std::pair(tess_tri.size()-1, m)); } tess_tri[i].p[(k+1)%3] = tess_tri[j].p[l]; for (int m = 0; m < 2; m++) { int ai = (int)round(atan2(fabs(tess_tri[i].p[(m+1)%3][0] - tess_tri[i].p[m][0]), fabs(tess_tri[i].p[(m+1)%3][1] - tess_tri[i].p[m][1])) / 0.001 ); - tri_by_atan2.insertMulti(ai, QPair(i, m)); + tri_by_atan2.emplace(ai, std::pair(i, m)); } added_triangles = true; } diff --git a/src/parsersettings.cc b/src/parsersettings.cc index a757ba1..8d82744 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -3,8 +3,9 @@ #include #include "boosty.h" #include -#include // Needed for Q_ defines - move the offending code somewhere else +#ifdef __APPLE__ #include "CocoaUtils.h" +#endif namespace fs = boost::filesystem; diff --git a/src/value.cc b/src/value.cc index f14f826..bec803a 100644 --- a/src/value.cc +++ b/src/value.cc @@ -34,12 +34,12 @@ #include #include #include - -#include +#include "boost-utils.h" +#include "boosty.h" std::ostream &operator<<(std::ostream &stream, const Filename &filename) { - stream << QuotedString(QDir::current().relativeFilePath(QString::fromLocal8Bit(filename.c_str())).toLocal8Bit().constData()); + stream << QuotedString(boosty::stringy(relativePath(filename, fs::current_path()))); return stream; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5eecaae..8fd079f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -179,28 +179,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") FIND_LIBRARY(COCOA_LIBRARY Cocoa REQUIRED) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Qt4 - -set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON) -find_package(OpenGL REQUIRED) -if ( "${OPENGL_glu_LIBRARY}" MATCHES "NOTFOUND" ) - # GLU and Mesa split in late 2012 so some systems dont have GLU - find_library(OPENGL_glu_LIBRARY GLU HINTS "$ENV{OPENSCAD_LIBRARIES}/lib" REQUIRED) - set( OPENGL_LIBRARY ${OPENGL_glu_LIBRARY} ${OPENGL_LIBRARY} ) -endif() - -if (MINGW_CROSS_ENV_DIR) - mingw_cross_env_find_qt() - mingw_cross_env_info() - include_directories( ${QT_INCLUDE_DIRS} ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT_CFLAGS_OTHER}") -else() - find_package(Qt4 COMPONENTS QtCore REQUIRED) - include(${QT_USE_FILE}) -endif() - -set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF) - # Eigen @@ -268,6 +246,8 @@ else() inclusion(EIGEN_DIR EIGEN_INCLUDE_DIR) endif() +# OpenGL +find_package(OpenGL REQUIRED) # OpenCSG if (NOT $ENV{OPENCSGDIR} STREQUAL "") @@ -444,6 +424,7 @@ set(CORE_SOURCES ../src/rotateextrude.cc ../src/printutils.cc ../src/progress.cc + ../src/boost-utils.cc ${FLEX_OpenSCADlexer_OUTPUTS} ${BISON_OpenSCADparser_OUTPUTS}) diff --git a/tests/cgalcachetest.cc b/tests/cgalcachetest.cc index 3a0a855..b7e51b5 100644 --- a/tests/cgalcachetest.cc +++ b/tests/cgalcachetest.cc @@ -40,7 +40,6 @@ #include "PolySetCGALEvaluator.h" #include "CGALCache.h" -#include #ifndef _MSC_VER #include #endif @@ -57,7 +56,6 @@ namespace po = boost::program_options; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -124,13 +122,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); - currentdir = boosty::stringy( fs::current_path() ); + currentdir = boosty::stringy(fs::current_path()); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index 52205fd..947a231 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -43,7 +43,6 @@ #include "cgal.h" #include "OffscreenView.h" -#include #ifndef _MSC_VER #include #endif @@ -57,7 +56,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -97,13 +95,12 @@ int main(int argc, char **argv) #endif Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/cgalstlsanitytest.cc b/tests/cgalstlsanitytest.cc index 2815463..228bfde 100644 --- a/tests/cgalstlsanitytest.cc +++ b/tests/cgalstlsanitytest.cc @@ -38,11 +38,6 @@ #include "CGALEvaluator.h" #include "PolySetCGALEvaluator.h" -#include -#include -#include -#include -#include #ifndef _MSC_VER #include #endif @@ -56,7 +51,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -83,13 +77,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc index 4a15050..9c8c090 100644 --- a/tests/cgaltest.cc +++ b/tests/cgaltest.cc @@ -38,7 +38,6 @@ #include "CGALEvaluator.h" #include "PolySetCGALEvaluator.h" -#include #ifndef _MSC_VER #include #endif @@ -52,7 +51,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -76,13 +74,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc index e793c4a..864ba5d 100644 --- a/tests/csgtermtest.cc +++ b/tests/csgtermtest.cc @@ -38,7 +38,6 @@ #include "Tree.h" #include "csgterm.h" -#include #ifndef _MSC_VER #include #endif @@ -53,7 +52,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::cout; @@ -71,13 +69,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 7583a41..1e518e2 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -23,9 +23,6 @@ #include "csgtermnormalizer.h" #include "OffscreenView.h" -#include -#include - #include #include @@ -128,14 +125,12 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); - fs::path original_path = fs::current_path(); std::string currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc index e050232..6a72dff 100644 --- a/tests/csgtexttest.cc +++ b/tests/csgtexttest.cc @@ -37,7 +37,6 @@ #include "builtin.h" #include "Tree.h" -#include #ifndef _MSC_VER #include #endif @@ -52,7 +51,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; void csgTree(CSGTextCache &cache, const AbstractNode &root) { @@ -75,13 +73,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index b75a2e2..4ddefe2 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -35,7 +35,6 @@ #include "builtin.h" #include "Tree.h" -#include #ifndef _MSC_VER #include #endif @@ -50,7 +49,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -81,13 +79,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy(fs::current_path()); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/echotest.cc b/tests/echotest.cc index bf2f4a4..af4942b 100644 --- a/tests/echotest.cc +++ b/tests/echotest.cc @@ -34,7 +34,6 @@ #include "builtin.h" #include "printutils.h" -#include #ifndef _MSC_VER #include #endif @@ -49,7 +48,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -83,13 +81,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); diff --git a/tests/modulecachetest.cc b/tests/modulecachetest.cc index 0028114..1103720 100644 --- a/tests/modulecachetest.cc +++ b/tests/modulecachetest.cc @@ -35,7 +35,6 @@ #include "builtin.h" #include "Tree.h" -#include #ifndef _MSC_VER #include #endif @@ -50,7 +49,6 @@ namespace fs = boost::filesystem; std::string commandline_commands; std::string currentdir; -QString examplesdir; using std::string; @@ -71,13 +69,12 @@ int main(int argc, char **argv) Builtins::instance()->initialize(); - QCoreApplication app(argc, argv); fs::path original_path = fs::current_path(); currentdir = boosty::stringy( fs::current_path() ); - parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); - add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); Context root_ctx; register_builtin(root_ctx); -- cgit v0.10.1 From 5628a18f6a0fcf2dd170cac31e386f1ad4f97c0c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 12 Mar 2013 12:35:32 -0400 Subject: boostfs_relative_path was buggy, replaced with boostfs_uncomplete for now diff --git a/src/boost-utils.cc b/src/boost-utils.cc index f81917a..5127047 100644 --- a/src/boost-utils.cc +++ b/src/boost-utils.cc @@ -2,10 +2,12 @@ #include #include -fs::path relativePath(const fs::path &path, const fs::path &relative_to) +// If the given (absolute) path is relative to the relative_to path, return a new +// relative path. Will normalize the given path first +fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to) { // create absolute paths - fs::path p = fs::absolute(path); + fs::path p = fs::absolute(boostfs_normalize(path)); fs::path r = fs::absolute(relative_to); // if root paths are different, return absolute path @@ -40,3 +42,125 @@ fs::path relativePath(const fs::path &path, const fs::path &relative_to) return result; } + +// Will normalize the given path, i.e. remove any redundant ".." path elements. +fs::path boostfs_normalize(const fs::path &path) +{ + fs::path absPath = absolute(path); + fs::path::iterator it = absPath.begin(); + fs::path result = *it++; + + // Get canonical version of the existing part + for(;exists(result) && it != absPath.end(); ++it) { + result /= *it; + } + result = canonical(result.parent_path()); + --it; + + // For the rest remove ".." and "." in a path with no symlinks + for (; it != absPath.end(); ++it) { + // Just move back on ../ + if (*it == "..") { + result = result.parent_path(); + } + // Ignore "." + else if (*it != ".") { + // Just cat other path entries + result /= *it; + } + } + + return result; +} + +/** + * https://svn.boost.org/trac/boost/ticket/1976#comment:2 + * + * "The idea: uncomplete(/foo/new, /foo/bar) => ../new + * The use case for this is any time you get a full path (from an open dialog, perhaps) + * and want to store a relative path so that the group of files can be moved to a different + * directory without breaking the paths. An IDE would be a simple example, so that the + * project file could be safely checked out of subversion." + * + * ALGORITHM: + * iterate path and base + * compare all elements so far of path and base + * whilst they are the same, no write to output +x2 * when they change, or one runs out: + * write to output, ../ times the number of remaining elements in base + * write to output, the remaining elements in path + */ +fs::path +boostfs_uncomplete(fs::path const p, fs::path const base) +{ + if (p == base) return "./"; + /*!! this breaks stuff if path is a filename rather than a directory, + which it most likely is... but then base shouldn't be a filename so... */ + + // create absolute paths + fs::path abs_p = fs::absolute(boostfs_normalize(p)); + fs::path abs_base = fs::absolute(base); + + fs::path from_path, from_base, output; + + fs::path::iterator path_it = abs_p.begin(), path_end = abs_p.end(); + fs::path::iterator base_it = abs_base.begin(), base_end = abs_base.end(); + + // check for emptiness + if ((path_it == path_end) || (base_it == base_end)) { + throw std::runtime_error("path or base was empty; couldn't generate relative path"); + } + +#ifdef WIN32 + // drive letters are different; don't generate a relative path + if (*path_it != *base_it) return p; + + // now advance past drive letters; relative paths should only go up + // to the root of the drive and not past it + ++path_it, ++base_it; +#endif + + // Cache system-dependent dot, double-dot and slash strings + const std::string _dot = "."; + const std::string _dots = ".."; + const std::string _sep = "/"; + + // iterate over path and base + while (true) { + + // compare all elements so far of path and base to find greatest common root; + // when elements of path and base differ, or run out: + if ((path_it == path_end) || (base_it == base_end) || (*path_it != *base_it)) { + + // write to output, ../ times the number of remaining elements in base; + // this is how far we've had to come down the tree from base to get to the common root + for (; base_it != base_end; ++base_it) { + if (*base_it == _dot) + continue; + else if (*base_it == _sep) + continue; + + output /= "../"; + } + + // write to output, the remaining elements in path; + // this is the path relative from the common root + fs::path::iterator path_it_start = path_it; + for (; path_it != path_end; ++path_it) { + if (path_it != path_it_start) output /= "/"; + if (*path_it == _dot) continue; + if (*path_it == _sep) continue; + output /= *path_it; + } + break; + } + + // add directory level to both paths and continue iteration + from_path /= fs::path(*path_it); + from_base /= fs::path(*base_it); + + ++path_it, ++base_it; + } + + return output; +} diff --git a/src/boost-utils.h b/src/boost-utils.h index c431857..3678ecc 100644 --- a/src/boost-utils.h +++ b/src/boost-utils.h @@ -3,6 +3,11 @@ #include namespace fs = boost::filesystem; -fs::path relativePath(const fs::path &path, const fs::path &relative_to); + +// FIXME: boostfs_relative_path() has been replaced by +// boostfs_uncomplete(), but kept around for now. +fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to); +fs::path boostfs_normalize(const fs::path &path); +fs::path boostfs_uncomplete(fs::path const p, fs::path const base); #endif diff --git a/src/dxfdata.cc b/src/dxfdata.cc index be982ff..8415228 100644 --- a/src/dxfdata.cc +++ b/src/dxfdata.cc @@ -390,10 +390,10 @@ DxfData::DxfData(double fn, double fs, double fa, BOOST_FOREACH(const EntityList::value_type &i, unsupported_entities_list) { if (layername.empty()) { PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in %s.", - i.first % i.second % QuotedString(boosty::stringy(relativePath(filename, fs::current_path())))); + i.first % i.second % QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path())))); } else { PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in layer '%s' of %s.", - i.first % i.second % layername % QuotedString(boosty::stringy(relativePath(filename, fs::current_path())))); + i.first % i.second % layername % QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path())))); } } diff --git a/src/value.cc b/src/value.cc index bec803a..ae810a2 100644 --- a/src/value.cc +++ b/src/value.cc @@ -39,7 +39,7 @@ std::ostream &operator<<(std::ostream &stream, const Filename &filename) { - stream << QuotedString(boosty::stringy(relativePath(filename, fs::current_path()))); + stream << QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path()))); return stream; } -- cgit v0.10.1 From 5edc8c57da6eb8bfb7725ac51c4b87edd950e847 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 16 Mar 2013 21:55:38 +0100 Subject: update cmakelist for building tests in same dir as gui binary diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5eecaae..6178c3a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -604,6 +604,10 @@ else() set(GUI_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../openscad") endif() +if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/openscad") + set(GUI_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad") +endif() + if(EXISTS "${GUI_BINPATH}") message(STATUS "Found OpenSCAD GUI binary: ${GUI_BINPATH}") else() -- cgit v0.10.1 From 100b1733df981aa542675d2dad198a259a61ccd2 Mon Sep 17 00:00:00 2001 From: don bright Date: Sun, 17 Mar 2013 18:34:47 +0100 Subject: backport boost functions to pre-1.48 diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index dc61f74..784a191 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -513,7 +513,7 @@ if [ $1 ]; then exit $? fi if [ $1 = "cgal" ]; then - build_cgal 4.0.2 use-sys-libs + build_cgal 4.1 use-sys-libs exit $? fi if [ $1 = "opencsg" ]; then diff --git a/src/boost-utils.cc b/src/boost-utils.cc index 5127047..534cbaa 100644 --- a/src/boost-utils.cc +++ b/src/boost-utils.cc @@ -1,3 +1,4 @@ +#include "boosty.h" #include "boost-utils.h" #include #include @@ -7,8 +8,8 @@ fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to) { // create absolute paths - fs::path p = fs::absolute(boostfs_normalize(path)); - fs::path r = fs::absolute(relative_to); + fs::path p = boosty::absolute(boostfs_normalize(path)); + fs::path r = boosty::absolute(relative_to); // if root paths are different, return absolute path if (p.root_path() != r.root_path()) @@ -46,16 +47,17 @@ fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to // Will normalize the given path, i.e. remove any redundant ".." path elements. fs::path boostfs_normalize(const fs::path &path) { - fs::path absPath = absolute(path); + fs::path absPath = boosty::absolute(path); fs::path::iterator it = absPath.begin(); - fs::path result = *it++; + fs::path result = *it; + if (it!=absPath.end()) it++; // Get canonical version of the existing part for(;exists(result) && it != absPath.end(); ++it) { result /= *it; } - result = canonical(result.parent_path()); - --it; + result = boosty::canonical(result.parent_path()); + if (it!=absPath.begin()) it--; // For the rest remove ".." and "." in a path with no symlinks for (; it != absPath.end(); ++it) { @@ -98,8 +100,8 @@ boostfs_uncomplete(fs::path const p, fs::path const base) which it most likely is... but then base shouldn't be a filename so... */ // create absolute paths - fs::path abs_p = fs::absolute(boostfs_normalize(p)); - fs::path abs_base = fs::absolute(base); + fs::path abs_p = boosty::absolute(boostfs_normalize(p)); + fs::path abs_base = boosty::absolute(base); fs::path from_path, from_base, output; diff --git a/src/boosty.h b/src/boosty.h index 6ec417a..5c82002 100644 --- a/src/boosty.h +++ b/src/boosty.h @@ -10,9 +10,8 @@ versions of boost found on popular versions of linux, circa early 2012. design - hope that the user is compiling with boost>1.46 + filesystem v3 - if not, fall back to older deprecated functions, and rely on - testing to find bugs. implement the minimum needed by OpenSCAD and no more. + the boost filsystem changed around 1.46-1.48. we do a large #ifdef + based on boost version that wraps various functions appropriately. in a few years, this file should be deleted as unnecessary. see also @@ -28,6 +27,7 @@ #include #include namespace fs = boost::filesystem; +#include "printutils.h" namespace boosty { @@ -77,6 +77,62 @@ inline std::string extension_str( fs::path p) #endif + + + + +#if BOOST_VERSION >= 104800 + +inline fs::path canonical( fs::path p, fs::path p2 ) +{ + return fs::canonical( p, p2, NULL ); +} + +inline fs::path canonical( fs::path p ) +{ + return fs::canonical( p, fs::current_path(), NULL ); +} + +#else + +inline fs::path canonical( fs::path p, fs::path p2 ) +{ + // dotpath: win32/mac builds will be using newer versions of boost + // so we can treat this as though it is unix only + const fs::path dot_path("."); + const fs::path dot_dot_path(".."); + fs::path result; + if (p=="") + { + p=p2; + } + for (fs::path::iterator itr = p.begin(); itr != p.end(); itr++) + { + if (*itr == dot_path) continue; + if (*itr == dot_dot_path) + { + result.remove_filename(); + continue; + } + result /= *itr; + if (fs::is_symlink(result)) + { + PRINT("WARNING: canonical() wrapper can't do symlinks. upgrade boost to >1.48"); + } + } + return result; +} + +inline fs::path canonical( fs::path p ) +{ + return canonical( p, fs::current_path() ); +} + +#endif + + + + } // namespace #endif diff --git a/src/value.cc b/src/value.cc index ae810a2..ebb825d 100644 --- a/src/value.cc +++ b/src/value.cc @@ -39,7 +39,9 @@ std::ostream &operator<<(std::ostream &stream, const Filename &filename) { - stream << QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path()))); + fs::path fnpath = fs::path( (std::string)filename ); + fs::path fpath = boostfs_uncomplete(fnpath, fs::current_path()); + stream << QuotedString(boosty::stringy( fpath )); return stream; } -- cgit v0.10.1 From c8c749de1893d76966d924e22276b3d7d58f3b58 Mon Sep 17 00:00:00 2001 From: don bright Date: Sun, 17 Mar 2013 11:21:15 -0700 Subject: fix some bugs in wrapper of canonical() diff --git a/src/boosty.h b/src/boosty.h index 5c82002..6dc9858 100644 --- a/src/boosty.h +++ b/src/boosty.h @@ -85,12 +85,12 @@ inline std::string extension_str( fs::path p) inline fs::path canonical( fs::path p, fs::path p2 ) { - return fs::canonical( p, p2, NULL ); + return fs::canonical( p, p2 ); } inline fs::path canonical( fs::path p ) { - return fs::canonical( p, fs::current_path(), NULL ); + return fs::canonical( p ); } #else -- cgit v0.10.1 From f40942441882823f9b432c57eead64a89507e577 Mon Sep 17 00:00:00 2001 From: don bright Date: Sun, 17 Mar 2013 11:57:29 -0700 Subject: update to match Marius' version diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 308bbe9..9e2da81 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -20,7 +20,6 @@ o Changed multmatrix floating-point output to improve dumptest portability o Regression test auto-starts & stops Xvfb / Xvnc if on headless unix machine o CGAL triangulation more lenient- enables partial rendering of 'bad' DXF data o Fixes problem where local changes are overwritten on automatic reload when included files has changed. -o Non-ascii filenames are now allowed OpenSCAD 2013.01 ================ -- cgit v0.10.1 From 1949403689f9cc6f5c5b59e27176518fac4426b9 Mon Sep 17 00:00:00 2001 From: don bright Date: Sun, 17 Mar 2013 11:58:53 -0700 Subject: boost s/b >=1.48 not >1.48 diff --git a/src/boosty.h b/src/boosty.h index 6dc9858..2b5ab38 100644 --- a/src/boosty.h +++ b/src/boosty.h @@ -117,7 +117,7 @@ inline fs::path canonical( fs::path p, fs::path p2 ) result /= *itr; if (fs::is_symlink(result)) { - PRINT("WARNING: canonical() wrapper can't do symlinks. upgrade boost to >1.48"); + PRINT("WARNING: canonical() wrapper can't do symlinks. upgrade boost to >=1.48"); } } return result; -- cgit v0.10.1 From 8e32cef0a8c52742bf12cafd2aa9dafd1efe764e Mon Sep 17 00:00:00 2001 From: don bright Date: Sun, 17 Mar 2013 12:29:02 -0700 Subject: more accurate help message diff --git a/src/boosty.h b/src/boosty.h index 2b5ab38..8b0c93e 100644 --- a/src/boosty.h +++ b/src/boosty.h @@ -117,7 +117,8 @@ inline fs::path canonical( fs::path p, fs::path p2 ) result /= *itr; if (fs::is_symlink(result)) { - PRINT("WARNING: canonical() wrapper can't do symlinks. upgrade boost to >=1.48"); + PRINT("WARNING: canonical() wrapper can't do symlinks. rebuild openscad with boost >=1.48"); + PRINT("WARNING: or don't use symbolic links"); } } return result; -- cgit v0.10.1 From 3d9a7c91e0189019a9a7bd3b6da67f3e619a5622 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 17 Mar 2013 17:29:57 -0500 Subject: Bumped mpfr to 3.1.2 diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 11d9919..9814987 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -412,7 +412,7 @@ mkdir -p $SRCDIR $DEPLOYDIR build_qt 4.8.4 build_eigen 3.1.2 build_gmp 5.1.1 -build_mpfr 3.1.1 +build_mpfr 3.1.2 build_boost 1.53.0 # NB! For CGAL, also update the actual download URL in the function build_cgal 4.1 -- cgit v0.10.1 From d545a227260ddd72b1fdb5c3dc2ebb1bae36c410 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 17 Mar 2013 17:30:29 -0500 Subject: Updated dependencies diff --git a/README.md b/README.md index c3e2e36..9449a91 100644 --- a/README.md +++ b/README.md @@ -84,15 +84,15 @@ libraries from aptitude. If you're using Mac, or an older Linux/BSD, there are build scripts that download and compile the libraries from source. Follow the instructions for the platform you're compiling on below. -* [Qt4 (4.4 - 4.7)](http://www.qt.nokia.com/) -* [CGAL (3.6 - 4.0.2)](http://www.cgal.org/) - * [GMP (5.0.x)](http://www.gmplib.org/) - * [cmake (2.6 - 2.8, required by CGAL and the test framework)](http://www.cmake.org/) +* [Qt4 (4.4 - 4.8)](http://www.qt.nokia.com/) +* [CGAL (3.6 - 4.1)](http://www.cgal.org/) + * [GMP (5.x)](http://www.gmplib.org/) + * [cmake (2.8, required by CGAL and the test framework)](http://www.cmake.org/) * [MPFR (3.x)](http://www.mpfr.org/) - * [boost (1.35 - 1.47)](http://www.boost.org/) + * [boost (1.35 - 1.53)](http://www.boost.org/) * [OpenCSG (1.3.2)](http://www.opencsg.org/) * [GLEW (1.5.4 ->)](http://glew.sourceforge.net/) -* [Eigen (2.0.13->3.1.1)](http://eigen.tuxfamily.org/) +* [Eigen (2.0.x->3.x)](http://eigen.tuxfamily.org/) * [GCC C++ Compiler (4.2 ->)](http://gcc.gnu.org/) * [Bison (2.4)](http://www.gnu.org/software/bison/) * [Flex (2.5.35)](http://flex.sourceforge.net/) -- cgit v0.10.1 From f242a7a6934effdb292c0fedafa954bafc615cc3 Mon Sep 17 00:00:00 2001 From: don bright Date: Thu, 21 Mar 2013 04:29:54 +0100 Subject: backport to boost 1.37. improve dependency build for older lib versions including the requirement of symlink to $DEPLOYDIR/include/boost if boost is so old that it uses version numbers in the path name diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index 784a191..bfc830f 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -264,6 +264,12 @@ build_boost() echo boost build failed exit 1 fi + if [ "`ls $DEPLOYDIR/include/ | grep boost.[0-9]`" ]; then + if [ ! -e $DEPLOYDIR/include/boost ]; then + echo "boost is old, make a symlink to $DEPLOYDIR/include/boost & rerun" + exit 1 + fi + fi } build_cgal() @@ -276,17 +282,26 @@ build_cgal() echo "Building CGAL" $version "..." cd $BASEDIR/src rm -rf CGAL-$version - if [ ! -f CGAL-$version.tar.* ]; then - # 4.1 - curl --insecure -O https://gforge.inria.fr/frs/download.php/31640/CGAL-$version.tar.bz2 - # 4.0.2 curl --insecure -O https://gforge.inria.fr/frs/download.php/31174/CGAL-$version.tar.bz2 - # 4.0 curl --insecure -O https://gforge.inria.fr/frs/download.php/30387/CGAL-$version.tar.gz #4.0 - # 3.9 curl --insecure -O https://gforge.inria.fr/frs/download.php/29125/CGAL-$version.tar.gz #3.9 - # 3.8 curl --insecure -O https://gforge.inria.fr/frs/download.php/28500/CGAL-$version.tar.gz - # 3.7 curl --insecure -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz - fi - tar xf CGAL-$version.tar.bz2 + ver4_1="curl --insecure -O https://gforge.inria.fr/frs/download.php/31640/CGAL-4.1.tar.bz2" + ver4_0_2="curl --insecure -O https://gforge.inria.fr/frs/download.php/31174/CGAL-4.0.2.tar.bz2" + ver4_0="curl --insecure -O https://gforge.inria.fr/frs/download.php/30387/CGAL-4.0.tar.gz" + ver3_9="curl --insecure -O https://gforge.inria.fr/frs/download.php/29125/CGAL-3.9.tar.gz" + ver3_8="curl --insecure -O https://gforge.inria.fr/frs/download.php/28500/CGAL-3.8.tar.gz" + ver3_7="curl --insecure -O https://gforge.inria.fr/frs/download.php/27641/CGAL-3.7.tar.gz" + vernull="echo already downloaded..skipping" + download_cmd=ver`echo $version | sed s/"\."/"_"/` + if [ -e CGAL-$version.tar.gz ]; then download_cmd=vernull; fi + if [ -e CGAL-$version.tar.bz2 ]; then download_cmd=vernull; fi + `eval echo "$"$download_cmd` + if [ -e CGAL-$version.tar.gz ]; then tar xf CGAL-$version.tar.gz; fi + if [ -e CGAL-$version.tar.bz2 ]; then tar xf CGAL-$version.tar.bz2; fi cd CGAL-$version + + # older cmakes have buggy FindBoost that can result in + # finding the system libraries but OPENSCAD_LIBRARIES include paths + FINDBOOST_CMAKE=$OPENSCAD_SCRIPTDIR/../tests/FindBoost.cmake + cp $FINDBOOST_CMAKE ./cmake/modules/ + mkdir bin cd bin rm -rf ./* @@ -295,10 +310,13 @@ build_cgal() else CGAL_BUILDTYPE="Debug" fi + + DEBUGBOOSTFIND=0 # for debugging FindBoost.cmake (not for debugging boost) + Boost_NO_SYSTEM_PATHS=1 if [ "`echo $2 | grep use-sys-libs`" ]; then - cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DCMAKE_BUILD_TYPE=$CGAL_BUILDTYPE .. + cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DCMAKE_BUILD_TYPE=$CGAL_BUILDTYPE -DBoost_DEBUG=$DEBUGBOOSTFIND .. else - cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DGMP_INCLUDE_DIR=$DEPLOYDIR/include -DGMP_LIBRARIES=$DEPLOYDIR/lib/libgmp.so -DGMPXX_LIBRARIES=$DEPLOYDIR/lib/libgmpxx.so -DGMPXX_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_LIBRARIES=$DEPLOYDIR/lib/libmpfr.so -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DBOOST_ROOT=$DEPLOYDIR -DBoost_USE_MULTITHREADED=false -DCMAKE_BUILD_TYPE=$CGAL_BUILD_TYPE .. + cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DGMP_INCLUDE_DIR=$DEPLOYDIR/include -DGMP_LIBRARIES=$DEPLOYDIR/lib/libgmp.so -DGMPXX_LIBRARIES=$DEPLOYDIR/lib/libgmpxx.so -DGMPXX_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_LIBRARIES=$DEPLOYDIR/lib/libmpfr.so -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DBOOST_LIBRARYDIR=$DEPLOYDIR/lib -DBOOST_INCLUDEDIR=$DEPLOYDIR/include -DCMAKE_BUILD_TYPE=$CGAL_BUILD_TYPE -DBoost_DEBUG=$DEBUGBOOSTFIND -DBoost_NO_SYSTEM_PATHS=1 .. fi make -j$NUMCPU make install @@ -459,7 +477,11 @@ build_eigen() # the 'dirname' command installed if [ "`command -v dirname`" ]; then + RUNDIR=$PWD OPENSCAD_SCRIPTDIR=`dirname $0` + cd $OPENSCAD_SCRIPTDIR + OPENSCAD_SCRIPTDIR=$PWD + cd $RUNDIR else if [ ! -f openscad.pro ]; then echo "Must be run from the OpenSCAD source root directory (dont have 'dirname')" diff --git a/src/boosty.h b/src/boosty.h index 8b0c93e..82c765b 100644 --- a/src/boosty.h +++ b/src/boosty.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace fs = boost::filesystem; #include "printutils.h" @@ -97,29 +98,33 @@ inline fs::path canonical( fs::path p ) inline fs::path canonical( fs::path p, fs::path p2 ) { - // dotpath: win32/mac builds will be using newer versions of boost - // so we can treat this as though it is unix only - const fs::path dot_path("."); - const fs::path dot_dot_path(".."); +#if defined (__WIN32__) || defined(__APPLE__) +#error you should be using a newer version of boost on win/mac +#endif + // based on the code in boost fs::path result; - if (p=="") + if (p=="") p=p2; + std::string result_s; + std::vector resultv, pieces; + std::vector::iterator pi; + std::string tmps = boosty::stringy( p ); + boost::split( pieces, tmps, boost::is_any_of("/") ); + for ( pi = pieces.begin(); pi != pieces.end(); ++pi ) + { + if (*pi == "..") + resultv.erase( resultv.end() ); + else + resultv.push_back( *pi ); + } + for ( pi = resultv.begin(); pi != resultv.end(); ++pi ) { - p=p2; + if ((*pi).length()>0) result_s = result_s + "/" + *pi; } - for (fs::path::iterator itr = p.begin(); itr != p.end(); itr++) + result = fs::path( result_s ); + if (fs::is_symlink(result)) { - if (*itr == dot_path) continue; - if (*itr == dot_dot_path) - { - result.remove_filename(); - continue; - } - result /= *itr; - if (fs::is_symlink(result)) - { - PRINT("WARNING: canonical() wrapper can't do symlinks. rebuild openscad with boost >=1.48"); - PRINT("WARNING: or don't use symbolic links"); - } + PRINT("WARNING: canonical() wrapper can't do symlinks. rebuild openscad with boost >=1.48"); + PRINT("WARNING: or don't use symbolic links"); } return result; } diff --git a/src/dxftess-glu.cc b/src/dxftess-glu.cc index 941dbed..3f87729 100644 --- a/src/dxftess-glu.cc +++ b/src/dxftess-glu.cc @@ -185,6 +185,17 @@ static bool point_on_line(double *p1, double *p2, double *p3) return true; } +typedef std::pair pair_ii; +inline void do_emplace( boost::unordered_multimap &tri_by_atan2, int ai, const pair_ii &indexes) +{ +#if BOOST_VERSION >= 104800 + tri_by_atan2.emplace(ai, indexes); +#else + std::pair< int, pair_ii > tmp( ai, indexes ); + tri_by_atan2.insert( tmp ); +#endif +} + /*! up: true if the polygon is facing in the normal direction (i.e. normal = [0,0,1]) rot: CLOCKWISE rotation around positive Z axis @@ -280,7 +291,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian for (int j = 0; j < 3; j++) { int ai = (int)round(atan2(fabs(tess_tri[i].p[(j+1)%3][0] - tess_tri[i].p[j][0]), fabs(tess_tri[i].p[(j+1)%3][1] - tess_tri[i].p[j][1])) / 0.001); - tri_by_atan2.emplace(ai, std::pair(i, j)); + do_emplace( tri_by_atan2, ai, std::pair(i, j) ); } while (added_triangles) { @@ -321,13 +332,13 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian for (int m = 0; m < 2; m++) { int ai = (int)round(atan2(fabs(tess_tri.back().p[(m+1)%3][0] - tess_tri.back().p[m][0]), fabs(tess_tri.back().p[(m+1)%3][1] - tess_tri.back().p[m][1])) / 0.001 ); - tri_by_atan2.emplace(ai, std::pair(tess_tri.size()-1, m)); + do_emplace(tri_by_atan2, ai, std::pair(tess_tri.size()-1, m)); } tess_tri[i].p[(k+1)%3] = tess_tri[j].p[l]; for (int m = 0; m < 2; m++) { int ai = (int)round(atan2(fabs(tess_tri[i].p[(m+1)%3][0] - tess_tri[i].p[m][0]), fabs(tess_tri[i].p[(m+1)%3][1] - tess_tri[i].p[m][1])) / 0.001 ); - tri_by_atan2.emplace(ai, std::pair(i, m)); + do_emplace(tri_by_atan2, ai, std::pair(i, m)); } added_triangles = true; } -- cgit v0.10.1 From 56bf724ab40facb4b26388baf8facf5bf5202cda Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 28 Mar 2013 12:10:43 -0400 Subject: Print warning in import() if OFF file is not found diff --git a/src/import.cc b/src/import.cc index 32d4fed..e693401 100644 --- a/src/import.cc +++ b/src/import.cc @@ -251,10 +251,15 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const #ifdef ENABLE_CGAL CGAL_Polyhedron poly; std::ifstream file(this->filename.c_str(), std::ios::in | std::ios::binary); - file >> poly; - file.close(); - - p = createPolySetFromPolyhedron(poly); + if (!file.good()) { + PRINTB("WARNING: Can't open import file '%s'.", this->filename); + } + else { + file >> poly; + file.close(); + + p = createPolySetFromPolyhedron(poly); + } #else PRINT("WARNING: OFF import requires CGAL."); #endif -- cgit v0.10.1 From c7f83aa3e35baf8a517c40a367ec247a7061b225 Mon Sep 17 00:00:00 2001 From: don bright Date: Tue, 2 Apr 2013 20:51:20 -0700 Subject: remove redundant code, root_node and absolute_root_node diff --git a/src/openscad.cc b/src/openscad.cc index f7cc48e..878c207 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -357,11 +357,10 @@ int main(int argc, char **argv) AbstractNode::resetIndexCounter(); absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); - root_node = root_module->evaluate(&root_ctx, &root_inst); // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) - root_node = absolute_root_node; + root_node = absolute_root_node; tree.setRoot(root_node); -- cgit v0.10.1 From 7b5cd11cdc923921cfae5b40fca5850fbd92de40 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 5 Apr 2013 00:11:48 -0400 Subject: bugfix: If the test driver returned an error, it was ignored by the test script diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py index eb01abd..470be1e 100755 --- a/tests/test_cmdline_tool.py +++ b/tests/test_cmdline_tool.py @@ -256,5 +256,6 @@ if __name__ == '__main__': verification = verify_test(options.testname, options.cmd) resultfile = run_test(options.testname, options.cmd, args[1:]) - + if not resultfile: exit(1) + if not verification or not compare_with_expected(resultfile): exit(1) -- cgit v0.10.1 From 1b8b7aa5faa167af2687970f195e19439dab5a30 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 5 Apr 2013 01:30:09 -0400 Subject: I think this should fix issue #217 diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 1ed37fa..53bc480 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -49,6 +49,9 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector &argnam double yorigin = 0; double scale = 1; + // FIXME: We don't lookup the file relative to where this function was instantiated + // since the path is only available for ModuleInstantiations, not function expressions. + // See isse #217 for (size_t i = 0; i < argnames.size() && i < args.size(); i++) { if (argnames[i] == "file") filename = ctx->getAbsolutePath(args[i].toString()); @@ -63,9 +66,16 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector &argnam } std::stringstream keystream; + fs::path filepath(filename); + uintmax_t filesize = -1; + time_t lastwritetime = -1; + if (fs::exists(filepath) && fs::is_regular_file(filepath)) { + filesize = fs::file_size(filepath); + lastwritetime = fs::last_write_time(filepath); + } keystream << filename << "|" << layername << "|" << name << "|" << xorigin - << "|" << yorigin <<"|" << scale << "|" << fs::last_write_time(filename) - << "|" << fs::file_size(filename); + << "|" << yorigin <<"|" << scale << "|" << lastwritetime + << "|" << filesize; std::string key = keystream.str(); if (dxf_dim_cache.find(key) != dxf_dim_cache.end()) return dxf_dim_cache.find(key)->second; @@ -133,6 +143,9 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector &argn double yorigin = 0; double scale = 1; + // FIXME: We don't lookup the file relative to where this function was instantiated + // since the path is only available for ModuleInstantiations, not function expressions. + // See isse #217 for (size_t i = 0; i < argnames.size() && i < args.size(); i++) { if (argnames[i] == "file") filename = ctx->getAbsolutePath(args[i].toString()); diff --git a/src/import.cc b/src/import.cc index 32d4fed..bbf5a6e 100644 --- a/src/import.cc +++ b/src/import.cc @@ -80,7 +80,7 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati c.args(argnames, argexpr, inst_argnames, inst->argvalues); Value v = c.lookup_variable("file"); - std::string filename = c.getAbsolutePath(v.isUndefined() ? "" : v.toString()); + std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { std::string extraw = boosty::extension_str( fs::path(filename) ); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 43db907..ff9682e 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -75,7 +75,7 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst if (!file.isUndefined()) { PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); - node->filename = c.getAbsolutePath(file.toString()); + node->filename = inst->getAbsolutePath(file.toString()); } // if height not given, and first argument is a number, diff --git a/src/module.cc b/src/module.cc index e6dcb57..322085b 100644 --- a/src/module.cc +++ b/src/module.cc @@ -32,6 +32,9 @@ #include "function.h" #include "printutils.h" +#include +namespace fs = boost::filesystem; +#include "boosty.h" #include #include #include @@ -67,6 +70,19 @@ IfElseModuleInstantiation::~IfElseModuleInstantiation() BOOST_FOREACH (ModuleInstantiation *v, else_children) delete v; } +/*! + Returns the absolute path to the given filename, unless it's empty. + */ +std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const +{ + if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { + return boosty::absolute(fs::path(this->modpath) / filename).string(); + } + else { + return filename; + } +} + std::string ModuleInstantiation::dump(const std::string &indent) const { std::stringstream dump; @@ -152,15 +168,15 @@ AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *in c.functions_p = &functions; c.modules_p = &modules; - + if (!usedlibs.empty()) c.usedlibs_p = &usedlibs; else c.usedlibs_p = NULL; - + BOOST_FOREACH(const std::string &var, assignments_var) { c.set_variable(var, assignments.at(var)->evaluate(&c)); - } + } AbstractNode *node = new AbstractNode(inst); for (size_t i = 0; i < children.size(); i++) { diff --git a/src/module.h b/src/module.h index cc82f81..1f9e303 100644 --- a/src/module.h +++ b/src/module.h @@ -10,7 +10,7 @@ class ModuleInstantiation { public: - ModuleInstantiation(const std::string &name = "") + ModuleInstantiation(const std::string &name = "") : ctx(NULL), tag_root(false), tag_highlight(false), tag_background(false), modname(name) { } virtual ~ModuleInstantiation(); @@ -19,6 +19,10 @@ public: class AbstractNode *evaluate(const class Context *ctx) const; std::vector evaluateChildren(const Context *ctx = NULL) const; + void setPath(const std::string &path) { this->modpath = path; } + const std::string &path() const { return this->modpath; } + std::string getAbsolutePath(const std::string &filename) const; + const std::string &name() const { return this->modname; } bool isBackground() const { return this->tag_background; } bool isHighlight() const { return this->tag_highlight; } @@ -35,6 +39,7 @@ public: bool tag_background; protected: std::string modname; + std::string modpath; friend class Module; }; @@ -61,6 +66,7 @@ class Module : public AbstractModule public: Module() : is_handling_dependencies(false) { } virtual ~Module(); + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; virtual std::string dump(const std::string &indent, const std::string &name) const; diff --git a/src/parser.y b/src/parser.y index 536f4ef..70aebba 100644 --- a/src/parser.y +++ b/src/parser.y @@ -58,6 +58,12 @@ int lexerlex(void); std::vector module_stack; Module *currmodule; +extern void lexerdestroy(); +extern FILE *lexerin; +extern const char *parser_input_buffer; +const char *parser_input_buffer; +std::string parser_source_path; + class ArgContainer { public: std::string argname; @@ -77,6 +83,7 @@ public: class Value *value; class Expression *expr; class ModuleInstantiation *inst; + std::vector *instvec; class IfElseModuleInstantiation *ifelse; class ArgContainer *arg; class ArgsContainer *args; @@ -117,8 +124,8 @@ public: %type module_instantiation %type if_statement %type ifelse_statement -%type children_instantiation -%type module_instantiation_list +%type children_instantiation +%type module_instantiation_list %type single_module_instantiation %type arguments_call @@ -182,9 +189,9 @@ statement: /* Will return a dummy parent node with zero or more children */ children_instantiation: module_instantiation { - $$ = new ModuleInstantiation(); + $$ = new std::vector; if ($1) { - $$->children.push_back($1); + $$->push_back($1); } } | '{' module_instantiation_list '}' { @@ -196,14 +203,14 @@ if_statement: $$ = new IfElseModuleInstantiation(); $$->argnames.push_back(""); $$->argexpr.push_back($3); + $$->setPath(parser_source_path); if ($$) { - $$->children = $5->children; + $$->children = *$5; } else { - for (size_t i = 0; i < $5->children.size(); i++) - delete $5->children[i]; + for (size_t i = 0; i < $5->size(); i++) + delete (*$5)[i]; } - $5->children.clear(); delete $5; } ; @@ -214,12 +221,11 @@ ifelse_statement: if_statement TOK_ELSE children_instantiation { $$ = $1; if ($$) { - $$->else_children = $3->children; + $$->else_children = *$3; } else { - for (size_t i = 0; i < $3->children.size(); i++) - delete $3->children[i]; + for (size_t i = 0; i < $3->size(); i++) + delete (*$3)[i]; } - $3->children.clear(); delete $3; } ; @@ -246,12 +252,11 @@ module_instantiation: single_module_instantiation children_instantiation { $$ = $1; if ($$) { - $$->children = $2->children; + $$->children = *$2; } else { - for (size_t i = 0; i < $2->children.size(); i++) - delete $2->children[i]; + for (size_t i = 0; i < $2->size(); i++) + delete (*$2)[i]; } - $2->children.clear(); delete $2; } | ifelse_statement { @@ -260,12 +265,12 @@ module_instantiation: module_instantiation_list: /* empty */ { - $$ = new ModuleInstantiation(); + $$ = new std::vector; } | module_instantiation_list module_instantiation { $$ = $1; if ($$) { - if ($2) $$->children.push_back($2); + if ($2) $$->push_back($2); } else { delete $2; } @@ -276,6 +281,7 @@ single_module_instantiation: $$ = new ModuleInstantiation($1); $$->argnames = $3->argnames; $$->argexpr = $3->argexpr; + $$->setPath(parser_source_path); free($1); delete $3; } @@ -536,18 +542,12 @@ void yyerror (char const *s) currmodule = NULL; } -extern void lexerdestroy(); -extern FILE *lexerin; -extern const char *parser_input_buffer; -const char *parser_input_buffer; -std::string parser_source_path; - Module *parse(const char *text, const char *path, int debug) { lexerin = NULL; parser_error_pos = -1; parser_input_buffer = text; - parser_source_path = std::string(path); + parser_source_path = boosty::absolute(std::string(path)).string(); module_stack.clear(); Module *rootmodule = currmodule = new Module(); diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index dc8ea34..c4d9342 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -71,7 +71,7 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst if (!file.isUndefined()) { PRINT("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); - node->filename = c.getAbsolutePath(file.toString()); + node->filename = inst->getAbsolutePath(file.toString()); } node->layername = layer.isUndefined() ? "" : layer.toString(); diff --git a/src/surface.cc b/src/surface.cc index 4339ead..ca5031e 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -83,7 +83,7 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat c.args(argnames, argexpr, inst->argnames, inst->argvalues); Value fileval = c.lookup_variable("file"); - node->filename = c.getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); + node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); Value center = c.lookup_variable("center", true); if (center.type() == Value::BOOL) { diff --git a/testdata/scad/misc/localfiles-test.scad b/testdata/scad/misc/localfiles-test.scad new file mode 100644 index 0000000..31efe96 --- /dev/null +++ b/testdata/scad/misc/localfiles-test.scad @@ -0,0 +1,3 @@ +use + +localfiles_module(); diff --git a/testdata/scad/misc/localfiles_dir/localfile.dat b/testdata/scad/misc/localfiles_dir/localfile.dat new file mode 100644 index 0000000..32eba08 --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfile.dat @@ -0,0 +1,2 @@ +0 1 +2 3 diff --git a/testdata/scad/misc/localfiles_dir/localfile.dxf b/testdata/scad/misc/localfiles_dir/localfile.dxf new file mode 100644 index 0000000..933e263 --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfile.dxf @@ -0,0 +1,1968 @@ +999 +dxflib 2.2.0.0 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1015 + 9 +$HANDSEED + 5 +FFFF + 9 +$DIMASZ + 40 +2.5 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMGAP + 40 +0.625 + 9 +$PLIMMAX + 10 +210.0 + 20 +297.0 + 9 +$INSUNITS + 70 +4 + 9 +$DIMSTYLE + 2 +Standard + 9 +$CLAYER + 8 +0 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMTXT + 40 +2.5 + 9 +$CLAYER + 8 +0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +100 +AcDbSymbolTable + 70 +1 + 0 +VPORT + 5 +30 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 +0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +286.3055555555554861 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +297.0 + 41 +1.92798353909465 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 +0 + 72 +100 + 73 +1 + 74 +3 + 75 +1 + 76 +1 + 77 +0 + 78 +0 +281 +0 + 65 +1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 +0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +100 +AcDbSymbolTable + 70 +21 + 0 +LTYPE + 5 +14 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +15 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 +0 + 3 + + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +16 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 +0 + 3 +Solid line + 72 +65 + 73 +0 + 40 +0.0 + 0 +LTYPE + 5 +31 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 +0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +6.3499999999999996 + 49 +0.0 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +32 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 +0 + 3 +Dot (.5x) ..................................... + 72 +65 + 73 +2 + 40 +3.1749999999999998 + 49 +0.0 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +33 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 +0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 +65 + 73 +2 + 40 +12.6999999999999993 + 49 +0.0 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +LTYPE + 5 +34 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 +0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 +65 + 73 +2 + 40 +19.0500000000000007 + 49 +12.6999999999999993 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +35 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 +0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 +65 + 73 +2 + 40 +9.5250000000000004 + 49 +6.3499999999999996 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +36 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 +0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 +65 + 73 +2 + 40 +38.1000000000000014 + 49 +25.3999999999999986 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +LTYPE + 5 +37 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 +0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 +65 + 73 +4 + 40 +25.3999999999999986 + 49 +12.6999999999999993 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +38 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 +0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 +65 + 73 +4 + 40 +12.6999999999999993 + 49 +6.3499999999999996 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +39 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 +0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 +65 + 73 +4 + 40 +50.7999999999999972 + 49 +25.3999999999999986 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +LTYPE + 5 +3A +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 +0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 +65 + 73 +6 + 40 +31.75 + 49 +12.6999999999999993 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +3B +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 +0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 +65 + 73 +6 + 40 +15.875 + 49 +6.3499999999999996 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +3C +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 +0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 +65 + 73 +6 + 40 +63.5 + 49 +25.3999999999999986 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +LTYPE + 5 +3D +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 +0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 +65 + 73 +4 + 40 +50.7999999999999972 + 49 +31.75 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +6.3499999999999996 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +3E +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 +0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 +65 + 73 +4 + 40 +28.5749999999999993 + 49 +19.0500000000000007 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +3.1749999999999998 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +3F +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 +0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 +65 + 73 +4 + 40 +101.5999999999999943 + 49 +63.5 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +12.6999999999999993 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +LTYPE + 5 +40 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 +0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 +65 + 73 +6 + 40 +44.4500000000000028 + 49 +12.6999999999999993 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +12.6999999999999993 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-6.3499999999999996 + 74 +0 + 0 +LTYPE + 5 +41 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 +0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 +65 + 73 +6 + 40 +22.2250000000000014 + 49 +6.3499999999999996 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +6.3499999999999996 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-3.1749999999999998 + 74 +0 + 0 +LTYPE + 5 +42 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 +0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 +65 + 73 +6 + 40 +88.9000000000000057 + 49 +25.3999999999999986 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +25.3999999999999986 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 49 +0.0 + 74 +0 + 49 +-12.6999999999999993 + 74 +0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +1 + 0 +LAYER + 5 +10 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 62 +7 +420 +0 + 6 +CONTINUOUS +370 +25 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +100 +AcDbSymbolTable + 70 +1 + 0 +STYLE + 5 +11 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 +0 + 40 +0.0 + 41 +0.75 + 50 +0.0 + 71 +0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +100 +AcDbSymbolTable + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +100 +AcDbSymbolTable + 70 +1 + 0 +APPID + 5 +12 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 +0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +100 +AcDbSymbolTable + 70 +1 +100 +AcDbDimStyleTable + 71 +0 + 0 +DIMSTYLE +105 +27 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 70 +0 + 73 +0 + 74 +0 + 77 +1 + 78 +8 +140 +2.5 +141 +2.5 +143 +0.03937007874016 +147 +0.625 +171 +3 +172 +1 +271 +2 +272 +2 +274 +3 +278 +44 +283 +0 +284 +8 +340 +11 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +100 +AcDbSymbolTable + 70 +1 + 0 +BLOCK_RECORD + 5 +1F +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +22 + 0 +BLOCK_RECORD + 5 +1B +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 0 +BLOCK_RECORD + 5 +23 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +26 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +100 +AcDbEntity + 67 +1 + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +100 +AcDbEntity + 67 +1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +24 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 +0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +ENDBLK + 5 +25 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +43 +100 +AcDbEntity +100 +AcDbLine + 8 +0 + 62 +256 +370 +-1 + 6 +ByLayer + 10 +10.0 + 20 +100.0 + 30 +0.0 + 11 +210.0 + 21 +100.0 + 31 +0.0 + 0 +LINE + 5 +44 +100 +AcDbEntity +100 +AcDbLine + 8 +0 + 62 +256 +370 +-1 + 6 +ByLayer + 10 +210.0 + 20 +100.0 + 30 +0.0 + 11 +210.0 + 21 +-100.0 + 31 +0.0 + 0 +LINE + 5 +45 +100 +AcDbEntity +100 +AcDbLine + 8 +0 + 62 +256 +370 +-1 + 6 +ByLayer + 10 +210.0 + 20 +-100.0 + 30 +0.0 + 11 +10.0 + 21 +-100.0 + 31 +0.0 + 0 +LINE + 5 +46 +100 +AcDbEntity +100 +AcDbLine + 8 +0 + 62 +256 +370 +-1 + 6 +ByLayer + 10 +10.0 + 20 +-100.0 + 30 +0.0 + 11 +10.0 + 21 +100.0 + 31 +0.0 + 0 +DIMENSION + 5 +47 +100 +AcDbEntity + 8 +0 + 62 +256 +370 +-1 + 6 +ByLayer +100 +AcDbDimension + 10 +10.0000000000000018 + 20 +150.0 + 30 +0.0 + 11 +110.0 + 21 +151.875 + 31 +0.0 + 70 +1 + 71 +5 + 72 +1 + 41 +1.0 + 42 +0.0 + 1 +localfile + 3 +Standard +100 +AcDbAlignedDimension + 13 +10.0 + 23 +130.0 + 33 +0.0 + 14 +210.0 + 24 +130.0 + 34 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +100 +AcDbDictionary +280 +0 +281 +1 + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACAD_PLOTSTYLENAME +350 +E + 3 +AcDbVariableDictionary +350 +48 + 0 +DICTIONARY + 5 +D +100 +AcDbDictionary +280 +0 +281 +1 + 0 +ACDBDICTIONARYWDFLT + 5 +E +100 +AcDbDictionary +281 +1 + 3 +Normal +350 +F +100 +AcDbDictionaryWithDefault +340 +F + 0 +ACDBPLACEHOLDER + 5 +F + 0 +DICTIONARY + 5 +17 +100 +AcDbDictionary +280 +0 +281 +1 + 3 +Standard +350 +18 + 0 +MLINESTYLE + 5 +18 +100 +AcDbMlineStyle + 2 +STANDARD + 70 +0 + 3 + + 62 +256 + 51 +90.0 + 52 +90.0 + 71 +2 + 49 +0.5 + 62 +256 + 6 +BYLAYER + 49 +-0.5 + 62 +256 + 6 +BYLAYER + 0 +DICTIONARY + 5 +19 +100 +AcDbDictionary +280 +0 +281 +1 + 0 +DICTIONARY + 5 +1A +100 +AcDbDictionary +281 +1 + 3 +Layout1 +350 +1E + 3 +Layout2 +350 +26 + 3 +Model +350 +22 + 0 +LAYOUT + 5 +1E +100 +AcDbPlotSettings + 1 + + 2 +C:\Program Files\AutoCAD 2002\plotters\DWF ePlot (optimized for plotting).pc3 + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +688 + 72 +0 + 73 +0 + 74 +5 + 7 + + 75 +16 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 +1 + 71 +1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +100000000000000000000.0 + 24 +100000000000000000000.0 + 34 +100000000000000000000.0 + 15 +-100000000000000000000.0 + 25 +-100000000000000000000.0 + 35 +-100000000000000000000.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +0 +330 +1B + 0 +LAYOUT + 5 +22 +100 +AcDbPlotSettings + 1 + + 2 +C:\Program Files\AutoCAD 2002\plotters\DWF ePlot (optimized for plotting).pc3 + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +1712 + 72 +0 + 73 +0 + 74 +0 + 7 + + 75 +0 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 +1 + 71 +0 + 10 +0.0 + 20 +0.0 + 11 +12.0 + 21 +9.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +0 +330 +1F + 0 +LAYOUT + 5 +26 +100 +AcDbPlotSettings + 1 + + 2 +C:\Program Files\AutoCAD 2002\plotters\DWF ePlot (optimized for plotting).pc3 + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 +688 + 72 +0 + 73 +0 + 74 +5 + 7 + + 75 +16 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout2 + 70 +1 + 71 +2 + 10 +0.0 + 20 +0.0 + 11 +12.0 + 21 +9.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 +0 +330 +23 + 0 +DICTIONARY + 5 +48 +100 +AcDbDictionary +281 +1 + 3 +DIMASSOC +350 +4A + 3 +HIDETEXT +350 +49 + 0 +DICTIONARYVAR + 5 +49 +100 +DictionaryVariables +280 +0 + 1 +2 + 0 +DICTIONARYVAR + 5 +4A +100 +DictionaryVariables +280 +0 + 1 +1 + 0 +ENDSEC + 0 +EOF diff --git a/testdata/scad/misc/localfiles_dir/localfiles_module.scad b/testdata/scad/misc/localfiles_dir/localfiles_module.scad new file mode 100644 index 0000000..b98a49b --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfiles_module.scad @@ -0,0 +1,10 @@ +module localfiles_module() +{ + linear_extrude(h=100) import("localfile.dxf"); + translate([-250,0,0]) linear_extrude(file="localfile.dxf"); + translate([0,350,0]) rotate_extrude(file="localfile.dxf"); + translate([250,0,0]) scale([200,200,50]) surface("localfile.dat"); + + // This is not supported: + // echo(dxf_dim(file="localfile.dxf", name="localfile")); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5eecaae..a0d8f6b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -769,12 +769,15 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} list(APPEND DUMPTEST_FILES ${MINIMAL_FILES} ${FEATURES_FILES} ${EXAMPLE_FILES}) list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) list(APPEND CGALPNGTEST_FILES ${FEATURES_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_FILES}) list(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/transform-nan-inf-tests.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/transform-nan-inf-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) + list(APPEND OPENCSGTEST_FILES ${CGALPNGTEST_FILES}) list(APPEND OPENCSGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/bbox-transform-bug.scad) list(APPEND OPENCSGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/intersection-prune-test.scad) diff --git a/tests/dumptest.cc b/tests/dumptest.cc index b75a2e2..3627608 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -118,7 +118,6 @@ int main(int argc, char **argv) exit(1); } - fs::current_path(original_path); std::ofstream outfile; outfile.open(outfilename); outfile << dumpstdstr << "\n"; @@ -127,21 +126,22 @@ int main(int argc, char **argv) delete root_node; delete root_module; + fs::current_path(original_path); root_module = parsefile(outfilename); if (!root_module) { fprintf(stderr, "Error: Unable to read back dumped file\n"); exit(1); } - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } - AbstractNode::resetIndexCounter(); root_node = root_module->evaluate(&root_ctx, &root_inst); tree.setRoot(root_node); + if (fs::path(outfilename).has_parent_path()) { + fs::current_path(fs::path(outfilename).parent_path()); + } + string readbackstr = dumptree(tree, *root_node); if (dumpstdstr != readbackstr) { fprintf(stderr, "Error: Readback is different from original dump:\n"); diff --git a/tests/regression/cgalpngtest/localfiles-test-expected.png b/tests/regression/cgalpngtest/localfiles-test-expected.png new file mode 100644 index 0000000..3ad3d96 Binary files /dev/null and b/tests/regression/cgalpngtest/localfiles-test-expected.png differ diff --git a/tests/regression/dumptest/localfiles-test-expected.txt b/tests/regression/dumptest/localfiles-test-expected.txt new file mode 100644 index 0000000..acdf7e7 --- /dev/null +++ b/tests/regression/dumptest/localfiles-test-expected.txt @@ -0,0 +1,17 @@ + group() { + linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + import(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, -250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { + rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { + surface(file = "localfiles_dir/localfile.dat", center = false); + } + } + } + diff --git a/tests/regression/opencsgtest/localfiles-test-expected.png b/tests/regression/opencsgtest/localfiles-test-expected.png new file mode 100644 index 0000000..7bc7909 Binary files /dev/null and b/tests/regression/opencsgtest/localfiles-test-expected.png differ diff --git a/tests/regression/throwntogethertest/localfiles-test-expected.png b/tests/regression/throwntogethertest/localfiles-test-expected.png new file mode 100644 index 0000000..7bc7909 Binary files /dev/null and b/tests/regression/throwntogethertest/localfiles-test-expected.png differ -- cgit v0.10.1 From 3307deee9361883a5297fbcac7f5a1cb428ed40c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Apr 2013 22:41:28 -0400 Subject: Added test for inner module variables diff --git a/testdata/scad/features/modulevariables.scad b/testdata/scad/features/modulevariables.scad new file mode 100644 index 0000000..fc7a183 --- /dev/null +++ b/testdata/scad/features/modulevariables.scad @@ -0,0 +1,7 @@ +module mymodule(modparam) { + inner_variable = 23; + inner_variable2 = modparam * 2; + cylinder(r1=inner_variable, r2=inner_variable2, h=10); +} + +mymodule(5); diff --git a/tests/regression/cgalpngtest/modulevariables-expected.png b/tests/regression/cgalpngtest/modulevariables-expected.png new file mode 100644 index 0000000..0dc18e8 Binary files /dev/null and b/tests/regression/cgalpngtest/modulevariables-expected.png differ diff --git a/tests/regression/dumptest/modulevariables-expected.txt b/tests/regression/dumptest/modulevariables-expected.txt new file mode 100644 index 0000000..fed4bbc --- /dev/null +++ b/tests/regression/dumptest/modulevariables-expected.txt @@ -0,0 +1,4 @@ + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 10, r1 = 23, r2 = 10, center = false); + } + diff --git a/tests/regression/opencsgtest/modulevariables-expected.png b/tests/regression/opencsgtest/modulevariables-expected.png new file mode 100644 index 0000000..bf23265 Binary files /dev/null and b/tests/regression/opencsgtest/modulevariables-expected.png differ diff --git a/tests/regression/throwntogethertest/modulevariables-expected.png b/tests/regression/throwntogethertest/modulevariables-expected.png new file mode 100644 index 0000000..bf23265 Binary files /dev/null and b/tests/regression/throwntogethertest/modulevariables-expected.png differ -- cgit v0.10.1 From b16c24fb2888d932ec035fff27cb29b4ffbc256b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Apr 2013 00:26:04 -0400 Subject: diagram update diff --git a/doc/OpenSCAD-polygons.graffle b/doc/OpenSCAD-polygons.graffle index 758d575..63985dc 100644 Binary files a/doc/OpenSCAD-polygons.graffle and b/doc/OpenSCAD-polygons.graffle differ -- cgit v0.10.1 From a37813a8999571f4b9235f33fdc7c22bcbe5fd17 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Apr 2013 00:28:16 -0400 Subject: Refactored context handling into using separate Module contexts and Eval contexts. This allows for recursive module calls, and cascading children. I believe this fixes issue #116 diff --git a/openscad.pro b/openscad.pro index d9442d4..7496e18 100644 --- a/openscad.pro +++ b/openscad.pro @@ -203,6 +203,8 @@ HEADERS += src/version_check.h \ src/AboutDialog.h \ src/builtin.h \ src/context.h \ + src/modcontext.h \ + src/evalcontext.h \ src/csgterm.h \ src/csgtermnormalizer.h \ src/dxfdata.h \ @@ -271,6 +273,8 @@ SOURCES += src/version_check.cc \ src/module.cc \ src/node.cc \ src/context.cc \ + src/modcontext.cc \ + src/evalcontext.cc \ src/csgterm.cc \ src/csgtermnormalizer.cc \ src/polyset.cc \ diff --git a/src/MainWindow.h b/src/MainWindow.h index 8745b8b..65deb15 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -4,7 +4,7 @@ #include #include "ui_MainWindow.h" #include "openscad.h" -#include "context.h" +#include "modcontext.h" #include "module.h" #include "Tree.h" #include "memory.h" @@ -29,7 +29,7 @@ public: QTimer *autoReloadTimer; std::string autoReloadId; - Context root_ctx; + ModuleContext root_ctx; Module *root_module; // Result of parsing ModuleInstantiation root_inst; // Top level instance AbstractNode *absolute_root_node; // Result of tree evaluation diff --git a/src/builtin.cc b/src/builtin.cc index 6eb32b6..bdd2d3b 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -1,6 +1,7 @@ #include "builtin.h" #include "function.h" #include "module.h" +#include "expression.h" #include Builtins *Builtins::instance(bool erase) @@ -15,12 +16,12 @@ Builtins *Builtins::instance(bool erase) void Builtins::init(const char *name, class AbstractModule *module) { - Builtins::instance()->builtinmodules[name] = module; + Builtins::instance()->rootmodule.modules[name] = module; } void Builtins::init(const char *name, class AbstractFunction *function) { - Builtins::instance()->builtinfunctions[name] = function; + Builtins::instance()->rootmodule.functions[name] = function; } extern void register_builtin_functions(); @@ -77,10 +78,28 @@ std::string Builtins::isDeprecated(const std::string &name) return std::string(); } +Builtins::Builtins() +{ + this->rootmodule.assignments_var.push_back("$fn"); + this->rootmodule.assignments["$fn"] = new Expression(Value(0.0)); + this->rootmodule.assignments_var.push_back("$fs"); + this->rootmodule.assignments["$fs"] = new Expression(Value(2.0)); + this->rootmodule.assignments_var.push_back("$fa"); + this->rootmodule.assignments["$fa"] = new Expression(Value(12.0)); + this->rootmodule.assignments_var.push_back("$t"); + this->rootmodule.assignments["$t"] = new Expression(Value(0.0)); + + Value::VectorType zero3; + zero3.push_back(Value(0.0)); + zero3.push_back(Value(0.0)); + zero3.push_back(Value(0.0)); + Value zero3val(zero3); + this->rootmodule.assignments_var.push_back("$vpt"); + this->rootmodule.assignments["$vpt"] = new Expression(zero3val); + this->rootmodule.assignments_var.push_back("$vpr"); + this->rootmodule.assignments["$vpr"] = new Expression(zero3val); +} + Builtins::~Builtins() { - BOOST_FOREACH(FunctionContainer::value_type &f, this->builtinfunctions) delete f.second; - this->builtinfunctions.clear(); - BOOST_FOREACH(ModuleContainer::value_type &m, this->builtinmodules) delete m.second; - this->builtinmodules.clear(); } diff --git a/src/builtin.h b/src/builtin.h index bc096e5..564c951 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -3,6 +3,7 @@ #include #include +#include "module.h" class Builtins { @@ -19,16 +20,17 @@ public: const FunctionContainer &functions() { return this->builtinfunctions; } const ModuleContainer &modules() { return this->builtinmodules; } + const Module &getRootModule() { return this->rootmodule; } + private: - Builtins() { } + Builtins(); ~Builtins(); + Module rootmodule; FunctionContainer builtinfunctions; ModuleContainer builtinmodules; boost::unordered_map deprecations; }; -extern void register_builtin(class Context &ctx); - #endif diff --git a/src/cgaladv.cc b/src/cgaladv.cc index a4cb5ec..8c98ae6 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -26,7 +26,7 @@ #include "cgaladvnode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include "PolySetEvaluator.h" #include @@ -39,10 +39,10 @@ class CgaladvModule : public AbstractModule public: cgaladv_type_e type; CgaladvModule(cgaladv_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { CgaladvNode *node = new CgaladvNode(inst, type); @@ -62,7 +62,7 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat argnames += "newsize", "auto"; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); Value convexity, path, subdiv_type, level; @@ -111,7 +111,7 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat if (node->level <= 1) node->level = 1; - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; diff --git a/src/color.cc b/src/color.cc index acca652..4e9c55d 100644 --- a/src/color.cc +++ b/src/color.cc @@ -26,7 +26,7 @@ #include "colornode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include "printutils.h" #include @@ -40,14 +40,14 @@ class ColorModule : public AbstractModule { public: ColorModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; private: static boost::unordered_map colormap; }; #include "colormap.h" -AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ColorNode *node = new ColorNode(inst); @@ -60,7 +60,7 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio argnames += "c", "alpha"; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); Value v = c.lookup_variable("c"); if (v.type() == Value::VECTOR) { @@ -88,7 +88,7 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio node->color[3] = alpha.toDouble(); } - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; diff --git a/src/context.cc b/src/context.cc index 97ea5b9..bc54b88 100644 --- a/src/context.cc +++ b/src/context.cc @@ -25,6 +25,7 @@ */ #include "context.h" +#include "evalcontext.h" #include "expression.h" #include "function.h" #include "module.h" @@ -40,26 +41,12 @@ std::vector Context::ctx_stack; /*! Initializes this context. Optionally initializes a context for an external library */ -Context::Context(const Context *parent, const Module *library) - : parent(parent), inst_p(NULL) +Context::Context(const Context *parent) + : parent(parent) { if (parent) recursioncount = parent->recursioncount; ctx_stack.push_back(this); if (parent) document_path = parent->document_path; - if (library) { - // FIXME: Don't access module members directly - this->functions_p = &library->functions; - this->modules_p = &library->modules; - this->usedlibs_p = &library->usedlibs; - BOOST_FOREACH(const std::string &var, library->assignments_var) { - this->set_variable(var, library->assignments.at(var)->evaluate(this)); - } - } - else { - functions_p = NULL; - modules_p = NULL; - usedlibs_p = NULL; - } } Context::~Context() @@ -68,25 +55,28 @@ Context::~Context() } /*! - Initialize context from argument lists (function call/module instantiation) - */ -void Context::args(const std::vector &argnames, - const std::vector &argexpr, - const std::vector &call_argnames, - const std::vector &call_argvalues) + Initialize context from a module argument list and a evaluation context + which may pass variables which will be preferred over default values. +*/ +void Context::setVariables(const std::vector &argnames, + const std::vector &argexpr, + const EvalContext *evalctx) { for (size_t i=0; ievaluate(this->parent) : Value()); } - size_t posarg = 0; - for (size_t i=0; ieval_arguments.size(); i++) { + const std::string &name = evalctx->eval_arguments[i].first; + const Value &val = evalctx->eval_arguments[i].second; + if (name.empty()) { + if (posarg < argnames.size()) this->set_variable(argnames[posarg++], val); + } else { + this->set_variable(name, val); + } } } } @@ -141,50 +131,21 @@ private: const std::string &name; }; -Value Context::evaluate_function(const std::string &name, - const std::vector &argnames, - const std::vector &argvalues) const +Value Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const { RecursionGuard g(*this, name); if (g.recursion_detected()) { PRINTB("Recursion detected calling function '%s'", name); return Value(); } - if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) - return this->functions_p->find(name)->second->evaluate(this, argnames, argvalues); - if (this->usedlibs_p) { - BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { - if (m.second->functions.find(name) != m.second->functions.end()) { - Context ctx(this->parent, m.second); - return m.second->functions[name]->evaluate(&ctx, argnames, argvalues); - } - } - } - if (this->parent) return this->parent->evaluate_function(name, argnames, argvalues); + if (this->parent) return this->parent->evaluate_function(name, evalctx); PRINTB("WARNING: Ignoring unknown function '%s'.", name); return Value(); } -AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst) const +AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const { - if (this->modules_p && this->modules_p->find(inst.name()) != this->modules_p->end()) { - AbstractModule *m = this->modules_p->find(inst.name())->second; - std::string replacement = Builtins::instance()->isDeprecated(inst.name()); - if (!replacement.empty()) { - PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement); - } - return m->evaluate(this, &inst); - } - if (this->usedlibs_p) { - BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { - assert(m.second); - if (m.second->modules.find(inst.name()) != m.second->modules.end()) { - Context ctx(this->parent, m.second); - return m.second->modules[inst.name()]->evaluate(&ctx, &inst); - } - } - } - if (this->parent) return this->parent->evaluate_module(inst); + if (this->parent) return this->parent->evaluate_module(inst, evalctx); PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name()); return NULL; } @@ -202,22 +163,34 @@ std::string Context::getAbsolutePath(const std::string &filename) const } } -void register_builtin(Context &ctx) +#ifdef DEBUG +void Context::dump(const AbstractModule *mod, const ModuleInstantiation *inst) { - ctx.functions_p = &Builtins::instance()->functions(); - ctx.modules_p = &Builtins::instance()->modules(); - ctx.set_variable("$fn", Value(0.0)); - ctx.set_variable("$fs", Value(2.0)); - ctx.set_variable("$fa", Value(12.0)); - ctx.set_variable("$t", Value(0.0)); - - Value::VectorType zero3; - zero3.push_back(Value(0.0)); - zero3.push_back(Value(0.0)); - zero3.push_back(Value(0.0)); - Value zero3val(zero3); - ctx.set_variable("$vpt", zero3val); - ctx.set_variable("$vpr", zero3val); + if (inst) + PRINTB("ModuleContext %p (%p) for %s inst (%p)", this % this->parent % inst->name() % inst); + else + PRINTB("Context: %p (%p)", this % this->parent); + PRINTB(" document path: %s", this->document_path); + if (mod) { + const Module *m = dynamic_cast(mod); + if (m) { + PRINT(" module args:"); + BOOST_FOREACH(const std::string &arg, m->argnames) { + PRINTB(" %s = %s", arg % variables[arg]); + } + } + } + typedef std::pair ValueMapType; + PRINT(" vars:"); + BOOST_FOREACH(const ValueMapType &v, constants) { + PRINTB(" %s = %s", v.first % v.second); + } + BOOST_FOREACH(const ValueMapType &v, variables) { + PRINTB(" %s = %s", v.first % v.second); + } + BOOST_FOREACH(const ValueMapType &v, config_variables) { + PRINTB(" %s = %s", v.first % v.second); + } - ctx.set_constant("PI",Value(M_PI)); } +#endif diff --git a/src/context.h b/src/context.h index eb9a175..5c75e48 100644 --- a/src/context.h +++ b/src/context.h @@ -9,44 +9,44 @@ class Context { public: - Context(const Context *parent = NULL, const class Module *library = NULL); - ~Context(); + Context(const Context *parent = NULL); + virtual ~Context(); - void args(const std::vector &argnames, - const std::vector &argexpr, - const std::vector &call_argnames, - const std::vector &call_argvalues); + virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const; + virtual class AbstractNode *evaluate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const; + + void setVariables(const std::vector &argnames, + const std::vector &argexpr, + const class EvalContext *evalctx = NULL); void set_variable(const std::string &name, const Value &value); void set_constant(const std::string &name, const Value &value); Value lookup_variable(const std::string &name, bool silent = false) const; - Value evaluate_function(const std::string &name, - const std::vector &argnames, - const std::vector &argvalues) const; - class AbstractNode *evaluate_module(const class ModuleInstantiation &inst) const; void setDocumentPath(const std::string &path) { this->document_path = path; } + const std::string &documentPath() const { return this->document_path; } std::string getAbsolutePath(const std::string &filename) const; public: const Context *parent; - const boost::unordered_map *functions_p; - const boost::unordered_map *modules_p; - typedef boost::unordered_map ModuleContainer; - const ModuleContainer *usedlibs_p; - const ModuleInstantiation *inst_p; static std::vector ctx_stack; mutable boost::unordered_map recursioncount; -private: +protected: typedef boost::unordered_map ValueMap; ValueMap constants; ValueMap variables; ValueMap config_variables; + std::string document_path; + +#ifdef DEBUG +public: + virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); +#endif }; #endif diff --git a/src/control.cc b/src/control.cc index 44847f5..9133f28 100644 --- a/src/control.cc +++ b/src/control.cc @@ -26,7 +26,8 @@ #include "module.h" #include "node.h" -#include "context.h" +#include "evalcontext.h" +#include "modcontext.h" #include "builtin.h" #include "printutils.h" #include @@ -45,18 +46,16 @@ class ControlModule : public AbstractModule public: control_type_e type; ControlModule(control_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, - const std::vector &call_argnames, - const std::vector &call_argvalues, - const Context *arg_context) + const Context *ctx, const EvalContext *evalctx) { - if (call_argnames.size() > l) { - const std::string &it_name = call_argnames[l]; - const Value &it_values = call_argvalues[l]; - Context c(arg_context); + if (evalctx->eval_arguments.size() > l) { + const std::string &it_name = evalctx->eval_arguments[l].first; + const Value &it_values = evalctx->eval_arguments[l].second; + Context c(ctx); if (it_values.type() == Value::RANGE) { Value::RangeType range = it_values.toRange(); if (range.end < range.begin) { @@ -67,55 +66,55 @@ void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, if (range.step > 0 && (range.begin-range.end)/range.step < 10000) { for (double i = range.begin; i <= range.end; i += range.step) { c.set_variable(it_name, Value(i)); - for_eval(node, inst, l+1, call_argnames, call_argvalues, &c); + for_eval(node, inst, l+1, &c, evalctx); } } } else if (it_values.type() == Value::VECTOR) { for (size_t i = 0; i < it_values.toVector().size(); i++) { c.set_variable(it_name, it_values.toVector()[i]); - for_eval(node, inst, l+1, call_argnames, call_argvalues, &c); + for_eval(node, inst, l+1, &c, evalctx); } } else if (it_values.type() != Value::UNDEFINED) { c.set_variable(it_name, it_values); - for_eval(node, inst, l+1, call_argnames, call_argvalues, &c); + for_eval(node, inst, l+1, &c, evalctx); } } else if (l > 0) { - std::vector evaluatednodes = inst.evaluateChildren(arg_context); + std::vector evaluatednodes = inst.evaluateChildren(ctx); node.children.insert(node.children.end(), evaluatednodes.begin(), evaluatednodes.end()); } } -AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation *inst) const +AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = NULL; if (type == CHILD) { size_t n = 0; - if (inst->argvalues.size() > 0) { + if (evalctx->eval_arguments.size() > 0) { double v; - if (inst->argvalues[0].getDouble(v)) { + if (evalctx->eval_arguments[0].second.getDouble(v)) { if (v < 0) return NULL; // Disallow negative child indices n = trunc(v); } } - for (int i = Context::ctx_stack.size()-1; i >= 0; i--) { - const Context *c = Context::ctx_stack[i]; - if (c->inst_p) { - if (n < c->inst_p->children.size()) { - node = c->inst_p->children[n]->evaluate(c->inst_p->ctx); - // FIXME: We'd like to inherit any tags from the ModuleInstantiation - // given as parameter to this method. However, the instantition which belongs - // to the returned node cannot be changed. This causes the test - // features/child-background.scad to fail. + + // Find the last custom module invocation, which will contain + // an eval context with the children of the module invokation + const Context *tmpc = evalctx; + while (tmpc->parent) { + const ModuleContext *filectx = dynamic_cast(tmpc->parent); + if (filectx) { + if (filectx->evalctx && n < filectx->evalctx->children.size()) { + node = filectx->evalctx->children[n]->evaluate_instance(filectx->evalctx); } return node; } - c = c->parent; + tmpc = tmpc->parent; } - return NULL; + return node; } if (type == INT_FOR) @@ -129,18 +128,18 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation msg << "ECHO: "; for (size_t i = 0; i < inst->argnames.size(); i++) { if (i > 0) msg << ", "; - if (!inst->argnames[i].empty()) msg << inst->argnames[i] << " = "; - msg << inst->argvalues[i]; + if (!evalctx->eval_arguments[i].first.empty()) msg << evalctx->eval_arguments[i].first << " = "; + msg << evalctx->eval_arguments[i].second; } PRINTB("%s", msg.str()); } if (type == ASSIGN) { - Context c(inst->ctx); - for (size_t i = 0; i < inst->argnames.size(); i++) { - if (!inst->argnames[i].empty()) - c.set_variable(inst->argnames[i], inst->argvalues[i]); + Context c(evalctx); + for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { + if (!evalctx->eval_arguments[i].first.empty()) + c.set_variable(evalctx->eval_arguments[i].first, evalctx->eval_arguments[i].second); } std::vector evaluatednodes = inst->evaluateChildren(&c); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); @@ -148,18 +147,18 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation if (type == FOR || type == INT_FOR) { - for_eval(*node, *inst, 0, inst->argnames, inst->argvalues, inst->ctx); + for_eval(*node, *inst, 0, evalctx, evalctx); } if (type == IF) { const IfElseModuleInstantiation *ifelse = dynamic_cast(inst); - if (ifelse->argvalues.size() > 0 && ifelse->argvalues[0].toBool()) { - std::vector evaluatednodes = ifelse->evaluateChildren(); + if (evalctx->eval_arguments.size() > 0 && evalctx->eval_arguments[0].second.toBool()) { + std::vector evaluatednodes = ifelse->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); } else { - std::vector evaluatednodes = ifelse->evaluateElseChildren(); + std::vector evaluatednodes = ifelse->evaluateElseChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); } } diff --git a/src/csgops.cc b/src/csgops.cc index 7524559..425b747 100644 --- a/src/csgops.cc +++ b/src/csgops.cc @@ -26,6 +26,7 @@ #include "csgnode.h" +#include "evalcontext.h" #include "module.h" #include "csgterm.h" #include "builtin.h" @@ -37,13 +38,13 @@ class CsgModule : public AbstractModule public: csg_type_e type; CsgModule(csg_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst) const +AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst, const EvalContext *evalctx) const { CsgNode *node = new CsgNode(inst, type); - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; } diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 53bc480..fbc24c4 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -30,7 +30,7 @@ #include "dxfdata.h" #include "builtin.h" #include "printutils.h" -#include "context.h" +#include "evalcontext.h" #include "mathc99.h" #include @@ -40,7 +40,7 @@ boost::unordered_map dxf_dim_cache; boost::unordered_map dxf_cross_cache; namespace fs = boost::filesystem; -Value builtin_dxf_dim(const Context *ctx, const std::vector &argnames, const std::vector &args) +Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) { std::string filename; std::string layername; @@ -51,18 +51,18 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector &argnam // FIXME: We don't lookup the file relative to where this function was instantiated // since the path is only available for ModuleInstantiations, not function expressions. - // See isse #217 - for (size_t i = 0; i < argnames.size() && i < args.size(); i++) { - if (argnames[i] == "file") - filename = ctx->getAbsolutePath(args[i].toString()); - if (argnames[i] == "layer") - layername = args[i].toString(); - if (argnames[i] == "origin") - args[i].getVec2(xorigin, yorigin); - if (argnames[i] == "scale") - args[i].getDouble(scale); - if (argnames[i] == "name") - name = args[i].toString(); + // See issue #217 + for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { + if (evalctx->eval_arguments[i].first == "file") + filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString()); + if (evalctx->eval_arguments[i].first == "layer") + layername = evalctx->eval_arguments[i].second.toString(); + if (evalctx->eval_arguments[i].first == "origin") + evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin); + if (evalctx->eval_arguments[i].first == "scale") + evalctx->eval_arguments[i].second.getDouble(scale); + if (evalctx->eval_arguments[i].first == "name") + name = evalctx->eval_arguments[i].second.toString(); } std::stringstream keystream; @@ -135,7 +135,7 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector &argnam return Value(); } -Value builtin_dxf_cross(const Context *ctx, const std::vector &argnames, const std::vector &args) +Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) { std::string filename; std::string layername; @@ -146,15 +146,15 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector &argn // FIXME: We don't lookup the file relative to where this function was instantiated // since the path is only available for ModuleInstantiations, not function expressions. // See isse #217 - for (size_t i = 0; i < argnames.size() && i < args.size(); i++) { - if (argnames[i] == "file") - filename = ctx->getAbsolutePath(args[i].toString()); - if (argnames[i] == "layer") - layername = args[i].toString(); - if (argnames[i] == "origin") - args[i].getVec2(xorigin, yorigin); - if (argnames[i] == "scale") - args[i].getDouble(scale); + for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { + if (evalctx->eval_arguments[i].first == "file") + filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString()); + if (evalctx->eval_arguments[i].first == "layer") + layername = evalctx->eval_arguments[i].second.toString(); + if (evalctx->eval_arguments[i].first == "origin") + evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin); + if (evalctx->eval_arguments[i].first == "scale") + evalctx->eval_arguments[i].second.getDouble(scale); } std::stringstream keystream; diff --git a/src/evalcontext.cc b/src/evalcontext.cc new file mode 100644 index 0000000..39e5aae --- /dev/null +++ b/src/evalcontext.cc @@ -0,0 +1,40 @@ +#include "evalcontext.h" +#include "module.h" +#include "expression.h" +#include "function.h" +#include "printutils.h" +#include "builtin.h" + +#include + +#ifdef DEBUG +void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst) +{ + if (inst) + PRINTB("EvalContext %p (%p) for %s inst (%p)", this % this->parent % inst->name() % inst); + else + PRINTB("Context: %p (%p)", this % this->parent); + PRINTB(" document path: %s", this->document_path); + + PRINT(" eval args:"); + for (int i=0;ieval_arguments.size();i++) { + PRINTB(" %s = %s", this->eval_arguments[i].first % this->eval_arguments[i].second); + } + if (this->children.size() > 0) { + PRINT(" children:"); + BOOST_FOREACH(const ModuleInstantiation *ch, this->children) { + PRINTB(" %s", ch->name()); + } + } + + if (mod) { + const Module *m = dynamic_cast(mod); + if (m) { + PRINT(" module args:"); + BOOST_FOREACH(const std::string &arg, m->argnames) { + PRINTB(" %s = %s", arg % variables[arg]); + } + } + } +} +#endif diff --git a/src/evalcontext.h b/src/evalcontext.h new file mode 100644 index 0000000..3d7d222 --- /dev/null +++ b/src/evalcontext.h @@ -0,0 +1,24 @@ +#ifndef EVALCONTEXT_H_ +#define EVALCONTEXT_H_ + +#include "context.h" + +/*! + This hold the evaluation context (the parameters actually sent + when calling a module or function, including the children). +*/ +class EvalContext : public Context +{ +public: + EvalContext(const Context *parent = NULL) : Context(parent) {} + virtual ~EvalContext() {} + + std::vector > eval_arguments; + std::vector children; + +#ifdef DEBUG + virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); +#endif +}; + +#endif diff --git a/src/expr.cc b/src/expr.cc index 75fc47a..1d7b440 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -26,7 +26,7 @@ #include "expression.h" #include "value.h" -#include "context.h" +#include "evalcontext.h" #include #include #include @@ -127,13 +127,18 @@ Value Expression::evaluate(const Context *context) const return Value(); } if (this->type == "F") { - Value::VectorType argvalues; - std::transform(this->children.begin(), this->children.end(), - std::back_inserter(argvalues), - boost::bind(&Expression::evaluate, _1, context)); + EvalContext c(context); + for (size_t i=0; i < this->children.size(); i++) { + c.eval_arguments.push_back(std::make_pair(this->call_argnames[i], + this->children[i]->evaluate(context))); + } + // Value::VectorType argvalues; + // std::transform(this->children.begin(), this->children.end(), + // std::back_inserter(argvalues), + // boost::bind(&Expression::evaluate, _1, context)); // for (size_t i=0; i < this->children.size(); i++) // argvalues.push_back(this->children[i]->evaluate(context)); - return context->evaluate_function(this->call_funcname, this->call_argnames, argvalues); + return context->evaluate_function(this->call_funcname, &c); } abort(); } diff --git a/src/func.cc b/src/func.cc index 791e957..ecd1f87 100644 --- a/src/func.cc +++ b/src/func.cc @@ -26,7 +26,7 @@ #include "function.h" #include "expression.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include #include @@ -61,7 +61,7 @@ AbstractFunction::~AbstractFunction() { } -Value AbstractFunction::evaluate(const Context*, const std::vector&, const std::vector&) const +Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const { return Value(); } @@ -79,12 +79,10 @@ Function::~Function() delete expr; } -Value Function::evaluate(const Context *ctx, - const std::vector &call_argnames, - const std::vector &call_argvalues) const +Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const { Context c(ctx); - c.args(argnames, argexpr, call_argnames, call_argvalues); + c.setVariables(argnames, argexpr, evalctx); return expr ? expr->evaluate(&c) : Value(); } @@ -105,9 +103,9 @@ BuiltinFunction::~BuiltinFunction() { } -Value BuiltinFunction::evaluate(const Context *ctx, const std::vector &call_argnames, const std::vector &call_argvalues) const +Value BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const { - return eval_func(ctx, call_argnames, call_argvalues); + return eval_func(ctx, evalctx); } std::string BuiltinFunction::dump(const std::string &indent, const std::string &name) const @@ -127,37 +125,37 @@ static inline double rad2deg(double x) return x * 180.0 / M_PI; } -Value builtin_abs(const Context *, const std::vector&, const std::vector &args) +Value builtin_abs(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(fabs(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(fabs(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_sign(const Context *, const std::vector&, const std::vector &args) +Value builtin_sign(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value((args[0].toDouble()<0) ? -1.0 : ((args[0].toDouble()>0) ? 1.0 : 0.0)); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value((evalctx->eval_arguments[0].second.toDouble()<0) ? -1.0 : ((evalctx->eval_arguments[0].second.toDouble()>0) ? 1.0 : 0.0)); return Value(); } -Value builtin_rands(const Context *, const std::vector&, const std::vector &args) +Value builtin_rands(const Context *, const EvalContext *evalctx) { bool deterministic = false; - if (args.size() == 3 && - args[0].type() == Value::NUMBER && - args[1].type() == Value::NUMBER && - args[2].type() == Value::NUMBER) + if (evalctx->eval_arguments.size() == 3 && + evalctx->eval_arguments[0].second.type() == Value::NUMBER && + evalctx->eval_arguments[1].second.type() == Value::NUMBER && + evalctx->eval_arguments[2].second.type() == Value::NUMBER) { deterministic = false; } - else if (args.size() == 4 && - args[0].type() == Value::NUMBER && - args[1].type() == Value::NUMBER && - args[2].type() == Value::NUMBER && - args[3].type() == Value::NUMBER) + else if (evalctx->eval_arguments.size() == 4 && + evalctx->eval_arguments[0].second.type() == Value::NUMBER && + evalctx->eval_arguments[1].second.type() == Value::NUMBER && + evalctx->eval_arguments[2].second.type() == Value::NUMBER && + evalctx->eval_arguments[3].second.type() == Value::NUMBER) { - deterministic_rng.seed( (unsigned int) args[3].toDouble() ); + deterministic_rng.seed( (unsigned int) evalctx->eval_arguments[3].second.toDouble() ); deterministic = true; } else @@ -165,11 +163,11 @@ Value builtin_rands(const Context *, const std::vector&, const std: return Value(); } - double min = std::min( args[0].toDouble(), args[1].toDouble() ); - double max = std::max( args[0].toDouble(), args[1].toDouble() ); + double min = std::min( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); + double max = std::max( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); boost::uniform_real<> distributor( min, max ); Value::VectorType vec; - for (int i=0; ieval_arguments[2].second.toDouble(); i++) { if ( deterministic ) { vec.push_back( Value( distributor( deterministic_rng ) ) ); } else { @@ -181,169 +179,169 @@ Value builtin_rands(const Context *, const std::vector&, const std: } -Value builtin_min(const Context *, const std::vector&, const std::vector &args) +Value builtin_min(const Context *, const EvalContext *evalctx) { - if (args.size() >= 1 && args[0].type() == Value::NUMBER) { - double val = args[0].toDouble(); - for (size_t i = 1; i < args.size(); i++) - if (args[1].type() == Value::NUMBER) - val = fmin(val, args[i].toDouble()); + if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { + double val = evalctx->eval_arguments[0].second.toDouble(); + for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) + if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) + val = fmin(val, evalctx->eval_arguments[i].second.toDouble()); return Value(val); } return Value(); } -Value builtin_max(const Context *, const std::vector&, const std::vector &args) +Value builtin_max(const Context *, const EvalContext *evalctx) { - if (args.size() >= 1 && args[0].type() == Value::NUMBER) { - double val = args[0].toDouble(); - for (size_t i = 1; i < args.size(); i++) - if (args[1].type() == Value::NUMBER) - val = fmax(val, args[i].toDouble()); + if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { + double val = evalctx->eval_arguments[0].second.toDouble(); + for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) + if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) + val = fmax(val, evalctx->eval_arguments[i].second.toDouble()); return Value(val); } return Value(); } -Value builtin_sin(const Context *, const std::vector&, const std::vector &args) +Value builtin_sin(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(sin(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(sin(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_cos(const Context *, const std::vector&, const std::vector &args) +Value builtin_cos(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(cos(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(cos(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_asin(const Context *, const std::vector&, const std::vector &args) +Value builtin_asin(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(asin(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(asin(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_acos(const Context *, const std::vector&, const std::vector &args) +Value builtin_acos(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(acos(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(acos(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_tan(const Context *, const std::vector&, const std::vector &args) +Value builtin_tan(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(tan(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(tan(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_atan(const Context *, const std::vector&, const std::vector &args) +Value builtin_atan(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(atan(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(atan(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_atan2(const Context *, const std::vector&, const std::vector &args) +Value builtin_atan2(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(rad2deg(atan2(args[0].toDouble(), args[1].toDouble()))); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(rad2deg(atan2(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble()))); return Value(); } -Value builtin_pow(const Context *, const std::vector&, const std::vector &args) +Value builtin_pow(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(pow(args[0].toDouble(), args[1].toDouble())); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(pow(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble())); return Value(); } -Value builtin_round(const Context *, const std::vector&, const std::vector &args) +Value builtin_round(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(round(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(round(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_ceil(const Context *, const std::vector&, const std::vector &args) +Value builtin_ceil(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(ceil(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(ceil(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_floor(const Context *, const std::vector&, const std::vector &args) +Value builtin_floor(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(floor(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(floor(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_sqrt(const Context *, const std::vector&, const std::vector &args) +Value builtin_sqrt(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(sqrt(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(sqrt(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_exp(const Context *, const std::vector&, const std::vector &args) +Value builtin_exp(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(exp(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(exp(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_length(const Context *, const std::vector&, const std::vector &args) +Value builtin_length(const Context *, const EvalContext *evalctx) { - if (args.size() == 1) { - if (args[0].type() == Value::VECTOR) return Value(int(args[0].toVector().size())); - if (args[0].type() == Value::STRING) return Value(int(args[0].toString().size())); + if (evalctx->eval_arguments.size() == 1) { + if (evalctx->eval_arguments[0].second.type() == Value::VECTOR) return Value(int(evalctx->eval_arguments[0].second.toVector().size())); + if (evalctx->eval_arguments[0].second.type() == Value::STRING) return Value(int(evalctx->eval_arguments[0].second.toString().size())); } return Value(); } -Value builtin_log(const Context *, const std::vector&, const std::vector &args) +Value builtin_log(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(log(args[1].toDouble()) / log(args[0].toDouble())); - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(log(args[0].toDouble()) / log(10.0)); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[1].second.toDouble()) / log(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[0].second.toDouble()) / log(10.0)); return Value(); } -Value builtin_ln(const Context *, const std::vector&, const std::vector &args) +Value builtin_ln(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(log(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_str(const Context *, const std::vector&, const std::vector &args) +Value builtin_str(const Context *, const EvalContext *evalctx) { std::stringstream stream; - for (size_t i = 0; i < args.size(); i++) { - stream << args[i].toString(); + for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { + stream << evalctx->eval_arguments[i].second.toString(); } return Value(stream.str()); } -Value builtin_lookup(const Context *, const std::vector&, const std::vector &args) +Value builtin_lookup(const Context *, const EvalContext *evalctx) { double p, low_p, low_v, high_p, high_v; - if (args.size() < 2 || // Needs two args - !args[0].getDouble(p) || // First must be a number - args[1].toVector().size() < 2 || // Second must be a vector of vectors - args[1].toVector()[0].toVector().size() < 2) + if (evalctx->eval_arguments.size() < 2 || // Needs two args + !evalctx->eval_arguments[0].second.getDouble(p) || // First must be a number + evalctx->eval_arguments[1].second.toVector().size() < 2 || // Second must be a vector of vectors + evalctx->eval_arguments[1].second.toVector()[0].toVector().size() < 2) return Value(); - if (!args[1].toVector()[0].getVec2(low_p, low_v) || !args[1].toVector()[0].getVec2(high_p, high_v)) + if (!evalctx->eval_arguments[1].second.toVector()[0].getVec2(low_p, low_v) || !evalctx->eval_arguments[1].second.toVector()[0].getVec2(high_p, high_v)) return Value(); - for (size_t i = 1; i < args[1].toVector().size(); i++) { + for (size_t i = 1; i < evalctx->eval_arguments[1].second.toVector().size(); i++) { double this_p, this_v; - if (args[1].toVector()[i].getVec2(this_p, this_v)) { + if (evalctx->eval_arguments[1].second.toVector()[i].getVec2(this_p, this_v)) { if (this_p <= p && (this_p > low_p || low_p > p)) { low_p = this_p; low_v = this_v; @@ -404,14 +402,14 @@ Value builtin_lookup(const Context *, const std::vector&, const std - returns [[0,4],[1,5],[2,6],[8]] */ -Value builtin_search(const Context *, const std::vector&, const std::vector &args) +Value builtin_search(const Context *, const EvalContext *evalctx) { - if (args.size() < 2) return Value(); + if (evalctx->eval_arguments.size() < 2) return Value(); - const Value &findThis = args[0]; - const Value &searchTable = args[1]; - unsigned int num_returns_per_match = (args.size() > 2) ? args[2].toDouble() : 1; - unsigned int index_col_num = (args.size() > 3) ? args[3].toDouble() : 0; + const Value &findThis = evalctx->eval_arguments[0].second; + const Value &searchTable = evalctx->eval_arguments[1].second; + unsigned int num_returns_per_match = (evalctx->eval_arguments.size() > 2) ? evalctx->eval_arguments[2].second.toDouble() : 1; + unsigned int index_col_num = (evalctx->eval_arguments.size() > 3) ? evalctx->eval_arguments[3].second.toDouble() : 0; Value::VectorType returnvec; @@ -499,7 +497,7 @@ Value builtin_search(const Context *, const std::vector&, const std #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) -Value builtin_version(const Context *, const std::vector&, const std::vector &) +Value builtin_version(const Context *, const EvalContext *evalctx) { Value::VectorType val; val.push_back(Value(double(OPENSCAD_YEAR))); @@ -510,9 +508,9 @@ Value builtin_version(const Context *, const std::vector&, const st return Value(val); } -Value builtin_version_num(const Context *ctx, const std::vector& call_argnames, const std::vector &args) +Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) { - Value val = (args.size() == 0) ? builtin_version(ctx, call_argnames, args) : args[0]; + Value val = (evalctx->eval_arguments.size() == 0) ? builtin_version(ctx, evalctx) : evalctx->eval_arguments[0].second; double y, m, d = 0; if (!val.getVec3(y, m, d)) { if (!val.getVec2(y, m)) { diff --git a/src/function.h b/src/function.h index 623ef7e..bd7c329 100644 --- a/src/function.h +++ b/src/function.h @@ -9,20 +9,20 @@ class AbstractFunction { public: virtual ~AbstractFunction(); - virtual Value evaluate(const class Context *ctx, const std::vector &call_argnames, const std::vector &call_argvalues) const; + virtual Value evaluate(const class Context *ctx, const class EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; class BuiltinFunction : public AbstractFunction { public: - typedef Value (*eval_func_t)(const Context *ctx, const std::vector &argnames, const std::vector &args); + typedef Value (*eval_func_t)(const Context *ctx, const EvalContext *evalctx); eval_func_t eval_func; BuiltinFunction(eval_func_t f) : eval_func(f) { } virtual ~BuiltinFunction(); - virtual Value evaluate(const Context *ctx, const std::vector &call_argnames, const std::vector &call_argvalues) const; + virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; @@ -37,7 +37,7 @@ public: Function() { } virtual ~Function(); - virtual Value evaluate(const Context *ctx, const std::vector &call_argnames, const std::vector &call_argvalues) const; + virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; diff --git a/src/import.cc b/src/import.cc index bbf5a6e..3d753fb 100644 --- a/src/import.cc +++ b/src/import.cc @@ -28,7 +28,7 @@ #include "module.h" #include "polyset.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include "dxfdata.h" #include "dxftess.h" @@ -60,10 +60,10 @@ class ImportModule : public AbstractModule public: import_type_e type; ImportModule(import_type_e type = TYPE_UNKNOWN) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { std::vector argnames; argnames += "file", "layer", "convexity", "origin", "scale"; @@ -77,7 +77,11 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati } Context c(ctx); - c.args(argnames, argexpr, inst_argnames, inst->argvalues); + c.setDocumentPath(evalctx->documentPath()); + c.setVariables(argnames, argexpr, evalctx); +#ifdef DEBUG + c.dump(this, inst); +#endif Value v = c.lookup_variable("file"); std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index ff9682e..de728f7 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -27,7 +27,7 @@ #include "linearextrudenode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "printutils.h" #include "builtin.h" #include "PolySetEvaluator.h" @@ -45,10 +45,10 @@ class LinearExtrudeModule : public AbstractModule { public: LinearExtrudeModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { LinearExtrudeNode *node = new LinearExtrudeNode(inst); @@ -57,7 +57,7 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst std::vector argexpr; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); @@ -81,10 +81,10 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst // if height not given, and first argument is a number, // then assume it should be the height. if (c.lookup_variable("height").isUndefined() && - inst->argnames.size() > 0 && - inst->argnames[0] == "" && - inst->argvalues[0].type() == Value::NUMBER) { - height = Value(inst->argvalues[0]); + evalctx->eval_arguments.size() > 0 && + evalctx->eval_arguments[0].first == "" && + evalctx->eval_arguments[0].second.type() == Value::NUMBER) { + height = Value(evalctx->eval_arguments[0].second); } node->layername = layer.isUndefined() ? "" : layer.toString(); @@ -117,7 +117,7 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst } if (node->filename.empty()) { - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); } diff --git a/src/mainwin.cc b/src/mainwin.cc index dd855fb..2e69ec2 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -158,7 +158,7 @@ settings_valueList(const QString &key, const QList &defaultList = QListopenglbox = NULL; root_module = NULL; @@ -643,8 +643,8 @@ bool MainWindow::compile(bool reload, bool procevents) if (procevents) QApplication::processEvents(); AbstractNode::resetIndexCounter(); - this->root_inst = ModuleInstantiation(); - this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst); + this->root_inst = ModuleInstantiation("group"); + this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst, NULL); if (this->absolute_root_node) { // Do we have an explicit root node (! modifier)? diff --git a/src/modcontext.cc b/src/modcontext.cc new file mode 100644 index 0000000..34c6dbe --- /dev/null +++ b/src/modcontext.cc @@ -0,0 +1,133 @@ +#include "modcontext.h" +#include "module.h" +#include "expression.h" +#include "function.h" +#include "printutils.h" +#include "builtin.h" + +#include + +ModuleContext::ModuleContext(const class Module *module, const Context *parent, const EvalContext *evalctx) + : Context(parent) +{ + if (module) { + setModule(*module, evalctx); + } + else { + this->functions_p = NULL; + this->modules_p = NULL; + this->usedlibs_p = NULL; + } +} + +ModuleContext::~ModuleContext() +{ +} + +void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) +{ + this->setVariables(module.argnames, module.argexpr, evalctx); + this->evalctx = evalctx; + + // FIXME: Don't access module members directly + this->functions_p = &module.functions; + this->modules_p = &module.modules; + this->usedlibs_p = &module.usedlibs; + BOOST_FOREACH(const std::string &var, module.assignments_var) { + this->set_variable(var, module.assignments.at(var)->evaluate(this)); + } + + if (!module.modulePath().empty()) this->document_path = module.modulePath(); +} + +/*! + Only used to initialize builtins for the top-level root context +*/ +void ModuleContext::registerBuiltin() +{ + this->setModule(Builtins::instance()->getRootModule()); + this->set_constant("PI",Value(M_PI)); +} + +Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const +{ + if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) { + return this->functions_p->find(name)->second->evaluate(this, evalctx); + } + + if (this->usedlibs_p) { + BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { + if (m.second->functions.find(name) != m.second->functions.end()) { + ModuleContext ctx(m.second, this->parent); + // FIXME: Set document path +#ifdef DEBUG + PRINTB("New lib Context for %s func:", name); + ctx.dump(NULL, NULL); +#endif + return m.second->functions[name]->evaluate(&ctx, evalctx); + } + } + } + return Context::evaluate_function(name, evalctx); +} + +AbstractNode *ModuleContext::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +{ + if (this->modules_p && this->modules_p->find(inst.name()) != this->modules_p->end()) { + AbstractModule *m = this->modules_p->find(inst.name())->second; + std::string replacement = Builtins::instance()->isDeprecated(inst.name()); + if (!replacement.empty()) { + PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement); + } + return m->evaluate(this, &inst, evalctx); + } + + if (this->usedlibs_p) { + BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { + assert(m.second); + if (m.second->modules.find(inst.name()) != m.second->modules.end()) { + ModuleContext ctx(m.second, this->parent); + // FIXME: Set document path +#ifdef DEBUG + PRINT("New lib Context:"); + ctx.dump(NULL, &inst); +#endif + return m.second->modules[inst.name()]->evaluate(&ctx, &inst, evalctx); + } + } + } + + return Context::evaluate_module(inst, evalctx); +} + +#ifdef DEBUG +void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst) +{ + if (inst) + PRINTB("ModuleContext %p (%p) for %s inst (%p) ", this % this->parent % inst->name() % inst); + else + PRINTB("ModuleContext: %p (%p)", this % this->parent); + PRINTB(" document path: %s", this->document_path); + if (mod) { + const Module *m = dynamic_cast(mod); + if (m) { + PRINT(" module args:"); + BOOST_FOREACH(const std::string &arg, m->argnames) { + PRINTB(" %s = %s", arg % variables[arg]); + } + } + } + typedef std::pair ValueMapType; + PRINT(" vars:"); + BOOST_FOREACH(const ValueMapType &v, constants) { + PRINTB(" %s = %s", v.first % v.second); + } + BOOST_FOREACH(const ValueMapType &v, variables) { + PRINTB(" %s = %s", v.first % v.second); + } + BOOST_FOREACH(const ValueMapType &v, config_variables) { + PRINTB(" %s = %s", v.first % v.second); + } + +} +#endif diff --git a/src/modcontext.h b/src/modcontext.h new file mode 100644 index 0000000..cecf91f --- /dev/null +++ b/src/modcontext.h @@ -0,0 +1,37 @@ +#ifndef FILECONTEXT_H_ +#define FILECONTEXT_H_ + +#include "context.h" + +/*! + This holds the context for a Module definition; keeps track of + global variables, submodules and functions defined inside a module. + + NB! every .scad file defines an implicit unnamed module holding the contents of the file. +*/ +class ModuleContext : public Context +{ +public: + ModuleContext(const class Module *module = NULL, const Context *parent = NULL, const EvalContext *evalctx = NULL); + virtual ~ModuleContext(); + + void setModule(const Module &module, const EvalContext *evalctx = NULL); + void registerBuiltin(); + + virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const; + virtual AbstractNode *evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; + + const boost::unordered_map *functions_p; + const boost::unordered_map *modules_p; + typedef boost::unordered_map ModuleContainer; + const ModuleContainer *usedlibs_p; + + // FIXME: Points to the eval context for the call to this module. Not sure where it belongs + const class EvalContext *evalctx; + +#ifdef DEBUG + virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); +#endif +}; + +#endif diff --git a/src/module.cc b/src/module.cc index 322085b..120d07e 100644 --- a/src/module.cc +++ b/src/module.cc @@ -27,7 +27,8 @@ #include "module.h" #include "ModuleCache.h" #include "node.h" -#include "context.h" +#include "modcontext.h" +#include "evalcontext.h" #include "expression.h" #include "function.h" #include "printutils.h" @@ -43,11 +44,11 @@ AbstractModule::~AbstractModule() { } -AbstractNode *AbstractModule::evaluate(const Context*, const ModuleInstantiation *inst) const +AbstractNode *AbstractModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = new AbstractNode(inst); - node->children = inst->evaluateChildren(); + node->children = inst->evaluateChildren(evalctx); return node; } @@ -108,43 +109,40 @@ std::string ModuleInstantiation::dump(const std::string &indent) const return dump.str(); } -AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const +AbstractNode *ModuleInstantiation::evaluate_instance(const Context *ctx) const { - AbstractNode *node = NULL; - if (this->ctx) { - PRINTB("WARNING: Ignoring recursive module instantiation of '%s'.", modname); - } else { - // FIXME: Casting away const.. - ModuleInstantiation *that = (ModuleInstantiation*)this; - that->argvalues.clear(); - BOOST_FOREACH (Expression *expr, that->argexpr) { - that->argvalues.push_back(expr->evaluate(ctx)); - } - that->ctx = ctx; - node = ctx->evaluate_module(*this); - that->ctx = NULL; - that->argvalues.clear(); + EvalContext c(ctx); + for (size_t i=0; ievaluate(ctx) : + Value())); } + c.children = this->children; + +#ifdef DEBUG + PRINT("New eval ctx:"); + c.dump(NULL, this); +#endif + AbstractNode *node = ctx->evaluate_module(*this, &c); // Passes c as evalctx return node; } -std::vector ModuleInstantiation::evaluateChildren(const Context *ctx) const +std::vector ModuleInstantiation::evaluateChildren(const Context *evalctx) const { - if (!ctx) ctx = this->ctx; std::vector childnodes; BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { - AbstractNode *node = modinst->evaluate(ctx); + AbstractNode *node = modinst->evaluate_instance(evalctx); if (node) childnodes.push_back(node); } return childnodes; } -std::vector IfElseModuleInstantiation::evaluateElseChildren(const Context *ctx) const +std::vector IfElseModuleInstantiation::evaluateElseChildren(const Context *evalctx) const { - if (!ctx) ctx = this->ctx; std::vector childnodes; BOOST_FOREACH (ModuleInstantiation *modinst, this->else_children) { - AbstractNode *node = modinst->evaluate(ctx); + AbstractNode *node = modinst->evaluate_instance(evalctx); if (node != NULL) childnodes.push_back(node); } return childnodes; @@ -158,29 +156,18 @@ Module::~Module() BOOST_FOREACH (ModuleInstantiation *v, children) delete v; } -AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { - Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); - - c.inst_p = inst; + ModuleContext c(this, ctx, evalctx); + // FIXME: Set document path to the path of the module c.set_variable("$children", Value(double(inst->children.size()))); - - c.functions_p = &functions; - c.modules_p = &modules; - - if (!usedlibs.empty()) - c.usedlibs_p = &usedlibs; - else - c.usedlibs_p = NULL; - - BOOST_FOREACH(const std::string &var, assignments_var) { - c.set_variable(var, assignments.at(var)->evaluate(&c)); - } +#ifdef DEBUG + c.dump(this, inst); +#endif AbstractNode *node = new AbstractNode(inst); for (size_t i = 0; i < children.size(); i++) { - AbstractNode *n = children[i]->evaluate(&c); + AbstractNode *n = children[i]->evaluate_instance(&c); if (n != NULL) node->children.push_back(n); } diff --git a/src/module.h b/src/module.h index 1f9e303..17f0c59 100644 --- a/src/module.h +++ b/src/module.h @@ -11,13 +11,12 @@ class ModuleInstantiation { public: ModuleInstantiation(const std::string &name = "") - : ctx(NULL), - tag_root(false), tag_highlight(false), tag_background(false), modname(name) { } + : tag_root(false), tag_highlight(false), tag_background(false), modname(name) { } virtual ~ModuleInstantiation(); std::string dump(const std::string &indent) const; - class AbstractNode *evaluate(const class Context *ctx) const; - std::vector evaluateChildren(const Context *ctx = NULL) const; + class AbstractNode *evaluate_instance(const class Context *ctx) const; + std::vector evaluateChildren(const Context *evalctx) const; void setPath(const std::string &path) { this->modpath = path; } const std::string &path() const { return this->modpath; } @@ -29,10 +28,8 @@ public: bool isRoot() const { return this->tag_root; } std::vector argnames; - std::vector argvalues; std::vector argexpr; std::vector children; - const Context *ctx; bool tag_root; bool tag_highlight; @@ -48,7 +45,7 @@ class IfElseModuleInstantiation : public ModuleInstantiation { public: IfElseModuleInstantiation() : ModuleInstantiation("if") { } virtual ~IfElseModuleInstantiation(); - std::vector evaluateElseChildren(const Context *ctx = NULL) const; + std::vector evaluateElseChildren(const Context *evalctx) const; std::vector else_children; }; @@ -57,7 +54,7 @@ class AbstractModule { public: virtual ~AbstractModule(); - virtual class AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual class AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; @@ -67,7 +64,10 @@ public: Module() : is_handling_dependencies(false) { } virtual ~Module(); - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + void setModulePath(const std::string &path) { this->path = path; } + const std::string &modulePath() const { return this->path; } + + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; void addChild(ModuleInstantiation *ch) { this->children.push_back(ch); } @@ -97,6 +97,7 @@ public: protected: private: + std::string path; }; #endif diff --git a/src/openscad.cc b/src/openscad.cc index 878c207..a345569 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -28,7 +28,7 @@ #include "MainWindow.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -327,11 +327,8 @@ int main(int argc, char **argv) if (!filename) help(argv[0]); - Context root_ctx; - register_builtin(root_ctx); - Module *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); AbstractNode *root_node; AbstractNode *absolute_root_node; CGAL_Nef_polyhedron root_N; @@ -351,12 +348,17 @@ int main(int argc, char **argv) if (!root_module) exit(1); root_module->handleDependencies(); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); + PRINT("Root Context:"); + root_ctx.dump(NULL, NULL); + fs::path fpath = boosty::absolute(fs::path(filename)); fs::path fparent = fpath.parent_path(); fs::current_path(fparent); AbstractNode::resetIndexCounter(); - absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + absolute_root_node = root_module->evaluate(&root_ctx, &root_inst, NULL); // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) diff --git a/src/parser.y b/src/parser.y index 70aebba..26bdba6 100644 --- a/src/parser.y +++ b/src/parser.y @@ -551,6 +551,7 @@ Module *parse(const char *text, const char *path, int debug) module_stack.clear(); Module *rootmodule = currmodule = new Module(); + rootmodule->setModulePath(path); // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); parserdebug = debug; diff --git a/src/primitives.cc b/src/primitives.cc index e02df35..40e7e0b 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -27,12 +27,13 @@ #include "module.h" #include "node.h" #include "polyset.h" -#include "context.h" +#include "evalcontext.h" #include "dxfdata.h" #include "dxftess.h" #include "builtin.h" #include "printutils.h" #include "visitor.h" +#include "context.h" #include #include #include @@ -55,7 +56,7 @@ class PrimitiveModule : public AbstractModule public: primitive_type_e type; PrimitiveModule(primitive_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; class PrimitiveNode : public AbstractPolyNode @@ -104,7 +105,7 @@ public: virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; }; -AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { PrimitiveNode *node = new PrimitiveNode(inst, this->type); @@ -141,7 +142,7 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti } Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); diff --git a/src/printutils.cc b/src/printutils.cc index 698fffb..37092fa 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -69,5 +69,3 @@ std::string two_digit_exp_format( double x ) s << x; return two_digit_exp_format( s.str() ); } - - diff --git a/src/printutils.h b/src/printutils.h index 439c884..18aadde 100644 --- a/src/printutils.h +++ b/src/printutils.h @@ -22,6 +22,9 @@ void PRINT(const std::string &msg); void PRINT_NOCACHE(const std::string &msg); #define PRINTB_NOCACHE(_fmt, _arg) do { PRINT_NOCACHE(str(boost::format(_fmt) % _arg)); } while (0) + +void PRINT_CONTEXT(const class Context *ctx, const class Module *mod, const class ModuleInstantiation *inst); + std::string two_digit_exp_format( std::string doublestr ); std::string two_digit_exp_format( double x ); diff --git a/src/projection.cc b/src/projection.cc index 1fcf639..46add48 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -26,7 +26,7 @@ #include "projectionnode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "printutils.h" #include "builtin.h" #include "visitor.h" @@ -41,10 +41,10 @@ class ProjectionModule : public AbstractModule { public: ProjectionModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ProjectionNode *node = new ProjectionNode(inst); @@ -53,7 +53,7 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant std::vector argexpr; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); Value convexity = c.lookup_variable("convexity", true); Value cut = c.lookup_variable("cut", true); @@ -63,7 +63,7 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant if (cut.type() == Value::BOOL) node->cut_mode = cut.toBool(); - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; diff --git a/src/render.cc b/src/render.cc index 81c3f7b..855e5e3 100644 --- a/src/render.cc +++ b/src/render.cc @@ -26,7 +26,7 @@ #include "rendernode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include "PolySetEvaluator.h" @@ -38,10 +38,10 @@ class RenderModule : public AbstractModule { public: RenderModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { RenderNode *node = new RenderNode(inst); @@ -50,13 +50,13 @@ AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiati std::vector argexpr; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); Value v = c.lookup_variable("convexity"); if (v.type() == Value::NUMBER) node->convexity = (int)v.toDouble(); - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index c4d9342..29a873f 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -26,7 +26,7 @@ #include "rotateextrudenode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "printutils.h" #include "builtin.h" #include "polyset.h" @@ -45,10 +45,10 @@ class RotateExtrudeModule : public AbstractModule { public: RotateExtrudeModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { RotateExtrudeNode *node = new RotateExtrudeNode(inst); @@ -57,7 +57,7 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst std::vector argexpr; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); @@ -86,7 +86,7 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst node->scale = 1; if (node->filename.empty()) { - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); } diff --git a/src/surface.cc b/src/surface.cc index ca5031e..22da93d 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -27,7 +27,7 @@ #include "module.h" #include "node.h" #include "polyset.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include "printutils.h" #include "handle_dep.h" // handle_dep() @@ -50,7 +50,7 @@ class SurfaceModule : public AbstractModule { public: SurfaceModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; class SurfaceNode : public AbstractPolyNode @@ -69,7 +69,7 @@ public: virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; }; -AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { SurfaceNode *node = new SurfaceNode(inst); node->center = false; @@ -80,7 +80,7 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat std::vector argexpr; Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); Value fileval = c.lookup_variable("file"); node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); diff --git a/src/transform.cc b/src/transform.cc index b01827f..6246a59 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -26,7 +26,7 @@ #include "transformnode.h" #include "module.h" -#include "context.h" +#include "evalcontext.h" #include "polyset.h" #include "builtin.h" #include "value.h" @@ -50,10 +50,10 @@ class TransformModule : public AbstractModule public: transform_type_e type; TransformModule(transform_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { TransformNode *node = new TransformNode(inst); @@ -83,7 +83,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti } Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); + c.setVariables(argnames, argexpr, evalctx); if (this->type == SCALE) { @@ -176,7 +176,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti } } - std::vector evaluatednodes = inst->evaluateChildren(); + std::vector evaluatednodes = inst->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); return node; diff --git a/testdata/scad/features/child-child-test.scad b/testdata/scad/features/child-child-test.scad new file mode 100644 index 0000000..e5e6d93 --- /dev/null +++ b/testdata/scad/features/child-child-test.scad @@ -0,0 +1,12 @@ +module up() { + translate([0,0,1]) child(0); +} + +module red() { + color("Red") child(0); +} + +up() cylinder(r=5); +translate([5,0,0]) up() up() cylinder(r=5); +translate([10,0,0]) up() up() up() red() cylinder(r=5); +translate([15,0,0]) red() up() up() up() up() cylinder(r=5); diff --git a/testdata/scad/features/module-recursion.scad b/testdata/scad/features/module-recursion.scad new file mode 100644 index 0000000..f67a1d0 --- /dev/null +++ b/testdata/scad/features/module-recursion.scad @@ -0,0 +1,15 @@ +module tree(currentScale, levels) +{ + h = currentScale; + w = currentScale/5; + childScale = currentScale * 0.7; + + if (levels > 0) { + cylinder(r=w, h=h); + translate([0,0,h]) for (i = [1:2]) { + rotate([40, 0, i * 180]) tree(childScale, levels-1); + } + } +} + +tree(1, 4); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a0d8f6b..36faa58 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -426,6 +426,8 @@ set(CORE_SOURCES ../src/ModuleCache.cc ../src/node.cc ../src/context.cc + ../src/modcontext.cc + ../src/evalcontext.cc ../src/csgterm.cc ../src/csgtermnormalizer.cc ../src/polyset.cc diff --git a/tests/cgalcachetest.cc b/tests/cgalcachetest.cc index 3a0a855..82864a4 100644 --- a/tests/cgalcachetest.cc +++ b/tests/cgalcachetest.cc @@ -30,7 +30,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -132,11 +132,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); root_module = parsefile(filename); if (!root_module) { diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index 52205fd..e2f7a72 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -30,7 +30,7 @@ #include "node.h" #include "module.h" #include "polyset.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -105,11 +105,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); root_module = parsefile(filename); if (!root_module) { diff --git a/tests/cgalstlsanitytest.cc b/tests/cgalstlsanitytest.cc index 2815463..15cc20f 100644 --- a/tests/cgalstlsanitytest.cc +++ b/tests/cgalstlsanitytest.cc @@ -29,7 +29,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -91,11 +91,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); root_module = parsefile(filename); if (!root_module) { diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc index 4a15050..2c071c1 100644 --- a/tests/cgaltest.cc +++ b/tests/cgaltest.cc @@ -29,7 +29,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -84,11 +84,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); root_module = parsefile(filename); if (!root_module) { diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc index e793c4a..edf334e 100644 --- a/tests/csgtermtest.cc +++ b/tests/csgtermtest.cc @@ -31,7 +31,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -79,11 +79,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); const AbstractNode *root_node; root_module = parsefile(filename); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 7583a41..a4f05e8 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -6,7 +6,7 @@ #include "openscad.h" #include "parsersettings.h" #include "builtin.h" -#include "context.h" +#include "modcontext.h" #include "node.h" #include "module.h" #include "polyset.h" @@ -137,11 +137,11 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); if (sysinfo_dump) root_module = parse("sphere();","",false); diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc index e050232..5bda1f1 100644 --- a/tests/csgtexttest.cc +++ b/tests/csgtexttest.cc @@ -31,7 +31,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -83,11 +83,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); AbstractNode *root_node; root_module = parsefile(filename); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index 3627608..3ca1c22 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -29,7 +29,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -89,11 +89,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); AbstractNode *root_node; root_module = parsefile(filename); diff --git a/tests/echotest.cc b/tests/echotest.cc index bf2f4a4..e3a0343 100644 --- a/tests/echotest.cc +++ b/tests/echotest.cc @@ -29,7 +29,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "builtin.h" #include "printutils.h" @@ -91,11 +91,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); AbstractNode *root_node; root_module = parsefile(filename); diff --git a/tests/modulecachetest.cc b/tests/modulecachetest.cc index 0028114..94d7a50 100644 --- a/tests/modulecachetest.cc +++ b/tests/modulecachetest.cc @@ -29,7 +29,7 @@ #include "parsersettings.h" #include "node.h" #include "module.h" -#include "context.h" +#include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" @@ -79,11 +79,11 @@ int main(int argc, char **argv) parser_init(QCoreApplication::instance()->applicationDirPath().toStdString()); add_librarydir(boosty::stringy(fs::path(QCoreApplication::instance()->applicationDirPath().toStdString()) / "../libraries")); - Context root_ctx; - register_builtin(root_ctx); + ModuleContext root_ctx; + root_ctx.registerBuiltin(); AbstractModule *root_module; - ModuleInstantiation root_inst; + ModuleInstantiation root_inst("group"); AbstractNode *root_node; root_module = parsefile(filename); diff --git a/tests/regression/cgalpngtest/child-child-test-expected.png b/tests/regression/cgalpngtest/child-child-test-expected.png new file mode 100644 index 0000000..80b70ba Binary files /dev/null and b/tests/regression/cgalpngtest/child-child-test-expected.png differ diff --git a/tests/regression/cgalpngtest/module-recursion-expected.png b/tests/regression/cgalpngtest/module-recursion-expected.png new file mode 100644 index 0000000..3012a12 Binary files /dev/null and b/tests/regression/cgalpngtest/module-recursion-expected.png differ diff --git a/tests/regression/dumptest/child-child-test-expected.txt b/tests/regression/dumptest/child-child-test-expected.txt new file mode 100644 index 0000000..13f098d --- /dev/null +++ b/tests/regression/dumptest/child-child-test-expected.txt @@ -0,0 +1,59 @@ + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 5, r2 = 5, center = false); + } + } + multmatrix([[1, 0, 0, 5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 5, r2 = 5, center = false); + } + } + } + } + } + multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + color([1, 0, 0, 1]) { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 5, r2 = 5, center = false); + } + } + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + color([1, 0, 0, 1]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 5, r2 = 5, center = false); + } + } + } + } + } + } + } + } + } + } + } + diff --git a/tests/regression/dumptest/module-recursion-expected.txt b/tests/regression/dumptest/module-recursion-expected.txt new file mode 100644 index 0000000..9ad8877 --- /dev/null +++ b/tests/regression/dumptest/module-recursion-expected.txt @@ -0,0 +1,244 @@ + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 0.2, r2 = 0.2, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.7, r1 = 0.14, r2 = 0.14, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.7], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.49, r1 = 0.098, r2 = 0.098, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.49], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.49, r1 = 0.098, r2 = 0.098, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.49], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.7, r1 = 0.14, r2 = 0.14, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.7], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.49, r1 = 0.098, r2 = 0.098, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.49], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.49, r1 = 0.098, r2 = 0.098, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.49], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group() { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 0.343, r1 = 0.0686, r2 = 0.0686, center = false); + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.343], [0, 0, 0, 1]]) { + group() { + multmatrix([[-1, 0, 0, 0], [0, -0.76604444311, 0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + multmatrix([[1, 0, 0, 0], [0, 0.76604444311, -0.64278760968, 0], [0, 0.64278760968, 0.76604444311, 0], [0, 0, 0, 1]]) { + group() { + group(); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + diff --git a/tests/regression/opencsgtest/child-child-test-expected.png b/tests/regression/opencsgtest/child-child-test-expected.png new file mode 100644 index 0000000..07d61c0 Binary files /dev/null and b/tests/regression/opencsgtest/child-child-test-expected.png differ diff --git a/tests/regression/opencsgtest/module-recursion-expected.png b/tests/regression/opencsgtest/module-recursion-expected.png new file mode 100644 index 0000000..324c260 Binary files /dev/null and b/tests/regression/opencsgtest/module-recursion-expected.png differ diff --git a/tests/regression/throwntogethertest/child-child-test-expected.png b/tests/regression/throwntogethertest/child-child-test-expected.png new file mode 100644 index 0000000..07d61c0 Binary files /dev/null and b/tests/regression/throwntogethertest/child-child-test-expected.png differ diff --git a/tests/regression/throwntogethertest/module-recursion-expected.png b/tests/regression/throwntogethertest/module-recursion-expected.png new file mode 100644 index 0000000..324c260 Binary files /dev/null and b/tests/regression/throwntogethertest/module-recursion-expected.png differ -- cgit v0.10.1 From 2018a1fb6ae6ee65b79dfc96328945045baab753 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Apr 2013 01:04:22 -0400 Subject: Added latest fixes diff --git a/RELEASE_NOTES b/RELEASE_NOTES index d912be4..c729e6e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -2,6 +2,7 @@ OpenSCAD 2013.XX ================ Features: +o Recursive modules and functions is now supported (including cascading child() operations) o Console output is now enabled on Windows through the openscad.com executable o Added basic syntax highlighting in the editor o Mac: Added document icon @@ -12,6 +13,7 @@ o Regression test now creates single monolithic .html file for easier uploading o value reassignment is now less strict Bugfixes: +o Importing files is now always relative to the importing script, also for libraries o OpenCSG rendering sometimes crashed when rendering large models o We didn't always print a warning when CSG normalization created too many elements o Binary STLs can now be read on big endian architectures -- cgit v0.10.1 From 151593705f0cd83e1c5880607639daae25502d8b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Apr 2013 01:04:36 -0400 Subject: Disable context debug output diff --git a/src/import.cc b/src/import.cc index 3d753fb..283bbe6 100644 --- a/src/import.cc +++ b/src/import.cc @@ -79,7 +79,7 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati Context c(ctx); c.setDocumentPath(evalctx->documentPath()); c.setVariables(argnames, argexpr, evalctx); -#ifdef DEBUG +#if 0 && DEBUG c.dump(this, inst); #endif diff --git a/src/modcontext.cc b/src/modcontext.cc index 34c6dbe..7902608 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -60,7 +60,7 @@ Value ModuleContext::evaluate_function(const std::string &name, const EvalContex if (m.second->functions.find(name) != m.second->functions.end()) { ModuleContext ctx(m.second, this->parent); // FIXME: Set document path -#ifdef DEBUG +#if 0 && DEBUG PRINTB("New lib Context for %s func:", name); ctx.dump(NULL, NULL); #endif @@ -88,7 +88,7 @@ AbstractNode *ModuleContext::evaluate_module(const ModuleInstantiation &inst, co if (m.second->modules.find(inst.name()) != m.second->modules.end()) { ModuleContext ctx(m.second, this->parent); // FIXME: Set document path -#ifdef DEBUG +#if 0 && DEBUG PRINT("New lib Context:"); ctx.dump(NULL, &inst); #endif diff --git a/src/module.cc b/src/module.cc index 120d07e..d1e574d 100644 --- a/src/module.cc +++ b/src/module.cc @@ -120,7 +120,7 @@ AbstractNode *ModuleInstantiation::evaluate_instance(const Context *ctx) const } c.children = this->children; -#ifdef DEBUG +#if 0 && DEBUG PRINT("New eval ctx:"); c.dump(NULL, this); #endif @@ -161,7 +161,7 @@ AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *in ModuleContext c(this, ctx, evalctx); // FIXME: Set document path to the path of the module c.set_variable("$children", Value(double(inst->children.size()))); -#ifdef DEBUG +#if 0 && DEBUG c.dump(this, inst); #endif diff --git a/src/openscad.cc b/src/openscad.cc index a345569..3b960f3 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -351,8 +351,9 @@ int main(int argc, char **argv) ModuleContext root_ctx; root_ctx.registerBuiltin(); PRINT("Root Context:"); +#if 0 && DEBUG root_ctx.dump(NULL, NULL); - +#endif fs::path fpath = boosty::absolute(fs::path(filename)); fs::path fparent = fpath.parent_path(); fs::current_path(fparent); -- cgit v0.10.1 From fd9dd04f5064a9a21f593670fdcc073fdc14dbfc Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Apr 2013 20:19:29 -0400 Subject: Print warnings on child index out of bounds diff --git a/src/control.cc b/src/control.cc index 9133f28..446e47e 100644 --- a/src/control.cc +++ b/src/control.cc @@ -92,12 +92,15 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (type == CHILD) { - size_t n = 0; + int n = 0; if (evalctx->eval_arguments.size() > 0) { double v; if (evalctx->eval_arguments[0].second.getDouble(v)) { - if (v < 0) return NULL; // Disallow negative child indices n = trunc(v); + if (n < 0) { + PRINTB("WARNING: Negative child index (%d) not allowed", n); + return NULL; // Disallow negative child indices + } } } @@ -107,8 +110,19 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat while (tmpc->parent) { const ModuleContext *filectx = dynamic_cast(tmpc->parent); if (filectx) { - if (filectx->evalctx && n < filectx->evalctx->children.size()) { - node = filectx->evalctx->children[n]->evaluate_instance(filectx->evalctx); + // This will trigger if trying to invoke child from the root of any file + // assert(filectx->evalctx); + + if (filectx->evalctx) { + if (n < filectx->evalctx->children.size()) { + node = filectx->evalctx->children[n]->evaluate_instance(filectx->evalctx); + } + else { + // How to deal with negative objects in this case? + // (e.g. first child of difference is invalid) + PRINTB("WARNING: Child index (%d) out of bounds (%d children)", + n % filectx->evalctx->children.size()); + } } return node; } -- cgit v0.10.1 From ff050c37921e4fb20095dab97bb6b08c7ca68432 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sun, 14 Apr 2013 01:07:39 -0500 Subject: add curl and imagemagick to get-dependency script for linux diff --git a/scripts/uni-get-dependencies.sh b/scripts/uni-get-dependencies.sh index 98170de..e2fdaa7 100755 --- a/scripts/uni-get-dependencies.sh +++ b/scripts/uni-get-dependencies.sh @@ -7,7 +7,8 @@ get_fedora_deps() { sudo yum install qt-devel bison flex eigen2-devel python-paramiko \ - boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc pkgconfig git libXmu-devel + boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc pkgconfig \ + git libXmu-devel curl imagemagick } get_qomo_deps() @@ -19,7 +20,7 @@ get_altlinux_deps() { for i in boost-devel boost-filesystem-devel gcc4.5 gcc4.5-c++ boost-program_options-devel \ boost-thread-devel boost-system-devel boost-regex-devel eigen2 libmpfr libgmp libgmp_cxx-devel qt4-devel libcgal-devel git-core \ - libglew-devel flex bison; do sudo apt-get install $i; done + libglew-devel flex bison curl imagemagick; do sudo apt-get install $i; done } get_freebsd_deps() @@ -27,19 +28,19 @@ get_freebsd_deps() pkg_add -r bison boost-libs cmake git bash eigen2 flex gmake gmp mpfr \ xorg libGLU libXmu libXi xorg-vfbserver glew \ qt4-corelib qt4-gui qt4-moc qt4-opengl qt4-qmake qt4-rcc qt4-uic \ - opencsg cgal + opencsg cgal curl imagemagick } get_netbsd_deps() { sudo pkgin install bison boost cmake git bash eigen flex gmake gmp mpfr \ - qt4 glew cgal opencsg modular-xorg python27 py27-paramiko + qt4 glew cgal opencsg modular-xorg python27 py27-paramiko curl imagemagick } get_opensuse_deps() { sudo zypper install libeigen2-devel mpfr-devel gmp-devel boost-devel \ - libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel + libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl } get_mageia_deps() @@ -56,7 +57,7 @@ get_debian_deps() libxmu-dev cmake bison flex git-core libboost-all-dev \ libXi-dev libmpfr-dev libboost-dev libglew-dev libeigen2-dev \ libeigen3-dev libcgal-dev libopencsg-dev libgmp3-dev libgmp-dev \ - python-paramiko ; do + python-paramiko curl imagemagick; do sudo apt-get -y install $pkg; done } -- cgit v0.10.1 From c5bdc40c26728dbcaa1bfb7f00e82b7448f32d62 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sun, 14 Apr 2013 01:11:09 -0500 Subject: fix bug in cmake file cgal-flags when using clang diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fff537a..55b6924 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -354,7 +354,7 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6) endif() inclusion(CGAL_DIR CGAL_INCLUDE_DIRS) -if(CMAKE_CXX_COMPILER MATCHES ".*clang.*") +if(CMAKE_CXX_COMPILER MATCHES ".*clang.*" AND NOT STREQUAL ${CGAL_CXX_FLAGS_INIT} "" ) string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) endif() -- cgit v0.10.1 From 73c2a45af6afca253159d2cf9c1ecf5747f0217e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 15 Apr 2013 20:58:15 -0400 Subject: Reinstate recursion guard to new context handling, fixes the last known subissue of #116 and #328 diff --git a/src/context.cc b/src/context.cc index bc54b88..6189205 100644 --- a/src/context.cc +++ b/src/context.cc @@ -44,7 +44,6 @@ std::vector Context::ctx_stack; Context::Context(const Context *parent) : parent(parent) { - if (parent) recursioncount = parent->recursioncount; ctx_stack.push_back(this); if (parent) document_path = parent->document_path; } @@ -120,24 +119,8 @@ Value Context::lookup_variable(const std::string &name, bool silent) const return Value(); } -class RecursionGuard -{ -public: - RecursionGuard(const Context &c, const std::string &name) : c(c), name(name) { c.recursioncount[name]++; } - ~RecursionGuard() { if (--c.recursioncount[name] == 0) c.recursioncount.erase(name); } - bool recursion_detected() const { return (c.recursioncount[name] > 100); } -private: - const Context &c; - const std::string &name; -}; - Value Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const { - RecursionGuard g(*this, name); - if (g.recursion_detected()) { - PRINTB("Recursion detected calling function '%s'", name); - return Value(); - } if (this->parent) return this->parent->evaluate_function(name, evalctx); PRINTB("WARNING: Ignoring unknown function '%s'.", name); return Value(); diff --git a/src/context.h b/src/context.h index 5c75e48..282a940 100644 --- a/src/context.h +++ b/src/context.h @@ -33,8 +33,6 @@ public: static std::vector ctx_stack; - mutable boost::unordered_map recursioncount; - protected: typedef boost::unordered_map ValueMap; ValueMap constants; diff --git a/src/modcontext.cc b/src/modcontext.cc index 7902608..3280108 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -49,8 +49,27 @@ void ModuleContext::registerBuiltin() this->set_constant("PI",Value(M_PI)); } +class RecursionGuard +{ +public: + RecursionGuard(const ModuleContext &c, const std::string &name) : c(c), name(name) { + c.recursioncount[name]++; + } + ~RecursionGuard() { if (--c.recursioncount[name] == 0) c.recursioncount.erase(name); } + bool recursion_detected() const { return (c.recursioncount[name] > 100); } +private: + const ModuleContext &c; + const std::string &name; +}; + Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const { + RecursionGuard g(*this, name); + if (g.recursion_detected()) { + PRINTB("Recursion detected calling function '%s'", name); + return Value(); + } + if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) { return this->functions_p->find(name)->second->evaluate(this, evalctx); } diff --git a/src/modcontext.h b/src/modcontext.h index cecf91f..5fce88f 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -2,6 +2,7 @@ #define FILECONTEXT_H_ #include "context.h" +#include /*! This holds the context for a Module definition; keeps track of @@ -32,6 +33,8 @@ public: #ifdef DEBUG virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); #endif + + mutable boost::unordered_map recursioncount; }; #endif -- cgit v0.10.1 From c42dcfc614995863aaaf5197a298b8de486d1c1e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 17 Apr 2013 17:27:49 -0400 Subject: Added missing highlighting of some special variables diff --git a/src/highlighter.cc b/src/highlighter.cc index 391e3a5..bf80bb4 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -151,7 +151,7 @@ Highlighter::Highlighter(QTextDocument *parent) tokentypes["import"] << "include" << "use" << "import_stl" << "import" << "import_dxf" << "dxf_dim" << "dxf_cross"; typeformats["import"].setForeground(Qt::darkYellow); - tokentypes["special"] << "$children" << "child" << "$fn" << "$fa" << "$fb"; + tokentypes["special"] << "$children" << "child" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr"; typeformats["special"].setForeground(Qt::darkGreen); tokentypes["extrude"] << "linear_extrude" << "rotate_extrude"; -- cgit v0.10.1 From 5cee6b58dd1589848518a628a79c582a7320a92e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 18 Apr 2013 18:26:39 -0400 Subject: Test old parameter names for import diff --git a/testdata/scad/templates/import_dxf-tests-template.scad b/testdata/scad/templates/import_dxf-tests-template.scad index f10dd06..91eca7a 100644 --- a/testdata/scad/templates/import_dxf-tests-template.scad +++ b/testdata/scad/templates/import_dxf-tests-template.scad @@ -4,7 +4,7 @@ translate([-210,0,0]) import(file="../../dxf/polygons.dxf", origin=[0,110]); translate([-210,0,0]) import(file="../../dxf/polygons.dxf", origin=[110,110], scale=0.5); import(file="../../dxf/multiple-layers.dxf"); translate([-200,200,0]) import(file="../../dxf/multiple-layers.dxf", layer="0"); -translate([0,200,0]) import(file="../../dxf/multiple-layers.dxf", layer="0"); +translate([0,200,0]) import(filename="../../dxf/multiple-layers.dxf", layername="0"); translate([200,200,0]) import(file="../../dxf/multiple-layers.dxf", layer="noname"); translate([0,200,0]) import(file="../../dxf/multiple-layers.dxf", layer="Layer with a pretty long name including \\ \"special\" /'\\\\ characters"); translate([200,0,0]) import(file="@CMAKE_SOURCE_DIR@/../testdata/dxf/polygons.dxf"); -- cgit v0.10.1 From 58bd9c9e3f4454d055bf51d63463a9965a9dcbd7 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 18 Apr 2013 18:34:14 -0400 Subject: Cleaned up argument list handling, related to #116 diff --git a/openscad.pro b/openscad.pro index 00df471..0f3394e 100644 --- a/openscad.pro +++ b/openscad.pro @@ -187,7 +187,8 @@ FORMS += src/MainWindow.ui \ src/AboutDialog.ui \ src/ProgressWidget.ui -HEADERS += src/version_check.h \ +HEADERS += src/typedefs.h \ + src/version_check.h \ src/ProgressWidget.h \ src/parsersettings.h \ src/renderer.h \ diff --git a/src/cgaladv.cc b/src/cgaladv.cc index 8c98ae6..aad3a95 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -46,23 +46,22 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat { CgaladvNode *node = new CgaladvNode(inst, type); - std::vector argnames; - std::vector argexpr; + AssignmentList args; if (type == MINKOWSKI) - argnames += "convexity"; + args += Assignment("convexity", NULL); if (type == GLIDE) - argnames += "path", "convexity"; + args += Assignment("path", NULL), Assignment("convexity", NULL); if (type == SUBDIV) - argnames += "type", "level", "convexity"; + args += Assignment("type", NULL), Assignment("level", NULL), Assignment("convexity", NULL); if (type == RESIZE) - argnames += "newsize", "auto"; + args += Assignment("newsize", NULL), Assignment("auto", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); Value convexity, path, subdiv_type, level; diff --git a/src/color.cc b/src/color.cc index 4e9c55d..6c3aaef 100644 --- a/src/color.cc +++ b/src/color.cc @@ -54,13 +54,12 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio node->color[0] = node->color[1] = node->color[2] = -1.0; node->color[3] = 1.0; - std::vector argnames; - std::vector argexpr; + AssignmentList args; - argnames += "c", "alpha"; + args += Assignment("c", NULL), Assignment("alpha", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); Value v = c.lookup_variable("c"); if (v.type() == Value::VECTOR) { diff --git a/src/context.cc b/src/context.cc index 6189205..706407c 100644 --- a/src/context.cc +++ b/src/context.cc @@ -57,13 +57,11 @@ Context::~Context() Initialize context from a module argument list and a evaluation context which may pass variables which will be preferred over default values. */ -void Context::setVariables(const std::vector &argnames, - const std::vector &argexpr, +void Context::setVariables(const AssignmentList &args, const EvalContext *evalctx) { - for (size_t i=0; ievaluate(this->parent) : Value()); + BOOST_FOREACH(const Assignment &arg, args) { + set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : Value()); } if (evalctx) { @@ -72,7 +70,7 @@ void Context::setVariables(const std::vector &argnames, const std::string &name = evalctx->eval_arguments[i].first; const Value &val = evalctx->eval_arguments[i].second; if (name.empty()) { - if (posarg < argnames.size()) this->set_variable(argnames[posarg++], val); + if (posarg < args.size()) this->set_variable(args[posarg++].first, val); } else { this->set_variable(name, val); } @@ -158,8 +156,8 @@ void Context::dump(const AbstractModule *mod, const ModuleInstantiation *inst) const Module *m = dynamic_cast(mod); if (m) { PRINT(" module args:"); - BOOST_FOREACH(const std::string &arg, m->argnames) { - PRINTB(" %s = %s", arg % variables[arg]); + BOOST_FOREACH(const Assignment &arg, m->definition_arguments) { + PRINTB(" %s = %s", arg.first % variables[arg.first]); } } } diff --git a/src/context.h b/src/context.h index 282a940..51fc45c 100644 --- a/src/context.h +++ b/src/context.h @@ -5,6 +5,7 @@ #include #include #include "value.h" +#include "typedefs.h" class Context { @@ -15,8 +16,7 @@ public: virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const; virtual class AbstractNode *evaluate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const; - void setVariables(const std::vector &argnames, - const std::vector &argexpr, + void setVariables(const AssignmentList &args, const class EvalContext *evalctx = NULL); void set_variable(const std::string &name, const Value &value); diff --git a/src/control.cc b/src/control.cc index 446e47e..d47eec0 100644 --- a/src/control.cc +++ b/src/control.cc @@ -140,7 +140,7 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat { std::stringstream msg; msg << "ECHO: "; - for (size_t i = 0; i < inst->argnames.size(); i++) { + for (size_t i = 0; i < inst->arguments.size(); i++) { if (i > 0) msg << ", "; if (!evalctx->eval_arguments[i].first.empty()) msg << evalctx->eval_arguments[i].first << " = "; msg << evalctx->eval_arguments[i].second; diff --git a/src/evalcontext.cc b/src/evalcontext.cc index 39e5aae..b7566e3 100644 --- a/src/evalcontext.cc +++ b/src/evalcontext.cc @@ -31,8 +31,8 @@ void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *ins const Module *m = dynamic_cast(mod); if (m) { PRINT(" module args:"); - BOOST_FOREACH(const std::string &arg, m->argnames) { - PRINTB(" %s = %s", arg % variables[arg]); + BOOST_FOREACH(const Assignment &arg, m->definition_arguments) { + PRINTB(" %s = %s", arg.first % variables[arg.first]); } } } diff --git a/src/expr.cc b/src/expr.cc index 1d7b440..7a8180f 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -128,9 +128,9 @@ Value Expression::evaluate(const Context *context) const } if (this->type == "F") { EvalContext c(context); - for (size_t i=0; i < this->children.size(); i++) { - c.eval_arguments.push_back(std::make_pair(this->call_argnames[i], - this->children[i]->evaluate(context))); + for (size_t i=0; i < this->call_arguments.size(); i++) { + c.eval_arguments.push_back(std::make_pair(this->call_arguments[i].first, + this->call_arguments[i].second->evaluate(context))); } // Value::VectorType argvalues; // std::transform(this->children.begin(), this->children.end(), @@ -183,10 +183,11 @@ std::string Expression::toString() const } else if (this->type == "F") { stream << this->call_funcname << "("; - for (size_t i=0; i < this->children.size(); i++) { + for (size_t i=0; i < this->call_arguments.size(); i++) { + const Assignment &arg = this->call_arguments[i]; if (i > 0) stream << ", "; - if (!this->call_argnames[i].empty()) stream << this->call_argnames[i] << " = "; - stream << *this->children[i]; + if (!arg.first.empty()) stream << arg.first << " = "; + stream << *arg.second; } stream << ")"; } diff --git a/src/expression.h b/src/expression.h index 2919b78..06becc0 100644 --- a/src/expression.h +++ b/src/expression.h @@ -4,6 +4,7 @@ #include #include #include "value.h" +#include "typedefs.h" class Expression { @@ -14,7 +15,7 @@ public: std::string var_name; std::string call_funcname; - std::vector call_argnames; + AssignmentList call_arguments; // Boolean: ! && || // Operators: * / % + - diff --git a/src/func.cc b/src/func.cc index ecd1f87..f2c9835 100644 --- a/src/func.cc +++ b/src/func.cc @@ -34,6 +34,7 @@ #include #include "stl-utils.h" #include "printutils.h" +#include /* Random numbers @@ -75,14 +76,14 @@ std::string AbstractFunction::dump(const std::string &indent, const std::string Function::~Function() { - std::for_each(this->argexpr.begin(), this->argexpr.end(), del_fun()); + BOOST_FOREACH(const Assignment &arg, this->definition_arguments) delete arg.second; delete expr; } Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const { Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(definition_arguments, evalctx); return expr ? expr->evaluate(&c) : Value(); } @@ -90,10 +91,11 @@ std::string Function::dump(const std::string &indent, const std::string &name) c { std::stringstream dump; dump << indent << "function " << name << "("; - for (size_t i=0; i < argnames.size(); i++) { + for (size_t i=0; i < definition_arguments.size(); i++) { + const Assignment &arg = definition_arguments[i]; if (i > 0) dump << ", "; - dump << argnames[i]; - if (argexpr[i]) dump << " = " << *argexpr[i]; + dump << arg.first; + if (arg.second) dump << " = " << *arg.second; } dump << ") = " << *expr << ";\n"; return dump.str(); diff --git a/src/function.h b/src/function.h index bd7c329..a1fde3c 100644 --- a/src/function.h +++ b/src/function.h @@ -2,6 +2,7 @@ #define FUNCTION_H_ #include "value.h" +#include "typedefs.h" #include #include @@ -29,8 +30,7 @@ public: class Function : public AbstractFunction { public: - std::vector argnames; - std::vector argexpr; + AssignmentList definition_arguments; Expression *expr; diff --git a/src/import.cc b/src/import.cc index 283bbe6..ba42b0a 100644 --- a/src/import.cc +++ b/src/import.cc @@ -65,20 +65,22 @@ public: AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { - std::vector argnames; - argnames += "file", "layer", "convexity", "origin", "scale"; - std::vector argexpr; + AssignmentList args; + args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("convexity", NULL), Assignment("origin", NULL), Assignment("scale", NULL); + // FIXME: This is broken. Tag as deprecated and fix // Map old argnames to new argnames for compatibility +#if 0 std::vector inst_argnames = inst->argnames; for (size_t i=0; idocumentPath()); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); #if 0 && DEBUG c.dump(this, inst); #endif diff --git a/src/lexer.l b/src/lexer.l index 4dff654..6766abc 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -26,6 +26,7 @@ %{ +#include "typedefs.h" #include "handle_dep.h" #include "printutils.h" #include "parsersettings.h" diff --git a/src/linearextrude.cc b/src/linearextrude.cc index de728f7..f4c1112 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -52,12 +52,11 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst { LinearExtrudeNode *node = new LinearExtrudeNode(inst); - std::vector argnames; - argnames += "file", "layer", "height", "origin", "scale", "center", "twist", "slices"; - std::vector argexpr; + AssignmentList args; + args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("height", NULL), Assignment("origin", NULL), Assignment("scale", NULL), Assignment("center", NULL), Assignment("twist", NULL), Assignment("slices", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); diff --git a/src/modcontext.cc b/src/modcontext.cc index 3280108..7d123b8 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -26,7 +26,7 @@ ModuleContext::~ModuleContext() void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) { - this->setVariables(module.argnames, module.argexpr, evalctx); + this->setVariables(module.definition_arguments, evalctx); this->evalctx = evalctx; // FIXME: Don't access module members directly @@ -131,8 +131,8 @@ void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *i const Module *m = dynamic_cast(mod); if (m) { PRINT(" module args:"); - BOOST_FOREACH(const std::string &arg, m->argnames) { - PRINTB(" %s = %s", arg % variables[arg]); + BOOST_FOREACH(const Assignment &arg, m->definition_arguments) { + PRINTB(" %s = %s", arg.first % variables[arg.first]); } } } diff --git a/src/module.cc b/src/module.cc index d1e574d..7d83975 100644 --- a/src/module.cc +++ b/src/module.cc @@ -62,8 +62,8 @@ std::string AbstractModule::dump(const std::string &indent, const std::string &n ModuleInstantiation::~ModuleInstantiation() { - BOOST_FOREACH (Expression *v, argexpr) delete v; - BOOST_FOREACH (ModuleInstantiation *v, children) delete v; + BOOST_FOREACH(const Assignment &arg, this->arguments) delete arg.second; + BOOST_FOREACH(ModuleInstantiation *v, children) delete v; } IfElseModuleInstantiation::~IfElseModuleInstantiation() @@ -89,10 +89,11 @@ std::string ModuleInstantiation::dump(const std::string &indent) const std::stringstream dump; dump << indent; dump << modname + "("; - for (size_t i=0; i < argnames.size(); i++) { + for (size_t i=0; i < this->arguments.size(); i++) { + const Assignment &arg = this->arguments[i]; if (i > 0) dump << ", "; - if (!argnames[i].empty()) dump << argnames[i] << " = "; - dump << *argexpr[i]; + if (!arg.first.empty()) dump << arg.first << " = "; + dump << *arg.second; } if (children.size() == 0) { dump << ");\n"; @@ -112,10 +113,10 @@ std::string ModuleInstantiation::dump(const std::string &indent) const AbstractNode *ModuleInstantiation::evaluate_instance(const Context *ctx) const { EvalContext c(ctx); - for (size_t i=0; ievaluate(ctx) : + BOOST_FOREACH(const Assignment &arg, this->arguments) { + c.eval_arguments.push_back(std::make_pair(arg.first, + arg.second ? + arg.second->evaluate(ctx) : Value())); } c.children = this->children; @@ -150,7 +151,7 @@ std::vector IfElseModuleInstantiation::evaluateElseChildren(const Module::~Module() { - BOOST_FOREACH (const AssignmentContainer::value_type &v, assignments) delete v.second; + BOOST_FOREACH (const Assignment &v, assignments) delete v.second; BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; BOOST_FOREACH (ModuleInstantiation *v, children) delete v; @@ -181,10 +182,11 @@ std::string Module::dump(const std::string &indent, const std::string &name) con std::string tab; if (!name.empty()) { dump << indent << "module " << name << "("; - for (size_t i=0; i < argnames.size(); i++) { + for (size_t i=0; i < this->definition_arguments.size(); i++) { + const Assignment &arg = this->definition_arguments[i]; if (i > 0) dump << ", "; - dump << argnames[i]; - if (argexpr[i]) dump << " = " << *argexpr[i]; + dump << arg.first; + if (arg.second) dump << " = " << *arg.second; } dump << ") {\n"; tab = "\t"; diff --git a/src/module.h b/src/module.h index 17f0c59..ace3c1b 100644 --- a/src/module.h +++ b/src/module.h @@ -6,6 +6,7 @@ #include #include #include "value.h" +#include "typedefs.h" class ModuleInstantiation { @@ -27,8 +28,7 @@ public: bool isHighlight() const { return this->tag_highlight; } bool isRoot() const { return this->tag_root; } - std::vector argnames; - std::vector argexpr; + AssignmentList arguments; std::vector children; bool tag_root; @@ -81,8 +81,8 @@ public: bool handleDependencies(); std::list assignments_var; - typedef boost::unordered_map AssignmentContainer; - AssignmentContainer assignments; + typedef boost::unordered_map AssignmentMap; + AssignmentMap assignments; typedef boost::unordered_map FunctionContainer; FunctionContainer functions; @@ -91,8 +91,7 @@ public: std::vector children; - std::vector argnames; - std::vector argexpr; + std::vector definition_arguments; protected: diff --git a/src/parser.y b/src/parser.y index 26bdba6..9b4f888 100644 --- a/src/parser.y +++ b/src/parser.y @@ -34,6 +34,7 @@ #include #endif +#include "typedefs.h" #include "module.h" #include "expression.h" #include "value.h" @@ -64,17 +65,6 @@ extern const char *parser_input_buffer; const char *parser_input_buffer; std::string parser_source_path; -class ArgContainer { -public: - std::string argname; - Expression *argexpr; -}; -class ArgsContainer { -public: - std::vector argnames; - std::vector argexpr; -}; - %} %union { @@ -85,8 +75,8 @@ public: class ModuleInstantiation *inst; std::vector *instvec; class IfElseModuleInstantiation *ifelse; - class ArgContainer *arg; - class ArgsContainer *args; + Assignment *arg; + AssignmentList *args; } %token TOK_MODULE @@ -168,8 +158,7 @@ statement: module_stack.push_back(currmodule); currmodule = new Module(); p->modules[$2] = currmodule; - currmodule->argnames = $4->argnames; - currmodule->argexpr = $4->argexpr; + currmodule->definition_arguments = *$4; free($2); delete $4; } statement { @@ -178,8 +167,7 @@ statement: } | TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { Function *func = new Function(); - func->argnames = $4->argnames; - func->argexpr = $4->argexpr; + func->definition_arguments = *$4; func->expr = $8; currmodule->functions[$2] = func; free($2); @@ -201,8 +189,7 @@ children_instantiation: if_statement: TOK_IF '(' expr ')' children_instantiation { $$ = new IfElseModuleInstantiation(); - $$->argnames.push_back(""); - $$->argexpr.push_back($3); + $$->arguments.push_back(Assignment("", $3)); $$->setPath(parser_source_path); if ($$) { @@ -279,8 +266,7 @@ module_instantiation_list: single_module_instantiation: TOK_ID '(' arguments_call ')' { $$ = new ModuleInstantiation($1); - $$->argnames = $3->argnames; - $$->argexpr = $3->argexpr; + $$->arguments = *$3; $$->setPath(parser_source_path); free($1); delete $3; @@ -448,8 +434,7 @@ expr: $$ = new Expression(); $$->type = "F"; $$->call_funcname = $1; - $$->call_argnames = $3->argnames; - $$->children = $3->argexpr; + $$->call_arguments = *$3; free($1); delete $3; } ; @@ -470,61 +455,50 @@ vector_expr: arguments_decl: /* empty */ { - $$ = new ArgsContainer(); + $$ = new AssignmentList(); } | argument_decl { - $$ = new ArgsContainer(); - $$->argnames.push_back($1->argname); - $$->argexpr.push_back($1->argexpr); + $$ = new AssignmentList(); + $$->push_back(*$1); delete $1; } | arguments_decl ',' optional_commas argument_decl { $$ = $1; - $$->argnames.push_back($4->argname); - $$->argexpr.push_back($4->argexpr); + $$->push_back(*$4); delete $4; } ; argument_decl: TOK_ID { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = NULL; + $$ = new Assignment($1, NULL); free($1); } | TOK_ID '=' expr { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = $3; + $$ = new Assignment($1, $3); free($1); } ; arguments_call: /* empty */ { - $$ = new ArgsContainer(); + $$ = new AssignmentList(); } | argument_call { - $$ = new ArgsContainer(); - $$->argnames.push_back($1->argname); - $$->argexpr.push_back($1->argexpr); + $$ = new AssignmentList(); + $$->push_back(*$1); delete $1; } | arguments_call ',' optional_commas argument_call { $$ = $1; - $$->argnames.push_back($4->argname); - $$->argexpr.push_back($4->argexpr); + $$->push_back(*$4); delete $4; } ; argument_call: expr { - $$ = new ArgContainer(); - $$->argexpr = $1; + $$ = new Assignment("", $1); } | TOK_ID '=' expr { - $$ = new ArgContainer(); - $$->argname = $1; - $$->argexpr = $3; + $$ = new Assignment($1, $3); free($1); } ; diff --git a/src/primitives.cc b/src/primitives.cc index 40e7e0b..184b40c 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -112,37 +112,36 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti node->center = false; node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1; - std::vector argnames; - std::vector argexpr; + AssignmentList args; switch (this->type) { case CUBE: - argnames += "size", "center"; + args += Assignment("size", NULL), Assignment("center", NULL); break; case SPHERE: - argnames += "r"; + args += Assignment("r", NULL); break; case CYLINDER: - argnames += "h", "r1", "r2", "center"; + args += Assignment("h", NULL), Assignment("r1", NULL), Assignment("r2", NULL), Assignment("center", NULL); break; case POLYHEDRON: - argnames += "points", "triangles", "convexity"; + args += Assignment("points", NULL), Assignment("triangles", NULL), Assignment("convexity", NULL); break; case SQUARE: - argnames += "size", "center"; + args += Assignment("size", NULL), Assignment("center", NULL); break; case CIRCLE: - argnames += "r"; + args += Assignment("r", NULL); break; case POLYGON: - argnames += "points", "paths", "convexity"; + args += Assignment("points", NULL), Assignment("paths", NULL), Assignment("convexity", NULL); break; default: assert(false && "PrimitiveModule::evaluate(): Unknown node type"); } Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); diff --git a/src/projection.cc b/src/projection.cc index 46add48..eeed411 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -48,12 +48,11 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant { ProjectionNode *node = new ProjectionNode(inst); - std::vector argnames; - argnames += "cut"; - std::vector argexpr; + AssignmentList args; + args += Assignment("cut", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); Value convexity = c.lookup_variable("convexity", true); Value cut = c.lookup_variable("cut", true); diff --git a/src/render.cc b/src/render.cc index 855e5e3..bb08c0c 100644 --- a/src/render.cc +++ b/src/render.cc @@ -45,12 +45,11 @@ AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiati { RenderNode *node = new RenderNode(inst); - std::vector argnames; - argnames += "convexity"; - std::vector argexpr; + AssignmentList args; + args += Assignment("convexity", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); Value v = c.lookup_variable("convexity"); if (v.type() == Value::NUMBER) diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 29a873f..b6edb8b 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -52,12 +52,11 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst { RotateExtrudeNode *node = new RotateExtrudeNode(inst); - std::vector argnames; - argnames += "file", "layer", "origin", "scale"; - std::vector argexpr; + AssignmentList args; + args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("origin", NULL), Assignment("scale", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); node->fn = c.lookup_variable("$fn").toDouble(); node->fs = c.lookup_variable("$fs").toDouble(); diff --git a/src/surface.cc b/src/surface.cc index 22da93d..d8fa422 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -75,12 +75,11 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat node->center = false; node->convexity = 1; - std::vector argnames; - argnames += "file", "center", "convexity"; - std::vector argexpr; + AssignmentList args; + args += Assignment("file", NULL), Assignment("center", NULL), Assignment("convexity", NULL); Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); Value fileval = c.lookup_variable("file"); node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); diff --git a/src/transform.cc b/src/transform.cc index 6246a59..cc026fb 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -59,31 +59,30 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti node->matrix = Transform3d::Identity(); - std::vector argnames; - std::vector argexpr; + AssignmentList args; switch (this->type) { case SCALE: - argnames += "v"; + args += Assignment("v", NULL); break; case ROTATE: - argnames += "a", "v"; + args += Assignment("a", NULL), Assignment("v", NULL); break; case MIRROR: - argnames += "v"; + args += Assignment("v", NULL); break; case TRANSLATE: - argnames += "v"; + args += Assignment("v", NULL); break; case MULTMATRIX: - argnames += "m"; + args += Assignment("m", NULL); break; default: assert(false); } Context c(ctx); - c.setVariables(argnames, argexpr, evalctx); + c.setVariables(args, evalctx); if (this->type == SCALE) { diff --git a/src/typedefs.h b/src/typedefs.h new file mode 100644 index 0000000..a6e9077 --- /dev/null +++ b/src/typedefs.h @@ -0,0 +1,10 @@ +#ifndef TYPEDEFS_H_ +#define TYPEDEFS_H_ + +#include +#include + +typedef std::pair Assignment; +typedef std::vector AssignmentList; + +#endif -- cgit v0.10.1 From d4d3e7456fdc32d56ec500fcf2fd0fd1a09b54ab Mon Sep 17 00:00:00 2001 From: don bright Date: Thu, 18 Apr 2013 17:23:08 -0700 Subject: fix bug report in clang detect reported by Marius Kintel diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55b6924..d178f0f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -97,7 +97,7 @@ endif() # Clang compiler -if(CMAKE_CXX_COMPILER MATCHES ".*clang.*") +if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*") # disable enormous amount of warnings about CGAL set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") @@ -354,7 +354,7 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6) endif() inclusion(CGAL_DIR CGAL_INCLUDE_DIRS) -if(CMAKE_CXX_COMPILER MATCHES ".*clang.*" AND NOT STREQUAL ${CGAL_CXX_FLAGS_INIT} "" ) +if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" ) string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) endif() -- cgit v0.10.1 From ea0d71329a84dbfb4ea38c0a2f9874afebe006fd Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 18 Apr 2013 21:51:46 -0400 Subject: Added bugfix hints. Related to #116 diff --git a/src/import.cc b/src/import.cc index 40468cc..c9a2b91 100644 --- a/src/import.cc +++ b/src/import.cc @@ -70,6 +70,10 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati // FIXME: This is broken. Tag as deprecated and fix // Map old argnames to new argnames for compatibility + // To fix: + // o after c.setVariables() + // - if "filename" in evalctx: deprecated-warning && v.set_variable("file", value); + // - if "layername" in evalctx: deprecated-warning && v.set_variable("layer", value); #if 0 std::vector inst_argnames = inst->argnames; for (size_t i=0; i Date: Thu, 18 Apr 2013 23:42:09 -0300 Subject: Update README.md diff --git a/README.md b/README.md index c2acded..d7560de 100644 --- a/README.md +++ b/README.md @@ -108,8 +108,7 @@ This will download the latest sources into a directory named 'openscad'. To pull the MCAD library (http://reprap.org/wiki/MCAD), do the following: cd openscad - git submodule init - git submodule update + git submodule update --init ### Building for Mac OS X -- cgit v0.10.1 From eb60b5f9377b71115741d9632f9b62f77c441dbc Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 19 Apr 2013 15:57:11 -0400 Subject: Tag search failures as warnings diff --git a/src/func.cc b/src/func.cc index 791e957..26d7e69 100644 --- a/src/func.cc +++ b/src/func.cc @@ -449,7 +449,7 @@ Value builtin_search(const Context *, const std::vector&, const std if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) break; } } - if (matchCount == 0) PRINTB(" search term not found: \"%s\"", findThis.toString()[i]); + if (matchCount == 0) PRINTB(" WARNING: search term not found: \"%s\"", findThis.toString()[i]); if (num_returns_per_match == 0 || num_returns_per_match > 1) { returnvec.push_back(Value(resultvec)); } @@ -478,10 +478,10 @@ Value builtin_search(const Context *, const std::vector&, const std } if (num_returns_per_match == 1 && matchCount == 0) { if (findThis.toVector()[i].type() == Value::NUMBER) { - PRINTB(" search term not found: %s",findThis.toVector()[i].toDouble()); + PRINTB(" WARNING: search term not found: %s",findThis.toVector()[i].toDouble()); } else if (findThis.toVector()[i].type() == Value::STRING) { - PRINTB(" search term not found: \"%s\"",findThis.toVector()[i].toString()); + PRINTB(" WARNING: search term not found: \"%s\"",findThis.toVector()[i].toString()); } returnvec.push_back(Value(resultvec)); } @@ -490,7 +490,7 @@ Value builtin_search(const Context *, const std::vector&, const std } } } else { - PRINTB(" search: none performed on input %s", findThis); + PRINTB(" WARNING: search: none performed on input %s", findThis); return Value(); } return Value(returnvec); diff --git a/tests/regression/echotest/search-tests-expected.txt b/tests/regression/echotest/search-tests-expected.txt index 64df0b6..0269f43 100644 --- a/tests/regression/echotest/search-tests-expected.txt +++ b/tests/regression/echotest/search-tests-expected.txt @@ -1,9 +1,9 @@ - search term not found: "q" - search term not found: 1000 - search term not found: "zzz" - search term not found: "zzz" - search term not found: 500 - search term not found: "" + WARNING: search term not found: "q" + WARNING: search term not found: 1000 + WARNING: search term not found: "zzz" + WARNING: search term not found: "zzz" + WARNING: search term not found: 500 + WARNING: search term not found: "" ECHO: "Characters in string (\"a\"): [0]" ECHO: "Characters in string (\"adeq\"): [[0, 5], [3, 8], [4], []]" ECHO: "Default string search (\"abe\"): [0, 1, 8]" -- cgit v0.10.1 From 2e37c07f08af9ae548e0c6e42686ac4f317e89e0 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 20 Apr 2013 14:08:04 -0700 Subject: fix eigen2 building bug rept by Roland Hieber diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index 7c483cb..6ad9e4d 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -206,9 +206,11 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node) bb = bounding_box( *N.p3 ); } - Eigen::Matrix scale, bbox_size; - scale << 1,1,1; - bbox_size << bb.xmax()-bb.xmin(), bb.ymax()-bb.ymin(), bb.zmax()-bb.zmin(); + std::vector scale, bbox_size; + for (int i=0;i<3;i++) scale.push_back( NT(1) ); + bbox_size.push_back( bb.xmax()-bb.xmin() ); + bbox_size.push_back( bb.ymax()-bb.ymin() ); + bbox_size.push_back( bb.zmax()-bb.zmin() ); for (int i=0;i<3;i++) { if (node.newsize[i]) { if (bbox_size[i]==NT(0)) { @@ -220,7 +222,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node) } } } - NT autoscale = scale.maxCoeff(); + NT autoscale = std::max( scale[0], std::max( scale[1], scale[2] )); for (int i=0;i<3;i++) { if (node.autosize[i]) scale[i] = autoscale; } -- cgit v0.10.1 From 6a87dd5cfa0a272f978e1b22ca59f1c8c55505a7 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 20 Apr 2013 14:24:39 -0700 Subject: accept 'layername' and 'filename' in import, WARNING deprecation diff --git a/src/import.cc b/src/import.cc index c9a2b91..927c9d8 100644 --- a/src/import.cc +++ b/src/import.cc @@ -67,6 +67,7 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati { AssignmentList args; args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("convexity", NULL), Assignment("origin", NULL), Assignment("scale", NULL); + args += Assignment("filename",NULL), Assignment("layername", NULL); // FIXME: This is broken. Tag as deprecated and fix // Map old argnames to new argnames for compatibility @@ -90,6 +91,12 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati #endif Value v = c.lookup_variable("file"); + if (v.isUndefined()) { + v = c.lookup_variable("filename"); + if (!v.isUndefined()) + PRINT("WARNING: filename= is deprecated. Please use file="); + } + std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { @@ -108,6 +115,11 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati node->filename = filename; Value layerval = c.lookup_variable("layer", true); + if (layerval.isUndefined()) { + layerval = c.lookup_variable("layername",true); + if (!layerval.isUndefined()) + PRINT("WARNING: layername= is deprecated. Please use layer="); + } node->layername = layerval.isUndefined() ? "" : layerval.toString(); node->convexity = c.lookup_variable("convexity", true).toDouble(); -- cgit v0.10.1 From d0bd89e6a0e87a7b9bf454404328af735b4c01d7 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 22 Apr 2013 13:35:05 -0400 Subject: We cannot target 10.5 while building on Mountain lion due to a compiler/sdk incompatibility. This should fix the build error by selecting 10.6 as a build target. Fixes #335 diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 3687041..2d0aaa4 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -29,6 +29,7 @@ OPTION_LLVM=false OPTION_CLANG=false OPTION_GCC=false DETECTED_LION=false +DETECTED_MOUNTAIN_LION=false export QMAKESPEC=macx-g++ printUsage() @@ -371,11 +372,14 @@ do done OSVERSION=`sw_vers -productVersion | cut -d. -f2` -if [[ $OSVERSION -ge 7 ]]; then - echo "Detected Lion or later" +if [[ $OSVERSION -ge 8 ]]; then + echo "Detected Mountain Lion (10.8) or later" + DETECTED_MOUNTAIN_LION=true +elif [[ $OSVERSION -ge 7 ]]; then + echo "Detected Lion (10.7) or later" DETECTED_LION=true else - echo "Detected Snow Leopard or earlier" + echo "Detected Snow Leopard (10.6) or earlier" fi USING_LLVM=false @@ -411,6 +415,20 @@ elif $USING_CLANG; then export QMAKESPEC=unsupported/macx-clang fi +if $DETECTED_MOUNTAIN_LION; then + echo "Setting build target to 10.6 or later" + MAC_OSX_VERSION_MIN=10.6 +else + echo "Setting build target to 10.5 or later" + MAC_OSX_VERSION_MIN=10.5 +fi + +if $OPTION_32BIT; then + echo "Building combined 32/64-bit binaries" +else + echo "Building 64-bit binaries" +fi + echo "Using basedir:" $BASEDIR mkdir -p $SRCDIR $DEPLOYDIR build_qt 4.8.4 -- cgit v0.10.1 From 8bcb17ddfba83e228b66dad812317b291e8c8fc5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 22 Apr 2013 13:48:23 -0400 Subject: Build 32-bit binaries only in deployment mode diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 2d0aaa4..d1b1a63 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -28,6 +28,7 @@ OPTION_32BIT=true OPTION_LLVM=false OPTION_CLANG=false OPTION_GCC=false +OPTION_DEPLOY=false DETECTED_LION=false DETECTED_MOUNTAIN_LION=false export QMAKESPEC=macx-g++ @@ -423,6 +424,12 @@ else MAC_OSX_VERSION_MIN=10.5 fi +if $OPTION_DEPLOY; then + echo "Building deployment version of libraries" +else + OPTION_32BIT=false +fi + if $OPTION_32BIT; then echo "Building combined 32/64-bit binaries" else -- cgit v0.10.1 From f0ee85e17d474ab9119f82ee6f802d4634743b12 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 22 Apr 2013 15:18:36 -0400 Subject: Better OX version check diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index d1b1a63..f3fbc2b 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -29,8 +29,6 @@ OPTION_LLVM=false OPTION_CLANG=false OPTION_GCC=false OPTION_DEPLOY=false -DETECTED_LION=false -DETECTED_MOUNTAIN_LION=false export QMAKESPEC=macx-g++ printUsage() @@ -372,13 +370,11 @@ do esac done -OSVERSION=`sw_vers -productVersion | cut -d. -f2` -if [[ $OSVERSION -ge 8 ]]; then +OSX_VERSION=`sw_vers -productVersion | cut -d. -f2` +if (( $OSX_VERSION >= 8 )); then echo "Detected Mountain Lion (10.8) or later" - DETECTED_MOUNTAIN_LION=true -elif [[ $OSVERSION -ge 7 ]]; then +elif (( $OSX_VERSION >= 7 )); then echo "Detected Lion (10.7) or later" - DETECTED_LION=true else echo "Detected Snow Leopard (10.6) or earlier" fi @@ -392,7 +388,7 @@ elif $OPTION_GCC; then USING_GCC=true elif $OPTION_CLANG; then USING_CLANG=true -elif $DETECTED_LION; then +elif (( $OSX_VERSION >= 7 )); then USING_GCC=true fi @@ -416,7 +412,7 @@ elif $USING_CLANG; then export QMAKESPEC=unsupported/macx-clang fi -if $DETECTED_MOUNTAIN_LION; then +if (( $OSX_VERSION >= 8 )); then echo "Setting build target to 10.6 or later" MAC_OSX_VERSION_MIN=10.6 else -- cgit v0.10.1 From a96f3f3c67d496279151cd3fff47589b8684c378 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 26 Apr 2013 17:37:59 -0400 Subject: Gave up on tabs. The only change is indentation diff --git a/src/parser.y b/src/parser.y index 9b4f888..fd6b164 100644 --- a/src/parser.y +++ b/src/parser.y @@ -44,39 +44,39 @@ #include #include -namespace fs = boost::filesystem; + namespace fs = boost::filesystem; #include "boosty.h" -int parser_error_pos = -1; + int parser_error_pos = -1; -int parserlex(void); -void yyerror(char const *s); + int parserlex(void); + void yyerror(char const *s); -int lexerget_lineno(void); -int lexerlex_destroy(void); -int lexerlex(void); + int lexerget_lineno(void); + int lexerlex_destroy(void); + int lexerlex(void); -std::vector module_stack; -Module *currmodule; + std::vector module_stack; + Module *currmodule; -extern void lexerdestroy(); -extern FILE *lexerin; -extern const char *parser_input_buffer; -const char *parser_input_buffer; -std::string parser_source_path; + extern void lexerdestroy(); + extern FILE *lexerin; + extern const char *parser_input_buffer; + const char *parser_input_buffer; + std::string parser_source_path; -%} + %} %union { - char *text; - double number; - class Value *value; - class Expression *expr; - class ModuleInstantiation *inst; - std::vector *instvec; - class IfElseModuleInstantiation *ifelse; - Assignment *arg; - AssignmentList *args; + char *text; + double number; + class Value *value; + class Expression *expr; + class ModuleInstantiation *inst; + std::vector *instvec; + class IfElseModuleInstantiation *ifelse; + Assignment *arg; + AssignmentList *args; } %token TOK_MODULE @@ -129,412 +129,412 @@ std::string parser_source_path; %% input: - /* empty */ | - TOK_USE { currmodule->usedlibs[$1] = NULL; } input | - statement input ; +/* empty */ | +TOK_USE { currmodule->usedlibs[$1] = NULL; } input | +statement input ; inner_input: - /* empty */ | - statement inner_input ; +/* empty */ | +statement inner_input ; statement: - ';' | - '{' inner_input '}' | - module_instantiation { - if ($1) { - currmodule->addChild($1); - } else { - delete $1; - } - } | - TOK_ID '=' expr ';' { - std::list::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1); - if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found); - currmodule->assignments_var.push_back($1); - currmodule->assignments[$1] = $3; - } | - TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { - Module *p = currmodule; - module_stack.push_back(currmodule); - currmodule = new Module(); - p->modules[$2] = currmodule; - currmodule->definition_arguments = *$4; - free($2); - delete $4; - } statement { - currmodule = module_stack.back(); - module_stack.pop_back(); - } | - TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { - Function *func = new Function(); - func->definition_arguments = *$4; - func->expr = $8; - currmodule->functions[$2] = func; - free($2); - delete $4; - } ';' ; +';' | +'{' inner_input '}' | +module_instantiation { + if ($1) { + currmodule->addChild($1); + } else { + delete $1; + } +} | +TOK_ID '=' expr ';' { + std::list::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1); + if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found); + currmodule->assignments_var.push_back($1); + currmodule->assignments[$1] = $3; +} | +TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { + Module *p = currmodule; + module_stack.push_back(currmodule); + currmodule = new Module(); + p->modules[$2] = currmodule; + currmodule->definition_arguments = *$4; + free($2); + delete $4; +} statement { + currmodule = module_stack.back(); + module_stack.pop_back(); + } | + TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { + Function *func = new Function(); + func->definition_arguments = *$4; + func->expr = $8; + currmodule->functions[$2] = func; + free($2); + delete $4; + } ';' ; /* Will return a dummy parent node with zero or more children */ children_instantiation: - module_instantiation { - $$ = new std::vector; - if ($1) { - $$->push_back($1); - } - } | - '{' module_instantiation_list '}' { - $$ = $2; - } ; +module_instantiation { + $$ = new std::vector; + if ($1) { + $$->push_back($1); + } +} | +'{' module_instantiation_list '}' { + $$ = $2; +} ; if_statement: - TOK_IF '(' expr ')' children_instantiation { - $$ = new IfElseModuleInstantiation(); - $$->arguments.push_back(Assignment("", $3)); - $$->setPath(parser_source_path); - - if ($$) { - $$->children = *$5; - } else { - for (size_t i = 0; i < $5->size(); i++) - delete (*$5)[i]; - } - delete $5; - } ; +TOK_IF '(' expr ')' children_instantiation { + $$ = new IfElseModuleInstantiation(); + $$->arguments.push_back(Assignment("", $3)); + $$->setPath(parser_source_path); + + if ($$) { + $$->children = *$5; + } else { + for (size_t i = 0; i < $5->size(); i++) + delete (*$5)[i]; + } + delete $5; +} ; ifelse_statement: - if_statement { - $$ = $1; - } | - if_statement TOK_ELSE children_instantiation { - $$ = $1; - if ($$) { - $$->else_children = *$3; - } else { - for (size_t i = 0; i < $3->size(); i++) - delete (*$3)[i]; - } - delete $3; - } ; +if_statement { + $$ = $1; +} | +if_statement TOK_ELSE children_instantiation { + $$ = $1; + if ($$) { + $$->else_children = *$3; + } else { + for (size_t i = 0; i < $3->size(); i++) + delete (*$3)[i]; + } + delete $3; +} ; module_instantiation: - '!' module_instantiation { - $$ = $2; - if ($$) $$->tag_root = true; - } | - '#' module_instantiation { - $$ = $2; - if ($$) $$->tag_highlight = true; - } | - '%' module_instantiation { - $$ = $2; - if ($$) $$->tag_background = true; - } | - '*' module_instantiation { - delete $2; - $$ = NULL; - } | - single_module_instantiation ';' { - $$ = $1; - } | - single_module_instantiation children_instantiation { - $$ = $1; - if ($$) { - $$->children = *$2; - } else { - for (size_t i = 0; i < $2->size(); i++) - delete (*$2)[i]; - } - delete $2; - } | - ifelse_statement { - $$ = $1; - } ; +'!' module_instantiation { + $$ = $2; + if ($$) $$->tag_root = true; +} | +'#' module_instantiation { + $$ = $2; + if ($$) $$->tag_highlight = true; +} | +'%' module_instantiation { + $$ = $2; + if ($$) $$->tag_background = true; +} | +'*' module_instantiation { + delete $2; + $$ = NULL; +} | +single_module_instantiation ';' { + $$ = $1; +} | +single_module_instantiation children_instantiation { + $$ = $1; + if ($$) { + $$->children = *$2; + } else { + for (size_t i = 0; i < $2->size(); i++) + delete (*$2)[i]; + } + delete $2; +} | +ifelse_statement { + $$ = $1; +} ; module_instantiation_list: - /* empty */ { - $$ = new std::vector; - } | - module_instantiation_list module_instantiation { - $$ = $1; - if ($$) { - if ($2) $$->push_back($2); - } else { - delete $2; - } - } ; +/* empty */ { + $$ = new std::vector; +} | +module_instantiation_list module_instantiation { + $$ = $1; + if ($$) { + if ($2) $$->push_back($2); + } else { + delete $2; + } +} ; single_module_instantiation: - TOK_ID '(' arguments_call ')' { - $$ = new ModuleInstantiation($1); - $$->arguments = *$3; - $$->setPath(parser_source_path); - free($1); - delete $3; - } +TOK_ID '(' arguments_call ')' { + $$ = new ModuleInstantiation($1); + $$->arguments = *$3; + $$->setPath(parser_source_path); + free($1); + delete $3; +} expr: - TOK_TRUE { - $$ = new Expression(Value(true)); - } | - TOK_FALSE { - $$ = new Expression(Value(false)); - } | - TOK_UNDEF { - $$ = new Expression(Value::undefined); - } | - TOK_ID { - $$ = new Expression(); - $$->type = "L"; - $$->var_name = $1; - free($1); - } | - expr '.' TOK_ID { - $$ = new Expression(); - $$->type = "N"; - $$->children.push_back($1); - $$->var_name = $3; - free($3); - } | - TOK_STRING { - $$ = new Expression(Value(std::string($1))); - free($1); - } | - TOK_NUMBER { - $$ = new Expression(Value($1)); - } | - '[' expr ':' expr ']' { - Expression *e_one = new Expression(Value(1.0)); - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back(e_one); - $$->children.push_back($4); - } | - '[' expr ':' expr ':' expr ']' { - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back($4); - $$->children.push_back($6); - } | - '[' optional_commas ']' { - $$ = new Expression(Value(Value::VectorType())); - } | - '[' vector_expr optional_commas ']' { - $$ = $2; - } | - expr '*' expr { - $$ = new Expression(); - $$->type = "*"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '/' expr { - $$ = new Expression(); - $$->type = "/"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '%' expr { - $$ = new Expression(); - $$->type = "%"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '+' expr { - $$ = new Expression(); - $$->type = "+"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '-' expr { - $$ = new Expression(); - $$->type = "-"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '<' expr { - $$ = new Expression(); - $$->type = "<"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr LE expr { - $$ = new Expression(); - $$->type = "<="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr EQ expr { - $$ = new Expression(); - $$->type = "=="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr NE expr { - $$ = new Expression(); - $$->type = "!="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr GE expr { - $$ = new Expression(); - $$->type = ">="; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr '>' expr { - $$ = new Expression(); - $$->type = ">"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr AND expr { - $$ = new Expression(); - $$->type = "&&"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - expr OR expr { - $$ = new Expression(); - $$->type = "||"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - '+' expr { - $$ = $2; - } | - '-' expr { - $$ = new Expression(); - $$->type = "I"; - $$->children.push_back($2); - } | - '!' expr { - $$ = new Expression(); - $$->type = "!"; - $$->children.push_back($2); - } | - '(' expr ')' { - $$ = $2; - } | - expr '?' expr ':' expr { - $$ = new Expression(); - $$->type = "?:"; - $$->children.push_back($1); - $$->children.push_back($3); - $$->children.push_back($5); - } | - expr '[' expr ']' { - $$ = new Expression(); - $$->type = "[]"; - $$->children.push_back($1); - $$->children.push_back($3); - } | - TOK_ID '(' arguments_call ')' { - $$ = new Expression(); - $$->type = "F"; - $$->call_funcname = $1; - $$->call_arguments = *$3; - free($1); - delete $3; - } ; +TOK_TRUE { + $$ = new Expression(Value(true)); +} | +TOK_FALSE { + $$ = new Expression(Value(false)); +} | +TOK_UNDEF { + $$ = new Expression(Value::undefined); +} | +TOK_ID { + $$ = new Expression(); + $$->type = "L"; + $$->var_name = $1; + free($1); +} | +expr '.' TOK_ID { + $$ = new Expression(); + $$->type = "N"; + $$->children.push_back($1); + $$->var_name = $3; + free($3); +} | +TOK_STRING { + $$ = new Expression(Value(std::string($1))); + free($1); +} | +TOK_NUMBER { + $$ = new Expression(Value($1)); +} | +'[' expr ':' expr ']' { + Expression *e_one = new Expression(Value(1.0)); + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back(e_one); + $$->children.push_back($4); +} | +'[' expr ':' expr ':' expr ']' { + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back($4); + $$->children.push_back($6); +} | +'[' optional_commas ']' { + $$ = new Expression(Value(Value::VectorType())); +} | +'[' vector_expr optional_commas ']' { + $$ = $2; +} | +expr '*' expr { + $$ = new Expression(); + $$->type = "*"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '/' expr { + $$ = new Expression(); + $$->type = "/"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '%' expr { + $$ = new Expression(); + $$->type = "%"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '+' expr { + $$ = new Expression(); + $$->type = "+"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '-' expr { + $$ = new Expression(); + $$->type = "-"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '<' expr { + $$ = new Expression(); + $$->type = "<"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr LE expr { + $$ = new Expression(); + $$->type = "<="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr EQ expr { + $$ = new Expression(); + $$->type = "=="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr NE expr { + $$ = new Expression(); + $$->type = "!="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr GE expr { + $$ = new Expression(); + $$->type = ">="; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr '>' expr { + $$ = new Expression(); + $$->type = ">"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr AND expr { + $$ = new Expression(); + $$->type = "&&"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +expr OR expr { + $$ = new Expression(); + $$->type = "||"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +'+' expr { + $$ = $2; +} | +'-' expr { + $$ = new Expression(); + $$->type = "I"; + $$->children.push_back($2); +} | +'!' expr { + $$ = new Expression(); + $$->type = "!"; + $$->children.push_back($2); +} | +'(' expr ')' { + $$ = $2; +} | +expr '?' expr ':' expr { + $$ = new Expression(); + $$->type = "?:"; + $$->children.push_back($1); + $$->children.push_back($3); + $$->children.push_back($5); +} | +expr '[' expr ']' { + $$ = new Expression(); + $$->type = "[]"; + $$->children.push_back($1); + $$->children.push_back($3); +} | +TOK_ID '(' arguments_call ')' { + $$ = new Expression(); + $$->type = "F"; + $$->call_funcname = $1; + $$->call_arguments = *$3; + free($1); + delete $3; +} ; optional_commas: - ',' optional_commas | ; +',' optional_commas | ; vector_expr: - expr { - $$ = new Expression(); - $$->type = 'V'; - $$->children.push_back($1); - } | - vector_expr ',' optional_commas expr { - $$ = $1; - $$->children.push_back($4); - } ; +expr { + $$ = new Expression(); + $$->type = 'V'; + $$->children.push_back($1); +} | +vector_expr ',' optional_commas expr { + $$ = $1; + $$->children.push_back($4); +} ; arguments_decl: - /* empty */ { - $$ = new AssignmentList(); - } | - argument_decl { - $$ = new AssignmentList(); - $$->push_back(*$1); - delete $1; - } | - arguments_decl ',' optional_commas argument_decl { - $$ = $1; - $$->push_back(*$4); - delete $4; - } ; +/* empty */ { + $$ = new AssignmentList(); +} | +argument_decl { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; +} | +arguments_decl ',' optional_commas argument_decl { + $$ = $1; + $$->push_back(*$4); + delete $4; +} ; argument_decl: - TOK_ID { - $$ = new Assignment($1, NULL); - free($1); - } | - TOK_ID '=' expr { - $$ = new Assignment($1, $3); - free($1); - } ; +TOK_ID { + $$ = new Assignment($1, NULL); + free($1); +} | +TOK_ID '=' expr { + $$ = new Assignment($1, $3); + free($1); +} ; arguments_call: - /* empty */ { - $$ = new AssignmentList(); - } | - argument_call { - $$ = new AssignmentList(); - $$->push_back(*$1); - delete $1; - } | - arguments_call ',' optional_commas argument_call { - $$ = $1; - $$->push_back(*$4); - delete $4; - } ; +/* empty */ { + $$ = new AssignmentList(); +} | +argument_call { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; +} | +arguments_call ',' optional_commas argument_call { + $$ = $1; + $$->push_back(*$4); + delete $4; +} ; argument_call: - expr { - $$ = new Assignment("", $1); - } | - TOK_ID '=' expr { - $$ = new Assignment($1, $3); - free($1); - } ; +expr { + $$ = new Assignment("", $1); +} | +TOK_ID '=' expr { + $$ = new Assignment($1, $3); + free($1); +} ; %% int parserlex(void) { - return lexerlex(); + return lexerlex(); } void yyerror (char const *s) { - // FIXME: We leak memory on parser errors... - PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); - currmodule = NULL; + // FIXME: We leak memory on parser errors... + PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); + currmodule = NULL; } Module *parse(const char *text, const char *path, int debug) { - lexerin = NULL; - parser_error_pos = -1; - parser_input_buffer = text; - parser_source_path = boosty::absolute(std::string(path)).string(); + lexerin = NULL; + parser_error_pos = -1; + parser_input_buffer = text; + parser_source_path = boosty::absolute(std::string(path)).string(); - module_stack.clear(); - Module *rootmodule = currmodule = new Module(); - rootmodule->setModulePath(path); - // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); + module_stack.clear(); + Module *rootmodule = currmodule = new Module(); + rootmodule->setModulePath(path); + // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); - parserdebug = debug; - int parserretval = parserparse(); - lexerdestroy(); - lexerlex_destroy(); + parserdebug = debug; + int parserretval = parserparse(); + lexerdestroy(); + lexerlex_destroy(); - if (parserretval != 0) return NULL; + if (parserretval != 0) return NULL; - parser_error_pos = -1; - return rootmodule; + parser_error_pos = -1; + return rootmodule; } -- cgit v0.10.1 From 64ed1eb9fe00e287d84b18830df86cc0de6b122a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 18 Apr 2013 21:42:33 -0400 Subject: Experiment: Lazy evaluation of argument lists in evaluation context. Allows e.g. for loop variables to be dependent on each other diff --git a/src/context.cc b/src/context.cc index 706407c..ea48dad 100644 --- a/src/context.cc +++ b/src/context.cc @@ -66,9 +66,9 @@ void Context::setVariables(const AssignmentList &args, if (evalctx) { size_t posarg = 0; - for (size_t i=0; ieval_arguments.size(); i++) { - const std::string &name = evalctx->eval_arguments[i].first; - const Value &val = evalctx->eval_arguments[i].second; + for (size_t i=0; inumArgs(); i++) { + const std::string &name = evalctx->getArgName(i); + const Value &val = evalctx->getArgValue(i); if (name.empty()) { if (posarg < args.size()) this->set_variable(args[posarg++].first, val); } else { diff --git a/src/control.cc b/src/control.cc index d47eec0..d45ee02 100644 --- a/src/control.cc +++ b/src/control.cc @@ -52,9 +52,9 @@ public: void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, const Context *ctx, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() > l) { - const std::string &it_name = evalctx->eval_arguments[l].first; - const Value &it_values = evalctx->eval_arguments[l].second; + if (evalctx->numArgs() > l) { + const std::string &it_name = evalctx->getArgName(l); + const Value &it_values = evalctx->getArgValue(l, ctx); Context c(ctx); if (it_values.type() == Value::RANGE) { Value::RangeType range = it_values.toRange(); @@ -93,9 +93,9 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (type == CHILD) { int n = 0; - if (evalctx->eval_arguments.size() > 0) { + if (evalctx->numArgs() > 0) { double v; - if (evalctx->eval_arguments[0].second.getDouble(v)) { + if (evalctx->getArgValue(0).getDouble(v)) { n = trunc(v); if (n < 0) { PRINTB("WARNING: Negative child index (%d) not allowed", n); @@ -114,14 +114,14 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat // assert(filectx->evalctx); if (filectx->evalctx) { - if (n < filectx->evalctx->children.size()) { - node = filectx->evalctx->children[n]->evaluate_instance(filectx->evalctx); + if (n < filectx->evalctx->numChildren()) { + node = filectx->evalctx->getChild(n)->evaluate_instance(filectx->evalctx); } else { // How to deal with negative objects in this case? // (e.g. first child of difference is invalid) PRINTB("WARNING: Child index (%d) out of bounds (%d children)", - n % filectx->evalctx->children.size()); + n % filectx->evalctx->numChildren()); } } return node; @@ -142,8 +142,8 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat msg << "ECHO: "; for (size_t i = 0; i < inst->arguments.size(); i++) { if (i > 0) msg << ", "; - if (!evalctx->eval_arguments[i].first.empty()) msg << evalctx->eval_arguments[i].first << " = "; - msg << evalctx->eval_arguments[i].second; + if (!evalctx->getArgName(i).empty()) msg << evalctx->getArgName(i) << " = "; + msg << evalctx->getArgValue(i); } PRINTB("%s", msg.str()); } @@ -151,9 +151,9 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (type == ASSIGN) { Context c(evalctx); - for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { - if (!evalctx->eval_arguments[i].first.empty()) - c.set_variable(evalctx->eval_arguments[i].first, evalctx->eval_arguments[i].second); + for (size_t i = 0; i < evalctx->numArgs(); i++) { + if (!evalctx->getArgName(i).empty()) + c.set_variable(evalctx->getArgName(i), evalctx->getArgValue(i)); } std::vector evaluatednodes = inst->evaluateChildren(&c); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); @@ -167,7 +167,7 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (type == IF) { const IfElseModuleInstantiation *ifelse = dynamic_cast(inst); - if (evalctx->eval_arguments.size() > 0 && evalctx->eval_arguments[0].second.toBool()) { + if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) { std::vector evaluatednodes = ifelse->evaluateChildren(evalctx); node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); } diff --git a/src/dxfdim.cc b/src/dxfdim.cc index fbc24c4..ecdae80 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -52,17 +52,17 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) // FIXME: We don't lookup the file relative to where this function was instantiated // since the path is only available for ModuleInstantiations, not function expressions. // See issue #217 - for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { - if (evalctx->eval_arguments[i].first == "file") - filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString()); - if (evalctx->eval_arguments[i].first == "layer") - layername = evalctx->eval_arguments[i].second.toString(); - if (evalctx->eval_arguments[i].first == "origin") - evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin); - if (evalctx->eval_arguments[i].first == "scale") - evalctx->eval_arguments[i].second.getDouble(scale); - if (evalctx->eval_arguments[i].first == "name") - name = evalctx->eval_arguments[i].second.toString(); + for (size_t i = 0; i < evalctx->numArgs(); i++) { + if (evalctx->getArgName(i) == "file") + filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString()); + if (evalctx->getArgName(i) == "layer") + layername = evalctx->getArgValue(i).toString(); + if (evalctx->getArgName(i) == "origin") + evalctx->getArgValue(i).getVec2(xorigin, yorigin); + if (evalctx->getArgName(i) == "scale") + evalctx->getArgValue(i).getDouble(scale); + if (evalctx->getArgName(i) == "name") + name = evalctx->getArgValue(i).toString(); } std::stringstream keystream; @@ -146,15 +146,15 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) // FIXME: We don't lookup the file relative to where this function was instantiated // since the path is only available for ModuleInstantiations, not function expressions. // See isse #217 - for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { - if (evalctx->eval_arguments[i].first == "file") - filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString()); - if (evalctx->eval_arguments[i].first == "layer") - layername = evalctx->eval_arguments[i].second.toString(); - if (evalctx->eval_arguments[i].first == "origin") - evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin); - if (evalctx->eval_arguments[i].first == "scale") - evalctx->eval_arguments[i].second.getDouble(scale); + for (size_t i = 0; i < evalctx->numArgs(); i++) { + if (evalctx->getArgName(i) == "file") + filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString()); + if (evalctx->getArgName(i) == "layer") + layername = evalctx->getArgValue(i).toString(); + if (evalctx->getArgName(i) == "origin") + evalctx->getArgValue(i).getVec2(xorigin, yorigin); + if (evalctx->getArgName(i) == "scale") + evalctx->getArgValue(i).getDouble(scale); } std::stringstream keystream; diff --git a/src/evalcontext.cc b/src/evalcontext.cc index b7566e3..25b6716 100644 --- a/src/evalcontext.cc +++ b/src/evalcontext.cc @@ -7,6 +7,19 @@ #include +const std::string &EvalContext::getArgName(size_t i) const +{ + assert(i < this->eval_arguments.size()); + return this->eval_arguments[i].first; +} + +Value EvalContext::getArgValue(size_t i, const Context *ctx) const +{ + assert(i < this->eval_arguments.size()); + const Assignment &arg = this->eval_arguments[i]; + return arg.second ? arg.second->evaluate(ctx ? ctx : this) : Value(); +} + #ifdef DEBUG void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst) { @@ -20,9 +33,9 @@ void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *ins for (int i=0;ieval_arguments.size();i++) { PRINTB(" %s = %s", this->eval_arguments[i].first % this->eval_arguments[i].second); } - if (this->children.size() > 0) { + if (this->children && this->children->size() > 0) { PRINT(" children:"); - BOOST_FOREACH(const ModuleInstantiation *ch, this->children) { + BOOST_FOREACH(const ModuleInstantiation *ch, *this->children) { PRINTB(" %s", ch->name()); } } diff --git a/src/evalcontext.h b/src/evalcontext.h index 3d7d222..26a4a68 100644 --- a/src/evalcontext.h +++ b/src/evalcontext.h @@ -10,15 +10,28 @@ class EvalContext : public Context { public: - EvalContext(const Context *parent = NULL) : Context(parent) {} + typedef std::vector InstanceList; + + EvalContext(const Context *parent, + const AssignmentList &args, const InstanceList *const children = NULL) + : Context(parent), eval_arguments(args), children(children) {} virtual ~EvalContext() {} - std::vector > eval_arguments; - std::vector children; + size_t numArgs() const { return this->eval_arguments.size(); } + const std::string &getArgName(size_t i) const; + Value getArgValue(size_t i, const Context *ctx = NULL) const; + + size_t numChildren() const { return this->children ? this->children->size() : 0; } + ModuleInstantiation *getChild(size_t i) const { return this->children ? (*this->children)[i] : NULL; } #ifdef DEBUG virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); #endif + +private: + const AssignmentList &eval_arguments; + std::vector > eval_values; + const InstanceList *const children; }; #endif diff --git a/src/expr.cc b/src/expr.cc index 7a8180f..6629bf5 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -127,11 +127,7 @@ Value Expression::evaluate(const Context *context) const return Value(); } if (this->type == "F") { - EvalContext c(context); - for (size_t i=0; i < this->call_arguments.size(); i++) { - c.eval_arguments.push_back(std::make_pair(this->call_arguments[i].first, - this->call_arguments[i].second->evaluate(context))); - } + EvalContext c(context, this->call_arguments); // Value::VectorType argvalues; // std::transform(this->children.begin(), this->children.end(), // std::back_inserter(argvalues), diff --git a/src/func.cc b/src/func.cc index 88bf3c8..4377a90 100644 --- a/src/func.cc +++ b/src/func.cc @@ -129,35 +129,35 @@ static inline double rad2deg(double x) Value builtin_abs(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(fabs(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(fabs(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_sign(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value((evalctx->eval_arguments[0].second.toDouble()<0) ? -1.0 : ((evalctx->eval_arguments[0].second.toDouble()>0) ? 1.0 : 0.0)); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value((evalctx->getArgValue(0).toDouble()<0) ? -1.0 : ((evalctx->getArgValue(0).toDouble()>0) ? 1.0 : 0.0)); return Value(); } Value builtin_rands(const Context *, const EvalContext *evalctx) { bool deterministic = false; - if (evalctx->eval_arguments.size() == 3 && - evalctx->eval_arguments[0].second.type() == Value::NUMBER && - evalctx->eval_arguments[1].second.type() == Value::NUMBER && - evalctx->eval_arguments[2].second.type() == Value::NUMBER) + if (evalctx->numArgs() == 3 && + evalctx->getArgValue(0).type() == Value::NUMBER && + evalctx->getArgValue(1).type() == Value::NUMBER && + evalctx->getArgValue(2).type() == Value::NUMBER) { deterministic = false; } - else if (evalctx->eval_arguments.size() == 4 && - evalctx->eval_arguments[0].second.type() == Value::NUMBER && - evalctx->eval_arguments[1].second.type() == Value::NUMBER && - evalctx->eval_arguments[2].second.type() == Value::NUMBER && - evalctx->eval_arguments[3].second.type() == Value::NUMBER) + else if (evalctx->numArgs() == 4 && + evalctx->getArgValue(0).type() == Value::NUMBER && + evalctx->getArgValue(1).type() == Value::NUMBER && + evalctx->getArgValue(2).type() == Value::NUMBER && + evalctx->getArgValue(3).type() == Value::NUMBER) { - deterministic_rng.seed( (unsigned int) evalctx->eval_arguments[3].second.toDouble() ); + deterministic_rng.seed( (unsigned int) evalctx->getArgValue(3).toDouble() ); deterministic = true; } else @@ -165,11 +165,11 @@ Value builtin_rands(const Context *, const EvalContext *evalctx) return Value(); } - double min = std::min( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); - double max = std::max( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); + double min = std::min( evalctx->getArgValue(0).toDouble(), evalctx->getArgValue(1).toDouble() ); + double max = std::max( evalctx->getArgValue(0).toDouble(), evalctx->getArgValue(1).toDouble() ); boost::uniform_real<> distributor( min, max ); Value::VectorType vec; - for (int i=0; ieval_arguments[2].second.toDouble(); i++) { + for (int i=0; igetArgValue(2).toDouble(); i++) { if ( deterministic ) { vec.push_back( Value( distributor( deterministic_rng ) ) ); } else { @@ -183,11 +183,11 @@ Value builtin_rands(const Context *, const EvalContext *evalctx) Value builtin_min(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { - double val = evalctx->eval_arguments[0].second.toDouble(); - for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) - if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) - val = fmin(val, evalctx->eval_arguments[i].second.toDouble()); + if (evalctx->numArgs() >= 1 && evalctx->getArgValue(0).type() == Value::NUMBER) { + double val = evalctx->getArgValue(0).toDouble(); + for (size_t i = 1; i < evalctx->numArgs(); i++) + if (evalctx->getArgValue(1).type() == Value::NUMBER) + val = fmin(val, evalctx->getArgValue(i).toDouble()); return Value(val); } return Value(); @@ -195,11 +195,11 @@ Value builtin_min(const Context *, const EvalContext *evalctx) Value builtin_max(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { - double val = evalctx->eval_arguments[0].second.toDouble(); - for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) - if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) - val = fmax(val, evalctx->eval_arguments[i].second.toDouble()); + if (evalctx->numArgs() >= 1 && evalctx->getArgValue(0).type() == Value::NUMBER) { + double val = evalctx->getArgValue(0).toDouble(); + for (size_t i = 1; i < evalctx->numArgs(); i++) + if (evalctx->getArgValue(1).type() == Value::NUMBER) + val = fmax(val, evalctx->getArgValue(i).toDouble()); return Value(val); } return Value(); @@ -207,117 +207,117 @@ Value builtin_max(const Context *, const EvalContext *evalctx) Value builtin_sin(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(sin(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(sin(deg2rad(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_cos(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(cos(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(cos(deg2rad(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_asin(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(rad2deg(asin(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(rad2deg(asin(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_acos(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(rad2deg(acos(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(rad2deg(acos(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_tan(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(tan(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(tan(deg2rad(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_atan(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(rad2deg(atan(evalctx->eval_arguments[0].second.toDouble()))); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(rad2deg(atan(evalctx->getArgValue(0).toDouble()))); return Value(); } Value builtin_atan2(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) - return Value(rad2deg(atan2(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble()))); + if (evalctx->numArgs() == 2 && evalctx->getArgValue(0).type() == Value::NUMBER && evalctx->getArgValue(1).type() == Value::NUMBER) + return Value(rad2deg(atan2(evalctx->getArgValue(0).toDouble(), evalctx->getArgValue(1).toDouble()))); return Value(); } Value builtin_pow(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) - return Value(pow(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble())); + if (evalctx->numArgs() == 2 && evalctx->getArgValue(0).type() == Value::NUMBER && evalctx->getArgValue(1).type() == Value::NUMBER) + return Value(pow(evalctx->getArgValue(0).toDouble(), evalctx->getArgValue(1).toDouble())); return Value(); } Value builtin_round(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(round(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(round(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_ceil(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(ceil(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(ceil(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_floor(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(floor(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(floor(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_sqrt(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(sqrt(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(sqrt(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_exp(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(exp(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(exp(evalctx->getArgValue(0).toDouble())); return Value(); } Value builtin_length(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1) { - if (evalctx->eval_arguments[0].second.type() == Value::VECTOR) return Value(int(evalctx->eval_arguments[0].second.toVector().size())); - if (evalctx->eval_arguments[0].second.type() == Value::STRING) return Value(int(evalctx->eval_arguments[0].second.toString().size())); + if (evalctx->numArgs() == 1) { + if (evalctx->getArgValue(0).type() == Value::VECTOR) return Value(int(evalctx->getArgValue(0).toVector().size())); + if (evalctx->getArgValue(0).type() == Value::STRING) return Value(int(evalctx->getArgValue(0).toString().size())); } return Value(); } Value builtin_log(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) - return Value(log(evalctx->eval_arguments[1].second.toDouble()) / log(evalctx->eval_arguments[0].second.toDouble())); - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(log(evalctx->eval_arguments[0].second.toDouble()) / log(10.0)); + if (evalctx->numArgs() == 2 && evalctx->getArgValue(0).type() == Value::NUMBER && evalctx->getArgValue(1).type() == Value::NUMBER) + return Value(log(evalctx->getArgValue(1).toDouble()) / log(evalctx->getArgValue(0).toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(log(evalctx->getArgValue(0).toDouble()) / log(10.0)); return Value(); } Value builtin_ln(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) - return Value(log(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + return Value(log(evalctx->getArgValue(0).toDouble())); return Value(); } @@ -325,8 +325,8 @@ Value builtin_str(const Context *, const EvalContext *evalctx) { std::stringstream stream; - for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { - stream << evalctx->eval_arguments[i].second.toString(); + for (size_t i = 0; i < evalctx->numArgs(); i++) { + stream << evalctx->getArgValue(i).toString(); } return Value(stream.str()); } @@ -334,16 +334,16 @@ Value builtin_str(const Context *, const EvalContext *evalctx) Value builtin_lookup(const Context *, const EvalContext *evalctx) { double p, low_p, low_v, high_p, high_v; - if (evalctx->eval_arguments.size() < 2 || // Needs two args - !evalctx->eval_arguments[0].second.getDouble(p) || // First must be a number - evalctx->eval_arguments[1].second.toVector().size() < 2 || // Second must be a vector of vectors - evalctx->eval_arguments[1].second.toVector()[0].toVector().size() < 2) + if (evalctx->numArgs() < 2 || // Needs two args + !evalctx->getArgValue(0).getDouble(p) || // First must be a number + evalctx->getArgValue(1).toVector().size() < 2 || // Second must be a vector of vectors + evalctx->getArgValue(1).toVector()[0].toVector().size() < 2) return Value(); - if (!evalctx->eval_arguments[1].second.toVector()[0].getVec2(low_p, low_v) || !evalctx->eval_arguments[1].second.toVector()[0].getVec2(high_p, high_v)) + if (!evalctx->getArgValue(1).toVector()[0].getVec2(low_p, low_v) || !evalctx->getArgValue(1).toVector()[0].getVec2(high_p, high_v)) return Value(); - for (size_t i = 1; i < evalctx->eval_arguments[1].second.toVector().size(); i++) { + for (size_t i = 1; i < evalctx->getArgValue(1).toVector().size(); i++) { double this_p, this_v; - if (evalctx->eval_arguments[1].second.toVector()[i].getVec2(this_p, this_v)) { + if (evalctx->getArgValue(1).toVector()[i].getVec2(this_p, this_v)) { if (this_p <= p && (this_p > low_p || low_p > p)) { low_p = this_p; low_v = this_v; @@ -406,12 +406,12 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx) */ Value builtin_search(const Context *, const EvalContext *evalctx) { - if (evalctx->eval_arguments.size() < 2) return Value(); + if (evalctx->numArgs() < 2) return Value(); - const Value &findThis = evalctx->eval_arguments[0].second; - const Value &searchTable = evalctx->eval_arguments[1].second; - unsigned int num_returns_per_match = (evalctx->eval_arguments.size() > 2) ? evalctx->eval_arguments[2].second.toDouble() : 1; - unsigned int index_col_num = (evalctx->eval_arguments.size() > 3) ? evalctx->eval_arguments[3].second.toDouble() : 0; + const Value &findThis = evalctx->getArgValue(0); + const Value &searchTable = evalctx->getArgValue(1); + unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2).toDouble() : 1; + unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3).toDouble() : 0; Value::VectorType returnvec; @@ -512,7 +512,7 @@ Value builtin_version(const Context *, const EvalContext *evalctx) Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) { - Value val = (evalctx->eval_arguments.size() == 0) ? builtin_version(ctx, evalctx) : evalctx->eval_arguments[0].second; + Value val = (evalctx->numArgs() == 0) ? builtin_version(ctx, evalctx) : evalctx->getArgValue(0); double y, m, d = 0; if (!val.getVec3(y, m, d)) { if (!val.getVec2(y, m)) { diff --git a/src/linearextrude.cc b/src/linearextrude.cc index f4c1112..a3337e8 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -80,10 +80,10 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst // if height not given, and first argument is a number, // then assume it should be the height. if (c.lookup_variable("height").isUndefined() && - evalctx->eval_arguments.size() > 0 && - evalctx->eval_arguments[0].first == "" && - evalctx->eval_arguments[0].second.type() == Value::NUMBER) { - height = Value(evalctx->eval_arguments[0].second); + evalctx->numArgs() > 0 && + evalctx->getArgName(0) == "" && + evalctx->getArgValue(0).type() == Value::NUMBER) { + height = evalctx->getArgValue(0); } node->layername = layer.isUndefined() ? "" : layer.toString(); diff --git a/src/module.cc b/src/module.cc index 7d83975..3f6dd22 100644 --- a/src/module.cc +++ b/src/module.cc @@ -112,14 +112,7 @@ std::string ModuleInstantiation::dump(const std::string &indent) const AbstractNode *ModuleInstantiation::evaluate_instance(const Context *ctx) const { - EvalContext c(ctx); - BOOST_FOREACH(const Assignment &arg, this->arguments) { - c.eval_arguments.push_back(std::make_pair(arg.first, - arg.second ? - arg.second->evaluate(ctx) : - Value())); - } - c.children = this->children; + EvalContext c(ctx, this->arguments, &this->children); #if 0 && DEBUG PRINT("New eval ctx:"); -- cgit v0.10.1 From b4568a09df8be0f212ba1c4fd1660459900e3cf0 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 19 Apr 2013 13:56:27 -0400 Subject: Refactored assignments and assignments_var into one component diff --git a/src/builtin.cc b/src/builtin.cc index bdd2d3b..37abde6 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -80,24 +80,18 @@ std::string Builtins::isDeprecated(const std::string &name) Builtins::Builtins() { - this->rootmodule.assignments_var.push_back("$fn"); - this->rootmodule.assignments["$fn"] = new Expression(Value(0.0)); - this->rootmodule.assignments_var.push_back("$fs"); - this->rootmodule.assignments["$fs"] = new Expression(Value(2.0)); - this->rootmodule.assignments_var.push_back("$fa"); - this->rootmodule.assignments["$fa"] = new Expression(Value(12.0)); - this->rootmodule.assignments_var.push_back("$t"); - this->rootmodule.assignments["$t"] = new Expression(Value(0.0)); + this->rootmodule.assignments.push_back(Assignment("$fn", new Expression(Value(0.0)))); + this->rootmodule.assignments.push_back(Assignment("$fs", new Expression(Value(2.0)))); + this->rootmodule.assignments.push_back(Assignment("$fa", new Expression(Value(12.0)))); + this->rootmodule.assignments.push_back(Assignment("$t", new Expression(Value(0.0)))); Value::VectorType zero3; zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); Value zero3val(zero3); - this->rootmodule.assignments_var.push_back("$vpt"); - this->rootmodule.assignments["$vpt"] = new Expression(zero3val); - this->rootmodule.assignments_var.push_back("$vpr"); - this->rootmodule.assignments["$vpr"] = new Expression(zero3val); + this->rootmodule.assignments.push_back(Assignment("$vpt", new Expression(zero3val))); + this->rootmodule.assignments.push_back(Assignment("$vpr", new Expression(zero3val))); } Builtins::~Builtins() diff --git a/src/modcontext.cc b/src/modcontext.cc index 7d123b8..83ad7c2 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -33,8 +33,8 @@ void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) this->functions_p = &module.functions; this->modules_p = &module.modules; this->usedlibs_p = &module.usedlibs; - BOOST_FOREACH(const std::string &var, module.assignments_var) { - this->set_variable(var, module.assignments.at(var)->evaluate(this)); + BOOST_FOREACH(const Assignment &ass, module.assignments) { + this->set_variable(ass.first, ass.second->evaluate(this)); } if (!module.modulePath().empty()) this->document_path = module.modulePath(); diff --git a/src/module.cc b/src/module.cc index 3f6dd22..3b1ec0a 100644 --- a/src/module.cc +++ b/src/module.cc @@ -190,8 +190,8 @@ std::string Module::dump(const std::string &indent, const std::string &name) con BOOST_FOREACH(const AbstractModuleContainer::value_type &m, modules) { dump << m.second->dump(indent + tab, m.first); } - BOOST_FOREACH(const std::string &var, assignments_var) { - dump << indent << tab << var << " = " << *assignments.at(var) << ";\n"; + BOOST_FOREACH(const Assignment &ass, assignments) { + dump << indent << tab << ass.first << " = " << *ass.second << ";\n"; } for (size_t i = 0; i < children.size(); i++) { dump << children[i]->dump(indent + tab); diff --git a/src/module.h b/src/module.h index ace3c1b..94de25e 100644 --- a/src/module.h +++ b/src/module.h @@ -80,9 +80,7 @@ public: bool is_handling_dependencies; bool handleDependencies(); - std::list assignments_var; - typedef boost::unordered_map AssignmentMap; - AssignmentMap assignments; + AssignmentList assignments; typedef boost::unordered_map FunctionContainer; FunctionContainer functions; diff --git a/src/parser.y b/src/parser.y index fd6b164..096bb89 100644 --- a/src/parser.y +++ b/src/parser.y @@ -148,10 +148,15 @@ module_instantiation { } } | TOK_ID '=' expr ';' { - std::list::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1); - if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found); - currmodule->assignments_var.push_back($1); - currmodule->assignments[$1] = $3; + for (AssignmentList::iterator iter = currmodule->assignments.begin(); + iter != currmodule->assignments.end(); + iter++) { + if (iter->first == $1) { + currmodule->assignments.erase(iter); + break; + } + } + currmodule->assignments.push_back(Assignment($1, $3)); } | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { Module *p = currmodule; -- cgit v0.10.1 From 9a297ecee57549a4eb3919bde4f7b41a548724de Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 19 Apr 2013 17:52:01 -0400 Subject: Refactoring: Split out FileModule from Module, Added LocalScope renamed some confusing 'evaluate' methods to 'instantiate', added FileContext (not yet used) diff --git a/src/MainWindow.h b/src/MainWindow.h index 65deb15..7bb008a 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -30,7 +30,7 @@ public: std::string autoReloadId; ModuleContext root_ctx; - Module *root_module; // Result of parsing + FileModule *root_module; // Result of parsing ModuleInstantiation root_inst; // Top level instance AbstractNode *absolute_root_node; // Result of tree evaluation AbstractNode *root_node; // Root if the root modifier (!) is used diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc index 19a3f84..4944495 100644 --- a/src/ModuleCache.cc +++ b/src/ModuleCache.cc @@ -28,9 +28,9 @@ static bool is_modified(const std::string &filename, const time_t &mtime) return (st.st_mtime > mtime); } -Module *ModuleCache::evaluate(const std::string &filename) +FileModule *ModuleCache::evaluate(const std::string &filename) { - Module *lib_mod = NULL; + FileModule *lib_mod = NULL; // Create cache ID struct stat st; @@ -48,7 +48,7 @@ Module *ModuleCache::evaluate(const std::string &filename) #endif lib_mod = &(*this->entries[filename].module); - BOOST_FOREACH(const Module::IncludeContainer::value_type &item, lib_mod->includes) { + BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, lib_mod->includes) { if (is_modified(item.first, item.second)) { lib_mod = NULL; break; @@ -78,7 +78,7 @@ Module *ModuleCache::evaluate(const std::string &filename) print_messages_push(); - Module *oldmodule = NULL; + FileModule *oldmodule = NULL; cache_entry e = { NULL, cache_id }; if (this->entries.find(filename) != this->entries.end()) { oldmodule = this->entries[filename].module; @@ -86,7 +86,7 @@ Module *ModuleCache::evaluate(const std::string &filename) this->entries[filename] = e; std::string pathname = boosty::stringy(fs::path(filename).parent_path()); - lib_mod = dynamic_cast(parse(textbuf.str().c_str(), pathname.c_str(), false)); + lib_mod = dynamic_cast(parse(textbuf.str().c_str(), pathname.c_str(), false)); PRINTB_NOCACHE(" compiled module: %p", lib_mod); if (lib_mod) { diff --git a/src/ModuleCache.h b/src/ModuleCache.h index 1e6373d..b8ded38 100644 --- a/src/ModuleCache.h +++ b/src/ModuleCache.h @@ -1,11 +1,14 @@ #include #include +/*! + Caches FileModules based on their filenames +*/ class ModuleCache { public: static ModuleCache *instance() { if (!inst) inst = new ModuleCache; return inst; } - class Module *evaluate(const std::string &filename); + class FileModule *evaluate(const std::string &filename); size_t size() { return this->entries.size(); } void clear(); @@ -16,7 +19,7 @@ private: static ModuleCache *inst; struct cache_entry { - class Module *module; + class FileModule *module; std::string cache_id; }; boost::unordered_map entries; diff --git a/src/builtin.cc b/src/builtin.cc index 37abde6..a8b60df 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -16,12 +16,12 @@ Builtins *Builtins::instance(bool erase) void Builtins::init(const char *name, class AbstractModule *module) { - Builtins::instance()->rootmodule.modules[name] = module; + Builtins::instance()->rootmodule.scope.modules[name] = module; } void Builtins::init(const char *name, class AbstractFunction *function) { - Builtins::instance()->rootmodule.functions[name] = function; + Builtins::instance()->rootmodule.scope.functions[name] = function; } extern void register_builtin_functions(); @@ -80,18 +80,18 @@ std::string Builtins::isDeprecated(const std::string &name) Builtins::Builtins() { - this->rootmodule.assignments.push_back(Assignment("$fn", new Expression(Value(0.0)))); - this->rootmodule.assignments.push_back(Assignment("$fs", new Expression(Value(2.0)))); - this->rootmodule.assignments.push_back(Assignment("$fa", new Expression(Value(12.0)))); - this->rootmodule.assignments.push_back(Assignment("$t", new Expression(Value(0.0)))); + this->rootmodule.scope.assignments.push_back(Assignment("$fn", new Expression(Value(0.0)))); + this->rootmodule.scope.assignments.push_back(Assignment("$fs", new Expression(Value(2.0)))); + this->rootmodule.scope.assignments.push_back(Assignment("$fa", new Expression(Value(12.0)))); + this->rootmodule.scope.assignments.push_back(Assignment("$t", new Expression(Value(0.0)))); Value::VectorType zero3; zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); Value zero3val(zero3); - this->rootmodule.assignments.push_back(Assignment("$vpt", new Expression(zero3val))); - this->rootmodule.assignments.push_back(Assignment("$vpr", new Expression(zero3val))); + this->rootmodule.scope.assignments.push_back(Assignment("$vpt", new Expression(zero3val))); + this->rootmodule.scope.assignments.push_back(Assignment("$vpr", new Expression(zero3val))); } Builtins::~Builtins() diff --git a/src/cgaladv.cc b/src/cgaladv.cc index aad3a95..70590f7 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -39,10 +39,10 @@ class CgaladvModule : public AbstractModule public: cgaladv_type_e type; CgaladvModule(cgaladv_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { CgaladvNode *node = new CgaladvNode(inst, type); @@ -110,8 +110,8 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat if (node->level <= 1) node->level = 1; - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/color.cc b/src/color.cc index 6c3aaef..7fef030 100644 --- a/src/color.cc +++ b/src/color.cc @@ -40,14 +40,14 @@ class ColorModule : public AbstractModule { public: ColorModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; private: static boost::unordered_map colormap; }; #include "colormap.h" -AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ColorNode *node = new ColorNode(inst); @@ -87,8 +87,8 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio node->color[3] = alpha.toDouble(); } - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/context.cc b/src/context.cc index ea48dad..a7273a4 100644 --- a/src/context.cc +++ b/src/context.cc @@ -124,9 +124,9 @@ Value Context::evaluate_function(const std::string &name, const EvalContext *eva return Value(); } -AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const { - if (this->parent) return this->parent->evaluate_module(inst, evalctx); + if (this->parent) return this->parent->instantiate_module(inst, evalctx); PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name()); return NULL; } diff --git a/src/context.h b/src/context.h index 51fc45c..5be1efd 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ public: virtual ~Context(); virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const; - virtual class AbstractNode *evaluate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const; + virtual class AbstractNode *instantiate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const; void setVariables(const AssignmentList &args, const class EvalContext *evalctx = NULL); diff --git a/src/control.cc b/src/control.cc index d45ee02..7786e36 100644 --- a/src/control.cc +++ b/src/control.cc @@ -46,7 +46,7 @@ class ControlModule : public AbstractModule public: control_type_e type; ControlModule(control_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, @@ -81,12 +81,12 @@ void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, for_eval(node, inst, l+1, &c, evalctx); } } else if (l > 0) { - std::vector evaluatednodes = inst.evaluateChildren(ctx); - node.children.insert(node.children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst.instantiateChildren(ctx); + node.children.insert(node.children.end(), instantiatednodes.begin(), instantiatednodes.end()); } } -AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *ControlModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = NULL; @@ -115,7 +115,7 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (filectx->evalctx) { if (n < filectx->evalctx->numChildren()) { - node = filectx->evalctx->getChild(n)->evaluate_instance(filectx->evalctx); + node = filectx->evalctx->getChild(n)->evaluate(filectx->evalctx); } else { // How to deal with negative objects in this case? @@ -155,8 +155,8 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat if (!evalctx->getArgName(i).empty()) c.set_variable(evalctx->getArgName(i), evalctx->getArgValue(i)); } - std::vector evaluatednodes = inst->evaluateChildren(&c); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(&c); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } if (type == FOR || type == INT_FOR) @@ -168,12 +168,12 @@ AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiat { const IfElseModuleInstantiation *ifelse = dynamic_cast(inst); if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) { - std::vector evaluatednodes = ifelse->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = ifelse->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } else { - std::vector evaluatednodes = ifelse->evaluateElseChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = ifelse->instantiateElseChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } } diff --git a/src/csgops.cc b/src/csgops.cc index 425b747..92b97e7 100644 --- a/src/csgops.cc +++ b/src/csgops.cc @@ -38,14 +38,14 @@ class CsgModule : public AbstractModule public: csg_type_e type; CsgModule(csg_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, const EvalContext *evalctx) const { CsgNode *node = new CsgNode(inst, type); - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/evalcontext.cc b/src/evalcontext.cc index 25b6716..57c206f 100644 --- a/src/evalcontext.cc +++ b/src/evalcontext.cc @@ -4,6 +4,7 @@ #include "function.h" #include "printutils.h" #include "builtin.h" +#include "localscope.h" #include @@ -20,6 +21,16 @@ Value EvalContext::getArgValue(size_t i, const Context *ctx) const return arg.second ? arg.second->evaluate(ctx ? ctx : this) : Value(); } +size_t EvalContext::numChildren() const +{ + return this->scope ? this->scope->children.size() : 0; +} + +ModuleInstantiation *EvalContext::getChild(size_t i) const +{ + return this->scope ? this->scope->children[i] : NULL; +} + #ifdef DEBUG void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst) { @@ -33,9 +44,9 @@ void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *ins for (int i=0;ieval_arguments.size();i++) { PRINTB(" %s = %s", this->eval_arguments[i].first % this->eval_arguments[i].second); } - if (this->children && this->children->size() > 0) { + if (this->scope && this->scope->children.size() > 0) { PRINT(" children:"); - BOOST_FOREACH(const ModuleInstantiation *ch, *this->children) { + BOOST_FOREACH(const ModuleInstantiation *ch, this->scope->children) { PRINTB(" %s", ch->name()); } } diff --git a/src/evalcontext.h b/src/evalcontext.h index 26a4a68..34f339a 100644 --- a/src/evalcontext.h +++ b/src/evalcontext.h @@ -13,16 +13,16 @@ public: typedef std::vector InstanceList; EvalContext(const Context *parent, - const AssignmentList &args, const InstanceList *const children = NULL) - : Context(parent), eval_arguments(args), children(children) {} + const AssignmentList &args, const class LocalScope *const scope = NULL) + : Context(parent), eval_arguments(args), scope(scope) {} virtual ~EvalContext() {} size_t numArgs() const { return this->eval_arguments.size(); } const std::string &getArgName(size_t i) const; Value getArgValue(size_t i, const Context *ctx = NULL) const; - size_t numChildren() const { return this->children ? this->children->size() : 0; } - ModuleInstantiation *getChild(size_t i) const { return this->children ? (*this->children)[i] : NULL; } + size_t numChildren() const; + ModuleInstantiation *getChild(size_t i) const; #ifdef DEBUG virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); @@ -31,7 +31,7 @@ public: private: const AssignmentList &eval_arguments; std::vector > eval_values; - const InstanceList *const children; + const LocalScope *const scope; }; #endif diff --git a/src/import.cc b/src/import.cc index 927c9d8..da79322 100644 --- a/src/import.cc +++ b/src/import.cc @@ -60,10 +60,10 @@ class ImportModule : public AbstractModule public: import_type_e type; ImportModule(import_type_e type = TYPE_UNKNOWN) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AssignmentList args; args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("convexity", NULL), Assignment("origin", NULL), Assignment("scale", NULL); diff --git a/src/lexer.l b/src/lexer.l index 6766abc..6dfe9bc 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -55,7 +55,7 @@ static void yyunput(int, char*) __attribute__((unused)); #endif extern const char *parser_input_buffer; extern std::string parser_source_path; -extern Module *currmodule; +extern FileModule *rootmodule; #define YY_INPUT(buf,result,max_size) { \ if (yyin && yyin != stdin) { \ @@ -248,7 +248,7 @@ void includefile() path_stack.push_back(finfo.parent_path()); handle_dep(fullname); - currmodule->registerInclude(fullname); + rootmodule->registerInclude(fullname); yyin = fopen(fullname.c_str(), "r"); if (!yyin) { PRINTB("WARNING: Can't open 'include' file '%s'.", filename); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index a3337e8..c64a235 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -45,10 +45,10 @@ class LinearExtrudeModule : public AbstractModule { public: LinearExtrudeModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { LinearExtrudeNode *node = new LinearExtrudeNode(inst); @@ -116,8 +116,8 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst } if (node->filename.empty()) { - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } return node; diff --git a/src/localscope.h b/src/localscope.h new file mode 100644 index 0000000..e631028 --- /dev/null +++ b/src/localscope.h @@ -0,0 +1,25 @@ +#ifndef LOCALSCOPE_H_ +#define LOCALSCOPE_H_ + +#include "typedefs.h" +#include + +class LocalScope +{ +public: + LocalScope(); + ~LocalScope(); + + size_t numElements() const { return assignments.size() + children.size(); } + std::string dump(const std::string &indent) const; + std::vector instantiateChildren(const class Context *evalctx) const; + + AssignmentList assignments; + ModuleInstantiationList children; + typedef boost::unordered_map FunctionContainer; + FunctionContainer functions; + typedef boost::unordered_map AbstractModuleContainer; + AbstractModuleContainer modules; +}; + +#endif diff --git a/src/mainwin.cc b/src/mainwin.cc index 2e69ec2..87ec744 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -644,7 +644,7 @@ bool MainWindow::compile(bool reload, bool procevents) AbstractNode::resetIndexCounter(); this->root_inst = ModuleInstantiation("group"); - this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst, NULL); + this->absolute_root_node = this->root_module->instantiate(&this->root_ctx, &this->root_inst, NULL); if (this->absolute_root_node) { // Do we have an explicit root node (! modifier)? @@ -1022,7 +1022,7 @@ static bool is_modified(const std::string &filename, const time_t &mtime) bool MainWindow::includesChanged() { if (this->root_module) { - BOOST_FOREACH(const Module::IncludeContainer::value_type &item, this->root_module->includes) { + BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, this->root_module->includes) { if (is_modified(item.first, item.second)) return true; } } diff --git a/src/modcontext.cc b/src/modcontext.cc index 83ad7c2..df341f9 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -8,16 +8,9 @@ #include ModuleContext::ModuleContext(const class Module *module, const Context *parent, const EvalContext *evalctx) - : Context(parent) + : Context(parent), functions_p(NULL), modules_p(NULL), usedlibs_p(NULL) { - if (module) { - setModule(*module, evalctx); - } - else { - this->functions_p = NULL; - this->modules_p = NULL; - this->usedlibs_p = NULL; - } + if (module) setModule(*module, evalctx); } ModuleContext::~ModuleContext() @@ -29,15 +22,19 @@ void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) this->setVariables(module.definition_arguments, evalctx); this->evalctx = evalctx; + // FIXME: Hack - split out file context into separate class? + const FileModule *fm = dynamic_cast(&module); + if (fm) { + this->usedlibs_p = &(fm->usedlibs); + if (!fm->modulePath().empty()) this->document_path = fm->modulePath(); + } + // FIXME: Don't access module members directly - this->functions_p = &module.functions; - this->modules_p = &module.modules; - this->usedlibs_p = &module.usedlibs; - BOOST_FOREACH(const Assignment &ass, module.assignments) { + this->functions_p = &module.scope.functions; + this->modules_p = &module.scope.modules; + BOOST_FOREACH(const Assignment &ass, module.scope.assignments) { this->set_variable(ass.first, ass.second->evaluate(this)); } - - if (!module.modulePath().empty()) this->document_path = module.modulePath(); } /*! @@ -45,6 +42,8 @@ void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) */ void ModuleContext::registerBuiltin() { + // FIXME: built-ins only contains variables, setModule isn't really needed for this + // FIXME: Where to put set_variable from setModule? this->setModule(Builtins::instance()->getRootModule()); this->set_constant("PI",Value(M_PI)); } @@ -75,22 +74,22 @@ Value ModuleContext::evaluate_function(const std::string &name, const EvalContex } if (this->usedlibs_p) { - BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { - if (m.second->functions.find(name) != m.second->functions.end()) { + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { + if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) { ModuleContext ctx(m.second, this->parent); // FIXME: Set document path #if 0 && DEBUG PRINTB("New lib Context for %s func:", name); ctx.dump(NULL, NULL); #endif - return m.second->functions[name]->evaluate(&ctx, evalctx); + return m.second->scope.functions[name]->evaluate(&ctx, evalctx); } } } return Context::evaluate_function(name, evalctx); } -AbstractNode *ModuleContext::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const { if (this->modules_p && this->modules_p->find(inst.name()) != this->modules_p->end()) { AbstractModule *m = this->modules_p->find(inst.name())->second; @@ -98,25 +97,25 @@ AbstractNode *ModuleContext::evaluate_module(const ModuleInstantiation &inst, co if (!replacement.empty()) { PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement); } - return m->evaluate(this, &inst, evalctx); + return m->instantiate(this, &inst, evalctx); } if (this->usedlibs_p) { - BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) { + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { assert(m.second); - if (m.second->modules.find(inst.name()) != m.second->modules.end()) { + if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { ModuleContext ctx(m.second, this->parent); // FIXME: Set document path #if 0 && DEBUG PRINT("New lib Context:"); ctx.dump(NULL, &inst); #endif - return m.second->modules[inst.name()]->evaluate(&ctx, &inst, evalctx); + return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); } } } - return Context::evaluate_module(inst, evalctx); + return Context::instantiate_module(inst, evalctx); } #ifdef DEBUG @@ -150,3 +149,11 @@ void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *i } #endif + +FileContext::FileContext(const class FileModule &module, + const Context *parent, const EvalContext *evalctx) + :ModuleContext(&module, parent, evalctx) +{ + +} + diff --git a/src/modcontext.h b/src/modcontext.h index 5fce88f..d9965c5 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -2,13 +2,14 @@ #define FILECONTEXT_H_ #include "context.h" +#include "module.h" #include /*! This holds the context for a Module definition; keeps track of global variables, submodules and functions defined inside a module. - NB! every .scad file defines an implicit unnamed module holding the contents of the file. + NB! every .scad file defines a FileModule holding the contents of the file. */ class ModuleContext : public Context { @@ -20,12 +21,11 @@ public: void registerBuiltin(); virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const; - virtual AbstractNode *evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; const boost::unordered_map *functions_p; const boost::unordered_map *modules_p; - typedef boost::unordered_map ModuleContainer; - const ModuleContainer *usedlibs_p; + const FileModule::ModuleContainer *usedlibs_p; // FIXME: Points to the eval context for the call to this module. Not sure where it belongs const class EvalContext *evalctx; @@ -37,4 +37,11 @@ public: mutable boost::unordered_map recursioncount; }; +class FileContext : public ModuleContext +{ +public: + FileContext(const class FileModule &module, const Context *parent = NULL, const EvalContext *evalctx = NULL); + virtual ~FileContext() {} +}; + #endif diff --git a/src/module.cc b/src/module.cc index 3b1ec0a..a9e3cbf 100644 --- a/src/module.cc +++ b/src/module.cc @@ -40,15 +40,59 @@ namespace fs = boost::filesystem; #include #include +LocalScope::LocalScope() +{ +} + +LocalScope::~LocalScope() +{ + BOOST_FOREACH(ModuleInstantiation *v, children) delete v; + BOOST_FOREACH (const Assignment &v, assignments) delete v.second; + BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; + BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; +} + +std::string LocalScope::dump(const std::string &indent) const +{ + std::stringstream dump; + BOOST_FOREACH(const FunctionContainer::value_type &f, this->functions) { + dump << f.second->dump(indent, f.first); + } + BOOST_FOREACH(const AbstractModuleContainer::value_type &m, this->modules) { + dump << m.second->dump(indent, m.first); + } + BOOST_FOREACH(const Assignment &ass, this->assignments) { + dump << indent << ass.first << " = " << *ass.second << ";\n"; + } + BOOST_FOREACH(const ModuleInstantiation *inst, this->children) { + dump << inst->dump(indent); + } + return dump.str(); +} + +std::vector LocalScope::instantiateChildren(const Context *evalctx) const +{ + Context c(evalctx); // FIXME: Is this correct, or should we use the parent? + BOOST_FOREACH (const Assignment &ass, this->assignments) { + c.set_variable(ass.first, ass.second->evaluate(&c)); + } + std::vector childnodes; + BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { + AbstractNode *node = modinst->evaluate(&c); + if (node) childnodes.push_back(node); + } + return childnodes; +} + AbstractModule::~AbstractModule() { } -AbstractNode *AbstractModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = new AbstractNode(inst); - node->children = inst->evaluateChildren(evalctx); + node->children = inst->instantiateChildren(evalctx); return node; } @@ -63,12 +107,10 @@ std::string AbstractModule::dump(const std::string &indent, const std::string &n ModuleInstantiation::~ModuleInstantiation() { BOOST_FOREACH(const Assignment &arg, this->arguments) delete arg.second; - BOOST_FOREACH(ModuleInstantiation *v, children) delete v; } IfElseModuleInstantiation::~IfElseModuleInstantiation() { - BOOST_FOREACH (ModuleInstantiation *v, else_children) delete v; } /*! @@ -95,76 +137,63 @@ std::string ModuleInstantiation::dump(const std::string &indent) const if (!arg.first.empty()) dump << arg.first << " = "; dump << *arg.second; } - if (children.size() == 0) { + if (scope.numElements() == 0) { dump << ");\n"; - } else if (children.size() == 1) { + } else if (scope.numElements() == 1) { dump << ")\n"; - dump << children[0]->dump(indent + "\t"); + dump << scope.dump(indent + "\t"); } else { dump << ") {\n"; - for (size_t i = 0; i < children.size(); i++) { - dump << children[i]->dump(indent + "\t"); - } + scope.dump(indent + "\t"); dump << indent << "}\n"; } return dump.str(); } -AbstractNode *ModuleInstantiation::evaluate_instance(const Context *ctx) const +AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const { - EvalContext c(ctx, this->arguments, &this->children); + EvalContext c(ctx, this->arguments, &this->scope); #if 0 && DEBUG PRINT("New eval ctx:"); c.dump(NULL, this); #endif - AbstractNode *node = ctx->evaluate_module(*this, &c); // Passes c as evalctx + AbstractNode *node = ctx->instantiate_module(*this, &c); // Passes c as evalctx return node; } -std::vector ModuleInstantiation::evaluateChildren(const Context *evalctx) const +std::vector ModuleInstantiation::instantiateChildren(const Context *evalctx) const { - std::vector childnodes; - BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { - AbstractNode *node = modinst->evaluate_instance(evalctx); - if (node) childnodes.push_back(node); - } - return childnodes; + return this->scope.instantiateChildren(evalctx); } -std::vector IfElseModuleInstantiation::evaluateElseChildren(const Context *evalctx) const +std::vector IfElseModuleInstantiation::instantiateElseChildren(const Context *evalctx) const { - std::vector childnodes; - BOOST_FOREACH (ModuleInstantiation *modinst, this->else_children) { - AbstractNode *node = modinst->evaluate_instance(evalctx); - if (node != NULL) childnodes.push_back(node); - } - return childnodes; + return this->else_scope.instantiateChildren(evalctx); } Module::~Module() { - BOOST_FOREACH (const Assignment &v, assignments) delete v.second; - BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; - BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; - BOOST_FOREACH (ModuleInstantiation *v, children) delete v; } -AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +void Module::addChild(ModuleInstantiation *ch) +{ + this->scope.children.push_back(ch); +} + +AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ModuleContext c(this, ctx, evalctx); // FIXME: Set document path to the path of the module - c.set_variable("$children", Value(double(inst->children.size()))); + c.set_variable("$children", Value(double(inst->scope.children.size()))); #if 0 && DEBUG c.dump(this, inst); #endif + // FIXME: this->scope.instantiateChildren(&c) and ModuleContext c() causes set_variable to be called twice, causing duplicate warning output in e.g. echotest_search-tests AbstractNode *node = new AbstractNode(inst); - for (size_t i = 0; i < children.size(); i++) { - AbstractNode *n = children[i]->evaluate_instance(&c); - if (n != NULL) - node->children.push_back(n); - } + std::vector instantiatednodes = this->scope.instantiateChildren(&c); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } @@ -184,25 +213,14 @@ std::string Module::dump(const std::string &indent, const std::string &name) con dump << ") {\n"; tab = "\t"; } - BOOST_FOREACH(const FunctionContainer::value_type &f, functions) { - dump << f.second->dump(indent + tab, f.first); - } - BOOST_FOREACH(const AbstractModuleContainer::value_type &m, modules) { - dump << m.second->dump(indent + tab, m.first); - } - BOOST_FOREACH(const Assignment &ass, assignments) { - dump << indent << tab << ass.first << " = " << *ass.second << ";\n"; - } - for (size_t i = 0; i < children.size(); i++) { - dump << children[i]->dump(indent + tab); - } + dump << scope.dump(indent + tab); if (!name.empty()) { dump << indent << "}\n"; } return dump.str(); } -void Module::registerInclude(const std::string &filename) +void FileModule::registerInclude(const std::string &filename) { struct stat st; memset(&st, 0, sizeof(struct stat)); @@ -214,17 +232,17 @@ void Module::registerInclude(const std::string &filename) Check if any dependencies have been modified and recompile them. Returns true if anything was recompiled. */ -bool Module::handleDependencies() +bool FileModule::handleDependencies() { if (this->is_handling_dependencies) return false; this->is_handling_dependencies = true; bool changed = false; // Iterating manually since we want to modify the container while iterating - Module::ModuleContainer::iterator iter = this->usedlibs.begin(); + FileModule::ModuleContainer::iterator iter = this->usedlibs.begin(); while (iter != this->usedlibs.end()) { - Module::ModuleContainer::iterator curr = iter++; - Module *oldmodule = curr->second; + FileModule::ModuleContainer::iterator curr = iter++; + FileModule *oldmodule = curr->second; curr->second = ModuleCache::instance()->evaluate(curr->first); if (curr->second != oldmodule) { changed = true; diff --git a/src/module.h b/src/module.h index 94de25e..39d4bba 100644 --- a/src/module.h +++ b/src/module.h @@ -7,6 +7,7 @@ #include #include "value.h" #include "typedefs.h" +#include "localscope.h" class ModuleInstantiation { @@ -16,8 +17,8 @@ public: virtual ~ModuleInstantiation(); std::string dump(const std::string &indent) const; - class AbstractNode *evaluate_instance(const class Context *ctx) const; - std::vector evaluateChildren(const Context *evalctx) const; + class AbstractNode *evaluate(const class Context *ctx) const; + std::vector instantiateChildren(const Context *evalctx) const; void setPath(const std::string &path) { this->modpath = path; } const std::string &path() const { return this->modpath; } @@ -29,7 +30,7 @@ public: bool isRoot() const { return this->tag_root; } AssignmentList arguments; - std::vector children; + LocalScope scope; bool tag_root; bool tag_highlight; @@ -45,55 +46,53 @@ class IfElseModuleInstantiation : public ModuleInstantiation { public: IfElseModuleInstantiation() : ModuleInstantiation("if") { } virtual ~IfElseModuleInstantiation(); - std::vector evaluateElseChildren(const Context *evalctx) const; + std::vector instantiateElseChildren(const Context *evalctx) const; - std::vector else_children; + LocalScope else_scope; }; class AbstractModule { public: virtual ~AbstractModule(); - virtual class AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const; + virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; class Module : public AbstractModule { public: - Module() : is_handling_dependencies(false) { } + Module() { } virtual ~Module(); - void setModulePath(const std::string &path) { this->path = path; } - const std::string &modulePath() const { return this->path; } - - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; - void addChild(ModuleInstantiation *ch) { this->children.push_back(ch); } + void addChild(ModuleInstantiation *ch); - typedef boost::unordered_map ModuleContainer; - ModuleContainer usedlibs; - void registerInclude(const std::string &filename); - typedef boost::unordered_map IncludeContainer; - IncludeContainer includes; - bool is_handling_dependencies; - bool handleDependencies(); + AssignmentList definition_arguments; - AssignmentList assignments; - - typedef boost::unordered_map FunctionContainer; - FunctionContainer functions; - typedef boost::unordered_map AbstractModuleContainer; - AbstractModuleContainer modules; + LocalScope scope; +}; - std::vector children; +class FileModule : public Module +{ +public: + FileModule() : is_handling_dependencies(false) {} + virtual ~FileModule() {} - std::vector definition_arguments; + void setModulePath(const std::string &path) { this->path = path; } + const std::string &modulePath() const { return this->path; } + void registerInclude(const std::string &filename); + bool handleDependencies(); -protected: + typedef boost::unordered_map ModuleContainer; + ModuleContainer usedlibs; + typedef boost::unordered_map IncludeContainer; + IncludeContainer includes; private: + bool is_handling_dependencies; std::string path; }; diff --git a/src/openscad.cc b/src/openscad.cc index 3b960f3..96dcf4e 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -327,7 +327,7 @@ int main(int argc, char **argv) if (!filename) help(argv[0]); - Module *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; AbstractNode *absolute_root_node; @@ -359,7 +359,7 @@ int main(int argc, char **argv) fs::current_path(fparent); AbstractNode::resetIndexCounter(); - absolute_root_node = root_module->evaluate(&root_ctx, &root_inst, NULL); + absolute_root_node = root_module->instantiate(&root_ctx, &root_inst, NULL); // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) diff --git a/src/openscad.h b/src/openscad.h index 8d9a01e..dd379a9 100644 --- a/src/openscad.h +++ b/src/openscad.h @@ -27,7 +27,7 @@ #ifndef OPENSCAD_H #define OPENSCAD_H -extern class Module *parse(const char *text, const char *path, int debug); +extern class FileModule *parse(const char *text, const char *path, int debug); extern int get_fragments_from_r(double r, double fn, double fs, double fa); #include diff --git a/src/parser.y b/src/parser.y index 096bb89..0cd1fbd 100644 --- a/src/parser.y +++ b/src/parser.y @@ -58,6 +58,7 @@ std::vector module_stack; Module *currmodule; + FileModule *rootmodule; extern void lexerdestroy(); extern FILE *lexerin; @@ -130,7 +131,7 @@ input: /* empty */ | -TOK_USE { currmodule->usedlibs[$1] = NULL; } input | +TOK_USE { rootmodule->usedlibs[$1] = NULL; } input | statement input ; inner_input: @@ -148,21 +149,21 @@ module_instantiation { } } | TOK_ID '=' expr ';' { - for (AssignmentList::iterator iter = currmodule->assignments.begin(); - iter != currmodule->assignments.end(); + for (AssignmentList::iterator iter = currmodule->scope.assignments.begin(); + iter != currmodule->scope.assignments.end(); iter++) { if (iter->first == $1) { - currmodule->assignments.erase(iter); + currmodule->scope.assignments.erase(iter); break; } } - currmodule->assignments.push_back(Assignment($1, $3)); + currmodule->scope.assignments.push_back(Assignment($1, $3)); } | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { Module *p = currmodule; module_stack.push_back(currmodule); currmodule = new Module(); - p->modules[$2] = currmodule; + p->scope.modules[$2] = currmodule; currmodule->definition_arguments = *$4; free($2); delete $4; @@ -174,11 +175,11 @@ TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { Function *func = new Function(); func->definition_arguments = *$4; func->expr = $8; - currmodule->functions[$2] = func; + currmodule->scope.functions[$2] = func; free($2); delete $4; } ';' ; - + /* Will return a dummy parent node with zero or more children */ children_instantiation: module_instantiation { @@ -196,9 +197,9 @@ TOK_IF '(' expr ')' children_instantiation { $$ = new IfElseModuleInstantiation(); $$->arguments.push_back(Assignment("", $3)); $$->setPath(parser_source_path); - + if ($$) { - $$->children = *$5; + $$->scope.children = *$5; } else { for (size_t i = 0; i < $5->size(); i++) delete (*$5)[i]; @@ -213,7 +214,7 @@ if_statement { if_statement TOK_ELSE children_instantiation { $$ = $1; if ($$) { - $$->else_children = *$3; + $$->else_scope.children = *$3; } else { for (size_t i = 0; i < $3->size(); i++) delete (*$3)[i]; @@ -244,7 +245,7 @@ single_module_instantiation ';' { single_module_instantiation children_instantiation { $$ = $1; if ($$) { - $$->children = *$2; + $$->scope.children = *$2; } else { for (size_t i = 0; i < $2->size(); i++) delete (*$2)[i]; @@ -521,7 +522,7 @@ void yyerror (char const *s) currmodule = NULL; } -Module *parse(const char *text, const char *path, int debug) +FileModule *parse(const char *text, const char *path, int debug) { lexerin = NULL; parser_error_pos = -1; @@ -529,7 +530,8 @@ Module *parse(const char *text, const char *path, int debug) parser_source_path = boosty::absolute(std::string(path)).string(); module_stack.clear(); - Module *rootmodule = currmodule = new Module(); + rootmodule = new FileModule(); + currmodule = rootmodule; rootmodule->setModulePath(path); // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); diff --git a/src/primitives.cc b/src/primitives.cc index 184b40c..be1ec6f 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -56,7 +56,7 @@ class PrimitiveModule : public AbstractModule public: primitive_type_e type; PrimitiveModule(primitive_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; class PrimitiveNode : public AbstractPolyNode @@ -105,7 +105,7 @@ public: virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; }; -AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { PrimitiveNode *node = new PrimitiveNode(inst, this->type); @@ -137,7 +137,7 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti args += Assignment("points", NULL), Assignment("paths", NULL), Assignment("convexity", NULL); break; default: - assert(false && "PrimitiveModule::evaluate(): Unknown node type"); + assert(false && "PrimitiveModule::instantiate(): Unknown node type"); } Context c(ctx); diff --git a/src/projection.cc b/src/projection.cc index eeed411..8d8cee6 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -41,10 +41,10 @@ class ProjectionModule : public AbstractModule { public: ProjectionModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ProjectionNode *node = new ProjectionNode(inst); @@ -62,8 +62,8 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant if (cut.type() == Value::BOOL) node->cut_mode = cut.toBool(); - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/render.cc b/src/render.cc index bb08c0c..5097661 100644 --- a/src/render.cc +++ b/src/render.cc @@ -38,10 +38,10 @@ class RenderModule : public AbstractModule { public: RenderModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { RenderNode *node = new RenderNode(inst); @@ -55,8 +55,8 @@ AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiati if (v.type() == Value::NUMBER) node->convexity = (int)v.toDouble(); - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index b6edb8b..2f9a28b 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -45,10 +45,10 @@ class RotateExtrudeModule : public AbstractModule { public: RotateExtrudeModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { RotateExtrudeNode *node = new RotateExtrudeNode(inst); @@ -85,8 +85,8 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst node->scale = 1; if (node->filename.empty()) { - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } return node; diff --git a/src/surface.cc b/src/surface.cc index d8fa422..b3246c1 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -50,7 +50,7 @@ class SurfaceModule : public AbstractModule { public: SurfaceModule() { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; class SurfaceNode : public AbstractPolyNode @@ -69,7 +69,7 @@ public: virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; }; -AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { SurfaceNode *node = new SurfaceNode(inst); node->center = false; diff --git a/src/transform.cc b/src/transform.cc index cc026fb..ddf222a 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -50,10 +50,10 @@ class TransformModule : public AbstractModule public: transform_type_e type; TransformModule(transform_type_e type) : type(type) { } - virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; }; -AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { TransformNode *node = new TransformNode(inst); @@ -175,8 +175,8 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti } } - std::vector evaluatednodes = inst->evaluateChildren(evalctx); - node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end()); + std::vector instantiatednodes = inst->instantiateChildren(evalctx); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } diff --git a/src/typedefs.h b/src/typedefs.h index a6e9077..fd676e2 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -6,5 +6,6 @@ typedef std::pair Assignment; typedef std::vector AssignmentList; +typedef std::vector ModuleInstantiationList; #endif diff --git a/tests/cgalcachetest.cc b/tests/cgalcachetest.cc index b65a2c8..fbc7350 100644 --- a/tests/cgalcachetest.cc +++ b/tests/cgalcachetest.cc @@ -145,7 +145,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index afc3128..deaf080 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -118,7 +118,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgalstlsanitytest.cc b/tests/cgalstlsanitytest.cc index 49a3f8e..01ab5fb 100644 --- a/tests/cgalstlsanitytest.cc +++ b/tests/cgalstlsanitytest.cc @@ -100,7 +100,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc index b7ae669..5e8803a 100644 --- a/tests/cgaltest.cc +++ b/tests/cgaltest.cc @@ -97,7 +97,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc index f4a88e0..8b98190 100644 --- a/tests/csgtermtest.cc +++ b/tests/csgtermtest.cc @@ -93,7 +93,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); Tree tree(root_node); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 6da6411..8cae5ef 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -154,7 +154,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc index 3e26814..be2dc34 100644 --- a/tests/csgtexttest.cc +++ b/tests/csgtexttest.cc @@ -97,7 +97,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); Tree tree; tree.setRoot(root_node); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index e0d2776..6e687d9 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -103,7 +103,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); Tree tree; tree.setRoot(root_node); @@ -131,7 +131,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); tree.setRoot(root_node); diff --git a/tests/echotest.cc b/tests/echotest.cc index 9924d11..96dd39e 100644 --- a/tests/echotest.cc +++ b/tests/echotest.cc @@ -105,7 +105,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); delete root_node; delete root_module; diff --git a/tests/modulecachetest.cc b/tests/modulecachetest.cc index 62f9543..fc9f325 100644 --- a/tests/modulecachetest.cc +++ b/tests/modulecachetest.cc @@ -94,7 +94,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); delete root_node; delete root_module; @@ -109,7 +109,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->evaluate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&root_ctx, &root_inst); delete root_node; delete root_module; diff --git a/tests/tests-common.cc b/tests/tests-common.cc index 703e1c5..ac85e37 100644 --- a/tests/tests-common.cc +++ b/tests/tests-common.cc @@ -7,9 +7,9 @@ #include #include -Module *parsefile(const char *filename) +FileModule *parsefile(const char *filename) { - Module *root_module = NULL; + FileModule *root_module = NULL; handle_dep(filename); std::ifstream ifs(filename); diff --git a/tests/tests-common.h b/tests/tests-common.h index 0047562..3393884 100644 --- a/tests/tests-common.h +++ b/tests/tests-common.h @@ -1,6 +1,6 @@ #ifndef TESTS_COMMON_H_ #define TESTS_COMMON_H_ -class Module *parsefile(const char *filename); +class FileModule *parsefile(const char *filename); #endif -- cgit v0.10.1 From 9b740b558dd627412e01a3521d5372d95e294af2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 24 Apr 2013 09:17:25 -0400 Subject: Further refactoring of scope/context mechanisms. Mostly related to the new FileContext class. Not quite there yet, but almost diff --git a/openscad.pro b/openscad.pro index 0f3394e..bd69dfe 100644 --- a/openscad.pro +++ b/openscad.pro @@ -216,6 +216,7 @@ HEADERS += src/typedefs.h \ src/function.h \ src/grid.h \ src/highlighter.h \ + src/localscope.h \ src/module.h \ src/node.h \ src/csgnode.h \ @@ -272,6 +273,7 @@ SOURCES += src/version_check.cc \ src/value.cc \ src/expr.cc \ src/func.cc \ + src/localscope.cc \ src/module.cc \ src/node.cc \ src/context.cc \ diff --git a/src/MainWindow.h b/src/MainWindow.h index 7bb008a..378705e 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -29,7 +29,7 @@ public: QTimer *autoReloadTimer; std::string autoReloadId; - ModuleContext root_ctx; + ModuleContext top_ctx; FileModule *root_module; // Result of parsing ModuleInstantiation root_inst; // Top level instance AbstractNode *absolute_root_node; // Result of tree evaluation diff --git a/src/builtin.cc b/src/builtin.cc index a8b60df..e116f17 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -16,12 +16,12 @@ Builtins *Builtins::instance(bool erase) void Builtins::init(const char *name, class AbstractModule *module) { - Builtins::instance()->rootmodule.scope.modules[name] = module; + Builtins::instance()->globalscope.modules[name] = module; } void Builtins::init(const char *name, class AbstractFunction *function) { - Builtins::instance()->rootmodule.scope.functions[name] = function; + Builtins::instance()->globalscope.functions[name] = function; } extern void register_builtin_functions(); @@ -80,18 +80,18 @@ std::string Builtins::isDeprecated(const std::string &name) Builtins::Builtins() { - this->rootmodule.scope.assignments.push_back(Assignment("$fn", new Expression(Value(0.0)))); - this->rootmodule.scope.assignments.push_back(Assignment("$fs", new Expression(Value(2.0)))); - this->rootmodule.scope.assignments.push_back(Assignment("$fa", new Expression(Value(12.0)))); - this->rootmodule.scope.assignments.push_back(Assignment("$t", new Expression(Value(0.0)))); + this->globalscope.assignments.push_back(Assignment("$fn", new Expression(Value(0.0)))); + this->globalscope.assignments.push_back(Assignment("$fs", new Expression(Value(2.0)))); + this->globalscope.assignments.push_back(Assignment("$fa", new Expression(Value(12.0)))); + this->globalscope.assignments.push_back(Assignment("$t", new Expression(Value(0.0)))); Value::VectorType zero3; zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); Value zero3val(zero3); - this->rootmodule.scope.assignments.push_back(Assignment("$vpt", new Expression(zero3val))); - this->rootmodule.scope.assignments.push_back(Assignment("$vpr", new Expression(zero3val))); + this->globalscope.assignments.push_back(Assignment("$vpt", new Expression(zero3val))); + this->globalscope.assignments.push_back(Assignment("$vpr", new Expression(zero3val))); } Builtins::~Builtins() diff --git a/src/builtin.h b/src/builtin.h index 564c951..9397aa9 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -4,6 +4,7 @@ #include #include #include "module.h" +#include "localscope.h" class Builtins { @@ -17,18 +18,13 @@ public: void initialize(); std::string isDeprecated(const std::string &name); - const FunctionContainer &functions() { return this->builtinfunctions; } - const ModuleContainer &modules() { return this->builtinmodules; } - - const Module &getRootModule() { return this->rootmodule; } + const LocalScope &getGlobalScope() { return this->globalscope; } private: Builtins(); ~Builtins(); - Module rootmodule; - FunctionContainer builtinfunctions; - ModuleContainer builtinmodules; + LocalScope globalscope; boost::unordered_map deprecations; }; diff --git a/src/context.h b/src/context.h index 5be1efd..9817df3 100644 --- a/src/context.h +++ b/src/context.h @@ -39,7 +39,7 @@ protected: ValueMap variables; ValueMap config_variables; - std::string document_path; + std::string document_path; // FIXME: This is a remnant only needed by dxfdim #ifdef DEBUG public: diff --git a/src/localscope.cc b/src/localscope.cc new file mode 100644 index 0000000..c4001f5 --- /dev/null +++ b/src/localscope.cc @@ -0,0 +1,67 @@ +#include "localscope.h" +#include "modcontext.h" +#include "module.h" +#include "typedefs.h" +#include "expression.h" +#include "function.h" + +#include + +LocalScope::LocalScope() +{ +} + +LocalScope::~LocalScope() +{ + BOOST_FOREACH (ModuleInstantiation *v, children) delete v; + BOOST_FOREACH (const Assignment &v, assignments) delete v.second; + BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; + BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; +} + +std::string LocalScope::dump(const std::string &indent) const +{ + std::stringstream dump; + BOOST_FOREACH(const FunctionContainer::value_type &f, this->functions) { + dump << f.second->dump(indent, f.first); + } + BOOST_FOREACH(const AbstractModuleContainer::value_type &m, this->modules) { + dump << m.second->dump(indent, m.first); + } + BOOST_FOREACH(const Assignment &ass, this->assignments) { + dump << indent << ass.first << " = " << *ass.second << ";\n"; + } + BOOST_FOREACH(const ModuleInstantiation *inst, this->children) { + dump << inst->dump(indent); + } + return dump.str(); +} + +// FIXME: Two parameters here is a hack. Rather have separate types of scopes, or check the type of the first parameter. Note const vs. non-const +std::vector LocalScope::instantiateChildren(const Context *evalctx, FileContext *filectx) const +{ + Context *c = filectx; + + if (!c) { + c = new Context(evalctx); + + // FIXME: If we make c a ModuleContext, child() doesn't work anymore + // c->functions_p = &this->functions; + // c->modules_p = &this->modules; + + BOOST_FOREACH (const Assignment &ass, this->assignments) { + c->set_variable(ass.first, ass.second->evaluate(c)); + } + } + + std::vector childnodes; + BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { + AbstractNode *node = modinst->evaluate(c); + if (node) childnodes.push_back(node); + } + + if (c != filectx) delete c; + + return childnodes; +} + diff --git a/src/localscope.h b/src/localscope.h index e631028..87f8430 100644 --- a/src/localscope.h +++ b/src/localscope.h @@ -12,7 +12,7 @@ public: size_t numElements() const { return assignments.size() + children.size(); } std::string dump(const std::string &indent) const; - std::vector instantiateChildren(const class Context *evalctx) const; + std::vector instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const; AssignmentList assignments; ModuleInstantiationList children; diff --git a/src/mainwin.cc b/src/mainwin.cc index 87ec744..027f72a 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -168,7 +168,7 @@ MainWindow::MainWindow(const QString &filename) this, SLOT(actionRenderCGALDone(CGAL_Nef_polyhedron *))); #endif - root_ctx.registerBuiltin(); + top_ctx.registerBuiltin(); this->openglbox = NULL; root_module = NULL; @@ -506,7 +506,7 @@ MainWindow::setFileName(const QString &filename) { if (filename.isEmpty()) { this->fileName.clear(); - this->root_ctx.setDocumentPath(currentdir); + this->top_ctx.setDocumentPath(currentdir); setWindowTitle("OpenSCAD - New Document[*]"); } else { @@ -522,7 +522,7 @@ MainWindow::setFileName(const QString &filename) this->fileName = fileinfo.fileName(); } - this->root_ctx.setDocumentPath(fileinfo.dir().absolutePath().toLocal8Bit().constData()); + this->top_ctx.setDocumentPath(fileinfo.dir().absolutePath().toLocal8Bit().constData()); QDir::setCurrent(fileinfo.dir().absolutePath()); } @@ -644,7 +644,7 @@ bool MainWindow::compile(bool reload, bool procevents) AbstractNode::resetIndexCounter(); this->root_inst = ModuleInstantiation("group"); - this->absolute_root_node = this->root_module->instantiate(&this->root_ctx, &this->root_inst, NULL); + this->absolute_root_node = this->root_module->instantiate(&top_ctx, &this->root_inst, NULL); if (this->absolute_root_node) { // Do we have an explicit root node (! modifier)? @@ -979,19 +979,19 @@ void MainWindow::pasteViewportRotation() void MainWindow::updateTemporalVariables() { - this->root_ctx.set_variable("$t", Value(this->e_tval->text().toDouble())); + this->top_ctx.set_variable("$t", Value(this->e_tval->text().toDouble())); Value::VectorType vpt; vpt.push_back(Value(-qglview->cam.object_trans.x())); vpt.push_back(Value(-qglview->cam.object_trans.y())); vpt.push_back(Value(-qglview->cam.object_trans.z())); - this->root_ctx.set_variable("$vpt", Value(vpt)); + this->top_ctx.set_variable("$vpt", Value(vpt)); Value::VectorType vpr; vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360))); vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360))); vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360))); - root_ctx.set_variable("$vpr", Value(vpr)); + top_ctx.set_variable("$vpr", Value(vpr)); } bool MainWindow::fileChangedOnDisk() diff --git a/src/modcontext.cc b/src/modcontext.cc index df341f9..44c2002 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -7,28 +7,18 @@ #include -ModuleContext::ModuleContext(const class Module *module, const Context *parent, const EvalContext *evalctx) - : Context(parent), functions_p(NULL), modules_p(NULL), usedlibs_p(NULL) +ModuleContext::ModuleContext(const Context *parent, const EvalContext *evalctx) + : Context(parent), functions_p(NULL), modules_p(NULL), evalctx(evalctx) { - if (module) setModule(*module, evalctx); } ModuleContext::~ModuleContext() { } -void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) +void ModuleContext::initializeModule(const class Module &module) { this->setVariables(module.definition_arguments, evalctx); - this->evalctx = evalctx; - - // FIXME: Hack - split out file context into separate class? - const FileModule *fm = dynamic_cast(&module); - if (fm) { - this->usedlibs_p = &(fm->usedlibs); - if (!fm->modulePath().empty()) this->document_path = fm->modulePath(); - } - // FIXME: Don't access module members directly this->functions_p = &module.scope.functions; this->modules_p = &module.scope.modules; @@ -37,17 +27,6 @@ void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) } } -/*! - Only used to initialize builtins for the top-level root context -*/ -void ModuleContext::registerBuiltin() -{ - // FIXME: built-ins only contains variables, setModule isn't really needed for this - // FIXME: Where to put set_variable from setModule? - this->setModule(Builtins::instance()->getRootModule()); - this->set_constant("PI",Value(M_PI)); -} - class RecursionGuard { public: @@ -61,60 +40,64 @@ private: const std::string &name; }; -Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const + +/*! + Only used to initialize builtins for the top-level root context +*/ +void ModuleContext::registerBuiltin() { - RecursionGuard g(*this, name); - if (g.recursion_detected()) { - PRINTB("Recursion detected calling function '%s'", name); - return Value(); + const LocalScope &scope = Builtins::instance()->getGlobalScope(); + + // FIXME: Don't access module members directly + this->functions_p = &scope.functions; + this->modules_p = &scope.modules; + BOOST_FOREACH(const Assignment &ass, scope.assignments) { + this->set_variable(ass.first, ass.second->evaluate(this)); } + this->set_constant("PI",Value(M_PI)); +} + +const AbstractFunction *ModuleContext::findLocalFunction(const std::string &name) const +{ if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) { - return this->functions_p->find(name)->second->evaluate(this, evalctx); + return this->functions_p->find(name)->second; } - - if (this->usedlibs_p) { - BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { - if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) { - ModuleContext ctx(m.second, this->parent); - // FIXME: Set document path -#if 0 && DEBUG - PRINTB("New lib Context for %s func:", name); - ctx.dump(NULL, NULL); -#endif - return m.second->scope.functions[name]->evaluate(&ctx, evalctx); - } - } - } - return Context::evaluate_function(name, evalctx); + return NULL; } -AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +const AbstractModule *ModuleContext::findLocalModule(const std::string &name) const { - if (this->modules_p && this->modules_p->find(inst.name()) != this->modules_p->end()) { - AbstractModule *m = this->modules_p->find(inst.name())->second; - std::string replacement = Builtins::instance()->isDeprecated(inst.name()); + if (this->modules_p && this->modules_p->find(name) != this->modules_p->end()) { + AbstractModule *m = this->modules_p->find(name)->second; + std::string replacement = Builtins::instance()->isDeprecated(name); if (!replacement.empty()) { - PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement); + PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", name % replacement); } - return m->instantiate(this, &inst, evalctx); + return m; } + return NULL; +} - if (this->usedlibs_p) { - BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { - assert(m.second); - if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { - ModuleContext ctx(m.second, this->parent); - // FIXME: Set document path -#if 0 && DEBUG - PRINT("New lib Context:"); - ctx.dump(NULL, &inst); -#endif - return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); - } - } +Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const +{ + RecursionGuard g(*this, name); + if (g.recursion_detected()) { + PRINTB("Recursion detected calling function '%s'", name); + return Value(); } + const AbstractFunction *foundf = findLocalFunction(name); + if (foundf) return foundf->evaluate(this, evalctx); + + return Context::evaluate_function(name, evalctx); +} + +AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +{ + const AbstractModule *foundm = this->findLocalModule(inst.name()); + if (foundm) return foundm->instantiate(this, &inst, evalctx); + return Context::instantiate_module(inst, evalctx); } @@ -150,10 +133,57 @@ void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *i } #endif -FileContext::FileContext(const class FileModule &module, - const Context *parent, const EvalContext *evalctx) - :ModuleContext(&module, parent, evalctx) +FileContext::FileContext(const class FileModule &module, const Context *parent) + : usedlibs(module.usedlibs), ModuleContext(parent) +{ + if (!module.modulePath().empty()) this->document_path = module.modulePath(); +} + +Value FileContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const { + RecursionGuard g(*this, name); + if (g.recursion_detected()) { + PRINTB("Recursion detected calling function '%s'", name); + return Value(); + } + + const AbstractFunction *foundf = findLocalFunction(name); + if (foundf) return foundf->evaluate(this, evalctx); + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { + if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) { + FileContext ctx(*m.second, this->parent); + ctx.initializeModule(*m.second); + // FIXME: Set document path +#if 0 && DEBUG + PRINTB("New lib Context for %s func:", name); + ctx.dump(NULL, NULL); +#endif + return m.second->scope.functions[name]->evaluate(&ctx, evalctx); + } + } + + return ModuleContext::evaluate_function(name, evalctx); } +AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +{ + const AbstractModule *foundm = this->findLocalModule(inst.name()); + if (foundm) return foundm->instantiate(this, &inst, evalctx); + + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { + assert(m.second); + if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { + FileContext ctx(*m.second, this->parent); + ctx.initializeModule(*m.second); + // FIXME: Set document path +#if 0 && DEBUG + PRINT("New file Context:"); + ctx.dump(NULL, &inst); +#endif + return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); + } + } + + return ModuleContext::instantiate_module(inst, evalctx); +} diff --git a/src/modcontext.h b/src/modcontext.h index d9965c5..4479051 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -14,18 +14,21 @@ class ModuleContext : public Context { public: - ModuleContext(const class Module *module = NULL, const Context *parent = NULL, const EvalContext *evalctx = NULL); + ModuleContext(const Context *parent = NULL, const EvalContext *evalctx = NULL); virtual ~ModuleContext(); - void setModule(const Module &module, const EvalContext *evalctx = NULL); + void initializeModule(const Module &m); void registerBuiltin(); + virtual Value evaluate_function(const std::string &name, + const EvalContext *evalctx) const; + virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, + const EvalContext *evalctx) const; - virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const; - virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; + const AbstractModule *findLocalModule(const std::string &name) const; + const AbstractFunction *findLocalFunction(const std::string &name) const; - const boost::unordered_map *functions_p; - const boost::unordered_map *modules_p; - const FileModule::ModuleContainer *usedlibs_p; + const LocalScope::FunctionContainer *functions_p; + const LocalScope::AbstractModuleContainer *modules_p; // FIXME: Points to the eval context for the call to this module. Not sure where it belongs const class EvalContext *evalctx; @@ -40,8 +43,14 @@ public: class FileContext : public ModuleContext { public: - FileContext(const class FileModule &module, const Context *parent = NULL, const EvalContext *evalctx = NULL); + FileContext(const class FileModule &module, const Context *parent); virtual ~FileContext() {} + virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const; + virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, + const EvalContext *evalctx) const; + +private: + const FileModule::ModuleContainer &usedlibs; }; #endif diff --git a/src/module.cc b/src/module.cc index a9e3cbf..e9a5169 100644 --- a/src/module.cc +++ b/src/module.cc @@ -40,50 +40,6 @@ namespace fs = boost::filesystem; #include #include -LocalScope::LocalScope() -{ -} - -LocalScope::~LocalScope() -{ - BOOST_FOREACH(ModuleInstantiation *v, children) delete v; - BOOST_FOREACH (const Assignment &v, assignments) delete v.second; - BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; - BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; -} - -std::string LocalScope::dump(const std::string &indent) const -{ - std::stringstream dump; - BOOST_FOREACH(const FunctionContainer::value_type &f, this->functions) { - dump << f.second->dump(indent, f.first); - } - BOOST_FOREACH(const AbstractModuleContainer::value_type &m, this->modules) { - dump << m.second->dump(indent, m.first); - } - BOOST_FOREACH(const Assignment &ass, this->assignments) { - dump << indent << ass.first << " = " << *ass.second << ";\n"; - } - BOOST_FOREACH(const ModuleInstantiation *inst, this->children) { - dump << inst->dump(indent); - } - return dump.str(); -} - -std::vector LocalScope::instantiateChildren(const Context *evalctx) const -{ - Context c(evalctx); // FIXME: Is this correct, or should we use the parent? - BOOST_FOREACH (const Assignment &ass, this->assignments) { - c.set_variable(ass.first, ass.second->evaluate(&c)); - } - std::vector childnodes; - BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { - AbstractNode *node = modinst->evaluate(&c); - if (node) childnodes.push_back(node); - } - return childnodes; -} - AbstractModule::~AbstractModule() { } @@ -183,14 +139,14 @@ void Module::addChild(ModuleInstantiation *ch) AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { - ModuleContext c(this, ctx, evalctx); - // FIXME: Set document path to the path of the module + ModuleContext c(ctx, evalctx); + c.initializeModule(*this); c.set_variable("$children", Value(double(inst->scope.children.size()))); + // FIXME: Set document path to the path of the module #if 0 && DEBUG c.dump(this, inst); #endif - // FIXME: this->scope.instantiateChildren(&c) and ModuleContext c() causes set_variable to be called twice, causing duplicate warning output in e.g. echotest_search-tests AbstractNode *node = new AbstractNode(inst); std::vector instantiatednodes = this->scope.instantiateChildren(&c); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); @@ -259,3 +215,20 @@ bool FileModule::handleDependencies() this->is_handling_dependencies = false; return changed; } + +AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +{ + assert(evalctx == NULL); + FileContext c(*this, ctx); + c.initializeModule(*this); + // FIXME: Set document path to the path of the module +#if 0 && DEBUG + c.dump(this, inst); +#endif + + AbstractNode *node = new AbstractNode(inst); + std::vector instantiatednodes = this->scope.instantiateChildren(ctx, &c); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); + + return node; +} diff --git a/src/module.h b/src/module.h index 39d4bba..b7ee23d 100644 --- a/src/module.h +++ b/src/module.h @@ -65,7 +65,7 @@ public: Module() { } virtual ~Module(); - virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + 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; void addChild(ModuleInstantiation *ch); @@ -75,6 +75,8 @@ public: LocalScope scope; }; +// FIXME: A FileModule doesn't have definition arguments, so we shouldn't really +// inherit from a Module class FileModule : public Module { public: @@ -85,6 +87,7 @@ public: const std::string &modulePath() const { return this->path; } void registerInclude(const std::string &filename); bool handleDependencies(); + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; typedef boost::unordered_map ModuleContainer; ModuleContainer usedlibs; diff --git a/src/openscad.cc b/src/openscad.cc index 96dcf4e..6a0d057 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -327,6 +327,14 @@ int main(int argc, char **argv) if (!filename) help(argv[0]); + // Top context - this context only holds builtins + ModuleContext top_ctx; + top_ctx.registerBuiltin(); + PRINT("Root Context:"); +#if 0 && DEBUG + top_ctx.dump(NULL, NULL); +#endif + FileModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; @@ -348,18 +356,12 @@ int main(int argc, char **argv) if (!root_module) exit(1); root_module->handleDependencies(); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); - PRINT("Root Context:"); -#if 0 && DEBUG - root_ctx.dump(NULL, NULL); -#endif fs::path fpath = boosty::absolute(fs::path(filename)); fs::path fparent = fpath.parent_path(); fs::current_path(fparent); AbstractNode::resetIndexCounter(); - absolute_root_node = root_module->instantiate(&root_ctx, &root_inst, NULL); + absolute_root_node = root_module->instantiate(&top_ctx, &root_inst, NULL); // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) diff --git a/testdata/scad/features/child-tests.scad b/testdata/scad/features/child-tests.scad index e4e3572..cf983b4 100644 --- a/testdata/scad/features/child-tests.scad +++ b/testdata/scad/features/child-tests.scad @@ -1,7 +1,7 @@ $fn=16; -module parent() { - for (i=[0:2]) { +module parent(range=[0:2]) { + for (i=range) { translate([2.5*i,0,0]) child(i); } } @@ -32,3 +32,6 @@ module parent3() { } translate([5,3,0]) parent3() { cube(); sphere(); } + +// Leaking variables to child list is not allowed +translate([0,6,0]) parent(range=[0:1], testvar=10) { sphere(); cube(testvar, center=true);} diff --git a/testdata/scad/misc/variable-scope-sub.scad b/testdata/scad/misc/variable-scope-sub.scad new file mode 100644 index 0000000..fda9520 --- /dev/null +++ b/testdata/scad/misc/variable-scope-sub.scad @@ -0,0 +1,24 @@ +sub_global = 15; + +module submodule() { + echo($children); + echo(submodule_var); + submodule_var = 16; + module subsubmodule() { + echo($children); + subsubmodule_var = 17; + echo(subsubmodule_var); + child(0); + } + subsubmodule() {child(0); sphere();} +} + +module submodule2() { + echo(sub_global); + echo($children); +} + +module submain() { + echo(global_var); // Undefined global var + submodule() {submodule2() sphere(); cube();} +} diff --git a/testdata/scad/misc/variable-scope-tests.scad b/testdata/scad/misc/variable-scope-tests.scad new file mode 100644 index 0000000..8426fbb --- /dev/null +++ b/testdata/scad/misc/variable-scope-tests.scad @@ -0,0 +1,53 @@ +echo("special variable inheritance"); +module special_module(a) { + echo(a, $fn); + special_module2(a); +} + +module special_module2(b) { + echo(a); + echo(b, $fn); +} + +special_module(23, $fn=5); + +echo("inner variables shadows parameter"); +module inner_variables(a, b) { + b = 24; + echo(a, b); +} + +inner_variables(5, 6); + +echo("user-defined special variables as parameter"); +module user_defined_special($b) { + echo($b); + user_defined_special2(); +} + +module user_defined_special2() { + echo($b); +} + +user_defined_special(7); + +echo("assign only visible in children's scope"); +module assigning() { + echo(c); +} + +module assigning2(c) { + echo(c); +} + +assign(c=5) { + assigning(); + assigning2(c); +} + +echo("undeclared variable can still be passed and used"); +module undeclared_var() { + echo(d); +} + +undeclared_var(d=6); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index de4bab7..909c8ed 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -402,6 +402,7 @@ set(CORE_SOURCES ../src/value.cc ../src/expr.cc ../src/func.cc + ../src/localscope.cc ../src/module.cc ../src/ModuleCache.cc ../src/node.cc @@ -751,7 +752,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad) list(APPEND DUMPTEST_FILES ${MINIMAL_FILES} ${FEATURES_FILES} ${EXAMPLE_FILES}) list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad diff --git a/tests/cgalcachetest.cc b/tests/cgalcachetest.cc index fbc7350..67d3313 100644 --- a/tests/cgalcachetest.cc +++ b/tests/cgalcachetest.cc @@ -129,10 +129,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); root_module = parsefile(filename); @@ -145,7 +145,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index deaf080..81fc6b4 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -102,10 +102,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); root_module = parsefile(filename); @@ -118,7 +118,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgalstlsanitytest.cc b/tests/cgalstlsanitytest.cc index 01ab5fb..4be7767 100644 --- a/tests/cgalstlsanitytest.cc +++ b/tests/cgalstlsanitytest.cc @@ -84,10 +84,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); root_module = parsefile(filename); @@ -100,7 +100,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc index 5e8803a..d750da9 100644 --- a/tests/cgaltest.cc +++ b/tests/cgaltest.cc @@ -81,10 +81,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); root_module = parsefile(filename); @@ -97,7 +97,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc index 8b98190..1460bbd 100644 --- a/tests/csgtermtest.cc +++ b/tests/csgtermtest.cc @@ -76,10 +76,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); const AbstractNode *root_node; @@ -93,7 +93,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); Tree tree(root_node); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 8cae5ef..320b533 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -132,10 +132,10 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); if (sysinfo_dump) @@ -154,7 +154,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) } AbstractNode::resetIndexCounter(); - AbstractNode *absolute_root_node = root_module->instantiate(&root_ctx, &root_inst); + AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); AbstractNode *root_node; // Do we have an explicit root node (! modifier)? if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node; diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc index be2dc34..97902f6 100644 --- a/tests/csgtexttest.cc +++ b/tests/csgtexttest.cc @@ -80,10 +80,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; @@ -97,7 +97,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); Tree tree; tree.setRoot(root_node); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index 6e687d9..e4876fa 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -74,7 +74,6 @@ int main(int argc, char **argv) const char *filename = argv[1]; const char *outfilename = argv[2]; - int rc = 0; Builtins::instance()->initialize(); @@ -86,10 +85,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; @@ -103,7 +102,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); Tree tree; tree.setRoot(root_node); @@ -115,10 +114,17 @@ int main(int argc, char **argv) exit(1); } + fs::current_path(original_path); std::ofstream outfile; outfile.open(outfilename); + if (!outfile.is_open()) { + fprintf(stderr, "Error: Unable to open output file %s\n", outfilename); + exit(1); + } + std::cout << "Opened " << outfilename << "\n"; outfile << dumpstdstr << "\n"; outfile.close(); + if (outfile.fail()) fprintf(stderr, "Failed to close file\n"); delete root_node; delete root_module; @@ -131,7 +137,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); tree.setRoot(root_node); diff --git a/tests/echotest.cc b/tests/echotest.cc index 96dd39e..3051751 100644 --- a/tests/echotest.cc +++ b/tests/echotest.cc @@ -88,10 +88,10 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; + FileModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; @@ -105,7 +105,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); delete root_node; delete root_module; diff --git a/tests/modulecachetest.cc b/tests/modulecachetest.cc index fc9f325..5531461 100644 --- a/tests/modulecachetest.cc +++ b/tests/modulecachetest.cc @@ -76,14 +76,13 @@ int main(int argc, char **argv) parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); - ModuleContext root_ctx; - root_ctx.registerBuiltin(); + ModuleContext top_ctx; + top_ctx.registerBuiltin(); - AbstractModule *root_module; ModuleInstantiation root_inst("group"); AbstractNode *root_node; - root_module = parsefile(filename); + FileModule *root_module = parsefile(filename); if (!root_module) { fprintf(stderr, "Error: Unable to parse input file\n"); exit(1); @@ -94,7 +93,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); delete root_node; delete root_module; @@ -109,7 +108,7 @@ int main(int argc, char **argv) } AbstractNode::resetIndexCounter(); - root_node = root_module->instantiate(&root_ctx, &root_inst); + root_node = root_module->instantiate(&top_ctx, &root_inst); delete root_node; delete root_module; diff --git a/tests/regression/cgalpngtest/child-tests-expected.png b/tests/regression/cgalpngtest/child-tests-expected.png index ed6207c..eb34f18 100644 Binary files a/tests/regression/cgalpngtest/child-tests-expected.png and b/tests/regression/cgalpngtest/child-tests-expected.png differ diff --git a/tests/regression/dumptest/child-tests-expected.txt b/tests/regression/dumptest/child-tests-expected.txt index 9a886fe..e1a7557 100644 --- a/tests/regression/dumptest/child-tests-expected.txt +++ b/tests/regression/dumptest/child-tests-expected.txt @@ -37,4 +37,16 @@ multmatrix([[1, 0, 0, 5], [0, 1, 0, 3], [0, 0, 1, 0], [0, 0, 0, 1]]) { group(); } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 6], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + sphere($fn = 16, $fa = 12, $fs = 2, r = 1); + } + multmatrix([[1, 0, 0, 2.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [1, 1, 1], center = true); + } + } + } + } diff --git a/tests/regression/echotest/variable-scope-tests-expected.txt b/tests/regression/echotest/variable-scope-tests-expected.txt new file mode 100644 index 0000000..92db05d --- /dev/null +++ b/tests/regression/echotest/variable-scope-tests-expected.txt @@ -0,0 +1,16 @@ +ECHO: "special variable inheritance" +ECHO: 23, 5 +WARNING: Ignoring unknown variable 'a'. +ECHO: undef +ECHO: 23, 5 +ECHO: "inner variables shadows parameter" +ECHO: 5, 24 +ECHO: "user-defined special variables as parameter" +ECHO: 7 +ECHO: 7 +ECHO: "assign only visible in children's scope" +WARNING: Ignoring unknown variable 'c'. +ECHO: undef +ECHO: 5 +ECHO: "undeclared variable can still be passed and used" +ECHO: 6 diff --git a/tests/regression/opencsgtest/child-tests-expected.png b/tests/regression/opencsgtest/child-tests-expected.png index e8ea39b..2ff902c 100644 Binary files a/tests/regression/opencsgtest/child-tests-expected.png and b/tests/regression/opencsgtest/child-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/child-tests-expected.png b/tests/regression/throwntogethertest/child-tests-expected.png index 561334e..2ff902c 100644 Binary files a/tests/regression/throwntogethertest/child-tests-expected.png and b/tests/regression/throwntogethertest/child-tests-expected.png differ -- cgit v0.10.1 From 81266c34a121108e876577cf7dc7c4cf466c15a1 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 26 Apr 2013 17:41:41 -0400 Subject: Re-added donb's patch for handling deprecated parameters to import diff --git a/src/import.cc b/src/import.cc index da79322..bd8f830 100644 --- a/src/import.cc +++ b/src/import.cc @@ -93,10 +93,10 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti Value v = c.lookup_variable("file"); if (v.isUndefined()) { v = c.lookup_variable("filename"); - if (!v.isUndefined()) - PRINT("WARNING: filename= is deprecated. Please use file="); + if (!v.isUndefined()) { + PRINT("DEPRECATED: filename= is deprecated. Please use file="); + } } - std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { @@ -116,9 +116,10 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti node->filename = filename; Value layerval = c.lookup_variable("layer", true); if (layerval.isUndefined()) { - layerval = c.lookup_variable("layername",true); - if (!layerval.isUndefined()) - PRINT("WARNING: layername= is deprecated. Please use layer="); + layerval = c.lookup_variable("layername"); + if (!layerval.isUndefined()) { + PRINT("DEPRECATED: layername= is deprecated. Please use layer="); + } } node->layername = layerval.isUndefined() ? "" : layerval.toString(); node->convexity = c.lookup_variable("convexity", true).toDouble(); -- cgit v0.10.1 From ba20c0e800566c649a8e48937a71c849e5aba96a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 26 Apr 2013 18:32:19 -0400 Subject: Modified parse to allow overloading of variables in local blocks. Also did some minor cleanups while at it. Test cases missing diff --git a/bison.pri b/bison.pri index 7a63f0e..d2972d6 100644 --- a/bison.pri +++ b/bison.pri @@ -1,4 +1,4 @@ -win32 { +{ bison.name = Bison ${QMAKE_FILE_IN} bison.input = BISONSOURCES bison.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}_yacc.cpp diff --git a/flex.pri b/flex.pri index 203d90d..0813300 100644 --- a/flex.pri +++ b/flex.pri @@ -1,4 +1,4 @@ -win32 { +{ flex.name = Flex ${QMAKE_FILE_IN} flex.input = FLEXSOURCES flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp diff --git a/openscad.pro b/openscad.pro index bd69dfe..81f5e6f 100644 --- a/openscad.pro +++ b/openscad.pro @@ -171,13 +171,8 @@ CONFIG(mingw-cross-env) { include(mingw-cross-env.pri) } -win32 { - FLEXSOURCES = src/lexer.l - BISONSOURCES = src/parser.y -} else { - LEXSOURCES += src/lexer.l - YACCSOURCES += src/parser.y -} +FLEXSOURCES = src/lexer.l +BISONSOURCES = src/parser.y RESOURCES = openscad.qrc diff --git a/src/expr.cc b/src/expr.cc index 6629bf5..985a53a 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -38,6 +38,20 @@ Expression::Expression() { } +Expression::Expression(const std::string &type, + Expression *left, Expression *right) + : type(type) +{ + this->children.push_back(left); + this->children.push_back(right); +} + +Expression::Expression(const std::string &type, Expression *expr) + : type(type) +{ + this->children.push_back(expr); +} + Expression::Expression(const Value &val) : const_value(val), type("C") { } diff --git a/src/expression.h b/src/expression.h index 06becc0..6c03f52 100644 --- a/src/expression.h +++ b/src/expression.h @@ -34,6 +34,8 @@ public: Expression(); Expression(const Value &val); + Expression(const std::string &type, Expression *left, Expression *right); + Expression(const std::string &type, Expression *expr); ~Expression(); Value evaluate(const class Context *context) const; diff --git a/src/localscope.cc b/src/localscope.cc index c4001f5..eecff91 100644 --- a/src/localscope.cc +++ b/src/localscope.cc @@ -19,6 +19,12 @@ LocalScope::~LocalScope() BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; } +void LocalScope::addChild(ModuleInstantiation *ch) +{ + assert(ch != NULL); + this->children.push_back(ch); +} + std::string LocalScope::dump(const std::string &indent) const { std::stringstream dump; diff --git a/src/localscope.h b/src/localscope.h index 87f8430..d81a27c 100644 --- a/src/localscope.h +++ b/src/localscope.h @@ -13,6 +13,7 @@ public: size_t numElements() const { return assignments.size() + children.size(); } std::string dump(const std::string &indent) const; std::vector instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const; + void addChild(ModuleInstantiation *ch); AssignmentList assignments; ModuleInstantiationList children; diff --git a/src/module.cc b/src/module.cc index e9a5169..9503f05 100644 --- a/src/module.cc +++ b/src/module.cc @@ -132,11 +132,6 @@ Module::~Module() { } -void Module::addChild(ModuleInstantiation *ch) -{ - this->scope.children.push_back(ch); -} - AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ModuleContext c(ctx, evalctx); diff --git a/src/module.h b/src/module.h index b7ee23d..8f1ccb7 100644 --- a/src/module.h +++ b/src/module.h @@ -68,8 +68,6 @@ 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; - void addChild(ModuleInstantiation *ch); - AssignmentList definition_arguments; LocalScope scope; diff --git a/src/parser.y b/src/parser.y index 0cd1fbd..272f801 100644 --- a/src/parser.y +++ b/src/parser.y @@ -56,8 +56,7 @@ int lexerlex_destroy(void); int lexerlex(void); - std::vector module_stack; - Module *currmodule; + std::stack scope_stack; FileModule *rootmodule; extern void lexerdestroy(); @@ -74,7 +73,6 @@ class Value *value; class Expression *expr; class ModuleInstantiation *inst; - std::vector *instvec; class IfElseModuleInstantiation *ifelse; Assignment *arg; AssignmentList *args; @@ -115,8 +113,6 @@ %type module_instantiation %type if_statement %type ifelse_statement -%type children_instantiation -%type module_instantiation_list %type single_module_instantiation %type arguments_call @@ -138,89 +134,66 @@ inner_input: /* empty */ | statement inner_input ; -statement: -';' | -'{' inner_input '}' | -module_instantiation { - if ($1) { - currmodule->addChild($1); - } else { - delete $1; - } -} | +assignment: TOK_ID '=' expr ';' { - for (AssignmentList::iterator iter = currmodule->scope.assignments.begin(); - iter != currmodule->scope.assignments.end(); + for (AssignmentList::iterator iter = scope_stack.top()->assignments.begin(); + iter != scope_stack.top()->assignments.end(); iter++) { if (iter->first == $1) { - currmodule->scope.assignments.erase(iter); + scope_stack.top()->assignments.erase(iter); break; } } - currmodule->scope.assignments.push_back(Assignment($1, $3)); + scope_stack.top()->assignments.push_back(Assignment($1, $3)); +} ; + +statement: +';' | +'{' inner_input '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); } | +assignment | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { - Module *p = currmodule; - module_stack.push_back(currmodule); - currmodule = new Module(); - p->scope.modules[$2] = currmodule; - currmodule->definition_arguments = *$4; + Module *newmodule = new Module(); + newmodule->definition_arguments = *$4; + scope_stack.top()->modules[$2] = newmodule; + scope_stack.push(&newmodule->scope); free($2); delete $4; } statement { - currmodule = module_stack.back(); - module_stack.pop_back(); + scope_stack.pop(); } | TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { Function *func = new Function(); func->definition_arguments = *$4; func->expr = $8; - currmodule->scope.functions[$2] = func; + scope_stack.top()->functions[$2] = func; free($2); delete $4; } ';' ; - -/* Will return a dummy parent node with zero or more children */ -children_instantiation: -module_instantiation { - $$ = new std::vector; - if ($1) { - $$->push_back($1); - } -} | -'{' module_instantiation_list '}' { - $$ = $2; -} ; if_statement: -TOK_IF '(' expr ')' children_instantiation { - $$ = new IfElseModuleInstantiation(); - $$->arguments.push_back(Assignment("", $3)); - $$->setPath(parser_source_path); - - if ($$) { - $$->scope.children = *$5; - } else { - for (size_t i = 0; i < $5->size(); i++) - delete (*$5)[i]; - } - delete $5; -} ; +TOK_IF '(' expr ')' { + $if = new IfElseModuleInstantiation(); + $if->arguments.push_back(Assignment("", $3)); + $if->setPath(parser_source_path); + scope_stack.push(&$if->scope); +}[if] child_statement { + scope_stack.pop(); + $$ = $if; + } ; ifelse_statement: if_statement { $$ = $1; } | -if_statement TOK_ELSE children_instantiation { +if_statement TOK_ELSE { + scope_stack.push(&$1->else_scope); +}[else] child_statement { + scope_stack.pop(); $$ = $1; - if ($$) { - $$->else_scope.children = *$3; - } else { - for (size_t i = 0; i < $3->size(); i++) - delete (*$3)[i]; - } - delete $3; -} ; + } ; module_instantiation: '!' module_instantiation { @@ -239,35 +212,28 @@ module_instantiation: delete $2; $$ = NULL; } | -single_module_instantiation ';' { - $$ = $1; -} | -single_module_instantiation children_instantiation { - $$ = $1; - if ($$) { - $$->scope.children = *$2; - } else { - for (size_t i = 0; i < $2->size(); i++) - delete (*$2)[i]; - } - delete $2; +single_module_instantiation { + $inst = $1; + scope_stack.push(&$inst->scope); +}[inst] child_statement { + scope_stack.pop(); + $$ = $inst; + } | + ifelse_statement { + $$ = $1; + } ; + +child_statement: +';' | +'{' child_statements '}' | +module_instantiation { + if ($1) scope_stack.top()->addChild($1); } | -ifelse_statement { - $$ = $1; -} ; +assignment ; -module_instantiation_list: -/* empty */ { - $$ = new std::vector; -} | -module_instantiation_list module_instantiation { - $$ = $1; - if ($$) { - if ($2) $$->push_back($2); - } else { - delete $2; - } -} ; +child_statements: +/* empty */ | +child_statements child_statement ; single_module_instantiation: TOK_ID '(' arguments_call ')' { @@ -295,9 +261,7 @@ TOK_ID { free($1); } | expr '.' TOK_ID { - $$ = new Expression(); - $$->type = "N"; - $$->children.push_back($1); + $$ = new Expression("N", $1); $$->var_name = $3; free($3); } | @@ -330,95 +294,52 @@ TOK_NUMBER { $$ = $2; } | expr '*' expr { - $$ = new Expression(); - $$->type = "*"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("*", $1, $3); } | expr '/' expr { - $$ = new Expression(); - $$->type = "/"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("/", $1, $3); } | expr '%' expr { - $$ = new Expression(); - $$->type = "%"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("%", $1, $3); } | expr '+' expr { - $$ = new Expression(); - $$->type = "+"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("+", $1, $3); } | expr '-' expr { - $$ = new Expression(); - $$->type = "-"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("-", $1, $3); } | expr '<' expr { - $$ = new Expression(); - $$->type = "<"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("<", $1, $3); } | expr LE expr { - $$ = new Expression(); - $$->type = "<="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("<=", $1, $3); } | expr EQ expr { - $$ = new Expression(); - $$->type = "=="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("==", $1, $3); } | expr NE expr { - $$ = new Expression(); - $$->type = "!="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("!=", $1, $3); } | expr GE expr { - $$ = new Expression(); - $$->type = ">="; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression(">=", $1, $3); } | expr '>' expr { - $$ = new Expression(); - $$->type = ">"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression(">", $1, $3); } | expr AND expr { - $$ = new Expression(); - $$->type = "&&"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("&&", $1, $3); } | expr OR expr { - $$ = new Expression(); - $$->type = "||"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("||", $1, $3); } | '+' expr { $$ = $2; } | '-' expr { - $$ = new Expression(); - $$->type = "I"; - $$->children.push_back($2); + $$ = new Expression("I", $2); } | '!' expr { - $$ = new Expression(); - $$->type = "!"; - $$->children.push_back($2); + $$ = new Expression("!", $2); } | '(' expr ')' { $$ = $2; @@ -431,10 +352,7 @@ expr '?' expr ':' expr { $$->children.push_back($5); } | expr '[' expr ']' { - $$ = new Expression(); - $$->type = "[]"; - $$->children.push_back($1); - $$->children.push_back($3); + $$ = new Expression("[]", $1, $3); } | TOK_ID '(' arguments_call ')' { $$ = new Expression(); @@ -450,9 +368,7 @@ optional_commas: vector_expr: expr { - $$ = new Expression(); - $$->type = 'V'; - $$->children.push_back($1); + $$ = new Expression("V", $1); } | vector_expr ',' optional_commas expr { $$ = $1; @@ -519,7 +435,6 @@ void yyerror (char const *s) { // FIXME: We leak memory on parser errors... PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); - currmodule = NULL; } FileModule *parse(const char *text, const char *path, int debug) @@ -529,10 +444,9 @@ FileModule *parse(const char *text, const char *path, int debug) parser_input_buffer = text; parser_source_path = boosty::absolute(std::string(path)).string(); - module_stack.clear(); rootmodule = new FileModule(); - currmodule = rootmodule; rootmodule->setModulePath(path); + scope_stack.push(&rootmodule->scope); // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule); parserdebug = debug; @@ -543,5 +457,6 @@ FileModule *parse(const char *text, const char *path, int debug) if (parserretval != 0) return NULL; parser_error_pos = -1; + scope_stack.pop(); return rootmodule; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 909c8ed..51abd06 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,7 +13,11 @@ include(CMakeParseArguments.cmake) # Detect Lion and force gcc IF (APPLE) EXECUTE_PROCESS(COMMAND sw_vers -productVersion OUTPUT_VARIABLE MACOSX_VERSION) - IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.7.0") + IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.8.0") + message("Detected Mountain Lion or later") + set(CMAKE_C_COMPILER "gcc") + set(CMAKE_CXX_COMPILER "g++") + ELSEIF (NOT ${MACOSX_VERSION} VERSION_LESS "10.7.0") message("Detected Lion or later") set(CMAKE_C_COMPILER "gcc") set(CMAKE_CXX_COMPILER "g++") @@ -325,9 +329,8 @@ if (WIN32) set(FLEX_UNISTD_FLAG "-DYY_NO_UNISTD_H") endif() FLEX_TARGET(OpenSCADlexer ../src/lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "-Plexer ${FLEX_UNISTD_FLAG}") -BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c COMPILE_FLAGS "-p parser") +BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp COMPILE_FLAGS "-p parser") ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser) -set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX") # CGAL -- cgit v0.10.1 From 886bc85eec1b3d4c0f10c82a7e90adb15dddfe47 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 27 Apr 2013 00:53:41 -0400 Subject: Fixes remaining dxfdim() issue from #217 diff --git a/src/dxfdim.cc b/src/dxfdim.cc index ecdae80..555ed49 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -54,7 +54,7 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) // See issue #217 for (size_t i = 0; i < evalctx->numArgs(); i++) { if (evalctx->getArgName(i) == "file") - filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString()); + filename = evalctx->getAbsolutePath(evalctx->getArgValue(i).toString()); if (evalctx->getArgName(i) == "layer") layername = evalctx->getArgValue(i).toString(); if (evalctx->getArgName(i) == "origin") diff --git a/src/expr.cc b/src/expr.cc index 985a53a..746c0e3 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -142,12 +142,6 @@ Value Expression::evaluate(const Context *context) const } if (this->type == "F") { EvalContext c(context, this->call_arguments); - // Value::VectorType argvalues; - // std::transform(this->children.begin(), this->children.end(), - // std::back_inserter(argvalues), - // boost::bind(&Expression::evaluate, _1, context)); - // for (size_t i=0; i < this->children.size(); i++) - // argvalues.push_back(this->children[i]->evaluate(context)); return context->evaluate_function(this->call_funcname, &c); } abort(); diff --git a/testdata/scad/misc/localfiles_dir/localfiles_module.scad b/testdata/scad/misc/localfiles_dir/localfiles_module.scad index b98a49b..2611e71 100644 --- a/testdata/scad/misc/localfiles_dir/localfiles_module.scad +++ b/testdata/scad/misc/localfiles_dir/localfiles_module.scad @@ -5,6 +5,5 @@ module localfiles_module() translate([0,350,0]) rotate_extrude(file="localfile.dxf"); translate([250,0,0]) scale([200,200,50]) surface("localfile.dat"); - // This is not supported: - // echo(dxf_dim(file="localfile.dxf", name="localfile")); + translate([0,-200,0]) sphere(r=dxf_dim(file="localfile.dxf", name="localfile")/2); } diff --git a/tests/regression/cgalpngtest/localfiles-test-expected.png b/tests/regression/cgalpngtest/localfiles-test-expected.png index 3ad3d96..d0cfd50 100644 Binary files a/tests/regression/cgalpngtest/localfiles-test-expected.png and b/tests/regression/cgalpngtest/localfiles-test-expected.png differ diff --git a/tests/regression/dumptest/localfiles-test-expected.txt b/tests/regression/dumptest/localfiles-test-expected.txt index acdf7e7..7a84e88 100644 --- a/tests/regression/dumptest/localfiles-test-expected.txt +++ b/tests/regression/dumptest/localfiles-test-expected.txt @@ -13,5 +13,8 @@ surface(file = "localfiles_dir/localfile.dat", center = false); } } + multmatrix([[1, 0, 0, 0], [0, 1, 0, -200], [0, 0, 1, 0], [0, 0, 0, 1]]) { + sphere($fn = 0, $fa = 12, $fs = 2, r = 100); + } } diff --git a/tests/regression/opencsgtest/localfiles-test-expected.png b/tests/regression/opencsgtest/localfiles-test-expected.png index 7bc7909..f280efd 100644 Binary files a/tests/regression/opencsgtest/localfiles-test-expected.png and b/tests/regression/opencsgtest/localfiles-test-expected.png differ diff --git a/tests/regression/throwntogethertest/localfiles-test-expected.png b/tests/regression/throwntogethertest/localfiles-test-expected.png index 7bc7909..f280efd 100644 Binary files a/tests/regression/throwntogethertest/localfiles-test-expected.png and b/tests/regression/throwntogethertest/localfiles-test-expected.png differ -- cgit v0.10.1 From 5c3d35622a6b9c87d1e7a97a6d5fcbcbb8d9ccf9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 27 Apr 2013 01:01:03 -0400 Subject: sync diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 65ff3a3..c53de47 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,6 +11,7 @@ o Commandline output to PNG, with various camera and rendering settings o resize() command introduced o Regression test now creates single monolithic .html file for easier uploading o value reassignment is now less strict +o value assignments in parameters can now depend on already declared parameters Bugfixes: o Importing files is now always relative to the importing script, also for libraries -- cgit v0.10.1 From c4cae2a29a7df82f4f1b43543e6b22b642a275b0 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 2 May 2013 22:11:23 -0400 Subject: Fixes crash if hull's children are empty objects. Fixes #345 diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index 6ad9e4d..d0140fa 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -141,6 +141,9 @@ CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node) PRINT("WARNING: hull() does not support mixing 2D and 3D objects."); continue; } + if (chN.isNull()) { // If one of the children evaluated to a null object + continue; + } if (dim == 2) { CGAL_Nef_polyhedron2::Explorer explorer = chN.p2->explorer(); BOOST_FOREACH(const CGAL_Nef_polyhedron2::Explorer::Vertex &vh, diff --git a/testdata/scad/features/hull2-tests.scad b/testdata/scad/features/hull2-tests.scad index e656e6a..82b56e4 100644 --- a/testdata/scad/features/hull2-tests.scad +++ b/testdata/scad/features/hull2-tests.scad @@ -31,7 +31,15 @@ module hull2dForLoop() { } } +module hull2null() { + hull() { + square(0); + circle(0); + } +} + convex2dHole(); translate([40,0,0]) convex2dSimple(); translate([0,-20,0]) concave2dSimple(); translate([30,-25,0]) hull2dForLoop(); +hull2null(); \ No newline at end of file diff --git a/testdata/scad/features/hull3-tests.scad b/testdata/scad/features/hull3-tests.scad index e3fc8e7..0f48b8f 100644 --- a/testdata/scad/features/hull3-tests.scad +++ b/testdata/scad/features/hull3-tests.scad @@ -26,3 +26,12 @@ translate([-5,-5,-5]) { } } } + +module hull3null() { + hull() { + cube(0); + sphere(0); + } +} +hull3null(); + diff --git a/tests/regression/dumptest/hull2-tests-expected.txt b/tests/regression/dumptest/hull2-tests-expected.txt index e4c5a5b..c14282f 100644 --- a/tests/regression/dumptest/hull2-tests-expected.txt +++ b/tests/regression/dumptest/hull2-tests-expected.txt @@ -56,4 +56,10 @@ } } } + group() { + hull() { + square(size = [0, 0], center = false); + circle($fn = 0, $fa = 12, $fs = 2, r = 0); + } + } diff --git a/tests/regression/dumptest/hull3-tests-expected.txt b/tests/regression/dumptest/hull3-tests-expected.txt index 4c05e2c..f8def3b 100644 --- a/tests/regression/dumptest/hull3-tests-expected.txt +++ b/tests/regression/dumptest/hull3-tests-expected.txt @@ -27,4 +27,10 @@ } } } + group() { + hull() { + cube(size = [0, 0, 0], center = false); + sphere($fn = 0, $fa = 12, $fs = 2, r = 0); + } + } -- cgit v0.10.1 From ada8185c769784d11381a78c925531efb9980777 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 5 May 2013 01:17:18 +0200 Subject: Backported to bison 2.4 diff --git a/src/parser.y b/src/parser.y index 272f801..464f992 100644 --- a/src/parser.y +++ b/src/parser.y @@ -175,13 +175,13 @@ TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { if_statement: TOK_IF '(' expr ')' { - $if = new IfElseModuleInstantiation(); - $if->arguments.push_back(Assignment("", $3)); - $if->setPath(parser_source_path); - scope_stack.push(&$if->scope); -}[if] child_statement { + $$ = new IfElseModuleInstantiation(); + $$->arguments.push_back(Assignment("", $3)); + $$->setPath(parser_source_path); + scope_stack.push(&$$->scope); +} child_statement { scope_stack.pop(); - $$ = $if; + $$ = $5; } ; ifelse_statement: @@ -190,7 +190,7 @@ if_statement { } | if_statement TOK_ELSE { scope_stack.push(&$1->else_scope); -}[else] child_statement { +} child_statement { scope_stack.pop(); $$ = $1; } ; @@ -213,11 +213,11 @@ module_instantiation: $$ = NULL; } | single_module_instantiation { - $inst = $1; - scope_stack.push(&$inst->scope); -}[inst] child_statement { + $$ = $1; + scope_stack.push(&$1->scope); +} child_statement { scope_stack.pop(); - $$ = $inst; + $$ = $2; } | ifelse_statement { $$ = $1; -- cgit v0.10.1 From ffe750d87e747a57f7bf85281b87e4894cbf92b2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 5 May 2013 01:22:02 +0200 Subject: Temporarily deactivate new feature: variable declarations in child block diff --git a/src/parser.y b/src/parser.y index 464f992..2b07f14 100644 --- a/src/parser.y +++ b/src/parser.y @@ -228,8 +228,13 @@ child_statement: '{' child_statements '}' | module_instantiation { if ($1) scope_stack.top()->addChild($1); -} | +} ; + +/* + FIXME: This allows for variable declaration in child blocks, not activated yet + | assignment ; +*/ child_statements: /* empty */ | -- cgit v0.10.1 From d4bc01d46c246e18fe1f795edb4533e130f9116a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 8 May 2013 00:00:09 +0200 Subject: New feature: Drag and drop stl, off or dxf files will create an import statement diff --git a/Info.plist b/Info.plist index 506bab7..84b270f 100644 --- a/Info.plist +++ b/Info.plist @@ -38,6 +38,36 @@ LSIsAppleDefaultForType + + CFBundleTypeExtensions + + stl + + CFBundleTypeName + STL 3D file + CFBundleTypeRole + Viewer + + + CFBundleTypeExtensions + + off + + CFBundleTypeName + OFF 3D file + CFBundleTypeRole + Viewer + + + CFBundleTypeExtensions + + dxf + + CFBundleTypeName + DXF file + CFBundleTypeRole + Viewer + NSAppleScriptEnabled diff --git a/src/mainwin.cc b/src/mainwin.cc index 027f72a..dc6d85c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -488,17 +488,25 @@ void MainWindow::requestOpenFile(const QString &) void MainWindow::openFile(const QString &new_filename) { + QString actual_filename; #ifdef ENABLE_MDI if (!editor->toPlainText().isEmpty()) { - new MainWindow(new_filename); + QFileInfo fi(new_filename); + if (!fi.suffix().toLower().contains(QRegExp("^(stl|off|dxf)$"))) { + actual_filename = new_filename; + } + new MainWindow(actual_filename); clearCurrentOutput(); return; } #endif - setFileName(new_filename); + setFileName(actual_filename); refreshDocument(); updateRecentFiles(); + if (actual_filename.isEmpty()) { + this->editor->setPlainText(QString("import(\"%1\");\n").arg(new_filename)); + } } void -- cgit v0.10.1 From 7470a77626c2b8e4e27376b2c82c28b9a6250264 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 8 May 2013 00:12:54 +0200 Subject: Small bugfix to previous commit diff --git a/src/mainwin.cc b/src/mainwin.cc index dc6d85c..5f9d633 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -488,12 +488,12 @@ void MainWindow::requestOpenFile(const QString &) void MainWindow::openFile(const QString &new_filename) { - QString actual_filename; + QString actual_filename = new_filename; #ifdef ENABLE_MDI if (!editor->toPlainText().isEmpty()) { QFileInfo fi(new_filename); - if (!fi.suffix().toLower().contains(QRegExp("^(stl|off|dxf)$"))) { - actual_filename = new_filename; + if (fi.suffix().toLower().contains(QRegExp("^(stl|off|dxf)$"))) { + actual_filename = QString(); } new MainWindow(actual_filename); clearCurrentOutput(); -- cgit v0.10.1 From db8ad9631d838fba26cab298ca9de26f0cfe3a77 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 8 May 2013 16:34:38 +0200 Subject: Added failing test for the #217 regression diff --git a/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad b/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad new file mode 100644 index 0000000..d6b197c --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad @@ -0,0 +1,3 @@ +use + +localfiles_submodule(); diff --git a/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad b/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad new file mode 100644 index 0000000..cab3499 --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad @@ -0,0 +1,9 @@ +module localfiles_submodule() +{ + linear_extrude(h=100) import("localfile.dxf"); + translate([-250,0,0]) linear_extrude(file="localfile.dxf"); + translate([0,350,0]) rotate_extrude(file="localfile.dxf"); + translate([250,0,0]) scale([200,200,50]) surface("localfile.dat"); + + translate([0,-200,0]) sphere(r=dxf_dim(file="localfile.dxf", name="localfile")/2); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 51abd06..7833572 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -762,13 +762,15 @@ list(APPEND DUMPTEST_FILES ${MINIMAL_FILES} ${FEATURES_FILES} ${EXAMPLE_FILES}) list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad) list(APPEND CGALPNGTEST_FILES ${FEATURES_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_FILES}) list(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/transform-nan-inf-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad) list(APPEND OPENCSGTEST_FILES ${CGALPNGTEST_FILES}) list(APPEND OPENCSGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/bbox-transform-bug.scad) -- cgit v0.10.1 From f8ad66c8bbb3c78548c2e4b3b930f82d4a57b345 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Wed, 8 May 2013 23:20:06 -0500 Subject: fix issue 352 - require 'file' to be a string diff --git a/src/linearextrude.cc b/src/linearextrude.cc index c64a235..4953781 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -72,7 +72,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI Value twist = c.lookup_variable("twist", true); Value slices = c.lookup_variable("slices", true); - if (!file.isUndefined()) { + if (!file.isUndefined() && file.type() == Value::STRING) { PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); node->filename = inst->getAbsolutePath(file.toString()); } @@ -80,7 +80,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI // if height not given, and first argument is a number, // then assume it should be the height. if (c.lookup_variable("height").isUndefined() && - evalctx->numArgs() > 0 && + evalctx->numArgs() > 0 && evalctx->getArgName(0) == "" && evalctx->getArgValue(0).type() == Value::NUMBER) { height = evalctx->getArgValue(0); -- cgit v0.10.1 From 0e938364fea8c3ab07b06491fd21cb34a403bf99 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 11:02:31 +0200 Subject: Search for included files first in the same location as the including module, then in the document root as a compatibility fallback. Fixes #217 diff --git a/src/fileutils.cc b/src/fileutils.cc new file mode 100644 index 0000000..b844b4a --- /dev/null +++ b/src/fileutils.cc @@ -0,0 +1,35 @@ +#include "fileutils.h" +#include "printutils.h" + +#include +namespace fs = boost::filesystem; +#include "boosty.h" + +/*! + Returns the absolute path to the given filename, unless it's empty. + If the file isn't found in the given path, the fallback path will be + used to be backwards compatible with <= 2013.01 (see issue #217). +*/ +std::string lookup_file(const std::string &filename, + const std::string &path, const std::string &fallbackpath) +{ + std::string resultfile; + if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { + fs::path absfile; + if (!path.empty()) absfile = boosty::absolute(fs::path(path) / filename); + fs::path absfile_fallback; + if (!fallbackpath.empty()) absfile_fallback = boosty::absolute(fs::path(fallbackpath) / filename); + + if (!fs::exists(absfile) && fs::exists(absfile_fallback)) { + resultfile = absfile_fallback.string(); + PRINTB("WARNING: Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); + } + else { + resultfile = absfile.string(); + } + } + else { + resultfile = filename; + } + return resultfile; +} diff --git a/src/fileutils.h b/src/fileutils.h new file mode 100644 index 0000000..1f68cdb --- /dev/null +++ b/src/fileutils.h @@ -0,0 +1,9 @@ +#ifndef FILEUTILS_H_ +#define FILEUTILS_H_ + +#include + +std::string lookup_file(const std::string &filename, + const std::string &path, const std::string &fallbackpath); + +#endif diff --git a/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png b/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png new file mode 100644 index 0000000..d0cfd50 Binary files /dev/null and b/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png differ diff --git a/tests/regression/dumptest/localfiles-compatibility-test-expected.txt b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt new file mode 100644 index 0000000..8725061 --- /dev/null +++ b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt @@ -0,0 +1,20 @@ + group() { + linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + import(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, -250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { + rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { + surface(file = "localfile.dat", center = false); + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, -200], [0, 0, 1, 0], [0, 0, 0, 1]]) { + sphere($fn = 0, $fa = 12, $fs = 2, r = 100); + } + } + diff --git a/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png b/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png new file mode 100644 index 0000000..f280efd Binary files /dev/null and b/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png differ diff --git a/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png b/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png new file mode 100644 index 0000000..f280efd Binary files /dev/null and b/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png differ -- cgit v0.10.1 From 14e1ad23635a65d98c59ae14e35484abbd3ba6c4 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 12:12:58 +0200 Subject: Forgot to actually add most files in previous commit (#217) diff --git a/openscad.pro b/openscad.pro index 81f5e6f..96a0a2a 100644 --- a/openscad.pro +++ b/openscad.pro @@ -227,6 +227,7 @@ HEADERS += src/typedefs.h \ src/handle_dep.h \ src/polyset.h \ src/printutils.h \ + src/fileutils.h \ src/value.h \ src/progress.h \ src/editor.h \ @@ -291,6 +292,7 @@ SOURCES += src/version_check.cc \ src/linearextrude.cc \ src/rotateextrude.cc \ src/printutils.cc \ + src/fileutils.cc \ src/progress.cc \ src/parsersettings.cc \ src/stl-utils.cc \ diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 555ed49..66842d2 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -30,6 +30,7 @@ #include "dxfdata.h" #include "builtin.h" #include "printutils.h" +#include "fileutils.h" #include "evalcontext.h" #include "mathc99.h" @@ -54,7 +55,8 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) // See issue #217 for (size_t i = 0; i < evalctx->numArgs(); i++) { if (evalctx->getArgName(i) == "file") - filename = evalctx->getAbsolutePath(evalctx->getArgValue(i).toString()); + filename = lookup_file(evalctx->getArgValue(i).toString(), + evalctx->documentPath(), ctx->documentPath()); if (evalctx->getArgName(i) == "layer") layername = evalctx->getArgValue(i).toString(); if (evalctx->getArgName(i) == "origin") diff --git a/src/import.cc b/src/import.cc index bd8f830..bb44d70 100644 --- a/src/import.cc +++ b/src/import.cc @@ -33,6 +33,7 @@ #include "dxfdata.h" #include "dxftess.h" #include "printutils.h" +#include "fileutils.h" #include "handle_dep.h" // handle_dep() #ifdef ENABLE_CGAL @@ -97,7 +98,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti PRINT("DEPRECATED: filename= is deprecated. Please use file="); } } - std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); + std::string filename = lookup_file(v.isUndefined() ? "" : v.toString(), inst->path(), ctx->documentPath()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { std::string extraw = boosty::extension_str( fs::path(filename) ); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index c64a235..3b9db02 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -29,6 +29,7 @@ #include "module.h" #include "evalcontext.h" #include "printutils.h" +#include "fileutils.h" #include "builtin.h" #include "PolySetEvaluator.h" #include "openscad.h" // get_fragments_from_r() @@ -74,7 +75,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (!file.isUndefined()) { PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); - node->filename = inst->getAbsolutePath(file.toString()); + node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); } // if height not given, and first argument is a number, diff --git a/src/module.cc b/src/module.cc index 9503f05..8b84c07 100644 --- a/src/module.cc +++ b/src/module.cc @@ -71,7 +71,10 @@ IfElseModuleInstantiation::~IfElseModuleInstantiation() /*! Returns the absolute path to the given filename, unless it's empty. - */ + + NB! This will actually search for the file, to be backwards compatible with <= 2013.01 + (see issue #217) +*/ std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const { if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { diff --git a/src/openscad.cc b/src/openscad.cc index 6a0d057..7c54762 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -359,7 +359,8 @@ int main(int argc, char **argv) fs::path fpath = boosty::absolute(fs::path(filename)); fs::path fparent = fpath.parent_path(); fs::current_path(fparent); - + top_ctx.setDocumentPath(fparent.string()); + AbstractNode::resetIndexCounter(); absolute_root_node = root_module->instantiate(&top_ctx, &root_inst, NULL); diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 2f9a28b..e073a69 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -28,6 +28,7 @@ #include "module.h" #include "evalcontext.h" #include "printutils.h" +#include "fileutils.h" #include "builtin.h" #include "polyset.h" #include "visitor.h" @@ -70,7 +71,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI if (!file.isUndefined()) { PRINT("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); - node->filename = inst->getAbsolutePath(file.toString()); + node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); } node->layername = layer.isUndefined() ? "" : layer.toString(); diff --git a/src/surface.cc b/src/surface.cc index b3246c1..46ddc07 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -30,6 +30,7 @@ #include "evalcontext.h" #include "builtin.h" #include "printutils.h" +#include "fileutils.h" #include "handle_dep.h" // handle_dep() #include "visitor.h" @@ -82,7 +83,7 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant c.setVariables(args, evalctx); Value fileval = c.lookup_variable("file"); - node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); + node->filename = lookup_file(fileval.isUndefined() ? "" : fileval.toString(), inst->path(), c.documentPath()); Value center = c.lookup_variable("center", true); if (center.type() == Value::BOOL) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7833572..964adc2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -429,6 +429,7 @@ set(CORE_SOURCES ../src/linearextrude.cc ../src/rotateextrude.cc ../src/printutils.cc + ../src/fileutils.cc ../src/progress.cc ../src/boost-utils.cc ${FLEX_OpenSCADlexer_OUTPUTS} diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index 81fc6b4..7b958de 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -113,9 +113,10 @@ int main(int argc, char **argv) exit(1); } - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); AbstractNode::resetIndexCounter(); AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 320b533..7b9dbab 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -148,9 +148,10 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) } if (!sysinfo_dump) { - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); } AbstractNode::resetIndexCounter(); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index e4876fa..4477703 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -97,9 +97,10 @@ int main(int argc, char **argv) exit(1); } - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); AbstractNode::resetIndexCounter(); root_node = root_module->instantiate(&top_ctx, &root_inst); @@ -130,7 +131,7 @@ int main(int argc, char **argv) delete root_module; fs::current_path(original_path); - root_module = parsefile(outfilename); + root_module = parsefile(outfilename, fparent.string().c_str()); if (!root_module) { fprintf(stderr, "Error: Unable to read back dumped file\n"); exit(1); @@ -141,9 +142,7 @@ int main(int argc, char **argv) tree.setRoot(root_node); - if (fs::path(outfilename).has_parent_path()) { - fs::current_path(fs::path(outfilename).parent_path()); - } + fs::current_path(fparent); string readbackstr = dumptree(tree, *root_node); if (dumpstdstr != readbackstr) { diff --git a/tests/tests-common.cc b/tests/tests-common.cc index ac85e37..3c66e1b 100644 --- a/tests/tests-common.cc +++ b/tests/tests-common.cc @@ -7,7 +7,12 @@ #include #include -FileModule *parsefile(const char *filename) +/*! + fakepath is used to force the parser to believe that the file is + read from this location, in order to ensure that filepaths are + eavluated relative to this path (for testing purposes). +*/ +FileModule *parsefile(const char *filename, const char *fakepath) { FileModule *root_module = NULL; @@ -19,7 +24,9 @@ FileModule *parsefile(const char *filename) else { std::string text((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); text += "\n" + commandline_commands; - std::string pathname = boosty::stringy(fs::path(filename).parent_path()); + std::string pathname; + if (fakepath) pathname = fakepath; + else pathname = boosty::stringy(fs::path(filename).parent_path()); root_module = parse(text.c_str(), pathname.c_str(), false); if (root_module) { root_module->handleDependencies(); diff --git a/tests/tests-common.h b/tests/tests-common.h index 3393884..e16bcda 100644 --- a/tests/tests-common.h +++ b/tests/tests-common.h @@ -1,6 +1,8 @@ #ifndef TESTS_COMMON_H_ #define TESTS_COMMON_H_ -class FileModule *parsefile(const char *filename); +#include + +class FileModule *parsefile(const char *filename, const char *fakepath = NULL); #endif -- cgit v0.10.1 From ad8ba77a15efd745fe7845e085b3daefd3f58e81 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 12:16:58 +0200 Subject: Added failing test for #352 diff --git a/testdata/scad/features/linear_extrude-tests.scad b/testdata/scad/features/linear_extrude-tests.scad index 67de8e6..67d892f 100644 --- a/testdata/scad/features/linear_extrude-tests.scad +++ b/testdata/scad/features/linear_extrude-tests.scad @@ -11,3 +11,5 @@ translate([31.5,2.5,0]) linear_extrude(height=10, twist=-45) polygon(points = [[ translate([0,20,0]) linear_extrude(height=20, twist=45, slices=2) square([10,10]); translate([19,20,0]) linear_extrude(height=20, twist=45, slices=10) square([10,10]); + +translate([-15,0,0]) linear_extrude(5) square([10,10]); diff --git a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png index 1486743..7d3ea2c 100644 Binary files a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png and b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png differ diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt index cba1189..298b7e7 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.txt +++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt @@ -29,4 +29,9 @@ square(size = [10, 10], center = false); } } + multmatrix([[1, 0, 0, -15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 5, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + square(size = [10, 10], center = false); + } + } diff --git a/tests/regression/opencsgtest/linear_extrude-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-tests-expected.png index f31b22a..b929d09 100644 Binary files a/tests/regression/opencsgtest/linear_extrude-tests-expected.png and b/tests/regression/opencsgtest/linear_extrude-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png index b672783..fddeeb8 100644 Binary files a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png and b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png differ -- cgit v0.10.1 From 89e27d997d97a7b51098e37a41be0991e7c47c06 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 14:23:29 +0200 Subject: sync diff --git a/RELEASE_NOTES b/RELEASE_NOTES index c53de47..56b92d9 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,7 @@ OpenSCAD 2013.XX Features: o Recursive modules and functions is now supported (including cascading child() operations) +o Parameter list values can now depend on earlier values, e.g. for (i=[0:2], j=[0:i]) .. o Console output is now enabled on Windows through the openscad.com executable o Added basic syntax highlighting in the editor o Mac: Added document icon @@ -12,6 +13,7 @@ o resize() command introduced o Regression test now creates single monolithic .html file for easier uploading o value reassignment is now less strict o value assignments in parameters can now depend on already declared parameters +o Attempting to open dxf, off or stl files in the GUI will now create an import statement. Bugfixes: o Importing files is now always relative to the importing script, also for libraries -- cgit v0.10.1 From c5ebdb788b63ce8998a85e7c678ed4d46f3ea841 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 14:23:52 +0200 Subject: Added failing test for #336 diff --git a/testdata/scad/features/surface-simple.scad b/testdata/scad/features/surface-simple.scad index 9659143..1215a0b 100644 --- a/testdata/scad/features/surface-simple.scad +++ b/testdata/scad/features/surface-simple.scad @@ -1 +1,3 @@ surface("surface-simple.dat", center=true); +// Surface without a trailing newline +translate([2,0,0]) surface("surface-simple2.dat", center=true); diff --git a/testdata/scad/features/surface-simple2.dat b/testdata/scad/features/surface-simple2.dat new file mode 100644 index 0000000..a711970 --- /dev/null +++ b/testdata/scad/features/surface-simple2.dat @@ -0,0 +1,3 @@ +# Surface without a trailing newline +0 1 +2 3 \ No newline at end of file diff --git a/tests/regression/cgalpngtest/surface-simple-expected.png b/tests/regression/cgalpngtest/surface-simple-expected.png index 4152c38..d75cda7 100644 Binary files a/tests/regression/cgalpngtest/surface-simple-expected.png and b/tests/regression/cgalpngtest/surface-simple-expected.png differ diff --git a/tests/regression/dumptest/surface-simple-expected.txt b/tests/regression/dumptest/surface-simple-expected.txt index 3b42fcb..48c918f 100644 --- a/tests/regression/dumptest/surface-simple-expected.txt +++ b/tests/regression/dumptest/surface-simple-expected.txt @@ -1,2 +1,5 @@ surface(file = "surface-simple.dat", center = true); + multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + surface(file = "surface-simple2.dat", center = true); + } diff --git a/tests/regression/opencsgtest/surface-simple-expected.png b/tests/regression/opencsgtest/surface-simple-expected.png index 2abef81..08abd5a 100644 Binary files a/tests/regression/opencsgtest/surface-simple-expected.png and b/tests/regression/opencsgtest/surface-simple-expected.png differ diff --git a/tests/regression/throwntogethertest/surface-simple-expected.png b/tests/regression/throwntogethertest/surface-simple-expected.png index 2abef81..08abd5a 100644 Binary files a/tests/regression/throwntogethertest/surface-simple-expected.png and b/tests/regression/throwntogethertest/surface-simple-expected.png differ -- cgit v0.10.1 From 6ee78e7f68e70f121625327aa97f979551e692b3 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 14:32:43 +0200 Subject: Handle lack of trailing newline in dat files. Fixes #336 diff --git a/src/surface.cc b/src/surface.cc index 46ddc07..7987b99 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -122,7 +122,7 @@ PolySet *SurfaceNode::evaluate_polyset(class PolySetEvaluator *) const std::getline(stream, line); boost::trim(line); } - if (stream.eof()) break; + if (line.size() == 0 && stream.eof()) break; int col = 0; tokenizer tokens(line, sep); diff --git a/testdata/scad/features/surface-simple.dat b/testdata/scad/features/surface-simple.dat index 32eba08..166c600 100644 --- a/testdata/scad/features/surface-simple.dat +++ b/testdata/scad/features/surface-simple.dat @@ -1,2 +1,6 @@ 0 1 2 3 + +# Comment + + -- cgit v0.10.1 From 715d539f4ea1a37833ab2429262593aee57304fe Mon Sep 17 00:00:00 2001 From: NateTG Date: Thu, 9 May 2013 08:40:01 -0600 Subject: Update func.cc Fix for https://github.com/openscad/openscad/issues/322 diff --git a/src/func.cc b/src/func.cc index 4377a90..8675963 100644 --- a/src/func.cc +++ b/src/func.cc @@ -355,9 +355,9 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx) } } if (p <= low_p) - return Value(low_v); - if (p >= high_p) return Value(high_v); + if (p >= high_p) + return Value(low_v); double f = (p-low_p) / (high_p-low_p); return Value(high_v * f + low_v * (1-f)); } -- cgit v0.10.1 From 3780677def0ab71375f976efe0235c840dd02de2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 17:28:05 +0200 Subject: Added testcase for #322 diff --git a/testdata/scad/misc/lookup-tests.scad b/testdata/scad/misc/lookup-tests.scad new file mode 100644 index 0000000..c03ec95 --- /dev/null +++ b/testdata/scad/misc/lookup-tests.scad @@ -0,0 +1,17 @@ +echo(lookup(undef, undef)); +echo(lookup(undef, [undef])); +echo(lookup(undef, [[undef]])); +echo(lookup(undef, [[undef, undef]])); +echo(lookup(0, [[0, 0]])); +echo(lookup(0.5, [[0, 0], + [1, 1]])); + +table = [[-1, -5], + [-10, -55], + [0, 0], + [1, 3], + [10, 333]]; +indices = [-20,-10,-9.9, -0.5, 0, 0.3, 1.1, 10, 10.1]; +for (i=[0:len(indices)-1]) { + echo(lookup(indices[i], table)); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 964adc2..38b2758 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -757,7 +757,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/lookup-tests.scad) list(APPEND DUMPTEST_FILES ${MINIMAL_FILES} ${FEATURES_FILES} ${EXAMPLE_FILES}) list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad diff --git a/tests/regression/echotest/lookup-tests-expected.txt b/tests/regression/echotest/lookup-tests-expected.txt new file mode 100644 index 0000000..b98ebe2 --- /dev/null +++ b/tests/regression/echotest/lookup-tests-expected.txt @@ -0,0 +1,15 @@ +ECHO: undef +ECHO: undef +ECHO: undef +ECHO: undef +ECHO: 0 +ECHO: 0.5 +ECHO: -55 +ECHO: -55 +ECHO: -54.44444444444 +ECHO: -2.5 +ECHO: 0 +ECHO: 0.9 +ECHO: 6.66666666666 +ECHO: 333 +ECHO: 333 -- cgit v0.10.1 From e01b37a03d91b5d8cd12cc4ec7d7a453f20ec907 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 17:45:40 +0200 Subject: Support lookup tables with one element, final fix of #322 diff --git a/src/func.cc b/src/func.cc index 8675963..18884b8 100644 --- a/src/func.cc +++ b/src/func.cc @@ -336,8 +336,7 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx) double p, low_p, low_v, high_p, high_v; if (evalctx->numArgs() < 2 || // Needs two args !evalctx->getArgValue(0).getDouble(p) || // First must be a number - evalctx->getArgValue(1).toVector().size() < 2 || // Second must be a vector of vectors - evalctx->getArgValue(1).toVector()[0].toVector().size() < 2) + evalctx->getArgValue(1).toVector()[0].toVector().size() < 2) // Second must be a vector of vectors return Value(); if (!evalctx->getArgValue(1).toVector()[0].getVec2(low_p, low_v) || !evalctx->getArgValue(1).toVector()[0].getVec2(high_p, high_v)) return Value(); -- cgit v0.10.1 From 7a8b6f5c516e43c1bb0a90eab3e662453d112b84 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 9 May 2013 18:48:27 +0200 Subject: Put back lex/yacc - we're not using any bison-specific stuff after all diff --git a/openscad.pro b/openscad.pro index 96a0a2a..a8f3d17 100644 --- a/openscad.pro +++ b/openscad.pro @@ -171,6 +171,13 @@ CONFIG(mingw-cross-env) { include(mingw-cross-env.pri) } +win32 { + FLEXSOURCES = src/lexer.l + BISONSOURCES = src/parser.y +} else { + LEXSOURCES += src/lexer.l + YACCSOURCES += src/parser.y +} FLEXSOURCES = src/lexer.l BISONSOURCES = src/parser.y -- cgit v0.10.1 From b5079a189aa70cf36e9a4ded6d891df6ae78ac58 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 10 May 2013 00:55:04 +0200 Subject: wops, duplicate parser files diff --git a/openscad.pro b/openscad.pro index a8f3d17..542bcc3 100644 --- a/openscad.pro +++ b/openscad.pro @@ -178,8 +178,6 @@ win32 { LEXSOURCES += src/lexer.l YACCSOURCES += src/parser.y } -FLEXSOURCES = src/lexer.l -BISONSOURCES = src/parser.y RESOURCES = openscad.qrc -- cgit v0.10.1 From 130e10778e9d74ceb07dfc813b85d75a52a71e10 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 11 Feb 2013 23:33:31 -0500 Subject: Initial code to support scaling of linear_extrude(). Part of Issue #273 diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index 4357e44..aadc2b4 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -52,7 +52,7 @@ CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root) this->polyhedron = NULL; this->polyset = new PolySet(); this->polyset->is2d = true; - dxf_tesselate(this->polyset, *dd, 0, true, false, 0); + dxf_tesselate(this->polyset, *dd, 0, 1, true, false, 0); delete dd; } else if (root.dim == 3) { diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index 8906595..d9cd174 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -90,7 +90,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() ps = new PolySet(); DxfData *dd = this->convertToDxfData(); ps->is2d = true; - dxf_tesselate(ps, *dd, 0, true, false, 0); + dxf_tesselate(ps, *dd, 0, 1, true, false, 0); dxf_border_to_ps(ps, *dd); delete dd; } diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index 5976daf..6d0704e 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -202,27 +202,37 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) return ps; } -static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, double rot1, double rot2, double h1, double h2) +static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, + double rot1, double rot2, + double h1, double h2, + double scale1, double scale2) { + // FIXME: If scale2 == 0 we need to handle tessellation separately bool splitfirst = sin(rot2 - rot1) >= 0.0; - for (size_t j = 1; j < path.indices.size(); j++) - { + for (size_t j = 1; j < path.indices.size(); j++) { int k = j - 1; - double jx1 = dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot1*M_PI/180); - double jy1 = dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot1*M_PI/180); + double jx1 = scale1 * (dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + + dxf.points[path.indices[j]][1] * sin(rot1*M_PI/180)); + double jy1 = scale1 * (dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + + dxf.points[path.indices[j]][1] * cos(rot1*M_PI/180)); - double jx2 = dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot2*M_PI/180); - double jy2 = dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot2*M_PI/180); + double jx2 = scale2 * (dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + + dxf.points[path.indices[j]][1] * sin(rot2*M_PI/180)); + double jy2 = scale2 * (dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + + dxf.points[path.indices[j]][1] * cos(rot2*M_PI/180)); - double kx1 = dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot1*M_PI/180); - double ky1 = dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot1*M_PI/180); + double kx1 = scale1 * (dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + + dxf.points[path.indices[k]][1] * sin(rot1*M_PI/180)); + double ky1 = scale1 * (dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + + dxf.points[path.indices[k]][1] * cos(rot1*M_PI/180)); - double kx2 = dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot2*M_PI/180); - double ky2 = dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot2*M_PI/180); + double kx2 = scale2 * (dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + + dxf.points[path.indices[k]][1] * sin(rot2*M_PI/180)); + double ky2 = scale2 * (dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + + dxf.points[path.indices[k]][1] * cos(rot2*M_PI/180)); - if (splitfirst) - { + if (splitfirst) { ps->append_poly(); if (path.is_inner) { ps->append_vertex(kx1, ky1, h1); @@ -234,19 +244,20 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, doub ps->insert_vertex(jx2, jy2, h2); } - ps->append_poly(); - if (path.is_inner) { - ps->append_vertex(kx2, ky2, h2); - ps->append_vertex(kx1, ky1, h1); - ps->append_vertex(jx2, jy2, h2); - } else { - ps->insert_vertex(kx2, ky2, h2); - ps->insert_vertex(kx1, ky1, h1); - ps->insert_vertex(jx2, jy2, h2); + if (scale2 > 0) { + ps->append_poly(); + if (path.is_inner) { + ps->append_vertex(kx2, ky2, h2); + ps->append_vertex(kx1, ky1, h1); + ps->append_vertex(jx2, jy2, h2); + } else { + ps->insert_vertex(kx2, ky2, h2); + ps->insert_vertex(kx1, ky1, h1); + ps->insert_vertex(jx2, jy2, h2); + } } } - else - { + else { ps->append_poly(); if (path.is_inner) { ps->append_vertex(kx1, ky1, h1); @@ -258,15 +269,17 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, doub ps->insert_vertex(kx2, ky2, h2); } - ps->append_poly(); - if (path.is_inner) { - ps->append_vertex(jx2, jy2, h2); - ps->append_vertex(kx2, ky2, h2); - ps->append_vertex(jx1, jy1, h1); - } else { - ps->insert_vertex(jx2, jy2, h2); - ps->insert_vertex(kx2, ky2, h2); - ps->insert_vertex(jx1, jy1, h1); + if (scale2 > 0) { + ps->append_poly(); + if (path.is_inner) { + ps->append_vertex(jx2, jy2, h2); + ps->append_vertex(kx2, ky2, h2); + ps->append_vertex(jx1, jy1, h1); + } else { + ps->insert_vertex(jx2, jy2, h2); + ps->insert_vertex(kx2, ky2, h2); + ps->insert_vertex(jx1, jy1, h1); + } } } } @@ -322,10 +335,8 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf } bool first_open_path = true; - for (size_t i = 0; i < dxf.paths.size(); i++) - { - if (dxf.paths[i].is_closed) - continue; + for (size_t i = 0; i < dxf.paths.size(); i++) { + if (dxf.paths[i].is_closed) continue; if (first_open_path) { PRINTB("WARNING: Open paths in dxf_linear_extrude(file = \"%s\", layer = \"%s\"):", node.filename % node.layername); @@ -339,33 +350,32 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf } - if (node.has_twist) - { - dxf_tesselate(ps, dxf, 0, false, true, h1); - dxf_tesselate(ps, dxf, node.twist, true, true, h2); - for (int j = 0; j < node.slices; j++) - { + if (node.has_twist) { + dxf_tesselate(ps, dxf, 0, 1, false, true, h1); + if (node.scale > 0) { + dxf_tesselate(ps, dxf, node.twist, node.scale, true, true, h2); + } + for (int j = 0; j < node.slices; j++) { double t1 = node.twist*j / node.slices; double t2 = node.twist*(j+1) / node.slices; double g1 = h1 + (h2-h1)*j / node.slices; double g2 = h1 + (h2-h1)*(j+1) / node.slices; - for (size_t i = 0; i < dxf.paths.size(); i++) - { - if (!dxf.paths[i].is_closed) - continue; - add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2); + double s1 = 1 - (1-node.scale)*j / node.slices; + double s2 = 1 - (1-node.scale)*(j+1) / node.slices; + for (size_t i = 0; i < dxf.paths.size(); i++) { + if (!dxf.paths[i].is_closed) continue; + add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2, s1, s2); } } } - else - { - dxf_tesselate(ps, dxf, 0, false, true, h1); - dxf_tesselate(ps, dxf, 0, true, true, h2); - for (size_t i = 0; i < dxf.paths.size(); i++) - { - if (!dxf.paths[i].is_closed) - continue; - add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2); + else { + dxf_tesselate(ps, dxf, 0, 1, false, true, h1); + if (node.scale > 0) { + dxf_tesselate(ps, dxf, 0, node.scale, true, true, h2); + } + for (size_t i = 0; i < dxf.paths.size(); i++) { + if (!dxf.paths[i].is_closed) continue; + add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2, 1, node.scale); } } diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index 0197473..fffa4f1 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -101,7 +101,7 @@ void mark_inner_outer(std::vector &tri, Grid2d &p } } -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool /* do_triangle_splitting */, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool /* do_triangle_splitting */, double h) { CDT cdt; @@ -124,8 +124,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool /* do_tr struct point_info_t *first_pi = NULL, *prev_pi = NULL; for (size_t j = 1; j < dxf.paths[i].indices.size(); j++) { - double x = dxf.points[dxf.paths[i].indices[j]][0]; - double y = dxf.points[dxf.paths[i].indices[j]][1]; + double x = scale * dxf.points[dxf.paths[i].indices[j]][0]; + double y = scale * dxf.points[dxf.paths[i].indices[j]][1]; if (point_info.has(x, y)) { // FIXME: How can the same path set contain the same point twice? diff --git a/src/dxftess-glu.cc b/src/dxftess-glu.cc index 3f87729..38b09e9 100644 --- a/src/dxftess-glu.cc +++ b/src/dxftess-glu.cc @@ -201,7 +201,7 @@ inline void do_emplace( boost::unordered_multimap &tri_by_atan2, i rot: CLOCKWISE rotation around positive Z axis */ -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_triangle_splitting, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h) { GLUtesselator *tobj = gluNewTess(); @@ -244,8 +244,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_trian dxf.points[dxf.paths[i].indices[j]][1], h) = std::pair(i, j); vl.push_back(tess_vdata()); - vl.back().v[0] = dxf.points[dxf.paths[i].indices[j]][0]; - vl.back().v[1] = dxf.points[dxf.paths[i].indices[j]][1]; + vl.back().v[0] = scale * dxf.points[dxf.paths[i].indices[j]][0]; + vl.back().v[1] = scale * dxf.points[dxf.paths[i].indices[j]][1]; vl.back().v[2] = h; gluTessVertex(tobj, vl.back().v, vl.back().v); } diff --git a/src/dxftess.h b/src/dxftess.h index d3af36e..92c85ea 100644 --- a/src/dxftess.h +++ b/src/dxftess.h @@ -3,7 +3,7 @@ class DxfData; class PolySet; -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool do_triangle_splitting, double h); +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h); void dxf_border_to_ps(PolySet *ps, const DxfData &dxf); #endif diff --git a/src/import.cc b/src/import.cc index bb44d70..bf21780 100644 --- a/src/import.cc +++ b/src/import.cc @@ -294,7 +294,7 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const p = new PolySet(); DxfData dd(this->fn, this->fs, this->fa, this->filename, this->layername, this->origin_x, this->origin_y, this->scale); p->is2d = true; - dxf_tesselate(p, dd, 0, true, false, 0); + dxf_tesselate(p, dd, 0, 1, true, false, 0); dxf_border_to_ps(p, dd); } else diff --git a/src/linearextrude.cc b/src/linearextrude.cc index bc678e6..89e92ba 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -91,7 +91,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI node->height = height.toDouble(); node->convexity = (int)convexity.toDouble(); origin.getVec2(node->origin_x, node->origin_y); - node->scale = scale.toDouble(); + node->scale = scale.isUndefined() ? 1 : scale.toDouble(); if (center.type() == Value::BOOL) node->center = center.toBool(); @@ -102,8 +102,8 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (node->convexity <= 0) node->convexity = 1; - if (node->scale <= 0) - node->scale = 1; + if (node->scale < 0) + node->scale = 0; if (twist.type() == Value::NUMBER) { node->twist = twist.toDouble(); @@ -166,6 +166,7 @@ std::string LinearExtrudeNode::toString() const if (this->has_twist) { stream << ", twist = " << this->twist << ", slices = " << this->slices; } + stream << ", scale = " << this->scale; stream << ", $fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")"; return stream.str(); diff --git a/src/primitives.cc b/src/primitives.cc index be1ec6f..3298073 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -546,7 +546,7 @@ sphere_next_r2: p->is2d = true; p->convexity = convexity; - dxf_tesselate(p, dd, 0, true, false, 0); + dxf_tesselate(p, dd, 0, 1, true, false, 0); dxf_border_to_ps(p, dd); } -- cgit v0.10.1 From adffb9121fbf5d12542ae0d8c5a010e78cc8a4f9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 10 May 2013 18:01:50 +0200 Subject: Added support for 2D scaling in linear_extrude diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index aadc2b4..0a75266 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -52,7 +52,7 @@ CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root) this->polyhedron = NULL; this->polyset = new PolySet(); this->polyset->is2d = true; - dxf_tesselate(this->polyset, *dd, 0, 1, true, false, 0); + dxf_tesselate(this->polyset, *dd, 0, Vector2d(1,1), true, false, 0); delete dd; } else if (root.dim == 3) { diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index d9cd174..440f4ed 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -90,7 +90,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() ps = new PolySet(); DxfData *dd = this->convertToDxfData(); ps->is2d = true; - dxf_tesselate(ps, *dd, 0, 1, true, false, 0); + dxf_tesselate(ps, *dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(ps, *dd); delete dd; } diff --git a/src/CGAL_Nef_polyhedron_DxfData.cc b/src/CGAL_Nef_polyhedron_DxfData.cc index 0388fe5..c4347e8 100644 --- a/src/CGAL_Nef_polyhedron_DxfData.cc +++ b/src/CGAL_Nef_polyhedron_DxfData.cc @@ -123,7 +123,7 @@ void CGAL_Nef_polyhedron::transform( const Transform3d &matrix ) PolySet ps; ps.is2d = true; - dxf_tesselate(&ps, *dd, 0, true, false, 0); + dxf_tesselate(&ps, *dd, 0, Vector2d(1,1), true, false, 0); Tree nulltree; CGALEvaluator tmpeval(nulltree); diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index 6d0704e..f0c274f 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -205,31 +205,32 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, double rot1, double rot2, double h1, double h2, - double scale1, double scale2) + double scale1_x, double scale1_y, + double scale2_x, double scale2_y) { // FIXME: If scale2 == 0 we need to handle tessellation separately bool splitfirst = sin(rot2 - rot1) >= 0.0; for (size_t j = 1; j < path.indices.size(); j++) { int k = j - 1; - double jx1 = scale1 * (dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + + double jx1 = scale1_x * (dxf.points[path.indices[j]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot1*M_PI/180)); - double jy1 = scale1 * (dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + + double jy1 = scale1_y * (dxf.points[path.indices[j]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot1*M_PI/180)); - double jx2 = scale2 * (dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + + double jx2 = scale2_x * (dxf.points[path.indices[j]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * sin(rot2*M_PI/180)); - double jy2 = scale2 * (dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + + double jy2 = scale2_y * (dxf.points[path.indices[j]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[j]][1] * cos(rot2*M_PI/180)); - double kx1 = scale1 * (dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + + double kx1 = scale1_x * (dxf.points[path.indices[k]][0] * cos(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot1*M_PI/180)); - double ky1 = scale1 * (dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + + double ky1 = scale1_y * (dxf.points[path.indices[k]][0] * -sin(rot1*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot1*M_PI/180)); - double kx2 = scale2 * (dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + + double kx2 = scale2_x * (dxf.points[path.indices[k]][0] * cos(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * sin(rot2*M_PI/180)); - double ky2 = scale2 * (dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + + double ky2 = scale2_y * (dxf.points[path.indices[k]][0] * -sin(rot2*M_PI/180) + dxf.points[path.indices[k]][1] * cos(rot2*M_PI/180)); if (splitfirst) { @@ -244,7 +245,7 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, ps->insert_vertex(jx2, jy2, h2); } - if (scale2 > 0) { + if (scale2_x > 0 || scale2_y > 0) { ps->append_poly(); if (path.is_inner) { ps->append_vertex(kx2, ky2, h2); @@ -269,7 +270,7 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, ps->insert_vertex(kx2, ky2, h2); } - if (scale2 > 0) { + if (scale2_x > 0 || scale2_y > 0) { ps->append_poly(); if (path.is_inner) { ps->append_vertex(jx2, jy2, h2); @@ -311,7 +312,7 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const LinearExtrudeNode &node) if (sum.isNull()) return NULL; dxf = sum.convertToDxfData();; } else { - dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); + dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale_x); } PolySet *ps = extrudeDxfData(node, *dxf); @@ -343,39 +344,41 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf first_open_path = false; } PRINTB(" %9.5f %10.5f ... %10.5f %10.5f", - (dxf.points[dxf.paths[i].indices.front()][0] / node.scale + node.origin_x) % - (dxf.points[dxf.paths[i].indices.front()][1] / node.scale + node.origin_y) % - (dxf.points[dxf.paths[i].indices.back()][0] / node.scale + node.origin_x) % - (dxf.points[dxf.paths[i].indices.back()][1] / node.scale + node.origin_y)); + (dxf.points[dxf.paths[i].indices.front()][0] / node.scale_x + node.origin_x) % + (dxf.points[dxf.paths[i].indices.front()][1] / node.scale_y + node.origin_y) % + (dxf.points[dxf.paths[i].indices.back()][0] / node.scale_x + node.origin_x) % + (dxf.points[dxf.paths[i].indices.back()][1] / node.scale_y + node.origin_y)); } if (node.has_twist) { - dxf_tesselate(ps, dxf, 0, 1, false, true, h1); - if (node.scale > 0) { - dxf_tesselate(ps, dxf, node.twist, node.scale, true, true, h2); + dxf_tesselate(ps, dxf, 0, Vector2d(1,1), false, true, h1); // bottom + if (node.scale_x > 0 || node.scale_y > 0) { + dxf_tesselate(ps, dxf, node.twist, Vector2d(node.scale_x, node.scale_y), true, true, h2); // top } for (int j = 0; j < node.slices; j++) { double t1 = node.twist*j / node.slices; double t2 = node.twist*(j+1) / node.slices; double g1 = h1 + (h2-h1)*j / node.slices; double g2 = h1 + (h2-h1)*(j+1) / node.slices; - double s1 = 1 - (1-node.scale)*j / node.slices; - double s2 = 1 - (1-node.scale)*(j+1) / node.slices; + double s1x = 1 - (1-node.scale_x)*j / node.slices; + double s1y = 1 - (1-node.scale_y)*j / node.slices; + double s2x = 1 - (1-node.scale_x)*(j+1) / node.slices; + double s2y = 1 - (1-node.scale_y)*(j+1) / node.slices; for (size_t i = 0; i < dxf.paths.size(); i++) { if (!dxf.paths[i].is_closed) continue; - add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2, s1, s2); + add_slice(ps, dxf, dxf.paths[i], t1, t2, g1, g2, s1x, s1y, s2x, s2y); } } } else { - dxf_tesselate(ps, dxf, 0, 1, false, true, h1); - if (node.scale > 0) { - dxf_tesselate(ps, dxf, 0, node.scale, true, true, h2); + dxf_tesselate(ps, dxf, 0, Vector2d(1,1), false, true, h1); //bottom + if (node.scale_x > 0 || node.scale_y > 0) { + dxf_tesselate(ps, dxf, 0, Vector2d(node.scale_x, node.scale_y), true, true, h2); // top } for (size_t i = 0; i < dxf.paths.size(); i++) { if (!dxf.paths[i].is_closed) continue; - add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2, 1, node.scale); + add_slice(ps, dxf, dxf.paths[i], 0, 0, h1, h2, 1, 1, node.scale_x, node.scale_y); } } diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index fffa4f1..16eaf9f 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -101,7 +101,7 @@ void mark_inner_outer(std::vector &tri, Grid2d &p } } -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool /* do_triangle_splitting */, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool /* do_triangle_splitting */, double h) { CDT cdt; @@ -124,8 +124,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, struct point_info_t *first_pi = NULL, *prev_pi = NULL; for (size_t j = 1; j < dxf.paths[i].indices.size(); j++) { - double x = scale * dxf.points[dxf.paths[i].indices[j]][0]; - double y = scale * dxf.points[dxf.paths[i].indices[j]][1]; + double x = dxf.points[dxf.paths[i].indices[j]][0]; + double y = dxf.points[dxf.paths[i].indices[j]][1]; if (point_info.has(x, y)) { // FIXME: How can the same path set contain the same point twice? @@ -314,8 +314,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, int idx = up ? j : (2-j); double px = tri[i].p[idx].x; double py = tri[i].p[idx].y; - ps->append_vertex(px * cos(rot*M_PI/180) + py * sin(rot*M_PI/180), - px * -sin(rot*M_PI/180) + py * cos(rot*M_PI/180), h); + ps->append_vertex(scale[0] * (px * cos(rot*M_PI/180) + py * sin(rot*M_PI/180)), + scale[1] * (px * -sin(rot*M_PI/180) + py * cos(rot*M_PI/180)), h); path[j] = point_info.data(px, py).pathidx; point[j] = point_info.data(px, py).pointidx; } diff --git a/src/dxftess-glu.cc b/src/dxftess-glu.cc index 38b09e9..89999c3 100644 --- a/src/dxftess-glu.cc +++ b/src/dxftess-glu.cc @@ -201,7 +201,7 @@ inline void do_emplace( boost::unordered_multimap &tri_by_atan2, i rot: CLOCKWISE rotation around positive Z axis */ -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h) +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool do_triangle_splitting, double h) { GLUtesselator *tobj = gluNewTess(); @@ -244,8 +244,8 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, dxf.points[dxf.paths[i].indices[j]][1], h) = std::pair(i, j); vl.push_back(tess_vdata()); - vl.back().v[0] = scale * dxf.points[dxf.paths[i].indices[j]][0]; - vl.back().v[1] = scale * dxf.points[dxf.paths[i].indices[j]][1]; + vl.back().v[0] = scale[0] * dxf.points[dxf.paths[i].indices[j]][0]; + vl.back().v[1] = scale[1] * dxf.points[dxf.paths[i].indices[j]][1]; vl.back().v[2] = h; gluTessVertex(tobj, vl.back().v, vl.back().v); } diff --git a/src/dxftess.h b/src/dxftess.h index 92c85ea..f0f27b5 100644 --- a/src/dxftess.h +++ b/src/dxftess.h @@ -1,9 +1,11 @@ #ifndef DXFTESS_H_ #define DXFTESS_H_ +#include "linalg.h" + class DxfData; class PolySet; -void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, double scale, bool up, bool do_triangle_splitting, double h); +void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool do_triangle_splitting, double h); void dxf_border_to_ps(PolySet *ps, const DxfData &dxf); #endif diff --git a/src/import.cc b/src/import.cc index bf21780..2180684 100644 --- a/src/import.cc +++ b/src/import.cc @@ -294,7 +294,7 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const p = new PolySet(); DxfData dd(this->fn, this->fs, this->fa, this->filename, this->layername, this->origin_x, this->origin_y, this->scale); p->is2d = true; - dxf_tesselate(p, dd, 0, 1, true, false, 0); + dxf_tesselate(p, dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(p, dd); } else diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 89e92ba..9a7365b 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -91,7 +91,10 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI node->height = height.toDouble(); node->convexity = (int)convexity.toDouble(); origin.getVec2(node->origin_x, node->origin_y); - node->scale = scale.isUndefined() ? 1 : scale.toDouble(); + node->scale_x = node->scale_y = 1; + scale.getDouble(node->scale_x); + scale.getDouble(node->scale_y); + scale.getVec2(node->scale_x, node->scale_y); if (center.type() == Value::BOOL) node->center = center.toBool(); @@ -102,8 +105,8 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (node->convexity <= 0) node->convexity = 1; - if (node->scale < 0) - node->scale = 0; + if (node->scale_x < 0) node->scale_x = 0; + if (node->scale_y < 0) node->scale_y = 0; if (twist.type() == Value::NUMBER) { node->twist = twist.toDouble(); @@ -151,7 +154,6 @@ std::string LinearExtrudeNode::toString() const "file = " << this->filename << ", " "layer = " << QuotedString(this->layername) << ", " "origin = [" << this->origin_x << ", " << this->origin_y << "], " - "scale = " << this->scale << ", " #ifndef OPENSCAD_TESTING // timestamp is needed for caching, but disturbs the test framework << "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0) << ", " @@ -166,7 +168,7 @@ std::string LinearExtrudeNode::toString() const if (this->has_twist) { stream << ", twist = " << this->twist << ", slices = " << this->slices; } - stream << ", scale = " << this->scale; + stream << ", scale = [" << this->scale_x << ", " << this->scale_y << "]"; stream << ", $fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")"; return stream.str(); diff --git a/src/linearextrudenode.h b/src/linearextrudenode.h index 112eccc..6ff8c56 100644 --- a/src/linearextrudenode.h +++ b/src/linearextrudenode.h @@ -11,7 +11,8 @@ public: LinearExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { convexity = slices = 0; fn = fs = fa = height = twist = 0; - origin_x = origin_y = scale = 0; + origin_x = origin_y = 0; + scale_x = scale_y = 1; center = has_twist = false; } virtual Response accept(class State &state, Visitor &visitor) const { @@ -22,7 +23,7 @@ public: int convexity, slices; double fn, fs, fa, height, twist; - double origin_x, origin_y, scale; + double origin_x, origin_y, scale_x, scale_y; bool center, has_twist; Filename filename; std::string layername; diff --git a/src/primitives.cc b/src/primitives.cc index 3298073..9b755ef 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -546,7 +546,7 @@ sphere_next_r2: p->is2d = true; p->convexity = convexity; - dxf_tesselate(p, dd, 0, 1, true, false, 0); + dxf_tesselate(p, dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(p, dd); } diff --git a/testdata/scad/features/linear_extrude-scale-tests.scad b/testdata/scad/features/linear_extrude-scale-tests.scad new file mode 100644 index 0000000..9a82c9d --- /dev/null +++ b/testdata/scad/features/linear_extrude-scale-tests.scad @@ -0,0 +1,17 @@ +difference() { + linear_extrude(height=40, scale=[0, 0]) { + square(10, center=true); + translate([10,0]) circle(10); + } + translate([0,0,35]) sphere(10); +} + +/* +Test case ideas: +o off-center starting point +o Concave polygon +o Disjoint polygons +o multi-rotation twist +o zero scales, zero scales in only one axis (for the above cases) +o boolean operations on scaled extrusion (including zero scale) +*/ -- cgit v0.10.1 From 8c532d525203d6cd0fc8ab200a4dea1dccd03dd6 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 11 May 2013 12:56:19 -0400 Subject: Updated test cases to reflect scale argument to linear_extrude (#273) diff --git a/tests/regression/dumptest/allmodules-expected.txt b/tests/regression/dumptest/allmodules-expected.txt index 86bb7fb..e6bd498 100644 --- a/tests/regression/dumptest/allmodules-expected.txt +++ b/tests/regression/dumptest/allmodules-expected.txt @@ -10,8 +10,8 @@ union(); difference(); intersection(); - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/dxf_linear_extrude-expected.txt b/tests/regression/dumptest/dxf_linear_extrude-expected.txt index ec46e66..9ad9e00 100644 --- a/tests/regression/dumptest/dxf_linear_extrude-expected.txt +++ b/tests/regression/dumptest/dxf_linear_extrude-expected.txt @@ -1,2 +1,2 @@ - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/example009-expected.txt b/tests/regression/dumptest/example009-expected.txt index b293224..b4c7bcf 100644 --- a/tests/regression/dumptest/example009-expected.txt +++ b/tests/regression/dumptest/example009-expected.txt @@ -1,20 +1,20 @@ - %linear_extrude(height = 22, center = true, convexity = 10, $fn = 0, $fa = 12, $fs = 2) { + %linear_extrude(height = 22, center = true, convexity = 10, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "example009.dxf", layer = "body", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } %group() { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 12], [0, 0, 0, 1]]) { - linear_extrude(height = 2, center = true, convexity = 10, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 2, center = true, convexity = 10, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "example009.dxf", layer = "plate", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -12], [0, 0, 0, 1]]) { - linear_extrude(height = 2, center = true, convexity = 10, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 2, center = true, convexity = 10, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "example009.dxf", layer = "plate", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } } } intersection() { - linear_extrude(height = 20, center = true, convexity = 10, twist = -57.5288, slices = 4, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = true, convexity = 10, twist = -57.5288, slices = 4, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "example009.dxf", layer = "fan_top", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } rotate_extrude(file = "example009.dxf", layer = "fan_side", origin = [0, -40], scale = 1, convexity = 10, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/include-tests-expected.txt b/tests/regression/dumptest/include-tests-expected.txt index 47f731e..3f3ecd9 100644 --- a/tests/regression/dumptest/include-tests-expected.txt +++ b/tests/regression/dumptest/include-tests-expected.txt @@ -62,7 +62,7 @@ multmatrix([[1, 0, 0, -6], [0, 1, 0, 0], [0, 0, 1, 19], [0, 0, 0, 1]]) { multmatrix([[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) { group() { - linear_extrude(height = 12, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 12, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { polygon(points = [[0, 0], [18, 0], [0, 4]], paths = [[0, 1, 2]], convexity = 1); } } diff --git a/tests/regression/dumptest/linear_extrude-expected.txt b/tests/regression/dumptest/linear_extrude-expected.txt index ec46e66..9ad9e00 100644 --- a/tests/regression/dumptest/linear_extrude-expected.txt +++ b/tests/regression/dumptest/linear_extrude-expected.txt @@ -1,2 +1,2 @@ - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt index 298b7e7..c031ed8 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.txt +++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt @@ -3,11 +3,11 @@ rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { cube(size = [1, 1, 1], center = false); } - linear_extrude(height = 10, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 10, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { square(size = [10, 10], center = false); } multmatrix([[1, 0, 0, 19], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 10, center = true, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 10, center = true, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { difference() { circle($fn = 0, $fa = 12, $fs = 2, r = 5); circle($fn = 0, $fa = 12, $fs = 2, r = 3); @@ -15,22 +15,22 @@ } } multmatrix([[1, 0, 0, 31.5], [0, 1, 0, 2.5], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 10, center = false, convexity = 1, twist = -45, slices = 3, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 10, center = false, convexity = 1, twist = -45, slices = 3, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { polygon(points = [[-5, -2.5], [5, -2.5], [0, 2.5]], paths = undef, convexity = 1); } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 20], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 20, center = false, convexity = 1, twist = 45, slices = 2, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = false, convexity = 1, twist = 45, slices = 2, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { square(size = [10, 10], center = false); } } multmatrix([[1, 0, 0, 19], [0, 1, 0, 20], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 20, center = false, convexity = 1, twist = 45, slices = 10, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = false, convexity = 1, twist = 45, slices = 10, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { square(size = [10, 10], center = false); } } multmatrix([[1, 0, 0, -15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 5, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 5, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { square(size = [10, 10], center = false); } } diff --git a/tests/regression/dumptest/localfiles-compatibility-test-expected.txt b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt index 8725061..95ba49b 100644 --- a/tests/regression/dumptest/localfiles-compatibility-test-expected.txt +++ b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt @@ -1,9 +1,9 @@ group() { - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, -250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/localfiles-test-expected.txt b/tests/regression/dumptest/localfiles-test-expected.txt index 7a84e88..a7e81e5 100644 --- a/tests/regression/dumptest/localfiles-test-expected.txt +++ b/tests/regression/dumptest/localfiles-test-expected.txt @@ -1,9 +1,9 @@ group() { - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { import(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, -250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + linear_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/projection-tests-expected.txt b/tests/regression/dumptest/projection-tests-expected.txt index 69cb49c..92e6870 100644 --- a/tests/regression/dumptest/projection-tests-expected.txt +++ b/tests/regression/dumptest/projection-tests-expected.txt @@ -3,13 +3,13 @@ projection(cut = true, convexity = 0) { square(size = [1, 1], center = false); } - linear_extrude(height = 20, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = false, convexity = 0) { sphere($fn = 0, $fa = 12, $fs = 2, r = 10); } } multmatrix([[1, 0, 0, 22], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 20, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = true, convexity = 0) { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 9], [0, 0, 0, 1]]) { sphere($fn = 0, $fa = 12, $fs = 2, r = 10); @@ -18,7 +18,7 @@ } } multmatrix([[1, 0, 0, 44], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 20, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 20, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = true, convexity = 0) { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7], [0, 0, 0, 1]]) { sphere($fn = 0, $fa = 12, $fs = 2, r = 10); @@ -27,7 +27,7 @@ } } multmatrix([[1, 0, 0, 0], [0, 1, 0, -22], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 5, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 5, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = true, convexity = 0) { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -4.999999], [0, 0, 0, 1]]) { cube(size = [10, 10, 10], center = true); @@ -36,7 +36,7 @@ } } multmatrix([[1, 0, 0, 0], [0, 1, 0, -44], [0, 0, 1, 0], [0, 0, 0, 1]]) { - linear_extrude(height = 5, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 5, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = true, convexity = 0) { union() { difference() { diff --git a/tests/regression/dumptest/scale2D-tests-expected.txt b/tests/regression/dumptest/scale2D-tests-expected.txt index 6d4c096..9465b8c 100644 --- a/tests/regression/dumptest/scale2D-tests-expected.txt +++ b/tests/regression/dumptest/scale2D-tests-expected.txt @@ -17,14 +17,14 @@ } } } - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { multmatrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { group() { square(size = [2, 3], center = true); } } } - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { multmatrix([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { group() { square(size = [2, 3], center = true); diff --git a/tests/regression/dumptest/scale3D-tests-expected.txt b/tests/regression/dumptest/scale3D-tests-expected.txt index c06b2fe..e802117 100644 --- a/tests/regression/dumptest/scale3D-tests-expected.txt +++ b/tests/regression/dumptest/scale3D-tests-expected.txt @@ -19,21 +19,21 @@ } } } - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { multmatrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]) { group() { cylinder($fn = 8, $fa = 12, $fs = 2, h = 1, r1 = 1, r2 = 1, center = true); } } } - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { multmatrix([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]) { group() { cylinder($fn = 8, $fa = 12, $fs = 2, h = 1, r1 = 1, r2 = 1, center = true); } } } - linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]) { group() { cylinder($fn = 8, $fa = 12, $fs = 2, h = 1, r1 = 1, r2 = 1, center = true); diff --git a/tests/regression/dumptest/use-tests-expected.txt b/tests/regression/dumptest/use-tests-expected.txt index dce0b7d..1095708 100644 --- a/tests/regression/dumptest/use-tests-expected.txt +++ b/tests/regression/dumptest/use-tests-expected.txt @@ -39,10 +39,10 @@ group() { multmatrix([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]) { union() { - linear_extrude(height = 1.5, center = true, convexity = 1, twist = 0, slices = 2, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 1.5, center = true, convexity = 1, twist = 0, slices = 2, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { circle($fn = 30, $fa = 12, $fs = 2, r = 0.3); } - linear_extrude(height = 1.5, center = true, convexity = 1, twist = 0, slices = 2, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 1.5, center = true, convexity = 1, twist = 0, slices = 2, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { projection(cut = false, convexity = 0) { multmatrix([[0, 0, -1, 0], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]]) { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.31819805153], [0, 0, 0, 1]]) { @@ -81,7 +81,7 @@ multmatrix([[1, 0, 0, -6], [0, 1, 0, 0], [0, 0, 1, 19], [0, 0, 0, 1]]) { multmatrix([[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) { group() { - linear_extrude(height = 12, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + linear_extrude(height = 12, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { polygon(points = [[0, 0], [18, 0], [0, 4]], paths = [[0, 1, 2]], convexity = 1); } } -- cgit v0.10.1 From 84eaad145709f4b2e1e5cf7dcdebf3cd32722301 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sun, 12 May 2013 12:19:04 -0500 Subject: update to match new mxe. add 'builder' script to automate some stuff diff --git a/README.md b/README.md index 0f4d8d7..5bbe8b6 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ complete, build OpenSCAD and package it to an installer: If you wish you can only build the openscad.exe binary: cd mingw32 - i686-pc-mingw32-qmake .. CONFIG+=mingw-cross-env + qmake .. CONFIG+=mingw-cross-env make ### Compilation diff --git a/scripts/builder.sh b/scripts/builder.sh new file mode 100755 index 0000000..e244cf5 --- /dev/null +++ b/scripts/builder.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# build&upload script for linux & windows binaries +# tested under linux + +# requirements - +# see http://mxe.cc for required tools (scons, perl, yasm, etc etc etc) + +# todo - 64 bit windows (needs mxe 64 bit stable) +# +# todo - can we build 32 bit linux from within 64 bit linux? +# +# todo - make linux work + +check_starting_path() +{ + if [ -e openscad.pro ]; then + echo 'please start from a clean directory outside of openscad' + exit + fi +} + +get_source_code() +{ + git clone http://github.com/openscad/openscad.git + cd openscad + git submodule update --init # MCAD +} + +build_win32() +{ + . ./scripts/setenv-mingw-xbuild.sh + ./scripts/mingw-x-build-dependencies.sh + ./scripts/release-common.sh mingw32 +} + +build_lin32() +{ + . ./scripts/setenv-unibuild.sh clang + ./scripts/uni-build-dependencies.sh + ./scripts/release-common.sh +} + +upload_win_generic() +{ + if [ -e $3 ]; then + echo $3 found + else + echo $3 not found + fi + opts= + opts="$opts -p openscad" + opts="$opts -u $2" + opts="$opts $3" + echo python ./scripts/googlecode_upload.py -s "$1" $opts + python ./scripts/googlecode_upload.py -s "$1" $opts +} + +upload_win32() +{ + SUMMARY1="Windows x86-32 Snapshot Zipfile" + SUMMARY2="Windows x86-32 Snapshot Installer" + DATECODE=`date +"%Y.%m.%d"` + PACKAGEFILE1=./mingw32/OpenSCAD-$DATECODE-x86-32.zip + PACKAGEFILE2=./mingw32/OpenSCAD-$DATECODE-x86-32-Installer.exe + upload_win_generic "$SUMMARY1" $USERNAME $PACKAGEFILE1 + upload_win_generic "$SUMMARY2" $USERNAME $PACKAGEFILE2 +} + +read_username_from_user() +{ + echo 'Please enter your username for https://code.google.com/hosting/settings' + echo -n 'Username:' + read -s USERNAME + echo 'username is ' $USERNAME +} + +read_password_from_user() +{ + echo 'Please enter your password for https://code.google.com/hosting/settings' + echo -n 'Password:' + read -s PASSWORD1 + echo + echo -n 'Verify :' + read -s PASSWORD2 + echo + if [ ! $PASSWORD1 = $PASSWORD2 ]; then + echo 'error - passwords dont match' + exit + fi + OSUPL_PASSWORD=$PASSWORD1 + export OSUPL_PASSWORD +} + +check_starting_path +read_username_from_user +read_password_from_user +get_source_code +build_win32 +upload_win32 + + + diff --git a/scripts/googlecode_upload.py b/scripts/googlecode_upload.py index 188dd6c..c0fe4c9 100755 --- a/scripts/googlecode_upload.py +++ b/scripts/googlecode_upload.py @@ -189,7 +189,7 @@ def encode_upload_request(fields, file_path): def upload_find_auth(file_path, project_name, summary, labels=None, - user_name=None, password=None, tries=3): + user_name=None, password=None, tries=1): """Find credentials and upload a file to a Google Code project's file server. file_path, project_name, summary, and labels are passed as-is to upload. @@ -203,6 +203,8 @@ def upload_find_auth(file_path, project_name, summary, labels=None, user_name: Your Google account name. tries: How many attempts to make. """ + print 'uploading. username: ', user_name + print 'password detected:', password!=None if user_name is None or password is None: from netrc import netrc authenticators = None @@ -255,14 +257,20 @@ def main(): help='Google Code project name') parser.add_option('-u', '--user', dest='user', help='Your Google Code username') - parser.add_option('-w', '--password', dest='password', - help='Your Google Code password') + #this is a massive security hole. anyone using 'ps' could steal p/w + #parser.add_option('-w', '--password', dest='password', + # help='Your Google Code password') parser.add_option('-l', '--labels', dest='labels', help='An optional list of comma-separated labels to attach ' 'to the file') options, args = parser.parse_args() + if os.environ.has_key('OSUPL_PASSWORD'): + options.password=os.environ['OSUPL_PASSWORD'] + else: + options.password=None + if not options.summary: parser.error('File summary is missing.') elif not options.project: @@ -279,6 +287,7 @@ def main(): else: labels = None + print 'read arguments' status, reason, url = upload_find_auth(file_path, options.project, options.summary, labels, options.user, options.password) @@ -293,4 +302,5 @@ def main(): if __name__ == '__main__': + print sys.argv sys.exit(main()) diff --git a/scripts/mingw-x-build-dependencies.sh b/scripts/mingw-x-build-dependencies.sh index ee51848..7a16530 100755 --- a/scripts/mingw-x-build-dependencies.sh +++ b/scripts/mingw-x-build-dependencies.sh @@ -49,7 +49,7 @@ fi echo "entering" $MXEDIR cd $MXEDIR -echo "make mpfr eigen opencsg cgal qt -j $NUMCPU JOBS=$NUMJOBS" +echo "make mpfr eigen opencsg cgal qt nsis -j $NUMCPU JOBS=$NUMJOBS" make mpfr eigen opencsg cgal qt nsis -j $NUMCPU JOBS=$NUMJOBS #make mpfr -j $NUMCPU JOBS=$NUMJOBS # for testing diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 10a1c18..85f0e71 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -134,7 +134,7 @@ esac case $OS in LINXWIN) - cd $DEPLOYDIR && i686-pc-mingw32-qmake VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+=$CONFIG CONFIG+=mingw-cross-env CONFIG-=debug ../openscad.pro + cd $DEPLOYDIR && qmake VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+=$CONFIG CONFIG+=mingw-cross-env CONFIG-=debug ../openscad.pro cd $OPENSCADDIR ;; *) @@ -144,7 +144,8 @@ esac case $OS in LINXWIN) - cd $DEPLOYDIR && make -s clean + #cd $DEPLOYDIR + make -s clean ## comment out for test-run cd $OPENSCADDIR ;; *) @@ -172,10 +173,14 @@ case $OS in # dont use paralell builds, it can error-out on parser_yacc. # make main openscad.exe - cd $DEPLOYDIR && make $TARGET - + cd $DEPLOYDIR + make $TARGET ## comment out for test-run + if [ ! -e $TARGET/openscad.exe ]; then + echo 'build failed. stopping.' + exit + fi # make console pipe-able openscad.com - see winconsole.pri for info - i686-pc-mingw32-qmake CONFIG+=winconsole ../openscad.pro + qmake CONFIG+=winconsole ../openscad.pro make cd $OPENSCADDIR @@ -245,21 +250,24 @@ case $OS in cp win32deps/* openscad-$VERSION cp $TARGET/openscad.exe openscad-$VERSION cp $TARGET/openscad.com openscad-$VERSION - rm -f openscad-$VERSION.zip - "$ZIP" $ZIPARGS openscad-$VERSION.zip openscad-$VERSION + rm -f openscad-$VERSION.x86-$ARCH.zip + "$ZIP" $ZIPARGS openscad-$VERSION.x86-$ARCH.zip openscad-$VERSION rm -rf openscad-$VERSION echo "Binary created: openscad-$VERSION.zip" ;; LINXWIN) + BINFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH.zip + INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH-Installer.exe + #package - echo "Creating binary package" + echo "Creating binary zip package" cd $DEPLOYDIR cp $TARGET/openscad.exe openscad-$VERSION cp $TARGET/openscad.com openscad-$VERSION - rm -f OpenSCAD-$VERSION.zip - "$ZIP" $ZIPARGS OpenSCAD-$VERSION.zip openscad-$VERSION + rm -f OpenSCAD-$VERSION.x86-$ARCH.zip + "$ZIP" $ZIPARGS $BINFILE openscad-$VERSION cd $OPENSCADDIR - echo "Binary package created" + echo "Binary zip package created" echo "Creating installer" echo "Copying NSIS files to $DEPLOYDIR/openscad-$VERSION" @@ -270,11 +278,9 @@ case $OS in # NSISDEBUG= # leave blank for full log echo $MAKENSIS $NSISDEBUG installer.nsi $MAKENSIS $NSISDEBUG installer.nsi - cp $DEPLOYDIR/openscad-$VERSION/openscad_setup.exe $DEPLOYDIR/OpenSCAD-$VERSION-Installer.exe + cp $DEPLOYDIR/openscad-$VERSION/openscad_setup.exe $INSTFILE cd $OPENSCADDIR - BINFILE=$DEPLOYDIR/OpenSCAD-$VERSION.zip - INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-Installer.exe if [ -e $BINFILE ]; then if [ -e $INSTFILE ]; then echo diff --git a/scripts/setenv-mingw-xbuild.sh b/scripts/setenv-mingw-xbuild.sh index e8976b7..e31534e 100644 --- a/scripts/setenv-mingw-xbuild.sh +++ b/scripts/setenv-mingw-xbuild.sh @@ -27,11 +27,6 @@ fi export PATH=$MXEDIR/usr/bin:$PATH -echo BASEDIR: $BASEDIR -echo MXEDIR: $MXEDIR -echo DEPLOYDIR: $DEPLOYDIR -echo PATH modified with $MXEDIR/usr/bin - if [ ! -e $DEPLOYDIR ]; then mkdir -p $DEPLOYDIR fi @@ -39,5 +34,13 @@ fi echo linking $MXEDIR/usr/i686-pc-mingw32/ to $DEPLOYDIR/mingw-cross-env rm -f $DEPLOYDIR/mingw-cross-env ln -s $MXEDIR/usr/i686-pc-mingw32/ $DEPLOYDIR/mingw-cross-env +export PATH=$MXEDIR/usr/i686-pc-mingw32/qt/bin:$PATH + +echo BASEDIR: $BASEDIR +echo MXEDIR: $MXEDIR +echo DEPLOYDIR: $DEPLOYDIR +echo PATH modified: $MXEDIR/usr/bin +echo PATH modified: $MXEDIR/usr/i686-pc-mingw32/qt/bin + -- cgit v0.10.1 From 348d13cf3bafc0369691b0fc351a75401ee79ccf Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sun, 12 May 2013 12:22:11 -0500 Subject: add notes diff --git a/scripts/builder.sh b/scripts/builder.sh index e244cf5..4bece8a 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -1,11 +1,13 @@ #!/usr/bin/env bash -# build&upload script for linux & windows binaries +# build&upload script for linux & windows snapshot binaries # tested under linux # requirements - # see http://mxe.cc for required tools (scons, perl, yasm, etc etc etc) +# todo - auto update webpage to link to proper snapshot +# # todo - 64 bit windows (needs mxe 64 bit stable) # # todo - can we build 32 bit linux from within 64 bit linux? -- cgit v0.10.1 From 0cc3bb3890fc144143bd3c11d605ca64f3c29266 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Mon, 13 May 2013 06:57:19 -0500 Subject: fix indentation, uncomment cd command, fix reading of username diff --git a/scripts/builder.sh b/scripts/builder.sh index 4bece8a..c2f81e8 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -73,7 +73,7 @@ read_username_from_user() { echo 'Please enter your username for https://code.google.com/hosting/settings' echo -n 'Username:' - read -s USERNAME + read USERNAME echo 'username is ' $USERNAME } diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 85f0e71..02b276b 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -144,7 +144,7 @@ esac case $OS in LINXWIN) - #cd $DEPLOYDIR + cd $DEPLOYDIR make -s clean ## comment out for test-run cd $OPENSCADDIR ;; @@ -174,8 +174,8 @@ case $OS in # make main openscad.exe cd $DEPLOYDIR - make $TARGET ## comment out for test-run - if [ ! -e $TARGET/openscad.exe ]; then + make $TARGET ## comment out for test-run + if [ ! -e $TARGET/openscad.exe ]; then echo 'build failed. stopping.' exit fi -- cgit v0.10.1 From ee6f149dd0d9bcef0cb94cef154ed32f308c23e1 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 13 May 2013 16:27:17 -0400 Subject: bugfix: Fixed recursion crash (#346) diff --git a/src/expr.cc b/src/expr.cc index 746c0e3..9eaeeef 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -31,6 +31,7 @@ #include #include #include "stl-utils.h" +#include "printutils.h" #include #include @@ -40,7 +41,7 @@ Expression::Expression() Expression::Expression(const std::string &type, Expression *left, Expression *right) - : type(type) + : type(type), recursioncount(0) { this->children.push_back(left); this->children.push_back(right); @@ -61,6 +62,18 @@ Expression::~Expression() std::for_each(this->children.begin(), this->children.end(), del_fun()); } +class FuncRecursionGuard +{ +public: + FuncRecursionGuard(const Expression &e) : expr(e) { + expr.recursioncount++; + } + ~FuncRecursionGuard() { expr.recursioncount--; } + bool recursion_detected() const { return (expr.recursioncount > 100); } +private: + const Expression &expr; +}; + Value Expression::evaluate(const Context *context) const { if (this->type == "!") @@ -141,6 +154,12 @@ Value Expression::evaluate(const Context *context) const return Value(); } if (this->type == "F") { + FuncRecursionGuard g(*this); + if (g.recursion_detected()) { + PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname); + return Value(); + } + EvalContext c(context, this->call_arguments); return context->evaluate_function(this->call_funcname, &c); } diff --git a/src/expression.h b/src/expression.h index 6c03f52..3629704 100644 --- a/src/expression.h +++ b/src/expression.h @@ -40,6 +40,8 @@ public: Value evaluate(const class Context *context) const; std::string toString() const; + + mutable int recursioncount; }; std::ostream &operator<<(std::ostream &stream, const Expression &expr); diff --git a/src/modcontext.cc b/src/modcontext.cc index 44c2002..3879811 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -27,20 +27,6 @@ void ModuleContext::initializeModule(const class Module &module) } } -class RecursionGuard -{ -public: - RecursionGuard(const ModuleContext &c, const std::string &name) : c(c), name(name) { - c.recursioncount[name]++; - } - ~RecursionGuard() { if (--c.recursioncount[name] == 0) c.recursioncount.erase(name); } - bool recursion_detected() const { return (c.recursioncount[name] > 100); } -private: - const ModuleContext &c; - const std::string &name; -}; - - /*! Only used to initialize builtins for the top-level root context */ @@ -81,12 +67,6 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const { - RecursionGuard g(*this, name); - if (g.recursion_detected()) { - PRINTB("Recursion detected calling function '%s'", name); - return Value(); - } - const AbstractFunction *foundf = findLocalFunction(name); if (foundf) return foundf->evaluate(this, evalctx); @@ -141,12 +121,6 @@ FileContext::FileContext(const class FileModule &module, const Context *parent) Value FileContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const { - RecursionGuard g(*this, name); - if (g.recursion_detected()) { - PRINTB("Recursion detected calling function '%s'", name); - return Value(); - } - const AbstractFunction *foundf = findLocalFunction(name); if (foundf) return foundf->evaluate(this, evalctx); diff --git a/src/modcontext.h b/src/modcontext.h index 4479051..0b3e48c 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -36,8 +36,6 @@ public: #ifdef DEBUG virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); #endif - - mutable boost::unordered_map recursioncount; }; class FileContext : public ModuleContext diff --git a/src/module.cc b/src/module.cc index 8b84c07..e853457 100644 --- a/src/module.cc +++ b/src/module.cc @@ -135,8 +135,28 @@ Module::~Module() { } +class ModRecursionGuard +{ +public: + ModRecursionGuard(const ModuleInstantiation &inst) : inst(inst) { + inst.recursioncount++; + } + ~ModRecursionGuard() { + inst.recursioncount--; + } + bool recursion_detected() const { return (inst.recursioncount > 100); } +private: + const ModuleInstantiation &inst; +}; + AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { + ModRecursionGuard g(*inst); + if (g.recursion_detected()) { + PRINTB("ERROR: Recursion detected calling module '%s'", inst->name()); + return NULL; + } + ModuleContext c(ctx, evalctx); c.initializeModule(*this); c.set_variable("$children", Value(double(inst->scope.children.size()))); diff --git a/src/module.h b/src/module.h index 8f1ccb7..9f46d37 100644 --- a/src/module.h +++ b/src/module.h @@ -13,7 +13,7 @@ class ModuleInstantiation { public: ModuleInstantiation(const std::string &name = "") - : tag_root(false), tag_highlight(false), tag_background(false), modname(name) { } + : tag_root(false), tag_highlight(false), tag_background(false), recursioncount(0), modname(name) { } virtual ~ModuleInstantiation(); std::string dump(const std::string &indent) const; @@ -35,6 +35,7 @@ public: bool tag_root; bool tag_highlight; bool tag_background; + mutable int recursioncount; protected: std::string modname; std::string modpath; -- cgit v0.10.1 From a1ade23e98307562f25a4496100c18af800e088f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 14 May 2013 01:31:44 +0200 Subject: bugfix: messed up parser filenames diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 38b2758..9821d70 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -329,8 +329,9 @@ if (WIN32) set(FLEX_UNISTD_FLAG "-DYY_NO_UNISTD_H") endif() FLEX_TARGET(OpenSCADlexer ../src/lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "-Plexer ${FLEX_UNISTD_FLAG}") -BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp COMPILE_FLAGS "-p parser") +BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c COMPILE_FLAGS "-p parser") ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser) +set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX") # CGAL -- cgit v0.10.1 From f179e0b5670631fe6ade5d1cc531529f4fcdfc87 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 13 May 2013 20:40:32 -0400 Subject: Forgot to initialize recursioncount in all constructors diff --git a/src/expr.cc b/src/expr.cc index 9eaeeef..4355400 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -35,7 +35,7 @@ #include #include -Expression::Expression() +Expression::Expression() : recursioncount(0) { } @@ -48,12 +48,12 @@ Expression::Expression(const std::string &type, } Expression::Expression(const std::string &type, Expression *expr) - : type(type) + : type(type), recursioncount(0) { this->children.push_back(expr); } -Expression::Expression(const Value &val) : const_value(val), type("C") +Expression::Expression(const Value &val) : const_value(val), type("C"), recursioncount(0) { } -- cgit v0.10.1 From beda4a79524e5dcc667455938a3405a9e9b3f735 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 14 May 2013 02:55:53 +0200 Subject: Updated expected test: ERROR label diff --git a/tests/regression/echotest/recursion-tests-expected.txt b/tests/regression/echotest/recursion-tests-expected.txt index f4897ee..e5c99b1 100644 --- a/tests/regression/echotest/recursion-tests-expected.txt +++ b/tests/regression/echotest/recursion-tests-expected.txt @@ -1,2 +1,2 @@ -Recursion detected calling function 'crash' +ERROR: Recursion detected calling function 'crash' ECHO: undef -- cgit v0.10.1 From 6161214083ba6fc3c6cadbc98e04ad5e826cf984 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Tue, 14 May 2013 23:45:40 -0500 Subject: enable auto updateing of website thru openscad.github.com diff --git a/scripts/builder.sh b/scripts/builder.sh index c2f81e8..9dcc3a6 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -13,9 +13,12 @@ # todo - can we build 32 bit linux from within 64 bit linux? # # todo - make linux work +# +# todo - detect failure and stop check_starting_path() { + STARTPATH=$PWD if [ -e openscad.pro ]; then echo 'please start from a clean directory outside of openscad' exit @@ -45,6 +48,7 @@ build_lin32() upload_win_generic() { + # 1=file summary, 2 = username, 3 = filename if [ -e $3 ]; then echo $3 found else @@ -54,7 +58,6 @@ upload_win_generic() opts="$opts -p openscad" opts="$opts -u $2" opts="$opts $3" - echo python ./scripts/googlecode_upload.py -s "$1" $opts python ./scripts/googlecode_upload.py -s "$1" $opts } @@ -63,10 +66,17 @@ upload_win32() SUMMARY1="Windows x86-32 Snapshot Zipfile" SUMMARY2="Windows x86-32 Snapshot Installer" DATECODE=`date +"%Y.%m.%d"` - PACKAGEFILE1=./mingw32/OpenSCAD-$DATECODE-x86-32.zip - PACKAGEFILE2=./mingw32/OpenSCAD-$DATECODE-x86-32-Installer.exe - upload_win_generic "$SUMMARY1" $USERNAME $PACKAGEFILE1 - upload_win_generic "$SUMMARY2" $USERNAME $PACKAGEFILE2 + BASEDIR=./mingw32/ + WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32.zip + WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32-Installer.exe + upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE1 + upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE2 + export WIN32_PACKAGEFILE1 + export WIN32_PACKAGEFILE2 + WIN32_PACKAGEFILE1_SIZE=`ls -sh $BASEDIR/$WIN32_PACKAGEFILE1 | awk ' {print $1} ';` + WIN32_PACKAGEFILE2_SIZE=`ls -sh $BASEDIR/$WIN32_PACKAGEFILE2 | awk ' {print $1} ';` + export WIN32_PACKAGEFILE1_SIZE + export WIN32_PACKAGEFILE2_SIZE } read_username_from_user() @@ -94,12 +104,49 @@ read_password_from_user() export OSUPL_PASSWORD } +update_www_download_links() +{ + cd $STARTPATH + git clone http://github.com/openscad/openscad.github.com.git + cd openscad.github.com + cd inc + echo `pwd` + BASEURL='https://openscad.google.com/files/' + DATECODE=`date +"%Y.%m.%d"` + + rm win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT1_URL'] = '$BASEURL$WIN32_PACKAGEFILE1'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT2_URL'] = '$BASEURL$WIN32_PACKAGEFILE2'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT1_NAME'] = 'OpenSCAD $DATECODE'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT2_NAME'] = 'OpenSCAD $DATECODE'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT1_SIZE'] = '$WIN32_PACKAGEFILE1_SIZE'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT2_SIZE'] = '$WIN32_PACKAGEFILE2_SIZE'" >> win_snapshot_links.js + echo 'modified win_snapshot_links.js' + cat win_snapshot_links.js + + git diff + echo git commit -a -m 'updated snapshot links' + echo git push origin +} + +check_ssh_agent() +{ + if [ ! $SSH_AUTH_SOCK ]; then + echo 'please start an ssh-agent for github.com/openscad/openscad.github.com uploads' + echo + echo ' ssh-agent > .tmp && source .tmp && ssh-add' + echo + fi +} + +check_ssh_agent check_starting_path read_username_from_user read_password_from_user get_source_code build_win32 upload_win32 +update_www_download_links -- cgit v0.10.1 From 8cdadca9208a83d60ccb8201d439fb3dd67ec019 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Wed, 15 May 2013 17:00:40 -0500 Subject: clarify comments diff --git a/scripts/builder.sh b/scripts/builder.sh index 9dcc3a6..9449a9c 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -125,7 +125,7 @@ update_www_download_links() cat win_snapshot_links.js git diff - echo git commit -a -m 'updated snapshot links' + echo git commit -a -m 'builder.sh - updated snapshot links' echo git push origin } @@ -133,6 +133,7 @@ check_ssh_agent() { if [ ! $SSH_AUTH_SOCK ]; then echo 'please start an ssh-agent for github.com/openscad/openscad.github.com uploads' + echo 'for example:' echo echo ' ssh-agent > .tmp && source .tmp && ssh-add' echo -- cgit v0.10.1 From 2e758fcc82a8a06152f5e89ec9295783b3e889fe Mon Sep 17 00:00:00 2001 From: Don Bright Date: Wed, 15 May 2013 17:04:46 -0500 Subject: enable 'dry run' in builder script diff --git a/scripts/builder.sh b/scripts/builder.sh index 9449a9c..e0bb608 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -16,6 +16,8 @@ # # todo - detect failure and stop +dryrun= + check_starting_path() { STARTPATH=$PWD @@ -58,7 +60,11 @@ upload_win_generic() opts="$opts -p openscad" opts="$opts -u $2" opts="$opts $3" - python ./scripts/googlecode_upload.py -s "$1" $opts + if [ ! dryrun ]; then + python ./scripts/googlecode_upload.py -s "$1" $opts + else + echo dry run, not uploading to googlecode + fi } upload_win32() @@ -125,8 +131,12 @@ update_www_download_links() cat win_snapshot_links.js git diff - echo git commit -a -m 'builder.sh - updated snapshot links' - echo git push origin + if [ ! dryrun ]; then + git commit -a -m 'builder.sh - updated snapshot links' + git push origin + else + echo dry run, not updating www links + fi } check_ssh_agent() -- cgit v0.10.1 From 5f6afe8cbbdd16538b662a0880f7961a9a3aade5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 15 May 2013 20:33:24 -0400 Subject: Update the new javascript with download info diff --git a/scripts/publish-macosx.sh b/scripts/publish-macosx.sh index 3aeeaf9..9d0423d 100755 --- a/scripts/publish-macosx.sh +++ b/scripts/publish-macosx.sh @@ -3,6 +3,41 @@ # NB! To build a release build, the VERSION and VERSIONDATE environment variables needs to be set. # See doc/release-checklist.txt +human_filesize() +{ + awk -v sum=$1 'BEGIN { + hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; + for (x=1024**3; x>=1024; x/=1024) { + if (sum>=x) { printf "%.1f %s\n",sum/x,hum[x]; break } + } + }' +} + +# Pass version= packagefile= filesize= +update_www_download_links() +{ + # Make the passed variables available + local $* + filesize=$(human_filesize $filesize) + webdir=../openscad.github.com + incfile=inc/mac_snapshot_links.js + BASEURL='https://openscad.google.com/files/' + DATECODE=`date +"%Y.%m.%d"` + + if [ -f $webdir/$incfile ]; then + cd $webdir + echo "snapinfo['MAC_SNAPSHOT_URL'] = '$BASEURL$packagefile'" > $incfile + echo "snapinfo['MAC_SNAPSHOT_NAME'] = 'OpenSCAD $version'" >> $incfile + echo "snapinfo['MAC_SNAPSHOT_SIZE'] = '$filesize'" >> $incfile + echo 'modified mac_snapshot_links.js' + + git --no-pager diff + echo "Web page updated. Remember to commit and push openscad.github.com" + else + echo "Web page not found at $incfile" + fi +} + if test -z "$VERSIONDATE"; then VERSIONDATE=`date "+%Y.%m.%d"` fi @@ -40,7 +75,8 @@ else APPCASTFILE=appcast.xml fi echo "Creating appcast $APPCASTFILE..." -sed -e "s,@VERSION@,$VERSION,g" -e "s,@VERSIONDATE@,$VERSIONDATE,g" -e "s,@DSASIGNATURE@,$SIGNATURE,g" -e "s,@FILESIZE@,$(stat -f "%z" OpenSCAD-$VERSION.dmg),g" $APPCASTFILE.in > $APPCASTFILE +FILESIZE=$(stat -f "%z" OpenSCAD-$VERSION.dmg) +sed -e "s,@VERSION@,$VERSION,g" -e "s,@VERSIONDATE@,$VERSIONDATE,g" -e "s,@DSASIGNATURE@,$SIGNATURE,g" -e "s,@FILESIZE@,$FILESIZE,g" $APPCASTFILE.in > $APPCASTFILE cp $APPCASTFILE ../openscad.github.com if [[ $VERSION == $VERSIONDATE ]]; then cp $APPCASTFILE ../openscad.github.com/appcast-snapshots.xml @@ -50,6 +86,9 @@ echo "Uploading..." LABELS=OpSys-OSX,Type-Executable if ! $SNAPSHOT; then LABELS=$LABELS,Featured; fi `dirname $0`/googlecode_upload.py -s 'Mac OS X Snapshot' -p openscad OpenSCAD-$VERSION.dmg -l $LABELS +if [[ $? != 0 ]]; then + exit 1 +fi # Update snapshot filename on web page -`dirname $0`/update-web.sh OpenSCAD-$VERSION.dmg +update_www_download_links version=$VERSION packagefile=OpenSCAD-$VERSION.dmg filesize=$FILESIZE -- cgit v0.10.1 From 602b529e9f737c940c7dad194d4e199f43c8bed9 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Wed, 15 May 2013 19:33:55 -0500 Subject: fix bug in dryrun settings diff --git a/scripts/builder.sh b/scripts/builder.sh index e0bb608..5b3835b 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -16,7 +16,7 @@ # # todo - detect failure and stop -dryrun= +DRYRUN= check_starting_path() { @@ -60,7 +60,7 @@ upload_win_generic() opts="$opts -p openscad" opts="$opts -u $2" opts="$opts $3" - if [ ! dryrun ]; then + if [ ! $DRYRUN ]; then python ./scripts/googlecode_upload.py -s "$1" $opts else echo dry run, not uploading to googlecode @@ -113,7 +113,7 @@ read_password_from_user() update_www_download_links() { cd $STARTPATH - git clone http://github.com/openscad/openscad.github.com.git + git clone git@github.com:openscad/openscad.github.com.git cd openscad.github.com cd inc echo `pwd` @@ -130,8 +130,8 @@ update_www_download_links() echo 'modified win_snapshot_links.js' cat win_snapshot_links.js - git diff - if [ ! dryrun ]; then + PAGER=cat git diff + if [ ! $DRYRUN ]; then git commit -a -m 'builder.sh - updated snapshot links' git push origin else -- cgit v0.10.1 From 26df5c446647aec19fa8a8615e61702950691746 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Wed, 15 May 2013 19:56:49 -0500 Subject: make size postpend 'B' for 'Bytes', for download page diff --git a/scripts/builder.sh b/scripts/builder.sh index 5b3835b..75b80f8 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -81,6 +81,8 @@ upload_win32() export WIN32_PACKAGEFILE2 WIN32_PACKAGEFILE1_SIZE=`ls -sh $BASEDIR/$WIN32_PACKAGEFILE1 | awk ' {print $1} ';` WIN32_PACKAGEFILE2_SIZE=`ls -sh $BASEDIR/$WIN32_PACKAGEFILE2 | awk ' {print $1} ';` + WIN32_PACKAGEFILE1_SIZE=`echo "$WIN32_PACKAGEFILE1_SIZE""B"` + WIN32_PACKAGEFILE2_SIZE=`echo "$WIN32_PACKAGEFILE2_SIZE""B"` export WIN32_PACKAGEFILE1_SIZE export WIN32_PACKAGEFILE2_SIZE } -- cgit v0.10.1 From 293f3cc7c9c6dfec76120714b33a458f54792545 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Thu, 16 May 2013 06:54:34 -0500 Subject: enable mingw64 cross build (alpha stage) diff --git a/eigen.pri b/eigen.pri index 5935a47..1c9a5ef 100644 --- a/eigen.pri +++ b/eigen.pri @@ -70,7 +70,12 @@ isEmpty(EIGEN_INCLUDEPATH) { } mingw-cross-env { - EIGEN_CFLAGS = $$system("i686-pc-mingw32-pkg-config --cflags eigen3") + exists(mingw-cross-env/../i686-pc-mingw32-pkg-config) { + EIGEN_CFLAGS = $$system("i686-pc-mingw32-pkg-config --cflags eigen3") + } + exists(mingw-cross-env/../x86_64-w64-mingw32-pkg-config) { + EIGEN_CFLAGS = $$system("x86_64-w64-mingw32-pkg-config --cflags eigen3") + } EIGEN_INCLUDEPATH = $$replace(EIGEN_CFLAGS,"-I","") } diff --git a/mingw-cross-env.pri b/mingw-cross-env.pri index 9b808c0..a447fd8 100644 --- a/mingw-cross-env.pri +++ b/mingw-cross-env.pri @@ -4,7 +4,9 @@ CONFIG(mingw-cross-env) { LIBS += mingw-cross-env/lib/libglut.a LIBS += mingw-cross-env/lib/libopengl32.a LIBS += mingw-cross-env/lib/libGLEW.a - LIBS += mingw-cross-env/lib/libglaux.a + exists( mingw-cross-env/lib/libglaux.a ) { + LIBS += mingw-cross-env/lib/libglaux.a + } LIBS += mingw-cross-env/lib/libglu32.a LIBS += mingw-cross-env/lib/libopencsg.a LIBS += mingw-cross-env/lib/libmpfr.a diff --git a/scripts/LogicLib.nsh b/scripts/LogicLib.nsh new file mode 100644 index 0000000..2f8968c --- /dev/null +++ b/scripts/LogicLib.nsh @@ -0,0 +1,792 @@ +; NSIS LOGIC LIBRARY - LogicLib.nsh +; Version 2.6 - 08/12/2007 +; By dselkirk@hotmail.com +; and eccles@users.sf.net +; with IfNot support added by Message +; +; Questions/Comments - +; See http://forums.winamp.com/showthread.php?s=&postid=1116241 +; +; Description: +; Provides the use of various logic statements within NSIS. +; +; Usage: +; The following "statements" are available: +; If|IfNot|Unless..{ElseIf|ElseIfNot|ElseUnless}..[Else]..EndIf|EndUnless +; - Conditionally executes a block of statements, depending on the value +; of an expression. IfNot and Unless are equivalent and +; interchangeable, as are ElseIfNot and ElseUnless. +; AndIf|AndIfNot|AndUnless|OrIf|OrIfNot|OrUnless +; - Adds any number of extra conditions to If, IfNot, Unless, ElseIf, +; ElseIfNot and ElseUnless statements. +; IfThen|IfNotThen..|..| +; - Conditionally executes an inline statement, depending on the value +; of an expression. +; IfCmd..||..| +; - Conditionally executes an inline statement, depending on a true +; value of the provided NSIS function. +; Select..{Case[2|3|4|5]}..[CaseElse|Default]..EndSelect +; - Executes one of several blocks of statements, depending on the value +; of an expression. +; Switch..{Case|CaseElse|Default}..EndSwitch +; - Jumps to one of several labels, depending on the value of an +; expression. +; Do[While|Until]..{ExitDo|Continue|Break}..Loop[While|Until] +; - Repeats a block of statements until stopped, or depending on the +; value of an expression. +; While..{ExitWhile|Continue|Break}..EndWhile +; - An alias for DoWhile..Loop (for backwards-compatibility) +; For[Each]..{ExitFor|Continue|Break}..Next +; - Repeats a block of statements varying the value of a variable. +; +; The following "expressions" are available: +; Standard (built-in) string tests (which are case-insensitive): +; a == b; a != b +; Additional case-insensitive string tests (using System.dll): +; a S< b; a S>= b; a S> b; a S<= b +; Case-sensitive string tests: +; a S== b; a S!= b +; Standard (built-in) signed integer tests: +; a = b; a <> b; a < b; a >= b; a > b; a <= b +; Standard (built-in) unsigned integer tests: +; a U< b; a U>= b; a U> b; a U<= b +; 64-bit integer tests (using System.dll): +; a L= b; a L<> b; a L< b; a L>= b; a L> b; a L<= b +; Built-in NSIS flag tests: +; ${Abort}; ${Errors}; ${RebootFlag}; ${Silent} +; Built-in NSIS other tests: +; ${FileExists} a +; Any conditional NSIS instruction test: +; ${Cmd} a +; Section flag tests: +; ${SectionIsSelected} a; ${SectionIsSectionGroup} a; +; ${SectionIsSectionGroupEnd} a; ${SectionIsBold} a; +; ${SectionIsReadOnly} a; ${SectionIsExpanded} a; +; ${SectionIsPartiallySelected} a +; +; Examples: +; See LogicLib.nsi in the Examples folder for lots of example usage. + +!verbose push +!verbose 3 +!ifndef LOGICLIB_VERBOSITY + !define LOGICLIB_VERBOSITY 3 +!endif +!define _LOGICLIB_VERBOSITY ${LOGICLIB_VERBOSITY} +!undef LOGICLIB_VERBOSITY +!verbose ${_LOGICLIB_VERBOSITY} + +!ifndef LOGICLIB + !define LOGICLIB + !define | "'" + !define || "' '" + !define LOGICLIB_COUNTER 0 + + !include Sections.nsh + + !macro _LOGICLIB_TEMP + !ifndef _LOGICLIB_TEMP + !define _LOGICLIB_TEMP + Var /GLOBAL _LOGICLIB_TEMP ; Temporary variable to aid the more elaborate logic tests + !endif + !macroend + + !macro _IncreaseCounter + !define _LOGICLIB_COUNTER ${LOGICLIB_COUNTER} + !undef LOGICLIB_COUNTER + !define /math LOGICLIB_COUNTER ${_LOGICLIB_COUNTER} + 1 + !undef _LOGICLIB_COUNTER + !macroend + + !macro _PushLogic + !insertmacro _PushScope Logic _LogicLib_Label_${LOGICLIB_COUNTER} + !insertmacro _IncreaseCounter + !macroend + + !macro _PopLogic + !insertmacro _PopScope Logic + !macroend + + !macro _PushScope Type label + !ifdef _${Type} ; If we already have a statement + !define _Cur${Type} ${_${Type}} + !undef _${Type} + !define _${Type} ${label} + !define ${_${Type}}Prev${Type} ${_Cur${Type}} ; Save the current logic + !undef _Cur${Type} + !else + !define _${Type} ${label} ; Initialise for first statement + !endif + !macroend + + !macro _PopScope Type + !ifndef _${Type} + !error "Cannot use _Pop${Type} without a preceding _Push${Type}" + !endif + !ifdef ${_${Type}}Prev${Type} ; If a previous statment was active then restore it + !define _Cur${Type} ${_${Type}} + !undef _${Type} + !define _${Type} ${${_Cur${Type}}Prev${Type}} + !undef ${_Cur${Type}}Prev${Type} + !undef _Cur${Type} + !else + !undef _${Type} + !endif + !macroend + + ; String tests + !macro _== _a _b _t _f + StrCmp `${_a}` `${_b}` `${_t}` `${_f}` + !macroend + + !macro _!= _a _b _t _f + !insertmacro _== `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Case-sensitive string tests + !macro _S== _a _b _t _f + StrCmpS `${_a}` `${_b}` `${_t}` `${_f}` + !macroend + + !macro _S!= _a _b _t _f + !insertmacro _S== `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Extra string tests (cannot do these case-sensitively - I tried and lstrcmp still ignored the case) + !macro _StrCmpI _a _b _e _l _m + !insertmacro _LOGICLIB_TEMP + System::Call `kernel32::lstrcmpiA(ts, ts) i.s` `${_a}` `${_b}` + Pop $_LOGICLIB_TEMP + IntCmp $_LOGICLIB_TEMP 0 `${_e}` `${_l}` `${_m}` + !macroend + + !macro _S< _a _b _t _f + !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_t}` `${_f}` + !macroend + + !macro _S>= _a _b _t _f + !insertmacro _S< `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _S> _a _b _t _f + !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_f}` `${_t}` + !macroend + + !macro _S<= _a _b _t _f + !insertmacro _S> `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Integer tests + !macro _= _a _b _t _f + IntCmp `${_a}` `${_b}` `${_t}` `${_f}` `${_f}` + !macroend + + !macro _<> _a _b _t _f + !insertmacro _= `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _< _a _b _t _f + IntCmp `${_a}` `${_b}` `${_f}` `${_t}` `${_f}` + !macroend + + !macro _>= _a _b _t _f + !insertmacro _< `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _> _a _b _t _f + IntCmp `${_a}` `${_b}` `${_f}` `${_f}` `${_t}` + !macroend + + !macro _<= _a _b _t _f + !insertmacro _> `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Unsigned integer tests (NB: no need for extra equality tests) + !macro _U< _a _b _t _f + IntCmpU `${_a}` `${_b}` `${_f}` `${_t}` `${_f}` + !macroend + + !macro _U>= _a _b _t _f + !insertmacro _U< `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _U> _a _b _t _f + IntCmpU `${_a}` `${_b}` `${_f}` `${_f}` `${_t}` + !macroend + + !macro _U<= _a _b _t _f + !insertmacro _U> `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Int64 tests + !macro _Int64Cmp _a _o _b _t _f + !insertmacro _LOGICLIB_TEMP + System::Int64Op `${_a}` `${_o}` `${_b}` + Pop $_LOGICLIB_TEMP + !insertmacro _= $_LOGICLIB_TEMP 0 `${_f}` `${_t}` + !macroend + + !macro _L= _a _b _t _f + !insertmacro _Int64Cmp `${_a}` = `${_b}` `${_t}` `${_f}` + !macroend + + !macro _L<> _a _b _t _f + !insertmacro _L= `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _L< _a _b _t _f + !insertmacro _Int64Cmp `${_a}` < `${_b}` `${_t}` `${_f}` + !macroend + + !macro _L>= _a _b _t _f + !insertmacro _L< `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + !macro _L> _a _b _t _f + !insertmacro _Int64Cmp `${_a}` > `${_b}` `${_t}` `${_f}` + !macroend + + !macro _L<= _a _b _t _f + !insertmacro _L> `${_a}` `${_b}` `${_f}` `${_t}` + !macroend + + ; Flag tests + !macro _Abort _a _b _t _f + IfAbort `${_t}` `${_f}` + !macroend + !define Abort `"" Abort ""` + + !macro _Errors _a _b _t _f + IfErrors `${_t}` `${_f}` + !macroend + !define Errors `"" Errors ""` + + !macro _FileExists _a _b _t _f + IfFileExists `${_b}` `${_t}` `${_f}` + !macroend + !define FileExists `"" FileExists` + + !macro _RebootFlag _a _b _t _f + IfRebootFlag `${_t}` `${_f}` + !macroend + !define RebootFlag `"" RebootFlag ""` + + !macro _Silent _a _b _t _f + IfSilent `${_t}` `${_f}` + !macroend + !define Silent `"" Silent ""` + + ; "Any instruction" test + !macro _Cmd _a _b _t _f + !define _t=${_t} + !ifdef _t= ; If no true label then make one + !define __t _LogicLib_Label_${LOGICLIB_COUNTER} + !insertmacro _IncreaseCounter + !else + !define __t ${_t} + !endif + ${_b} ${__t} + !define _f=${_f} + !ifndef _f= ; If a false label then go there + Goto ${_f} + !endif + !undef _f=${_f} + !ifdef _t= ; If we made our own true label then place it + ${__t}: + !endif + !undef __t + !undef _t=${_t} + !macroend + !define Cmd `"" Cmd` + + ; Section flag test + !macro _SectionFlagIsSet _a _b _t _f + !insertmacro _LOGICLIB_TEMP + SectionGetFlags `${_b}` $_LOGICLIB_TEMP + IntOp $_LOGICLIB_TEMP $_LOGICLIB_TEMP & `${_a}` + !insertmacro _= $_LOGICLIB_TEMP `${_a}` `${_t}` `${_f}` + !macroend + !define SectionIsSelected `${SF_SELECTED} SectionFlagIsSet` + !define SectionIsSubSection `${SF_SUBSEC} SectionFlagIsSet` + !define SectionIsSubSectionEnd `${SF_SUBSECEND} SectionFlagIsSet` + !define SectionIsSectionGroup `${SF_SECGRP} SectionFlagIsSet` + !define SectionIsSectionGroupEnd `${SF_SECGRPEND} SectionFlagIsSet` + !define SectionIsBold `${SF_BOLD} SectionFlagIsSet` + !define SectionIsReadOnly `${SF_RO} SectionFlagIsSet` + !define SectionIsExpanded `${SF_EXPAND} SectionFlagIsSet` + !define SectionIsPartiallySelected `${SF_PSELECTED} SectionFlagIsSet` + + !define IfCmd `!insertmacro _IfThen "" Cmd ${|}` + + !macro _If _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !insertmacro _PushLogic + !define ${_Logic}If + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the Else + !insertmacro _IncreaseCounter + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + !verbose pop + !macroend + !define If `!insertmacro _If true` + !define Unless `!insertmacro _If false` + !define IfNot `!insertmacro _If false` + + !macro _And _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use And without a preceding If or IfNot/Unless" + !endif + !ifndef ${_Logic}Else + !error "Cannot use And following an Else" + !endif + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + !verbose pop + !macroend + !define AndIf `!insertmacro _And true` + !define AndUnless `!insertmacro _And false` + !define AndIfNot `!insertmacro _And false` + + !macro _Or _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use Or without a preceding If or IfNot/Unless" + !endif + !ifndef ${_Logic}Else + !error "Cannot use Or following an Else" + !endif + !define _label _LogicLib_Label_${LOGICLIB_COUNTER} ; Skip this test as we already + !insertmacro _IncreaseCounter + Goto ${_label} ; have a successful result + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new If + !insertmacro _IncreaseCounter + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + ${_label}: + !undef _label + !verbose pop + !macroend + !define OrIf `!insertmacro _Or true` + !define OrUnless `!insertmacro _Or false` + !define OrIfNot `!insertmacro _Or false` + + !macro _Else + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use Else without a preceding If or IfNot/Unless" + !endif + !ifndef ${_Logic}Else + !error "Cannot use Else following an Else" + !endif + !ifndef ${_Logic}EndIf ; First Else for this If? + !define ${_Logic}EndIf _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the EndIf + !insertmacro _IncreaseCounter + !endif + Goto ${${_Logic}EndIf} ; Go to the EndIf + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !verbose pop + !macroend + !define Else `!insertmacro _Else` + + !macro _ElseIf _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${Else} ; Perform the Else + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new If + !insertmacro _IncreaseCounter + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + !verbose pop + !macroend + !define ElseIf `!insertmacro _ElseIf true` + !define ElseUnless `!insertmacro _ElseIf false` + !define ElseIfNot `!insertmacro _ElseIf false` + + !macro _EndIf _n + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use End${_n} without a preceding If or IfNot/Unless" + !endif + !ifdef ${_Logic}Else + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !endif + !ifdef ${_Logic}EndIf + ${${_Logic}EndIf}: ; Place the EndIf + !undef ${_Logic}EndIf ; and remove it + !endif + !undef ${_Logic}If + !insertmacro _PopLogic + !verbose pop + !macroend + !define EndIf `!insertmacro _EndIf If` + !define EndUnless `!insertmacro _EndIf Unless` + + !macro _IfThen _a _o _b _t + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${If} `${_a}` `${_o}` `${_b}` + ${_t} + ${EndIf} + !verbose pop + !macroend + !define IfThen `!insertmacro _IfThen` + + !macro _IfNotThen _a _o _b _t + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${IfNot} `${_a}` `${_o}` `${_b}` + ${_t} + ${EndIf} + !verbose pop + !macroend + !define IfNotThen `!insertmacro _IfNotThen` + + !macro _ForEach _v _f _t _o _s + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + StrCpy "${_v}" "${_f}" ; Assign the initial value + Goto +2 ; Skip the loop expression for the first iteration + !define _DoLoopExpression `IntOp "${_v}" "${_v}" "${_o}" "${_s}"` ; Define the loop expression + !define _o=${_o} + !ifdef _o=+ ; Check the loop expression operator + !define __o > ; to determine the correct loop condition + !else ifdef _o=- + !define __o < + !else + !error "Unsupported ForEach step operator (must be + or -)" + !endif + !undef _o=${_o} + !insertmacro _Do For false `${_v}` `${__o}` `${_t}` ; Let Do do the rest + !undef __o + !verbose pop + !macroend + !define ForEach `!insertmacro _ForEach` + + !macro _For _v _f _t + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${ForEach} `${_v}` `${_f}` `${_t}` + 1 ; Pass on to ForEach + !verbose pop + !macroend + !define For `!insertmacro _For` + + !define ExitFor `!insertmacro _Goto ExitFor For` + + !define Next `!insertmacro _Loop For Next "" "" "" ""` + + !define While `!insertmacro _Do While true` + + !define ExitWhile `!insertmacro _Goto ExitWhile While` + + !define EndWhile `!insertmacro _Loop While EndWhile "" "" "" ""` + + !macro _Do _n _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !insertmacro _PushLogic + !define ${_Logic}${_n} _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the start of the loop + !insertmacro _IncreaseCounter + ${${_Logic}${_n}}: + !insertmacro _PushScope Exit${_n} _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the end of the loop + !insertmacro _IncreaseCounter + !insertmacro _PushScope Break ${_Exit${_n}} ; Break goes to the end of the loop + !ifdef _DoLoopExpression + ${_DoLoopExpression} ; Special extra parameter for inserting code + !undef _DoLoopExpression ; between the Continue label and the loop condition + !endif + !define _c=${_c} + !ifdef _c= ; No starting condition + !insertmacro _PushScope Continue _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for Continue at the end of the loop + !insertmacro _IncreaseCounter + !else + !insertmacro _PushScope Continue ${${_Logic}${_n}} ; Continue goes to the start of the loop + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${_Exit${_n}} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} "" + !endif + !endif + !undef _c=${_c} + !define ${_Logic}Condition ${_c} ; Remember the condition used + !verbose pop + !macroend + !define Do `!insertmacro _Do Do "" "" "" ""` + !define DoWhile `!insertmacro _Do Do true` + !define DoUntil `!insertmacro _Do Do false` + + !macro _Goto _n _s + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _${_n} + !error "Cannot use ${_n} without a preceding ${_s}" + !endif + Goto ${_${_n}} + !verbose pop + !macroend + !define ExitDo `!insertmacro _Goto ExitDo Do` + + !macro _Loop _n _e _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}${_n} + !error "Cannot use ${_e} without a preceding ${_n}" + !endif + !define _c=${${_Logic}Condition} + !ifdef _c= ; If Do had no condition place the Continue label + ${_Continue}: + !endif + !undef _c=${${_Logic}Condition} + !define _c=${_c} + !ifdef _c= ; No ending condition + Goto ${${_Logic}${_n}} + !else ifdef _c=true ; If condition is true + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}${_n}} ${_Exit${_n}} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ${${_Logic}${_n}} + !endif + !undef _c=${_c} + Goto ${_Continue} ; Just to ensure it is referenced at least once + Goto ${_Exit${_n}} ; Just to ensure it is referenced at least once + ${_Exit${_n}}: ; Place the loop exit point + !undef ${_Logic}Condition + !insertmacro _PopScope Continue + !insertmacro _PopScope Break + !insertmacro _PopScope Exit${_n} + !undef ${_Logic}${_n} + !insertmacro _PopLogic + !verbose pop + !macroend + !define Loop `!insertmacro _Loop Do Loop "" "" "" ""` + !define LoopWhile `!insertmacro _Loop Do LoopWhile true` + !define LoopUntil `!insertmacro _Loop Do LoopUntil false` + + !define Continue `!insertmacro _Goto Continue "For or Do or While"` + !define Break `!insertmacro _Goto Break "For or Do or While"` + + !macro _Select _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !insertmacro _PushLogic + !define ${_Logic}Select `${_a}` ; Remember the left hand side of the comparison + !verbose pop + !macroend + !define Select `!insertmacro _Select` + + !macro _Select_CaseElse + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}Select + !error "Cannot use Case without a preceding Select" + !endif + !ifdef ${_Logic}EndSelect ; This is set only after the first case + !ifndef ${_Logic}Else + !error "Cannot use Case following a CaseElse" + !endif + Goto ${${_Logic}EndSelect} ; Go to the EndSelect + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !else + !define ${_Logic}EndSelect _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the EndSelect + !insertmacro _IncreaseCounter + !endif + !verbose pop + !macroend + !define CaseElse `!insertmacro _CaseElse` + !define Case_Else `!insertmacro _CaseElse` ; Compatibility with 2.2 and earlier + !define Default `!insertmacro _CaseElse` ; For the C-minded + + !macro _Select_Case _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case + !insertmacro _IncreaseCounter + !insertmacro _== `${${_Logic}Select}` `${_a}` "" ${${_Logic}Else} + !verbose pop + !macroend + !define Case `!insertmacro _Case` + + !macro _Case2 _a _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case + !insertmacro _IncreaseCounter + !insertmacro _== `${${_Logic}Select}` `${_a}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` "" ${${_Logic}Else} + !verbose pop + !macroend + !define Case2 `!insertmacro _Case2` + + !macro _Case3 _a _b _c + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case + !insertmacro _IncreaseCounter + !insertmacro _== `${${_Logic}Select}` `${_a}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` "" ${${_Logic}Else} + !verbose pop + !macroend + !define Case3 `!insertmacro _Case3` + + !macro _Case4 _a _b _c _d + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case + !insertmacro _IncreaseCounter + !insertmacro _== `${${_Logic}Select}` `${_a}` +4 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_d}` "" ${${_Logic}Else} + !verbose pop + !macroend + !define Case4 `!insertmacro _Case4` + + !macro _Case5 _a _b _c _d _e + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case + !insertmacro _IncreaseCounter + !insertmacro _== `${${_Logic}Select}` `${_a}` +5 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +4 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_d}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_e}` "" ${${_Logic}Else} + !verbose pop + !macroend + !define Case5 `!insertmacro _Case5` + + !macro _EndSelect + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}Select + !error "Cannot use EndSelect without a preceding Select" + !endif + !ifdef ${_Logic}Else + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !endif + !ifdef ${_Logic}EndSelect ; This won't be set if there weren't any cases + ${${_Logic}EndSelect}: ; Place the EndSelect + !undef ${_Logic}EndSelect ; and remove it + !endif + !undef ${_Logic}Select + !insertmacro _PopLogic + !verbose pop + !macroend + !define EndSelect `!insertmacro _EndSelect` + + !macro _Switch _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !insertmacro _PushLogic + !insertmacro _PushScope Switch ${_Logic} ; Keep a separate stack for switch data + !insertmacro _PushScope Break _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a lable for beyond the end of the switch + !insertmacro _IncreaseCounter + !define ${_Switch}Var `${_a}` ; Remember the left hand side of the comparison + !tempfile ${_Switch}Tmp ; Create a temporary file + !define ${_Logic}Switch _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the end of the switch + !insertmacro _IncreaseCounter + Goto ${${_Logic}Switch} ; and go there + !verbose pop + !macroend + !define Switch `!insertmacro _Switch` + + !macro _Case _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifdef _Logic & ${_Logic}Select ; Check for an active Select + !insertmacro _Select_Case `${_a}` + !else ifndef _Switch ; If not then check for an active Switch + !error "Cannot use Case without a preceding Select or Switch" + !else + !define _label _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for this case, + !insertmacro _IncreaseCounter + ${_label}: ; place it and add it's check to the temp file + !appendfile "${${_Switch}Tmp}" `!insertmacro _== $\`${${_Switch}Var}$\` $\`${_a}$\` ${_label} ""$\n` + !undef _label + !endif + !verbose pop + !macroend + + !macro _CaseElse + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifdef _Logic & ${_Logic}Select ; Check for an active Select + !insertmacro _Select_CaseElse + !else ifndef _Switch ; If not then check for an active Switch + !error "Cannot use Case without a preceding Select or Switch" + !else ifdef ${_Switch}Else ; Already had a default case? + !error "Cannot use CaseElse following a CaseElse" + !else + !define ${_Switch}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the default case, + !insertmacro _IncreaseCounter + ${${_Switch}Else}: ; and place it + !endif + !verbose pop + !macroend + + !macro _EndSwitch + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}Switch + !error "Cannot use EndSwitch without a preceding Switch" + !endif + Goto ${_Break} ; Skip the jump table + ${${_Logic}Switch}: ; Place the end of the switch + !undef ${_Logic}Switch + !include "${${_Switch}Tmp}" ; Include the jump table + !delfile "${${_Switch}Tmp}" ; and clear it up + !ifdef ${_Switch}Else ; Was there a default case? + Goto ${${_Switch}Else} ; then go there if all else fails + !undef ${_Switch}Else + !endif + !undef ${_Switch}Tmp + !undef ${_Switch}Var + ${_Break}: ; Place the break label + !insertmacro _PopScope Break + !insertmacro _PopScope Switch + !insertmacro _PopLogic + !verbose pop + !macroend + !define EndSwitch `!insertmacro _EndSwitch` + +!endif ; LOGICLIB +!verbose 3 +!define LOGICLIB_VERBOSITY ${_LOGICLIB_VERBOSITY} +!undef _LOGICLIB_VERBOSITY +!verbose pop diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 1841431..2cbd6d3 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -1,7 +1,10 @@ +InstallDir "" +!include "LogicLib.nsh" !include "mingw-file-association.nsh" +!include "x64.nsh" Name "OpenSCAD" OutFile "openscad_setup.exe" -InstallDir $PROGRAMFILES\OpenSCAD +!include "installer_arch.nsi" DirText "This will install OpenSCAD on your computer. Choose a directory" Section "install" SetOutPath $INSTDIR diff --git a/scripts/installer32.nsi b/scripts/installer32.nsi new file mode 100644 index 0000000..051cb0e --- /dev/null +++ b/scripts/installer32.nsi @@ -0,0 +1,3 @@ +Function .onInit + StrCpy $InstDir $PROGRAMFILES\OpenSCAD +FunctionEnd diff --git a/scripts/installer64.nsi b/scripts/installer64.nsi new file mode 100644 index 0000000..1b24c0c --- /dev/null +++ b/scripts/installer64.nsi @@ -0,0 +1,8 @@ +Function .onInit +${If} ${RunningX64} + StrCpy $InstDir $PROGRAMFILES64\OpenSCAD + SetRegView 64 +${Else} + Messagebox MB_OK "This is 64 bit OpenSCAD, your machine is 32 bits. Error." +${EndIf} +FunctionEnd diff --git a/scripts/mingw-x-build-dependencies.sh b/scripts/mingw-x-build-dependencies.sh index 7a16530..03adc22 100755 --- a/scripts/mingw-x-build-dependencies.sh +++ b/scripts/mingw-x-build-dependencies.sh @@ -1,11 +1,13 @@ #!/bin/sh -e # # This script builds all library dependencies of OpenSCAD for cross-compilation -# from linux to mingw32 for windows, using the MXE cross build system. +# from linux to mingw32/64 for windows, using the MXE cross build system. # # This script must be run from the OpenSCAD source root directory # -# Usage: ./scripts/mingw-x-build-dependencies.sh +# Usage: +# ./scripts/mingw-x-build-dependencies.sh # 32 bit +# ./scripts/mingw-x-build-dependencies.sh 64 # 64 bit # # Prerequisites: # @@ -13,6 +15,8 @@ # # Also see http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Cross-compiling_for_Windows_on_Linux_or_Mac_OS_X # +# Also note the 64 bit is built on the branch of mxe by Tony Theodore +# which hasnt been merged to official mxe as of writing OPENSCADDIR=$PWD if [ ! -f $OPENSCADDIR/openscad.pro ]; then @@ -34,7 +38,7 @@ if [ ! $NUMJOBS ]; then fi fi -. ./scripts/setenv-mingw-xbuild.sh +. ./scripts/setenv-mingw-xbuild.sh $* if [ ! -e $BASEDIR ]; then mkdir -p $BASEDIR @@ -44,7 +48,11 @@ if [ ! -e $MXEDIR ]; then mkdir -p $MXEDIR cd $MXEDIR/.. echo "Downloading MXE into " $PWD - git clone git://github.com/mxe/mxe.git + if [ `echo $* | grep 64` ]; then + git clone -b multi-rebase git://github.com/tonytheodore/mxe.git ./mxe-w64 + else + git clone git://github.com/mxe/mxe.git + fi fi echo "entering" $MXEDIR diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 02b276b..035fa3f 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -7,11 +7,12 @@ # The script will create a file called openscad-. in # the current directory (or under ./mingw32) # -# Usage: release-common.sh [-v ] [-c] [-x32] +# Usage: release-common.sh [-v ] [-c] [-mingw[32|64]] # -v Version string (e.g. -v 2010.01) # -d Version date (e.g. -d 2010.01.23) # -c Build with commit info # -mingw32 Cross-compile for win32 using MXE +# -mingw64 Cross-compile for win64 using MXE # # If no version string or version date is given, todays date will be used (YYYY-MM-DD) # If only verion date is given, it will be used also as version string. @@ -20,7 +21,7 @@ # The commit info will extracted from git and be passed to qmake as OPENSCAD_COMMIT # to identify a build in the about box. # -# The mingw32 cross compile depends on the MXE cross-build tools. Please +# The mingw cross compile depends on the MXE cross-build tools. Please # see the README.md file on how to install these dependencies. printUsage() @@ -52,6 +53,12 @@ fi if [ "`echo $* | grep mingw32`" ]; then OS=LINXWIN + ARCH=32 +fi + +if [ "`echo $* | grep mingw64`" ]; then + OS=LINXWIN + ARCH=64 fi if [ $OS ]; then @@ -83,7 +90,6 @@ echo "Checking pre-requisites..." case $OS in LINXWIN) MAKENSIS= - if [ "`command -v makensis`" ]; then MAKENSIS=makensis elif [ "`command -v i686-pc-mingw32-makensis`" ]; then @@ -124,7 +130,7 @@ case $OS in TARGET=release ;; LINXWIN) - . ./scripts/setenv-mingw-xbuild.sh + . ./scripts/setenv-mingw-xbuild.sh $ARCH TARGET=release ZIP="zip" ZIPARGS="-r" @@ -170,13 +176,12 @@ fi case $OS in LINXWIN) - # dont use paralell builds, it can error-out on parser_yacc. - + # make || make enables paralell builds, thanks Tony Theodore # make main openscad.exe cd $DEPLOYDIR - make $TARGET ## comment out for test-run + make $TARGET -j$NUMCPU || make $TARGET -j $NUMCPU ## comment 4 test if [ ! -e $TARGET/openscad.exe ]; then - echo 'build failed. stopping.' + echo "cant find $TARGET/openscad.exe. build failed. stopping." exit fi # make console pipe-able openscad.com - see winconsole.pri for info @@ -271,8 +276,11 @@ case $OS in echo "Creating installer" echo "Copying NSIS files to $DEPLOYDIR/openscad-$VERSION" - cp ./scripts/installer.nsi $DEPLOYDIR/openscad-$VERSION - cp ./scripts/mingw-file-association.nsh $DEPLOYDIR/openscad-$VERSION + cp ./scripts/installer$ARCH.nsi $DEPLOYDIR/openscad-$VERSION/installer_arch.nsi + cp ./scripts/installer.nsi $DEPLOYDIR/openscad-$VERSION/ + cp ./scripts/mingw-file-association.nsh $DEPLOYDIR/openscad-$VERSION/ + cp ./scripts/x64.nsh $DEPLOYDIR/openscad-$VERSION/ + cp ./scripts/LogicLib.nsh $DEPLOYDIR/openscad-$VERSION/ cd $DEPLOYDIR/openscad-$VERSION NSISDEBUG=-V2 # NSISDEBUG= # leave blank for full log @@ -288,12 +296,11 @@ case $OS in echo "Installer created:" $INSTFILE echo else - echo "Build failed. Cannot find" $INSTFILE - exit 1 + echo "Build failed. Cannot find" $INSTFILE fi else - echo "Build failed. Cannot find" $BINFILE - exit 1 + echo "Build failed. Cannot find" $BINFILE + exit 1 fi ;; LINUX) diff --git a/scripts/setenv-mingw-xbuild.sh b/scripts/setenv-mingw-xbuild.sh index e31534e..b6fa156 100644 --- a/scripts/setenv-mingw-xbuild.sh +++ b/scripts/setenv-mingw-xbuild.sh @@ -2,7 +2,10 @@ # # set environment variables for mingw/mxe cross-build # -# Usage: source ./scripts/setenv-mingw-xbuild.sh +# Usage: +# +# source ./scripts/setenv-mingw-xbuild.sh # 32 bit build +# source ./scripts/setenv-mingw-xbuild.sh 64 # 64 bit build # # Prerequisites: # @@ -18,11 +21,20 @@ if [ ! $BASEDIR ]; then fi if [ ! $DEPLOYDIR ]; then - export DEPLOYDIR=$OPENSCADDIR/mingw32 + if [ `echo $* | grep 64 ` ]; then + DEPLOYDIR=$OPENSCADDIR/mingw64 + else + DEPLOYDIR=$OPENSCADDIR/mingw32 + fi + export DEPLOYDIR fi if [ ! $MXEDIR ]; then - export MXEDIR=$BASEDIR/mxe + if [ `echo $* | grep 64 ` ]; then + export MXEDIR=$BASEDIR/mxe-w64 + else + export MXEDIR=$BASEDIR/mxe + fi fi export PATH=$MXEDIR/usr/bin:$PATH @@ -31,16 +43,21 @@ if [ ! -e $DEPLOYDIR ]; then mkdir -p $DEPLOYDIR fi -echo linking $MXEDIR/usr/i686-pc-mingw32/ to $DEPLOYDIR/mingw-cross-env +if [ `echo $* | grep 64 ` ]; then + MXETARGETDIR=$MXEDIR/usr/x86_64-w64-mingw32 +else + MXETARGETDIR=$MXEDIR/usr/i686-pc-mingw32 +fi +echo linking $MXETARGETDIR to $DEPLOYDIR/mingw-cross-env rm -f $DEPLOYDIR/mingw-cross-env -ln -s $MXEDIR/usr/i686-pc-mingw32/ $DEPLOYDIR/mingw-cross-env -export PATH=$MXEDIR/usr/i686-pc-mingw32/qt/bin:$PATH +ln -s $MXETARGETDIR $DEPLOYDIR/mingw-cross-env +export PATH=$MXETARGETDIR/qt/bin:$PATH echo BASEDIR: $BASEDIR echo MXEDIR: $MXEDIR echo DEPLOYDIR: $DEPLOYDIR echo PATH modified: $MXEDIR/usr/bin -echo PATH modified: $MXEDIR/usr/i686-pc-mingw32/qt/bin +echo PATH modified: $MXETARGETDIR/qt/bin diff --git a/scripts/x64.nsh b/scripts/x64.nsh new file mode 100644 index 0000000..e694c1e --- /dev/null +++ b/scripts/x64.nsh @@ -0,0 +1,54 @@ +; --------------------- +; x64.nsh +; --------------------- +; +; A few simple macros to handle installations on x64 machines. +; +; RunningX64 checks if the installer is running on x64. +; +; ${If} ${RunningX64} +; MessageBox MB_OK "running on x64" +; ${EndIf} +; +; DisableX64FSRedirection disables file system redirection. +; EnableX64FSRedirection enables file system redirection. +; +; SetOutPath $SYSDIR +; ${DisableX64FSRedirection} +; File some.dll # extracts to C:\Windows\System32 +; ${EnableX64FSRedirection} +; File some.dll # extracts to C:\Windows\SysWOW64 +; + +!ifndef ___X64__NSH___ +!define ___X64__NSH___ + +!include LogicLib.nsh + +!macro _RunningX64 _a _b _t _f + !insertmacro _LOGICLIB_TEMP + System::Call kernel32::GetCurrentProcess()i.s + System::Call kernel32::IsWow64Process(is,*i.s) + Pop $_LOGICLIB_TEMP + !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}` +!macroend + +!define RunningX64 `"" RunningX64 ""` + +!macro DisableX64FSRedirection + + System::Call kernel32::Wow64EnableWow64FsRedirection(i0) + +!macroend + +!define DisableX64FSRedirection "!insertmacro DisableX64FSRedirection" + +!macro EnableX64FSRedirection + + System::Call kernel32::Wow64EnableWow64FsRedirection(i1) + +!macroend + +!define EnableX64FSRedirection "!insertmacro EnableX64FSRedirection" + +!endif # !___X64__NSH___ diff --git a/src/mainwin.cc b/src/mainwin.cc index 5f9d633..da3501d 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1765,6 +1765,12 @@ void MainWindow::helpLibrary() OPENCSG_VERSION_STRING, qVersion()); +#if defined( __MINGW64__ ) + libinfo += QString("Compiled for MingW64\n\n"); +#elif defined( __MINGW32__ ) + libinfo += QString("Compiled for MingW32\n\n"); +#endif + if (!this->openglbox) { this->openglbox = new QMessageBox(QMessageBox::Information, "OpenGL Info", "OpenSCAD Detailed Library Info ", -- cgit v0.10.1 From be87d30f427a4ffff8a21c3871e0304670443710 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Thu, 16 May 2013 22:59:58 -0500 Subject: enable both win32 and win64 build and upload (beta level) from same script diff --git a/scripts/builder.sh b/scripts/builder.sh index 75b80f8..e8876e8 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -6,10 +6,6 @@ # requirements - # see http://mxe.cc for required tools (scons, perl, yasm, etc etc etc) -# todo - auto update webpage to link to proper snapshot -# -# todo - 64 bit windows (needs mxe 64 bit stable) -# # todo - can we build 32 bit linux from within 64 bit linux? # # todo - make linux work @@ -36,14 +32,23 @@ get_source_code() build_win32() { + . ./scripts/setenv-mingw-xbuild.sh clean . ./scripts/setenv-mingw-xbuild.sh ./scripts/mingw-x-build-dependencies.sh ./scripts/release-common.sh mingw32 } +build_win64() +{ + . ./scripts/setenv-mingw-xbuild.sh clean + . ./scripts/setenv-mingw-xbuild.sh 64 + ./scripts/mingw-x-build-dependencies.sh 64 + ./scripts/release-common.sh mingw64 +} + build_lin32() { - . ./scripts/setenv-unibuild.sh clang + . ./scripts/setenv-unibuild.sh ./scripts/uni-build-dependencies.sh ./scripts/release-common.sh } @@ -87,6 +92,26 @@ upload_win32() export WIN32_PACKAGEFILE2_SIZE } +upload_win64() +{ + SUMMARY1="Windows x86-64 Snapshot Zipfile" + SUMMARY2="Windows x86-64 Snapshot Installer" + DATECODE=`date +"%Y.%m.%d"` + BASEDIR=./mingw64/ + WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64.zip + WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64-Installer.exe + upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN64_PACKAGEFILE1 + upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN64_PACKAGEFILE2 + export WIN64_PACKAGEFILE1 + export WIN64_PACKAGEFILE2 + WIN64_PACKAGEFILE1_SIZE=`ls -sh $BASEDIR/$WIN64_PACKAGEFILE1 | awk ' {print $1} ';` + WIN64_PACKAGEFILE2_SIZE=`ls -sh $BASEDIR/$WIN64_PACKAGEFILE2 | awk ' {print $1} ';` + WIN64_PACKAGEFILE1_SIZE=`echo "$WIN64_PACKAGEFILE1_SIZE""B"` + WIN64_PACKAGEFILE2_SIZE=`echo "$WIN64_PACKAGEFILE2_SIZE""B"` + export WIN64_PACKAGEFILE1_SIZE + export WIN64_PACKAGEFILE2_SIZE +} + read_username_from_user() { echo 'Please enter your username for https://code.google.com/hosting/settings' @@ -112,7 +137,7 @@ read_password_from_user() export OSUPL_PASSWORD } -update_www_download_links() +update_win_www_download_links() { cd $STARTPATH git clone git@github.com:openscad/openscad.github.com.git @@ -123,6 +148,13 @@ update_www_download_links() DATECODE=`date +"%Y.%m.%d"` rm win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT1_URL'] = '$BASEURL$WIN64_PACKAGEFILE1'" >> win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT2_URL'] = '$BASEURL$WIN64_PACKAGEFILE2'" >> win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT1_NAME'] = 'OpenSCAD $DATECODE'" >> win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT2_NAME'] = 'OpenSCAD $DATECODE'" >> win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT1_SIZE'] = '$WIN64_PACKAGEFILE1_SIZE'" >> win_snapshot_links.js + echo "snapinfo['WIN64_SNAPSHOT2_SIZE'] = '$WIN64_PACKAGEFILE2_SIZE'" >> win_snapshot_links.js + echo "snapinfo['WIN32_SNAPSHOT1_URL'] = '$BASEURL$WIN32_PACKAGEFILE1'" >> win_snapshot_links.js echo "snapinfo['WIN32_SNAPSHOT2_URL'] = '$BASEURL$WIN32_PACKAGEFILE2'" >> win_snapshot_links.js echo "snapinfo['WIN32_SNAPSHOT1_NAME'] = 'OpenSCAD $DATECODE'" >> win_snapshot_links.js @@ -130,7 +162,6 @@ update_www_download_links() echo "snapinfo['WIN32_SNAPSHOT1_SIZE'] = '$WIN32_PACKAGEFILE1_SIZE'" >> win_snapshot_links.js echo "snapinfo['WIN32_SNAPSHOT2_SIZE'] = '$WIN32_PACKAGEFILE2_SIZE'" >> win_snapshot_links.js echo 'modified win_snapshot_links.js' - cat win_snapshot_links.js PAGER=cat git diff if [ ! $DRYRUN ]; then @@ -157,9 +188,12 @@ check_starting_path read_username_from_user read_password_from_user get_source_code + build_win32 +build_win64 upload_win32 -update_www_download_links +upload_win64 +update_win_www_download_links diff --git a/scripts/mingw-x-build-dependencies.sh b/scripts/mingw-x-build-dependencies.sh index 03adc22..168b847 100755 --- a/scripts/mingw-x-build-dependencies.sh +++ b/scripts/mingw-x-build-dependencies.sh @@ -48,7 +48,7 @@ if [ ! -e $MXEDIR ]; then mkdir -p $MXEDIR cd $MXEDIR/.. echo "Downloading MXE into " $PWD - if [ `echo $* | grep 64` ]; then + if [ "`echo $* | grep 64`" ]; then git clone -b multi-rebase git://github.com/tonytheodore/mxe.git ./mxe-w64 else git clone git://github.com/mxe/mxe.git @@ -57,9 +57,15 @@ fi echo "entering" $MXEDIR cd $MXEDIR -echo "make mpfr eigen opencsg cgal qt nsis -j $NUMCPU JOBS=$NUMJOBS" -make mpfr eigen opencsg cgal qt nsis -j $NUMCPU JOBS=$NUMJOBS -#make mpfr -j $NUMCPU JOBS=$NUMJOBS # for testing +if [ "`echo $* | grep 64`" ]; then + MXE_TARGETS='x86_64-w64-mingw32' + PACKAGES='mpfr eigen opencsg cgal qt' +else + MXE_TARGETS= + PACKAGES='mpfr eigen opencsg cgal qt nsis' +fi +echo make $PACKAGES MXE_TARGETS=$MXE_TARGETS -j $NUMCPU JOBS=$NUMJOBS +make $PACKAGES MXE_TARGETS=$MXE_TARGETS -j $NUMCPU JOBS=$NUMJOBS echo "leaving" $MXEDIR diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 035fa3f..85b719c 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -116,6 +116,13 @@ fi echo "Building openscad-$VERSION ($VERSIONDATE) $CONFIGURATION..." +if [ ! $NUMCPU ]; then + echo "note: you can 'export NUMCPU=x' for multi-core compiles (x=number)"; + NUMCPU=2 +else + echo "NUMCPU: " $NUMCPU +fi + CONFIG=deploy case $OS in LINUX|MACOSX) @@ -169,17 +176,12 @@ case $OS in ;; esac -if [ ! $NUMCPU ]; then - echo "note: you can 'export NUMCPU=x' for multi-core compiles (x=number)"; - NUMCPU=2 -fi - case $OS in LINXWIN) # make || make enables paralell builds, thanks Tony Theodore # make main openscad.exe cd $DEPLOYDIR - make $TARGET -j$NUMCPU || make $TARGET -j $NUMCPU ## comment 4 test + make $TARGET -j$NUMCPU || make $TARGET -j$NUMCPU ## comment 4 test if [ ! -e $TARGET/openscad.exe ]; then echo "cant find $TARGET/openscad.exe. build failed. stopping." exit diff --git a/scripts/setenv-mingw-xbuild.sh b/scripts/setenv-mingw-xbuild.sh index b6fa156..15449ce 100644 --- a/scripts/setenv-mingw-xbuild.sh +++ b/scripts/setenv-mingw-xbuild.sh @@ -14,50 +14,82 @@ # Also see http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Cross-compiling_for_Windows_on_Linux_or_Mac_OS_X # -export OPENSCADDIR=$PWD +OPENSCADDIR=$PWD if [ ! $BASEDIR ]; then - export BASEDIR=$HOME/openscad_deps + BASEDIR=$HOME/openscad_deps fi +DEPLOYDIR64=$OPENSCADDIR/mingw64 +DEPLOYDIR32=$OPENSCADDIR/mingw32 + if [ ! $DEPLOYDIR ]; then - if [ `echo $* | grep 64 ` ]; then - DEPLOYDIR=$OPENSCADDIR/mingw64 + if [ "`echo $* | grep 64 `" ]; then + DEPLOYDIR=$DEPLOYDIR64 else - DEPLOYDIR=$OPENSCADDIR/mingw32 + DEPLOYDIR=$DEPLOYDIR32 fi - export DEPLOYDIR fi if [ ! $MXEDIR ]; then - if [ `echo $* | grep 64 ` ]; then - export MXEDIR=$BASEDIR/mxe-w64 + if [ "`echo $* | grep 64 `" ]; then + MXEDIR=$BASEDIR/mxe-w64 else - export MXEDIR=$BASEDIR/mxe + MXEDIR=$BASEDIR/mxe fi fi -export PATH=$MXEDIR/usr/bin:$PATH - if [ ! -e $DEPLOYDIR ]; then mkdir -p $DEPLOYDIR fi -if [ `echo $* | grep 64 ` ]; then +if [ "`echo $* | grep 64 `" ]; then MXETARGETDIR=$MXEDIR/usr/x86_64-w64-mingw32 else MXETARGETDIR=$MXEDIR/usr/i686-pc-mingw32 fi -echo linking $MXETARGETDIR to $DEPLOYDIR/mingw-cross-env -rm -f $DEPLOYDIR/mingw-cross-env -ln -s $MXETARGETDIR $DEPLOYDIR/mingw-cross-env -export PATH=$MXETARGETDIR/qt/bin:$PATH + +if [ ! $MINGWX_SAVED_ORIGINAL_PATH ]; then + MINGWX_SAVED_ORIGINAL_PATH=$PATH + echo current path saved +fi + +PATH=$MXEDIR/usr/bin:$PATH +PATH=$MXETARGETDIR/qt/bin:$PATH + + + + + +if [ "`echo $* | grep clean`" ]; then + BASEDIR= + MXEDIR= + MXETARGETDIR= + DEPLOYDIR= + PATH=$MINGWX_SAVED_ORIGINAL_PATH + MINGWX_SAVED_ORIGINAL_PATH= +else + echo 'linking' $MXETARGETDIR + echo ' to' $DEPLOYDIR/mingw-cross-env + rm -f $DEPLOYDIR/mingw-cross-env + ln -s $MXETARGETDIR $DEPLOYDIR/mingw-cross-env +fi + +export BASEDIR +export MXEDIR +export MXETARGETDIR +export DEPLOYDIR +export PATH +export MINGWX_SAVED_ORIGINAL_PATH echo BASEDIR: $BASEDIR echo MXEDIR: $MXEDIR +echo MXETARGETDIR: $MXETARGETDIR echo DEPLOYDIR: $DEPLOYDIR -echo PATH modified: $MXEDIR/usr/bin -echo PATH modified: $MXETARGETDIR/qt/bin - - +if [ "`echo $* | grep clean`" ]; then + echo PATH restored to pre-setenv-mingw-x state +else + echo PATH modified: $MXEDIR/usr/bin + echo PATH modified: $MXETARGETDIR/qt/bin +fi -- cgit v0.10.1 From b3b83059e7c62339712e71294662cd3fa883f0db Mon Sep 17 00:00:00 2001 From: Don Bright Date: Fri, 17 May 2013 15:32:23 -0500 Subject: tweaks to improve build. alos update about.html docs diff --git a/scripts/builder.sh b/scripts/builder.sh index e8876e8..7cd551e 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -12,11 +12,16 @@ # # todo - detect failure and stop -DRYRUN= +DRYRUN=1 -check_starting_path() +init_variables() { STARTPATH=$PWD + export STARTPATH +} + +check_starting_path() +{ if [ -e openscad.pro ]; then echo 'please start from a clean directory outside of openscad' exit @@ -36,6 +41,8 @@ build_win32() . ./scripts/setenv-mingw-xbuild.sh ./scripts/mingw-x-build-dependencies.sh ./scripts/release-common.sh mingw32 + DATECODE=`date +"%Y.%m.%d"` + export DATECODE } build_win64() @@ -44,6 +51,8 @@ build_win64() . ./scripts/setenv-mingw-xbuild.sh 64 ./scripts/mingw-x-build-dependencies.sh 64 ./scripts/release-common.sh mingw64 + DATECODE=`date +"%Y.%m.%d"` + export DATECODE } build_lin32() @@ -51,24 +60,29 @@ build_lin32() . ./scripts/setenv-unibuild.sh ./scripts/uni-build-dependencies.sh ./scripts/release-common.sh + DATECODE=`date +"%Y.%m.%d"` + export DATECODE } upload_win_generic() { - # 1=file summary, 2 = username, 3 = filename - if [ -e $3 ]; then - echo $3 found + summary="$1" + username=$2 + filename=$3 + if [ -f $filename ]; then + echo 'file "'$filename'" found' else - echo $3 not found + echo 'file "'$filename'" not found' fi opts= opts="$opts -p openscad" - opts="$opts -u $2" - opts="$opts $3" - if [ ! $DRYRUN ]; then - python ./scripts/googlecode_upload.py -s "$1" $opts - else + opts="$opts -u $username" + opts="$opts $filename" + if [ $DRYRUN ]; then echo dry run, not uploading to googlecode + echo cmd - python ./scripts/googlecode_upload.py -s '"'$summary'"' $opts + else + python ./scripts/googlecode_upload.py -s "$summary" $opts fi } @@ -76,7 +90,6 @@ upload_win32() { SUMMARY1="Windows x86-32 Snapshot Zipfile" SUMMARY2="Windows x86-32 Snapshot Installer" - DATECODE=`date +"%Y.%m.%d"` BASEDIR=./mingw32/ WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32.zip WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32-Installer.exe @@ -96,7 +109,6 @@ upload_win64() { SUMMARY1="Windows x86-64 Snapshot Zipfile" SUMMARY2="Windows x86-64 Snapshot Installer" - DATECODE=`date +"%Y.%m.%d"` BASEDIR=./mingw64/ WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64.zip WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64-Installer.exe @@ -114,6 +126,7 @@ upload_win64() read_username_from_user() { + if [ $DRYRUN ]; then USERNAME=none;export USERNAME; return; fi echo 'Please enter your username for https://code.google.com/hosting/settings' echo -n 'Username:' read USERNAME @@ -122,6 +135,7 @@ read_username_from_user() read_password_from_user() { + if [ $DRYRUN ]; then return; fi echo 'Please enter your password for https://code.google.com/hosting/settings' echo -n 'Password:' read -s PASSWORD1 @@ -145,7 +159,6 @@ update_win_www_download_links() cd inc echo `pwd` BASEURL='https://openscad.google.com/files/' - DATECODE=`date +"%Y.%m.%d"` rm win_snapshot_links.js echo "snapinfo['WIN64_SNAPSHOT1_URL'] = '$BASEURL$WIN64_PACKAGEFILE1'" >> win_snapshot_links.js @@ -174,6 +187,7 @@ update_win_www_download_links() check_ssh_agent() { + if [ $DRYRUN ]; then echo 'skipping ssh, dry run'; return; fi if [ ! $SSH_AUTH_SOCK ]; then echo 'please start an ssh-agent for github.com/openscad/openscad.github.com uploads' echo 'for example:' @@ -183,6 +197,7 @@ check_ssh_agent() fi } +init_variables check_ssh_agent check_starting_path read_username_from_user diff --git a/scripts/mingw-x-build-dependencies.sh b/scripts/mingw-x-build-dependencies.sh index 168b847..c3d5179 100755 --- a/scripts/mingw-x-build-dependencies.sh +++ b/scripts/mingw-x-build-dependencies.sh @@ -46,13 +46,13 @@ fi if [ ! -e $MXEDIR ]; then mkdir -p $MXEDIR - cd $MXEDIR/.. - echo "Downloading MXE into " $PWD - if [ "`echo $* | grep 64`" ]; then - git clone -b multi-rebase git://github.com/tonytheodore/mxe.git ./mxe-w64 - else - git clone git://github.com/mxe/mxe.git - fi +fi +cd $MXEDIR/.. +echo "Downloading MXE into " $PWD +if [ "`echo $* | grep 64`" ]; then + git clone -b multi-rebase git://github.com/tonytheodore/mxe.git ./mxe-w64 +else + git clone git://github.com/mxe/mxe.git fi echo "entering" $MXEDIR diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 85b719c..a9fb3b5 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -48,17 +48,19 @@ elif [[ $OSTYPE == "linux-gnu" ]]; then else ARCH=32 fi - echo "Detected ARCH: $ARCH" + echo "Detected build-machine ARCH: $ARCH" fi if [ "`echo $* | grep mingw32`" ]; then OS=LINXWIN ARCH=32 + echo Mingw-cross build using ARCH=32 fi if [ "`echo $* | grep mingw64`" ]; then OS=LINXWIN ARCH=64 + echo Mingw-cross build using ARCH=64 fi if [ $OS ]; then diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 6203e83..946f5e7 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -67,7 +67,7 @@ Please visit this link for a copy of the license: Marius Kintel

@@ -101,6 +101,8 @@ Please visit this link for a copy of the license: iamwilhelm

  • clothbot
  • colah +
  • Peter Uithoven + -- cgit v0.10.1 From 9b5f34a8ecbac1d67ef6a9d974889319bab733d0 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Fri, 17 May 2013 17:58:22 -0500 Subject: fix bad url being pushed to website, bug report per Andrew Plumb diff --git a/scripts/builder.sh b/scripts/builder.sh index 75b80f8..1cee38c 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -119,7 +119,7 @@ update_www_download_links() cd openscad.github.com cd inc echo `pwd` - BASEURL='https://openscad.google.com/files/' + BASEURL='https://openscad.googlecode.com/files/' DATECODE=`date +"%Y.%m.%d"` rm win_snapshot_links.js diff --git a/scripts/publish-macosx.sh b/scripts/publish-macosx.sh index 9d0423d..a3b0090 100755 --- a/scripts/publish-macosx.sh +++ b/scripts/publish-macosx.sh @@ -21,7 +21,7 @@ update_www_download_links() filesize=$(human_filesize $filesize) webdir=../openscad.github.com incfile=inc/mac_snapshot_links.js - BASEURL='https://openscad.google.com/files/' + BASEURL='https://openscad.googlecode.com/files/' DATECODE=`date +"%Y.%m.%d"` if [ -f $webdir/$incfile ]; then -- cgit v0.10.1 From 5e995b9ff41c6b6e6d288356f3387b4fab106c5f Mon Sep 17 00:00:00 2001 From: Don Bright Date: Fri, 17 May 2013 18:10:37 -0500 Subject: windows zipfile was filpped with installfile diff --git a/scripts/builder.sh b/scripts/builder.sh index 1cee38c..6232904 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -69,12 +69,12 @@ upload_win_generic() upload_win32() { - SUMMARY1="Windows x86-32 Snapshot Zipfile" - SUMMARY2="Windows x86-32 Snapshot Installer" + SUMMARY1="Windows x86-32 Snapshot Installer" + SUMMARY2="Windows x86-32 Snapshot Zipfile" DATECODE=`date +"%Y.%m.%d"` BASEDIR=./mingw32/ - WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32.zip - WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32-Installer.exe + WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.zip + WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.exe upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE1 upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE2 export WIN32_PACKAGEFILE1 -- cgit v0.10.1 From e25fff81af72a31f6118f4840b65193aa0ec1d0a Mon Sep 17 00:00:00 2001 From: Don Bright Date: Fri, 17 May 2013 18:14:10 -0500 Subject: windows .zip flipped with .exe diff --git a/scripts/builder.sh b/scripts/builder.sh index 6232904..876e6d1 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -73,8 +73,8 @@ upload_win32() SUMMARY2="Windows x86-32 Snapshot Zipfile" DATECODE=`date +"%Y.%m.%d"` BASEDIR=./mingw32/ - WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.zip - WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.exe + WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.exe + WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.zip upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE1 upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE2 export WIN32_PACKAGEFILE1 -- cgit v0.10.1 From 48816160cd87fe067156c5b8622e31ab10754e74 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 17:49:26 +0200 Subject: fix eigen bugs mingw32/64 diff --git a/eigen.pri b/eigen.pri index 1c9a5ef..7b4d46a 100644 --- a/eigen.pri +++ b/eigen.pri @@ -15,10 +15,6 @@ OPENSCAD_LIBRARIES_DIR = $$(OPENSCAD_LIBRARIES) EIGEN2_DIR = $$(EIGEN2DIR) EIGEN_DIR = $$(EIGENDIR) -CONFIG(mingw-cross-env) { - EIGEN_INCLUDEPATH = mingw-cross-env/include/eigen2 -} - # Optionally specify location of Eigen3 using the # OPENSCAD_LIBRARIES env. variable !isEmpty(OPENSCAD_LIBRARIES_DIR) { @@ -69,16 +65,6 @@ isEmpty(EIGEN_INCLUDEPATH) { EIGEN_INCLUDEPATH = $$replace(EIGEN_CFLAGS,"-I","") } -mingw-cross-env { - exists(mingw-cross-env/../i686-pc-mingw32-pkg-config) { - EIGEN_CFLAGS = $$system("i686-pc-mingw32-pkg-config --cflags eigen3") - } - exists(mingw-cross-env/../x86_64-w64-mingw32-pkg-config) { - EIGEN_CFLAGS = $$system("x86_64-w64-mingw32-pkg-config --cflags eigen3") - } - EIGEN_INCLUDEPATH = $$replace(EIGEN_CFLAGS,"-I","") -} - # disable Eigen SIMD optimizations for platforms where it breaks compilation !macx { !freebsd-g++ { diff --git a/scripts/builder.sh b/scripts/builder.sh index 7cd551e..11b6e02 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -33,6 +33,7 @@ get_source_code() git clone http://github.com/openscad/openscad.git cd openscad git submodule update --init # MCAD + git checkout issue341 } build_win32() diff --git a/scripts/mingw-x-build-dependencies.sh b/scripts/mingw-x-build-dependencies.sh index c3d5179..e9f124b 100755 --- a/scripts/mingw-x-build-dependencies.sh +++ b/scripts/mingw-x-build-dependencies.sh @@ -46,13 +46,13 @@ fi if [ ! -e $MXEDIR ]; then mkdir -p $MXEDIR -fi -cd $MXEDIR/.. -echo "Downloading MXE into " $PWD -if [ "`echo $* | grep 64`" ]; then - git clone -b multi-rebase git://github.com/tonytheodore/mxe.git ./mxe-w64 -else - git clone git://github.com/mxe/mxe.git + cd $MXEDIR/.. + echo "Downloading MXE into " $PWD + if [ "`echo $* | grep 64`" ]; then + git clone -b multi-rebase git://github.com/tonytheodore/mxe.git $MXEDIR + else + git clone git://github.com/mxe/mxe.git $MXEDIR + fi fi echo "entering" $MXEDIR diff --git a/scripts/setenv-mingw-xbuild.sh b/scripts/setenv-mingw-xbuild.sh index 15449ce..d3a014c 100644 --- a/scripts/setenv-mingw-xbuild.sh +++ b/scripts/setenv-mingw-xbuild.sh @@ -57,11 +57,10 @@ fi PATH=$MXEDIR/usr/bin:$PATH PATH=$MXETARGETDIR/qt/bin:$PATH - - - +OPENSCAD_LIBRARIES=$MXETARGETDIR if [ "`echo $* | grep clean`" ]; then + OPENSCAD_LIBRARIES= BASEDIR= MXEDIR= MXETARGETDIR= @@ -75,6 +74,7 @@ else ln -s $MXETARGETDIR $DEPLOYDIR/mingw-cross-env fi +export OPENSCAD_LIBRARIES export BASEDIR export MXEDIR export MXETARGETDIR @@ -82,6 +82,7 @@ export DEPLOYDIR export PATH export MINGWX_SAVED_ORIGINAL_PATH +echo OPENSCAD_LIBRARIES: $OPENSCAD_LIBRARIES echo BASEDIR: $BASEDIR echo MXEDIR: $MXEDIR echo MXETARGETDIR: $MXETARGETDIR -- cgit v0.10.1 From 7d68cb0232d15950275b22836652238625eb9ae2 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 18:39:48 +0200 Subject: improve mingw build, make rm silent diff --git a/mingw-cross-env.pri b/mingw-cross-env.pri index a447fd8..1ddce88 100644 --- a/mingw-cross-env.pri +++ b/mingw-cross-env.pri @@ -4,15 +4,16 @@ CONFIG(mingw-cross-env) { LIBS += mingw-cross-env/lib/libglut.a LIBS += mingw-cross-env/lib/libopengl32.a LIBS += mingw-cross-env/lib/libGLEW.a - exists( mingw-cross-env/lib/libglaux.a ) { - LIBS += mingw-cross-env/lib/libglaux.a - } +# exists( mingw-cross-env/lib/libglaux.a ) { +# LIBS += mingw-cross-env/lib/libglaux.a +# } LIBS += mingw-cross-env/lib/libglu32.a LIBS += mingw-cross-env/lib/libopencsg.a LIBS += mingw-cross-env/lib/libmpfr.a LIBS += mingw-cross-env/lib/libgmp.a LIBS += mingw-cross-env/lib/libCGAL.a QMAKE_CXXFLAGS += -fpermissive + QMAKE_DEL_FILE = rm -f } diff --git a/scripts/release-common.sh b/scripts/release-common.sh index a9fb3b5..261905d 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -160,7 +160,7 @@ esac case $OS in LINXWIN) cd $DEPLOYDIR - make -s clean ## comment out for test-run + make clean ## comment out for test-run cd $OPENSCADDIR ;; *) -- cgit v0.10.1 From 78303a79fae63bc3f7519184fa10f7e1e9cb5653 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 18:45:13 +0200 Subject: reduce flood of eigen warnings on mingw build diff --git a/mingw-cross-env.pri b/mingw-cross-env.pri index 1ddce88..f13bfa7 100644 --- a/mingw-cross-env.pri +++ b/mingw-cross-env.pri @@ -14,6 +14,5 @@ CONFIG(mingw-cross-env) { LIBS += mingw-cross-env/lib/libCGAL.a QMAKE_CXXFLAGS += -fpermissive QMAKE_DEL_FILE = rm -f + QMAKE_CXXFLAGS_WARN_ON += -Wunused-local-typedefs #eigen3 } - - -- cgit v0.10.1 From d8bcf47df699ce7104a7cb0572cbf6c34f6a3cd8 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 18:48:39 +0200 Subject: gcc warning off, eigen3 mingw build diff --git a/mingw-cross-env.pri b/mingw-cross-env.pri index f13bfa7..e696b56 100644 --- a/mingw-cross-env.pri +++ b/mingw-cross-env.pri @@ -14,5 +14,5 @@ CONFIG(mingw-cross-env) { LIBS += mingw-cross-env/lib/libCGAL.a QMAKE_CXXFLAGS += -fpermissive QMAKE_DEL_FILE = rm -f - QMAKE_CXXFLAGS_WARN_ON += -Wunused-local-typedefs #eigen3 + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs #eigen3 } -- cgit v0.10.1 From 127d84a58cf58f394f6786429296bde357803a24 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 18:55:44 +0200 Subject: url bugfix diff --git a/scripts/builder.sh b/scripts/builder.sh index 11b6e02..6a9fd54 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -159,7 +159,7 @@ update_win_www_download_links() cd openscad.github.com cd inc echo `pwd` - BASEURL='https://openscad.google.com/files/' + BASEURL='https://openscad.googlecode.com/files/' rm win_snapshot_links.js echo "snapinfo['WIN64_SNAPSHOT1_URL'] = '$BASEURL$WIN64_PACKAGEFILE1'" >> win_snapshot_links.js -- cgit v0.10.1 From 874a4840687bc0c3209ffe3bcb7649f549a18e63 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 18:57:08 +0200 Subject: if .com fails, stop build. also stop using make || make diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 261905d..5c63ccd 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -180,10 +180,9 @@ esac case $OS in LINXWIN) - # make || make enables paralell builds, thanks Tony Theodore # make main openscad.exe cd $DEPLOYDIR - make $TARGET -j$NUMCPU || make $TARGET -j$NUMCPU ## comment 4 test + make $TARGET -j$NUMCPU ## comment 4 test if [ ! -e $TARGET/openscad.exe ]; then echo "cant find $TARGET/openscad.exe. build failed. stopping." exit @@ -191,6 +190,10 @@ case $OS in # make console pipe-able openscad.com - see winconsole.pri for info qmake CONFIG+=winconsole ../openscad.pro make + if [ ! -e $TARGET/openscad.com ]; then + echo "cant find $TARGET/openscad.com. build failed. stopping." + exit + fi cd $OPENSCADDIR ;; -- cgit v0.10.1 From cc94b647f1af763944d104468affb48625ab7f9a Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 19:01:35 +0200 Subject: credit tony theodore diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 5c63ccd..9e56263 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -12,7 +12,7 @@ # -d Version date (e.g. -d 2010.01.23) # -c Build with commit info # -mingw32 Cross-compile for win32 using MXE -# -mingw64 Cross-compile for win64 using MXE +# -mingw64 Cross-compile for win64 using Tony Theodore's MXE fork # # If no version string or version date is given, todays date will be used (YYYY-MM-DD) # If only verion date is given, it will be used also as version string. diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 946f5e7..2ec691d 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -107,7 +107,7 @@ OpenSCAD Maintainer: Marius Kintel

    -Mailing list, bug reports, testing, contribs, &c +Mailing list, bug reports, testing, contribs, help, &c

    nop head, Triffid Hunter, Len Trigg, Kliment Yanev, Christian Siefkes, @@ -117,7 +117,7 @@ Brett Sutton, hmnapier, Eero af Heurlin, caliston, 5263, ghost, 42loop, uniqx, Michael Thomson, Michael Ivko, Pierre Doucet, myglc2, Alan Cox, Peter Falke, Michael Ambrus, Gordon Wrigley, Ed Nisley, Stony Smith, Pasca Andrei, David Goodenough, William A Adams, mrrobinson, 1i7, -benhowes, 5263, Craig Trader, Miro Hrončok, ... and many others +benhowes, 5263, Craig Trader, Miro Hrončok, Tony Theodore ... and many others

    Hosting & resources -- cgit v0.10.1 From 2c5b09a0a79609b5cf02f1abc9dca0cb27677f79 Mon Sep 17 00:00:00 2001 From: don bright Date: Sat, 18 May 2013 19:03:08 +0200 Subject: zip silent diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 9e56263..7d36907 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -142,7 +142,7 @@ case $OS in . ./scripts/setenv-mingw-xbuild.sh $ARCH TARGET=release ZIP="zip" - ZIPARGS="-r" + ZIPARGS="-r -q" ;; esac -- cgit v0.10.1 From 6509f0838269de67e6b84759ef36f0078f6e65f7 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sat, 18 May 2013 14:37:04 -0500 Subject: allow 'upload only' and 'dryrun' debugging options diff --git a/scripts/builder.sh b/scripts/builder.sh index 6a9fd54..984a651 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -12,12 +12,24 @@ # # todo - detect failure and stop -DRYRUN=1 - init_variables() { STARTPATH=$PWD export STARTPATH + if [ "`echo $* | grep uploadonly`" ]; then + UPLOADONLY=1 + DATECODE=`date +"%Y.%m.%d"` + else + UPLOADONLY= + fi + if [ "`echo $* | grep dry`" ]; then + DRYRUN=1 + else + DRYRUN= + fi + export UPLOADONLY + export DRYRUN + export DATECODE } check_starting_path() @@ -198,15 +210,17 @@ check_ssh_agent() fi } -init_variables +init_variables $* check_ssh_agent check_starting_path read_username_from_user read_password_from_user get_source_code -build_win32 -build_win64 +if [ ! $UPLOADONLY ]; then + build_win32 + build_win64 +fi upload_win32 upload_win64 update_win_www_download_links -- cgit v0.10.1 From ca4fb9238fa50fc11efdc36070bdd38f77148ff5 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sat, 18 May 2013 15:40:01 -0500 Subject: update readme diff --git a/README.md b/README.md index 5bbe8b6..73eea87 100644 --- a/README.md +++ b/README.md @@ -188,14 +188,14 @@ http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Building_on_Windows To cross-build, first make sure that you have development tools installed to get GCC. Then after you've cloned this git repository, -start a new clean shell and run the script that sets up the environment +start a new clean bash shell and run the script that sets up the environment variables. - source ./scripts/setenv-mingw-xbuild.sh + source ./scripts/setenv-mingw-xbuild.sh 32 Then run the script to download & compile all the prerequisite libraries above: - ./scripts/mingw-x-build-dependencies.sh + ./scripts/mingw-x-build-dependencies.sh 32 Note that this process can take several hours, as it uses the http://mxe.cc system to cross-build many libraries. After it is @@ -208,7 +208,9 @@ If you wish you can only build the openscad.exe binary: cd mingw32 qmake .. CONFIG+=mingw-cross-env make - + +For a 64-bit Windows cross-build, replace 32 with 64 in the above instructions. + ### Compilation First, run 'qmake' from Qt4 to generate a Makefile. On some systems you need to diff --git a/scripts/builder.sh b/scripts/builder.sh index 984a651..9850bcc 100755 --- a/scripts/builder.sh +++ b/scripts/builder.sh @@ -45,7 +45,7 @@ get_source_code() git clone http://github.com/openscad/openscad.git cd openscad git submodule update --init # MCAD - git checkout issue341 + #git checkout branch ##debugging } build_win32() @@ -104,8 +104,8 @@ upload_win32() SUMMARY1="Windows x86-32 Snapshot Zipfile" SUMMARY2="Windows x86-32 Snapshot Installer" BASEDIR=./mingw32/ - WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32.zip - WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32-Installer.exe + WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.exe + WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.zip upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE1 upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN32_PACKAGEFILE2 export WIN32_PACKAGEFILE1 @@ -123,8 +123,8 @@ upload_win64() SUMMARY1="Windows x86-64 Snapshot Zipfile" SUMMARY2="Windows x86-64 Snapshot Installer" BASEDIR=./mingw64/ - WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64.zip - WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64-Installer.exe + WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64-Installer.exe + WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64.zip upload_win_generic "$SUMMARY1" $USERNAME $BASEDIR/$WIN64_PACKAGEFILE1 upload_win_generic "$SUMMARY2" $USERNAME $BASEDIR/$WIN64_PACKAGEFILE2 export WIN64_PACKAGEFILE1 @@ -192,7 +192,7 @@ update_win_www_download_links() PAGER=cat git diff if [ ! $DRYRUN ]; then git commit -a -m 'builder.sh - updated snapshot links' - git push origin + git push origin master else echo dry run, not updating www links fi -- cgit v0.10.1 From 5a647f963a2dbe2344fe64d98ea5bd42f8f3e806 Mon Sep 17 00:00:00 2001 From: Don Bright Date: Sat, 18 May 2013 16:04:59 -0500 Subject: bold a single about box line diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 2ec691d..005f61f 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -67,7 +67,7 @@ Please visit this link for a copy of the license: Marius Kintel +OpenSCAD Maintainer: Marius Kintel

    -- cgit v0.10.1 From fab07bafdaacf931314673e396111a9670dccc0e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 21 May 2013 19:21:00 -0400 Subject: Added recursion example. Fixes #346 diff --git a/examples/example024.scad b/examples/example024.scad new file mode 100644 index 0000000..1502ec7 --- /dev/null +++ b/examples/example024.scad @@ -0,0 +1,32 @@ +// Menger Sponge +// By Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013 +// CC-BY-SA license + +// Size of edge of sponge +D=100; +// Fractal depth (number of iterations) +n=3; + +module menger() { + difference() { + cube(D, center=true); + for (v=[[0,0,0], [0,0,90], [0,90,0]]) + rotate(v) menger_negative(side=D, maxside=D, level=n); + } +} + +module menger_negative(side=1, maxside=1, level=1) { + l=side/3; + cube([maxside*1.1, l, l], center=true); + if (level > 1) { + for (i=[-1:1], j=[-1:1]) + if (i || j) + translate([0, i*l, j*l]) + menger_negative(side=l, maxside=maxside, level=level-1); + } +} + +difference() { + rotate([45, atan(1/sqrt(2)), 0]) menger(); + translate([0,0,-D]) cube(2*D, center=true); +} -- cgit v0.10.1 From 71ab237aada8db602045063f0f1c6082ef06972a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 21 May 2013 21:26:51 -0400 Subject: Added tests for linear extrude with scale. Should mostly fix #273 diff --git a/testdata/scad/features/linear_extrude-scale-tests.scad b/testdata/scad/features/linear_extrude-scale-tests.scad deleted file mode 100644 index 9a82c9d..0000000 --- a/testdata/scad/features/linear_extrude-scale-tests.scad +++ /dev/null @@ -1,17 +0,0 @@ -difference() { - linear_extrude(height=40, scale=[0, 0]) { - square(10, center=true); - translate([10,0]) circle(10); - } - translate([0,0,35]) sphere(10); -} - -/* -Test case ideas: -o off-center starting point -o Concave polygon -o Disjoint polygons -o multi-rotation twist -o zero scales, zero scales in only one axis (for the above cases) -o boolean operations on scaled extrusion (including zero scale) -*/ diff --git a/testdata/scad/features/linear_extrude-scale-zero-tests.scad b/testdata/scad/features/linear_extrude-scale-zero-tests.scad new file mode 100644 index 0000000..8a85203 --- /dev/null +++ b/testdata/scad/features/linear_extrude-scale-zero-tests.scad @@ -0,0 +1,56 @@ +// test cases for linear extrude with scale +// by TakeItAndRun 2013 + +// syntax: linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) + +a=3; +b=20; +c=0; +x=1; +y=1; + +module linear_extrudes_of_different_shapes(a=a,b=b,c=c,x=x,y=y) { + translate(00*[4,0,0]) + // linear_extrude of shape with hole + linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) + difference() { + square(2,true); square(1,true); + } + + translate(01*[4,0,0]) + // linear_extrude of disjoint polygons shapes + linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) { + translate([1,0,0]) square(1,true); + translate([-1,0,0]) square(1,true); + } + + translate(02*[4,0,0]) + // linear_extrude with a coplanar face + linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) { + translate([.5,0,0])square(); + translate([-.5,0,0])square(); + } + + translate(03*[4,0,0]) + // linear_extrude with internal hole and one coplanar edge + linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) + difference() { + square(2,true); + translate([-0.5,0,0]) square(1,true); + } +} + + +// Test varying parameters +translate(00*[0,3,0]) +linear_extrudes_of_different_shapes(c=0,x=0,y=y); +translate(01*[0,3,0]) +linear_extrudes_of_different_shapes(c=0,x=x,y=0); +translate(02*[0,3,0]) +linear_extrudes_of_different_shapes(c=0,x=0,y=0); +translate(03*[0,3,0]) +linear_extrudes_of_different_shapes(c=180,x=0,y=y); +translate(04*[0,3,0]) +linear_extrudes_of_different_shapes(c=180,x=x,y=0); +translate(05*[0,3,0]) +linear_extrudes_of_different_shapes(c=180,x=0,y=0); diff --git a/testdata/scad/features/linear_extrude-tests.scad b/testdata/scad/features/linear_extrude-tests.scad index 67d892f..528eea2 100644 --- a/testdata/scad/features/linear_extrude-tests.scad +++ b/testdata/scad/features/linear_extrude-tests.scad @@ -12,4 +12,13 @@ translate([31.5,2.5,0]) linear_extrude(height=10, twist=-45) polygon(points = [[ translate([0,20,0]) linear_extrude(height=20, twist=45, slices=2) square([10,10]); translate([19,20,0]) linear_extrude(height=20, twist=45, slices=10) square([10,10]); -translate([-15,0,0]) linear_extrude(5) square([10,10]); +translate([0,-15,0]) linear_extrude(5) square([10,10]); + +// scale given as a scalar +translate([-25,-10,0]) linear_extrude(height=10, scale=2) square(5, center=true); +// scale given as a 3-dim vector +translate([-15,20,0]) linear_extrude(height=20, scale=[4,5,6]) square(10); +// scale is negative +translate([-10,5,0]) linear_extrude(height=15, scale=-2) square(10, center=true); +// scale given as undefined +translate([-15,-15,0]) linear_extrude(height=10, scale=var_undef) square(10); diff --git a/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png new file mode 100644 index 0000000..3b1c934 Binary files /dev/null and b/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png differ diff --git a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png index 7d3ea2c..c85142e 100644 Binary files a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png and b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png differ diff --git a/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt b/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt new file mode 100644 index 0000000..950c724 --- /dev/null +++ b/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt @@ -0,0 +1,253 @@ + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 3], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 6], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 9], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = false); + } + } + } + multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + difference() { + square(size = [2, 2], center = true); + multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [1, 1], center = true); + } + } + } + } + } + } + diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt index c031ed8..c867388 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.txt +++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt @@ -29,9 +29,29 @@ square(size = [10, 10], center = false); } } - multmatrix([[1, 0, 0, -15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, 0], [0, 1, 0, -15], [0, 0, 1, 0], [0, 0, 0, 1]]) { linear_extrude(height = 5, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { square(size = [10, 10], center = false); } } + multmatrix([[1, 0, 0, -25], [0, 1, 0, -10], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 10, center = false, convexity = 1, scale = [2, 2], $fn = 0, $fa = 12, $fs = 2) { + square(size = [5, 5], center = true); + } + } + multmatrix([[1, 0, 0, -15], [0, 1, 0, 20], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 20, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + square(size = [10, 10], center = false); + } + } + multmatrix([[1, 0, 0, -10], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 15, center = false, convexity = 1, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) { + square(size = [10, 10], center = true); + } + } + multmatrix([[1, 0, 0, -15], [0, 1, 0, -15], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 10, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + square(size = [10, 10], center = false); + } + } diff --git a/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png new file mode 100644 index 0000000..22e94ad Binary files /dev/null and b/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png differ diff --git a/tests/regression/opencsgtest/linear_extrude-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-tests-expected.png index b929d09..cbbdc11 100644 Binary files a/tests/regression/opencsgtest/linear_extrude-tests-expected.png and b/tests/regression/opencsgtest/linear_extrude-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png new file mode 100644 index 0000000..22e94ad Binary files /dev/null and b/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png index fddeeb8..cbbdc11 100644 Binary files a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png and b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png differ -- cgit v0.10.1 From 1c480a554ad4094bfb2337d915be33393a679e13 Mon Sep 17 00:00:00 2001 From: don bright Date: Thu, 23 May 2013 19:16:04 -0700 Subject: make dependency build work for OpenCSG without qmake diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index bfc830f..67df0b7 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -408,11 +408,25 @@ build_opencsg() OPENCSG_QMAKE=qmake-qt4 elif [ "`command -v qmake4`" ]; then OPENCSG_QMAKE=qmake4 - else + elif [ "`command -v qmake`" ]; then OPENCSG_QMAKE=qmake + else + echo qmake not found... using standard OpenCSG makefiles + OPENCSG_QMAKE=make + cp Makefile Makefile.bak + cp src/Makefile src/Makefile.bak + + cat Makefile.bak | sed s/example// |sed s/glew// > Makefile + cat src/Makefile.bak | sed s@^INCPATH.*@INCPATH\ =\ -I$BASEDIR/include\ -I../include\ -I..\ -I.@ > src/Makefile + cp src/Makefile src/Makefile.bak2 + cat src/Makefile.bak2 | sed s@^LIBS.*@LIBS\ =\ -L$BASEDIR/lib\ -L/usr/X11R6/lib\ -lGLU\ -lGL@ > src/Makefile + tmp=$version + build_glu 9.0.0 # todo - autodetect the need for glu + version=$tmp fi cd $BASEDIR/src/OpenCSG-$version/src + OPENCSG_QMAKE=make $OPENCSG_QMAKE cd $BASEDIR/src/OpenCSG-$version @@ -562,7 +576,7 @@ fi build_eigen 3.1.1 build_gmp 5.0.5 build_mpfr 3.1.1 -build_boost 1.49.0 +build_boost 1.53.0 # NB! For CGAL, also update the actual download URL in the function build_cgal 4.1 build_glew 1.9.0 -- cgit v0.10.1 From f95941bbba15c016e8ceba55accd79f98c171aa9 Mon Sep 17 00:00:00 2001 From: don bright Date: Thu, 23 May 2013 19:31:49 -0700 Subject: update cmake to work with custom built GLU in $BASEDIR diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9821d70..39dc341 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -252,6 +252,18 @@ endif() # OpenGL find_package(OpenGL REQUIRED) +if (NOT OPENGL_GLU_FOUND) + message(STATUS "GLU not found in system paths...searching $ENV{OPENSCAD_LIBRARIES} ") + find_library(OPENGL_glu_LIBRARY GLU HINTS $ENV{OPENSCAD_LIBRARIES}/lib) + if (NOT OPENGL_glu_LIBRARY) + message(FATAL "GLU library not found") + endif() + set(OPENGL_LIBRARIES ${OPENGL_glu_LIBRARY} ${OPENGL_LIBRARIES}) + message(STATUS "OpenGL LIBRARIES: ") + foreach(GLLIB ${OPENGL_LIBRARIES}) + message(STATUS " " ${GLLIB}) + endforeach() +endif() # OpenCSG if (NOT $ENV{OPENCSGDIR} STREQUAL "") -- cgit v0.10.1 From 85a6cf92feebd75f817e68bbfd53807d3d2fd1fd Mon Sep 17 00:00:00 2001 From: don bright Date: Thu, 23 May 2013 19:35:44 -0700 Subject: remove debugging assignment diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index 67df0b7..60dbb74 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -426,7 +426,6 @@ build_opencsg() fi cd $BASEDIR/src/OpenCSG-$version/src - OPENCSG_QMAKE=make $OPENCSG_QMAKE cd $BASEDIR/src/OpenCSG-$version -- cgit v0.10.1