Diff for /parser3/src/classes/op.C between versions 1.106 and 1.127.2.6

version 1.106, 2002/09/10 12:02:23 version 1.127.2.6, 2003/01/31 14:03:52
Line 1 Line 1
 /** @file  /** @file
         Parser: parser @b operators.          Parser: parser @b operators.
   
         Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2003 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)
 */  */
   
Line 25  static const char* IDENT_OP_C="$Date$"; Line 25  static const char* IDENT_OP_C="$Date$";
   
 // 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;  
 };  };
   
   // helpers
   
   Hash<StringPtr, int> Hash untaint_lang_name2enum;
   
 // methods  // methods
   
 static void _if(Request& r, const String&, MethodParams *params) {  static void _if(Request& r, const String&, MethodParams *params) {
Line 102  static void _taint(Request& r, const Str Line 99  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();
         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_last_derived_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  
                 const String& source=r.process_to_string(params->as_junction(0, "body must be code"));  
                 // calculate pseudo file name of processed chars                  // calculate pseudo file name of processed chars
                 // would be something like "/some/file(4) process"                  // would be something like "/some/file(4) process"
                 char local_place[MAX_STRING];                  char local_place[MAX_STRING];
Line 137  static void _process(Request& r, const S Line 145  static void _process(Request& r, const S
   
                 // 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 185  static void _while(Request& r, const Str Line 194  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 203  static void _for(Request& r, const Strin Line 212  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.method_frame->put_element(var_name, vint, false);          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 243  struct timeval mt[2]; Line 252  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 270  r.sql_connect_time+=t[1]-t[0]; Line 283  r.sql_connect_time+=t[1]-t[0];
                 r.write_assign_lang(r.process(body_code));                  r.write_assign_lang(r.process(body_code));
         } catch(...) { // process problem          } catch(...) { // process problem
                 connection->mark_to_rollback();                  connection->mark_to_rollback();
                 /*re*/throw;                   rethrow; 
         }          }
 }  }
   
Line 293  static void _switch(Request& r, const St Line 306  static void _switch(Request& r, const St
         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, false /* get all that can be got */ ));                  r.write_pass_lang(r.process(*selected_code));
         }          }
 }  }
   
