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

📄 common.cpp.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
 PEntry pe;
 bool is_class_context;
 Table* alloc_context;
 static int offset=0, bit_offs=0, field_size;
 if (name=="") return NULL;
 if (name=="obuff") //*DEBUG*
     name = "obuff";
 try {
  PopAtEnd restore_cntxt;
  int size;
// *add 1.2.3 Support for 'static' applied within file scope
// The trick here is to explicitly load this module's anonymous namespace
  bool is_static = mode == ENUM_INIT; 
  if (mode == Static) {
      is_static = true;
      if (is_global(&context())) {
          add_namespace("");
          restore_cntxt.set();
      }
  }
  if (name=="*") name = make_temp_name(); // assign a temporary name...
  if (t == t_null  && ! in_typedef) { // *add 1.1.1 support for __declare    
    if (init == NULL) fail("must initialize a __declare variable");
    t = init->type();
	t.strip_const();   // i.e. we want the base type
	t.make_zero_int(); // *fix 1.1.2 the zero bit must go!
	if (t.is_function()) t.incr_pointer(); // *fix 1.2.0 (Eric) otherwise we crash	
  }
  // _cannot_ use a namespace name as if it were a plain type!
  if (t.is_namespace()) fail("Namespace not allowed here");

  // is our context ready?
  check_context(mode);
  PClass pc = t.is_class() ? t.as_class() : NULL;

  //issue here is that pc->make_available() _usually_ fails because a template class
  //instantiation failed, setting the error(). We need a way around this...
  if (pc != NULL && /*! in_typedef &&*/ ! pc->make_available()) return NULL; //fail("Class not fully defined");

  // *fix 1.1.2 Watch out for bad array init here, except for char arrays
  // *fix 1.2.0 Deduce the size of the array in declarations like 'char p[] = "hello"'
  if (t.is_pointer() && s_array_size != 1) { // a fiddle: means we have an array!     
     bool is_elist = init && init->is_expr_list();     
     if (init && ! is_elist) {
		 if (! t.is_char() || init->type() != t_char_ptr || ! init->is_entry())
		   error("bad array initializer");
		 else if (s_array_size==0) {
		   s_array_size = strlen((char *)init->entry()->global_ptr())+1;
		 }		 
	 } else 
     if (s_array_size == 0) { // hm, may be asking us to guess the array size!
       if (init && is_elist) s_array_size = init->expr_list()->size();       
       else fail("arrays of size zero not allowed"); // *add 1.2.9
     } 
  }
  size = s_array_size*s_twodim_array;  // will be > 1 for arrays!

  // Has this variable already been added?
  pe = context().lookup(name);
  bool already_declared = pe != NULL;
  if (already_declared) { 
     if (context().is_local_entry(pe)) {
      // *fix 0.9.4 Redefinition is not an error if 'extern'; we reuse an entry unless it will be larger
      // *fix 1.2.2 or will be differently initialized...   
       // *fix 1.2.3b If we've already allocated in an extern declaration, then now initialize...
       if (pe->m_access == NotInitialized) {
          pe->rmode = DIRECT;
          is_class_context = false;
          goto rest_of_init;
       }
       if (! in_extern()) error_already_defined(name); 
       else return pe;  // *fix 1.2.3b Don't redeclare extern variables....
       if (pe->type == t && pe->size >= size && !t.is_class() && !init) {
          reset_array_size();
          return pe;
       }
     }
    //*SJD* This is very irritating  - I think it should be optional
    //if (pe->type == t) warning(quotes(name) + ": hidden variable");
  }

  pe = context().add(name);  
  // put any non-tempory variables in the init list
  if (name[0] != '$') dcl_init_list.push_back(pe);
  pe->type = t;
  pe->size = size;

  // extract the base type, if we have an array (1- or 2-D only)
  // *fix 1.2.8 We weren't doing the 2D case properly; double [3][3] had the wrong size!
  if (t.is_pointer() && s_array_size != 1) {
      if (s_array_size < 0)
          error("array size cannot be negative");
      t.decr_pointer(); 
      if (s_twodim_array > 1)
        t.decr_pointer();
  }
  // use the reference size, not the size of what it's refering to!
  if (t.is_reference()) size = sizeof(void *)*pe->size;
                   else size = t.size()*pe->size;
  pe->rmode = is_static ? DIRECT : context().refmode();
  is_static = pe->rmode == DIRECT;  // *fix 1.0.0
  pe->m_typename = false;

  
  //*HACK* 2D arrays are _formally_ allowed in class defs...
  if(pe->rmode == OREL) s_twodim_array = 1;

  alloc_context = NULL;
  if (in_typedef) {
    pe->data = 0;
    pe->m_typename = true;
	if (Module::current()) Module::current()->add_typename(pe);
    return pe;  //*NOTE* not perfect! will mess w/ array_size!
  } else
  if (mode != ARG) { // i.e. default!
    if(s_twodim_array > 1) { // two-dimensional array
       if(pe->rmode != DIRECT) error("can only define static two-dim arrays");
       // leave room for the pointer table...
      size += sizeof(void *)*s_array_size;
    }
    alloc_context = is_static ? &global() : &context(); 
    is_class_context = alloc_context ? is_class(alloc_context) : false;

    // *add 1.1.4 Bit fields are now allowed in structures
    // *fix 1.2.0 Now allocated to ensure 4-byte alignment for the next field, to be consistent with GCC
    // *fix 1.2.3 Bit fields will now fit properly in structures one word in size
    if (init && init->is_const()) {
        if(pe->rmode != OREL || ! pe->type.is_int()) 
            fail("Bit fields must be integer and are only allowed in structs");
        int bit_size = const_int_expr(init->entry());
        if (bit_offs == 0) {
            size = 4 - alloc_context->size() % 4; // room available upto next 4-byte boundary
            offset = alloc_context->alloc(size,NULL);
            field_size = 8*size; // bits left in this field
        } 
        pe->set_bit_field(offset,bit_offs,bit_size);
        bit_offs += bit_size;
        if (bit_offs > field_size) bit_offs = 0;  // have we gone over a boundary?
        init = NULL;
    } else {
   // *add 1.2.0 Support for 8-byte alignment of doubles in structures
       if (is_class_context && debug.class_dword_align == 8 && t == t_double)
         pe->data = alloc_context->alloc_qword();
       else 
         pe->data = alloc_context->alloc(size,NULL);
	   bit_offs = 0;
    }
	// *change 1.1 Stack now grows downwards, so locals have -ve offset.
    // *fix 1.2.2  Important to round up size to nearest dword bounary!
    if (is_local(alloc_context)) pe->data = -pe->data - Allocator::dword_align(size)/sizeof(int);
    if(s_twodim_array > 1) { // two-dimensional array
      void **ptr = (void **)pe->global_ptr();
      void **ptable_begin = ptr + s_array_size;
      // row length in dwords
      int row_size = t.size()*s_twodim_array/sizeof(void**);
      for(int i = 0; i < s_array_size; i++)
        ptr[i] = ptable_begin + row_size*i;
    } else
    if (t.is_class()) {
     if(t.is_object() && pc->get_VMT() != NULL) {    // i.e first dword is for the VMT entry
       (pe->data) += (pe->is_stack_relative() ? 1 : sizeof(int));
     }
    }
  } else 
  if (is_local(&context())) {
    PFBlock fb = ((FunctionContext&)context()).fun_block();
    pe->data = fb->nargs;
    fb->nargs += Table::dword_align(size)/sizeof(int); // ie. in dwords
	return pe;
  } else fail("how is ARG possible here?");
  pe->context = &context();

  // *fix 1.2.3b Don't initialize variables in extern declarations
  if (in_extern()) {
      pe->m_access = NotInitialized;
      return pe;
  }
rest_of_init:

  // no default initialization for class members!
  if (init || !is_class_context) {
   // even if no init, we pass objects through this in case they
   // _may_ need default construction. Don't try to construct in typedefs! 
   if (init || (t.is_object() && mode != DEFER_TEMP/* && !in_typedef*/)) { 
    if (init && (!alloc_context || (is_class_context && mode != ENUM_INIT)))
      fail("initialization not allowed here");
   //*SJD* The context flag needs some work....
      if (mode != ENUM_INIT || !init->is_entry() || !init->type().is_const()) {
        PExpr e = Expressions::initialize_op(pe,init,NULL,mode==TEMP ? 1 : 0);
        if (e != NULL && ! e->is_nil())
			   (is_static ? static_code() : code())
			             .compile(e,in_loop_dcl() ? 0 : DROP_VALUE);       
      } else if (init->is_entry()) {
        pe->data = init->entry()->data;      
      } else fail("bad init");
    }
    else if (t.is_reference() && (mode != ARG && !in_typedef))
       fail("uninitialized reference");
   }
  } catch(string msg) { error(msg); }
  reset_array_size();
  return pe;
}

// This is called after every declaration; used to detect anonymous unions
void ParserState::check_dcl_init(Type t)
{ 
    if (dcl_init_list.size() > 0) { 
        dcl_init_list.clear();
        return;  // there were declarations
    }

    if (! t.is_class()) return;   // only interested in empty class declarations...
    PClass pc = t.as_class();
    if (pc->is_anonymous_union()) { // which are anonymous unions
    // iterate over all non-static members of the union
    // and insert them into the enclosing context.
    // First add a temp variable of the union type to allocate some space...
        PEntry union_entry = add_variable(t,"*");
        Table* cntxt = &context();
        EntryList el;
        EntryList::iterator eli;
        pc->list_entries(el,NON_STATIC | FIELDS);
        for(eli = el.begin(); eli != el.end(); ++eli) {
           PEntry entry = *eli;
           string name = entry->name;
           PEntry new_pe = cntxt->new_entry(name); 
           new_pe->type = entry->type;
           new_pe->size = entry->size;
           new_pe->data = union_entry->data;
           new_pe->rmode = is_class(cntxt) ? OREL : DIRECT;  
           cntxt->add_entry(name,new_pe);           
        }       
    }
}

int array_size(PEntry pe)
{
 return pe->size;
}

int size_of_entry(PEntry pe)
{
 Type t = pe->type;
 // for arrays, use the size of the base type...
 if (array_size(pe) > 1 && t.is_pointer()) { 
      t.decr_pointer(); 
      return array_size(pe)*t.size();
 } else return t.size();
}

int const_int_expr(PEntry pe)
{
// *fix 1.2.1 (Eric) Named enums are also valid integer constants!
// *fix 1.2.1 (Eric) Constants may be short
// *fix 1.2.1 Watch out for unsigned shorts...
  void *ptr = pe->global_ptr();
  Type t = pe->type;
  if (t.is_enum()) return *(int *)ptr;
  if (!t.is_const() || !t.is_int())
     fail("const expr expected, not: " + pe->name);
  if (t.is_short()) {
      if (t.is_unsigned()) return *(unsigned short *)ptr;
      else return *(short *)ptr;
  }
  if (t.is_int())
      return *(int *)ptr;
  else return 0;
}

int const_int_expr(Expression e)
{ 
// *add 1.1.4 Some limited ability to fold compile-time constants
// *add 1.2.5 Added relational ops for #if expressions
 if (! e->is_entry()) {
     if (e->is_function()) fail("Constant expressions cannot contain functions");
	 int op = e->op();
	 int v1 = e->arg1() ? const_int_expr(e->arg1()) : 0;
	 int v2 = e->arg2() ? const_int_expr(e->arg2()) : 0;
	 switch (op) {
	 case LSHIFT: return  v1 << v2;
     case RSHIFT: return  v1 >> v2;
	 case STAR:   return  v1 * v2;
	 case PLUS:   return  v1 + v2;
     case MINUS:  return  v1 - v2;
	 case DIVIDE: return  v1 / v2;
     case BIN_OR: return  v1 | v2;
     case ADDR:   return  v1 & v2;
     case BIN_NOT: return ~v1;
     case LOG_OR:  return v1 || v2;
     case LOG_AND: return v1 && v2;
     case EQUAL:   return v1 == v2;
     case NOT_EQUAL: return v1 != v2;
     case LESS_THAN: return v1 < v2;
     case LEQ:       return v1 <= v2;
     case GREATER:   return v1 > v2;
     case GEQ:       return v1 >= v2;
	 default: fail("Must be a simple constant integer expression");	 
     }  
 }
 // plain entry case...
 return const_int_expr(Expressions::ExprToEntry(e));
}

void *create_const_entry(Type t, PEntry& rpe)
{ 
  PEntry pe = new Entry;
  pe->rmode = DIRECT;
  t.make_const();
  pe->type = t;
  pe->size = 1;  // by default; for arrays it's > 1!!
  pe->m_typename = false;
  pe->data = global().alloc(t.size(),NULL);
  rpe = pe;
  return pe->global_ptr();
}

//////////////////////// Enumerations /////////////////////////////////
// *fix 1.1.4
// * Enums can now be parts of declarations, and I've now made
// it possible for the optional initialization to be an earlier enum constant,
// so that 'enum {ONE,TWO=ONE+1}' will now work.
// * C mode works like w/ structs!

static int gVal;
static Enum* gEnum;

Type ParserState::do_enum(string name)
{
try {
  Enum *enum_obj;
  Type t_const_int = t_int;   t_const_int.make_const();
  Type et = t_const_int;
  gVal = 0;
  // True nameless enums are like 'enum {...}' and just introduce a set of constants.
  // If however we get 'typedef enum {...} tag' then it is _not_ nameless
  // and we need a distinct name, rather like the equivalent w/ struct.
  bool nameless = name=="" && ! in_typedef;
  if (nameless) name="?enum";                 // entry name of nameless enum
  else if (name=="") name = make_temp_name(); // assign a temporary name... 
  else if (debug.c_mode) name = "$_" + name; 
  //PEntry pe = symbol_lookup(name);
  // *fix 1.2.7 _only_ look in local context; 
  // a previously defined enum wd collide w/ a definition w/in a class
  PEntry pe = context().lookup(name,false);
  // *hack 1.1.4 this test in C mode interferes w/ old-fashioned 'enum Name var'
  if (! debug.c_mode && pe && !nameless) fail("already defined"); 
  if (! pe) {
     pe = context().add(name);
     pe->rmode = DIRECT;
     pe->m_typename = true;
     enum_obj = new Enum(name);
	 enum_obj->entry(pe);          // *add 1.2.7 Enum now carries entry...
     pe->data = global().alloc(sizeof(Enum),enum_obj);
     if (!nameless) { 
         et = Type(enum_obj); 
         Module::current()->add_typename(pe);  // will need to clean these entries out...
     }
     pe->type = et;
  } else 
 // *fix 1.2.7 The enum object is via a _direct_ reference!
      enum_obj = (Enum *)global().addr(pe->data); 
   gEnum = enum_obj;

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


void ParserState::add_enum(Type et, string name, PExpr init)  
{
  // Add a constant to the current enumeration!
  // *fix 1.2.1 (Eric) Simplified, and no longer mistreats shorts...
  bool was_in_typedef = in_typedef;  
  PEntry pe_entry,entry;
  in_typedef = false;
  try {
   if (init) 
      gVal = const_int_expr(init);
   *(int *)create_const_entry(t_int, pe_entry) = gVal++;
   entry = add_variable(et,name,Expressions::entry_op(pe_entry),ENUM_INIT);  
   gEnum->add_entry(entry);
  } catch(string msg) 
  { error(msg); }   
  in_typedef = was_in_typedef;
}

/////////////////////////////// Exception handling....//////////////////////////////
void do_start_try_block()
{
 Function *curr_fn = current_function();
 if (curr_fn == NULL){ error("try..catch only allowed in functions"); return; }

 CatchHandler *pch = new CatchHandler(curr_fn

⌨️ 快捷键说明

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