--- parser3/src/classes/op.C 2005/08/30 08:23:09 1.157 +++ parser3/src/classes/op.C 2005/11/25 11:53:59 1.162 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_OP_C="$Date: 2005/08/30 08:23:09 $"; +static const char * const IDENT_OP_C="$Date: 2005/11/25 11:53:59 $"; #include "classes.h" #include "pa_vmethod_frame.h" @@ -22,7 +22,7 @@ static const char * const IDENT_OP_C="$D // limits -#define MAX_LOOPS 10000 +#define MAX_LOOPS 20000 // defines @@ -76,6 +76,7 @@ public: ULN("optimized-xml", XML|String::L_OPTIMIZE_BIT); ULN("html", HTML); ULN("optimized-html", HTML|String::L_OPTIMIZE_BIT); + ULN("regex", REGEX); #undef ULN } } untaint_lang_name2enum; @@ -229,10 +230,12 @@ static void _rem(Request&, MethodParams& static void _while(Request& r, MethodParams& params) { Value& vcondition=params.as_junction(0, "condition must be expression"); - Value& body=params.as_junction(1, "body must be code"); + Value& body_code=params.as_junction(1, "body must be code"); + Value* delim_maybe_code=params.count()>2?¶ms[2]:0; // while... int endless_loop_count=0; + bool need_delim=false; while(true) { if(++endless_loop_count>=MAX_LOOPS) // endless loop? throw Exception("parser.runtime", @@ -244,8 +247,14 @@ static void _while(Request& r, MethodPar if(!condition) // ...condition is true break; - // write processed body - r.write_pass_lang(r.process(body)); + StringOrValue sv_processed=r.process(body_code); + const String* s_processed=sv_processed.get_string(); + if(delim_maybe_code && s_processed && s_processed->length()) { // delimiter set and we have body + if(need_delim) // need delim & iteration produced string? + r.write_pass_lang(r.process(*delim_maybe_code)); + need_delim=true; + } + r.write_pass_lang(sv_processed); } } @@ -416,7 +425,7 @@ struct Try_catch_result { template static Try_catch_result try_catch(Request& r, StringOrValue body_code(Request&, I), I info, - Value* catch_code) + Value* catch_code, bool could_be_handled_by_caller=false) { Try_catch_result result; if(!catch_code) { @@ -447,11 +456,14 @@ static Try_catch_result try_catch(Reques bool bhandled=false; if(vhandled) { if(vhandled->is_string()) { // not simple $exception.handled(1/0)? - result.exception_should_be_handled=vhandled->get_string(); // considering 'recovered' and let the caller recover - return result; - } - - bhandled=vhandled->as_bool(); + if(could_be_handled_by_caller) { // and we can possibly handle it + result.exception_should_be_handled=vhandled->get_string(); // considering 'recovered' and let the caller recover + return result; + } + + bhandled=false; + } else + bhandled=vhandled->as_bool(); } if(!bhandled) { @@ -509,19 +521,17 @@ static void locked_process_and_cache_put Locked_process_and_cache_put_action_info& info= *static_cast(context); + + const String* body_from_disk=info.scope->body_from_disk; // body->process Try_catch_result result=try_catch(*info.r, process_cache_body_code, info.body_code, - info.catch_code); + info.catch_code, body_from_disk!=0 /*we have something old=we can handle=recover later*/); if(result.exception_should_be_handled) { if(*result.exception_should_be_handled==CACHE_EXCEPTION_HANDLED_CACHE_NAME) { - if(const String* body_from_disk=info.scope->body_from_disk) // we have something old? - info.processed_code=body_from_disk; - else - throw Exception(0, - new String("$"EXCEPTION_VAR_NAME"."EXCEPTION_HANDLED_PART_NAME"["CACHE_EXCEPTION_HANDLED_CACHE_NAME"]"), - "fallback failed - there is no old cached body"); + assert(body_from_disk); + info.processed_code=body_from_disk; } else throw Exception("parser.runtime", result.exception_should_be_handled, @@ -611,6 +621,18 @@ static const String& as_file_spec(Reques return r.absolute(params.as_string(index, "filespec must be string")); } static void _cache(Request& r, MethodParams& params) { + if(params.count()==0) + { + // return current expiration time + Cache_scope* scope=static_cast(r.classes_conf.get(cache_data_name)); + if(!scope) + throw Exception("parser.runtime", + 0, + "expire-time get without cache"); + r.write_no_lang(*new VDate(scope->expires)); + return; + } + time_t now=time(0); // ^cache[filename] ^cache(seconds) ^cache[expires date] @@ -796,7 +818,7 @@ VClassMAIN::VClassMAIN(): VClass() { add_native_method("rem", Method::CT_ANY, _rem, 1, 10000); // ^while(condition){code} - add_native_method("while", Method::CT_ANY, _while, 2, 2); + add_native_method("while", Method::CT_ANY, _while, 2, 3); // ^use[file] add_native_method("use", Method::CT_ANY, _use, 1, 1); @@ -814,7 +836,8 @@ VClassMAIN::VClassMAIN(): VClass() { // ^cache[file_spec](time){code}[{catch code}] time=0 no cache // ^cache[file_spec] delete cache - add_native_method("cache", Method::CT_ANY, _cache, 1, 4); + // ^cache[] get current expiration time + add_native_method("cache", Method::CT_ANY, _cache, 0, 4); // switch