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

📄 function.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
{
 int mfb = Parser::global().alloc(sizeof(FBlock),NULL);
 FBlock *pf = (FBlock *)Parser::global().addr(mfb);
 pf->context = NULL;
 pf->nlocal = 0;
 pf->nargs = 0;
 pf->ntotal = 0;
 pf->entry = pe;
 pf->pstart = NULL;
 pf->class_ptr = pc;
 pf->data = NULL;
 pf->trace = NULL;
 return pf;
}

void FBlock::finalize(int sz)
{
 pstart = Parser::code().end_code();
 nlocal = sz/sizeof(int);     // our _total_ context size in _dwords_!
 ntotal = nlocal + nargs; // add args to get total size
 //class_ptr = NULL; // for now!!
}

int NFBlock::create(Function *pfn, CALLFN fn)
{
 PFBlock pfb = pfn->fun_block();

// set up native code call block;
 NFBlock fblk;
 fblk.pfn = fn;
 fblk.nargs = pfn->stdarg() ? -1 : pfb->nargs;
 fblk.flags = pfn->is_cdecl() ? DC_CDECL : 0;

// *add 1.1.0 Sometimes imported methods use the cdecl calling convention;
// the 'this' pointer becomes a hidden extra argument.
  if (pfn->is_method() && pfn->is_cdecl())
      fblk.nargs++;

 Type rt = pfn->return_type(); //sig.m_type;

 // Some schemes use half-assed cdecl convention for returning objects
 // *add 1.2.6 add support for true return by value (GCC3)
 ImportScheme* import = pfn->import_scheme(); 
 if (import && rt.is_object() && import->ret_obj_popped()) {
     if (! import->true_return_by_value(rt))
        fblk.flags += DC_RET_OBJ;
     else
        fblk.flags += DC_RET_VAL | DC_NOWORD;
 }
 else
 if (! rt.is_pointer()) {
   fblk.flags += rt.is_double() ? DC_QWORD : 0;
   fblk.flags += rt.is_void() ? DC_NOWORD : 0;
 } // otherwise a pointer is of course the default: 4 bytes.

 return Parser::global().alloc(sizeof(fblk),&fblk);
}


////
Function::Function(Signature *sig, FunctionEntry *pfe)
 : m_sig(sig),m_context(NULL),m_slot_id(0),m_fun_entry(pfe),
   m_default_args(NULL),m_stdarg(false),m_builtin(false),
   m_line_nos(NULL),m_templ_info(NULL),m_import_scheme(NULL)
{
 m_fun_block = FBlock::create(pfe->reference(),class_context());
 m_fun_block->function = this;
 m_line = Input::lineno();
 Module* pm = Module::current();
 m_mod = pm ? pm->id() : -1;
}

Function::~Function()
{
    delete m_line_nos;
}

bool Function::undefined()
{
  return m_fun_block->pstart == NULL;
}

void 
Function::set_construct_destruct(int ftype, bool no_implicit_type_conversion)
{
 m_ftype = ftype;
 Class *pc = class_context();
 //if (!is_plain() && pc) fail("must be within class definition");
 if (is_destructor()) {
  if(signature()->size() > 0) fail("destructor cannot be passed parameters");
  pc->destructor(this);
 } else
 if (is_constructor()) pc->add_constructor(this,no_implicit_type_conversion);
}

string
Function::name()
{
 return fun_entry()->reference()->name;
}

void Function::attach_context(FunctionContext *context)
{
 // since this happens whenever a function is being redefined, we call clear()!!
  clear();
  m_context = context;
  m_fun_block->context = m_context;
}

void Function::clear()
// this is used when we are interactively redefining a function;
// an opportunity to dispose of code, etc
{
// *NOTE* blew up trying to delete this....how was it alloc?
 //delete m_fun_block->context; 

 // line number info
 delete m_line_nos; 
 m_line_nos = new LineNumbers;

 // function block
 m_fun_block->nargs = 0;
}

void Function::slot_id(int i)
{
 m_slot_id = i;

}

void
Function::set_default_args(PExprList pel)
// ONLY called if there _were_ any default values for arguments
// Hmm...we must watch out here!
{
 int k=0;
 m_default_args = new ExprArray(0 /*pel->size()*/);
 m_default_index = -1;
 ExprList::iterator eli;
  for (eli = pel->begin(); eli != pel->end(); ++eli,++k)
    if (*eli != NULL) {
      if (m_default_index == -1) m_default_index = k; 
      m_default_args->push_back(*eli);
    } 
}

