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

📄 common.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
{   
    Table *cntxt = context_stack.TOS(); 
    if (!cntxt) { // *DEBUG*
       warning("Restoring lost context...");
       cntxt = &global();
       push_context(cntxt);
    } 
    return *cntxt;  
}

void ParserState::add_to_arg_list(Type t, const string& name, Expression init)
{
 arg_list.push_back(ArgEntry(t,name,init));
}

static ArgList tmp_arg_list;

void ParserState::begin_args()
{
 tmp_arg_list = arg_list;
 arg_list.clear();
}

void ParserState::end_args()
{
 arg_list = tmp_arg_list;
}

void clear_parse_flags()
{
 force_comma_flag(); // *hack 0.9.6 the dcl stack is getting out of order...
 state.token_stack.clear();
}

void restore_global_context()
{
 if (is_local(&state.context())) state.pop_context();
}

bool mFakeInitBlock = false;

// *add 1.2.7 Method bodies are cached for later compilation

bool ParserState::handle_method_body(Class* pc, bool plain_method)
{
  // With imported methods, the idea is to ignore the inline code and link to the exported fn.  
    if (Builtin::get_dll_handle() != NULL) {
  // *fix 1.2.0L GCC under Linux doesn't export these guys, so compile them as usual!
// *ch 1.2.9 patch
#ifndef _WIN32
      return false;
#else
     // (ignore case of methods outside class defn...)
     if (pc != NULL) pop_context();
     // but force a dynamic link to those w/in the class body
     else  declare_function(tpop(),token_stack.pop(),NULL);  
     //  and ignore the method body
     Template::grab_function_body(plain_method,NULL); 
     // *fix 1.2.8 see 'hack of the week' in the next block - we gotta fool the parser!
     if (! plain_method) {
         Input::insert_string("__init_block__ {}");
         mFakeInitBlock = true;
     }
#endif
  } else {
    // Only method bodies _inside_ class definitions are cached. Or caching can be switched off...
     if (! debug.skip_method_bodies || pc != NULL) return false;  
    // otherwise, we want to cache these bodies for later compilation when the class is finalized;
    // make sure they're declared      
     TemplateInstance* ti = in_template;
     in_template = NULL;
     Function* pf = declare_function(tpop(),token_stack.pop(),NULL);            
     in_template = ti;
     char* body_buff = Template::generate_function_header(pf,plain_method,false);
     Template::grab_function_body(plain_method,body_buff);
     pf->class_context()->add_defered_method_body(pf,body_buff);
     // *hack 1.2.7 hack of the week: we have grabbed the init list, but need to push
     // something into the input stream which the parser recognizes as 'class_init_list block'
     if (! plain_method) {
         Input::insert_string("__init_block__ {}");
         mFakeInitBlock = true;
     } else {
         block_stack.push(0);
         Input::insert_string("}");
     }   
  }
  dcl_reset();                                // and ensure that the state is properly reset!
  while (tstack_depth() > 2) tpop();                
  clear_parse_flags();
  return true;    
}

