diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/func.cc | 46 | ||||
| -rw-r--r-- | src/lexer.l | 98 | 
2 files changed, 120 insertions, 24 deletions
diff --git a/src/func.cc b/src/func.cc index d73b152..7627a94 100644 --- a/src/func.cc +++ b/src/func.cc @@ -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); diff --git a/src/lexer.l b/src/lexer.l index 48729c8..9e8aaf8 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -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 )); +} +  | 
