diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CGALEvaluator.cc | 6 | ||||
-rw-r--r-- | src/Preferences.cc | 18 | ||||
-rw-r--r-- | src/context.cc | 7 | ||||
-rw-r--r-- | src/dxfdim.cc | 17 | ||||
-rw-r--r-- | src/func.cc | 18 | ||||
-rw-r--r-- | src/handle_dep.cc | 17 | ||||
-rw-r--r-- | src/highlighter.cc | 2 | ||||
-rw-r--r-- | src/import.cc | 85 | ||||
-rw-r--r-- | src/lexer.l | 104 | ||||
-rw-r--r-- | src/linearextrude.cc | 2 | ||||
-rw-r--r-- | src/mainwin.cc | 3 | ||||
-rw-r--r-- | src/module.h | 2 | ||||
-rw-r--r-- | src/openscad.cc | 52 | ||||
-rw-r--r-- | src/openscad.h | 4 | ||||
-rw-r--r-- | src/parser.y | 31 | ||||
-rw-r--r-- | src/parsersettings.cc | 27 | ||||
-rw-r--r-- | src/parsersettings.h | 11 | ||||
-rw-r--r-- | src/polyset.cc | 1 | ||||
-rw-r--r-- | src/rotateextrude.cc | 2 | ||||
-rw-r--r-- | src/surface.cc | 55 | ||||
-rw-r--r-- | src/value.cc | 12 |
21 files changed, 263 insertions, 213 deletions
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index a6b2f06..88d1f00 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -32,7 +32,6 @@ #include <sstream> #include <iostream> #include <assert.h> -#include <QRegExp> #include <boost/foreach.hpp> #include <boost/unordered_map.hpp> @@ -86,6 +85,11 @@ void CGALEvaluator::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedr // union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad std::string opstr = op == CGE_UNION ? "union" : op == CGE_INTERSECTION ? "intersection" : op == CGE_DIFFERENCE ? "difference" : op == CGE_MINKOWSKI ? "minkowski" : "UNKNOWN"; PRINTF("CGAL error in CGAL_Nef_polyhedron's %s operator: %s", opstr.c_str(), e.what()); + + // Minkowski errors can result in corrupt polyhedrons + if (op == CGE_MINKOWSKI) { + target = src; + } } CGAL::set_error_behaviour(old_behaviour); } diff --git a/src/Preferences.cc b/src/Preferences.cc index 4c43f2d..e05106b 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -47,16 +47,24 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) // Setup default settings this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text(); + this->defaultmap["advanced/opencsg_show_warning"] = true; + this->defaultmap["advanced/enable_opencsg_opengl1x"] = true; + + // Setup default font (Try to use a nice monospace font) + QString fontfamily; #ifdef Q_WS_X11 - this->defaultmap["editor/fontfamily"] = "Mono"; + fontfamily = "Mono"; #elif defined (Q_WS_WIN) - this->defaultmap["editor/fontfamily"] = "Console"; + fontfamily = "Console"; #elif defined (Q_WS_MAC) - this->defaultmap["editor/fontfamily"] = "Monaco"; + fontfamily = "Monaco"; #endif + QFont font; + font.setStyleHint(QFont::TypeWriter); + font.setFamily(fontfamily); // this runs Qt's font matching algorithm + QString found_family(QFontInfo(font).family()); + this->defaultmap["editor/fontfamily"] = found_family; this->defaultmap["editor/fontsize"] = 12; - this->defaultmap["advanced/opencsg_show_warning"] = true; - this->defaultmap["advanced/enable_opencsg_opengl1x"] = true; // Toolbar QActionGroup *group = new QActionGroup(this); diff --git a/src/context.cc b/src/context.cc index f636b05..354195f 100644 --- a/src/context.cc +++ b/src/context.cc @@ -30,9 +30,9 @@ #include "module.h" #include "builtin.h" #include "printutils.h" -#include <QFileInfo> -#include <QDir> #include <boost/foreach.hpp> +#include <boost/filesystem.hpp> +using namespace boost::filesystem; std::vector<const Context*> Context::ctx_stack; @@ -176,8 +176,7 @@ AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst) const std::string Context::getAbsolutePath(const std::string &filename) const { if (!filename.empty()) { - return QFileInfo(QDir(QString::fromStdString(this->document_path)), - QString::fromStdString(filename)).absoluteFilePath().toStdString(); + return absolute(path(this->document_path) / filename).string(); } else { return filename; diff --git a/src/dxfdim.cc b/src/dxfdim.cc index c696226..44b5d73 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -33,10 +33,11 @@ #include "context.h" #include "mathc99.h" -#include <QDateTime> -#include <QFileInfo> #include <sstream> +#include <boost/filesystem.hpp> +using namespace boost::filesystem; + boost::unordered_map<std::string,Value> dxf_dim_cache; boost::unordered_map<std::string,Value> dxf_cross_cache; @@ -62,12 +63,10 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnam name = args[i].text; } - QFileInfo fileInfo(QString::fromStdString(filename)); - std::stringstream keystream; keystream << filename << "|" << layername << "|" << name << "|" << xorigin - << "|" << yorigin <<"|" << scale << "|" << fileInfo.lastModified().toTime_t() - << "|" << fileInfo.size(); + << "|" << yorigin <<"|" << scale << "|" << last_write_time(filename) + << "|" << file_size(filename); std::string key = keystream.str(); if (dxf_dim_cache.find(key) != dxf_dim_cache.end()) return dxf_dim_cache.find(key)->second; @@ -144,12 +143,10 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argn args[i].getnum(scale); } - QFileInfo fileInfo(QString::fromStdString(filename)); - std::stringstream keystream; keystream << filename << "|" << layername << "|" << xorigin << "|" << yorigin - << "|" << scale << "|" << fileInfo.lastModified().toTime_t() - << "|" << fileInfo.size(); + << "|" << scale << "|" << last_write_time(filename) + << "|" << file_size(filename); std::string key = keystream.str(); if (dxf_cross_cache.find(key) != dxf_cross_cache.end()) diff --git a/src/func.cc b/src/func.cc index 1138173..6686cb9 100644 --- a/src/func.cc +++ b/src/func.cc @@ -96,24 +96,14 @@ std::string BuiltinFunction::dump(const std::string &indent, const std::string & return dump.str(); } -static double deg2rad(double x) +static inline double deg2rad(double x) { - while (x < 0.0) - x += 360.0; - while (x >= 360.0) - x -= 360.0; - x = x * M_PI * 2.0 / 360.0; - return x; + return x * M_PI / 180.0; } -static double rad2deg(double x) +static inline double rad2deg(double x) { - x = x * 360.0 / (M_PI * 2.0); - while (x < 0.0) - x += 360.0; - while (x >= 360.0) - x -= 360.0; - return x; + return x * 180.0 / M_PI; } Value builtin_abs(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) diff --git a/src/handle_dep.cc b/src/handle_dep.cc index d4380f5..d642555 100644 --- a/src/handle_dep.cc +++ b/src/handle_dep.cc @@ -1,27 +1,28 @@ #include "handle_dep.h" #include <string> #include <sstream> -#include <QString> -#include <QDir> -#include <QSet> #include <stdlib.h> // for system() #include <boost/unordered_set.hpp> #include <boost/foreach.hpp> +#include <boost/regex.hpp> +#include <boost/filesystem.hpp> +using namespace boost::filesystem; boost::unordered_set<std::string> dependencies; const char *make_command = NULL; void handle_dep(const std::string &filename) { - if (filename[0] == '/') + path filepath(filename); + if (filepath.is_absolute()) { dependencies.insert(filename); + } else { - QString dep = QDir::currentPath() + QString("/") + QString::fromStdString(filename); - dependencies.insert(dep.toStdString()); + dependencies.insert((current_path() / filepath).string()); } - if (!QFile(QString::fromStdString(filename)).exists() && make_command) { + if (!exists(filepath) && make_command) { std::stringstream buf; - buf << make_command << " '" << QString::fromStdString(filename).replace("'", "'\\''").toUtf8().data() << "'"; + buf << make_command << " '" << boost::regex_replace(filename, boost::regex("'"), "'\\''") << "'"; system(buf.str().c_str()); // FIXME: Handle error } } diff --git a/src/highlighter.cc b/src/highlighter.cc index 759826c..64ea980 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -25,7 +25,7 @@ */ #include "highlighter.h" -#include "openscad.h" // extern int parser_error_pos; +#include "parsersettings.h" // extern int parser_error_pos; #ifdef _QCODE_EDIT_ Highlighter::Highlighter(QDocument *parent) diff --git a/src/import.cc b/src/import.cc index b77c120..435d06d 100644 --- a/src/import.cc +++ b/src/import.cc @@ -39,13 +39,15 @@ #include "cgalutils.h" #endif -#include <QFile> -#include <QRegExp> -#include <QStringList> #include <sys/types.h> #include <fstream> #include <sstream> #include <assert.h> +#include <boost/algorithm/string.hpp> +#include <boost/regex.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> +using namespace boost::filesystem; #include <boost/assign/std/vector.hpp> using namespace boost::assign; // bring 'operator+=()' into scope @@ -79,10 +81,10 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati std::string filename = c.getAbsolutePath(v.text); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { - QFileInfo fi(QString::fromStdString(filename)); - if (fi.suffix().toLower() == "stl") actualtype = TYPE_STL; - else if (fi.suffix().toLower() == "off") actualtype = TYPE_OFF; - else if (fi.suffix().toLower() == "dxf") actualtype = TYPE_DXF; + std::string ext = boost::algorithm::to_lower_copy(path(filename).extension().string()); + if (ext == ".stl") actualtype = TYPE_STL; + else if (ext == ".off") actualtype = TYPE_OFF; + else if (ext == ".dxf") actualtype = TYPE_DXF; } ImportNode *node = new ImportNode(inst, actualtype); @@ -110,48 +112,57 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati return node; } -PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *evaluator) const +PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const { PolySet *p = NULL; if (this->type == TYPE_STL) { handle_dep(this->filename); - QFile f(QString::fromStdString(this->filename)); - if (!f.open(QIODevice::ReadOnly)) { + std::ifstream f(this->filename.c_str()); + if (!f.good()) { PRINTF("WARNING: Can't open import file `%s'.", this->filename.c_str()); return p; } p = new PolySet(); - QByteArray data = f.read(5); - if (data.size() == 5 && QString(data) == QString("solid")) - { + + boost::regex ex_sfe("solid|facet|endloop"); + boost::regex ex_outer("outer loop"); + boost::regex ex_vertex("vertex"); + boost::regex ex_vertices("\\s*vertex\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)"); + + char data[5]; + f.read(data, 5); + if (!f.eof() && !memcmp(data, "solid", 5)) { int i = 0; double vdata[3][3]; - QRegExp splitre = QRegExp("\\s*(vertex)?\\s+"); - f.readLine(); - while (!f.atEnd()) - { - QString line = QString(f.readLine()).remove("\n").remove("\r"); - if (line.contains("solid") || line.contains("facet") || line.contains("endloop")) + std::string line; + std::getline(f, line); + while (!f.eof()) { + + std::getline(f, line); + boost::trim(line); + if (boost::regex_search(line, ex_sfe)) { continue; - if (line.contains("outer loop")) { + } + if (boost::regex_search(line, ex_outer)) { i = 0; continue; } - if (line.contains("vertex")) { - QStringList tokens = line.split(splitre); - bool ok[3] = { false, false, false }; - if (tokens.size() == 4) { - vdata[i][0] = tokens[1].toDouble(&ok[0]); - vdata[i][1] = tokens[2].toDouble(&ok[1]); - vdata[i][2] = tokens[3].toDouble(&ok[2]); + boost::smatch results; + if (boost::regex_search(line, results, ex_vertices)) { + try { + for (int v=0;v<3;v++) { + vdata[i][v] = boost::lexical_cast<double>(results[v+1]); + } } - if (!ok[0] || !ok[1] || !ok[2]) { - PRINTF("WARNING: Can't parse vertex line `%s'.", line.toAscii().data()); + catch (boost::bad_lexical_cast &blc) { + PRINTF("WARNING: Can't parse vertex line `%s'.", line.c_str()); i = 10; - } else if (++i == 3) { + continue; + } + if (++i == 3) { p->append_poly(); p->append_vertex(vdata[0][0], vdata[0][1], vdata[0][2]); p->append_vertex(vdata[1][0], vdata[1][1], vdata[1][2]); @@ -162,7 +173,7 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *evaluator) const } else { - f.read(80-5+4); + f.ignore(80-5+4); while (1) { #ifdef _MSC_VER #pragma pack(push,1) @@ -177,17 +188,17 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *evaluator) const #ifdef __GNUC__ __attribute__ ((packed)) #endif - data; + stldata; #ifdef _MSC_VER #pragma pack(pop) #endif - if (f.read((char*)&data, sizeof(data)) != sizeof(data)) - break; + f.read((char*)&stldata, sizeof(stldata)); + if (f.eof()) break; p->append_poly(); - p->append_vertex(data.x1, data.y1, data.z1); - p->append_vertex(data.x2, data.y2, data.z2); - p->append_vertex(data.x3, data.y3, data.z3); + p->append_vertex(stldata.x1, stldata.y1, stldata.z1); + p->append_vertex(stldata.x2, stldata.y2, stldata.z2); + p->append_vertex(stldata.x3, stldata.y3, stldata.z3); } } } diff --git a/src/lexer.l b/src/lexer.l index 07819b2..1b776d3 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -27,13 +27,14 @@ %{ #include "handle_dep.h" -#include "openscad.h" // librarydir #include "printutils.h" +#include "parsersettings.h" #include "parser_yacc.h" -#include <QStack> -#include <QFileInfo> -#include <QDir> #include <assert.h> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> +using namespace boost::filesystem; //isatty for visual c++ and mingw-cross-env #if defined __WIN32__ && ! defined _MSC_VER @@ -44,7 +45,7 @@ extern "C" int __cdecl _isatty(int _FileHandle); #define isatty _isatty #endif -QString* stringcontents; +std::string stringcontents; int lexerget_lineno(void); #ifdef __GNUC__ static void yyunput(int, char*) __attribute__((unused)); @@ -73,12 +74,12 @@ extern const char *parser_source_path; } void includefile(); -QDir sourcepath(); -QStack<QDir> path_stack; -QStack<FILE*> openfiles; +path sourcepath(); +std::vector<path> path_stack; +std::vector<FILE*> openfiles; -QString filename; -QString filepath; +std::string filename; +std::string filepath; %} @@ -87,6 +88,7 @@ QString filepath; %x comment string %x include +%x use D [0-9] E [Ee][+-]?{D}+ @@ -101,25 +103,27 @@ include[ \t\r\n>]*"<" { BEGIN(include); } } -use[ \t\r\n>]*"<"[^\t\r\n>]+">" { - QString filename(yytext); - filename.remove(QRegExp("^use[ \t\r\n>]*<")); - filename.remove(QRegExp(">$")); - QFileInfo finfo(QDir(parser_source_path), filename); - if (!finfo.exists()) { - finfo = QFileInfo(QDir(librarydir), filename); +use[ \t\r\n>]*"<" { BEGIN(use); } +<use>{ +[^\t\r\n>]+ { filename = yytext; } + ">" { + BEGIN(INITIAL); + path usepath = path(parser_source_path) / filename; + if (!exists(usepath)) { + usepath = librarydir / filename; } - handle_dep(finfo.absoluteFilePath().toStdString()); - parserlval.text = strdup(finfo.absoluteFilePath().toLocal8Bit()); + handle_dep(absolute(usepath).generic_string()); + parserlval.text = strdup(absolute(usepath).c_str()); return TOK_USE; + } } <<EOF>> { - if(!path_stack.empty()) - path_stack.pop(); + if(!path_stack.empty()) path_stack.pop_back(); if (yyin && yyin != stdin) { assert(!openfiles.empty()); - fclose(openfiles.pop()); + fclose(openfiles.back()); + openfiles.pop_back(); } yypop_buffer_state(); if (!YY_CURRENT_BUFFER) @@ -137,20 +141,19 @@ use[ \t\r\n>]*"<"[^\t\r\n>]+">" { {D}+{E}? | {D}*\.{D}+{E}? | -{D}+\.{D}*{E}? { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } +{D}+\.{D}*{E}? { parserlval.number = boost::lexical_cast<double>(yytext); return TOK_NUMBER; } "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } -\" { BEGIN(string); stringcontents = new QString(); } +\" { BEGIN(string); stringcontents.clear(); } <string>{ -\\n { stringcontents->append('\n'); } -\\t { stringcontents->append('\t'); } -\\r { stringcontents->append('\r'); } -\\\\ { stringcontents->append('\\'); } -\\\" { stringcontents->append('"'); } -[^\\\n\"]+ { stringcontents->append(lexertext); } +\\n { stringcontents += '\n'; } +\\t { stringcontents += '\t'; } +\\r { stringcontents += '\r'; } +\\\\ { stringcontents += '\\'; } +\\\" { stringcontents += '"'; } +[^\\\n\"]+ { stringcontents += lexertext; } \" { BEGIN(INITIAL); - parserlval.text = strdup(stringcontents->toLocal8Bit()); - delete stringcontents; + parserlval.text = strdup(stringcontents.c_str()); return TOK_STRING; } } @@ -171,12 +174,11 @@ use[ \t\r\n>]*"<"[^\t\r\n>]+">" { %% -QDir sourcepath() +path sourcepath() { - if(!path_stack.empty()) - return path_stack.top(); - - return QDir(parser_source_path); + if (!path_stack.empty()) return path_stack.back(); + + return path(parser_source_path); } /* @@ -186,29 +188,29 @@ QDir sourcepath() */ void includefile() { - if (filename.isEmpty()) return; + if (filename.empty()) return; - QDir dirinfo(sourcepath()); - if (!filepath.isEmpty()) { - dirinfo.cd(filepath); + path dirinfo = sourcepath(); + if (!filepath.empty()) { + dirinfo /= filepath; } - QFileInfo finfo(dirinfo, filename); - if (!finfo.exists()) { - finfo = QFileInfo(QFileInfo(QDir(librarydir), filepath).dir(), filename); + path finfo = dirinfo / filename; + if (!exists(finfo)) { + finfo = librarydir / filepath / filename; } filepath.clear(); - path_stack.push(dirinfo); + path_stack.push_back(dirinfo); - handle_dep(finfo.absoluteFilePath().toStdString()); - yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); + handle_dep(absolute(finfo).generic_string()); + yyin = fopen(absolute(finfo).c_str(), "r"); if (!yyin) { - PRINTA("WARNING: Can't open input file `%1'.", filename); - path_stack.pop(); + PRINTF("WARNING: Can't open input file `%s'.", filename.c_str()); + path_stack.pop_back(); return; } - openfiles.append(yyin); + openfiles.push_back(yyin); filename.clear(); yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); @@ -220,7 +222,7 @@ void includefile() */ void lexerdestroy() { - foreach (FILE *f, openfiles) fclose(f); + BOOST_FOREACH (FILE *f, openfiles) fclose(f); openfiles.clear(); path_stack.clear(); } diff --git a/src/linearextrude.cc b/src/linearextrude.cc index bc11629..775eeb0 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -38,8 +38,6 @@ #include <boost/assign/std/vector.hpp> using namespace boost::assign; // bring 'operator+=()' into scope -#include <QFileInfo> - class LinearExtrudeModule : public AbstractModule { public: diff --git a/src/mainwin.cc b/src/mainwin.cc index 0c5537f..57467fb 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -27,6 +27,7 @@ #include "PolySetCache.h" #include "MainWindow.h" #include "openscad.h" // examplesdir +#include "parsersettings.h" #include "Preferences.h" #include "printutils.h" #include "node.h" @@ -483,7 +484,7 @@ MainWindow::setFileName(const QString &filename) { if (filename.isEmpty()) { this->fileName.clear(); - this->root_ctx.setDocumentPath(currentdir.toStdString()); + this->root_ctx.setDocumentPath(currentdir); setWindowTitle("OpenSCAD - New Document[*]"); } else { diff --git a/src/module.h b/src/module.h index 557b7c5..6c6529b 100644 --- a/src/module.h +++ b/src/module.h @@ -65,7 +65,7 @@ public: void addChild(ModuleInstantiation *ch) { this->children.push_back(ch); } - static Module *compile_library(std::string filename); + static Module *compile_library(const std::string &filename); static void clear_library_cache(); typedef boost::unordered_map<std::string, class Module*> ModuleContainer; diff --git a/src/openscad.cc b/src/openscad.cc index c6dd7b6..04c25bb 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -35,6 +35,7 @@ #include "nodedumper.h" #include "printutils.h" #include "handle_dep.h" +#include "parsersettings.h" #include <string> #include <vector> @@ -47,12 +48,7 @@ #endif #include <QApplication> -#include <QFile> #include <QDir> -#include <QSet> -#include <QSettings> -#include <QTextStream> -#include <boost/program_options.hpp> #include <sstream> #ifdef Q_WS_MAC @@ -60,11 +56,15 @@ #include "AppleEvents.h" #endif +#include <boost/program_options.hpp> +#include <boost/filesystem.hpp> + #ifdef _MSC_VER #define snprintf _snprintf #endif namespace po = boost::program_options; +namespace fs = boost::filesystem; static void help(const char *progname) { @@ -83,9 +83,8 @@ static void version() } std::string commandline_commands; -QString currentdir; +std::string currentdir; QString examplesdir; -QString librarydir; using std::string; using std::vector; @@ -115,7 +114,7 @@ int main(int argc, char **argv) #ifdef Q_WS_MAC app.installEventFilter(new EventFilter(&app)); #endif - QDir original_path = QDir::current(); + fs::path original_path = fs::current_path(); // set up groups for QSettings QCoreApplication::setOrganizationName("OpenSCAD"); @@ -200,7 +199,7 @@ int main(int argc, char **argv) } #endif - currentdir = QDir::currentPath(); + currentdir = fs::current_path().generic_string(); QDir exdir(QApplication::instance()->applicationDirPath()); #ifdef Q_WS_MAC @@ -221,24 +220,7 @@ int main(int argc, char **argv) examplesdir = exdir.path(); } - QDir libdir(QApplication::instance()->applicationDirPath()); -#ifdef Q_WS_MAC - libdir.cd("../Resources"); // Libraries can be bundled - if (!libdir.exists("libraries")) libdir.cd("../../.."); -#elif defined(Q_OS_UNIX) - if (libdir.cd("../share/openscad/libraries")) { - librarydir = libdir.path(); - } else - if (libdir.cd("../../share/openscad/libraries")) { - librarydir = libdir.path(); - } else - if (libdir.cd("../../libraries")) { - librarydir = libdir.path(); - } else -#endif - if (libdir.cd("libraries")) { - librarydir = libdir.path(); - } + parser_init(QApplication::instance()->applicationDirPath().toStdString()); // Initialize global visitors NodeCache nodecache; @@ -276,7 +258,6 @@ int main(int argc, char **argv) ModuleInstantiation root_inst; AbstractNode *root_node; - QFileInfo fileInfo(filename); handle_dep(filename); FILE *fp = fopen(filename, "rt"); if (!fp) { @@ -292,18 +273,17 @@ int main(int argc, char **argv) } fclose(fp); text << commandline_commands; - root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false); + root_module = parse(text.str().c_str(), fs::absolute(filename).generic_string().c_str(), false); if (!root_module) exit(1); } - QDir::setCurrent(fileInfo.absolutePath()); - + fs::current_path(fs::path(filename).parent_path()); AbstractNode::resetIndexCounter(); root_node = root_module->evaluate(&root_ctx, &root_inst); tree.setRoot(root_node); if (csg_output_file) { - QDir::setCurrent(original_path.absolutePath()); + fs::current_path(original_path); std::ofstream fstream(csg_output_file); if (!fstream.is_open()) { PRINTF("Can't open file \"%s\" for export", csg_output_file); @@ -316,7 +296,7 @@ int main(int argc, char **argv) else { CGAL_Nef_polyhedron root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); - QDir::setCurrent(original_path.absolutePath()); + fs::current_path(original_path); if (deps_output_file) { if (!write_deps(deps_output_file, @@ -391,7 +371,7 @@ int main(int argc, char **argv) #endif QString qfilename; - if (filename) qfilename = QFileInfo(original_path, filename).absoluteFilePath(); + if (filename) qfilename = QString::fromStdString((original_path / filename).generic_string()); #if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ // turn on anti-aliasing @@ -405,8 +385,8 @@ int main(int argc, char **argv) vector<string> inputFiles; if (vm.count("input-file")) { inputFiles = vm["input-file"].as<vector<string> >(); - for (vector<string>::const_iterator i = inputFiles.begin()+1; i != inputFiles.end(); i++) { - new MainWindow(QFileInfo(original_path, i->c_str()).absoluteFilePath()); + for (vector<string>::const_iterator infile = inputFiles.begin()+1; infile != inputFiles.end(); infile++) { + new MainWindow(QString::fromStdString((original_path / *infile).generic_string())); } } app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); diff --git a/src/openscad.h b/src/openscad.h index 61aec0e..dab14cd 100644 --- a/src/openscad.h +++ b/src/openscad.h @@ -32,15 +32,13 @@ extern int get_fragments_from_r(double r, double fn, double fs, double fa); #include <string> extern std::string commandline_commands; -extern int parser_error_pos; #include <QString> // The CWD when application started. We shouldn't change CWD, but until we stop // doing this, use currentdir to get the original CWD. -extern QString currentdir; +extern std::string currentdir; extern QString examplesdir; -extern QString librarydir; #endif diff --git a/src/parser.y b/src/parser.y index 3dd933c..1c4a784 100644 --- a/src/parser.y +++ b/src/parser.y @@ -28,11 +28,6 @@ %{ -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QTextStream> - #include <sys/types.h> #include <sys/stat.h> #ifndef _MSC_VER @@ -46,6 +41,9 @@ #include "printutils.h" #include <sstream> #include <boost/foreach.hpp> +#include <boost/filesystem.hpp> + +using namespace boost::filesystem; int parser_error_pos = -1; @@ -605,7 +603,7 @@ AbstractModule *parse(const char *text, const char *path, int debug) boost::unordered_map<std::string, Module::libs_cache_ent> Module::libs_cache; -Module *Module::compile_library(std::string filename) +Module *Module::compile_library(const std::string &filename) { struct stat st; memset(&st, 0, sizeof(struct stat)); @@ -620,12 +618,19 @@ Module *Module::compile_library(std::string filename) return &(*libs_cache[filename].mod); } - QFile f(QString::fromStdString(filename)); - if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { - PRINTF("WARNING: Can't open library file `%s'.", filename.c_str()); - return NULL; - } - QString text = QTextStream(&f).readAll(); + FILE *fp = fopen(filename.c_str(), "rt"); + if (!fp) { + fprintf(stderr, "WARNING: Can't open library file '%s'\n", filename.c_str()); + return NULL; + } + std::stringstream text; + char buffer[513]; + int ret; + while ((ret = fread(buffer, 1, 512, fp)) > 0) { + buffer[ret] = 0; + text << buffer; + } + fclose(fp); print_messages_push(); @@ -636,7 +641,7 @@ Module *Module::compile_library(std::string filename) libs_cache[filename] = e; Module *backup_mod = module; - Module *lib_mod = dynamic_cast<Module*>(parse(text.toLocal8Bit(), QFileInfo(QString::fromStdString(filename)).absoluteDir().absolutePath().toLocal8Bit(), 0)); + Module *lib_mod = dynamic_cast<Module*>(parse(text.str().c_str(), path(filename).parent_path().generic_string().c_str(), 0)); module = backup_mod; if (lib_mod) { diff --git a/src/parsersettings.cc b/src/parsersettings.cc new file mode 100644 index 0000000..2d0b1b3 --- /dev/null +++ b/src/parsersettings.cc @@ -0,0 +1,27 @@ +#include "parsersettings.h" +#include <boost/filesystem.hpp> + +using namespace boost::filesystem; + +std::string librarydir; + +void parser_init(const std::string &applicationpath) +{ + path libdir(applicationpath); + path tmpdir; +#ifdef Q_WS_MAC + libdir /= "../Resources"; // Libraries can be bundled + if (!is_directory(libdir / "libraries")) libdir /= "../../.."; +#elif defined(Q_OS_UNIX) + if (is_directory(tmpdir = libdir / "../share/openscad/libraries")) { + librarydir = tmpdir.generic_string(); + } else if (is_directory(tmpdir = libdir / "../../share/openscad/libraries")) { + librarydir = tmpdir.generic_string(); + } else if (is_directory(tmpdir = libdir / "../../libraries")) { + librarydir = tmpdir.generic_string(); + } else +#endif + if (is_directory(tmpdir = libdir / "libraries")) { + librarydir = tmpdir.generic_string(); + } +} diff --git a/src/parsersettings.h b/src/parsersettings.h new file mode 100644 index 0000000..61dcf99 --- /dev/null +++ b/src/parsersettings.h @@ -0,0 +1,11 @@ +#ifndef PARSERSETTINGS_H_ +#define PARSERSETTINGS_H_ + +#include <string> + +extern std::string librarydir; +extern int parser_error_pos; + +void parser_init(const std::string &applicationpath); + +#endif diff --git a/src/polyset.cc b/src/polyset.cc index 7e40eac..778201b 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -27,7 +27,6 @@ #include "polyset.h" #include "linalg.h" #include <Eigen/LU> -#include <QColor> /*! /class PolySet diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 4e2db9e..0da30ce 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -38,8 +38,6 @@ #include <boost/assign/std/vector.hpp> using namespace boost::assign; // bring 'operator+=()' into scope -#include <QFileInfo> - class RotateExtrudeModule : public AbstractModule { public: diff --git a/src/surface.cc b/src/surface.cc index 39d1972..fe1c6aa 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -33,11 +33,13 @@ #include "handle_dep.h" // handle_dep() #include "visitor.h" -#include <QFile> -#include <QRegExp> -#include <QStringList> #include <sstream> +#include <fstream> +#include <boost/foreach.hpp> #include <boost/unordered_map.hpp> +#include <boost/tokenizer.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/algorithm/string.hpp> #include <boost/assign/std/vector.hpp> using namespace boost::assign; // bring 'operator+=()' into scope @@ -95,9 +97,9 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat PolySet *SurfaceNode::evaluate_polyset(class PolySetEvaluator *) const { handle_dep(filename); - QFile f(QString::fromStdString(filename)); + std::ifstream stream(filename.c_str()); - if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (!stream.good()) { PRINTF("WARNING: Can't open DAT file `%s'.", filename.c_str()); return NULL; } @@ -107,23 +109,34 @@ PolySet *SurfaceNode::evaluate_polyset(class PolySetEvaluator *) const boost::unordered_map<std::pair<int,int>,double> data; double min_val = 0; - while (!f.atEnd()) - { - QString line = QString(f.readLine()).remove("\n").remove("\r"); - line.replace(QRegExp("^[ \t]+"), ""); - line.replace(QRegExp("[ \t]+$"), ""); - - if (line.startsWith("#")) - continue; - - QStringList fields = line.split(QRegExp("[ \t]+")); - for (int i = 0; i < fields.count(); i++) { - if (i >= columns) - columns = i + 1; - double v = fields[i].toDouble(); - data[std::make_pair(lines, i)] = v; - min_val = fmin(v-1, min_val); + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(" \t"); + + while (!stream.eof()) { + std::string line; + while (!stream.eof() && (line.size() == 0 || line[0] == '#')) { + std::getline(stream, line); + boost::trim(line); } + if (stream.eof()) break; + + int col = 0; + tokenizer tokens(line, sep); + try { + BOOST_FOREACH(const std::string &token, tokens) { + double v = boost::lexical_cast<double>(token); + data[std::make_pair(lines, col++)] = v; + if (col > columns) columns = col; + min_val = std::min(v-1, min_val); + } + } + catch (boost::bad_lexical_cast &blc) { + if (!stream.eof()) { + PRINTF("WARNING: Illegal value in '%s': %s", filename.c_str(), blc.what()); + } + break; + } + lines++; } diff --git a/src/value.cc b/src/value.cc index 5ea766c..47fac1e 100644 --- a/src/value.cc +++ b/src/value.cc @@ -368,10 +368,17 @@ std::string Value::toString() const // across platforms for testing purposes. { std::stringstream tmp; - tmp.precision(16); + tmp.precision(12); + tmp.setf(std::ios_base::fixed); tmp << this->num; std::string tmpstr = tmp.str(); - if (tmpstr.size() > 16) tmpstr.erase(16); + size_t endpos = tmpstr.find_last_not_of('0'); + if (endpos >= 0 && tmpstr[endpos] == '.') endpos--; + tmpstr = tmpstr.substr(0, endpos+1); + size_t dotpos = tmpstr.find('.'); + if (dotpos != std::string::npos) { + if (tmpstr.size() - dotpos > 12) tmpstr.erase(dotpos + 12); + } stream << tmpstr; } #else @@ -435,6 +442,7 @@ std::ostream &operator<<(std::ostream &stream, const Filename &filename) return stream; } +// FIXME: This could probably be done more elegantly using boost::regex std::ostream &operator<<(std::ostream &stream, const QuotedString &s) { stream << '"'; |