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

📄 common.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:

// *fix 1.2.4 When breaking out of a loop inside a local context, do check that 
// there _actually is_ a context local to the loop!  We were trashing objects!
// *fix 1.2.5 The new 'false' param for LocalContext::check_objects() prevents
//  the system for considering this context to be fully unwound. We were losing
//  normal unwind at the end of loops.
bool check_local_unwind()
{
 if (is_local(&state.context()) && state.context_generated())
     return ((LocalContext&)state.context()).check_objects(false);
 else return false;
}

bool do_break_continue(int keyword)
{
  LabelStack &lstack = (keyword==BREAK) ? state.break_stack : state.continue_stack;
  if (lstack.depth()==0) { error("break/continue not allowed here"); return false; }
  if (keyword==BREAK) check_local_unwind();
  code().jump(JMP,lstack.TOS());
  return true;
}

///// implementing switch statements

void do_switch(PExpr e)
{
 state.in_switch = true;
 push_label_stack(); // for the break....
 code().compile(e);
 state.switch_stack.push(new SwitchBlock(&code()));
 code().emit(JSWITCH,DIRECT,0);
}

bool do_case(PExpr e)
{
 if (e) {
   void *cnst_ptr = ExprToPtr(e);
   int val;
   if (cnst_ptr==NULL) { error("Case label cannot be an expression"); return false; }
   switch(e->type().size()) {
   case sizeof(long):  val = *(long *)cnst_ptr;  break;
   case sizeof(short): val = *(short*)cnst_ptr;  break;
   case sizeof(char):  val = *(char *)cnst_ptr;  break;
   default: { error("Case label must be an integer type"); return false; }
   }
   state.switch_stack.TOS()->add_jump(val);
 }else state.switch_stack.TOS()->add_default();
 return true; // for now
}

void end_switch()
{
 state.break_stack.TOS()->here();
 delete state.switch_stack.pop()->construct();
}

////////// implementing goto
static Label* create_goto_label(char* label_name)
{
// NB to create the label in the overall function context, not some local block
 Table* cntxt = ((LocalContext&)state.context()).function()->context();
 PEntry label_entry = cntxt->add(label_name);  
 label_entry->type = t_label;
 label_entry->size = 0;
 Label* label = new Label(&code());
 label_entry->data = (int)label;
 return label;
}

static Label* check_goto_label(PEntry label_entry)
{
  if (! state.return_label())
     fail("goto only allowed in functions");
  if (label_entry->type != t_label)
     fail(label_entry->name + " is already defined");
  return (Label*)label_entry->data;    
}

void do_goto(char* label_name)
{
 try {
  Label* label = NULL;
  Table* cntxt = &state.context();
  PEntry label_entry = cntxt->lookup(label_name);
  if (label_entry) label = check_goto_label(label_entry);
  if (! label) {           // ----not declared yet; forward jump----
     label = create_goto_label(label_name);  
     // if there were local objects needing destruction, keep track of this!
     if (check_local_unwind()) label->context(cntxt);
  } else {                 // ----backward jump---------------------
      // only try to unwind local objects if the actual label was outside our context
      // (if the label doesn't have an address, then we haven't found it yet)
     if (label->context() != cntxt || ! label->addr_is_set()) check_local_unwind();
  }
  // and do the jump!
  code().jump(JMP,label);
 } catch(string s) {
   error(s);
 }
}

void goto_label_new(char* name)
{
 Label* l = create_goto_label(name);
 l->here();
}

void goto_label_existing(PEntry pe)
{
 try {
   Label* l = check_goto_label(pe);
   l->here();
   if (l->context() == &state.context()) l->patch_with_NOP();
 } catch(string s) {
   error(s);
 }
}


string name_of(Type t)
{ 
 static string s;
 t.as_string(s);
 return s;
}

bool ParserState::begin_scope(Type t)
{
 if (!t.is_class()) {
    error(quotes(name_of(t)) + " is not a class, struct or namespace");
    return false;
 } else {
    PClass pc = t.as_class();  
  //* this forces instantiation of templates when we need to access their members
    if (! t.is_namespace()) pc->make_available();
    push_context(pc);
    scope_context_stack.push(scope_context);
    scope_context = &context(); 
    gScopeContext = scope_context;
    return true;
 }
}

// *add 1.2.7 backing scope_context with a stack...
void ParserState::end_scope()
{
  pop_context();
  scope_context = scope_context_stack.pop();
}

