--- parser3/src/main/execute.C 2001/05/16 16:48:56 1.157 +++ parser3/src/main/execute.C 2001/06/29 14:16:09 1.171 @@ -4,17 +4,15 @@ Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) Author: Alexander Petrosyan (http://design.ru/paf) - - $Id: execute.C,v 1.157 2001/05/16 16:48:56 parser Exp $ */ +static const char *RCSId="$Id: execute.C,v 1.171 2001/06/29 14:16:09 parser Exp $"; -#include "pa_config_includes.h" #include "pa_opcode.h" #include "pa_array.h" #include "pa_request.h" #include "pa_vstring.h" #include "pa_vhash.h" -#include "pa_vunknown.h" +#include "pa_vvoid.h" #include "pa_vcode_frame.h" #include "pa_vmethod_frame.h" #include "pa_vobject.h" @@ -26,10 +24,7 @@ //#define DEBUG_EXECUTE - -#define PUSH(value) stack.push(value) -#define POP() static_cast(stack.pop()) -#define POP_NAME() static_cast(stack.pop())->as_string() +const uint ANTI_ENDLESS_EXECUTE_RECOURSION=500; #ifdef DEBUG_EXECUTE char *opcode_name[]={ @@ -60,69 +55,73 @@ char *opcode_name[]={ "IS" }; -void va_log_printf(Pool& pool, const char *fmt,va_list args) { +void va_debug_printf(Pool& pool, const char *fmt,va_list args) { char buf[MAX_STRING]; vsnprintf(buf, MAX_STRING, fmt, args); SAPI::log(pool, "%s", buf); } -void log_printf(Pool& pool, const char *fmt, ...) { +void debug_printf(Pool& pool, const char *fmt, ...) { va_list args; va_start(args,fmt); - va_log_printf(pool,fmt,args); + va_debug_printf(pool,fmt,args); va_end(args); } -void dump(Pool& pool, int level, const Array& ops) { +void debug_dump(Pool& pool, int level, const Array& ops) { { int size=ops.quick_size(); - //log_printf(pool, "size=%d\n", size); + //debug_printf(pool, "size=%d\n", size); for(int i=0; i(ops.quick_get(++i)); - log_printf(pool, + debug_printf(pool, "%*s%s" " \"%s\" %s", level*4, "", opcode_name[op.code], value->get_string()->cstr(), value->type()); continue; } - log_printf(pool, "%*s%s", level*4, "", opcode_name[op.code]); + debug_printf(pool, "%*s%s", level*4, "", opcode_name[op.code]); if(op.code==OP_CURLY_CODE__STORE_PARAM || op.code==OP_EXPR_CODE__STORE_PARAM) { const Array *local_ops=reinterpret_cast(ops.quick_get(++i)); - dump(pool, level+1, *local_ops); + debug_dump(pool, level+1, *local_ops); } } } #endif +#define PUSH(value) stack.push(value) +#define POP() static_cast(stack.pop()) +#define POP_NAME() static_cast(stack.pop())->as_string() + void Request::execute(const Array& ops) { #ifdef DEBUG_EXECUTE - log_printf(pool(), "source----------------------------\n"); - dump(pool(), 0, ops); - log_printf(pool(), "execution-------------------------\n"); + debug_printf(pool(), "source----------------------------\n"); + debug_dump(pool(), 0, ops); + debug_printf(pool(), "execution-------------------------\n"); #endif int size=ops.quick_size(); - //log_printf(pool(), "size=%d\n", size); + //debug_printf(pool(), "size=%d\n", size); for(int i=0; i(ops.quick_get(++i)); #ifdef DEBUG_EXECUTE - log_printf(pool(), " \"%s\" %s", value->get_string()->cstr(), value->type()); + debug_printf(pool(), " \"%s\" %s", value->get_string()->cstr(), value->type()); #endif PUSH(value); break; @@ -143,8 +142,8 @@ void Request::execute(const Array& ops) // code const Array *local_ops=reinterpret_cast(ops.quick_get(++i)); #ifdef DEBUG_EXECUTE - log_printf(pool(), " (%d)\n", local_ops->size()); - dump(pool(), 1, *local_ops); + debug_printf(pool(), " (%d)\n", local_ops->size()); + debug_dump(pool(), 1, *local_ops); #endif // when they evaluate expression parameter, // the object expression result @@ -243,7 +242,7 @@ void Request::execute(const Array& ops) { VString *vstring=static_cast(ops.quick_get(++i)); #ifdef DEBUG_EXECUTE - log_printf(pool(), " \"%s\"", vstring->string().cstr()); + debug_printf(pool(), " \"%s\"", vstring->string().cstr()); #endif write_no_lang(vstring->string()); break; @@ -300,7 +299,7 @@ void Request::execute(const Array& ops) if(string) value=NEW VString(*string); else - value=NEW VUnknown(pool()); + value=NEW VVoid(pool()); wcontext=static_cast(POP()); rcontext=POP(); PUSH(value); @@ -321,7 +320,7 @@ void Request::execute(const Array& ops) if(string) value=NEW VString(*string); else - NEW VUnknown(pool()); + NEW VVoid(pool()); wcontext=static_cast(POP()); PUSH(value); break; @@ -363,7 +362,7 @@ void Request::execute(const Array& ops) case OP_CALL: { #ifdef DEBUG_EXECUTE - log_printf(pool(), "->\n"); + debug_printf(pool(), "->\n"); #endif VMethodFrame *frame=static_cast(POP()); frame->fill_unspecified_params(); @@ -415,11 +414,20 @@ void Request::execute(const Array& ops) method.check_actual_numbered_params(pool(), frame->junction.self, frame->name(), frame->numbered_params()); - (*method.native_code)( + method.native_code( *this, frame->name(), frame->numbered_params()); // execute it - } else // parser code + } else { // parser code + if(++anti_endless_execute_recoursion==ANTI_ENDLESS_EXECUTE_RECOURSION) { + anti_endless_execute_recoursion=0; // give @exception a chance + THROW(0, 0, + &frame->name(), + "endless recursion detected"); + } + execute(*method.parser_code); // execute it + anti_endless_execute_recoursion--; + } else THROW(0, 0, &frame->name(), @@ -436,7 +444,7 @@ void Request::execute(const Array& ops) PUSH(value); #ifdef DEBUG_EXECUTE - log_printf(pool(), "<-returned"); + debug_printf(pool(), "<-returned"); #endif break; } @@ -521,16 +529,44 @@ void Request::execute(const Array& ops) case OP_DIV: { Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), a->as_double() / b->as_double()); + + double a_double=a->as_double(); + double b_double=b->as_double(); + + if(b_double == 0) { + const String *problem_source=&b->as_string(); +#ifndef NO_STRING_ORIGIN + if(!problem_source->origin().file) + problem_source=b->name(); +#endif + THROW(0, 0, + problem_source, + "Division by zero"); + } + + Value *value=NEW VDouble(pool(), a_double / b_double); PUSH(value); break; } case OP_MOD: { Value *b=POP(); Value *a=POP(); - Value *value=NEW VDouble(pool(), - a->as_int() % - b->as_int()); + + int a_int=a->as_int(); + int b_int=b->as_int(); + + if(b_int == 0) { + const String *problem_source=&b->as_string(); +#ifndef NO_STRING_ORIGIN + if(!problem_source->origin().file) + problem_source=b->name(); +#endif + THROW(0, 0, + problem_source, + "Modulus by zero"); + } + + Value *value=NEW VDouble(pool(), a_int % b_int); PUSH(value); break; } @@ -696,15 +732,14 @@ Value *Request::get_element() { if(value) value=&process(*value, &name); // process possible code-junction else { - value=NEW VUnknown(pool()); + value=NEW VVoid(pool()); value->set_name(name); } return value; } -/** - intercept_string: +/** @param intercept_string - true: they want result=string value, possible object result goes to wcontext @@ -719,7 +754,7 @@ Value& Request::process(Value& value, co if(junction && junction->code) { // is it a code-junction? // process it #ifdef DEBUG_EXECUTE - log_printf(pool(), "ja->\n"); + debug_printf(pool(), "ja->\n"); #endif PUSH(self); PUSH(root); @@ -759,7 +794,7 @@ Value& Request::process(Value& value, co self=static_cast(POP()); #ifdef DEBUG_EXECUTE - log_printf(pool(), "<-ja returned"); + debug_printf(pool(), "<-ja returned"); #endif } else result=&value;