merged current master

stl_dim
Marius Kintel 2010-12-09 19:04:11 +01:00
commit 00c237d3ce
4 changed files with 133 additions and 29 deletions

View File

@ -1,8 +1,10 @@
OpenSCAD 2010.06
OpenSCAD 2010.XX
================
... add stuff here ...
o Added rands() function
o Added sign() function
o Bugfixes: More robust DXF export
OpenSCAD 2010.05
================

View File

@ -131,10 +131,11 @@ o Function-Module-Interface
- Pass a module instanciation to a function (e.g. for a volume() function)
- Pass a function to a module instanciation (e.g. for dynamic extrusion paths)
o Language Frontend
- include statement doesn't support nesting. This can be fixed by
keeping a nested stack of current input files in the lexer. See
the "Flex & Bison" O'Reilly book, "Start States and Nested Input
Files", page 28, for an example.
- Allow local variables and functions everywhere (not only on module level)
- Add "use" statement to load modules. Like include but read a module only once,
ignore all top level objects (they are used as module testcase) and search in
a module search path.
- allow 0/1 f/t FALSE/TRUE as boolean values
- allow any expression to be evaluated as boolean (e.g. 1 = true, 0 = false)
- Rethink for vs. intersection_for vs. group. Should for loops
@ -194,6 +195,11 @@ o Consider evaluating all referenced files relative to the document path instead
of being absolute. This would e.g. make regression testing of dumpcaching easier.
This would require us to pass a document contect to all traversal methods though.
BUILD SYSTEM
------------
o Fedora is reported to ship with byacc, which doesn't support bison extensions (e.g. %debuig). Look into this, either be yacc-compatible or force the build system to use bison.
o We currently link in -lboost_thread. Should we always use -lboost_thread-mt under Linux or can we pick this up using qmake?
TESTING
-------
o Caching and MDI looks suspicious when the code relies on external resources

View File

@ -125,6 +125,51 @@ Value builtin_sign(const Context *, const QVector<QString>&, const QVector<Value
return Value();
}
double frand()
{
return rand()/(double(RAND_MAX)+1);
}
double frand(double min, double max)
{
return (min>max) ? frand()*(min-max)+max : frand()*(max-min)+min;
}
Value builtin_rands(const Context *, const QVector<QString>&, const QVector<Value> &args)
{
if (args.size() == 3 &&
args[0].type == Value::NUMBER &&
args[1].type == Value::NUMBER &&
args[2].type == Value::NUMBER)
{
srand((unsigned int)time(0));
}
else if (args.size() == 4 &&
args[0].type == Value::NUMBER &&
args[1].type == Value::NUMBER &&
args[2].type == Value::NUMBER &&
args[3].type == Value::NUMBER)
{
srand((unsigned int)args[3].num);
}
else
{
return Value();
}
Value v;
v.type = Value::VECTOR;
for (int i=0; i<args[2].num; i++)
{
Value * r = new Value(frand(args[0].num, args[1].num));
v.vec.append(r);
}
return v;
}
Value builtin_min(const Context *, const QVector<QString>&, const QVector<Value> &args)
{
if (args.size() >= 1 && args[0].type == Value::NUMBER) {
@ -298,6 +343,7 @@ void initialize_builtin_functions()
{
builtin_functions["abs"] = new BuiltinFunction(&builtin_abs);
builtin_functions["sign"] = new BuiltinFunction(&builtin_sign);
builtin_functions["rands"] = new BuiltinFunction(&builtin_rands);
builtin_functions["min"] = new BuiltinFunction(&builtin_min);
builtin_functions["max"] = new BuiltinFunction(&builtin_max);
builtin_functions["sin"] = new BuiltinFunction(&builtin_sin);

View File

@ -28,9 +28,10 @@
#include "openscad.h"
#include "printutils.h"
#include "parser_yacc.h"
#include <QStack>
#include <QFileInfo>
#include <QDir>
QString* stringcontents;
int lexerget_lineno(void);
#ifdef __GNUC__
static void yyunput(int, char*) __attribute__((unused));
@ -58,33 +59,33 @@ extern const char *parser_source_path;
} \
}
void includefile();
QDir sourcepath();
QStack<QDir> path_stack;
QString filename;
QString filepath;
%}
%option yylineno
%option noyywrap
%x comment
%x comment string
%x include
DIGIT [0-9]
%%
include[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
QString filename(yytext);
filename.remove(QRegExp("^include[ \t\r\n>]*<"));
filename.remove(QRegExp(">$"));
QFileInfo finfo(QDir(parser_source_path), filename);
if (!finfo.exists()) {
finfo = QFileInfo(QDir(librarydir), filename);
}
handle_dep(finfo.absoluteFilePath());
yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r");
if (!yyin) {
PRINTA("WARNING: Can't open input file `%1'.", filename);
} else {
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
BEGIN(INITIAL);
}
include[ \t\r\n>]*"<" { BEGIN(include); }
<include>{
[^\t\r\n>]+"/" { filepath = yytext; }
[^\t\r\n>/]+ { filename = yytext; }
">" { BEGIN(INITIAL); includefile(); }
}
use[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
QString filename(yytext);
filename.remove(QRegExp("^use[ \t\r\n>]*<"));
@ -106,7 +107,7 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
finfo = QFileInfo(QDir(librarydir), filename);
}
PRINTF("WARNING: Support for implicit include will be removed in future releases. Use `include <filename>' instead.");
PRINTF("DEPRECATED: Support for implicit include will be removed in future releases. Use `include <filename>' instead.");
handle_dep(finfo.absoluteFilePath());
yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r");
if (!yyin) {
@ -119,6 +120,8 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
}
<<EOF>> {
if(!path_stack.isEmpty())
path_stack.pop();
if (yyin && yyin != stdin)
fclose(yyin);
yypop_buffer_state();
@ -135,13 +138,21 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
"false" return TOK_FALSE;
"undef" return TOK_UNDEF;
[0-9][0-9.]* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; }
{DIGIT}+|{DIGIT}*\.{DIGIT}+|{DIGIT}+\.{DIGIT}* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; }
"$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; }
\"[^"]*\" {
parserlval.text = strdup(yytext+1);
parserlval.text[strlen(parserlval.text)-1] = 0;
return TOK_STRING;
\" { BEGIN(string); stringcontents = new QString(); }
<string>{
\\n { stringcontents->append('\n'); }
\\t { stringcontents->append('\t'); }
\\r { stringcontents->append('\r'); }
\\\\ { stringcontents->append('\\'); }
\\\" { stringcontents->append('"'); }
[^\\\n\"]+ { stringcontents->append(lexertext); }
\" { BEGIN(INITIAL);
parserlval.text = strdup(stringcontents->toLocal8Bit());
delete stringcontents;
return TOK_STRING; }
}
[\n\r\t ]
@ -159,3 +170,42 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" {
. { return yytext[0]; }
%%
QDir sourcepath()
{
if(!path_stack.isEmpty())
return path_stack.top();
return QDir(parser_source_path);
}
void includefile()
{
if(filename.isEmpty())
return;
if(filepath.isEmpty()) {
path_stack.push(sourcepath());
} else {
QFileInfo dirinfo(sourcepath(),filepath);
path_stack.push(dirinfo.dir());
filepath.clear();
}
QFileInfo finfo(sourcepath(), filename);
if (!finfo.exists()) {
finfo = QFileInfo(QDir(librarydir), filename);
}
handle_dep(finfo.absoluteFilePath());
yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r");
if (!yyin) {
PRINTA("WARNING: Can't open input file `%1'.", filename);
return;
}
filename.clear();
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
}