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

📄 function.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* FUNCTION.CPP
 * Support for functions: classes: Function,FunctionEntry,LocalContext
 * UnderC C++ interpreter
 * Steve Donovan, 2001
 * This is GPL'd software, and the usual disclaimers apply.
 * See LICENCE
*/
#include "common.h"
#include "opcodes.h"
#include "module.h"
#include <ctype.h>
#include "directcall.h"
#include "input.h"

#ifdef __GNUC__
#include <strstream.h>
#endif

const int MAX_FUN_NAME = 256;

//#include "function.h"
//#include "expressions.h"

namespace { // private stuff
 string s_fun_name = "<none>";
 bool s_ctor = false, s_dtor = false;

 inline int max(int i, int j)
{ return i > j ? i : j; }

};

// Line Number Management

typedef std::list<LineInfo> LineInfoList;

// this overrides the virtual base class
class LineNumbers: public LineNumbersB {
private:
    LineInfoList m_li;
    int m_module;
public:
   void add(const LineInfo& li) // override
   {
     m_li.push_back(li);
   }

   // *fix 1.2.7 necessary to look for the next line, if we match exactly
   bool lookup_line(LineInfo& li, bool find_line) // override
   {
       LineInfoList::iterator lili, lili_end = m_li.end();
       for(lili = m_li.begin(); lili != lili_end; lili++)
           if (find_line && lili->ip_offset >= li.ip_offset) {
               if (lili->ip_offset == li.ip_offset) {
                   lili++;
                   if (lili == lili_end) return false; //*ALWAYS?*
               }
               li = *lili;
               return true;
           } else
           if (!find_line && lili->line >= li.line) {
               li = *lili;
               return true;
           }         
       return false;
   }

   // *add 1.2.7    
   void dump(ostream& out)
   {
       LineInfoList::iterator lili;
       for(lili = m_li.begin(); lili != m_li.end(); lili++)
           out << lili->line << ' ' << lili->ip_offset << ' ' << lili->file << endl;
   }

   
   int  lookup_ip(int line) // override
   {
    LineInfo li;
    li.line = line;
    if (lookup_line(li,false)) return li.ip_offset;
    else return 0;
   }

   void lookup_range(int& l1, int& l2)
   {
       LineInfoList::iterator lili;
       if (m_li.size()==0) 
	   {
		   l1 = l2 = -1; 
	   }
	   l1 = m_li.front().line;
	   l2 = m_li.back().line;
   } 

   LineNumbers() : m_module(-1) {}

   void module(int id)     { m_module = id;   }
   int  module()           { return m_module; }

};

static bool s_full_names = true;

void Signature::set_fun_name(const string& name, bool is_ctor, bool is_dtor)
{
  s_ctor = is_ctor;
  s_dtor = is_dtor;
  s_fun_name = name;
}

string Signature::get_fun_name()
{ return s_fun_name; }

void Signature::write_qualified_names(bool yesno)
{ s_full_names = yesno; }

// miscelaneous output routines
ostream& operator << (ostream& os, Signature& sig)
{
 Signature::iterator si;
 StringList::iterator sli;
 StringList *args = sig.get_arg_names();
 if (args && args->size()==0) args = NULL;
 if (!s_ctor && !s_dtor)  // *fix 1.1.2 these don't have return types!
   os << sig.return_type() << ' ';  
 string na = s_fun_name;
 char first = na[0];
 // *fix 1.2.7 wasn't outputing 'operator' in front of '()'
 if (!isalpha(first) && first != '_' /*&& first != '('*/) na = "operator" + na;
 PClass pc = sig.class_ptr();
 if (pc != NULL) {
    string classn = pc->name();
    if (! s_full_names && pc->is_template()) classn = pc->get_template()->name();
    if (s_ctor)  na = classn; else
	if (s_dtor)  na = "~" + classn;
    if (s_full_names) na = classn + "::" + na;
 }
 os << na << '(';
 if (args != NULL) sli = args->begin();
 for(si = sig.begin(); si != sig.end(); ) {
   os << *si++;
   if (args != NULL) os << ' ' << *sli++;
   if (si != sig.end()) os << ',';
 }
 os << ')';
 if (sig.is_const()) os << " const";
 return os;
}

ostream& operator <<(ostream& os, Function& f)
{
  f.dump(os);
  return os;
}


LocalContext::LocalContext(Table *parent, Function *f) 
  : Table(parent,SREL,0),m_function(f), m_no_auto_dtor(false)
{
    m_type = FUNCTION;
    set_mem_unit(4);     // we work in DWORDS
    set_dword_align(4);  // *fix 1.2.3 Local contexts have 32-bit alignment _explicitly_
    set_parent(parent);
}

