Merge branch 'master' of github.com:openscad/openscad into issue406

issue406
Don Bright 2014-02-17 20:34:06 -06:00
commit 3a77956bdd
17 changed files with 278 additions and 53 deletions

View File

@ -50,7 +50,7 @@ bool ModuleCache::evaluate(const std::string &filename, FileModule *&module)
bool valid = (stat(filename.c_str(), &st) == 0);
// If file isn't there, just return and let the cache retain the old module
if (!valid) return NULL;
if (!valid) return false;
// If the file is present, we'll always cache some result
std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size);
@ -96,7 +96,7 @@ bool ModuleCache::evaluate(const std::string &filename, FileModule *&module)
std::ifstream ifs(filename.c_str());
if (!ifs.is_open()) {
PRINTB("WARNING: Can't open library file '%s'\n", filename);
return NULL;
return false;
}
textbuf << ifs.rdbuf();
}

View File

@ -1,6 +1,11 @@
#include "PlatformUtils.h"
#import <Foundation/Foundation.h>
std::string PlatformUtils::pathSeparatorChar()
{
return ":";
}
std::string PlatformUtils::documentsPath()
{
return std::string([[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] UTF8String]);

View File

@ -1,6 +1,11 @@
#include "PlatformUtils.h"
#include "boosty.h"
std::string PlatformUtils::pathSeparatorChar()
{
return ":";
}
std::string PlatformUtils::documentsPath()
{
const char *home = getenv("HOME");

View File

@ -6,6 +6,11 @@
#endif
#include <shlobj.h>
std::string PlatformUtils::pathSeparatorChar()
{
return ";";
}
// convert from windows api w_char strings (usually utf16) to utf8 std::string
std::string winapi_wstr_to_utf8( std::wstring wstr )
{

View File

@ -1,7 +1,9 @@
#include <glib.h>
#include "PlatformUtils.h"
#include "boosty.h"
#include <glib.h>
extern std::vector<std::string> librarypath;
bool PlatformUtils::createLibraryPath()
{
@ -142,6 +144,8 @@ std::string PlatformUtils::info()
std::string cgal_2d_kernelEx = "";
#endif // ENABLE_CGAL
const char *env_path = getenv("OPENSCADPATH");
s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION)
<< "\nCompiler, build date: " << compiler_info << ", " << __DATE__
<< "\nBoost version: " << BOOST_LIB_VERSION
@ -151,7 +155,12 @@ std::string PlatformUtils::info()
<< "\nQt version: " << qtVersion
<< "\nMingW build: " << mingwstatus
<< "\nGLib version: " << GLIB_MAJOR_VERSION << "." << GLIB_MINOR_VERSION << "." << GLIB_MICRO_VERSION
<< "\nOPENSCADPATH: " << getenv("OPENSCADPATH") << "\n"
;
<< "\nOPENSCADPATH: " << (env_path == NULL ? "<not set>" : env_path)
<< "\nOpenSCAD library path:\n";
for (std::vector<std::string>::iterator it = librarypath.begin();it != librarypath.end();it++) {
s << " " << *it << "\n";
}
return s.str();
}

View File

@ -11,6 +11,15 @@ namespace PlatformUtils {
std::string backupPath();
bool createBackupPath();
std::string info();
/**
* Single character separating path specifications in a list
* (e.g. OPENSCADPATH). On Windows that's ';' and on most other
* systems ':'.
*
* @return the path separator
*/
std::string pathSeparatorChar();
}
#endif

View File

@ -36,6 +36,10 @@
#include "printutils.h"
#include <boost/foreach.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
using boost::math::isnan;
using boost::math::isinf;
/*
Random numbers
@ -598,6 +602,71 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx)
return Value(Module::stack_element(s - 1 - n));
}
Value builtin_norm(const Context *, const EvalContext *evalctx)
{
if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::VECTOR) {
double sum = 0;
Value::VectorType v = evalctx->getArgValue(0).toVector();
for (size_t i = 0; i < v.size(); i++)
if (v[i].type() == Value::NUMBER)
sum += pow(v[i].toDouble(),2);
else {
PRINT(" WARNING: Incorrect arguments to norm()");
return Value();
}
return Value(sqrt(sum));
}
return Value();
}
Value builtin_cross(const Context *, const EvalContext *evalctx)
{
if (evalctx->numArgs() != 2) {
PRINT("WARNING: Invalid number of parameters for cross()");
return Value();
}
Value arg0 = evalctx->getArgValue(0);
Value arg1 = evalctx->getArgValue(1);
if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) {
PRINT("WARNING: Invalid type of parameters for cross()");
return Value();
}
Value::VectorType v0 = arg0.toVector();
Value::VectorType v1 = arg1.toVector();
if ((v0.size() != 3) || (v1.size() != 3)) {
PRINT("WARNING: Invalid vector size of parameter for cross()");
return Value();
}
for (unsigned int a = 0;a < 3;a++) {
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) {
PRINT("WARNING: Invalid value in parameter vector for cross()");
return Value();
}
double d0 = v0[a].toDouble();
double d1 = v1[a].toDouble();
if (isnan(d0) || isnan(d1)) {
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
return Value();
}
if (isinf(d0) || isinf(d1)) {
PRINT("WARNING: Invalid value (INF) in parameter vector for cross()");
return Value();
}
}
double x = v0[1].toDouble() * v1[2].toDouble() - v0[2].toDouble() * v1[1].toDouble();
double y = v0[2].toDouble() * v1[0].toDouble() - v0[0].toDouble() * v1[2].toDouble();
double z = v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble();
Value::VectorType result;
result.push_back(Value(x));
result.push_back(Value(y));
result.push_back(Value(z));
return Value(result);
}
void register_builtin_functions()
{
Builtins::init("abs", new BuiltinFunction(&builtin_abs));
@ -627,5 +696,7 @@ void register_builtin_functions()
Builtins::init("search", new BuiltinFunction(&builtin_search));
Builtins::init("version", new BuiltinFunction(&builtin_version));
Builtins::init("version_num", new BuiltinFunction(&builtin_version_num));
Builtins::init("norm", new BuiltinFunction(&builtin_norm));
Builtins::init("cross", new BuiltinFunction(&builtin_cross));
Builtins::init("parent_module", new BuiltinFunction(&builtin_parent_module));
}

View File

@ -453,16 +453,12 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
#include <QApplication>
#include <QString>
#include <QDir>
#include <QFileInfo>
// Only if "fileName" is not absolute, prepend the "absoluteBase".
static QString assemblePath(const fs::path& absoluteBaseDir,
static QString assemblePath(const fs::path& absoluteBase,
const string& fileName) {
if (fileName.empty()) return "";
QString qsDir( boosty::stringy( absoluteBaseDir ).c_str() );
QString qsFile( fileName.c_str() );
QFileInfo info( qsDir, qsFile ); // if qsfile is absolute, dir is ignored.
return info.absoluteFilePath();
return fileName.empty() ? "" : QDir(QString::fromStdString((const string&) absoluteBase))
.absoluteFilePath(QString::fromStdString(fileName));
}
bool QtUseGUI()

View File

@ -90,17 +90,15 @@ fs::path find_valid_path(const fs::path &sourcepath,
void parser_init(const std::string &applicationpath)
{
// Add paths from OPENSCADPATH before adding built-in paths
// Add paths from OPENSCADPATH before adding built-in paths
const char *openscadpaths = getenv("OPENSCADPATH");
if (openscadpaths) {
std::string paths(openscadpaths);
typedef boost::split_iterator<std::string::iterator> string_split_iterator;
for (string_split_iterator it =
make_split_iterator(paths, first_finder(":", boost::is_iequal()));
it != string_split_iterator();
++it) {
add_librarydir(boosty::absolute(fs::path(boost::copy_range<std::string>(*it))).string());
}
std::string sep = PlatformUtils::pathSeparatorChar();
typedef boost::split_iterator<std::string::iterator> string_split_iterator;
for (string_split_iterator it = boost::make_split_iterator(paths, boost::first_finder(sep, boost::is_iequal())); it != string_split_iterator(); ++it) {
add_librarydir(boosty::absolute(fs::path(boost::copy_range<std::string>(*it))).string());
}
}
// This is the built-in user-writable library path

View File

@ -28,6 +28,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// want to use system definitions instead like #include <system.h>
#ifndef WIFEXITED
#define WIFEXITED(S) (((S) & 0xff) == 0)
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(S) (((S) >> 8) & 0xff)
#endif
#define MAXCMDLEN 64000
#define BUFFSIZE 42
@ -36,57 +45,64 @@ int main( int argc, char * argv[] )
FILE *cmd_stdout;
char cmd[MAXCMDLEN];
char buffer[BUFFSIZE];
char *fgets_result;
int eof = 0;
int pclose_result;
int i;
const char * argchar;
int result = 0;
int quotify_arg = 0;
unsigned n; // total number of characters in cmd
static const char exe_str[] = "openscad.exe";
static const char redirect_str[] = " 2>&1"; // capture stderr and stdout
strcat( cmd, "\0" );
strcat( cmd, "openscad.exe" );
memcpy(cmd, exe_str, (n = sizeof(exe_str)-1)); // without \0
for ( i = 1 ; i < argc ; ++i ) {
quotify_arg = 0;
for ( argchar = argv[i]; *argchar!=0; argchar++ ) {
if ((char)(*argchar)==' ') quotify_arg = 1;
register char *s;
/*bool*/ int quote;
cmd[n++] = ' ';
// MS Windows special characters need quotation
// See issues #440, #441 & #479
quote = NULL != strpbrk((s = argv[i]), " \"&'<>^|\t");
if (quote) cmd[n++] = '"';
while (*s) { // copy & check
if ('"' == *s) cmd[n++] = *s; // duplicate it
cmd[n++] = *s++;
if (n >= MAXCMDLEN-sizeof(redirect_str)) {
fprintf(stderr, "Command line length exceeds limit of %d\n", MAXCMDLEN);
return 1;
}
}
strcat( cmd, " " );
if (quotify_arg) strcat( cmd, "\"");
strcat( cmd, argv[i] );
if (quotify_arg) strcat( cmd, "\"");
if (quote) cmd[n++] = '"';
}
strcat( cmd, " 2>&1"); // capture stderr and stdout
printf("openscad.com: running command: %s\n", cmd );
memcpy(&cmd[n], redirect_str, sizeof(redirect_str)); // including \0
cmd_stdout = _popen( cmd, "rt" );
if ( cmd_stdout == NULL ) {
printf( "Error opening _popen for command: %s", cmd );
perror( "Error message:" );
fprintf(stderr, "Error opening _popen for command: %s", cmd );
perror( "Error message" );
return 1;
}
while ( !eof )
{
fgets_result = fgets( buffer, BUFFSIZE, cmd_stdout );
if ( fgets_result == NULL ) {
for(;;) {
if (NULL == fgets(buffer, BUFFSIZE, cmd_stdout)) {
if ( ferror( cmd_stdout ) ) {
printf("Error reading from stdout of %s\n", cmd);
fprintf(stderr, "Error reading from stdout of %s\n", cmd);
result = 1;
}
if ( feof( cmd_stdout ) ) {
eof = 1;
break;
}
} else {
fprintf( stdout, "%s", buffer );
fputs(buffer, stdout);
}
}
pclose_result = _pclose( cmd_stdout );
if ( pclose_result < 0 ) {
perror("Error while closing stdout for command:");
// perror() applicable with return value of -1 only!
// Avoid stupid "Error: No Error" message
if (pclose_result == -1) {
perror("Error while closing stdout for command");
result = 1;
} else if (!result) {
result = WIFEXITED(pclose_result) ? WEXITSTATUS(pclose_result) : 1;
}
return result;
}

View File

@ -0,0 +1,17 @@
echo(cross([2, 3, 4], [5, 6, 7]));
echo(cross([2, 1, -3], [0, 4, 5]));
echo(cross([2, 1, -3], cross([2, 3, 4], [5, 6, 7])));
echo(cross([2, 0/0, -3], [0, 4, 5]));
echo(cross([2, 1/0, -3], [0, 4, 5]));
echo(cross([2, -1/0, -3], [0, 4, 5]));
echo(cross(0));
echo(cross(0, 1));
echo(cross(0, "a"));
echo(cross(0, 1, 3));
echo(cross([0], [1]));
echo(cross([1, 2, 3], [1, 2]));
echo(cross([1, 2, 3], [1, 2, "a"]));
echo(cross([1, 2, 3], [1, 2, [0]]));
echo(cross([1, 2, 3], [1, 2, [1:2]]));

27
testdata/scad/functions/norm-tests.scad vendored Normal file
View File

@ -0,0 +1,27 @@
u=undef;
echo(norm([]));
echo(norm([1]));
echo(norm([1,2]));
echo(norm([1,2,3]));
echo(norm([1,2,3,4]));
echo(norm());
echo(norm([1,2,0/0]));
echo(norm([1,2,1/0]));
echo(norm([1,2,-1/0]));
echo(norm(""));
echo(norm("abcd"));
echo(norm(true));
echo(norm([1:4]));
echo(norm([1, 2, "a"]));
echo(norm([1, 2, []]));
echo(norm([1, 2, [1]]));
echo(norm([1, 2, [1:3]]));
echo(norm([[1,2,3,4],[1,2,3],[1,2],[1]]));
echo(norm(u));
echo(norm(u, u));
echo(norm(a, a));

4
testdata/scad/misc/override.scad vendored Normal file
View File

@ -0,0 +1,4 @@
// Used to test variable override with the -D parameter
a = 1;
b = 2;
echo(a,b);

View File

@ -540,6 +540,8 @@ set(CORE_SOURCES
../src/fileutils.cc
../src/progress.cc
../src/boost-utils.cc
../src/PlatformUtils.cc
../src/${PLATFORMUTILS_SOURCE}
${FLEX_OpenSCADlexer_OUTPUTS}
${BISON_OpenSCADparser_OUTPUTS})
@ -586,13 +588,11 @@ set(OFFSCREEN_SOURCES
../src/ThrownTogetherRenderer.cc
../src/renderer.cc
../src/render.cc
../src/PlatformUtils.cc
../src/${PLATFORMUTILS_SOURCE}
../src/OpenCSGRenderer.cc)
add_library(tests-core STATIC ${CORE_SOURCES})
target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} ${COCOA_LIBRARY})
add_library(tests-common STATIC ${COMMON_SOURCES})
target_link_libraries(tests-common tests-core)
@ -625,14 +625,14 @@ target_link_libraries(csgtexttest tests-nocgal ${TESTS-NOCGAL-LIBRARIES})
#
add_executable(cgalcachetest cgalcachetest.cc)
set_target_properties(cgalcachetest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${COCOA_LIBRARY})
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY})
#
# openscad no-qt
#
add_executable(openscad_nogui ../src/openscad.cc)
set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL -DENABLE_OPENCSG ${CGAL_CXX_FLAGS_INIT}")
target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ${APP_SERVICES_LIBRARY})
target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY})
#
# GUI binary tests
@ -1010,7 +1010,16 @@ add_cmdline_test(openscad-nonascii EXE ${OPENSCAD_BINPATH} ARGS -o
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/sfære.scad)
# Image output
# Variable override (-D arg)
# Override simple variable
add_cmdline_test(openscad-override EXE ${OPENSCAD_BINPATH}
ARGS -D a=3$<SEMICOLON> -o
SUFFIX echo
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/override.scad)
# Image output parameters
add_cmdline_test(openscad-imgsize EXE ${OPENSCAD_BINPATH}
ARGS --imgsize 100,100 -o
SUFFIX png

View File

@ -0,0 +1,27 @@
ECHO: [-3, 6, -3]
ECHO: [17, -10, 8]
ECHO: [15, 15, 15]
WARNING: Invalid value (NaN) in parameter vector for cross()
ECHO: undef
WARNING: Invalid value (INF) in parameter vector for cross()
ECHO: undef
WARNING: Invalid value (INF) in parameter vector for cross()
ECHO: undef
WARNING: Invalid number of parameters for cross()
ECHO: undef
WARNING: Invalid type of parameters for cross()
ECHO: undef
WARNING: Invalid type of parameters for cross()
ECHO: undef
WARNING: Invalid number of parameters for cross()
ECHO: undef
WARNING: Invalid vector size of parameter for cross()
ECHO: undef
WARNING: Invalid vector size of parameter for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef

View File

@ -0,0 +1,26 @@
ECHO: 0
ECHO: 1
ECHO: 2.2360679775
ECHO: 3.74165738677
ECHO: 5.47722557505
ECHO: undef
ECHO: nan
ECHO: inf
ECHO: inf
ECHO: undef
ECHO: undef
ECHO: undef
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
ECHO: undef
ECHO: undef
ECHO: undef

View File

@ -0,0 +1 @@
ECHO: 3, 2