Line 343  static void _case(Request& r, const Stri Line 356  static void _case(Request& r, const Stri
   
 // consts  // consts
   
 const int DATA_STRING_SERIALIZED_VERSION=0x0002;  const int DATA_STRING_SERIALIZED_VERSION=0x0003;
   
 // helper types  // helper types
   
Line 368  struct Locked_process_and_cache_put_acti Line 381  struct Locked_process_and_cache_put_acti
         Value *body_code; const String *evaluated_body;          Value *body_code; const String *evaluated_body;
 };  };
 #endif  #endif
   /* @todo maybe network order worth spending some effort?
           don't bothering myself with network byte order,
           am not planning to be able to move resulting file across platforms
   */
 static void locked_process_and_cache_put_action(int f, void *context) {  static void locked_process_and_cache_put_action(int f, void *context) {
         Locked_process_and_cache_put_action_info& info=          Locked_process_and_cache_put_action_info& info=
                 *static_cast<Locked_process_and_cache_put_action_info *>(context);                  *static_cast<Locked_process_and_cache_put_action_info *>(context);
Line 419  String *cache_get(Pool& pool, const Stri Line 436  String *cache_get(Pool& pool, const Stri
         if(file_read(pool, file_spec,           if(file_read(pool, file_spec, 
                            data, data_size,                              data, data_size, 
                            false/*as_text*/,                              false/*as_text*/, 
                              0, 0, //no params&out_fields
                            false/*fail_on_read_problem*/)                             false/*fail_on_read_problem*/)
             && data_size/* ignore reads which are empty due to               && data_size/* ignore reads which are empty due to 
                         non-unary open+lockEX conflict with lockSH */) {                          non-unary open+lockEX conflict with lockSH */) {
Line 539  static void _cache(Request& r, const Str Line 557  static void _cache(Request& r, const Str
 }  }
   
 // also used in pa_request.C to pass param to @unhandled_exception  // also used in pa_request.C to pass param to @unhandled_exception
 VHash& exception2vhash(Pool& pool, const Exception& e) {  VHashPtr exception2vhash(const Exception& e) {
         VHash& result=*new(pool) VHash(pool);          VHashPtr result(new VHash));
         Hash& hash=result.hash(0);          Hash& hash=result.hash(0);
         if(const char *type=e.type(true))          if(const char* type=e.type(true))
                 hash.put(*exception_type_part_name, new(pool) VString(*new(pool) String(pool, type)));                  hash.put(*exception_type_part_name, new(pool) VString(*new(pool) String(pool, type)));
         if(const String *asource=e.problem_source()) {          if(const String *asource=e.problem_source()) {
                 String& source=*new(pool) String(pool);                   String& source=*new(pool) String(pool); 
Line 557  VHash& exception2vhash(Pool& pool, const Line 575  VHash& exception2vhash(Pool& pool, const
                         new(pool) VInt(pool, 1+origin.line));                          new(pool) VInt(pool, 1+origin.line));
 #endif  #endif
         }          }
         if(const char *ecomment=e.comment(true)) {          if(const char* ecomment=e.comment(true)) {
                 int comment_size=strlen(ecomment);                  int comment_size=strlen(ecomment);
                 char *pcomment=(char *)pool.malloc(comment_size);                  char *pcomment=(char *)pool.malloc(comment_size);
                 memcpy(pcomment, ecomment, comment_size);                  memcpy(pcomment, ecomment, comment_size);
Line 577  static void _try_operator(Request& r, co Line 595  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;  
         VMethodFrame *smethod_frame=r.method_frame;  
         Value *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.method_frame=smethod_frame, r.rcontext=srcontext; r.wcontext=swcontext;                  VHashPtr vhash=exception2vhash(pool, e);
                   
                   
                 VHash& vhash=exception2vhash(pool, e);  
   
                 Junction *junction=catch_code.get_junction();                  Junction *junction=catch_code.get_junction();
                 Value *method_frame=junction->method_frame;                  Value *method_frame=junction->method_frame;
                 Value *saved_exception_var_value=method_frame->get_element(*exception_var_name, method_frame, false);                  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);                  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;
Line 606  static void _try_operator(Request& r, co Line 615  static void _try_operator(Request& r, co
                         handled=value->as_bool();                                         handled=value->as_bool();               
                 junction->method_frame->put_element(*exception_var_name, saved_exception_var_value, false);                  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 619  static void _throw_operator(Request& r, Line 630  static void _throw_operator(Request& r,
         if(params->size()==1) {          if(params->size()==1) {
                 Value& param0=params->get(0);                  Value& param0=params->get(0);
                 if(Hash *hash=param0.get_hash(&method_name)) {                  if(Hash *hash=param0.get_hash(&method_name)) {
                         const char *type=0;                          const char* type=0;
                         if(Value *value=static_cast<Value *>(hash->get(*exception_type_part_name)))                          if(Value *value=static_cast<Value *>(hash->get(*exception_type_part_name)))
                                 type=value->as_string().cstr();                                  type=value->as_string().cstr();
                         const String *source=0;                          const String *source=0;
                         if(Value *value=static_cast<Value *>(hash->get(*exception_source_part_name)))                          if(Value *value=static_cast<Value *>(hash->get(*exception_source_part_name)))
                                 source=&value->as_string();                                  source=&value->as_string();
                         const char *comment=0;                          const char* comment=0;
                         if(Value *value=                          if(Value *value=
                                 static_cast<Value *>(hash->get(*exception_comment_part_name)))                                  static_cast<Value *>(hash->get(*exception_comment_part_name)))
                                 comment=value->as_string().cstr();                                  comment=value->as_string().cstr();
Line 638  static void _throw_operator(Request& r, Line 649  static void _throw_operator(Request& r,
                                 &method_name,                                  &method_name,
                                 "one-param version has hash param");                                  "one-param version has hash param");
         } else {          } else {
                 const char *type=params->as_string(0, "type must be string").cstr();                  const char* type=params->as_string(0, "type must be string").cstr();
                 const String& source=params->as_string(1, "source must be string");                  const String& source=params->as_string(1, "source must be string");
                 const char *comment=params->size()>2?params->as_string(2, "comment must be string").cstr():0;                  const char* comment=params->size()>2?params->as_string(2, "comment must be string").cstr():0;
                 throw Exception(type, &source, "%s", comment?comment:"");                  throw Exception(type, &source, "%s", comment?comment:"");
         }          }
 }  }
                   
 // 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 662  MOP::MOP(Pool& apool) : Methoded(apool, Line 672  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 708  MOP::MOP(Pool& apool) : Methoded(apool, Line 718  MOP::MOP(Pool& apool) : Methoded(apool,
   
 // constructor & configurator  // constructor & configurator
   
 Methoded *MOP_create(Pool& pool) {  VStateless_classPtr VClassMAIN_create() {
         return new(pool) MOP(pool);          #define ULN(name, LANG) \
 }                  untaint_lang_name2enum.put(StringPtr(new String(name)), (int)String::UL_##LANG);
           ULN("as-is", AS_IS);
 void MOP::configure_user(Request& r) {          ULN("optimized-as-is", AS_IS|String::UL_OPTIMIZE_BIT);
         Pool& pool=r.pool();          ULN("file-spec", FILE_SPEC);
           ULN("http-header", HTTP_HEADER);
         // $MAIN:SQL.drivers          ULN("mail-header", MAIL_HEADER);
         if(Value *sql=r.main_class->get_element(main_sql_name, r.main_class, false))          ULN("uri", URI);
                 if(Value *element=sql->get_element(main_sql_drivers_name, sql, false))          ULN("table", TABLE);
                         if(Table *protocol2library=element->get_table())          ULN("sql", SQL);
                                 r.classes_conf.put(name(), protocol2library);          ULN("js", JS);
           ULN("xml", XML);
           ULN("optimized-xml", XML|String::UL_OPTIMIZE_BIT);
           ULN("html", HTML);
           ULN("optimized-html", HTML|String::UL_OPTIMIZE_BIT);
           #undef ULN
           
           return VStateless_classPtr(new VClassMAIN);
 }  }

Removed from v.1.106  
changed lines
  Added in v.1.127.2.6


E-mail: