From 1b8b7aa5faa167af2687970f195e19439dab5a30 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 5 Apr 2013 01:30:09 -0400 Subject: [PATCH 1/2] I think this should fix issue #217 --- src/dxfdim.cc | 17 +- src/import.cc | 2 +- src/linearextrude.cc | 2 +- src/module.cc | 22 +- src/module.h | 8 +- src/parser.y | 50 +- src/rotateextrude.cc | 2 +- src/surface.cc | 2 +- testdata/scad/misc/localfiles-test.scad | 3 + .../scad/misc/localfiles_dir/localfile.dat | 2 + .../scad/misc/localfiles_dir/localfile.dxf | 1968 +++++++++++++++++ .../localfiles_dir/localfiles_module.scad | 10 + tests/CMakeLists.txt | 7 +- tests/dumptest.cc | 10 +- .../cgalpngtest/localfiles-test-expected.png | Bin 0 -> 8454 bytes .../dumptest/localfiles-test-expected.txt | 17 + .../opencsgtest/localfiles-test-expected.png | Bin 0 -> 8844 bytes .../localfiles-test-expected.png | Bin 0 -> 8844 bytes 18 files changed, 2080 insertions(+), 42 deletions(-) create mode 100644 testdata/scad/misc/localfiles-test.scad create mode 100644 testdata/scad/misc/localfiles_dir/localfile.dat create mode 100644 testdata/scad/misc/localfiles_dir/localfile.dxf create mode 100644 testdata/scad/misc/localfiles_dir/localfiles_module.scad create mode 100644 tests/regression/cgalpngtest/localfiles-test-expected.png create mode 100644 tests/regression/dumptest/localfiles-test-expected.txt create mode 100644 tests/regression/opencsgtest/localfiles-test-expected.png create mode 100644 tests/regression/throwntogethertest/localfiles-test-expected.png diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 1ed37fa1..53bc4806 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 32d4fedd..bbf5a6ea 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 43db9079..ff9682e9 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 e6dcb579..322085bb 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 cc82f815..1f9e3039 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 536f4efe..70aebba2 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 dc8ea34e..c4d93427 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 4339eade..ca5031e7 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 00000000..31efe964 --- /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 00000000..32eba08b --- /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 00000000..933e2635 --- /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 00000000..b98a49b4 --- /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 5eecaae2..a0d8f6b2 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 b75a2e26..36276084 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 0000000000000000000000000000000000000000..3ad3d96a2f7fa9670959a8afd780acc571e92ef9 GIT binary patch literal 8454 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 HC#L*A4rYEZ literal 0 HcmV?d00001 diff --git a/tests/regression/dumptest/localfiles-test-expected.txt b/tests/regression/dumptest/localfiles-test-expected.txt new file mode 100644 index 00000000..acdf7e7a --- /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 0000000000000000000000000000000000000000..7bc7909024e7a03b2331eafc68f209f961268285 GIT binary patch literal 8844 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 T4ha9t1aNdXw5N0zDe->*nKo4j literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/localfiles-test-expected.png b/tests/regression/throwntogethertest/localfiles-test-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc7909024e7a03b2331eafc68f209f961268285 GIT binary patch literal 8844 zcmeHt`9D-&{QtePSTbd@E6Y?uybB>@nNg`kQDhr3twbS`b<7>!ZAzq6_Gyult!!nR znR<&NlnlifBHLhOo6MM*&+Ys8{sEsKKR@)-J@>p`=lOb_*Ez4}nfp3(-SyDE)vMO6 z0svsO=F|&2f*tdo(!B?kLj<_LiPCeb+Ezfb7vmZBk2Q z?)Sp_zBXQ$gxa`HHSP8G3!x`|yl+a;t^Kkmyhc}d1%2-H<2O=?@AvzvDZYKXACLua z`Z9dgF!*gZ&AUv^$+a))Uep%l#TMmt{2M0x`n;4+#&=kEL=|;RM9kPk&(5XbQ8HMZ ztIJ?W!)Brhh(O8MC}Dvm5N;)}l7Svwt~m$y$pCQ>03saFD8lEr#2v5@1=$iHfcgl5 zpal+X&4z^th8B(h5e|c(Yvt^{gRnkGlE>l*v}X{Y?-SjsOMoDtT>6hScLJcawf?js zjz9o=y8R(UUFu)Q}K_8iFwJ>i0>li@3D6yUJxd?rd)#d2Ky zsXH~*+2%>>!L5U9NI{2tHkC(GZ=?*AFnp>ZYpBZoqmAqn?CV}pw)c{iUek$>E^jpn z%Uc16fTun@&n6S_J)1kirOTf*zLYI?AO-S6S&>a{tVb_1V``DT&Re$r%lHQ|EPPF* zdap8Va$tkb569P`b{H5p3N4K9_?~*qkTYu4WV}Ti+fZ{5ccRYoL0P%!HMrx4ov$E)mIohV5z2#%E z+y!Z4!?GKSURMe6ZkM#vjt9I(wz#4raOF=3@%&Jax)z#~L7_&UCgJ0&2TD{dwW+RL z2&L`J*VqH(JozPy=u`2k7uM9DpcTj@;DAKt>V2dbs!a*KDh=G~FoN_)Ui-R3h58e% za7iMyd93(e8LQ1SOxoDAyj5}krZoD8T6vj)e-Jn|8)2A{_(R>9tRHgP;x=c`OW*7e z%XO5xRVJNB+C&7PZEO9?;uv>gzT}{fb70*g7N^uls#2-K4hvMw?e&dM5s89SnZ|cR zQrMK5z3Rr5EYBPxpp-zI+ENfJ!kuP@wN(wkgB;*NrnXqXlzFS6_!xd~d9>C!+9J=> zA2Su~Ec61LxiLSxD}{zb0^1UIt#idfp20sz!Sn(%Ko(-2a8hUMb|#%P+z6*e&LiD1pA$Ois4SlM={*fEd=6IcV)NT#mfd&i!TMY zK=)3x!DjaIh9VY4FB7ll=kJh8j*_tN-3EsxlQK{+##|Kq)kB!$ZbDnsp4wy*25cYS z4H{o-rSq>|I6pCkF`)^gX7trNKYSUZ0ppJsW;G;}Jj1Gq`FqJ=iDacZ9ULPcB6|Qi z=`r!X96I36>-wcm6Y{^E-cC#X!n8sR0wWVweI#yjsUdQE0vIBBvtc@4B#DVrvD>MX z243BG-%bV4+~q@&PTpOE-eo#?7%&@dh58)E#rrWA>n>_412yiIVxoqfr6Kk{=z^eS z-ojWC?=1xdP>f8$Um8njJ--f5Q=#jB%DCI_xCx143um z4KbtbpDd1%e}y()n)JTaEN8|Cx6|a~BD8VHoe%3#UqAd9+)eFB7>W~OYbA|))0>aU zO?u0ep(A%GlVw}*66>g>Bu}|Ep+V>M`_NJV*MsCg+;*}CA+%KH0T(4A&B0&MR15mV zw_mF2G3XkEEy!LqwL3!&U{mNTTA_{vsfFUFn81f0(S*8ic^T)8X+!yv>0Rxo7@?B) z+&)Rw*nKh%d8wdG=tnqR(|9?QNc#XSalwPlJl`qtFS?{TG%BxRIjIh#FWwA-<;&y{ z>QB^?P}tPO%l9?LWT`#N0TF{g{IPmi%Pnb>i}|XOxfgnR-+7AW?`YvtGEf4=G{<3Z z|KNIw@Ery;Zsci~ObtQkY=<;hW(j<0;{0QME;75_~|nIM7| z@y>exU=AaZjeo_{R;+aFj1P)C-g$~pQF_E*0Sh!|_pe3hp;ZD!sRL5==QzBP-XOKR zwaU-{*GQ8cn1xv}?wIqq60v_KoI13rB`O&H^NN%PT{N+^;RjntYRzIBGjTB(9sirdp# zu=CA6O`UQ@nLv?)AYts*M|G)gSdjGv?CeMN*AJN+CH$sa^PeS|qenwT8Nxp*SSd77 zQmRsbB<-7ho4;~yo`AV1{`pU2SR<=!g5SUY#=rL8W;jX($AJ1pMGOB}&aX>K$Yx!K zTPv+}5hsc+d2FTff|q(YMKUPb_}}nCB4mfd~=)Pv5EmrLh44dDCBn9)h+{uKWJ0BP!W|SZ6t2$)qYv`fm~7RkjoREoBN|A%Rc6x+r>*7? z5H0(Rw-i6r!Kt@Cs<5z`I9@L%OOj|A>b~ytX-88zDEAQ#Q~i=^U<-nYzj>mTdQuYhl`;8DI+}-=`CpH(X5u z`p4anJH<>5|KAmQe9B|W^bckRSq(>9%-^K~6rQ@GNf~m{Zp~m-dQL zWC=Zh?UbPEdNN|7ft0#j+bGq!RXCY6Gpu*3)}fcVvO+x8w`C!-BcWzKx+5uHoO;}a z{@agWBw`yasrx7_9L`$IarB|{5Ls1ww-vTh(E=)(ostFE*)$5Z?#2j-#R!?4qlUA5per5DNAykU~QNbWZxdZALq(v zN90jagghVLJjZ}t^>d3ad3!`H`{-}h$I(;$^FGD4|E}^E{}O%JTa9rnH^NU3x9mJ* zJ#XWw2*d=v>~$6o@)L^Gg*W`Q*6ZBZI`|($noPHSVXO7c{<}`#(;@VuY86kLYsKG{ zyNEq*D8`<}SeP&wWk?sZ@>Y#i{c&t|b(40&%u@68*?EyJ)Q7YaKUh`oyeYadkev|SD>Xk_ov`YbqE*|2u%_I#!VvSaC3c{6$d&VfNL5Xk2;hxgfzh2JAd? zPDBM>`wcZANhxH>j-hv{f3TRhb4n-{j$oK;@pOVd5Ylt$IncY8LqESf`?w&TroMAp zHN~_>?1x4(+8;6`a?sn2fr%=Ww9(wAe#SwbjzaIe$cgWLi@9wjq7Y4 z$)SYexgBP+$eQT#0Km+N?*UO4@vo8k1N_uq20F}1A4#b*VlcWcWZ@cMX)sk81qj4z zXNRcMo0$h-T($p)%S-^wg8gP2NW%ltoo(dwP~`biQ%9hFp@TCZU}Ywd<#g>U9ym4z z)-SQ>hDE@Ggb2NcM=)O71E7I6rHW0Z;@aCW4u)Ed(IBfT^I zia{~eVS2!{n}Z-x&o_*uInDs<5-<2m=Lv5x1mg6%g}|wT^uZ);LH}pp9g#E=@cXiH z_IGC2w!JVNMijlM;#5|+D>zrBx%X`86|JX$X+erlAKYxre}u8s-5?u_^Rp{B!{xk@ zfm(%+Thz6e$1QFYUyN(Li|XmF4CivL%R*Y#dZMx`6md$&G0|y&OmAM}^=V5wE#P^j zSo1Cr{pxt*;=71Ysf2LWWrn@ zY{lR^C~LJ6dPLIK1Z~3Z^bu?OX7c*Lid&{e;Dj)jNS|W9phpE3aHNVB^S@2b0PTb4 zM%?P?v(t2x#VdnWwQc3oH5XR%XE7WppEL5;sM`x>yq>W*)E{Yl(7g|Ng67jy7$h;ckbrbl{P#**$9L+`XC1DJKp2DS4eSamY~M7 zYuQ5w7_IR8l+nZpIuLp3k&nb%D}M?ud}->-Y1BqVjmV=k@d0IWDHgsXs|4bWQ+;ag zz`~1@f_$mZq3R9o;k!F;Y+*Y3P!cy5$E`w;$`UdX*8Ml|s!ltZ8ggG_UzJ!R(o6Ku zM`;ETe}Vgn@xo~QKRGN?G3i!aP9wg(qe31H%Qjp~wMNCq(2$##(pcJDztd)5x#$3W zZkcB%SsK&zE?l4Js3z^VhpYYH&k=hBf`q+)M|;&ZDnzF7q;cza0q0K1-(1c$?pYh{ zH@>sxM#mR{k%HB60}wRMIK}3^-teGk$w%Uz{wZ<=d(G|vf|i;du}$t8wRNvvdnez8 z;Tz+{<;m*-0;1LYD@g72xyq<3Ec#Uw=I#=T{v$xmV05Jw(P$Gku%CnHMKlFei48lm z3T2?akbnVvJn@MENHtj{lwZQ7GX%2X(2D0$=P%6VfSiE@EWbh0&sOxt1?5A$)ix^dHQtFpuM zkq>pq__2GhV?BH%-4~@@lmKa*U5+2Eg}ci~;%x26&&PTI&etZ6AW=IskUkQKY&_y# zLb>Kq7J()h>FRybDKF@`ydcWl;TYjvLeV9H#)`$QYZSc}S5sN|;@;iuEWy>l)pni$ zMtA<-Wt4|13=*Gh&&}_sZg>SVr%lVoG`!S;$eW+c!W;6$O=w2rmFDZH@PrrwH$U=5 zpr~R_%ikB!$jpf`o&Ee~4N6Am&4x}vKuOgf{pUC2pncnIDW+jF`BG~ohTx&;BCA_Q z%1D7&qr0E}ltnLFyW$0)l8j9I|D`L3XQFM?&F3OFlt``%d?nq2vGi%OAK01w@p>le zOaqKNwhhLu3G3j>L3yr7m-%5xD$y@WP-#Nr`FmcrhgV&-B)cHvJ ztC;HCh-Uh>CyUKfQf&PDHxhjWjh`R@#h7Ox(bU$-B?{0N_0g%bP+v9vw* zm*8&-lBp<$a$w#o1l0}xM!Tx)!j*sA7>fhL%yach2{h3hp`CNK3c<|IHXN@MA9b(J zd;)km6|~)9tU^_am6gthCL;!A-;1-UBC~6H24W{#A;jV+8g!pUkVsbH60>X68y8}? zQVVSbVrgC9<*wF4(TDG^T8jnZ+JqKh+*Mnha&u~&k?pb1uXQ>FJ&h(P#&^R&F>0^O zR5~dd6DZo$sc3r?=-+lF8|u@tGuU7}a)rR@AZdYM*!QXr(5EKGM7IC~ zB7UM!jDqx5$Z40I3&c187x7cyYMvs@ci~nx5FmyC?x3&JIz^!CS>1pu?V0d9Z_-R1 zClwoPbsM0rz^P73ImI9t7b@b?JO}{BC1Poud2c{ync}fTyKBzw4-@V@$T>^VhDOF}6`iy|b)k*%C@_B=HOjLDJ&?GBNI` zKje25laucK`9cZBq3OW(qo8rXh9&>Cu|F-wG$tmhvi)UeKlV^&7lt>a{>Q+U>=_FZ zT~B^l^jrpd7H%sU8FSjVnb|EDe1cIU>sO+>vZn;E7Ju@cEHs-~?bvxU#~foPa^ZxW z;m`2v?R=XdGP+XSc%GqrN_?^ud{wvQRNfHBZM!ApHKdop%2@g4HlQ4s?qC@ESp^+hUCtFEaXIR zhlBCad|vz{%Z=wR@Q$u&Ut*HL5{hxA9!3c+FJapzq!EVKsgZ0jP$XT~cGXn&w>QC* zdGF0s!#=!vU0XO(rAP=<{t3Oo%{c4hm5gmjk8nfd*ecUwFcq!sDX2rC2=|juddgg* z8g}N{IB+Q&hv*Lx2;AK`A-wEVbCy6l(TaQkJ{k(12HUD&k+#)|EDrL+mU;NnDTeIi z?}y3Jr?V)C_d|goh~0WD#KxrDGrWW%|L)ySG>S22u5Xew2Q$I_-mzdJoa)3T4_i(; z+))b zy(j+Uuf^rUeX#ZY=TAn;p4%){DK4GddC!L-pXB71x9d*u3DSKO*SBJZ-d=k&zsee# zw8r%aJfkgWi(}t+oiW`5=f&snkeiGHCkWisZ)^5uy1;d}0Pe?OltMGa!k1R&{(#NROg-Za6_O;GW7%T9U_p!RXoMdI7f{_$!A5tDXYM<(Rw8thK z;NfPVIIZ$v8$2xJ_`VuL98gW{J7TyVK3gcyKb?440{uByyyyf)B$8tW2ai7K5!L`{ zOGP#02Aoj}+)j$J=sX!-OOe+pJm<~OWZZi}j5>e+*xD}w?#yaKjv`EtYFZ)AG(*@z zit@Mc_cAh&No-!76t%fbrooTvzq_i<#C`D3j=j1j&=|hh!?tV~yuq-VB&on{8C5JW zG$N$~-y5z0!L-L~&e+4m76z~Qp%4PBJOcj)`m6dk0)Hd$Hv)en@V}10Z;DfxB`d4t T4ha9t1aNdXw5N0zDe->*nKo4j literal 0 HcmV?d00001 From 3307deee9361883a5297fbcac7f5a1cb428ed40c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Apr 2013 22:41:28 -0400 Subject: [PATCH 2/2] Added test for inner module variables --- testdata/scad/features/modulevariables.scad | 7 +++++++ .../cgalpngtest/modulevariables-expected.png | Bin 0 -> 9534 bytes .../dumptest/modulevariables-expected.txt | 4 ++++ .../opencsgtest/modulevariables-expected.png | Bin 0 -> 9854 bytes .../modulevariables-expected.png | Bin 0 -> 9854 bytes 5 files changed, 11 insertions(+) create mode 100644 testdata/scad/features/modulevariables.scad create mode 100644 tests/regression/cgalpngtest/modulevariables-expected.png create mode 100644 tests/regression/dumptest/modulevariables-expected.txt create mode 100644 tests/regression/opencsgtest/modulevariables-expected.png create mode 100644 tests/regression/throwntogethertest/modulevariables-expected.png diff --git a/testdata/scad/features/modulevariables.scad b/testdata/scad/features/modulevariables.scad new file mode 100644 index 00000000..fc7a1834 --- /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 0000000000000000000000000000000000000000..0dc18e8b26adf571e5fdfdff2f0e793bafc338cd GIT binary patch literal 9534 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 literal 0 HcmV?d00001 diff --git a/tests/regression/dumptest/modulevariables-expected.txt b/tests/regression/dumptest/modulevariables-expected.txt new file mode 100644 index 00000000..fed4bbc6 --- /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 0000000000000000000000000000000000000000..bf2326516565aca2bd79c2fb604a9cea4fc01c4d GIT binary patch literal 9854 zcmeHN`9D;D)W3ITni&-{C?Sj@v|6*I%!pDUN?A%Mi6ld|#F&vR^_6L}(@05KvSmq_ zNkx+E*_VkdW8WDwbD!JuS3J+_)h~1Bbzh(NIp>~x_H*xBo;DHQD7_H?0O6A-jL!l9 z0{)8tuzxQ>(nh%epmgk{vEjMf;8b5j{mr`bwR6)IX(C$V6>b+!qVIxFb;UHipFKuu zihI8vJK?PuWxR;P-bK0|vck*g;f+PNgvqO5cb>8|G(0Bmb~Ne@s;Bc^rp16yqmRRK zmum6y+scm77avwqDzmL~moE8rX8@>@bo;Ubj6ktu{t5L@Q~zx0pZEO>3IBrU|I0Mfj|34JSl;|- z)r@-u5n5w@xYKtGtBW}TqH4}>(;54;Ni2j4 z=j2&n>}%w?MY1_?#p}Q5iIZ@W6|=p@5Vc%nuqEfhC8KGt>dwMMcN_9C*f;A)ujBpc zD43*n7yu@K=JEQdHoiXXTHk9_QU17=F%8(<>`mSSW>EJOyq&6Jox9SFgVQzAt5@2T z)JHJQI-{@AguUvgiAv*cwv}UYm?>xDjibm5k8`d?0_W;)huuC8q4DBok3vyz^mR@G{?7+X*c2$!VEHA3;&?GR z=b$19DP5i8^Z+>b?N+knc}QF4X>Rbc=D_lO0#}+gL1;znLS|V&)V>x&W+AM(*Q*bx#Yhzc&>@1l)H(W|%k!kozu?4MYBYbexA)`ev-xY@Zl50!SI#<52KBbQ*-M2lA;@W&f;2DoDrqZk8| z%y-u~Z@}j0%`$f9*GWK@3vYLSb_Ves-EN&RSAN0%XZLE7iTo+3Syxy$efF{FzV7(s&^c(xPs7XjF_-N=PK+rtMpk2`bf4tRhQgLIZxwB0O0_4S=hJ2CSfa-k zaL{TaB(6A?r-V*l-?tY0W<67)@SuE6;a1%Z zRUM5er@TapR7V?!7(6NN-*`I2A!d=+8r09{u&YZe`K6fW1B+7zq4nj|Ngo>^{ZBN7 zw0OusEUHm!5F4CFz_J`P*SB=EwGb{P*+80AUj{dS`_mCxPVG)Wr?kul%E4-&_n`0i z+439Th=w5_sq)sSsgI=`DhS(EJ7{VLdG1Y@_rWi8A(bKz=$npN=|;8?2nV43@m=&_ zT*7NPfy^CY9`_*>Gz&P))Fm@;=?B{$TGY{oN)~hU@rRxS| z3)n4ZfOoGi>txO9Q)i2@vtfCc)*xR8;ll??+G!urdDF=BZNg=-X%zdv-Z7+qrZ-D~ z%pl(BKe9sCZs-tP_9^2s#arsgju5xipS?7bV0ql)PTt&{R)1gA+@6%*&JC|K#yU zb>7*_RxHNmot}QO2VhTnRT}*F`ab$zgSrL@`E!uGxEJhn`|VJEB#%qCTdkE;un0+a zv1upr#;t(rf|JQKH=+ab_(qmwva^=_nE zO&vk?TNaL}@)W*}+<@}+#y^qYGXhpMoiS=dLbI3Ue%uySIdqz`O{Lt7vPI@n4N=(O zOUrDcmt@6~t*+-<{T0mMMP4l6p>(5&PT5&4mqjg8Hv+DmgCyTjL9Fsh7ATrj8iuG= z3XuVC%A1?UPKSwq6ZugTlCKi_aHt@P*J-@nEcLRUGDNdpVNGXnepRlCKt>rQNf zh>qSOPJd`%g=ooHo*fp1zbXR+s1N>&E;cDWAYc`PNl^V9iVp4!WT-HW{Ch1+{OdC6B1f+K)Xvj9i z5Qhk8<9PKNjF$Yq6xb2-V!~qXkIjZDq=`J8AAZ6axPB$6{NRjV+DUSF1ak;?H+@cW z$XjAq_szKR?F4mwTI36Y~QL8dG1q&*KLO-ddvg^`jR%WiL|-gMmVbJ=T#aS_4FOA zIKO8xYz`p<3T)5YyAr{es-gg(IbeCW<>IBA;&|uWV2LdX&!>>TAN&=FT`Mv; zXBX9y$0ZsFZ(nq(QIbzL>&9&M*zj{1WQQ?Tn(BNN0Nm*>vjrBq0V|!#-M(eZj(7c* z$Dt>N@hg|0Eh@p!Gr^~KWr<(%(J6I+aKf|jS2Z!TC#)C^eS3aSoWRSCvo2_M>94c! zO`)ucQ{u6#CkqV8J9VO#zK$>+ExRxhqNTr{=!@S%sikYox?6U7%lO7c)rRZ>=xm}r z_jBf73o`_i8t9Q&(rw+ULyQQ`^T-;UG4izD3a?AF30e4(iz7J}@(5}@P;MY~_awe! z)hfwKd4h@N-k}o{WW?Po{RZ;U1AQA)GMb;V zHRZb;g-F`$fJufmlx-BVo8Ros+eEZ6sjDg*?jo<2c&#yHFO4pb%A$^0(%XSrLtKhY z46TJtFr`NO`mqTePqU!tj*#laE?mgV8Rrd7>@|y30udK1IyT6vU~cgr)1SFM`(g&! zc()oPV`K~S=kxr54=g&I;|eS`=Wz+Q^67sdBY`%{Tdc7kC9~g*s}@qmE=rSJ^dR7E zWH9F6zgE=v0}EvjIer)TWIstOzN^f74s)3f5I*v7m^+=|z3ryYk%W=DC*~yEgi2gO zfl$Js-nQCm!TH3`&rWb-fmgI6af1A+`2vgRvacM1r|JNRr+xN#z8`4jv!(F{x*~^$ zy~7=4!Qx0bK1~qTjnx*iprac%bqLhC^Bktyy@2PAY#W9r(L^>Yp1Su)^;IN^IaPq$! zBP+xb{rUrUhL4G%RF8ctrtagF7B4gEOiOp8;)p^C8r`ua3nF)`EhEsnBIQqBxWIm~ zGXyTF>W!ZX=3qrU4xKRVU$wtIFYa(qk0%xNGuImR`q%Fw@AYPyS2Q}s#g%P?P$LZX zafmI8(cx6v5RWB-RCnJseFMl&Pzs7HCV3#-SbcA8i#`RpM^vhDtZNO}HQaXU<;lqD z%KgyABcLb3HU9V&g4#@|ms{g2OmpNY_?aG#Tc>4PL<9&CRaNw9bsmx11eZOB3oPCT zpIDk1opr6Phw6&l^Nn!HG%v4W*v2NNo!M?acVvb`X9qWz2R;RQjeVACyp{;mF+z>b z1%BQYZ*OswgdFNvw3d_jeYqJ$P_mKp_D?QUbg@^OIZLnU$rV(}3J$wubTF*x;La+g zWSUaSp*Gr(HOs)s{ech*b%nT?I8)VLeqxEaRS-S#lX{JGvEOA)$>}~$oqG;bld>V) z)I`|!x5K9@RGMK+tqo+mO1wHXApfn@+*VM!Q}6TXY;#tdSnxP!(wz0F?HuMPvgRAh z5b1$9uyD{T9N5eX^q=6&Q^SoQuPb%i8Ih84#8pa7dXef)N02*sW5!d`@v~K0gu{NF z;zIPj&st7_zYgrj(@d3|^P(MBBfkc2g2p;6mdIti0D-3elOyDgMkRS3#~OKMuM=T5 z_;)YwIN+JCSLywMXT!HxTdmMTST$aLhwjWo-^|#Mxox<7B_Zf!WzngXzBF&IxClb9#9nM&`&O zTLMIQ{r4kw;;Dq7nM!DfHe%zKkEYcr$vYi3Mot?@2!;l@iw@2Y0w!;jMWP1$_`%D~IBIb3@6t237on{+_K7<3Mi zf@R?sYz2+Fiww%V=J11{i%LyAbrK^Pkk0>b@)Qtpwxqin8vHVEBY@S9VP4LfVp~Xh zga~{FM>_tXMsllEYp2YShtXv}n#Z>yyiN^ujS?U>owyz{Q(qlUCAUKkWz)n2Qja<5 zvy&WN+fRe4|(>3Y5zL)wP7n5(jVSU|9$E zkR8_>2G$~zSDp`aIxbP=9GL?fs}R0P(Ic>kUJpvE;d)A|{>V8fL*0InT*YHbehTM{ z=i|nRwJ4`EF^Ap?gb6%!Of+X^ZYDj@|D#W1GOfqKqD(W$>ek^+^D?&q9Z-_yGy3a5 zHk6vs=Rit>YJteXYaP9&+Vwi%WuFq_3(!QWY_TC09(#|Ng{km^as^WLkY3c1lzAF# zzKh>pN*h=stB*;mJyJ%f0i)d9@C;(KcHq!Lxz8mBKS8U@g@}}-%CRcnh1Zl*=$d~n|HcC!%;mNAOnWkHmHAa^!zRAYN!CJC;PM>71) zg}nqmdPs}Bzw~VkR;>BS#MOrh`=LC={*3*2w*#jyV#_n=D5t2ARYUx2yb*+ zW+xDU=X1!szElYv&(d6h4%+Tc7rXK7-6HPj5i~a7i8fe-sBFEyLAY$laIFU=@3K)V zPaqXZ-2IrT=Dr5q{Sp$wEN*fT+aYXwlpN@Y@M5sr%vsi1%s&vnmt1tLU&+ZxdXVS( zV|W+ftWv4rfGj!7Hwn)bMP%diakd*4VhypZttxPoc*D&+0Hs2`sYl<^!7Gb!_g#Hi z+AHAaRV{hI`E7q63TEtlB)R`UG1nr%^%ic1cKZ0Q_eM2_mR1-?Z-M3$Wl&Ox^R|nI zzIqO7II?;q?LCj7mZ6b6aue~S!n0Ut^{eArk0NfxH4f1FHeQki{fdW##ePNJpR`JA zQ+cWl)*mD-F`fk=)Py=>%~|k)_in|<2em^*;QP$fcM}0vmfrzfMbe%5rPefzu~*3mxu~;Cj#vh;57B9j zl=z_0*)>na)00hw4qp{d?8p07bmA|SAttbN7N04ya#4J$E z99j=qd#F>Z^Sp09EU(hlf8en!k;@G-DM{&`bRG!wv|D0)pLGw?r)AqJIocO)?KE6s z{4m9!UgLFxcAr>cAjog_gOcf*!Fix2aJcdK1U79qBgKKg*#CT zf>d8rn}Nv?J*+UB`lY0rZ4q5)3ffL#ReRU&Fi>$SXt^w9Vz37~hZs zr^pyQV1uVgW~?cZ#&KCvM3j6O$27V0s*_GT@#roYZLtGhm&lzpVrxQ(gSE9;`P z^=OHbvNl-X+AWpS0OFgwbp8&|lIseclnJQFIpMeZYb;Ch)We=v-&yYM#56puMAMm?N&4hEyxs5=wdaFY zi!^NZS(Kv9Qnp20j3}bX|3c1gfW3AonI`FGi+m<1DRO&q5VmQX^_rV5PUfKP2QG$7 zA%MqdL0f6qsW|i-!PJfKTmC~iZOr{qQXlKoz#%AFOVDDop&jk|A);gWL8K0Nih4~? z>P9jUy{q{2$6XrvuYnwUJ~Ctj7^Sw?1My7Y_n2Z5;N=5m3EJo;uj$O+*xpkFYJU&b~C0nb7=wiBboXp`5Aje$1) z;Zq#ucfXXf4#`O!7xZA(p>SKA^n8ljUNlNx z)haWNuoGaj+Lb|$;JUm2aw0If?}ZV2-e^8Bb0oK;6J7yKI7d4Qx+aD>wow@=le?Xa2D63iGBwmV`S3_zFF0y z=9gTC=L-rJ6Swu`(I}_XEh#Zi-V0gIS?t&bnE?+hXvu8GeGn`=xo7J5UeI!`_3Zn= z&nTyb-9JR+pACk#6VtN;QCmVAC4jBOb=+6aNpV`=t6S})kY(knfYdoTTRsl-{H;!V z!2IdaJD`GcqUup>jis_I?SP$+OSQp0g3s61s?bWn`gd1q^S*N%5MC$VJ{TBi>kl*e zJMitjvRNVg#WR36P2dknSk;YA!F%zZhCY!a%yZ#=SlaKZ&uiuUM_AUfkL|&`4BlgU z9-iA5$=b8N(N4`+3`9Ia#o7H`f(IaGIDLkK9e>x~!|=>p&))7Bybv!}CIRIZq8NCC z9x8)C$w%(Z{<~^lfd};~yMN2WTl7apG+@}vWh=ZGAA1gfV+O}$jA7s{ES@IwE@vl9 zuTNYa=*x@>`wJ9-Iev~k|CeJByg*pr;*E!a-*%9ITV;h0VBWqKG{Bd!Q{*pD59T6b zWBr%+G+ZQ1TYWKvf%1_6_>KL256rvi2t0M6JkX8$C-gr}|1*z&j`%Nn{2z_ep%CT? Y(CN~x_H*xBo;DHQD7_H?0O6A-jL!l9 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 Y(CN