int LocalContext::alloc(int sz, void *data)
{
// remember to keep the parent updated!
 if (m_parent->type()==FUNCTION) m_parent->alloc(sz,NULL);
 return Table::alloc(sz,data);
}

void LocalContext::set_parent(Table *parent)
{
    m_parent = parent;  // *fix 0.9.5 m_parent was set _after_ calling update_parent!

   // start off where our parent ended....
    if (parent->type()== FUNCTION) {
       if (m_data == 0) m_data = (char *)parent->size();
    }
}

bool LocalContext::check_objects(bool do_clear)
{
    // Any local objects requiring destruction must be unwound...
    if (m_first_obj != NULL) {
      Parser::code().emit(UNWIND,SREL,m_first_obj->data);
      if (do_clear) m_first_obj = NULL;
      return true;
    } else return false;
}

void LocalContext::finalize()
{
	check_objects();
}

void LocalContext::add_line_no(const string& file, int line) // override
{
  LineInfo li;
  if (function() == NULL) return;  // local context in interactive mode
  li.file = file;
  li.cntxt = this;
  li.line = line;
  li.ip_offset = Parser::code().ip_offset();
  // *fix 1.2.7 We were adding line numbers in interactive debugging mode.
  // So check that the module id has been set (which only happens on finalization of context)
  LineNumbersB* lnb = function()->line_nos();
  if (lnb->module() == -1) lnb->add(li);
}

FunctionContext::FunctionContext(Table *parent, Function *f)
 : LocalContext(parent,f)
{
}

FBlock *
FunctionContext::fun_block()
{
 return function()->fun_block();
}

void FunctionContext::initialize()
{
 Function *fn = function();
 fn->attach_context(this);
 
 FBlock *fb = fun_block();
 if (fb->pstart) delete fb->pstart;  // may be previously defined!
 fb->pstart = 0;
 fb->nargs = 0;                      // crucial to clear this!

// and switch to the function compile context!
 Parser::set_function_code(true);

 // *change 1.2.9 This is now retired; this is called explicitly before main()
 // *fix 1.2.5 Ensure that any library initializations occur before a program is run!
 //if (fn->name()=="main") {
 //  Parser::code().compile(Expressions::function_call("_init_lib",NULL),DROP_VALUE);
 //}
}


void FunctionContext::finalize()
{
 UCContext& code = Parser::code();
 // if the last instruction was a trival RETURN jump, ignore it!
 int op = code.last_pi()->opcode;
 Label *ret_lbl = Parser::state.return_label();
 if (op == JMP && code.last_pi()->data == code.ip_offset()) {
   ret_lbl->remove(code.last_pi());  // take out this JMP
   code.backspace();                 // skip back
   ret_lbl->here();                  // repatch all other instances of return jump
 } else
 if (ret_lbl && op == UNWIND) ret_lbl->here(-1);

 LocalContext::finalize();

 // *fix 1.1.0 Finalizing the context often generates an UNWIND;
 // ensure that all returns jump to it first!
 if (ret_lbl && code.last_pi()->opcode == UNWIND) ret_lbl->here(-1);
 
 // appropriate RETx instruction
 code.emit_return(m_function->return_type());

 fun_block()->finalize(size());

  // and switch to back to the static compile context...
 Parser::set_function_code(false);

 // update the module structure with our line number range
 int lstart, lend;
 function()->line_nos()->lookup_range(lstart,lend);
 if (lstart < 0 || lend < 0)
     lstart = 0;
 Module *pm = Module::current();
 if(pm) {
     pm->add_function(function(),lstart,lend);
     function()->line_nos()->module(pm->id());
 } else function()->line_nos()->module(0);
}

bool  FunctionContext::ip_to_line(LineInfo& li)
{
    return function()->line_nos()->lookup_line(li,true);
}

ConstructorContext::ConstructorContext(Table *parent, Function *fun)
 : FunctionContext(parent,fun)
{
}

void ConstructorContext::initialize()
{
 FunctionContext::initialize();
 if (!function()->builtin()) function()->class_context()->auto_construct(false);
}

void ConstructorContext::finalize()
{
  Parser::check_temp_context();  // *fix 0.9.5 force this where there's no code in constructor body
  FunctionContext::finalize();
}

DestructorContext::DestructorContext(Table *parent, Function *fun)
 : FunctionContext(parent,fun)
{
}

void DestructorContext::finalize()
{
  if (!function()->builtin()) function()->class_context()->auto_destruct(false);
  FunctionContext::finalize();  // *fix 0.9.4 auto-generated destructor code wasn't written to function!
}

FBlock *FBlock::create(PEntry pe, PClass pc)

⌨️ 快捷键说明

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