/// Managing blocks!
// also used to start function definitions....
void ParserState::init_block(int type)
{
// parser can ask us to ignore the next init_block(); used w/
// constructor initialization lists to prematurely start the function
// definition.  That is, we break the usual function init_block up into
// two separate operations: constructing the function and its block,
// and then initializing it!
 if (in_method) {
   in_method = false; 
   // if we're inside a class body, then skip this initialization
   if (debug.skip_method_bodies && (class_dcl != t_void || mFakeInitBlock)) {
       block_stack.push(0);
       mFakeInitBlock = false;
       return;
   }
   if (!is_local(&context())) { 
       error("Context not local!");
       return;
   }
   FunctionContext& fc = static_cast<FunctionContext&>(context());
   FBlock *fb = fc.fun_block();
   int nargs = fb->nargs;  // *hack 0.9.8 was being reset to zero...MUST OVERHAUL!
   fc.initialize();
   fb->nargs = nargs;
   return;
 }

 bool is_continueable = in_loop, is_breakable = in_loop;
 int flags = 0;
 if (in_declaration) { // _only_ if this is a function block!
   Table *cntxt = &context();
   PClass pc = NULL;
   // *fix 1.1.3 If this was a template method, then don't muck up the IC!
   // Careful to exclude the case of instantiating methods of a template class.
   bool template_instantiating =
       cntxt->type() == INSTANTIATION_CONTEXT  
    && ! in_template->get_template()->get_entry()->is_method();
   flags = CONTEXT_PUSHED;
   if (class_dcl != t_void) { // nested Class:: notation...
     if (!class_dcl.is_class()) { error("Not a class name"); return; }
     pc = class_dcl.as_class();
     // class context may _already_ be pushed in the case of constructor
     // initialization lists - but we flag it as a method anyhow.
     if (cntxt != pc  /*&& ! template_instantiating*/) { 
         push_context(pc);
         cntxt = pc;
     }
     if (! template_instantiating) flags |= IN_METHOD;  
   }

   // *add 1.1.0 Expressly forbid nested functions! Otherwise we get nasty brace mismatch issues...
   if (is_local(cntxt)) {
       error("Cannot have functions within functions"); return;
   }
   string name = token_stack.TOS();

   // *add 1.1.0 Skip the bodies of any inline imported methods, except for ctors w/ init lists
   if (is_class(cntxt)) {
       if (handle_method_body(pc,type != CONSTRUCTOR_BLOCK)) return;
   }
   start_function(tpop(),token_stack.pop(), type != CONSTRUCTOR_BLOCK);

   dcl_reset();

   // *change 1.2.3 The return label is now backed by a stack
   m_ret_label = new Label(&code());
   m_ret_label_stack.push(m_ret_label);
   flags |= FUN_BLOCK;
 } else
 if (in_switch) {
   flags = IN_SWITCH;    
   is_breakable = true;
 } else
 if (in_class) {
   flags = CONTEXT_PUSHED;
   in_class = false;
 } else
 if (type==LOOP_BLOCK) {
   flags = LOOP_SCOPE;
 }

 if (is_breakable) {
   flags |= BREAKABLE;
   break_stack.push(label_stack.TOS());
   if (in_switch) { // *fix 0.9.4 switch left label stack pushed - mucked w/ while!
      label_stack.pop();
      in_switch = false;
   }
 }
 if (is_continueable) {
   flags |= CONTINUEABLE;
   continue_stack.push(new Label(&code()));  
   in_loop = false;
 }
 block_stack.push(flags); 
 clear_parse_flags();
}

bool ParserState::context_generated()
{
  return block_stack.depth() == 0 || block_stack.TOS() & CONTEXT_PUSHED;
}

void ParserState::check_context(int mode)
{
// if a fresh context has been pushed, cool...
 if (context_generated()) return; 
 Function *function = current_function();
 // function==NULL is a C++ error, but is allowed in interactive mode
 push_context(new LocalContext(&context(),function));
 block_stack.TOS() |= CONTEXT_PUSHED;
}

bool ParserState::in_loop_dcl()
{
  return block_stack.TOS() & LOOP_SCOPE;
}

void end_switch();

void ParserState::finalize_block()
{
 if (block_stack.depth() < 1) 
	 block_stack.push(CONTEXT_PUSHED);

  int flags = block_stack.pop();
  if (flags & IN_SWITCH) end_switch();
  if (flags & CONTINUEABLE) {
      m_continue = continue_stack.pop();
      m_continue->here();     
  } else m_continue = NULL;

  if (flags & BREAKABLE) break_stack.pop();
  if (flags & FUN_BLOCK) { // *fix 0.9.5 UCW can fall over if braces are mismatched..
     if (m_ret_label_stack.empty()) error("misplaced braces");
     else m_ret_label->here(); 

  // *hack 1.1.0 It's difficult to skip the body of a imported ctor w/ init list,
  // so ensure that declare_function() is called to import this function!
    if (Builtin::get_dll_handle() && is_class(&context())) {
       string name;
       if (!Builtin::add_dll_function(current_function(),0,name))
          cerr << "cannot link to ctor " + quotes(name) << endl;
//	   fn->builtin(Function::CDECL); //?
	}
  }
  if (flags & CONTEXT_PUSHED) {
    context().finalize();
    pop_context();
    class_dcl = t_void;
  }   

  // If we were in a method body, then the class context must be dropped
  if (flags & IN_METHOD) pop_context();
  // can now dispose of the continue/return label
  if (flags & CONTINUEABLE) delete m_continue;
  if (flags & FUN_BLOCK) {
      delete m_ret_label;
      m_ret_label = NULL;
      m_ret_label_stack.pop();

  } 
  state.in_construct_destruct = IsPlain; //*fix 1.2.4
}