PClass class_context()
{
 return is_class(&state.context()) ? PClass(&state.context()) : NULL;
}

void error_already_defined(const string& name)
{
 if (! interactive_mode())
  fail(quotes(name) + " is already defined");
}


// *add 1.2.6 union
Type ParserState::add_class(int s_or_c, const string& pname, int deriv_access, Type base_class)
{
 bool is_struct = s_or_c != CLASS;
try {
 Table *instantiation_context = NULL;
 Table *cntxt = &context();
 // *add 1.1.4 
 // * tagless structs are given a temporary name
 // * in C mode, structs and unions are made distinct so they don't conflict w/ variable names ('struct tm tm')
 string name = pname;
 if (name == "") name = make_temp_name();
 else if (debug.c_mode && is_struct) name = "$_" + name; 
 PEntry pe = context().lookup(name);
 bool already_defined = pe != NULL;

  //*SJD* ISSUE Policy is a little loose here;  I'm allowing redefinition
 // but really it is another concession to interactive mode.
// if(already_defined && context().is_local_entry(pe)) error_already_defined(name);
 if(!already_defined) {
 // *fix 0.9.6 a template class is w/in an 'instantiation context' - watch out for nested case!
 // *fix 0.9.8 the IC is _injected_ into the class context - parent trick breaks down w/ derivation
    // if (in_template == NULL || context().type() != INSTANTIATION_CONTEXT)
    //      pe = context().add(name);
    // else pe = context().parent_context()->add(name); // the enclosing namespace

    if (in_template != NULL && context().type() == INSTANTIATION_CONTEXT) {
       instantiation_context = pop_context();
       cntxt = instantiation_context->parent_context();
    }
    pe = cntxt->add(name);
	//if (deriv_access == ForwardClass && in_typedef)
 } 
 Class *base = NULL;
 if (deriv_access != NotDerived && deriv_access != ForwardClass) {
   string nb = quotes(as_str(base_class));
   if (!base_class.is_class())   fail(nb + " is not a class");
   base = base_class.as_class();
   if (! base->make_available()) fail(nb + " is not fully defined");
 }
 if (deriv_access == Default) deriv_access = is_struct ? Public : Private;
 Class *new_class;
 if (! already_defined) {
   new_class = new Class(base ? base : cntxt /*&context()*/,deriv_access);
   new_class->entry(pe);
   // *add 1.2.3 Class now keeps track of whether it's declared as struct or not
   if (is_struct) new_class->make_struct();
   new_class->set_access_mode(is_struct ? Public : Private);
   if (s_or_c == UNION) new_class->set_anonymous_union();
   pe->type = Type(new_class);
   pe->size = 0;
   pe->data = 0;  // which distinguishes us from Namespaces!!
   pe->set_class();  // meaning: we are not a typedef!
   pe->m_typename = true;
   if (instantiation_context != NULL) {
     new_class->inject_namespace((Namespace *)instantiation_context);
     push_context(instantiation_context);
   }
  } else if (deriv_access != ForwardClass) {
   // *fix 1.1.2 A forward class definition must not clear out an existing class
   // redefinition or full definition.
    new_class = pe->type.as_class();
   // two cases: full defn of forward class, 
   //  and redefinition of existing class (an extension!)
   //*SJD* Absolutely need to call the base-setting code for derived classes
    new_class->set_base_class(base,deriv_access);
 }

 if (deriv_access != ForwardClass) {
      if (state.in_template != NULL)
        state.in_template->instantiated(true);

     Module::current()->add_typename(pe);
     push_context(new_class);
     state.in_class = true;
     state.class_dcl = t_void;  

  }
  return pe->type;
 } catch(string msg) { error(msg); }
 return t_void;
}

void ParserState::set_access_mode(int val)
{
 if (!is_class(&context())) error("Access mode not allowed here");
 else ((Class&)context()).set_access_mode(val);
}

void ParserState::add_friend_class(const string& name)
{
 if (!is_class(&context())) error("Friend not allowed here"); 
 else {
  PEntry pe = symbol_lookup(name);
  if (!pe->type.is_class()) error("Must be a class context");
  else ((Class&)context()).add_friend_object(pe->type.as_class(),true);
 }
}

/*REF:NAMESPACE*/

