diff --git a/module/fib.cpp b/module/fib.cpp index a65f8d6..b58ab8e 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -39,6 +39,6 @@ mod_func func_tbl[]={ {nullptr, nullptr}, }; -extern "C" mod_func* get() { +extern "C" mod_func* get(ghost_register_table* table) { return func_tbl; } \ No newline at end of file diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 57f7f25..6736385 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -95,6 +95,6 @@ mod_func func_tbl[]={ {nullptr,nullptr} }; -extern "C" mod_func* get() { +extern "C" mod_func* get(ghost_register_table* table) { return func_tbl; } \ No newline at end of file diff --git a/module/matrix.cpp b/module/matrix.cpp index 9166fdc..d74431c 100644 --- a/module/matrix.cpp +++ b/module/matrix.cpp @@ -291,6 +291,6 @@ mod_func func_tbl[]={ {nullptr,nullptr} }; -extern "C" mod_func* get() { +extern "C" mod_func* get(ghost_register_table* table) { return func_tbl; } \ No newline at end of file diff --git a/module/nasocket.cpp b/module/nasocket.cpp index 3d4fa9b..3935567 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -206,6 +206,6 @@ mod_func func_tbl[]={ {nullptr,nullptr} }; -extern "C" mod_func* get() { +extern "C" mod_func* get(ghost_register_table* table) { return func_tbl; } \ No newline at end of file diff --git a/nasal_builtin.h b/nasal_builtin.h index e36061b..a1c6c55 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -544,13 +544,13 @@ var builtin_open(var* local, gc& ngc) { return nas_err("open", "failed to open file <"+name.str()+">"); } var ret=ngc.alloc(vm_obj); - ret.obj().set(obj_type::file, res); + ret.obj().set(ghost_file, res); return ret; } var builtin_close(var* local, gc& ngc) { var fd=local[1]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("close", "not a valid filehandle"); } fd.obj().clear(); @@ -561,7 +561,7 @@ var builtin_read(var* local, gc& ngc) { var fd=local[1]; var buf=local[2]; var len=local[3]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("read", "not a valid filehandle"); } if (buf.type!=vm_str || buf.val.gcobj->unmut) { @@ -587,7 +587,7 @@ var builtin_read(var* local, gc& ngc) { var builtin_write(var* local, gc& ngc) { var fd=local[1]; var str=local[2]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("write", "not a valid filehandle"); } if (str.type!=vm_str) { @@ -600,7 +600,7 @@ var builtin_seek(var* local, gc& ngc) { var fd=local[1]; var pos=local[2]; var whence=local[3]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("seek", "not a valid filehandle"); } return var::num((f64)fseek((FILE*)fd.obj().ptr, pos.num(), whence.num())); @@ -608,7 +608,7 @@ var builtin_seek(var* local, gc& ngc) { var builtin_tell(var* local, gc& ngc) { var fd=local[1]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("tell", "not a valid filehandle"); } return var::num((f64)ftell((FILE*)fd.obj().ptr)); @@ -616,7 +616,7 @@ var builtin_tell(var* local, gc& ngc) { var builtin_readln(var* local, gc& ngc) { var fd=local[1]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("readln", "not a valid filehandle"); } var str=ngc.alloc(vm_str); @@ -664,7 +664,7 @@ var builtin_stat(var* local, gc& ngc) { var builtin_eof(var* local, gc& ngc) { var fd=local[1]; - if (!fd.objchk(obj_type::file)) { + if (!fd.objchk(ghost_file)) { return nas_err("readln", "not a valid filehandle"); } return var::num((f64)feof((FILE*)fd.obj().ptr)); @@ -849,13 +849,13 @@ var builtin_opendir(var* local, gc& ngc) { } #endif var ret=ngc.alloc(vm_obj); - ret.obj().set(obj_type::dir,p); + ret.obj().set(ghost_dir,p); return ret; } var builtin_readdir(var* local, gc& ngc) { var handle=local[1]; - if (!handle.objchk(obj_type::dir)) { + if (!handle.objchk(ghost_dir)) { return nas_err("readdir", "not a valid dir handle"); } #ifdef _MSC_VER @@ -872,7 +872,7 @@ var builtin_readdir(var* local, gc& ngc) { var builtin_closedir(var* local, gc& ngc) { var handle=local[1]; - if (!handle.objchk(obj_type::dir)) { + if (!handle.objchk(ghost_dir)) { return nas_err("closedir", "not a valid dir handle"); } handle.obj().clear(); @@ -936,7 +936,7 @@ var builtin_dlopen(var* local, gc& ngc) { } var ret=ngc.temp=ngc.alloc(vm_hash); var lib=ngc.alloc(vm_obj); - lib.obj().set(obj_type::dylib, ptr); + lib.obj().set(ghost_dylib, ptr); ret.hash().elems["lib"]=lib; #ifdef _WIN32 @@ -948,14 +948,14 @@ var builtin_dlopen(var* local, gc& ngc) { return nas_err("dlopen", "cannot find function"); } // get function pointer by name - mod_func* tbl=(mod_func*)((getptr)func)(); + mod_func* tbl=(mod_func*)((getptr)func)(&global_ghost_type_table); if (!tbl) { return nas_err("dlopen", "failed to get module functions"); } for(u32 i=0;tbl[i].name;++i) { void* p=(void*)tbl[i].fd; var tmp=ngc.alloc(vm_obj); - tmp.obj().set(obj_type::faddr, p); + tmp.obj().set(ghost_faddr, p); ret.hash().elems[tbl[i].name]=tmp; } @@ -965,7 +965,7 @@ var builtin_dlopen(var* local, gc& ngc) { var builtin_dlclose(var* local, gc& ngc) { var libptr=local[1]; - if (!libptr.objchk(obj_type::dylib)) { + if (!libptr.objchk(ghost_dylib)) { return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); } libptr.obj().clear(); @@ -975,7 +975,7 @@ var builtin_dlclose(var* local, gc& ngc) { var builtin_dlcallv(var* local, gc& ngc) { var fp=local[1]; var args=local[2]; - if (!fp.objchk(obj_type::faddr)) { + if (!fp.objchk(ghost_faddr)) { return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); } auto& vec=args.vec().elems; @@ -984,7 +984,7 @@ var builtin_dlcallv(var* local, gc& ngc) { var builtin_dlcall(var* local, gc& ngc) { var fp=local[1]; - if (!fp.objchk(obj_type::faddr)) { + if (!fp.objchk(ghost_faddr)) { return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); } diff --git a/nasal_gc.h b/nasal_gc.h index 0374e6b..63f37db 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -43,14 +43,6 @@ enum vm_type:u8 { const u32 gc_type_size=vm_co-vm_str+1; -enum class obj_type:u32 { - null=0, - file=1, - dir, - dylib, - faddr -}; - enum class coroutine_status:u32 { suspended, running, @@ -99,7 +91,7 @@ public: // number and string can be translated to each other f64 tonum(); string tostr(); - bool objchk(obj_type); + bool objchk(usize); // create new var object static var none(); @@ -175,49 +167,76 @@ struct nas_upval { void clear() {onstk=true;elems.clear();size=0;} }; -struct ghost_info { - string name; - void (*destructor)(void*); +void file_dtor(void* ptr) { + if ((FILE*)ptr==stdin) { + return; + } + fclose((FILE*)ptr); +} + +void dir_dtor(void* ptr) { +#ifndef _MSC_VER + closedir((DIR*)ptr); +#else + FindClose(ptr); +#endif +} + +void dylib_dtor(void* ptr) { +#ifdef _WIN32 + FreeLibrary((HMODULE)ptr); +#else + dlclose(ptr); +#endif +} + +void faddr_dtor(void* ptr) {} + +usize ghost_file, ghost_dir, ghost_dylib, ghost_faddr; + +struct ghost_register_table { +private: + using dtor=void (*)(void*); + +private: + std::unordered_map mapper; + std::vector destructors; + +public: + ghost_register_table() { + ghost_file=register_ghost_type("file", file_dtor); + ghost_dir=register_ghost_type("dir", dir_dtor); + ghost_dylib=register_ghost_type("dylib", dylib_dtor); + ghost_faddr=register_ghost_type("faddr", faddr_dtor); + } + + usize register_ghost_type(const std::string& name, dtor ptr) { + if (mapper.count(name)) { + std::cerr<<"ghost type \""< ghost_register_table; +ghost_register_table global_ghost_type_table; + +struct nas_obj { +public: usize type; void* ptr; public: - nas_ghost(): type(0), ptr(nullptr) {} - ~nas_ghost() { - if (!ptr) { return; } - ghost_register_table[type].destructor(ptr); - } - - static usize regist_ghost_type(ghost_info i) { - auto res=ghost_register_table.size(); - ghost_register_table.push_back(i); - return res; - } - - const std::string& name() { - return ghost_register_table[type].name; - } -}; - -struct nas_obj { - obj_type type; - void* ptr; - -private: - /* RAII constructor, new object is initialized when creating */ - void file_dtor(); - void dir_dtor(); - void dylib_dtor(); - -public: - nas_obj(): type(obj_type::null), ptr(nullptr) {} + nas_obj(): type(0), ptr(nullptr) {} ~nas_obj() {clear();} - void set(obj_type, void*); + void set(usize, void*); void clear(); }; @@ -357,47 +376,19 @@ void nas_func::clear() { keys.clear(); } -void nas_obj::set(obj_type t, void* p) { +void nas_obj::set(usize t, void* p) { type=t; ptr=p; } void nas_obj::clear() { - if (!ptr) { + if (!ptr || !type) { return; } - switch(type) { - case obj_type::file: file_dtor(); break; - case obj_type::dir: dir_dtor(); break; - case obj_type::dylib: dylib_dtor();break; - default: break; - } + global_ghost_type_table.destructor(type)(ptr); ptr=nullptr; } -void nas_obj::file_dtor() { - if ((FILE*)ptr==stdin) { - return; - } - fclose((FILE*)ptr); -} - -void nas_obj::dir_dtor() { -#ifndef _MSC_VER - closedir((DIR*)ptr); -#else - FindClose(ptr); -#endif -} - -void nas_obj::dylib_dtor() { -#ifdef _WIN32 - FreeLibrary((HMODULE)ptr); -#else - dlclose(ptr); -#endif -} - void nas_co::clear() { for(u32 i=0;i