⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
   pe->m_typename = false;
   FunctionEntry *pfe = new FunctionEntry(pe);
   pe->data = (int)pfe;
   return pfe;
}

// *add 1.2.8 convenient function for working with signatures
string sig_as_str(Signature* sig, const string& name)
{
    char buff[255];
    Signature::set_fun_name(name);
    ostrstream out(buff,255);
    out << *sig;
    return buff;
}

string class_name(Type t)
{ return t.is_class() ? t.as_class()->name() : string("<unknown>"); }

void error_not_in_class(const string& name, Type class_type)
{
 fail(quotes(name) + " not found in class " +  quotes(class_name(class_type)));
}

// *change 1.2.9 template functions in enclosing scopes are NOT handled specially
// any more. We just have to be careful for the case where a function entry has
// no functions.
// *fix 1.2.9 member templates now work.
FunctionEntry *
lookup_function_entry(Signature *sig, const string& name,bool fn_defn,
                                     Function **fn, int& slot_id)
{ 
 Type method_scope = state.class_dcl;
 state.class_dcl = t_void;
 bool method_body = method_scope != t_void;

 PEntry pe = symbol_lookup(name);  
 mIsConversion = name == CONVERSION_OPNAME;
 FunctionEntry *pfe = NULL, *local_entry = NULL;
 slot_id = 0;
 *fn = NULL;
 if (pe) { // already is an entry
    bool is_function = pe->type.is_signature();   
    Table* cntxt = &state.context(); 
    pfe = (FunctionEntry *)pe->data;

    // but is it local?  In which case we try to overload 
    if (cntxt->is_local_entry(pe)){
     // *add 1.2.8 'main' can't be overloaded...
     if (name == "main") return NULL;
     if (is_function) { 
        *fn = pfe->simple_match(sig);
        if (*fn) { // but not if this signature is already present!
           // if this function is already complete, we can only
           // redeclare it, not redefine it.           
           if ((*fn)->context() && fn_defn) {
               if (!interactive_mode()) { error_already_defined(name); return NULL; }
             else (*fn)->clear(); // ISSUE: again, interactive mode is more lenient
           } 
           // *issue 0.9.5 allows us to actually change the return type; when shd it be an error?
           if ((*fn)->return_type() != sig->return_type()) { *fn = NULL; return NULL; }
           return pfe;  // reuse entry...
        } else // another case: the set is virtual - in which case, this entry
               // is hiding the original virtual entry!
        if (state.in_template != NULL && pfe->size() > 0 && pfe->back()->is_virtual()) {
           pe = cntxt->parent_context()->lookup(name);
           if (pe==NULL) return pfe; // this set was created in the current class...
           if (pe->type.is_signature()) { // continue to find virtual slot....
               local_entry = pfe;                //save local entry
               pfe = (FunctionEntry *)pe->data;  //but look at inherited entry!
           } else return NULL;  // wasn't a function, so ditto
        } else {  // cool - can now try to overload....
        // *fix 1.2.8 except of course, if this is a method body definition;
        // there must be a corresponding method declaration!
        // *fix 1.2.9 unless this is a member template instantiation; the function
        // doesn't exist at this point!
            if (method_body && state.in_template == NULL)
                error_not_in_class(sig_as_str(sig,name),method_scope);
            else return pfe;          
        }
     } else { error_already_defined(name); return NULL; }// and it wasn't a function!
   }
   // *fix 1.2.4 Qualified method name (C::name(...)) where 'name' is not found directly in 'C'
   else if (method_body) error_not_in_class(name,method_scope);

   // an entry in some enclosing scope
   if (is_class(pe->context)) {
       *fn = pfe->simple_match(sig);
       // if a virtual method, get its slot id
       // but always redeclare (hence hiding the original entry)
       if (*fn != NULL) {
         if ((*fn)->is_virtual()) { 
			 slot_id = (*fn)->slot_id();
			 if (slot_id > 512) slot_id = 1;
		 }
         //*HACK* this was very irritating - switch it off while importing...
        // else warning(quotes(name) + " will be hidden");   
       } 
   }
   *fn = NULL; //*????*
   // *fix 1.2.9 The _specific case_ where we're instantiating a function template;
   // the entry already exists!
   if (state.in_template && 
       state.in_template->get_template()->get_entry()->entry() == pe) return pfe;
   else  return local_entry ? local_entry : NULL; // NULL create a new entry please!
 } else // not found!
 if (method_body) {
  error_not_in_class(name,method_scope);
  return NULL;
 } else return NULL;
}   


void ParserState::set_construct_destruct(int ftype)
{
  in_construct_destruct = ftype;
}

