Skip to content

Commit

Permalink
Merge pull request #326 from openscad/issue217
Browse files Browse the repository at this point in the history
Issue217
  • Loading branch information
kintel committed Apr 27, 2013
2 parents f0ee85e + 5f10c9f commit 6b3daa7
Show file tree
Hide file tree
Showing 23 changed files with 2,091 additions and 42 deletions.
17 changes: 15 additions & 2 deletions src/dxfdim.cc
Expand Up @@ -49,6 +49,9 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &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());
Expand All @@ -63,9 +66,16 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &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;
Expand Down Expand Up @@ -133,6 +143,9 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &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());
Expand Down
2 changes: 1 addition & 1 deletion src/import.cc
Expand Up @@ -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) );
Expand Down
2 changes: 1 addition & 1 deletion src/linearextrude.cc
Expand Up @@ -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,
Expand Down
22 changes: 19 additions & 3 deletions src/module.cc
Expand Up @@ -32,6 +32,9 @@
#include "function.h"
#include "printutils.h"

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#include "boosty.h"
#include <boost/foreach.hpp>
#include <sstream>
#include <sys/stat.h>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++) {
Expand Down
8 changes: 7 additions & 1 deletion src/module.h
Expand Up @@ -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();
Expand All @@ -19,6 +19,10 @@ class ModuleInstantiation
class AbstractNode *evaluate(const class Context *ctx) const;
std::vector<AbstractNode*> 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; }
Expand All @@ -35,6 +39,7 @@ class ModuleInstantiation
bool tag_background;
protected:
std::string modname;
std::string modpath;

friend class Module;
};
Expand All @@ -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;

Expand Down
50 changes: 25 additions & 25 deletions src/parser.y
Expand Up @@ -58,6 +58,12 @@ int lexerlex(void);
std::vector<Module*> 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;
Expand All @@ -77,6 +83,7 @@ public:
class Value *value;
class Expression *expr;
class ModuleInstantiation *inst;
std::vector<ModuleInstantiation*> *instvec;
class IfElseModuleInstantiation *ifelse;
class ArgContainer *arg;
class ArgsContainer *args;
Expand Down Expand Up @@ -117,8 +124,8 @@ public:
%type <inst> module_instantiation
%type <ifelse> if_statement
%type <ifelse> ifelse_statement
%type <inst> children_instantiation
%type <inst> module_instantiation_list
%type <instvec> children_instantiation
%type <instvec> module_instantiation_list
%type <inst> single_module_instantiation

%type <args> arguments_call
Expand Down Expand Up @@ -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<ModuleInstantiation*>;
if ($1) {
$$->children.push_back($1);
$$->push_back($1);
}
} |
'{' module_instantiation_list '}' {
Expand All @@ -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;
} ;

Expand All @@ -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;
} ;

Expand All @@ -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 {
Expand All @@ -260,12 +265,12 @@ module_instantiation:

module_instantiation_list:
/* empty */ {
$$ = new ModuleInstantiation();
$$ = new std::vector<ModuleInstantiation*>;
} |
module_instantiation_list module_instantiation {
$$ = $1;
if ($$) {
if ($2) $$->children.push_back($2);
if ($2) $$->push_back($2);
} else {
delete $2;
}
Expand All @@ -276,6 +281,7 @@ single_module_instantiation:
$$ = new ModuleInstantiation($1);
$$->argnames = $3->argnames;
$$->argexpr = $3->argexpr;
$$->setPath(parser_source_path);
free($1);
delete $3;
}
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/rotateextrude.cc
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/surface.cc
Expand Up @@ -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) {
Expand Down
7 changes: 7 additions & 0 deletions 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);
3 changes: 3 additions & 0 deletions testdata/scad/misc/localfiles-test.scad
@@ -0,0 +1,3 @@
use <localfiles_dir/localfiles_module.scad>

localfiles_module();
2 changes: 2 additions & 0 deletions testdata/scad/misc/localfiles_dir/localfile.dat
@@ -0,0 +1,2 @@
0 1
2 3

0 comments on commit 6b3daa7

Please sign in to comment.