📄 directcall.cpp
字号:
}
#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 + -