--- parser3/src/classes/op.C 2001/09/06 06:11:13 1.41 +++ parser3/src/classes/op.C 2001/11/01 16:11:03 1.55 @@ -2,10 +2,10 @@ Parser: parser @b operators. Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + + $Id: op.C,v 1.55 2001/11/01 16:11:03 paf Exp $ */ -static const char *RCSId="$Id: op.C,v 1.41 2001/09/06 06:11:13 parser Exp $"; #include "classes.h" #include "pa_config_includes.h" @@ -39,25 +39,25 @@ private: // methods static void _if(Request& r, const String&, MethodParams *params) { - Value& condition_code=params->get(0); + Value& condition_code=params->as_junction(0, "condition must be expression"); bool condition=r.process(condition_code, 0/*no name*/, false/*don't intercept string*/).as_bool(); if(condition) r.write_pass_lang(r.process(params->as_junction(1, "'then' parameter must be code"))); - else if(params->size()==3) + else if(params->size()>2) 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) { Pool& pool=r.pool(); - const String& lang_name=r.process(params->get(0)).as_string(); + const String& lang_name=params->as_string(0, "lang must be string"); String::Untaint_lang lang=static_cast( untaint_lang_name2enum->get_int(lang_name)); if(!lang) - PTHROW(0, 0, + throw Exception(0, 0, &lang_name, "invalid untaint language"); @@ -76,12 +76,11 @@ static void _taint(Request& r, const Str if(params->size()==1) lang=String::UL_TAINTED; // mark as simply 'tainted'. useful in table:set else { - const String& lang_name= - r.process(params->get(0)).as_string(); + const String& lang_name=params->as_string(0, "lang must be string"); lang=static_cast( untaint_lang_name2enum->get_int(lang_name)); if(!lang) - PTHROW(0, 0, + throw Exception(0, 0, &lang_name, "invalid taint language"); } @@ -119,7 +118,7 @@ static void _process(Request& r, const S // evaluate source to process const String& source= - r.process(params->get(0)).as_string(); + r.process(params->as_no_junction(0, "body must be string")).as_string(); // process source code, append processed methods to 'self' class // maybe-define new @main @@ -147,7 +146,7 @@ static void _while(Request& r, const Str int endless_loop_count=0; while(true) { if(++endless_loop_count>=MAX_LOOPS) // endless loop? - PTHROW(0, 0, + throw Exception(0, 0, &method_name, "endless loop detected"); @@ -171,28 +170,28 @@ static void _use(Request& r, const Strin static void _for(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool(); - const String& var_name=r.process(params->get(0)).as_string(); - int from=r.process(params->get(1)).as_int(); - int to=r.process(params->get(2)).as_int(); + const String& var_name=params->as_string(0, "var name must be string"); + int from=params->as_int(1, "from must be int", r); + int to=params->as_int(2, "to must be int", r); Value& body_code=params->as_junction(3, "body must be code"); - Value *delim_code=params->size()==3+1+1?¶ms->get(3+1):0; + Value *delim_maybe_code=params->size()>4?¶ms->get(4):0; bool need_delim=false; VInt *vint=new(pool) VInt(pool, 0); int endless_loop_count=0; for(int i=from; i<=to; i++) { if(++endless_loop_count>=MAX_LOOPS) // endless loop? - PTHROW(0, 0, + throw Exception(0, 0, &method_name, "endless loop detected"); vint->set_int(i); - r.root->put_element(var_name, vint); + r.self/*root*/->put_element(var_name, vint); Value& processed_body=r.process(body_code); - if(delim_code) { // delimiter set? + 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(*delim_code)); + r.write_pass_lang(r.process(*delim_maybe_code)); need_delim=true; } r.write_pass_lang(processed_body); @@ -205,7 +204,7 @@ static void _eval(Request& r, const Stri Value *result=r.process(expr, 0/*no name YET*/, true/*don't intercept string*/).as_expr_result(); - if(params->size()==2) { + if(params->size()>1) { Value& fmt=params->as_no_junction(1, "fmt must not be code"); Pool& pool=r.pool(); @@ -217,8 +216,18 @@ static void _eval(Request& r, const Stri r.write_no_lang(*result); } +static void _error(Request& r, const String& method_name, MethodParams *params) { + Pool& pool=r.pool(); + + const String& serror=params->as_string(0, "message must be string"); + throw Exception(0, 0, + &method_name, + "%s", serror.cstr()); +} -static void _connect(Request& r, const String&, MethodParams *params) { + +/// @todo rewrite ugly code with try/try to autoobject TempConnection +static void _connect(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool(); Value& url=params->as_no_junction(0, "url must not be code"); @@ -229,42 +238,37 @@ static void _connect(Request& r, const S // connect SQL_Connection& connection=SQL_driver_manager->get_connection( - url.as_string(), protocol2driver_and_client); + url.as_string(), method_name, protocol2driver_and_client); - Exception rethrow_me; // remember/set current connection SQL_Connection *saved_connection=r.connection; r.connection=&connection; // execute body - bool body_failed=false; - PTRY - r.write_assign_lang(r.process(body_code)); - PCATCH(e) { // connect/process problem - rethrow_me=e; body_failed=true; - } - PEND_CATCH - - bool finalizer_failed=false; - PTRY - // FINALLY - if(body_failed) - connection.rollback(); - else + try { + try { + r.write_assign_lang(r.process(body_code)); + connection.commit(); - PCATCH(e) { // commit/rollback problem - rethrow_me=e; finalizer_failed=true; + } catch(...) { // process/commit problem + connection.rollback(); + + /*re*/throw; + } + + } catch(...) { + // close connection [cache it] + connection.close(); + // recall current connection from remembered + r.connection=saved_connection; + + /*re*/throw; } - PEND_CATCH + // and anyway // close connection [cache it] connection.close(); // recall current connection from remembered r.connection=saved_connection; - - if(body_failed || finalizer_failed) // were there an exception for us to rethrow? - PTHROW(rethrow_me.type(), rethrow_me.code(), - rethrow_me.problem_source(), - rethrow_me.comment()); } #ifndef DOXYGEN @@ -292,7 +296,7 @@ static void _case(Request& r, const Stri Switch_data *data=static_cast(r.classes_conf.get(*switch_data_name)); if(!data) - PTHROW(0, 0, + throw Exception(0, 0, &method_name, "without switch"); @@ -341,7 +345,7 @@ MOP::MOP(Pool& apool) : Methoded(apool), add_native_method("process", Method::CT_ANY, _process, 1, 1); // ^rem{code} - add_native_method("rem", Method::CT_ANY, _rem, 1, 1000); + add_native_method("rem", Method::CT_ANY, _rem, 1, 10000); // ^while(condition){code} add_native_method("while", Method::CT_ANY, _while, 2, 2); @@ -349,13 +353,16 @@ MOP::MOP(Pool& apool) : Methoded(apool), // ^use[file] add_native_method("use", Method::CT_ANY, _use, 1, 1); - // ^for[i;from-number;to-number-inclusive]{code}[delim] + // ^for[i](from-number;to-number-inclusive){code}[delim] add_native_method("for", Method::CT_ANY, _for, 3+1, 3+1+1); // ^eval(expr) // ^eval(expr)[format] add_native_method("eval", Method::CT_ANY, _eval, 1, 2); + // ^error[msg] + add_native_method("error", Method::CT_ANY, _error, 1, 1); + // ^connect[protocol://user:pass@host[:port]/database]{code with ^sql-s} add_native_method("connect", Method::CT_ANY, _connect, 2, 2); @@ -366,7 +373,7 @@ MOP::MOP(Pool& apool) : Methoded(apool), add_native_method("switch", Method::CT_ANY, _switch, 2, 2); // ^case[value]{code} - add_native_method("case", Method::CT_ANY, _case, 2, 1000); + add_native_method("case", Method::CT_ANY, _case, 2, 10000); } // constructor & configurator @@ -375,7 +382,6 @@ Methoded *MOP_create(Pool& pool) { return new(pool) MOP(pool); } - void MOP::configure_user(Request& r) { Pool& pool=r.pool();