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

📄 directcall.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

#endif

const int CDECL = Function::CDECL;

namespace Builtin {

void add(const Sig& sig,char *name, CALLFN fn, bool is_stdarg = false, int ftype=CDECL);

// this is used to find out how big allocated object arrays were....
int alloc_size(void *p)
{
 PointerMap::iterator pmi = mPtrMap.find(p);
 if (pmi != mPtrMap.end()) return pmi->second;
 // issue here is that when we're checking ALL alloc ptrs get an entry in this map!
 if (Parser::debug.ptr_check) return 0;
 else return 1;
}

// *add 0.9.4 Pointer sanity check if #opt p+
void bad_ptr_check(void *data)
{
  if (data == NULL)
      throw BadPointer("NULL pointer");
  // other checks (dangling, invalid, etc) go here....
}

typedef int (*TWOFN)(int,int);

int _wrap(char *name)
{
 Function *pf = Function::lookup(name);
 if (pf == NULL) return 0;
 TWOFN pfn = (TWOFN)generate_native_stub(pf);
 return (*pfn)(10,20);
}

// *add 1.0.0 These exported functions support the fast specialization map<string,int>
// You can of course use any other associative container for this implementation.

typedef std::map<string,int> MSI;
typedef MSI *PMSI;
typedef MSI::iterator IMSI;
typedef IMSI *PIMSI;

struct StrPair {
     string first;
     int second;
};
typedef StrPair* PSP;

void* _map_create()
{ return new MSI;    }

void  _map_destroy(void *pm)
{ delete PMSI(pm);}

int   _map_size(void *pm)
{ return PMSI(pm)->size(); }

int*  _map_find(const string& key,void *pm) {
   MSI::iterator msi = PMSI(pm)->find(key);
   return msi != PMSI(pm)->end() ? &msi->second : 0;
}

int*  _map_insert(const string& key,int val,void *pm) {  
  int& res = (*PMSI(pm))[key] = val;
  return &res;
}

// *ad 1.2.9 corresponding iterator stuff
void* _map_iter_ep(void* pm, int which)
{
    MSI::iterator it;
    if (which==0) it = PMSI(pm)->begin();
            else  it = PMSI(pm)->end();
    return new IMSI(it);
}

void* _map_iter_find(void* pm, const string& key)
{
    MSI::iterator it = PMSI(pm)->find(key);
    return new IMSI(it);
}

int  _map_iter_equal(void* i1, void* i2)
{
  return *PIMSI(i1) == *PIMSI(i2);
}

void _map_iter_fetch(void* pi, void* dat)
{
  PSP(dat)->first =  (*PIMSI(pi))->first;
  PSP(dat)->second = (*PIMSI(pi))->second;
}

void _map_iter_next(void* pi, int wdir)
{
  ++(*PIMSI(pi));
}

void* _native_stub(FBlock *pfb)
{
//*fix 1.2.3a The function may well be NULL...
   if (pfb == NULL) return NULL;
   if (pfb->function->builtin()) return pfb->native_addr();
   else return generate_native_stub(pfb->function);
}

// *add 1.2.5 range checking: _range_check
int _range_check(int sz, int i)
{
    if (i >= sz || i < 0) {
        char buff[80];
        if (i >= sz) sprintf(buff,"Range Error: %d >= %d",i,sz);
               else  sprintf(buff,"Range Error: %d < 0",i);
#ifdef WIN32	
        throw RangeError(buff);
#else   
        throw_range_error(buff);
#endif
    }
    return i;
}

static int mRangeCheck;

void init()
{
 Type t_ccp = t_char_ptr;
 Type t_int_ptr = t_int;
 t_ccp.make_const();
 t_int_ptr.incr_pointer();
 Signature *sig = new Signature(t_int);
 sig->push_back(t_int);
 sig->push_back(t_int);
 Type st(sig);
 st.incr_pointer();

 add(Sig(t_void_ptr) << t_void_ptr,"_native_stub",(CALLFN)_native_stub);
 add(Sig(t_void_ptr) << t_int,          "_new",(CALLFN)&_new);
 add(Sig(t_void_ptr) << t_int << t_int, "_new_vect",(CALLFN)&_new_vect);
 add(Sig(t_void) << t_void_ptr << t_int,"_delete",(CALLFN)&_delete);
 add(Sig(t_void_ptr) << t_int,          "_new_ex",(CALLFN)&_new_ex);
 add(Sig(t_void_ptr) << t_int << t_int, "_new_vect_ex",(CALLFN)&_new_vect_ex);
 add(Sig(t_void) << t_void_ptr << t_int,"_delete_ex",(CALLFN)&_delete_ex);

 add(Sig(t_double) << t_double,"sin",(CALLFN)&sin);
 add(Sig(t_double) << t_double,"cos",(CALLFN)&cos);
 add(Sig(t_double) << t_double,"tan",(CALLFN)&tan);
 add(Sig(t_double) << t_double << t_double,"atan2",(CALLFN)&atan2);
 add(Sig(t_double) << t_double << t_double,"pow",(CALLFN)&pow);
 add(Sig(t_double) << t_double,"exp",(CALLFN)&exp);
 add(Sig(t_double) << t_double,"log",(CALLFN)&log);
 add(Sig(t_double) << t_double,"sqrt",(CALLFN)&sqrt);
 add(Sig(t_double) << t_ccp,"atof",(CALLFN)&atof);
 add(Sig(t_long) << t_ccp,"atoi",(CALLFN)&atoi);
 add(Sig(t_char_ptr) << t_int << t_char_ptr << t_int, "itoa", (CALLFN)&itoa);
 add(Sig(t_long),"rand",(CALLFN)&rand);

 add(Sig(t_char_ptr) << t_char_ptr << t_ccp,"strcpy",(CALLFN)&strcpy);
 add(Sig(t_char_ptr) << t_char_ptr << t_ccp << t_int,"strncpy",(CALLFN)&strncpy);
 add(Sig(t_char_ptr) << t_char_ptr << t_ccp,"strcat",(CALLFN)&strcat);
 add(Sig(t_int) << t_ccp << t_ccp,"strcmp",(CALLFN)&strcmp);
 add(Sig(t_char_ptr) << t_ccp,"strdup",(CALLFN)&strdup);
 add(Sig(t_char_ptr) << t_char_ptr << t_ccp,"strtok",(CALLFN)&strtok);
 add(Sig(t_char_ptr) << t_char_ptr << t_char_ptr,"strstr",(CALLFN)&strstr);
 add(Sig(t_char_ptr) << t_char_ptr << t_int,"strchr",(CALLFN)&strchr);
 add(Sig(t_char_ptr) << t_char_ptr << t_int,"strrchr",(CALLFN)&strrchr);
 add(Sig(t_int) << t_ccp,"strlen",(CALLFN)&strlen);
 add(Sig(t_void_ptr) << t_void_ptr << t_void_ptr << t_int,
      "memmove",(CALLFN)&memmove);

 add(Sig(t_void_ptr) << t_void_ptr << t_int, "_str_cpy", (CALLFN)&str_cpy);
 add(Sig(t_int) << t_int, "_str_eof", (CALLFN)&str_eof);

 // stdio builtins (first entry used to get stdin, etc)
 add(Sig(t_void_ptr) << t_int,"_get_std_stream",(CALLFN)&_get_std_stream);
 add(Sig(t_int) << t_ccp,"puts",(CALLFN)&puts);
 add(Sig(t_int) << t_ccp,"printf",(CALLFN)&printf,true);
 add(Sig(t_int) << t_ccp << t_ccp,"sprintf",(CALLFN)&sprintf,true);
 // *change 1.2.3 GCC has finally persuaded me not to export puts().
 // add(Sig(t_char_ptr) << t_char_ptr,"gets",(CALLFN)&gets);
 add(Sig(t_char_ptr) << t_char_ptr << t_int << t_void_ptr,"fgets",(CALLFN)&fgets);
 add(Sig(t_int) << t_void_ptr << t_ccp,"fprintf",(CALLFN)&fprintf,true);
 add(Sig(t_int) << t_void_ptr << t_ccp,"fscanf",(CALLFN)&fscanf,true);
 add(Sig(t_int) << t_int << t_void_ptr, "ungetc",(CALLFN)&ungetc,true);

 add(Sig(t_int) << t_void_ptr << t_ccp,"wcon_fscanf",(CALLFN)&wcon_fscanf,true);

 add(Sig(t_int) << t_void_ptr << t_int << t_int << t_void_ptr,"fread",(CALLFN)&fread);
 add(Sig(t_int) << t_void_ptr << t_int << t_int << t_void_ptr,"fwrite",(CALLFN)&fwrite);
 add(Sig(t_int) << t_void_ptr,"feof",(CALLFN)&feof);
 add(Sig(t_void_ptr) << t_char_ptr << t_char_ptr,"fopen",(CALLFN)&fopen);
 add(Sig(t_int) << t_void_ptr, "fclose",(CALLFN)&fclose);
 add(Sig(t_int) << t_void_ptr, "fflush",(CALLFN)&fflush);
 add(Sig(t_int) << t_char_ptr << t_char_ptr, "rename", (CALLFN)&rename);
 add(Sig(t_int) << t_void_ptr, "fgetc", (CALLFN)&fgetc);
 add(Sig(t_int) << t_int << t_void_ptr, "fputc", (CALLFN)&fputc);
 add(Sig(t_int) << t_void_ptr << t_long << t_int, "fseek", (CALLFN)&fseek);
 add(Sig(t_long) << t_void_ptr, "ftell", (CALLFN)&ftell);

 add(Sig(t_void) << t_ccp,"uc_cmd",(CALLFN)&uc_hash_cmd);
 add(Sig(t_void) << t_ccp << t_char_ptr << t_int,"uc_macro_subst",(CALLFN)&uc_macro_subst);
 add(Sig(t_int) << t_void_ptr, "_dissem",(CALLFN)&_dissem);
 //add(Sig(t_void), "_init_lib",(CALLFN)&Parser::init_lib);
 // *add 1.2.5 range checking: _range_check
 add(Sig(t_int) << t_int << t_int,"_range_check",(CALLFN)&_range_check);

 // *add 1.2.4 uc_exec(), uc_result()
 add(Sig(t_int) << t_ccp,"uc_exec",(CALLFN)&_uc_exec_1);
 add(Sig(t_int) << t_ccp << t_void_ptr << t_ccp << t_int,"uc_exec",(CALLFN)&_uc_exec);
 add(Sig(t_void) << t_int << t_char_ptr << t_int << t_char_ptr << t_void_ptr,"uc_result_pos",(CALLFN)&_uc_result);
 add(Sig(t_void_ptr) << t_char_ptr,"copy_body",(CALLFN)&_copy_body);

 // *add 1.2.6 uc_include_path() will find a system file using the UC include paths.
 add(Sig(t_int) << t_ccp << t_char_ptr << t_int,"uc_include_path",(CALLFN)&_uc_include_path);

// These support the specialization map<string,int> (see <map> in the pocket library)
 add(Sig(t_void_ptr),                                     "_map_create",  (CALLFN)&_map_create);
 add(Sig(t_void)    << t_void_ptr,                        "_map_destroy", (CALLFN)&_map_destroy);
 add(Sig(t_int)     << t_void_ptr,                        "_map_size",    (CALLFN)&_map_size);
 add(Sig(t_int_ptr) << t_void_ptr << t_void_ptr,          "_map_find",    (CALLFN)&_map_find);
 add(Sig(t_int_ptr) << t_void_ptr << t_int << t_void_ptr, "_map_insert",  (CALLFN)&_map_insert);
 // *add 1.2.9 iterator support for the fast specialization
 add(Sig(t_void_ptr) << t_void_ptr << t_int,              "_map_iter_ep", (CALLFN)&_map_iter_ep);
 add(Sig(t_void_ptr) << t_void_ptr << t_void_ptr,         "_map_iter_find",(CALLFN)&_map_iter_find);
 add(Sig(t_int)      << t_void_ptr << t_void_ptr,         "_map_iter_equal",(CALLFN)&_map_iter_equal);
 add(Sig(t_void)     << t_void_ptr << t_void_ptr,         "_map_iter_fetch",(CALLFN)&_map_iter_fetch);
 add(Sig(t_void)     << t_void_ptr << t_int,              "_map_iter_next", (CALLFN)&_map_iter_next);
 
 add(Sig(t_void) << t_int,"__break",(CALLFN)__break);
 add(Sig(t_void),"__mangle",(CALLFN)__mangle);
 
 // UCW Graphics
 #ifdef _WCON
 //unsigned long ucw_rgb(int r, int g, int b);
 //void ucw_set_colour(UCWin win, unsigned long clr, bool fg);

 add(Sig(t_int) << t_char_ptr << t_int << t_int << t_int << t_int,
         "ucw_create_window",(CALLFN)&ucw_create_window);
 add(Sig(t_int) << t_int << t_char_ptr,"ucw_title",(CALLFN)&ucw_title);
 add(Sig(t_int) << t_int << t_char_ptr,"ucw_cmd",(CALLFN)&ucw_cmd);
 add(Sig(t_int) << t_int << t_int << t_int << t_int << t_int,"ucw_size_window",(CALLFN)&ucw_size_window);         
 add(Sig(t_int) << t_int << t_int << t_int,"ucw_move_to",(CALLFN)&ucw_move_to);
 add(Sig(t_int) << t_int << t_int << t_int,"ucw_line_to",(CALLFN)&ucw_line_to);
 add(Sig(t_int) << t_int << t_char_ptr,"ucw_text_out",(CALLFN)&ucw_text_out);
 add(Sig(t_int) << t_int << t_char_ptr << t_int,"ucw_font",(CALLFN)&ucw_font);
 add(Sig(t_int) << t_int << t_float << t_float << t_float,"ucw_fcolour",(CALLFN)&ucw_fcolour);
 add(Sig(t_int) << t_int << t_float << t_float << t_float,"ucw_bcolour",(CALLFN)&ucw_bcolour);
 add(Sig(t_int) << t_int << t_int << t_int << t_int << t_int,"ucw_rectangle",(CALLFN)&ucw_rectangle);         
 add(Sig(t_int) << t_int << t_int << t_int << t_int << t_int,"ucw_ellipse",(CALLFN)&ucw_ellipse);         
 add(Sig(t_int) << t_char_ptr << t_int << t_bool,"exec",(CALLFN)&exec);
 add(Sig(t_long) << t_int << t_int << t_int,"ucw_rgb",(CALLFN)&ucw_rgb);
 add(Sig(t_void) << t_int << t_long << t_int,"ucw_set_colour",(CALLFN)&ucw_set_colour);
#endif

 Function* pf = Function::lookup("_range_check");
 mRangeCheck = NFBlock::create(pf,(CALLFN)pf->fun_block()->native_addr());
}

//---------------------- adding builtin functions ---------------------------
// We keep a map of imported functions to quickly tell what they are imported as!
typedef std::map<CALLFN,FBlock *> ClassImportMap;
ClassImportMap mImportMap;

// *hack 1.2.0 The optimized Win32 MS build blows up here occaisionally - no idea why!
#pragma optimize( "", off )
static FBlock *_pfb;
static Function *_pfn;
static int _kount = 0;
void insert_ptr_map(CALLFN fn, Function *pfn)
{
  try {
  _pfn = pfn;
  _pfb = pfn->fun_block();
  mImportMap[fn] = _pfb; 
  } catch(...) {
     ++_kount;
  }
}
#pragma optimize( "", on ) 

void add(const Sig& sig,char *name, CALLFN fn, bool is_stdarg, int ftype)
// Builtin::add() assumes that the Signature has been collected in the proper way.
// It's usually called from state.declare_function(), but also from add_dll_function().
// In both cases the class Sig acts as a interface to the common signature stuff.
{
 Function *pfn = state.start_function(sig.m_type,name,true,ftype);
 FunctionContext *fe = pfn->context();
 int nargs = pfn->fun_block()->nargs;
 if (is_stdarg) pfn->stdarg(true);
 
 Parser::code().emit_native_function_call(pfn,fn);
 

#ifdef __GNUC__ 
 mImportMap[fn] = pfn->fun_block();
#else
 insert_ptr_map(fn,pfn);
#endif

 fe->finalize();
 state.pop_context(); // usually done by block-end!
}

// *add 1.2.5 Offset of range checking function
int range_check_function()
{
  return mRangeCheck;
}

FBlock *import_vmethod(CALLFN fn, PFBlock pfb)
// this is passed a native routine, and a UC function block which acts as a prototype
// for the _anonymous method import_
{
  Parser::set_function_code(true);  // enter function code context
  UCContext& code = Parser::code();
  Function *pf = pfb->function;
  FBlock *fb;
  try {
	fb = FBlock::create(pfb->entry,NULL);
	mImportMap[fn] = fb;
    code.emit_native_function_call(pf,fn);
    code.emit_return(pf->return_type());
    
	fb->finalize(0);
  } catch(...) { error("error when importing function"); }  
  Parser::set_function_code(false); // go back to static code context 
  return fb;
}

//----------------------- importing functions and methods from DLLs -------------


FBlock *imported_fblock_from_function(void *pfn)
{
  return mImportMap[(CALLFN)pfn];
}


CALLFN lookup_self_link(PClass pc, const string& name);  // later in this module...


// *add    1.2.3  Support for uc_import() - the UseAddr modifier
static void* mDirectAddr = NULL;

void set_direct_import(void* p)
{ 
// A Two-Part Hack.
// It's NB to call this function with a NULL argument afterwards to reset the state.

⌨️ 快捷键说明

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