bool
Function::can_match(int size)
// can this function in principle match an argument list of a particular size?
{
  int asz = signature()->size();
  if (!m_default_args) {
    if (stdarg()) return size >= asz;
    else return size == asz; 
  } else 
  return size >= m_default_index && size <= asz;
}

PExprList
Function::complete_arg_list(PExprList args)
{
 if (!m_default_args) return NULL;
 if (args->size() < signature()->size()) {
   PExprList pdef = new ExprList(m_default_args->begin() + args->size()-m_default_index,
                                 m_default_args->end());
   args->insert(args->end(),pdef->begin(),pdef->end());
   return pdef;
 } else return NULL;
}

void Function::dump(ostream& os)
{
 Signature::set_fun_name(name(),is_constructor(),is_destructor()); 
 os << *signature();
}

string Function::as_str()
{
 char buffer[MAX_FUN_NAME];
 ostrstream out(buffer,MAX_FUN_NAME);
 dump(out);
 out << ends;
 return buffer;
}

Function *
Function::from_fun_block(FBlock *pfb)
{
  FunctionEntry *pfe = (FunctionEntry *) pfb->entry->data;
  return pfe->fun_from_fblock(pfb);
}

// do note that this version only works for non-overloaded functions!
Function *
Function::lookup(const string& nm)
{
 PEntry pe = Parser::symbol_lookup(nm);
 if (!pe || !pe->type.is_signature()) return NULL;
 FunctionEntry *pfe = (FunctionEntry *)pe->data;   // shd be a method, really
 return pfe->back();
}


void FunctionEntry::dump (ostream& os)
{
 iterator ife;
 int idx = 1;
 for (ife = begin(); ife != end(); ++ife) {
   Function *pf = *ife;
   os << idx++ << ' ';
   pf->dump(os);
   if (pf->is_virtual()) os << " - slot " << pf->slot_id();
   os << endl;
 }
 Signature::set_fun_name("");
}


Function *
FunctionEntry::nth_fun(int idx)
{
   iterator fei = begin();
   Function *fn;
   if (idx == 0) idx = 1; 
   if (idx >= size()) idx = size();
   for(int i = 1; i <= size(); ++i, ++fei)
       if (i == idx) { fn = *fei; break; }
   return fn;
}

Function *
FunctionEntry::fun_from_fblock(FBlock *pfb)
{
   for(iterator fei = begin(); fei != end(); ++fei)
       if ((*fei)->fun_block()==pfb) return *fei;
   return NULL;
}


// these odd little functions are useful when debugging the system, 
// since Visual Studio and GDB will happily execute them for you on request.
static char buff[60];

char *sh_sig(Signature& s)
{
 *buff = 0;
 ostrstream outs(buff,60);
 outs << s << ends;
 return buff;
}

char *sh_type(Type& t)
{
 *buff = 0;
 ostrstream outs(buff,60);
 outs << t << ends;
 return buff;
}


// *change 1.2.3a 'do_strict' insists that the signatures match exactly; otherwise
// we allow for looser matches (particularly method signatures)
bool Signature::match(const Signature& sig, bool do_strict) const
{
// Comparing signatures 
// *fix 1.2.2b (Eric) Functions w/ no args can be incorrectly matched
 if (this == &sig) return true;
 if (size() != sig.size() || !class_ptr() != !sig.class_ptr()) return false;
 // *fix 1.2.3 Method signatures made tighter in 'exact match' mode
 if (class_ptr() != NULL && sig.class_ptr() != NULL) {
     if ((do_strict && class_ptr() != sig.class_ptr())
        || !sig.class_ptr()->inherits_from(class_ptr()))
     return false; // *fix 1.2.1 Member function signatures are distinct!
 }
 if (is_const() != sig.is_const())
     return false; // *fix 0.9.6 constness makes signatures distinct
 if (stdarg() != sig.stdarg())
     return false; // *fix 1.2.3 (Eric) And so does whether this is stdarg or not
 
 Signature::iterator ti,tio;
 try {
 for(ti = begin(), tio = sig.begin(); ti != end(); ++ti,++tio)
   if (!(*ti == *tio)) return false;
 } catch(...) {
   return false;
 }
 //* return tio == sig.end() && ti == end(); //true;
 return true;
}

#pragma optimize( "", off )
static Function *_fn;

Function *
FunctionEntry::simple_match(Signature *sig)
{
 iterator ife;
 for (ife = begin(); ife != end(); ++ife) {
   _fn = *ife;
   if (_fn == NULL)
       return NULL;
   if (_fn->signature()->match(*sig)) return *ife;
 }
 return NULL; // for now...
}

Function *
FunctionEntry::full_match(Signature *)
{
// basically not implemented!
 return back();
}



⌨️ 快捷键说明

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