Function *generate_function(Signature *sig, FunctionEntry *pfe, int slot_id, bool imported)
{
  PClass pclass = class_context();
  Function *fn = new Function(sig,pfe); 
  //*NOTE* This is somewhat awkward, and needs to be done up 
  // before _anybody else_ sees it!
  if (pclass != NULL && state.modifier != Static && state.in_construct_destruct == IsPlain)
       state.in_construct_destruct = 3;
  fn->set_construct_destruct(state.in_construct_destruct, state.modifier == Explicit);
  state.in_construct_destruct = IsPlain;
  pfe->push_back(fn);
  fn->builtin(imported ? Function::CDECL : Function::UCFN);
  // *change 1.2.3 Flag how this function must be exported as a callback
  fn->export_as_cdecl(state.modifier != Stdcall);

  if (state.modifier==Virtual || slot_id > 0) {     
     if (!pclass) fail("'virtual' not allowed here");
     /// A new virtual method gets a new (non-zero) slot id
     if (slot_id == 0) slot_id = pclass->next_slot();
     fn->slot_id(slot_id); 
	 // *fix 1.1.0 add the slot to the class...
	 pclass->set_slot(fn->slot_id(),fn);             
  }
  state.modifier = None; 

  if (mIsConversion) { 
     if (!pclass) fail("conversion operator must be a method");
     pclass->set_conversion_to(fn);
  }
  //REF:TEMPLATE
  // *fix 0.9.3 Didn't check to see that this was the same template....
  // (got confused during class instantiation)
  if (pfe->get_template() != NULL && state.in_template != NULL
         && ! state.in_template->get_template()->is_class()) {
       fn->set_template(state.in_template);
       fn->get_template()->data(fn);
  }
  return fn;
}

void set_default_args(Function *fn, bool do_clear, bool is_defn=false)
{
  // set any default arguments - will overwrite any currently defined ones!
  PExprList pel = get_default_arguments();
  if (pel) { 
     // *fix 0.9.4 Now complains about default args in fn. defn 
     // *NOTE* We should move this 'not defined' test to Function...
     if (is_defn && fn->fun_block()->pstart == NULL
        && fn->has_default_args()) fail("Cannot redefine default arguments");
     fn->set_default_args(pel);
     delete pel;
  }
  if (do_clear) state.arg_list.clear(); 
}


Table* enclosing_namespace(Table* pt)
{
  while (pt->type() != IS_NAMESPACE && pt != &global())
    pt = pt->parent_context();
  return pt;
}

Function *ParserState::declare_function(Type t,const string& name, PExpr poss_init)
{
 int slot_id, modifier_flags = modifier;  
 in_declaration = false;
 Function* fn = NULL;
 Table* fcntext = NULL;
try {
  Signature *sig = get_signature(t);

  bool was_import = Builtin::get_dll_handle() && poss_init == NULL;
  PClass  class_ptr = class_context();

 // string cname = class_ptr ? class_ptr->name() : ""; //*DEBUG

  if (in_friend_dcl) {  // *add 0.9.5 Friend function declaration
      if (class_ptr == NULL) fail("Friend declaration only allowed in class declaration");
      pop_context(); // to ensure that friend dcl lookup is outside this scope...
  } else if (context().type()==FUNCTION) { // *fix 1.2.6 declaration within function scope
     fcntext = enclosing_namespace(&context());
     push_context(fcntext);
  }

  FunctionEntry *pfe = lookup_function_entry(sig,name,false,&fn, slot_id); 

  if (in_friend_dcl) {  // Parser::state.in_friend_dcl
      push_context(class_ptr);
  } 

  if (!pfe) pfe = create_function_entry(sig,name);
  if (!fn) { // add a new function to the overloaded set!
   fn = generate_function(sig,pfe,slot_id,was_import); 
  }

  if (fcntext) pop_context();

  set_default_args(fn,true);

  if (in_friend_dcl) { // *fix 1.1.0 friend declarations act as forward declarations
     class_ptr->add_friend_object(fn,false);
     in_friend_dcl = false;
     return fn;
  }

  if (state.in_template && class_ptr) { // w/in class template instantiation
   // *add 1.1.0 Any externally defined method template entries must be attached
   // to corresp methods
    TemplateInstance *ti = state.in_template;  // i.e. the class template instance
    const EntryList *pfl = ti->get_template()->get_entry()->method_entries();
    if (pfl) {
       EntryList::const_iterator eli;
       FORALL(eli,*pfl) {
		  PEntry pe = *eli;
		  if (pe->name == name)  // attach the method templates to the methods...
		    pfe->set_template(PFunctionEntry(pe->data)->get_template()); 	      
       }	 
    } 
  }
 
  if (poss_init != NULL) { // *add 0.9.5 pure virtual methods
     if (class_ptr == NULL) fail("must be in class context");
     if (!fn->is_virtual()) fail("method must be virtual");
     if (!poss_init->type().is_zero()) fail("must be zero for pure virtual method");
     class_ptr->make_abstract();
  } else {
  // This prototype may represent a dynamic link to a DLL
  // *fix 1.2.3 Don't try to import a pure virtual method
    if (was_import) {
      string name;
   // *fix 0.9.5 state.modifier is reset - this CONTINUOUSLY gives trouble...
   // *hack 1.1.4 Some libraries have a number of entries which can't be found.
      if (!Builtin::add_dll_function(fn,modifier_flags,name) && ! debug.suppress_link_errors)
        cerr << "cannot link to " + quotes(name) << endl;
    }
  }
 } catch(string msg) { error(msg); }
 // NB to reset state!!
 modifier = None;  
 in_friend_dcl = false;
 return fn;
}