Label *ParserState::return_label()
{ 
  return m_ret_label;
}

//---------------doing control statements---------------

// *fix 1.2.7 In 'A::B<C>', C was looked up in A's context.
// The fix involves detecting whether we're in a scoped context,
// and popping and pushing the context.
void ParserState::begin_templ_list()
{
 if (scope_context != NULL) pop_context();
}

void ParserState::end_templ_list()
{
 if (scope_context != NULL) push_context(scope_context);
}


void push_label_stack()
{  state.label_stack.push(new Label(&code())); }

void label_jump(int jtype, bool do_push)
{
 if (do_push) push_label_stack();
 code().jump(jtype,state.label_stack.TOS());
 if (!do_push) { delete state.label_stack.pop(); }
}

void label_here()
{
 push_label_stack();
 state.label_stack.TOS()->here();
}

void compile_condition(PExpr cond)
{
  code().compile(Expressions::cast_to_bool_op(cond));
}

bool do_loop_start(PExpr cond, bool jump_back)
{
 // skip the controlled statement if not true!
 // *fix 0.9.4 Push a non-zero value to ensure for(;;) keeps going..
 if (!cond) cond = Expressions::sizeof_op(1);
 compile_condition(cond);
 // Quite NB to dispose of any temporaries before we continue...
 check_temp_context();
 /*if (jump_back)*/ label_jump(JZ,true);
 return true;
}

bool do_loop_end(bool is_jump, bool is_forward)
{
 Label *l1 = state.label_stack.pop(); 
 // now either jump forward (if-else) or back (while-do-for)
 if (is_jump) label_jump(JMP, is_forward);   
 l1->here(); // the forward jump!
 return true;
}

bool do_for_end(PExpr e)
{ 
 if (e) code().compile(e,DROP_VALUE);
 do_loop_end(true);
 return true;
}

// *fix 1.2.3 break inside a do-while loop was broken!
bool do_do_end(PExpr cond)
{
// this will be the break label
 Label *l1 = state.label_stack.pop(); 
 compile_condition(cond);
 check_temp_context();
 // if condition fails, we jump back to the top label;
 code().jump(JNZ,state.label_stack.pop());
 // break will jump to here
 l1->here();
 return true;
} 

void check_enclosing_scopes(LocalContext *outer)
// Given a local context, look at the enclosing scopes until we hit
// some outer context (usually the outermost function context). If the
// outer context has auto objects, then do nothing, since the jump will
// go to a proper unwind.  Otherwise, find the first enclosing scope
// that does have auto objects.
// note: must only be called from within a local function context
{
 LocalContext *cntxts[BLOCK_DEPTH];
 LocalContext *lc = (LocalContext *)&state.context();
 int ic = 0;
 while ((cntxts[ic++] = lc) != outer)  
   lc = (LocalContext *)lc->parent_context(); 
 while (--ic >= 0) 
   if (cntxts[ic] != outer && cntxts[ic]->first_obj() != NULL) {
		 cntxts[ic]->check_objects();
		 return;
   }
}

bool do_return(PExpr e)
{
  Label *ret_label = state.return_label();
  if (!ret_label) { error("return only in function"); return false; }
  Function *fn = ((LocalContext&)state.context()).function(); 
  Type rt = fn->return_type();
//  if (fn->name()=="bh_begin")
//     ret_label = 0;     
   // *add 1.1.1 support for __declare; uses first return type!
  if (rt == t_null) { // t_undefined
	  rt = e->type();
	  rt.strip_const();
	  fn->adjust_return_type(rt);
  } 
  // *change 1.1.0 Void functions can return void 'values' (ISO standard behaviour)
  if (rt == t_void && e != NULL && e->type() != t_void) { 
      error("void function cannot return value");
      return false;
  }
  if (e) {
      PExpr ret_exp = Expressions::return_op(fn,rt,e); 
      if (ret_exp->is_nil()) { 
          error("Could not copy return object");
          return false;
      }  
      code().compile(ret_exp);
  }
  // *fix 1.1.0 Must ensure that a proper UNWIND operation occurs for any locals
  check_enclosing_scopes(fn->context());
  code().jump(JMP,ret_label);
  return true;
}

⌨️ 快捷键说明

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