void ParserState::add_namespace(string name)
{
 Namespace *ns;
 // *fix 1.2.0 Change in grammar for 'class_name' broke anonymous namespaces.
 // *fix 1.2.3 Nasty code that was too free with string char data caused anon namespaces
 // to break in debug mode.
 bool is_anonymous = name == "";
 if (is_anonymous) name = Module::anonymous_namespace_name();
 PEntry pe = context().lookup(name);
 bool already_defined = pe != NULL;
 if(!already_defined) { 
     pe = context().add(name);
     ns = new Namespace(&context());
     pe->data = (int)ns;
	 pe->set_class();
     ns->entry(pe);
     pe->type = Type(ns);
     pe->m_typename = true;
 } else ns = (Namespace *)pe->data;
 if(is_anonymous) context().inject_namespace(ns);
 else  Module::add_namespace(ns);
 push_context(ns);
}


Signature *ParserState::get_signature(Type t, bool clear_arglist) 
{
// 'clear_arglist' now (apart from doing what it says afterwards) 
// also attaches the list of parameter names to the signature. 
 TypeList ts;
 int sz = 0;
 bool was_stdarg = false;
 ArgList::iterator ali;
 StringList sl;
 if (arg_list.back().type == t_void) { // means '...'!!
    arg_list.pop_back();
    was_stdarg = true;
 }
 for(ali = arg_list.begin(); ali != arg_list.end();  ++ali) {
    ts.push_back(ali->type);
    // *fix 1.2.2 Displayed prototypes of imported functions had extra '*' symbols;
    // they were probably put in to signify 'no name'
    if (ali->name != "*")  sl.push_back(ali->name);  
                    else   sl.push_back("");
    sz += (ts.back().is_double() ? sizeof(double) : sizeof(int));
 }
 Table *pc = &context();
 // *fix 1.1.3 Member function template being instantiated!
 if (pc->type() == INSTANTIATION_CONTEXT) pc = pc->parent_context();
 Class *cptr = is_class(pc) ? (Class *)pc : NULL;

 //HACK15  If this is a method pointer declaration, then use 
 // state.class_dcl which is set in the declaration grammar
 if (was_fun_ptr && state.class_dcl != t_void) {
   cptr = state.class_dcl.as_class();
   state.class_dcl = t_void;
 }

 Signature *sig = new Signature(t,ts,cptr); 
 sig->byte_size(sz);
 sig->stdarg(was_stdarg);
 if (member_is_const) sig->set_const();
 member_is_const = false;
 // *fix 1.1.2 Argument names are now always saved by get_signature()
 sig->set_arg_names(sl);
 if (clear_arglist) end_args();
 
 //*HACK* This can be set by array args...
 // (usually reset by add_variable)
 s_array_size = 1;
 s_twodim_array = 1;

 return sig;
}

// *fix 1.1.3 This is only called by do_function_template(), but 
// there are two cases (i) a method of a template class declared outside,
// and (ii) a genuine method template.
Signature *get_prototype(bool& outside_class)
{
 string name = state.token_stack.pop();
 Type rtype  = Parser::tpop(); //??
 dcl_reset();  
 
 Signature::set_fun_name(name);
 Signature *sig = state.get_signature(rtype,true); 
 outside_class = false;
 if (state.class_dcl != t_void) {
   sig->set_class_ptr(state.class_dcl.as_class());
   state.class_dcl = t_void;
   outside_class = true;
 }
 return sig;
}

Type ParserState::signature_type(Type rt)
{
   // *fix 1.1.0 Building up function ptr type (they are declared like any other var...)
 // function pointer declaration!!
	was_fun_ptr = true;
    Signature *sig = get_signature(rt,true);
  // *fix 0.9.4  NB that signature ptrs are unique in fun ptr declarations.
	rt = Type(unique_signature(sig));
    rt.incr_pointer();
    was_fun_ptr = false;
	return rt;
}

PExprList get_default_arguments()
{
 PExprList pel = new ExprList;
 bool gotcha = false;
 ArgList::iterator ali;
 for(ali = state.arg_list.begin(); ali != state.arg_list.end();  ++ali)
    if (ali->init) { pel->push_back(ali->init); gotcha = true; }
    else if (gotcha) error("Default arguments must be at the end");
    else pel->push_back(NULL);
 if (!gotcha) { 
   delete pel; return NULL;
 } else return pel; 
}

static bool mIsConversion = false;

FunctionEntry *
create_function_entry(Signature *sig, const string& name, PEntry pe) 
{
   if (pe==NULL) pe = state.context().add(name);
   mIsConversion = name == CONVERSION_OPNAME;
   pe->type = Type(sig);
   pe->name = name;
   pe->rmode = DIRECT;

⌨️ 快捷键说明

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