Diff for /parser3/src/classes/op.C between versions 1.97 and 1.123

version 1.97, 2002/06/20 14:50:22 version 1.123, 2002/10/17 09:04:53
Line 3 Line 3
   
         Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
   
         $Id$  
 */  */
   
   static const char* IDENT_OP_C="$Date$";
   
 #include "classes.h"  #include "classes.h"
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_request.h"  #include "pa_request.h"
 #include "pa_vint.h"  #include "pa_vint.h"
 #include "pa_sql_connection.h"  #include "pa_sql_connection.h"
 #include "pa_vdate.h"  #include "pa_vdate.h"
   #include "pa_vmethod_frame.h"
   
 // limits  // limits
   
Line 24 Line 25
   
 // class  // class
   
 class MOP : public Methoded {  class VClassMAIN: public VClass {
 public:  public:
         MOP(Pool& pool);          VClassMAIN(Pool& apool);
 public: // Methoded  
         bool used_directly() { return true; }  
         void configure_user(Request& r);  
   
 private:  
         String main_sql_name;  
         String main_sql_drivers_name;  
 };  };
   
 // methods  // methods
Line 101  static void _taint(Request& r, const Str Line 95  static void _taint(Request& r, const Str
   
 static void _process(Request& r, const String& method_name, MethodParams *params) {  static void _process(Request& r, const String& method_name, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
         // calculate pseudo file name of processed chars  
         // would be something like "/some/file(4) process"  
         char local_place[MAX_STRING];  
 #ifndef NO_STRING_ORIGIN  
         const Origin& origin=method_name.origin();  
         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(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;          const Method *main_method;
           Value& target_self=params->size()>1?
                   params->as_no_junction(0, "target must not be code")
                   :r.get_method_frame()->caller()->self();
         {          {
                   Value& vjunction=params->as_junction(params->size()-1, "body must be code");
   
                   VStateless_class *target_class=target_self.get_class();
                   if(!target_class)
                           throw Exception("parser.runtime",
                                   &method_name,
                                   "no target class");
                   
                   // evaluate source to process
                   const String& source=r.process_to_string(vjunction);
   
                 // temporary remove language change                  // temporary remove language change
                 Temp_lang temp_lang(r, String::UL_PASS_APPENDED);                  Temp_lang temp_lang(r, String::UL_PASS_APPENDED);
                 // temporary zero @main so to maybe-replace it in processed code                  // temporary zero @main so to maybe-replace it in processed code
                 Temp_method temp_method_main(self_class, r.main_method_name, 0);                  Temp_method temp_method_main(*target_class, r.main_method_name, 0);
                 // temporary zero @auto so it wouldn't be auto-called in Request::use_buf                  // temporary zero @auto so it wouldn't be auto-called in Request::use_buf
                 Temp_method temp_method_auto(self_class, *auto_method_name, 0);                  Temp_method temp_method_auto(*target_class, *auto_method_name, 0);
                                   
                 // evaluate source to process                  // calculate pseudo file name of processed chars
                 const String& source=r.process_to_string(params->as_junction(0, "body must be code"));                  // would be something like "/some/file(4) process"
                   char local_place[MAX_STRING];
   #ifndef NO_STRING_ORIGIN
                   const Origin& source_origin=source.origin();
                   const Origin& method_origin=method_name.origin();
                   size_t place_size;
                   if(source_origin.file==method_origin.file)
                           place_size=snprintf(local_place, MAX_STRING, "%s(%d) %s",  // same file
                                   source_origin.file?source_origin.file:"unknown_file", 1+source_origin.line, 
                                   method_name.cstr())+1;
                   else // different files ^process{external__file_text__or__sql}
                           place_size=snprintf(local_place, MAX_STRING, "%s", 
                                   source_origin.file?source_origin.file:"unknown_file")+1;
   #else
                   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);
   
                 // process source code, append processed methods to 'self' class                  // process source code, append processed methods to 'self' class
                 // maybe-define new @main                  // maybe-define new @main
                 r.use_buf(                  r.use_buf(*target_class,
                         source.cstr(String::UL_UNSPECIFIED, r.connection(0)),                           source.cstr(String::UL_UNSPECIFIED, r.connection(0)), 
                         *new(pool) String(pool, heap_place, place_size, true /*tainted*/),                          *new(pool) String(pool, heap_place, place_size, true /*tainted*/),
                         heap_place,                           heap_place);
                         &self_class);  
                                   
                 // main_method                  // main_method
                 main_method=self_class.get_method(r.main_method_name);                  main_method=target_class->get_method(r.main_method_name);
         }          }
         // after restoring current-request-lang          // after restoring current-request-lang
         // maybe-execute @main[]          // maybe-execute @main[]
         if(main_method) {          if(main_method) {
                   // temporarily set method_frame's self to target_self
                   Temp_method_frame_self tmfs(*r.get_method_frame(), target_self);
                 // execute!                       // execute!     
                 r.execute(*main_method->parser_code);                  r.execute(*main_method->parser_code);
         }          }
Line 180  static void _while(Request& r, const Str Line 190  static void _while(Request& r, const Str
   
 static void _use(Request& r, const String& method_name, MethodParams *params) {  static void _use(Request& r, const String& method_name, MethodParams *params) {
         Value& vfile=params->as_no_junction(0, "file name must not be code");          Value& vfile=params->as_no_junction(0, "file name must not be code");
         r.use_file(vfile.as_string());          r.use_file(r.main_class, vfile.as_string());
 }  }
   
 static void _for(Request& r, const String& method_name, MethodParams *params) {  static void _for(Request& r, const String& method_name, MethodParams *params) {
Line 198  static void _for(Request& r, const Strin Line 208  static void _for(Request& r, const Strin
   
         bool need_delim=false;          bool need_delim=false;
         VInt *vint=new(pool) VInt(pool, 0);          VInt *vint=new(pool) VInt(pool, 0);
         r.root->put_element(var_name, vint);          r.get_method_frame()->caller()->put_element(var_name, vint, false);
         for(int i=from; i<=to; i++) {          for(int i=from; i<=to; i++) {
                 vint->set_int(i);                  vint->set_int(i);
   
                 StringOrValue processed_body=r.process(body_code);                  StringOrValue sv_processed=r.process(body_code);
                 if(delim_maybe_code) { // delimiter set?                  const String *s_processed=sv_processed.get_string();
                         const String *string=processed_body.get_string();                  if(delim_maybe_code && s_processed && s_processed->size()) { // delimiter set and we have body
                         if(need_delim && string && string->size()) // need delim & iteration produced string?                          if(need_delim) // need delim & iteration produced string?
                                 r.write_pass_lang(r.process(*delim_maybe_code));                                  r.write_pass_lang(r.process(*delim_maybe_code));
                         need_delim=true;                          need_delim=true;
                 }                  }
                 r.write_pass_lang(processed_body);                  r.write_pass_lang(sv_processed);
         }          }
 }  }
   
Line 238  struct timeval mt[2]; Line 248  struct timeval mt[2];
         Value& url=params->as_no_junction(0, "url must not be code");          Value& url=params->as_no_junction(0, "url must not be code");
         Value& body_code=params->as_junction(1, "body must be code");          Value& body_code=params->as_junction(1, "body must be code");
   
         Table *protocol2driver_and_client=          Table *protocol2driver_and_client=0;
                 static_cast<Table *>(r.classes_conf.get(r.OP.name()));          if(Value *sql=r.main_class.get_element(*new(pool) String(pool, MAIN_SQL_NAME), &r.main_class, false)) {
                   if(Value *element=sql->get_element(*new(pool) String(pool, MAIN_SQL_DRIVERS_NAME), sql, false)) {
                           protocol2driver_and_client=element->get_table();
                   }
           }
   
 #ifdef RESOURCES_DEBUG  #ifdef RESOURCES_DEBUG
 //measure:before  //measure:before
Line 287  static void _switch(Request& r, const St Line 301  static void _switch(Request& r, const St
         r.process(cases_code, true/*intercept_string*/);          r.process(cases_code, true/*intercept_string*/);
         if(Value *selected_code=data.found ? data.found : data._default) {          if(Value *selected_code=data.found ? data.found : data._default) {
                 // setting code context, would execute in ^switch[...]{>>context<<}                  // setting code context, would execute in ^switch[...]{>>context<<}
                 selected_code->get_junction()->change_context(cases_code.get_junction());                  //selected_code->get_junction()->change_context(cases_code.get_junction());
                 r.write_pass_lang(r.process(*selected_code));                  r.write_pass_lang(r.process(*selected_code));
         }          }
 }  }
Line 306  static void _case(Request& r, const Stri Line 320  static void _case(Request& r, const Stri
                   
         // killing context for safety, would execute in ^switch[...]{>>context<<}          // killing context for safety, would execute in ^switch[...]{>>context<<}
         // reason: context is stacked, and it would become invalid afterwards          // reason: context is stacked, and it would become invalid afterwards
         code->get_junction()->change_context(0);          //code->get_junction()->change_context(0);
   
         for(int i=0; i<count; i++) {          for(int i=0; i<count; i++) {
                 Value& value=r.process_to_value(params->get(i));                  Value& value=r.process_to_value(params->get(i));
Line 404  const String *locked_process_and_cache_p Line 418  const String *locked_process_and_cache_p
                 false/*do_append*/,                  false/*do_append*/,
                 false/*block*/,                  false/*block*/,
                 false/*fail on lock problem*/) ? info.evaluated_body: 0;                  false/*fail on lock problem*/) ? info.evaluated_body: 0;
         if(data.expires==0)          time_t now=time(0);
           if(data.expires<=now)
                 cache_delete(file_spec);                  cache_delete(file_spec);
         return result;          return result;
 }  }
Line 436  static time_t as_expires(Request& r, con Line 451  static time_t as_expires(Request& r, con
                                                 int index, time_t now) {                                                  int index, time_t now) {
         time_t result;          time_t result;
         Value& vlifespan_or_expires=params->get(index);          Value& vlifespan_or_expires=params->get(index);
         if(strcmp(vlifespan_or_expires.type(), VDATE_TYPE)==0)          if(Value *vdate=vlifespan_or_expires.as(VDATE_TYPE, false))
                 result=static_cast<VDate&>(vlifespan_or_expires).get_time();                  result=static_cast<VDate *>(vdate)->get_time();
         else          else
                 result=now+(time_t)params->as_double(index, "lifespan must be date or number", r);                  result=now+(time_t)params->as_double(index, "lifespan must be date or number", r);
                   
Line 571  static void _try_operator(Request& r, co Line 586  static void _try_operator(Request& r, co
         Value& catch_code=params->as_junction(1, "catch_code must be code");          Value& catch_code=params->as_junction(1, "catch_code must be code");
   
         StringOrValue result;          StringOrValue result;
           // taking snapshot of try-context
         // taking snapshot of request processing status          Request_context_saver try_context(r);
         //int ssexception_trace=r.exception_trace.top_index();  
         int sstack=r.stack.top_index();  
         Value *sself=r.self, *sroot=r.root, *srcontext=r.rcontext;    
         WContext *swcontext=r.wcontext;   
         try {          try {
                 result=r.process(body_code);                  result=r.process(body_code);
         } catch(const Exception& e) {          } catch(const Exception& e) {
                 // restoring request processing status                  Request_context_saver throw_context(r); // taking snapshot of throw-context [stack trace contains error]
                 //r.exception_trace.top_index(ssexception_trace);                  try_context.restore(); // restoring try-context to perform catch-code
                 r.stack.top_index(sstack);  
                 r.self=sself; r.root=sroot, r.rcontext=srcontext; r.wcontext=swcontext;  
                   
                   
                 VHash& vhash=exception2vhash(pool, e);                  VHash& vhash=exception2vhash(pool, e);
   
                 Junction *junction=catch_code.get_junction();                  Junction *junction=catch_code.get_junction();
                 Value *saved_exception_var_value=junction->root->get_element(*exception_var_name);                  Value *method_frame=junction->method_frame;
                 junction->root->put_element(*exception_var_name, &vhash);                  Value *saved_exception_var_value=method_frame->get_element(*exception_var_name, method_frame, false);
                   junction->method_frame->put_element(*exception_var_name, &vhash, false);
                 result=r.process(catch_code);                  result=r.process(catch_code);
                 bool handled=false;                  bool handled=false;
                 if(Value *value=static_cast<Value *>(vhash.hash(0).get(*exception_handled_part_name)))                  if(Value *value=static_cast<Value *>(vhash.hash(0).get(*exception_handled_part_name)))
                         handled=value->as_bool();                                         handled=value->as_bool();               
                 junction->root->put_element(*exception_var_name, saved_exception_var_value);                  junction->method_frame->put_element(*exception_var_name, saved_exception_var_value, false);
   
                 if(!handled)                  if(!handled) {
                           throw_context.restore(); // restoring throw-context [exception were not handled]
                         throw(e); // rethrow                          throw(e); // rethrow
                   }
         }          }
         // write it out           // write out result
         r.write_pass_lang(result);          r.write_pass_lang(result);
 }  }
   
Line 638  static void _throw_operator(Request& r, Line 649  static void _throw_operator(Request& r,
                   
 // constructor  // constructor
   
 MOP::MOP(Pool& apool) : Methoded(apool, "OP"),  VClassMAIN::VClassMAIN(Pool& apool): VClass(apool) {
         main_sql_name(apool, MAIN_SQL_NAME),          set_name(*NEW String(pool(), MAIN_CLASS_NAME));
         main_sql_drivers_name(apool, MAIN_SQL_DRIVERS_NAME)  
 {  
         // ^if(condition){code-when-true}          // ^if(condition){code-when-true}
         // ^if(condition){code-when-true}{code-when-false}          // ^if(condition){code-when-true}{code-when-false}
         add_native_method("if", Method::CT_ANY, _if, 2, 3);          add_native_method("if", Method::CT_ANY, _if, 2, 3);
Line 653  MOP::MOP(Pool& apool) : Methoded(apool, Line 663  MOP::MOP(Pool& apool) : Methoded(apool,
         add_native_method("taint", Method::CT_ANY, _taint, 1, 2);          add_native_method("taint", Method::CT_ANY, _taint, 1, 2);
   
         // ^process[code]          // ^process[code]
         add_native_method("process", Method::CT_ANY, _process, 1, 1);          add_native_method("process", Method::CT_ANY, _process, 1, 2);
   
         // ^rem{code}          // ^rem{code}
         add_native_method("rem", Method::CT_ANY, _rem, 1, 10000);          add_native_method("rem", Method::CT_ANY, _rem, 1, 10000);
Line 699  MOP::MOP(Pool& apool) : Methoded(apool, Line 709  MOP::MOP(Pool& apool) : Methoded(apool,
   
 // constructor & configurator  // constructor & configurator
   
 Methoded *MOP_create(Pool& pool) {  VClass& VClassMAIN_create(Pool& pool) {
         return new(pool) MOP(pool);          return *new(pool) VClassMAIN(pool);
 }  
   
 void MOP::configure_user(Request& r) {  
         Pool& pool=r.pool();  
   
         // $MAIN:SQL.drivers  
         if(Value *sql=r.main_class->get_element(main_sql_name))  
                 if(Value *element=sql->get_element(main_sql_drivers_name))  
                         if(Table *protocol2library=element->get_table())  
                                 r.classes_conf.put(name(), protocol2library);  
 }  }

Removed from v.1.97  
changed lines
  Added in v.1.123


E-mail: