1 /* -*- mode: c; mode: fold; -*- */
2 /*
3 * Copyright (C) 2000-2005 Chris Ross and various contributors
4 * Copyright (C) 1999-2000 Chris Ross
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * o Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 * o Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * o Neither the name of the ferite software nor the names of its contributors may
16 * be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifdef HAVE_CONFIG_HEADER
33 #include "../config.h"
34 #endif
35
36 #include "ferite.h"
37 #include "aphex.h"
38 #include <math.h>
39
40 #define GET_VAR( var ) if( var && var->accessors && var->accessors->get ) (var->accessors->get)( script, var )
41 #define GET_A_VAR GET_VAR( a )
42 #define GET_B_VAR GET_VAR( b )
43 #define GET_INPUT_VARS GET_A_VAR; GET_B_VAR
44
45 /*{{{ FeriteVariable *ferite_build_object( FeriteScript *script, FeriteClass *nclass) */
ferite_build_object(FeriteScript * script,FeriteClass * nclass)46 FeriteVariable *ferite_build_object( FeriteScript *script, FeriteClass *nclass)
47 {
48 FeriteVariable *ptr = NULL;
49
50 FE_ENTER_FUNCTION;
51
52 if( nclass != NULL )
53 {
54 FUD(("BUILDOBJECT: Creating an instance of %s\n", nclass->name ));
55 ptr = ferite_create_object_variable( script, nclass->name, FE_ALLOC );
56 if( script && script->objects->stack_ptr )
57 VAO(ptr) = ferite_stack_pop( script->objects );
58 else
59 VAO(ptr) = fmalloc( sizeof( FeriteObject ) );
60 VAO(ptr)->name = fstrdup( nclass->name );
61 VAO(ptr)->klass = nclass;
62
63 FUD(("BUILDOBJECT: Creating a duplicate varaible hash\n"));
64 VAO(ptr)->variables = ferite_duplicate_object_variable_list( script, nclass );
65
66 FUD(("BUILDOBJECT: Linking function list up\n"));
67 VAO(ptr)->functions = nclass->object_methods;
68
69 VAO(ptr)->oid = nclass->id;
70 VAO(ptr)->odata = NULL;
71
72 VAO(ptr)->refcount = 1;
73
74 ferite_add_to_gc( script, VAO(ptr) );
75 }
76 FE_LEAVE_FUNCTION( ptr );
77 }
78 /*}}}*/
79
80 /**
81 * @group Objects
82 */
83 /*{{{ FeriteVariable *ferite_new_object( FeriteScript *script, FeriteClass *nclass, FeriteVariable **plist ) */
84 /**
85 * @function ferite_new_object
86 * @declaration FeriteVariable *ferite_new_object( FeriteScript *script, FeriteClass *nclass, FeriteVariable **plist)
87 * @brief Create a new object - the C equivalent to the ferite 'new' keyword.
88 * @param FeriteScript *script The script to create the object within.
89 * @param FeriteClass *nclass The class to instantiate an object from
90 * @param FeriteVariable **plist The parameters to be passed to the objects constructor. This can be NULL for an empty
91 list.
92 * @return A variable that references the newly created object.
93 * @warning The return variable is marked as disposable. If you wish to retain a reference and return the object from a
94 native function you must 'UNMARK_VARIABLE_AS_DISPOSABLE'
95 */
ferite_new_object(FeriteScript * script,FeriteClass * nclass,FeriteVariable ** plist)96 FeriteVariable *ferite_new_object( FeriteScript *script, FeriteClass *nclass, FeriteVariable **plist)
97 {
98 FeriteVariable *ptr = NULL, *rval = NULL;
99 FeriteFunction *func = NULL;
100 FeriteVariable **params = NULL;
101
102 FE_ENTER_FUNCTION;
103 if(nclass != NULL)
104 {
105 if( nclass->state == FE_ITEM_IS_ABSTRACT )
106 {
107 ferite_error( script, 0, "You can't create instances of the abstract class %s\n", nclass->name );
108 FE_LEAVE_FUNCTION( NULL );
109 }
110 else if( nclass->state == FE_ITEM_IS_PROTOCOL )
111 {
112 ferite_error( script, 0, "You can't create instances of the protocol %s\n", nclass->name );
113 FE_LEAVE_FUNCTION( NULL );
114 }
115
116 if( plist != NULL )
117 params = plist;
118 else
119 params = ferite_create_parameter_list( 3 );
120
121 ptr = ferite_build_object(script,nclass);
122
123 FUD(("NEWOBJECT: Marking as disposable\n" ));
124 MARK_VARIABLE_AS_DISPOSABLE( ptr );
125
126 FUD(("NEWOBJECT: Searching for constructor\n" ));
127 func = ferite_find_constructor( script, VAO(ptr), params );
128 if( func != NULL )
129 {
130 FUD(("OPS: Calling constructor in class %s\n", nclass->name ));
131
132 if( func->type == FNC_IS_EXTRL )
133 rval = (func->fncPtr)( script, VAO(ptr), NULL, func, params );
134 else
135 rval = ferite_script_function_execute( script, VAO(ptr), NULL, func, params );
136
137 if( rval == NULL || (rval != NULL && rval->type == F_VAR_OBJ && VAO(rval) == NULL) )
138 {
139 if( rval == NULL )
140 ferite_error( script, 0, "Unable to instantiate object from class '%s'\n", nclass->name );
141
142 /* clean up the class */
143 ferite_delete_object_variable_list( script, VAO(ptr)->variables );
144 VAO(ptr)->variables = NULL;
145 VAO(ptr)->functions = NULL;
146 VAO(ptr)->klass = NULL;
147 ffree( VAO(ptr)->name );
148
149 /* set our return val to NULL */
150 VAO(ptr) = NULL;
151 }
152 if( rval != NULL )
153 ferite_variable_destroy( script, rval );
154 }
155 else
156 ferite_error( script, 0, "Unable to find constructor of the class '%s' for the given parameters\n", nclass->name );
157
158 if( plist == NULL )
159 ferite_delete_parameter_list( script, params );
160 }
161 FE_LEAVE_FUNCTION( ptr );
162 }
163 /*}}}*/
164 /** @end */
165
166 /*{{{ FERITE_UNARY_OP( left_incrc ) */
FERITE_UNARY_OP(left_incr)167 FERITE_UNARY_OP( left_incr )
168 {
169 FeriteVariable *ptr = NULL;
170
171 FE_ENTER_FUNCTION;
172 LOCK_VARIABLE(a);
173 GET_A_VAR;
174
175 if( !FE_VAR_IS_FINALSET( a ) )
176 {
177 switch( a->type )
178 {
179 case F_VAR_LONG:
180 FUD(("OPS: Incrementing %s from %ld to ", a->name, VAI( a ) ));
181 VAI( a ) += 1;
182 FUD(("%ld\n", VAI( a ) ));
183 /* ptr = ferite_duplicate_variable( script, a, NULL );
184 MARK_VARIABLE_AS_DISPOSABLE( ptr ); */
185 break;
186 default:
187 ferite_error( script, 0, "Can't increment variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
188 }
189 if( FE_VAR_IS_FINAL( a ) )
190 MARK_VARIABLE_AS_FINALSET( a );
191 }
192 UNLOCK_VARIABLE(a);
193 FE_LEAVE_FUNCTION( a/*ptr*/ );
194 }
195 /*}}}*/
196
197 /*{{{ FERITE_UNARY_OP( right_incr ) */
FERITE_UNARY_OP(right_incr)198 FERITE_UNARY_OP( right_incr )
199 {
200 FeriteVariable *ptr = NULL;
201
202 FE_ENTER_FUNCTION;
203 LOCK_VARIABLE(a);
204 GET_A_VAR;
205
206 if( !FE_VAR_IS_FINALSET( a ) )
207 {
208 switch( a->type )
209 {
210 case F_VAR_LONG:
211 ptr = ferite_duplicate_variable( script, a, NULL );
212 FUD(("OPS: Incrementing %s from %ld to ", a->name, VAI( a ) ));
213 VAI( a ) += 1;
214 FUD(("%ld\n", VAI( a ) ));
215 MARK_VARIABLE_AS_DISPOSABLE( ptr );
216 break;
217 default:
218 ferite_error( script, 0,"Can't increment variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
219 }
220 if( FE_VAR_IS_FINAL( a ) )
221 MARK_VARIABLE_AS_FINALSET( a );
222 }
223 UNLOCK_VARIABLE(a);
224 FE_LEAVE_FUNCTION( ptr );
225 }
226 /*}}}*/
227
228 /*{{{ FERITE_UNARY_OP( left_decr ) */
FERITE_UNARY_OP(left_decr)229 FERITE_UNARY_OP( left_decr )
230 {
231 FeriteVariable *ptr = NULL;
232
233 FE_ENTER_FUNCTION;
234 LOCK_VARIABLE(a);
235 GET_A_VAR;
236
237 if( !FE_VAR_IS_FINALSET( a ) )
238 {
239 switch( a->type )
240 {
241 case F_VAR_LONG:
242 FUD(("OPS: Decrementing %s from %ld to ", a->name, VAI( a ) ));
243 VAI( a ) -= 1;
244 FUD(("%ld\n", VAI( a ) ));
245 /* ptr = ferite_duplicate_variable( script, a, NULL );
246 MARK_VARIABLE_AS_DISPOSABLE( ptr );*/
247 break;
248 default:
249 ferite_error( script, 0,"Can't decrement variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
250 }
251 if( FE_VAR_IS_FINAL( a ) )
252 MARK_VARIABLE_AS_FINALSET( a );
253 }
254 UNLOCK_VARIABLE(a);
255 FE_LEAVE_FUNCTION( a/*ptr*/ );
256 }
257 /*}}}*/
258
259 /*{{{ FERITE_UNARY_OP( right_decr ) */
FERITE_UNARY_OP(right_decr)260 FERITE_UNARY_OP( right_decr )
261 {
262 FeriteVariable *ptr = NULL;
263
264 FE_ENTER_FUNCTION;
265 LOCK_VARIABLE(a);
266 GET_A_VAR;
267
268 if( !FE_VAR_IS_FINALSET( a ) )
269 {
270 switch( a->type )
271 {
272 case F_VAR_LONG:
273 ptr = ferite_duplicate_variable( script, a, NULL );
274 MARK_VARIABLE_AS_DISPOSABLE( ptr );
275 FUD(("OPS: Decrementing %s from %ld to ", a->name, VAI( a ) ));
276 VAI( a ) -= 1;
277 FUD(("%ld\n", VAI( a ) ));
278 break;
279 default:
280 ferite_error( script, 0, "Can't decrement variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
281 }
282 if( FE_VAR_IS_FINAL( a ) )
283 MARK_VARIABLE_AS_FINALSET( a );
284 }
285 UNLOCK_VARIABLE(a);
286 FE_LEAVE_FUNCTION( ptr );
287 }
288 /*}}}*/
289
290 /*{{{ FERITE_UNARY_OP( positive_var ) */
FERITE_UNARY_OP(positive_var)291 FERITE_UNARY_OP( positive_var )
292 {
293 FeriteVariable *ptr = NULL;
294
295 FE_ENTER_FUNCTION;
296 LOCK_VARIABLE(a);
297 GET_A_VAR;
298
299 switch( a->type )
300 {
301 case F_VAR_LONG:
302 ptr = ferite_duplicate_variable( script, a, NULL );
303 MARK_VARIABLE_AS_DISPOSABLE( ptr );
304 if( VAI(ptr) < 0 )
305 {
306 VAI(ptr) = 0 - VAI(ptr);
307 }
308 break;
309 case F_VAR_DOUBLE:
310 ptr = ferite_duplicate_variable( script, a, NULL );
311 MARK_VARIABLE_AS_DISPOSABLE( ptr );
312 if( VAF(ptr) < 0 )
313 {
314 VAF(ptr) = 0 - VAF(ptr);
315 }
316 break;
317 default:
318 ferite_error( script, 0, "Can't positise variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
319 }
320 UNLOCK_VARIABLE(a);
321 FE_LEAVE_FUNCTION( ptr );
322 }
323 /*}}}*/
324
325 /*{{{ FERITE_UNARY_OP( negative_var ) */
FERITE_UNARY_OP(negative_var)326 FERITE_UNARY_OP( negative_var )
327 {
328 FeriteVariable *ptr = NULL;
329
330 FE_ENTER_FUNCTION;
331 LOCK_VARIABLE(a);
332 GET_A_VAR;
333
334 switch( a->type )
335 {
336 case F_VAR_LONG:
337 ptr = ferite_duplicate_variable( script, a, NULL );
338 MARK_VARIABLE_AS_DISPOSABLE( ptr );
339 VAI(ptr) = 0 - VAI(ptr);
340 break;
341 case F_VAR_DOUBLE:
342 ptr = ferite_duplicate_variable( script, a, NULL );
343 MARK_VARIABLE_AS_DISPOSABLE( ptr );
344 VAF(ptr) = 0 - VAF(ptr);
345 break;
346 default:
347 ferite_error( script, 0, "Can't negatise variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
348 }
349 UNLOCK_VARIABLE(a);
350 FE_LEAVE_FUNCTION( ptr );
351 }
352 /*}}}*/
353
354 /*{{{ MACROS FOR WRITING CLEAN OPERATORS */
355
356 #define RETVNAME( n ) "op-" n "-return-value"
357
358 #define BEGIN_BLOCK( t, var ) \
359 case t: \
360 switch( var->type ) \
361 {
362
363 #define END_BLOCK \
364 } \
365 break;
366
367 #define BEGIN_OP( var ) \
368 FeriteVariable *retv = NULL; \
369 FE_ENTER_FUNCTION; \
370 LOCK_VARIABLE(a); \
371 LOCK_VARIABLE(b); \
372 GET_INPUT_VARS; \
373 switch( var->type ){
374
375 #define BLOCK_DIE( t ) \
376 default: \
377 ferite_error( script, 1, "Can't %s variables of type %s and %s\n", t, \
378 ferite_variable_id_to_str( script,a->type), ferite_variable_id_to_str( script,b->type) );
379
380 #define END_OP( d ) \
381 BLOCK_DIE( d )\
382 } \
383 if( retv != NULL ) { MARK_VARIABLE_AS_DISPOSABLE( retv ); } \
384 UNLOCK_VARIABLE(a); \
385 UNLOCK_VARIABLE(b); \
386 FE_LEAVE_FUNCTION( retv );
387
388 #define DO_OP( t, cv, c ) \
389 case t: \
390 cv; \
391 c; \
392 break;
393
394 #define FE_VAR_TRUE( var, op ) var = ferite_create_number_long_variable( script, RETVNAME( op ), FE_TRUE, FE_STATIC )
395 #define FE_VAR_FALSE( var, op ) var = ferite_create_number_long_variable( script, RETVNAME( op ), FE_FALSE, FE_STATIC )
396
397 #define FE_VAR_TEST( test, op ) \
398 if( test ) \
399 FE_VAR_TRUE( ptr, op ); \
400 else \
401 FE_VAR_FALSE( ptr, op );
402
403 #define FE_OP_RETURN_VOID( var, op ) \
404 var = ferite_create_void_variable( script, RETVNAME( op ), FE_STATIC ); \
405 MARK_VARIABLE_AS_DISPOSABLE(var); \
406 FE_LEAVE_FUNCTION( var );
407
408 #define TEST_ZERO( test ) \
409 if( test == 0 ){ \
410 ferite_error( script, 0, "Divide By Zero Error\n" ); \
411 FE_LEAVE_FUNCTION( NULL ); }
412
413 /*}}}*/
414
415 /*{{{ FERITE_UNARY_OP( not_op ) */
FERITE_UNARY_OP(not_op)416 FERITE_UNARY_OP( not_op )
417 {
418 FeriteVariable *ptr;
419
420 FE_ENTER_FUNCTION;
421 LOCK_VARIABLE(a);
422 GET_A_VAR;
423
424 if( !ferite_variable_is_false( script,a ) )
425 FE_VAR_FALSE( ptr, "not-op" );
426 else
427 FE_VAR_TRUE( ptr, "not-op" );
428 MARK_VARIABLE_AS_DISPOSABLE( ptr );
429 UNLOCK_VARIABLE(a);
430 FE_LEAVE_FUNCTION( ptr );
431 }
432 /*}}}*/
433
434 /*{{{ FERITE_UNARY_OP( eval ) */
FERITE_UNARY_OP(eval)435 FERITE_UNARY_OP( eval )
436 {
437 FeriteVariable *new_script_return = NULL;
438
439 FE_ENTER_FUNCTION;
440 GET_A_VAR;
441
442 if( a->type != F_VAR_STR )
443 {
444 ferite_error( script, 0, "Can not eval variables of type %s\n", ferite_variable_id_to_str( script,a->type) );
445 new_script_return = ferite_create_number_long_variable( script, "eval-return", FE_FALSE, FE_STATIC );
446 }
447 else
448 new_script_return = ferite_script_eval( script, FE_STR2PTR(a) );
449
450 if( new_script_return == NULL )
451 new_script_return = ferite_create_void_variable( script, "eval-gone-wrong", FE_STATIC );
452
453 MARK_VARIABLE_AS_DISPOSABLE( new_script_return );
454 FE_LEAVE_FUNCTION( new_script_return );
455 }
456 /*}}}*/
457
458 /*{{{ FERITE_UNARY_OP( include ) */
FERITE_UNARY_OP(include)459 FERITE_UNARY_OP( include )
460 {
461 FeriteVariable *ptr;
462
463 FE_ENTER_FUNCTION;
464 GET_A_VAR;
465
466 if( a->type != F_VAR_STR )
467 ferite_error( script, 0, "You must pass include a string\n" );
468
469 ptr = ferite_script_include( script, FE_STR2PTR(a) );
470
471 if( ptr == NULL )
472 {
473 ferite_error( script, 0, "Unable to include file '%s'\n", FE_STR2PTR(a) );
474 ptr = ferite_create_void_variable( script, "include-gone-wrong", FE_STATIC );
475 }
476
477 MARK_VARIABLE_AS_DISPOSABLE( ptr );
478 FE_LEAVE_FUNCTION( ptr );
479 }
480 /*}}}*/
481
482 /*{{{ FERITE_BINARY_OP( add ) */
FERITE_BINARY_OP(add)483 FERITE_BINARY_OP( add )
484 {
485 double dval = 0;
486 FeriteString *str = NULL;
487
488 BEGIN_OP( a )
489 BEGIN_BLOCK( F_VAR_DOUBLE, b )
490 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "add" ), VAF(a) + VAI(b), FE_STATIC ) )
491 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "add" ), VAF(a) + VAF(b), FE_STATIC ) )
492 BLOCK_DIE( "add" )
493 END_BLOCK
494 BEGIN_BLOCK( F_VAR_STR, b )
495 default:
496 retv = ferite_create_string_variable( script, "add", VAS(a), FE_STATIC );
497 str = ferite_variable_to_str( script, b,0 );
498 ferite_str_cat( VAS(retv), str );
499 ferite_str_destroy( str );
500 FUD(( "returning (str)\"%s\"\n", FE_STR2PTR(retv)));
501 END_BLOCK
502 BEGIN_BLOCK( F_VAR_LONG, b )
503 DO_OP( F_VAR_LONG,
504 dval = (double)VAI(a) + (double)VAI(b);
505 if( dval > (double)LONG_MAX )
506 retv = ferite_create_number_double_variable( script, RETVNAME( "add" ), dval, FE_STATIC );
507 else
508 retv = ferite_create_number_long_variable( script, RETVNAME( "add" ), VAI(a) + VAI(b), FE_STATIC ), NOWT )
509 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "add" ), VAI(a)+VAF(b), FE_STATIC ); )
510 BLOCK_DIE( "add" );
511 END_BLOCK
512 END_OP( "add" )
513 }
514 /*}}}*/
515
516 /*{{{ FERITE_BINARY_OP( minus ) */
FERITE_BINARY_OP(minus)517 FERITE_BINARY_OP( minus )
518 {
519 double dval = 0;
520 FeriteString *var = NULL, *tmp = NULL;
521
522 BEGIN_OP( a )
523 BEGIN_BLOCK( F_VAR_DOUBLE, b )
524 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "minus" ), VAF(a) - VAI(b), FE_STATIC ) )
525 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "minus" ), VAF(a) - VAF(b), FE_STATIC ) )
526 BLOCK_DIE( "minus" )
527 END_BLOCK
528 BEGIN_BLOCK( F_VAR_LONG, b )
529 DO_OP( F_VAR_LONG,
530 dval = (double)VAI(a) - (double)VAI(b);
531 if( dval < (double)LONG_MIN )
532 retv = ferite_create_number_double_variable( script, RETVNAME( "minus" ), (double)VAI(a) - (double)VAI(b), FE_STATIC );
533 else
534 retv = ferite_create_number_long_variable( script, RETVNAME( "minus" ), VAI(a)-VAI(b), FE_STATIC ) , NOWT )
535 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "minus" ), VAI(a)-VAF(b), FE_STATIC ); )
536 BLOCK_DIE( "minus" );
537 END_BLOCK
538 BEGIN_BLOCK( F_VAR_STR, b )
539 DO_OP( F_VAR_STR,
540 NOWT,
541 tmp = ferite_str_new( "", 0, FE_CHARSET_DEFAULT );
542 var = ferite_str_replace( VAS(a), VAS(b), tmp );
543 retv = ferite_create_string_variable( script, RETVNAME( "minus" ), var, FE_STATIC );
544 ferite_str_destroy( tmp );
545 ferite_str_destroy( var ); )
546 BLOCK_DIE( "minus" )
547 END_BLOCK
548 END_OP( "minus" )
549 }
550 /*}}}*/
551
552 /*{{{ FERITE_BINARY_OP( mult ) */
FERITE_BINARY_OP(mult)553 FERITE_BINARY_OP( mult )
554 {
555 double dval = 0;
556
557 BEGIN_OP( a )
558 BEGIN_BLOCK( F_VAR_DOUBLE, b )
559 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "mult" ), VAF(a) * VAI(b), FE_STATIC ) )
560 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "mult" ), VAF(a) * VAF(b), FE_STATIC ) )
561 BLOCK_DIE( "mult" )
562 END_BLOCK
563 BEGIN_BLOCK( F_VAR_LONG, b )
564 DO_OP( F_VAR_LONG,
565 dval = (double)VAI(a) * (double)VAI(b);
566 if( dval > (double)LONG_MAX )
567 retv = ferite_create_number_double_variable( script, RETVNAME( "mult" ), dval, FE_STATIC );
568 else
569 retv = ferite_create_number_long_variable( script, RETVNAME( "mult" ), VAI(a) * VAI(b), FE_STATIC ); , NOWT)
570 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_double_variable( script, RETVNAME( "mult" ), VAI(a)*VAF(b), FE_STATIC ); )
571 BLOCK_DIE( "mult" );
572 END_BLOCK
573 END_OP( "mult" )
574 }
575 /*}}}*/
576
577 /*{{{ FERITE_BINARY_OP( divide ) */
FERITE_BINARY_OP(divide)578 FERITE_BINARY_OP( divide )
579 {
580 BEGIN_OP( a )
581 BEGIN_BLOCK( F_VAR_DOUBLE, b )
582 DO_OP( F_VAR_LONG, TEST_ZERO( VAI(b) ), retv = ferite_create_number_double_variable( script, RETVNAME( "divide" ), VAF(a) / VAI(b), FE_STATIC ) )
583 DO_OP( F_VAR_DOUBLE, TEST_ZERO( VAF(b) ), retv = ferite_create_number_double_variable( script, RETVNAME( "divide" ), VAF(a) / VAF(b), FE_STATIC ) )
584 BLOCK_DIE( "divide" )
585 END_BLOCK
586 BEGIN_BLOCK( F_VAR_LONG, b )
587 DO_OP( F_VAR_LONG, TEST_ZERO( VAI(b) ), retv = ferite_create_number_long_variable( script, RETVNAME( "divide" ), VAI(a)/VAI(b), FE_STATIC ); )
588 DO_OP( F_VAR_DOUBLE, TEST_ZERO( VAF(b) ), retv = ferite_create_number_double_variable( script, RETVNAME( "divide" ), VAI(a)/VAF(b), FE_STATIC ); )
589 BLOCK_DIE( "divide" );
590 END_BLOCK
591 END_OP( "divide" )
592 }
593 /*}}}*/
594
595 /*{{{ FERITE_BINARY_OP( modulus ) */
FERITE_BINARY_OP(modulus)596 FERITE_BINARY_OP( modulus )
597 {
598 BEGIN_OP( a )
599 BEGIN_BLOCK( F_VAR_DOUBLE, b )
600 DO_OP( F_VAR_LONG, if( VAI(b) == 0 ) ferite_error( script, 0, "modulus By Zero Error\n" ); , retv = ferite_create_number_double_variable( script, RETVNAME( "modulus" ), (long)VAF(a) % VAI(b), FE_STATIC ) )
601 DO_OP( F_VAR_DOUBLE, if( VAF(b) == 0 ) ferite_error( script, 0, "modulus By Zero Error\n" ); , retv = ferite_create_number_double_variable( script, RETVNAME( "modulus" ), (long)VAF(a) % (long)VAF(b), FE_STATIC ) )
602 BLOCK_DIE( "modulus" )
603 END_BLOCK
604 BEGIN_BLOCK( F_VAR_LONG, b )
605 DO_OP( F_VAR_LONG, if( VAI(b) == 0 ) ferite_error( script, 0, "modulus By Zero Error\n" );, retv = ferite_create_number_long_variable( script, RETVNAME( "modulus" ), VAI(a)%VAI(b), FE_STATIC ); )
606 DO_OP( F_VAR_DOUBLE, if( VAF(b) == 0 ) ferite_error( script, 0, "modulus By Zero Error\n" );, retv = ferite_create_number_double_variable( script, RETVNAME( "modulus" ), VAI(a)%(long)VAF(b), FE_STATIC ); )
607 BLOCK_DIE( "modulus" );
608 END_BLOCK
609 END_OP( "modulus" )
610 }
611 /*}}}*/
612
613 /*{{{ FERITE_BINARY_OP( assign ) */
FERITE_BINARY_OP(assign)614 FERITE_BINARY_OP( assign )
615 {
616 FeriteVariable *retv = NULL;
617
618 FE_ENTER_FUNCTION;
619 LOCK_VARIABLE(a);
620 LOCK_VARIABLE(b);
621 GET_B_VAR;
622 if( !FE_VAR_IS_FINALSET( a ) )
623 {
624 switch( a->type )
625 {
626 BEGIN_BLOCK( F_VAR_LONG, b )
627 DO_OP( F_VAR_LONG, VAI(a) = VAI(b);, retv = ferite_create_number_long_variable( script, RETVNAME( "assign" ), VAI(a), FE_STATIC ); )
628 DO_OP( F_VAR_DOUBLE, a->type = F_VAR_DOUBLE; VAF(a) = VAF(b);, retv = ferite_create_number_double_variable( script, RETVNAME( "assign" ), VAF(a), FE_STATIC ); )
629 BLOCK_DIE( "assign" )
630 END_BLOCK
631
632 BEGIN_BLOCK( F_VAR_STR, b )
633 DO_OP( F_VAR_STR, ferite_str_cpy(VAS(a), VAS(b));, retv = ferite_create_string_variable( script, RETVNAME( "assign" ), VAS(a), FE_STATIC ); )
634 BLOCK_DIE( "assign" )
635 END_BLOCK
636
637 BEGIN_BLOCK( F_VAR_DOUBLE, b )
638 DO_OP( F_VAR_DOUBLE, VAF(a) = VAF(b);, retv = ferite_create_number_double_variable( script, RETVNAME( "assign" ), VAF(a), FE_STATIC ); )
639 DO_OP( F_VAR_LONG, a->type = F_VAR_LONG; VAI(a) = VAI(b);, retv = ferite_create_number_long_variable( script, RETVNAME( "assign" ), VAI(a), FE_STATIC ); )
640 BLOCK_DIE( "assign" )
641 END_BLOCK
642
643 BEGIN_BLOCK( F_VAR_OBJ, b )
644 DO_OP( F_VAR_OBJ,
645 if( VAO(a) != NULL )
646 {
647 VAO(a)->refcount -= a->refcount;
648 if( VAO(a)->refcount <= 0 )
649 FUD(("OPS: GC: Object \"%s\" Flagged for DELETION\n", a->name));
650 }
651 if( VAO(b) != NULL )
652 VAO(b)->refcount += a->refcount + 1;
653 VAO(a) = VAO(b);,
654 retv = ferite_create_object_variable( script, RETVNAME( "assign" ), FE_STATIC );
655 VAO(retv) = VAO(b);
656 )
657 BLOCK_DIE( "assign" );
658 END_BLOCK
659
660 BEGIN_BLOCK( F_VAR_UARRAY, b )
661 DO_OP( F_VAR_UARRAY,
662 ferite_uarray_destroy( script, VAUA(a));,
663 VAUA(a) = ferite_uarray_dup( script, VAUA(b), (void *(*)(FeriteScript*,FeriteVariable *,void *))ferite_duplicate_variable );
664 retv = ferite_duplicate_variable( script, a, NULL );
665 )
666 BLOCK_DIE( "assign" );
667 END_BLOCK
668
669 BEGIN_BLOCK( F_VAR_VOID, b )
670 DO_OP( F_VAR_LONG,
671 a->type = F_VAR_LONG;
672 VAI(a) = VAI(b);,
673 retv = ferite_create_number_long_variable( script, RETVNAME( "assign" ), VAI(a), FE_STATIC );
674 )
675 DO_OP( F_VAR_DOUBLE,
676 a->type = F_VAR_DOUBLE;
677 VAF(a) = VAF(b);,
678 retv = ferite_create_number_double_variable( script, RETVNAME( "assign" ), VAF(a), FE_STATIC );
679 )
680 DO_OP( F_VAR_STR,
681 a->type = F_VAR_STR;
682 VAS(a) = ferite_str_dup(VAS(b));,
683 retv = ferite_create_string_variable( script, RETVNAME( "assign" ), VAS(a), FE_STATIC );
684 )
685 DO_OP( F_VAR_OBJ,
686 a->type = F_VAR_OBJ;
687 if( VAO(b) != NULL )
688 VAO(b)->refcount++;
689 VAO(a) = VAO(b);,
690 retv = ferite_create_number_long_variable( script, RETVNAME( "assign" ), 1, FE_STATIC );
691 )
692 DO_OP( F_VAR_UARRAY,
693 a->type = F_VAR_UARRAY;
694 VAUA(a) = ferite_uarray_dup( script, VAUA(b), (void *(*)(FeriteScript*,FeriteVariable *,void*))ferite_duplicate_variable );,
695 retv = ferite_duplicate_variable( script, a, NULL );
696 )
697 DO_OP( F_VAR_VOID, NOWT,
698 retv = ferite_create_void_variable( script, RETVNAME( "assign" ), FE_STATIC );
699 )
700 DO_OP( F_VAR_NS, NOWT,
701 a->type = F_VAR_NS;
702 VAP(a) = VAN(b);
703 retv = ferite_create_void_variable( script, RETVNAME( "assign" ), FE_STATIC );
704 retv->type = F_VAR_NS;
705 VAP(retv) = VAN(b);
706 )
707 DO_OP( F_VAR_CLASS, NOWT,
708 a->type = F_VAR_CLASS;
709 VAP(a) = VAC(b);
710 retv = ferite_create_void_variable( script, RETVNAME( "assign" ), FE_STATIC );
711 retv->type = F_VAR_CLASS;
712 VAP(retv) = VAC(b);
713 )
714 BLOCK_DIE( "assign" );
715 END_BLOCK
716 BLOCK_DIE( "assign" );
717 }
718 if( FE_VAR_IS_FINAL( a ) )
719 MARK_VARIABLE_AS_FINALSET( a ); /* set it so that the variable is constant for forever and a day */
720
721 /* call the set method */
722 if( a->accessors != NULL && a->accessors->set != NULL )
723 {
724 FUD(( "calling var->set()\n" ));
725 (a->accessors->set)( script, a, b );
726 }
727 }
728 else
729 {
730 ferite_error( script, 0, "Can not assign to a constant variable.\n" );
731 retv = ferite_create_void_variable( script, RETVNAME( "assign" ), FE_STATIC );
732 }
733 if( retv != NULL )
734 MARK_VARIABLE_AS_DISPOSABLE( retv );
735 UNLOCK_VARIABLE(a);
736 UNLOCK_VARIABLE(b);
737 FE_LEAVE_FUNCTION( retv );
738 }
739 /*}}}*/
740
741 /*{{{ FERITE_BINARY_OP( add_assign ) */
FERITE_BINARY_OP(add_assign)742 FERITE_BINARY_OP( add_assign )
743 {
744 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
745
746 FE_ENTER_FUNCTION;
747 LOCK_VARIABLE(a);
748 LOCK_VARIABLE(b);
749
750 tmp_ptr = ferite_op_add( script, a, b );
751 if( tmp_ptr != NULL )
752 {
753 ptr = ferite_op_assign( script, a, tmp_ptr );
754 MARK_VARIABLE_AS_DISPOSABLE( ptr );
755 ferite_variable_destroy( script, tmp_ptr );
756 }
757
758 UNLOCK_VARIABLE(a);
759 UNLOCK_VARIABLE(b);
760 FE_LEAVE_FUNCTION( ptr );
761 }
762 /*}}}*/
763
764 /*{{{ FERITE_BINARY_OP( minus_assign ) */
FERITE_BINARY_OP(minus_assign)765 FERITE_BINARY_OP( minus_assign )
766 {
767 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
768
769 FE_ENTER_FUNCTION;
770 LOCK_VARIABLE(a);
771 LOCK_VARIABLE(b);
772
773 tmp_ptr = ferite_op_minus( script, a, b );
774 if( tmp_ptr != NULL )
775 {
776 ptr = ferite_op_assign( script, a, tmp_ptr );
777 MARK_VARIABLE_AS_DISPOSABLE( ptr );
778 ferite_variable_destroy( script, tmp_ptr );
779 }
780
781 UNLOCK_VARIABLE(a);
782 UNLOCK_VARIABLE(b);
783 FE_LEAVE_FUNCTION( ptr );
784 }
785 /*}}}*/
786
787 /*{{{ FERITE_BINARY_OP( mult_assign ) */
FERITE_BINARY_OP(mult_assign)788 FERITE_BINARY_OP( mult_assign )
789 {
790 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
791
792 FE_ENTER_FUNCTION;
793 LOCK_VARIABLE(a);
794 LOCK_VARIABLE(b);
795
796 tmp_ptr = ferite_op_mult( script, a, b );
797 if( tmp_ptr != NULL )
798 {
799 ptr = ferite_op_assign( script, a, tmp_ptr );
800 MARK_VARIABLE_AS_DISPOSABLE( ptr );
801 ferite_variable_destroy( script, tmp_ptr );
802 }
803
804 UNLOCK_VARIABLE(a);
805 UNLOCK_VARIABLE(b);
806 FE_LEAVE_FUNCTION( ptr );
807 }
808 /*}}}*/
809
810 /*{{{ FERITE_BINARY_OP( divide_assign ) */
FERITE_BINARY_OP(divide_assign)811 FERITE_BINARY_OP( divide_assign )
812 {
813 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
814
815 FE_ENTER_FUNCTION;
816 LOCK_VARIABLE(a);
817 LOCK_VARIABLE(b);
818
819 tmp_ptr = ferite_op_divide( script, a, b );
820 if( tmp_ptr != NULL )
821 {
822 ptr = ferite_op_assign( script, a, tmp_ptr );
823 MARK_VARIABLE_AS_DISPOSABLE( ptr );
824 ferite_variable_destroy( script, tmp_ptr );
825 }
826
827 UNLOCK_VARIABLE(a);
828 UNLOCK_VARIABLE(b);
829 FE_LEAVE_FUNCTION( ptr );
830 }
831 /*}}}*/
832
833 /*{{{ FERITE_BINARY_OP( logical_or ) */
FERITE_BINARY_OP(logical_or)834 FERITE_BINARY_OP( logical_or )
835 {
836 FeriteVariable *ptr;
837
838 FE_ENTER_FUNCTION;
839 LOCK_VARIABLE(a);
840 LOCK_VARIABLE(b);
841 GET_INPUT_VARS;
842
843 FE_VAR_TEST( (!ferite_variable_is_false( script,a) || !ferite_variable_is_false( script,b )), "logical_or" );
844 MARK_VARIABLE_AS_DISPOSABLE( ptr );
845
846 UNLOCK_VARIABLE(a);
847 UNLOCK_VARIABLE(b);
848 FE_LEAVE_FUNCTION( ptr );
849 }
850 /*}}}*/
851
852 /*{{{ FERITE_BINARY_OP( logical_and ) */
FERITE_BINARY_OP(logical_and)853 FERITE_BINARY_OP( logical_and )
854 {
855 FeriteVariable *ptr;
856
857 FE_ENTER_FUNCTION;
858 LOCK_VARIABLE(a);
859 LOCK_VARIABLE(b);
860 GET_INPUT_VARS;
861
862 FE_VAR_TEST( (!ferite_variable_is_false( script,a) && !ferite_variable_is_false( script,b )), "logical_and" );
863 MARK_VARIABLE_AS_DISPOSABLE( ptr );
864
865 UNLOCK_VARIABLE(a);
866 UNLOCK_VARIABLE(b);
867 FE_LEAVE_FUNCTION( ptr );
868 }
869 /*}}}*/
870
871 /*{{{ FERITE_BINARY_OP( equals ) */
872 /* binary operators that push a true or falsae value onto the stack */
FERITE_BINARY_OP(equals)873 FERITE_BINARY_OP( equals )
874 {
875 FeriteVariable *ptr = NULL;
876
877 FE_ENTER_FUNCTION;
878 LOCK_VARIABLE(a);
879 LOCK_VARIABLE(b);
880 GET_INPUT_VARS;
881 if( a->type != b->type &&
882 !(a->type == F_VAR_LONG && b->type == F_VAR_DOUBLE) &&
883 !(a->type == F_VAR_DOUBLE && b->type == F_VAR_LONG) )
884 {
885 FUD(("OPS: Variable types do not match in equals( %s, %s )\nReturning false\n", a->name, b->name ));
886 ptr = ferite_create_number_long_variable( script, "equals", 0, FE_STATIC );
887 MARK_VARIABLE_AS_DISPOSABLE( ptr );
888 UNLOCK_VARIABLE(a);
889 UNLOCK_VARIABLE(b);
890 FE_LEAVE_FUNCTION( ptr );
891 }
892 /* we know that they are the same */
893 switch( a->type )
894 {
895 case F_VAR_LONG:
896 case F_VAR_DOUBLE:
897 {
898 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
899 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
900 double delta = left - right;
901 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
902 {
903 FE_VAR_TEST( (delta < 0.000001 && delta > -0.000001), "equals" );
904 }
905 else
906 {
907 FE_VAR_TEST( (VAI(a) == VAI(b)), "equals" );
908 }
909 break;
910 }
911 case F_VAR_STR:
912 FE_VAR_TEST( (ferite_str_cmp( VAS(a), VAS(b) ) == 1), "equals" );
913 break;
914 case F_VAR_OBJ:
915 FE_VAR_TEST( (VAO(a) == VAO(b)), "equals" );
916 break;
917 case F_VAR_UARRAY:
918 FE_VAR_TEST( (ferite_uarray_cmp( script, VAUA(a), VAUA(b) ) == 1), "equals" );
919 break;
920 case F_VAR_VOID:
921 FE_VAR_TEST( FE_TRUE, "equals" );
922 break;
923 case F_VAR_CLASS:
924 FE_VAR_TEST( (VAC(a) == VAC(b)), "equals" );
925 break;
926 case F_VAR_NS:
927 FE_VAR_TEST( (VAN(a) == VAN(b)), "equals" );
928 break;
929 default:
930 ferite_error( script, 0, "EEEK: unknown type %s in equals()\n", ferite_variable_id_to_str( script,a->type ) );
931 }
932 if( ptr )
933 MARK_VARIABLE_AS_DISPOSABLE( ptr );
934 UNLOCK_VARIABLE(a);
935 UNLOCK_VARIABLE(b);
936 FE_LEAVE_FUNCTION( ptr );
937 }
938 /*}}}*/
939
940 /*{{{ FERITE_BINARY_OP( case ) */
941 /* binary operators that push a true or falsae value onto the stack */
FERITE_BINARY_OP(case)942 FERITE_BINARY_OP( case )
943 {
944 FeriteVariable *ptr = NULL;
945
946 FE_ENTER_FUNCTION;
947 LOCK_VARIABLE(a);
948 LOCK_VARIABLE(b);
949 GET_INPUT_VARS;
950
951 if( a->type != b->type &&
952 !(a->type == F_VAR_LONG && b->type == F_VAR_DOUBLE) &&
953 !(a->type == F_VAR_DOUBLE && b->type == F_VAR_LONG) )
954 {
955 FUD(("OPS: Variable types do not match in equals( %s, %s )\nReturning false\n", a->name, b->name ));
956 ptr = ferite_create_number_long_variable( script, "equals", 0, FE_STATIC );
957 MARK_VARIABLE_AS_DISPOSABLE( ptr );
958 UNLOCK_VARIABLE(a);
959 UNLOCK_VARIABLE(b);
960 FE_LEAVE_FUNCTION( ptr );
961 }
962 /* we know that they are the same */
963 switch( a->type )
964 {
965 case F_VAR_LONG:
966 case F_VAR_DOUBLE:
967 {
968 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
969 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
970 double delta = left - right;
971 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
972 {
973 FE_VAR_TEST( (delta < 0.000001 && delta > -0.000001), "equals" );
974 }
975 else
976 {
977 FE_VAR_TEST( (VAI(a) == VAI(b)), "equals" );
978 }
979 break;
980 }
981 case F_VAR_STR:
982 FE_VAR_TEST( (ferite_str_cmp( VAS(a), VAS(b) ) == 1), "equals" );
983 break;
984 case F_VAR_OBJ:
985 FE_VAR_TEST( (VAO(a) == VAO(b)), "equals" );
986 break;
987 default:
988 ferite_error( script, 0, "EEEK: unknown type %s in equals()\n", ferite_variable_id_to_str( script,a->type ) );
989 }
990 if( ptr )
991 MARK_VARIABLE_AS_DISPOSABLE( ptr );
992 UNLOCK_VARIABLE(a);
993 UNLOCK_VARIABLE(b);
994 FE_LEAVE_FUNCTION( ptr );
995 }
996 /*}}}*/
997
998 /*{{{ FERITE_BINARY_OP( notequals ) */
FERITE_BINARY_OP(notequals)999 FERITE_BINARY_OP( notequals )
1000 {
1001 FeriteVariable *ptr, *tptr;
1002
1003 FE_ENTER_FUNCTION;
1004 LOCK_VARIABLE(a);
1005 LOCK_VARIABLE(b);
1006 GET_INPUT_VARS;
1007 tptr = ferite_op_equals( script, a, b );
1008 FE_VAR_TEST( (ferite_variable_is_false( script,tptr )), "not_equals" );
1009 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1010 ferite_variable_destroy( script, tptr );
1011 UNLOCK_VARIABLE(a);
1012 UNLOCK_VARIABLE(b);
1013 FE_LEAVE_FUNCTION( ptr );
1014 }
1015 /*}}}*/
1016
1017 /*{{{ FERITE_BINARY_OP( less_than ) */
FERITE_BINARY_OP(less_than)1018 FERITE_BINARY_OP( less_than )
1019 {
1020 FeriteVariable *ptr = NULL;
1021
1022 FE_ENTER_FUNCTION;
1023 LOCK_VARIABLE(a);
1024 LOCK_VARIABLE(b);
1025 GET_INPUT_VARS;
1026
1027 switch( a->type )
1028 {
1029 case F_VAR_LONG:
1030 case F_VAR_DOUBLE:
1031 {
1032 switch( b->type )
1033 {
1034 case F_VAR_LONG:
1035 case F_VAR_DOUBLE:
1036 {
1037 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
1038 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
1039 double delta = left - right;
1040 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
1041 {
1042 FE_VAR_TEST( (delta < 0.0), "less-than" );
1043 }
1044 else
1045 {
1046 FE_VAR_TEST( (VAI(a) < VAI(b)), "less-than" );
1047 }
1048 break;
1049 }
1050 default:
1051 ferite_error( script, 0, "ERROR: can't compare values of type %s with integers\n", ferite_variable_id_to_str( script,b->type) );
1052 }
1053 break;
1054 }
1055 default:
1056 ferite_error( script, 0, "ERK, can't compare items of type %s and %s\n", ferite_variable_id_to_str( script,a->type), ferite_variable_id_to_str( script, b->type ));
1057 }
1058 if( ptr )
1059 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1060 UNLOCK_VARIABLE(a);
1061 UNLOCK_VARIABLE(b);
1062 FE_LEAVE_FUNCTION( ptr );
1063 }
1064 /*}}}*/
1065
1066 /*{{{ FERITE_BINARY_OP( less_than_equals ) */
FERITE_BINARY_OP(less_than_equals)1067 FERITE_BINARY_OP( less_than_equals )
1068 {
1069 FeriteVariable *ptr = NULL;
1070
1071 FE_ENTER_FUNCTION;
1072 LOCK_VARIABLE(a);
1073 LOCK_VARIABLE(b);
1074 GET_INPUT_VARS;
1075
1076 switch( a->type )
1077 {
1078 case F_VAR_LONG:
1079 case F_VAR_DOUBLE:
1080 {
1081 switch( b->type )
1082 {
1083 case F_VAR_LONG:
1084 case F_VAR_DOUBLE:
1085 {
1086 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
1087 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
1088 double delta = left - right;
1089 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
1090 {
1091 FE_VAR_TEST( (delta <= 0.0), "less-than-equals" );
1092 }
1093 else
1094 {
1095 FE_VAR_TEST( (VAI(a) <= VAI(b)), "less-than-equals" );
1096 }
1097 break;
1098 }
1099 default:
1100 ferite_error( script, 0, "ERROR: can't compare values of type %s with integers\n", ferite_variable_id_to_str( script,b->type) );
1101 }
1102 break;
1103 }
1104 default:
1105 ferite_error( script, 0, "ERK, can't compare items of type %s and %s\n", ferite_variable_id_to_str( script,a->type), ferite_variable_id_to_str( script, b->type ));
1106 }
1107 if( ptr )
1108 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1109
1110 UNLOCK_VARIABLE(a);
1111 UNLOCK_VARIABLE(b);
1112 FE_LEAVE_FUNCTION( ptr );
1113 }
1114 /*}}}*/
1115
1116 /*{{{ FERITE_BINARY_OP( greater_than ) */
FERITE_BINARY_OP(greater_than)1117 FERITE_BINARY_OP( greater_than )
1118 {
1119 FeriteVariable *ptr = NULL;
1120
1121 FE_ENTER_FUNCTION;
1122 LOCK_VARIABLE(a);
1123 LOCK_VARIABLE(b);
1124 GET_INPUT_VARS;
1125
1126 switch( a->type )
1127 {
1128 case F_VAR_LONG:
1129 case F_VAR_DOUBLE:
1130 {
1131 switch( b->type )
1132 {
1133 case F_VAR_LONG:
1134 case F_VAR_DOUBLE:
1135 {
1136 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
1137 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
1138 double delta = left - right;
1139 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
1140 {
1141 FE_VAR_TEST( (delta > 0.0), "greater-than" );
1142 }
1143 else
1144 {
1145 FE_VAR_TEST( (VAI(a) > VAI(b)), "greater-than" );
1146 }
1147 break;
1148 }
1149 default:
1150 ferite_error( script, 0, "ERROR: can't compare values of type %s with integers\n", ferite_variable_id_to_str( script,b->type) );
1151 }
1152 break;
1153 }
1154 default:
1155 ferite_error( script, 0, "ERK, can't compare items of type %s and %s\n", ferite_variable_id_to_str( script,a->type), ferite_variable_id_to_str( script, b->type ));
1156 }
1157 if( ptr )
1158 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1159
1160 UNLOCK_VARIABLE(a);
1161 UNLOCK_VARIABLE(b);
1162 FE_LEAVE_FUNCTION( ptr );
1163 }
1164 /*}}}*/
1165
1166 /*{{{ FERITE_BINARY_OP( greater_than_equals ) */
FERITE_BINARY_OP(greater_than_equals)1167 FERITE_BINARY_OP( greater_than_equals )
1168 {
1169 FeriteVariable *ptr = NULL;
1170
1171 FE_ENTER_FUNCTION;
1172 LOCK_VARIABLE(a);
1173 LOCK_VARIABLE(b);
1174 GET_INPUT_VARS;
1175
1176 switch( a->type )
1177 {
1178 case F_VAR_LONG:
1179 case F_VAR_DOUBLE:
1180 {
1181 switch( b->type )
1182 {
1183 case F_VAR_LONG:
1184 case F_VAR_DOUBLE:
1185 {
1186 double left = (a->type == F_VAR_LONG ? (double)VAI(a) : VAF(a));
1187 double right = (b->type == F_VAR_LONG ? (double)VAI(b) : VAF(b));
1188 double delta = left - right;
1189 if( a->type == F_VAR_DOUBLE || b->type == F_VAR_DOUBLE )
1190 {
1191 FE_VAR_TEST( (delta >= 0.0), "greater-than-equals" );
1192 }
1193 else
1194 {
1195 FE_VAR_TEST( (VAI(a) >= VAI(b)), "greater-than-equals" );
1196 }
1197 break;
1198 }
1199 default:
1200 ferite_error( script, 0, "ERROR: can't compare values of type %s with integers\n", ferite_variable_id_to_str( script,b->type) );
1201 }
1202 break;
1203 }
1204 default:
1205 ferite_error( script, 0, "ERK, can't compare items of type %s and %s\n", ferite_variable_id_to_str( script,a->type), ferite_variable_id_to_str( script, b->type ));
1206 }
1207 if( ptr )
1208 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1209
1210 UNLOCK_VARIABLE(a);
1211 UNLOCK_VARIABLE(b);
1212 FE_LEAVE_FUNCTION( ptr );
1213 }
1214 /*}}}*/
1215
1216 /*{{{ FERITE_MANY_OP( array_slice ) */
FERITE_MANY_OP(array_slice)1217 FERITE_MANY_OP(array_slice)
1218 {
1219 FeriteVariable *result = NULL;
1220 FeriteVariable *array = NULL, *a = NULL, *b = NULL, *tmp = NULL;
1221 long size,lower,upper,ii,cal_lo,cal_up;
1222 char *buf = NULL;
1223 FeriteString *str = NULL;
1224
1225 FE_ENTER_FUNCTION;
1226
1227 /* FIXME: thread locking! */
1228
1229 array = vars[2];
1230 a = vars[1]; /* the lower bound */
1231 b = vars[0]; /* the upper bound */
1232
1233 GET_VAR( array );
1234 GET_INPUT_VARS;
1235
1236 if(array->type != F_VAR_STR && array->type != F_VAR_UARRAY)
1237 {
1238 ferite_error(script, 0, "Slices only work on Arrays and Strings\n");
1239 FE_OP_RETURN_VOID( result, "array_slice" );
1240 }
1241
1242 if(array->type == F_VAR_STR)
1243 size = FE_STRLEN(array);
1244 else
1245 size = VAUA(array)->size;
1246
1247 if(a->type == F_VAR_LONG)
1248 lower = VAI(a);
1249 else if(a->type == F_VAR_DOUBLE)
1250 lower = (int)floor(VAF(a));
1251 else
1252 {
1253 ferite_error(script, 0, "Invalid lower slice bound type: %s\n", ferite_variable_id_to_str(script, a->type));
1254 FE_OP_RETURN_VOID( result, "array_slice" );
1255 }
1256
1257 if(b->type == F_VAR_VOID && FE_VAR_IS_PLACEHOLDER( b ) )
1258 upper = size - 1;
1259 else if(b->type == F_VAR_LONG)
1260 upper = VAI(b);
1261 else if(b->type == F_VAR_DOUBLE)
1262 upper = (int)floor(VAF(b));
1263 else
1264 {
1265 ferite_error(script, 0, "Invalid upper slice bound type: %s\n", ferite_variable_id_to_str(script, b->type));
1266 FE_OP_RETURN_VOID( result, "array_slice" );
1267 }
1268
1269 cal_lo = lower;
1270 if(lower < 0)
1271 cal_lo = size + lower;
1272
1273 cal_up = upper;
1274 if( upper < 0 )
1275 cal_up = size + upper;
1276
1277 if(cal_lo < 0 || cal_up < 0 || cal_lo > size - 1 || cal_up > size - 1)
1278 {
1279 ferite_error(script, 0, "Invalid slice bounds: %d (%d) to %d (%d)\n",lower,cal_lo,upper,cal_up);
1280 FE_OP_RETURN_VOID( result, "array_slice" );
1281 }
1282 if(array->type == F_VAR_STR)
1283 {
1284 str = ferite_str_new( NULL, FE_STRLEN(array), FE_CHARSET_DEFAULT );
1285 buf = str->data;
1286 ii = 0;
1287 if(cal_lo > cal_up)
1288 {
1289 for(size=cal_lo;size >= cal_up; size--)
1290 {
1291 buf[ii] = FE_STR2PTR(array)[size];
1292 ii++;
1293 }
1294 }
1295 else
1296 {
1297 for(size=cal_lo;size <= cal_up; size++)
1298 {
1299 buf[ii] = FE_STR2PTR(array)[size];
1300 ii++;
1301 }
1302 }
1303
1304 buf[ii] = '\0';
1305 str->length = ii;
1306
1307 result = ferite_create_string_variable( script, "spliced_content", str, FE_STATIC );
1308 ferite_str_destroy( str );
1309 }
1310 else
1311 {
1312 result = ferite_create_uarray_variable( script, "spliced_content", VAUA(array)->size, FE_STATIC );
1313 if(cal_lo > cal_up)
1314 {
1315 for(size=cal_lo;size >= cal_up; size--)
1316 {
1317 tmp = ferite_uarray_get_index(script, VAUA(array),(int)size);
1318 tmp = ferite_duplicate_variable(script, tmp, NULL);
1319 ferite_uarray_add(script, VAUA(result), tmp, NULL, FE_ARRAY_ADD_AT_END);
1320 }
1321 }
1322 else
1323 {
1324 for(size=cal_lo;size <= cal_up; size++)
1325 {
1326 tmp = ferite_uarray_get_index(script, VAUA(array),(int)size);
1327 tmp = ferite_duplicate_variable(script, tmp, NULL);
1328 ferite_uarray_add(script, VAUA(result), tmp, NULL, FE_ARRAY_ADD_AT_END);
1329 }
1330 }
1331 }
1332 MARK_VARIABLE_AS_DISPOSABLE( result );
1333 FE_LEAVE_FUNCTION( result );
1334 }
1335 /*}}}*/
1336
1337 /*{{{ FERITE_BINARY_OP( array_index ) */
FERITE_BINARY_OP(array_index)1338 FERITE_BINARY_OP( array_index )
1339 {
1340 /* a = array variable */
1341 /* b = index */
1342 FeriteVariable *ptr = NULL;
1343 char *s;
1344
1345 FE_ENTER_FUNCTION;
1346 LOCK_VARIABLE(a);
1347 LOCK_VARIABLE(b);
1348 GET_INPUT_VARS;
1349
1350 if( a->type != F_VAR_STR && a->type != F_VAR_UARRAY)
1351 {
1352 ferite_error( script, 0, "OPS: array_index: First Variable is not an Array or String\n" );
1353 UNLOCK_VARIABLE(a);
1354 UNLOCK_VARIABLE(b);
1355 FE_LEAVE_FUNCTION(ptr);
1356 }
1357
1358 switch( a->type )
1359 {
1360 case F_VAR_STR:
1361 {
1362 switch( b->type )
1363 {
1364 case F_VAR_LONG:
1365 {
1366 size_t offset;
1367 if( VAI(b) > (signed)FE_STRLEN( a ) )
1368 {
1369 ferite_error( script, 0, "String index out of range [%d]\n", VAI(b) );
1370 break;
1371 }
1372 s = fmalloc(sizeof(char) * 2);
1373 if(VAI(b) < 0)
1374 {
1375 offset = FE_STRLEN( a ) + VAI( b );
1376 // printf("grabbing index %d (%d)\n",offset,strlen(VAS(a)) -1 );
1377 }
1378 else
1379 {
1380 offset = VAI(b);
1381 }
1382 s[0] = FE_STR2PTR(a)[offset];
1383 s[1] = '\0';
1384 ptr = ferite_create_string_variable_from_ptr( script, "array_String_return", s, 1, FE_CHARSET_DEFAULT, FE_STATIC );
1385 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1386 ffree(s);
1387 }
1388
1389 break;
1390 case F_VAR_DOUBLE:
1391 {
1392 size_t index = (size_t)VAF(b);
1393 if( VAI(b) > (signed)FE_STRLEN( a ) )
1394 {
1395 ferite_error( script, 0, "String index out of range [%d]\n", index );
1396 break;
1397 }
1398 s = fmalloc(sizeof(char) * 2);
1399 if(index < 0)
1400 {
1401 index = FE_STRLEN( a ) + index;
1402 }
1403 s[0] = FE_STR2PTR( a )[index];
1404 s[1] = '\0';
1405 ptr = ferite_create_string_variable_from_ptr( script, "array_String_return", s, 1, FE_CHARSET_DEFAULT, FE_STATIC );
1406 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1407 ffree(s);
1408 }
1409 break;
1410 default:
1411 ferite_error( script, 0, "Other index methods not implemented in strings (%s)\n", ferite_variable_id_to_str( script, b->type ) );
1412 }
1413 break;
1414 }
1415 case F_VAR_UARRAY:
1416 {
1417 if( b->type == F_VAR_STR && VAS(b)->length == 0 )
1418 ptr = ferite_create_void_variable( script, "array_void_variable", FE_STATIC );
1419 else
1420 ptr = ferite_uarray_op( script, VAUA(a), b, NULL );
1421 break;
1422 }
1423 }
1424 UNLOCK_VARIABLE(a);
1425 UNLOCK_VARIABLE(b);
1426 FE_LEAVE_FUNCTION( ptr );
1427 }
1428 /*}}}*/
1429
1430 /*{{{ FERITE_UNARY_OP( array_clear ) */
FERITE_UNARY_OP(array_clear)1431 FERITE_UNARY_OP( array_clear )
1432 {
1433 FeriteVariable *ptr = NULL;
1434 long iteration = 0, iteration_type = 0;
1435
1436 FE_ENTER_FUNCTION;
1437 LOCK_VARIABLE(a);
1438 GET_A_VAR;
1439
1440 if( a->type == F_VAR_UARRAY && VAUA(a)->size > 0 )
1441 {
1442 iteration = VAUA(a)->iteration;
1443 iteration_type = VAUA(a)->iterator_type;
1444
1445 ferite_uarray_destroy( script, VAUA(a) );
1446 VAUA(a) = ferite_uarray_create();
1447
1448 VAUA(a)->iteration = iteration;
1449 VAUA(a)->iterator_type = iteration_type;
1450 }
1451 UNLOCK_VARIABLE(a);
1452 FE_OP_RETURN_VOID( ptr, "array_clear" );
1453 }
1454 /*}}}*/
1455
1456 /*{{{ FERITE_BINARY_OP( left_shift ) */
FERITE_BINARY_OP(left_shift)1457 FERITE_BINARY_OP( left_shift )
1458 {
1459 BEGIN_OP( a )
1460 BEGIN_BLOCK( F_VAR_LONG, b )
1461 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "left_shift" ), VAI(a) << VAI(b), FE_STATIC ); )
1462 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "left_shift" ), VAI(a) << (long)VAF(b), FE_STATIC ); )
1463 BLOCK_DIE( "left_shift" );
1464 END_BLOCK
1465 BEGIN_BLOCK( F_VAR_DOUBLE, b )
1466 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "left_shift" ), (long)VAF(a) << VAI(b), FE_STATIC ); )
1467 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "left_shift" ), (long)VAF(a) << (long)VAF(b), FE_STATIC ); )
1468 BLOCK_DIE( "left_shift" );
1469 END_BLOCK
1470 END_OP( "left_shift" )
1471 }
1472 /*}}}*/
1473
1474 /*{{{ FERITE_BINARY_OP( right_shift ) */
FERITE_BINARY_OP(right_shift)1475 FERITE_BINARY_OP( right_shift )
1476 {
1477 BEGIN_OP( a )
1478 BEGIN_BLOCK( F_VAR_LONG, b )
1479 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "right_shift" ), VAI(a) >> VAI(b), FE_STATIC ); )
1480 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "right_shift" ), VAI(a) >> (long)VAF(b), FE_STATIC ); )
1481 BLOCK_DIE( "right_shift" );
1482 END_BLOCK
1483 BEGIN_BLOCK( F_VAR_DOUBLE, b )
1484 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "right_shift" ), (long)VAF(a) >> VAI(b), FE_STATIC ); )
1485 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "right_shift" ), (long)VAF(a) >> (long)VAF(b), FE_STATIC ); )
1486 BLOCK_DIE( "right_shift" );
1487 END_BLOCK
1488 END_OP( "right_shift" )
1489 }
1490 /*}}}*/
1491
1492 /*{{{ FERITE_BINARY_OP( binary_or ) */
FERITE_BINARY_OP(binary_or)1493 FERITE_BINARY_OP( binary_or )
1494 {
1495 BEGIN_OP( a )
1496 BEGIN_BLOCK( F_VAR_LONG, b )
1497 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_or" ), VAI(a) | VAI(b), FE_STATIC ); )
1498 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_or" ), VAI(a) | (long)VAF(b), FE_STATIC ); )
1499 BLOCK_DIE( "binary_or" );
1500 END_BLOCK
1501 BEGIN_BLOCK( F_VAR_DOUBLE, b )
1502 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_or" ), (long)VAF(a) | VAI(b), FE_STATIC ); )
1503 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_or" ), (long)VAF(a) | (long)VAF(b), FE_STATIC ); )
1504 BLOCK_DIE( "binary_or" );
1505 END_BLOCK
1506 END_OP( "binary_or" )
1507 }
1508 /*}}}*/
1509
1510 /*{{{ FERITE_BINARY_OP( binary_and ) */
FERITE_BINARY_OP(binary_and)1511 FERITE_BINARY_OP( binary_and )
1512 {
1513 BEGIN_OP( a )
1514 BEGIN_BLOCK( F_VAR_LONG, b )
1515 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_and" ), VAI(a) & VAI(b), FE_STATIC ); )
1516 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_and" ), VAI(a) & (long)VAF(b), FE_STATIC ); )
1517 BLOCK_DIE( "binary_and" );
1518 END_BLOCK
1519 BEGIN_BLOCK( F_VAR_DOUBLE, b )
1520 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_and" ), (long)VAF(a) & VAI(b), FE_STATIC ); )
1521 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_and" ), (long)VAF(a) & (long)VAF(b), FE_STATIC ); )
1522 BLOCK_DIE( "binary_and" );
1523 END_BLOCK
1524 END_OP( "binary_and" )
1525 }
1526 /*}}}*/
1527
1528 /*{{{ FERITE_BINARY_OP( binary_xor ) */
FERITE_BINARY_OP(binary_xor)1529 FERITE_BINARY_OP( binary_xor )
1530 {
1531 BEGIN_OP( a )
1532 BEGIN_BLOCK( F_VAR_LONG, b )
1533 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_xor" ), VAI(a) ^ VAI(b), FE_STATIC ); )
1534 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_xor" ), VAI(a) ^ (long)VAF(b), FE_STATIC ); )
1535 BLOCK_DIE( "binary_xor" );
1536 END_BLOCK
1537 BEGIN_BLOCK( F_VAR_DOUBLE, b )
1538 DO_OP( F_VAR_LONG, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_xor" ), (long)VAF(a) ^ VAI(b), FE_STATIC ); )
1539 DO_OP( F_VAR_DOUBLE, NOWT, retv = ferite_create_number_long_variable( script, RETVNAME( "binary_xor" ), (long)VAF(a) ^ (long)VAF(b), FE_STATIC ); )
1540 BLOCK_DIE( "binary_xor" );
1541 END_BLOCK
1542 END_OP( "binary_xor" )
1543 }
1544 /*}}}*/
1545
1546 /*{{{ FERITE_BINARY_OP( left_shift_assign ) */
FERITE_BINARY_OP(left_shift_assign)1547 FERITE_BINARY_OP( left_shift_assign )
1548 {
1549 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
1550
1551 FE_ENTER_FUNCTION;
1552 LOCK_VARIABLE(a);
1553 LOCK_VARIABLE(b);
1554 tmp_ptr = ferite_op_left_shift( script, a, b );
1555 if( tmp_ptr != NULL )
1556 {
1557 ptr = ferite_op_assign( script, a, tmp_ptr );
1558 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1559 ferite_variable_destroy( script, tmp_ptr );
1560 }
1561 UNLOCK_VARIABLE(a);
1562 UNLOCK_VARIABLE(b);
1563 FE_LEAVE_FUNCTION( ptr );
1564 }
1565 /*}}}*/
1566
1567 /*{{{ FERITE_BINARY_OP( right_shift_assign ) */
FERITE_BINARY_OP(right_shift_assign)1568 FERITE_BINARY_OP( right_shift_assign )
1569 {
1570 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
1571
1572 FE_ENTER_FUNCTION;
1573 LOCK_VARIABLE(a);
1574 LOCK_VARIABLE(b);
1575 tmp_ptr = ferite_op_right_shift( script, a, b );
1576 if( tmp_ptr != NULL )
1577 {
1578 ptr = ferite_op_assign( script, a, tmp_ptr );
1579 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1580 ferite_variable_destroy( script, tmp_ptr );
1581 }
1582 UNLOCK_VARIABLE(a);
1583 UNLOCK_VARIABLE(b);
1584 FE_LEAVE_FUNCTION( ptr );
1585 }
1586 /*}}}*/
1587
1588 /*{{{ FERITE_BINARY_OP( binary_and_assign ) */
FERITE_BINARY_OP(binary_and_assign)1589 FERITE_BINARY_OP( binary_and_assign )
1590 {
1591 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
1592
1593 FE_ENTER_FUNCTION;
1594 LOCK_VARIABLE(a);
1595 LOCK_VARIABLE(b);
1596 tmp_ptr = ferite_op_binary_and( script, a, b );
1597 if( tmp_ptr != NULL )
1598 {
1599 ptr = ferite_op_assign( script, a, tmp_ptr );
1600 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1601 ferite_variable_destroy( script, tmp_ptr );
1602 }
1603 UNLOCK_VARIABLE(a);
1604 UNLOCK_VARIABLE(b);
1605 FE_LEAVE_FUNCTION( ptr );
1606 }
1607 /*}}}*/
1608
1609 /*{{{ FERITE_BINARY_OP( binary_or_assign ) */
FERITE_BINARY_OP(binary_or_assign)1610 FERITE_BINARY_OP( binary_or_assign )
1611 {
1612 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
1613
1614 FE_ENTER_FUNCTION;
1615 LOCK_VARIABLE(a);
1616 LOCK_VARIABLE(b);
1617 tmp_ptr = ferite_op_binary_or( script, a, b );
1618 if( tmp_ptr != NULL )
1619 {
1620 ptr = ferite_op_assign( script, a, tmp_ptr );
1621 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1622 ferite_variable_destroy( script, tmp_ptr );
1623 }
1624 UNLOCK_VARIABLE(a);
1625 UNLOCK_VARIABLE(b);
1626 FE_LEAVE_FUNCTION( ptr );
1627 }
1628 /*}}}*/
1629
1630 /*{{{ FERITE_BINARY_OP( binary_xor_assign ) */
FERITE_BINARY_OP(binary_xor_assign)1631 FERITE_BINARY_OP( binary_xor_assign )
1632 {
1633 FeriteVariable *ptr = NULL, *tmp_ptr = NULL;
1634
1635 FE_ENTER_FUNCTION;
1636 LOCK_VARIABLE(a);
1637 LOCK_VARIABLE(b);
1638 tmp_ptr = ferite_op_binary_xor( script, a, b );
1639 if( tmp_ptr != NULL )
1640 {
1641 ptr = ferite_op_assign( script, a, tmp_ptr );
1642 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1643 ferite_variable_destroy( script, tmp_ptr );
1644 }
1645 UNLOCK_VARIABLE(a);
1646 UNLOCK_VARIABLE(b);
1647 FE_LEAVE_FUNCTION( ptr );
1648 }
1649 /*}}}*/
1650
1651 /*{{{ FERITE_BINARY_OP( isa ) */
FERITE_BINARY_OP(isa)1652 FERITE_BINARY_OP( isa )
1653 {
1654 FeriteVariable *ptr = NULL;
1655
1656 FE_ENTER_FUNCTION;
1657 LOCK_VARIABLE(a);
1658 LOCK_VARIABLE(b);
1659 GET_INPUT_VARS;
1660 FE_VAR_TEST( (strcmp( VAS(b)->data, ferite_variable_id_to_str(script,a->type) ) == 0), "isa" );
1661 UNLOCK_VARIABLE(a);
1662 UNLOCK_VARIABLE(b);
1663 if( ptr != NULL )
1664 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1665 FE_LEAVE_FUNCTION( ptr );
1666 }
1667 /*}}}*/
1668
1669 /*{{{ FERITE_BINARY_OP( instanceof ) */
FERITE_BINARY_OP(instanceof)1670 FERITE_BINARY_OP( instanceof )
1671 {
1672 FeriteVariable *ptr = NULL;
1673
1674 FE_ENTER_FUNCTION;
1675 LOCK_VARIABLE(a);
1676 LOCK_VARIABLE(b);
1677 GET_INPUT_VARS;
1678 if( a->type == F_VAR_OBJ && b->type == F_VAR_CLASS && VAO(a) != NULL && VAO(a)->klass == b->data.pval )
1679 FE_VAR_TRUE( ptr, "instanceof" );
1680 else
1681 FE_VAR_FALSE( ptr, "instanceof" );
1682 UNLOCK_VARIABLE(a);
1683 UNLOCK_VARIABLE(b);
1684 if( ptr != NULL )
1685 MARK_VARIABLE_AS_DISPOSABLE( ptr );
1686 FE_LEAVE_FUNCTION( ptr );
1687 }
1688 /*}}}*/
1689
1690 FeriteOpTable ferite_op_table[] =
1691 {
1692 { FERITE_OPCODE_not_op, "not_op", FERITE_OP_CALL( not_op ) },
1693 { FERITE_OPCODE_left_incr, "left_incr", FERITE_OP_CALL( left_incr ) },
1694 { FERITE_OPCODE_right_incr, "right_incr", FERITE_OP_CALL( right_incr ) },
1695 { FERITE_OPCODE_left_decr, "left_decr", FERITE_OP_CALL( left_decr ) },
1696 { FERITE_OPCODE_right_decr, "right_decr", FERITE_OP_CALL( right_decr ) },
1697 { FERITE_OPCODE_positive_var, "positive_var", FERITE_OP_CALL( positive_var ) },
1698 { FERITE_OPCODE_negative_var, "negative_var", FERITE_OP_CALL( negative_var ) },
1699 { FERITE_OPCODE_eval, "eval", FERITE_OP_CALL( eval ) },
1700 { FERITE_OPCODE_include, "include", FERITE_OP_CALL( include ) },
1701 { FERITE_OPCODE_add, "add", FERITE_OP_CALL( add ) },
1702 { FERITE_OPCODE_minus, "minus", FERITE_OP_CALL( minus ) },
1703 { FERITE_OPCODE_mult, "mult", FERITE_OP_CALL( mult ) },
1704 { FERITE_OPCODE_divide, "divide", FERITE_OP_CALL( divide ) },
1705 { FERITE_OPCODE_modulus, "modulus", FERITE_OP_CALL( modulus ) },
1706 { FERITE_OPCODE_assign, "assign", FERITE_OP_CALL( assign ) },
1707 { FERITE_OPCODE_add_assign, "add_assign", FERITE_OP_CALL( add_assign ) },
1708 { FERITE_OPCODE_minus_assign, "minus_assign", FERITE_OP_CALL( minus_assign ) },
1709 { FERITE_OPCODE_mult_assign, "mult_assign", FERITE_OP_CALL( mult_assign ) },
1710 { FERITE_OPCODE_divide_assign, "divide_assign", FERITE_OP_CALL( divide_assign ) },
1711 { FERITE_OPCODE_binary_or, "binary_or", FERITE_OP_CALL( binary_or ) },
1712 { FERITE_OPCODE_binary_and, "binary_and", FERITE_OP_CALL( binary_and ) },
1713 { FERITE_OPCODE_binary_xor, "binary_xor", FERITE_OP_CALL( binary_xor ) },
1714 { FERITE_OPCODE_logical_or, "logical_or", FERITE_OP_CALL( logical_or ) },
1715 { FERITE_OPCODE_logical_and, "logical_and", FERITE_OP_CALL( logical_and ) },
1716 { FERITE_OPCODE_equals, "equals", FERITE_OP_CALL( equals ) },
1717 { FERITE_OPCODE_case, "case", FERITE_OP_CALL( case ) },
1718 { FERITE_OPCODE_notequals, "notequals", FERITE_OP_CALL( notequals ) },
1719 { FERITE_OPCODE_less_than, "less_than", FERITE_OP_CALL( less_than ) },
1720 { FERITE_OPCODE_less_than_equals, "less_than_equals", FERITE_OP_CALL( less_than_equals ) },
1721 { FERITE_OPCODE_greater_than, "greater_than", FERITE_OP_CALL( greater_than ) },
1722 { FERITE_OPCODE_greater_than_equals, "greater_than_equals", FERITE_OP_CALL( greater_than_equals ) },
1723 { FERITE_OPCODE_array_index, "array_index", FERITE_OP_CALL( array_index ) },
1724 { FERITE_OPCODE_array_slice, "array_slice", FERITE_OP_CALL( array_slice ) },
1725 { FERITE_OPCODE_left_shift, "left_shift", FERITE_OP_CALL( left_shift ) },
1726 { FERITE_OPCODE_right_shift, "right_shift", FERITE_OP_CALL( right_shift ) },
1727 { FERITE_OPCODE_left_shift_assign, "left_shift_assign", FERITE_OP_CALL( left_shift_assign ) },
1728 { FERITE_OPCODE_right_shift_assign, "right_shift_assign", FERITE_OP_CALL( right_shift_assign ) },
1729 { FERITE_OPCODE_binary_and_assign, "binary_and_assign", FERITE_OP_CALL( binary_and_assign ) },
1730 { FERITE_OPCODE_binary_or_assign, "binary_or_assign", FERITE_OP_CALL( binary_or_assign ) },
1731 { FERITE_OPCODE_binary_xor_assign, "binary_xor_assign", FERITE_OP_CALL( binary_xor_assign ) },
1732 { FERITE_OPCODE_isa, "isa", FERITE_OP_CALL( isa ) },
1733 { FERITE_OPCODE_instanceof, "instanceof", FERITE_OP_CALL( instanceof ) },
1734 { FERITE_OPCODE_array_clear, "array_clear", FERITE_OP_CALL( array_clear ) }
1735 };
1736