1 
2 /*
3  *  Math2
4  *  Copyright (c) 2003-2007 by Mattias Hultgren <tilda_o_tize@hotmail.com>
5  *
6  *  See math2.h
7  */
8 
9 
10 
11 #include "math2.h"
12 #include "math2.intern.h"
13 #include "keyfile.h"
14 #include <stdarg.h>
15 #include <time.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 namespace math
21 {
22 
23 VariableList global_varlist;
24 Format *intern_format = 0;
25 
26 Vector<utf8_string> autoload_directories;
27 
28 Complex degfix( 1.0 );
29 
30 const char *VARIABLE_TYPE_NAMES[] = {
31                                      "Complex",
32                                      "Matrix",
33                                      "Array",
34                                      "String",
35                                      "Picture",
36                                      "Boolean",
37                                      "Void",
38                                      0
39                                     };
40 
41 
init(void)42 void init(void) throw(error_obj)
43 {
44 	static bool already_inited = false;
45 	Variable tmpvar;
46 
47 	if(!already_inited)
48 	{
49 		already_inited = true;
50 		srand(time(0));
51 
52 		tmpvar.set_boolean( false );
53 		tmpvar.set_name( "false" );
54 		global_varlist.create( tmpvar, true, false, false); // constant
55 		tmpvar.set_boolean( true );
56 		tmpvar.set_name( "true" );
57 		global_varlist.create( tmpvar, true,false,false); // constant
58 
59 		tmpvar.set_complex( Complex( PI ) );
60 		tmpvar.set_name( "pi" );
61 		global_varlist.create( tmpvar , true,false,false); // constant
62 		tmpvar.set_complex( Complex(0, 1) );
63 		tmpvar.set_name( "i" );
64 		global_varlist.create( tmpvar , true,false,false);  // constant
65 		tmpvar.set_complex( Complex( E ) );
66 		tmpvar.set_name( "e" );
67 		global_varlist.create( tmpvar , true,false,false);  // constant
68 
69 		tmpvar.set_complex( Complex( 0 ) );
70 		tmpvar.set_name( "x" );
71 		global_varlist.create( tmpvar , false,false,true);
72 		tmpvar.set_name( "y" );
73 		global_varlist.create( tmpvar , false,false,true);
74 
75 		tmpvar.set_void();
76 		tmpvar.set_name( "void" );
77 		global_varlist.create( tmpvar, true, false, false);
78 
79 		function_list.add_function( "append", builtin_append, 15, true, true );
80 		function_list.add_function( "(array_of_two)", builtin_array_of_two, 15, true, true );
81 		function_list.add_function( "axes", builtin_axes, 15, true, true );
82 		function_list.add_function( "circle", builtin_circle, 15, true, true );
83 		function_list.add_function( "(eval)", builtin_round_eval, 15, true, true );
84 		function_list.add_function( "[get]", builtin_hook_get, 15, true, true );
85 		function_list.add_function( "get_bottom", builtin_get_bottom, 15, true, false );
86 		function_list.add_function( "get_col", builtin_get_col, 15, true, true );
87 		function_list.add_function( "get_height", builtin_get_height, 15, true, false );
88 		function_list.add_function( "get_left", builtin_get_left, 15, true, false );
89 		function_list.add_function( "get_right", builtin_get_right, 15, true, false );
90 		function_list.add_function( "get_row", builtin_get_row, 15, true, true );
91 		function_list.add_function( "get_top", builtin_get_top, 15, true, false );
92 		function_list.add_function( "get_type", builtin_get_type, 15, true, false );
93 		function_list.add_function( "get_width", builtin_get_width, 15, true, false );
94 		function_list.add_function( "grid", builtin_grid, 15, true, true );
95 		function_list.add_function( "insert", builtin_insert, 15, true, true );
96 		function_list.add_function( "line", builtin_line, 15, true, true );
97 		function_list.add_function( "merge", builtin_merge, 15, true, true );
98 		function_list.add_function( "pixel_circle", builtin_pixel_circle, 15, true, true );
99 		function_list.add_function( "pixel_line", builtin_pixel_line, 15, true, true );
100 		function_list.add_function( "plot", builtin_plot, 15, true, true );
101 		function_list.add_function( "(powMod)", builtin_pow_mod, 15, true, true );
102 		function_list.add_function( "remove", builtin_remove, 15, true, true );
103 		function_list.add_function( "[set]", builtin_hook_set, 15, true, true );
104 		function_list.add_function( "[set_next]", builtin_hook_set_next, 15, true, true );
105 		function_list.add_function( "set_pixel", builtin_set_pixel, 15, true, true );
106 		function_list.add_function( "set_point", builtin_set_point, 15, true, true );
107 		function_list.add_function( "set_window", builtin_set_window, 15, true, true );
108 
109 
110 		function_list.add_function( "abs", builtin_abs, 14, false, true );
111 		function_list.add_function( "acos", builtin_acos, 14, false, true );
112 		function_list.add_function( "acosh", builtin_acosh, 14, false, true );
113 		function_list.add_function( "adj", builtin_adj, 14, false, true );
114 		function_list.add_function( "arg", builtin_arg, 14, false, true );
115 		function_list.add_function( "array", builtin_array, 14, false, true );
116 		function_list.add_function( "asin", builtin_asin, 14, false, true );
117 		function_list.add_function( "asinh", builtin_asinh, 14, false, true );
118 		function_list.add_function( "atan", builtin_atan, 14, false, true );
119 		function_list.add_function( "atanh", builtin_atanh, 14, false, true );
120 		function_list.add_function( "clear", builtin_clear, 14, false, true );
121 		function_list.add_function( "comb", builtin_comb, 14, false, true );
122 		function_list.add_function( "cos", builtin_cos, 14, false, true );
123 		function_list.add_function( "cosh", builtin_cosh, 14, false, true );
124 		function_list.add_function( "dec", builtin_dec, 14, false, true );
125 		function_list.add_function( "delete", builtin_delete, 14, false, true );
126 		function_list.add_function( "det", builtin_det, 14, false, true );
127 		function_list.add_function( "error", builtin_error, 14, false, true );
128 		function_list.add_function( "frac", builtin_frac, 14, false, true );
129 		function_list.add_function( "fPart", builtin_fpart, 14, false, true );
130 		function_list.add_function( "im", builtin_im, 14, false, true );
131 		function_list.add_function( "iPart", builtin_ipart, 14, false, true );
132 		function_list.add_function( "iSqrt", builtin_isqrt, 14, false, true );
133 		function_list.add_function( "log", builtin_log, 14, false, true );
134 		function_list.add_function( "log2", builtin_log2, 14, false, true );
135 		function_list.add_function( "ln", builtin_ln, 14, false, true );
136 		function_list.add_function( "make_constant", builtin_make_constant, 14, false, true );
137 		function_list.add_function( "make_type_locked", builtin_make_type_locked, 14, false, true );
138 		function_list.add_function( "make_undeletable", builtin_make_undeletable, 14, false, true );
139 		function_list.add_function( "matrix", builtin_matrix, 14, false, true );
140 		function_list.add_function( "nDeriv", builtin_nderiv, 14, false, true );
141 		function_list.add_function( "nInt", builtin_nint, 14, false, true );
142 		function_list.add_function( "nSolve", builtin_nsolve, 14, false, true );
143 		function_list.add_function( "perm", builtin_perm, 14, false, true );
144 		function_list.add_function( "picture", builtin_picture, 14, false, true );
145 		function_list.add_function( "polyreg", builtin_polyreg, 14, false, true );
146 		function_list.add_function( "rand", builtin_rand, 14, false, false );
147 		function_list.add_function( "re", builtin_re, 14, false, true );
148 		function_list.add_function( "shade", builtin_shade, 14, false, true );
149 		function_list.add_function( "sin", builtin_sin, 14, false, true );
150 		function_list.add_function( "sinh", builtin_sinh, 14, false, true );
151 		function_list.add_function( "sum", builtin_sum, 14, false, true );
152 		function_list.add_function( "sqrt", builtin_sqrt, 14, false, true );
153 		function_list.add_function( "table", builtin_table, 14, false, true );
154 		function_list.add_function( "table2d", builtin_table2d, 14, false, true );
155 		function_list.add_function( "tan", builtin_tan, 14, false, true );
156 		function_list.add_function( "tanh", builtin_tanh, 14, false, true );
157 		function_list.add_function( "time", builtin_time, 14, false, false );
158 		function_list.add_function( "++", builtin_inc, 14, true, false );
159 		function_list.add_function( "--", builtin_decrement, 14, true, false );
160 		function_list.add_function( "-(neg)", builtin_neg, 14, false, true );
161 
162 		function_list.add_function( "!", builtin_faculty, 13, true, false );
163 
164 		function_list.add_function( "^", builtin_pow, 12, true, true );
165 
166 		function_list.add_function( "*", builtin_mul, 11, true, true );
167 		function_list.add_function( "/", builtin_div, 11, true, true );
168 		function_list.add_function( "mod", builtin_modulo, 11, true, true );
169 		function_list.add_function( "\\", builtin_intdiv, 11, true, true );
170 
171 		function_list.add_function( "+", builtin_plus, 10, true, true );
172 		function_list.add_function( "-", builtin_minus, 10, true, true );
173 
174 		function_list.add_function( "==", builtin_equal, 9, true, true );
175 		function_list.add_function( "!=", builtin_notequal, 9, true, true );
176 		function_list.add_function( ">", builtin_greater, 9, true, true );
177 		function_list.add_function( "<", builtin_smaller, 9, true, true );
178 		function_list.add_function( ">=", builtin_greater_eq, 9, true, true );
179 		function_list.add_function( "<=", builtin_smaller_eq, 9, true, true );
180 		function_list.add_function( "~=", builtin_almost_eq, 9, true, true );
181 
182 		function_list.add_function( "and", builtin_and, 8, true, true );
183 		function_list.add_function( "or", builtin_or, 8, true, true );
184 		function_list.add_function( "xor", builtin_xor, 8, true, true );
185 		function_list.add_function( "not", builtin_not, 8, false, true );
186 
187 		function_list.add_function( "=", builtin_set, 7, true, true );
188 		function_list.add_function( "+=", builtin_set_add, 7, true, true );
189 		function_list.add_function( "-=", builtin_set_sub, 7, true, true );
190 		function_list.add_function( "*=", builtin_set_mul, 7, true, true );
191 		function_list.add_function( "/=", builtin_set_div, 7, true, true );
192 		function_list.add_function( "\\=", builtin_set_intdiv, 7, true, true );
193 		function_list.add_function( "^=", builtin_set_pow, 7, true, true );
194 	}
195 }
196 
197 
add_function(const utf8_string & name,BuiltinFunctionPtr newfunction,bool needleft,bool needright)198 void add_function( const utf8_string &name, BuiltinFunctionPtr newfunction, bool needleft,
199                    bool needright ) throw(error_obj)
200 {
201 	function_list.add_function( name, newfunction, 14, needleft, needright );
202 }
203 
204 
argument_check(const char * function,const Variable * input,...)205 void argument_check(const char *function, const Variable *input, ...) throw(error_obj)
206 {
207 	va_list ap;
208 	argument_types type;
209 	const Variable *var = 0;
210 	const Array *array;
211 	Array tmparray;
212 	Complex tmp;
213 
214 	Complex *out_complex;
215 	floatx *out_floatx;
216 	int64 *out_int64;
217 	Integer *out_integer;
218 	bool *out_boolean;
219 	Picture *out_picture;
220 	Matrix *out_matrix;
221 	utf8_string *out_string;
222 	Variable *out_variable;
223 
224 	va_start(ap,input);
225 
226 	try
227 	{
228 		switch(input->get_type())
229 		{
230 		case VariableType_Array:
231 			array = input->get_array();
232 			argument_check_do_the_check:
233 			for(uint32 i=0;i<array->get_size();)
234 			{
235 				type = argument_types( va_arg(ap, int) );
236 				if(type == type_end)
237 				{
238 					char tmp_err[ERROR_OBJ_MSG_LEN];
239 					snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
240 					THROW_ERROR( ErrorType_General, tmp_err );
241 				}
242 
243 				if(var == 0)
244 					var = array->get_variable(i);
245 				switch(type)
246 				{
247 				case type_complex:
248 				case type_complex_default:
249 					out_complex = va_arg(ap, Complex *);
250 					if(var->get_type() == VariableType_Complex)
251 					{
252 						*out_complex = *(var->get_complex());
253 						var = 0;
254 					}
255 					else
256 					{
257 						if(type == type_complex)
258 						{
259 							char tmp_err[ERROR_OBJ_MSG_LEN];
260 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
261 							THROW_ERROR( ErrorType_General, tmp_err );
262 						}
263 					}
264 					break;
265 
266 				case type_floatx:
267 				case type_floatx_default:
268 					out_floatx = va_arg(ap, floatx *);
269 					if(var->get_type() == VariableType_Complex)
270 					{
271 						tmp = *(var->get_complex());
272 						if(floatx(tmp.imaginary) != 0.0)
273 							THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
274 
275 						*out_floatx = floatx(tmp.real);
276 						var = 0;
277 					}
278 					else
279 					{
280 						if(type == type_floatx)
281 						{
282 							char tmp_err[ERROR_OBJ_MSG_LEN];
283 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
284 							THROW_ERROR( ErrorType_General, tmp_err );
285 						}
286 					}
287 					break;
288 
289 				case type_int64:
290 				case type_int64_default:
291 					out_int64 = va_arg(ap, int64 *);
292 					if(var->get_type() == VariableType_Complex)
293 					{
294 						tmp = *(var->get_complex());
295 
296 						if(floatx(tmp.imaginary) != 0.0)
297 							THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
298 						if(ipart(tmp.real) != tmp.real)
299 							THROW_ERROR( ErrorType_Domain, _("Domain error: The number must be an integer.") );
300 
301 						if(floatx(tmp.real) >= int64_max) {
302 							THROW_ERROR( ErrorType_Domain, _("Domain error: The number must be below 2^64.") );
303 						} else if(floatx(tmp.real) <= int64_min) {
304 							THROW_ERROR( ErrorType_Domain, _("Domain error: The number must be above -2^64.") );
305 						} else
306 							*out_int64 = int64(floatx(tmp.real));
307 						var = 0;
308 					}
309 					else
310 					{
311 						if(type == type_int64)
312 						{
313 							char tmp_err[ERROR_OBJ_MSG_LEN];
314 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
315 							THROW_ERROR( ErrorType_General, tmp_err );
316 						}
317 					}
318 					break;
319 
320 				case type_integer:
321 				case type_integer_default:
322 					out_integer = va_arg(ap, Integer *);
323 					if(var->get_type() == VariableType_Complex)
324 					{
325 						tmp = *(var->get_complex());
326 
327 						if(floatx(tmp.imaginary) != 0.0)
328 							THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
329 						if( !tmp.real.isInteger() )
330 							THROW_ERROR( ErrorType_Domain, _("Domain error: The number must be an integer.") );
331 
332 						tmp.real.get_top( out_integer );
333 						var = 0;
334 					}
335 					else
336 					{
337 						if(type == type_integer)
338 						{
339 							char tmp_err[ERROR_OBJ_MSG_LEN];
340 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
341 							THROW_ERROR( ErrorType_General, tmp_err );
342 						}
343 					}
344 					break;
345 
346 				case type_boolean:
347 				case type_boolean_default:
348 					out_boolean = va_arg(ap, bool *);
349 					if(var->get_type() == VariableType_Boolean)
350 					{
351 						*out_boolean = var->get_boolean();
352 						var = 0;
353 					}
354 					else
355 					{
356 						if(type == type_boolean)
357 						{
358 							char tmp_err[ERROR_OBJ_MSG_LEN];
359 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
360 							THROW_ERROR( ErrorType_General, tmp_err );
361 						}
362 					}
363 					break;
364 
365 				case type_picture:
366 				case type_picture_default:
367 					out_picture = va_arg(ap, Picture *);
368 					if(var->get_type() == VariableType_Picture)
369 					{
370 						*out_picture = *(var->get_picture());
371 						var = 0;
372 					}
373 					else
374 					{
375 						if(type == type_picture)
376 						{
377 							char tmp_err[ERROR_OBJ_MSG_LEN];
378 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
379 							THROW_ERROR( ErrorType_General, tmp_err );
380 						}
381 					}
382 					break;
383 
384 				case type_matrix:
385 				case type_matrix_default:
386 					out_matrix = va_arg(ap, Matrix *);
387 					if(var->get_type() == VariableType_Matrix)
388 					{
389 						*out_matrix = *(var->get_matrix());
390 						var = 0;
391 					}
392 					else
393 					{
394 						if(type == type_matrix)
395 						{
396 							char tmp_err[ERROR_OBJ_MSG_LEN];
397 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
398 							THROW_ERROR( ErrorType_General, tmp_err );
399 						}
400 					}
401 					break;
402 
403 				case type_string:
404 				case type_string_default:
405 					out_string = va_arg(ap, utf8_string *);
406 					if(var->get_type() == VariableType_String)
407 					{
408 						*out_string = *(var->get_string());
409 						var = 0;
410 					}
411 					else
412 					{
413 						if(type == type_string)
414 						{
415 							char tmp_err[ERROR_OBJ_MSG_LEN];
416 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
417 							THROW_ERROR( ErrorType_General, tmp_err );
418 						}
419 					}
420 					break;
421 
422 				case type_name:
423 				case type_name_default:
424 					out_string = va_arg(ap, utf8_string *);
425 					if(var->has_name())
426 					{
427 						*out_string = *(var->get_name());
428 						var = 0;
429 					}
430 					else
431 					{
432 						if(type == type_name)
433 						{
434 							char tmp_err[ERROR_OBJ_MSG_LEN];
435 							snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
436 							THROW_ERROR( ErrorType_General, tmp_err );
437 						}
438 					}
439 					break;
440 
441 				case type_variable:
442 				case type_variable_default:
443 					out_variable = va_arg(ap, Variable *);
444 
445 					*out_variable = *var;
446 					var = 0;
447 					break;
448 
449 				default:
450 					printf("argument_check was called in an unsupported way\n\n");
451 					exit(-1);
452 				}
453 				if(var == 0)
454 					i++;
455 			}
456 			break;
457 
458 		default:
459 			tmparray.clear();
460 			tmparray.add_variable( input );
461 			array = &tmparray;
462 			goto argument_check_do_the_check;
463 		}
464 
465 
466 		bool loop=true;
467 		do{
468 			switch(argument_types( va_arg(ap, int) ))
469 			{
470 			case type_end:
471 				loop = false;
472 				break;
473 
474 			case type_complex_default:
475 			case type_floatx_default:
476 			case type_int64_default:
477 			case type_integer_default:
478 			case type_boolean_default:
479 			case type_picture_default:
480 			case type_matrix_default:
481 			case type_string_default:
482 			case type_name_default:
483 			case type_variable_default:
484 				break;
485 
486 			default:
487 				{
488 					char tmp_err[ERROR_OBJ_MSG_LEN];
489 					snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Argument list doesn't match for %s"), function );
490 					THROW_ERROR( ErrorType_General, tmp_err );
491 				}
492 			}
493 			out_complex = va_arg(ap, Complex *); // this is not always a legal pointer, but all pointers are
494 		}while(loop);                            // equal in size so the code is OK
495 	}
496 	catch(error_obj error)
497 	{
498 		va_end(ap);
499 		throw;
500 	}
501 	catch(...)
502 	{
503 		va_end(ap);
504 		THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );
505 	}
506 	va_end(ap);
507 }
508 
colorrgb_to_colormatrix(const picture_h::colorrgb & color,Matrix * matr)509 void colorrgb_to_colormatrix(const picture_h::colorrgb &color, Matrix *matr) throw(error_obj)
510 {
511 	Complex tmp;
512 
513 	if(matr == 0)
514 		THROW_ERROR( ErrorType_General, _("Invalid matrix width") );
515 
516 	matr->set_size( 3, 1 );
517 
518 	tmp.imaginary = Real(0);
519 
520 	tmp.real = Real( int64(color.red), 255 );
521 	matr->set_complex(1,1,tmp);
522 
523 	tmp.real = Real( int64(color.green), 255 );
524 	matr->set_complex(2,1,tmp);
525 
526 	tmp.real = Real( int64(color.blue), 255 );
527 	matr->set_complex(3,1,tmp);
528 }
colormatrix_to_colorrgb(const Matrix & matr,picture_h::colorrgb * color,uint32 index)529 void colormatrix_to_colorrgb(const Matrix &matr, picture_h::colorrgb *color, uint32 index)
530                              throw(error_obj)
531 {
532 	Complex tmp;
533 
534 	if( index == 0 )
535 		THROW_ERROR( ErrorType_General, _("colormatrix_to_colorrgb: Index mustn't be zero.") );
536 
537 	if( matr.get_width() != 3  ||  matr.get_height() < index )
538 		THROW_ERROR( ErrorType_General, _("Invalid matrix width") );
539 
540 	tmp = matr.get_complex( 1, index );
541 	tmp.real = floatx(tmp.real) * 255.0 + 0.5;
542 	if( floatx(tmp.real) > 255.0 )
543 		color->red = 255;
544 	else if( floatx(tmp.real) < 0.0 )
545 		color->red = 0;
546 	else
547 		color->red = uint8(floatx(tmp.real));
548 
549 	tmp = matr.get_complex( 2, index );
550 	tmp.real = floatx(tmp.real) * 255.0 + 0.5;
551 	if( floatx(tmp.real) > 255.0 )
552 		color->green = 255;
553 	else if( floatx(tmp.real) < 0.0 )
554 		color->green = 0;
555 	else
556 		color->green = uint8(floatx(tmp.real));
557 
558 	tmp = matr.get_complex( 3, index );
559 	tmp.real = floatx(tmp.real) * 255.0 + 0.5;
560 	if( floatx(tmp.real) > 255.0 )
561 		color->blue = 255;
562 	else if( floatx(tmp.real) < 0.0 )
563 		color->blue = 0;
564 	else
565 		color->blue = uint8(floatx(tmp.real));
566 }
567 
colormatrix_to_colorrgbs(const Matrix & matr,Vector<picture_h::colorrgb> & colors)568 void colormatrix_to_colorrgbs(const Matrix &matr, Vector<picture_h::colorrgb> &colors)
569                               throw(error_obj)
570 {
571 	colors.set_size_filled( int(matr.get_height()) );
572 
573 	for( uint32 i=1; i<=matr.get_height(); i++ )
574 		colormatrix_to_colorrgb( matr, colors[i-1], i );
575 }
576 
color_list_get_color(const Vector<picture_h::colorrgb> & colors,floatx min,floatx max,floatx value,picture_h::colorrgb * out_color)577 void color_list_get_color( const Vector<picture_h::colorrgb> &colors, floatx min, floatx max,
578                            floatx value, picture_h::colorrgb *out_color)
579 {
580 	int base;
581 
582 	if( min >= max  ||  colors.get_size() == 0 )
583 		return;
584 	if( value < min )
585 		value = min;
586 	if( value > max )
587 		value = max;
588 
589 	value = (value - min ) / (max - min );
590 	value = value * floatx(colors.get_size()-1);
591 	base = int(value);
592 	value -= truncx( value );
593 
594 	if( base >= (colors.get_size()-1) )
595 		*out_color = *colors[base];
596 	else
597 	{
598 		out_color->red = uint8( floatx(colors[base]->red)*(1.0-value) +
599 		                        floatx(colors[base+1]->red)*value );
600 		out_color->green = uint8( floatx(colors[base]->green)*(1.0-value) +
601 		                          floatx(colors[base+1]->green)*value );
602 		out_color->blue = uint8( floatx(colors[base]->blue)*(1.0-value) +
603 		                         floatx(colors[base+1]->blue)*value );
604 	}
605 }
606 
autoload_file(const utf8_string & name)607 bool autoload_file( const utf8_string &name ) throw(error_obj)
608 {
609 	utf8_string filename;
610 	FILE *fp;
611 	CodeBlock code;
612 
613 	for( int i=0; i<autoload_directories.get_size(); i++ )
614 	{
615 		filename = *autoload_directories[i];
616 		filename.append( "/" );
617 		filename.append( name );
618 		filename.append( ".ump" );
619 
620 		fp = fopen( filename.c_str(), "r" );
621 		if( fp != 0 )
622 		{
623 			fclose(fp);
624 
625 			code.set_code_from_file( filename, &name );
626 
627 			return true;
628 		}
629 	}
630 
631 	return false;
632 }
633 
parse_create_symbol_vector(const utf8_string & string,Vector<utf8_string> * symbols)634 void parse_create_symbol_vector( const utf8_string &string, Vector<utf8_string> *symbols) throw(error_obj)
635 {
636 	utf8_string tmp;
637 	int start;
638 
639 	try
640 	{
641 		for( int i=0; string.c_str_from( i )[0] != '\0'; i++ )
642 		{
643 			if( string.test_character( i, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" ) )
644 			{
645 				start = i;
646 
647 				for( i++; string.test_character( i,
648 				          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789" ); i++ )
649 					;
650 				tmp.assign( string, start, i-start );
651 				symbols->append( tmp );
652 				i--;
653 			}
654 			else if( string.test_character( i, "0123456789" )  ||
655 			         ( string.test_character( i, "." )  &&  string.test_character( i+1, "0123456789" ) ))
656 			{
657 				start = i;
658 
659 				for( i++; string.test_character( i, "0123456789." ); i++ )
660 					;
661 				tmp.assign( string, start, i-start );
662 				symbols->append( tmp );
663 				i--;
664 			}
665 			else if( string.test_character( i, "\"" ) )
666 			{
667 				start = i;
668 
669 				for( i++; !string.test_character( i, "\"" ); i++ )
670 				{
671 					if( string.test_character( i, "\\" ) )
672 					{
673 						if( string.c_str_from(i)[0] == '\0' )
674 							THROW_ERROR( ErrorType_General, _("Expected closing \" but found line break or end of file.") );
675 						if( string.test_character( i, "\"\\" ) )
676 							i++;
677 					}
678 					if(  string.c_str_from(i)[0] == '\0'  ||  string.test_character( i, "\0\n\r" ) )
679 						THROW_ERROR( ErrorType_General, _("Expected closing \" but found line break or end of file.") );
680 				}
681 				tmp.assign( string, start, i-start+1 );
682 				tmp.remove_escape_sequences();
683 				symbols->append( tmp );
684 			}
685 			else if( !string.test_character( i, " \t\n\r" ) )
686 			{
687 				int len=1;
688 				const char *tmp_c_str = string.c_str_from( i );
689 
690 				if( (tmp_c_str[0] == '+' && tmp_c_str[1] == '+')  ||  (tmp_c_str[0] == '+' && tmp_c_str[1] == '=')  ||
691 				    (tmp_c_str[0] == '-' && tmp_c_str[1] == '-')  ||  (tmp_c_str[0] == '-' && tmp_c_str[1] == '=')  ||
692 				    (tmp_c_str[0] == '*' && tmp_c_str[1] == '=')  ||  (tmp_c_str[0] == '/' && tmp_c_str[1] == '=')  ||
693 				    (tmp_c_str[0] == '\\' && tmp_c_str[1] == '=')  ||  (tmp_c_str[0] == '^' && tmp_c_str[1] == '=') ||
694 				    (tmp_c_str[0] == '=' && tmp_c_str[1] == '=')  ||  (tmp_c_str[0] == '~' && tmp_c_str[1] == '=') ||
695 				    (tmp_c_str[0] == '<' && tmp_c_str[1] == '=')  ||  (tmp_c_str[0] == '>' && tmp_c_str[1] == '=')  ||
696 				    (tmp_c_str[0] == '!' && tmp_c_str[1] == '=') )
697 					len = 2;
698 
699 				tmp.assign( string, i, len );
700 				symbols->append( tmp );
701 				i += (len-1);
702 			}
703 		}
704 	}
705 	catch( error_obj error ) {  throw error;  }
706 	catch(...) {  THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") );  }
707 }
708 
709 } // namespace math
710