Function *ParserState::start_function(Type t, const string& name,bool init_context, int ftype)
{
 int slot_id, modifier_flags = modifier;
 PEntry pe;
 Function *fn = NULL;
 ArgList by_val_list;
 
 try {  
  PClass  class_ptr = class_context();

  Signature *sig = get_signature(t);
  FunctionEntry *pfe = lookup_function_entry(sig,name,true,&fn,slot_id);
  if (!pfe)  pfe = create_function_entry(sig,name);
  if (!fn)  // add a new function to the overloaded set!
     fn = generate_function(sig,pfe,slot_id,false); 
 
  fn->builtin(ftype);
  if (fn->builtin()) fn->import_scheme(Import::scheme());
  set_default_args(fn,false,true);

#if _DEBUG
  gLastFunction = fn; //*DEBUG*
  if (gDebugBreak) {
      if (gDebugBreak == 2) 
          __break(2);
      else
         gFunBlock = fn->fun_block();
      gDebugBreak = 0;
  }
#endif

   // Create a function context and make it current!
  FunctionContext *fcntxt;
  Table *cntxt = &context();
  if (fn->is_constructor()) fcntxt = new ConstructorContext(cntxt,fn); else
  if (fn->is_destructor())  fcntxt = new DestructorContext(cntxt,fn);
  else fcntxt = new FunctionContext(cntxt,fn);
  if (init_context) fcntxt->initialize();
  else  {
      fn->clear();
      set_function_code(true); // *fix 0.9.5 was not called before constructor init. lists
  }
  push_context(fcntxt);  

  if (class_ptr) { // methods need a 'this' variable!
     Type cpt = class_ptr->entry()->type;
     cpt.incr_pointer();
     //     cpt.make_const();  // *fix 1.2.7
     PEntry p_this = fcntxt->add("this");
     p_this->type = cpt;
     p_this->data = THIS_OFFSET;
  }

  dcl_init_size = 0; 

  // Add any args, ignoring the initializers
  // (1) Passing objects _by value_ is achieved by a dummy ref. argument,
  // which is then used to initialize a proper local object.
  // *add 1.1.0 unless we're importing a function which does need true by value passing! (like MSC++)
  // *add 1.2.6 which may well be conditional on the object size and type (like GCC 3)
  // (2) We pass a hidden first arg for routines returning object values
  // *add 1.2.6 unless this is a function which does true by value return (like GCC 3)

  ImportScheme* import = fn->import_scheme();
  if (t.is_object() && ! (import && import->true_return_by_value(t))) {
     t.make_reference();
     fn->return_object(add_variable(t,"*",NULL,ARG));
  }
  ArgList::iterator ali;
  bool passing_obj_by_value = false;
  // *fix 0.9.2 Template class arguments may be instantiated during add_variable()
  //  The state is restored ok, but the arg_list iterator was no longer valid.
  for(; arg_list.size() > 0; arg_list.pop_front()) {
     Type t = arg_list.front().type;
     string name = arg_list.front().name;
     // *fix 1.2.2b if this name is empty, replace by '*', which means 'create temporary name'
     if (name == "") name = "*";
     if (t.is_object() && ! (import && import->true_pass_by_value(t))) {
       by_val_list.push_back(ArgEntry(t,name,NULL));
       t.make_reference();
       name = "*";
       passing_obj_by_value = true;
     }

     pe = add_variable(t,name,NULL,ARG); 

     if (passing_obj_by_value) {
       by_val_list.back().init = Expressions::entry_op(pe);
       passing_obj_by_value = false;
     }  
  }
  // any objects passed by value are now declared in the function context; these
  // are initialized using the reference parameter created above.
  // *add 1.1.0 except if this was a native call...
  if (by_val_list.size() > 0 && ! fn->builtin()) {
    for(ali = by_val_list.begin(); ali != by_val_list.end(); ++ali)
      add_variable(ali->type,ali->name,ali->init);
    by_val_list.clear();
  }

 } catch(string msg) { error(msg); }  
 class_dcl = t_void;  // just in case...
 return fn;
}

PEntry ParserState::add_typedef(Type t, const string& name)
{
 in_typedef = true;
 PEntry pe = add_variable(t,name,NULL,None);
 in_typedef = false;
 return pe;
}

// this structure makes sure that the state is _always_ properly sorted out
// when we leave add_variable(), even if we just return.
// *fix 1.2.7 this sorts out a problem with extern arrays followed by plain const defs:
//  extern char obuff[BUFFSIZE];
//  const int TOPLEFT = 1;  // blew up because s_array_size was NOT reset

struct PopAtEnd {
    bool m_context_pushed;

    PopAtEnd() : m_context_pushed(false) { }
    void set() { m_context_pushed = true; }
    ~PopAtEnd() {
        if (m_context_pushed) state.pop_context();
        reset_array_size();
    }
};


PEntry ParserState::add_variable(Type t, string name, Expression init, int mode)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -