--- parser3/src/classes/op.C 2002/04/15 06:45:55 1.82 +++ parser3/src/classes/op.C 2002/04/16 08:22:19 1.89 @@ -4,7 +4,7 @@ Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - $Id: op.C,v 1.82 2002/04/15 06:45:55 paf Exp $ + $Id: op.C,v 1.89 2002/04/16 08:22:19 paf Exp $ */ #include "classes.h" @@ -43,12 +43,12 @@ static void _if(Request& r, const String Value& condition_code=params->as_junction(0, "condition must be expression"); bool condition=r.process_to_value(condition_code, - 0/*no name*/, + /*0/*no name* /,*/ false/*don't intercept string*/).as_bool(); if(condition) - r.write_pass_lang(r.process_to_value(params->as_junction(1, "'then' parameter must be code"))); + r.write_pass_lang(r.process(params->as_junction(1, "'then' parameter must be code"))); else if(params->size()>2) - r.write_pass_lang(r.process_to_value(params->as_junction(2, "'else' parameter must be code"))); + r.write_pass_lang(r.process(params->as_junction(2, "'else' parameter must be code"))); } static void _untaint(Request& r, const String& method_name, MethodParams *params) { @@ -70,7 +70,7 @@ static void _untaint(Request& r, const S Value& vbody=params->as_junction(params->size()-1, "body must be code"); Temp_lang temp_lang(r, lang); // set temporarily specified ^untaint[language; - r.write_pass_lang(r.process_to_value(vbody)); // process marking tainted with that lang + r.write_pass_lang(r.process(vbody)); // process marking tainted with that lang } } @@ -103,15 +103,19 @@ static void _taint(Request& r, const Str static void _process(Request& r, const String& method_name, MethodParams *params) { // calculate pseudo file name of processed chars // would be something like "/some/file(4) process" - char place[MAX_STRING]; + char local_place[MAX_STRING]; #ifndef NO_STRING_ORIGIN const Origin& origin=method_name.origin(); - snprintf(place, MAX_STRING, "%s(%d) %s", - origin.file, 1+origin.line, - method_name.cstr()); + size_t place_size=snprintf(local_place, MAX_STRING, "%s(%d) %s", + origin.file?origin.file:"unknown_file", 1+origin.line, + method_name.cstr())+1; #else - strncpy(place, method_name.cstr(), MAX_STRING-1); place[MAX_STRING-1]=0; -#endif + strncpy(local_place, method_name.cstr(), MAX_STRING-1); place[MAX_STRING-1]=0; + size_t place_size=strlen(local_place)+1; +#endif + char *heap_place=(char *)r.malloc(place_size); + memcpy(heap_place, local_place, place_size); + VStateless_class& self_class=*r.self->get_class(); const Method *main_method; @@ -124,14 +128,13 @@ static void _process(Request& r, const S Temp_method temp_method_auto(self_class, *auto_method_name, 0); // evaluate source to process - const String& source= - r.process_to_string(params->as_junction(0, "body must be code")); + const String& source=r.process_to_string(params->as_junction(0, "body must be code")); // process source code, append processed methods to 'self' class // maybe-define new @main r.use_buf( source.cstr(String::UL_UNSPECIFIED, r.connection(0)), - place, + heap_place, &self_class); // main_method @@ -163,16 +166,14 @@ static void _while(Request& r, const Str &method_name, "endless loop detected"); - bool condition= - r.process_to_value( - vcondition, - 0/*no name*/, + bool condition=r.process_to_value(vcondition, + /*0/*no name* /,*/ false/*don't intercept string*/).as_bool(); if(!condition) // ...condition is true break; // write processed body - r.write_pass_lang(r.process_to_value(body)); + r.write_pass_lang(r.process(body)); } } @@ -200,11 +201,11 @@ static void _for(Request& r, const Strin vint->set_int(i); r.root->put_element(var_name, vint); - Value& processed_body=r.process_to_value(body_code); + StringOrValue processed_body=r.process(body_code); if(delim_maybe_code) { // delimiter set? const String *string=processed_body.get_string(); if(need_delim && string && string->size()) // need delim & iteration produced string? - r.write_pass_lang(r.process_to_string(*delim_maybe_code)); + r.write_pass_lang(r.process(*delim_maybe_code)); need_delim=true; } r.write_pass_lang(processed_body); @@ -215,7 +216,7 @@ static void _eval(Request& r, const Stri Value& expr=params->as_junction(0, "need expression"); // evaluate expresion Value *result=r.process_to_value(expr, - 0/*no name YET*/, + /*0/*no name YET* /,*/ true/*don't intercept string*/).as_expr_result(); if(params->size()>1) { Value& fmt=params->as_no_junction(1, "fmt must not be code"); @@ -261,7 +262,7 @@ r.sql_connect_time+=t[1]-t[0]; Temp_connection temp_connection(r, connection.get()); // execute body try { - r.write_assign_lang(r.process_to_value(body_code)); + r.write_assign_lang(r.process(body_code)); } catch(...) { // process problem connection->mark_to_rollback(); /*re*/throw; @@ -274,28 +275,21 @@ struct Switch_data { Value *searching; Value *found; Value *_default; - Value *result; }; #endif -static void switch_postexecute(void *info) { - Switch_data& data=*static_cast(info); - - if(Value *code=data.found ? data.found : data._default) - data.result=&data.r->process_to_value(*code); -} static void _switch(Request& r, const String&, MethodParams *params) { Switch_data data={&r, &r.process_to_value(params->get(0))}; Temp_hash_value switch_data_setter(r.classes_conf, *switch_data_name, &data); + Value& cases_code=params->as_junction(1, "switch cases must be code"); // execution of found ^case[...]{code} must be in context of ^switch[...]{code} // because of stacked WWrapper used there as wcontext - r.process_to_nothing( - params->as_junction(1, "switch cases must be code"), - switch_postexecute, &data - ); - - if(data.result) - r.write_pass_lang(*data.result); + r.process(cases_code, true/*intercept_string*/); + if(Value *selected_code=data.found ? data.found : data._default) { + // setting code context, would execute in ^switch[...]{>>context<<} + selected_code->get_junction()->change_context(cases_code.get_junction()); + r.write_pass_lang(r.process(*selected_code)); + } } static void _case(Request& r, const String& method_name, MethodParams *params) { @@ -309,6 +303,11 @@ static void _case(Request& r, const Stri int count=params->size(); Value *code=¶ms->as_junction(--count, "case result must be code"); + + // killing context for safety, would execute in ^switch[...]{>>context<<} + // reason: context is stacked, and it would become invalid afterwards + code->get_junction()->change_context(0); + for(int i=0; iget(i)); @@ -546,7 +545,7 @@ VHash& exception2vhash(Pool& pool, const hash.put(*exception_source_part_name, new(pool) VString(source)); #ifndef NO_STRING_ORIGIN const Origin& origin=source.origin(); - hash.put(*new(pool) String(pool, "file"), + hash.put(*new(pool) String(pool, "file", 0, true), new(pool) VString(*new(pool) String(pool, origin.file))); hash.put(*new(pool) String(pool, "lineno"), new(pool) VInt(pool, 1+origin.line)); @@ -571,7 +570,7 @@ static void _try_operator(Request& r, co Value& body_code=params->as_junction(0, "body_code must be code"); Value& catch_code=params->as_junction(1, "catch_code must be code"); - Value *result; + StringOrValue result; // taking snapshot of request processing status //int ssexception_trace=r.exception_trace.top_index(); @@ -579,7 +578,7 @@ static void _try_operator(Request& r, co Value *sself=r.self, *sroot=r.root, *srcontext=r.rcontext; WContext *swcontext=r.wcontext; try { - result=&r.process_to_value(body_code); + result=r.process(body_code); } catch(const Exception& e) { // restoring request processing status //r.exception_trace.top_index(ssexception_trace); @@ -592,7 +591,7 @@ static void _try_operator(Request& r, co Junction *junction=catch_code.get_junction(); Value *saved_exception_var_value=junction->root->get_element(*exception_var_name); junction->root->put_element(*exception_var_name, &vhash); - result=&r.process_to_value(catch_code); + result=r.process(catch_code); bool handled=false; if(Value *value=static_cast(vhash.hash(0).get(*exception_handled_part_name))) handled=value->as_bool(); @@ -602,7 +601,7 @@ static void _try_operator(Request& r, co throw(e); // rethrow } // write it out - r.write_pass_lang(*result); + r.write_pass_lang(result); } static void _throw_operator(Request& r, const String& method_name, MethodParams *params) {