From e131c8da4bb275c868671c87738a1f5a3e4220bb Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 11 Aug 2023 00:48:57 +0800 Subject: [PATCH] :sparkles: split dylib and unix lib --- src/dylib_lib.cpp | 100 +++++++++++++++++++ src/dylib_lib.h | 15 +++ src/nasal_builtin.cpp | 223 ------------------------------------------ src/nasal_builtin.h | 30 +----- src/nasal_gc.cpp | 18 ---- src/nasal_gc.h | 4 - src/unix_lib.cpp | 146 +++++++++++++++++++++++++++ src/unix_lib.h | 29 ++++++ std/unix.nas | 9 +- 9 files changed, 297 insertions(+), 277 deletions(-) diff --git a/src/dylib_lib.cpp b/src/dylib_lib.cpp index 467a18f..d2352b3 100644 --- a/src/dylib_lib.cpp +++ b/src/dylib_lib.cpp @@ -1,5 +1,105 @@ #include "dylib_lib.h" +const auto dylib_type_name = "dylib"; +const auto func_addr_type_name = "faddr"; + +void dylib_destructor(void* ptr) { +#ifdef _WIN32 + FreeLibrary((HMODULE)ptr); +#else + dlclose(ptr); +#endif +} + +void func_addr_destructor(void* ptr) {} + +var builtin_dlopen(var* local, gc& ngc) { + var dlname = local[1]; + if (dlname.type!=vm_str) { + return nas_err("dlopen", "\"libname\" must be string"); + } +#ifdef _WIN32 + wchar_t* str = new wchar_t[dlname.str().size()+1]; + if (!str) { + return nas_err("dlopen", "malloc failed"); + } + memset(str, 0, sizeof(wchar_t)*dlname.str().size()+1); + mbstowcs(str, dlname.str().c_str(),dlname.str().size()+1); + void* ptr = LoadLibraryA(dlname.str().c_str()); + delete []str; +#else + void* ptr = dlopen(dlname.str().c_str(), RTLD_LOCAL|RTLD_LAZY); +#endif + if (!ptr) { + return nas_err("dlopen", "cannot open dynamic lib <"+dlname.str()+">"); + } + var ret = ngc.temp = ngc.alloc(vm_hash); + var lib = ngc.alloc(vm_obj); + lib.obj().set(dylib_type_name, dylib_destructor, ptr); + ret.hash().elems["lib"] = lib; + +#ifdef _WIN32 + void* func = (void*)GetProcAddress((HMODULE)lib.obj().ptr, "get"); +#else + void* func = dlsym(lib.obj().ptr, "get"); +#endif + if (!func) { + return nas_err("dlopen", "cannot find function"); + } + // get function pointer by name + module_func_info* tbl = ((get_func_ptr)func)(); + 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(func_addr_type_name, func_addr_destructor, p); + ret.hash().elems[tbl[i].name] = tmp; + } + + ngc.temp = nil; + return ret; +} + +var builtin_dlclose(var* local, gc& ngc) { + var libptr = local[1]; + if (!libptr.objchk(dylib_type_name)) { + return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); + } + libptr.obj().clear(); + return nil; +} + +var builtin_dlcallv(var* local, gc& ngc) { + var fp = local[1]; + var args = local[2]; + if (!fp.objchk(func_addr_type_name)) { + return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); + } + auto& vec = args.vec().elems; + return ((module_func)fp.obj().ptr)(vec.data(), vec.size(), &ngc); +} + +var builtin_dlcall(var* local, gc& ngc) { + var fp = local[1]; + if (!fp.objchk(func_addr_type_name)) { + return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); + } + + var* local_frame_start = local+2; + usize local_frame_size = ngc.rctx->top-local_frame_start; + // arguments' stored place begins at local +2 + return ((module_func)fp.obj().ptr)( + local_frame_start, + local_frame_size, + &ngc); +} + nasal_builtin_table dylib_lib_native[] = { + {"__dlopen", builtin_dlopen}, + {"__dlclose", builtin_dlclose}, + {"__dlcallv", builtin_dlcallv}, + {"__dlcall", builtin_dlcall}, {nullptr, nullptr} }; \ No newline at end of file diff --git a/src/dylib_lib.h b/src/dylib_lib.h index 3d8566b..1abe4a8 100644 --- a/src/dylib_lib.h +++ b/src/dylib_lib.h @@ -4,4 +4,19 @@ #include "nasal_gc.h" #include "nasal_builtin.h" +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +void dylib_destructor(void*); +void func_addr_destructor(void*); + +var builtin_dlopen(var*, gc&); +var builtin_dlclose(var*, gc&); +var builtin_dlcallv(var*, gc&); +var builtin_dlcall(var*, gc&); + extern nasal_builtin_table dylib_lib_native[]; \ No newline at end of file diff --git a/src/nasal_builtin.cpp b/src/nasal_builtin.cpp index 6a3c87c..17866ad 100644 --- a/src/nasal_builtin.cpp +++ b/src/nasal_builtin.cpp @@ -411,215 +411,6 @@ var builtin_sleep(var* local, gc& ngc) { return nil; } -var builtin_pipe(var* local, gc& ngc) { -#ifndef _WIN32 - i32 fd[2]; - var res = ngc.alloc(vm_vec); - if (pipe(fd)==-1) { - return nas_err("pipe", "failed to create pipe"); - } - res.vec().elems.push_back(var::num((f64)fd[0])); - res.vec().elems.push_back(var::num((f64)fd[1])); - return res; -#endif - return nas_err("pipe", "not supported"); -} - -var builtin_fork(var* local, gc& ngc) { -#ifndef _WIN32 - f64 res=fork(); - if (res<0) { - return nas_err("fork", "failed to fork a process"); - } - return var::num((f64)res); -#endif - return nas_err("fork", "not supported"); -} - -var builtin_waitpid(var* local, gc& ngc) { - var pid = local[1]; - var nohang = local[2]; - if (pid.type!=vm_num || nohang.type!=vm_num) { - return nas_err("waitpid", "pid and nohang must be number"); - } -#ifndef _WIN32 - i32 ret_pid,status; - ret_pid = waitpid(pid.num(),&status,nohang.num()==0? 0:WNOHANG); - var vec = ngc.alloc(vm_vec); - vec.vec().elems.push_back(var::num((f64)ret_pid)); - vec.vec().elems.push_back(var::num((f64)status)); - return vec; -#endif - return nas_err("waitpid", "not supported"); -} - -var builtin_opendir(var* local, gc& ngc) { - var path = local[1]; - if (path.type!=vm_str) { - return nas_err("opendir", "\"path\" must be string"); - } -#ifdef _MSC_VER - WIN32_FIND_DATAA data; - HANDLE p; - p = FindFirstFileA((path.str()+"\\*.*").c_str(),&data); - if (p==INVALID_HANDLE_VALUE) { - return nas_err("opendir", "cannot open dir <"+path.str()+">"); - } -#else - DIR* p = opendir(path.str().c_str()); - if (!p) { - return nas_err("opendir", "cannot open dir <"+path.str()+">"); - } -#endif - var ret = ngc.alloc(vm_obj); - ret.obj().set("dir", dir_entry_destructor, p); - return ret; -} - -var builtin_readdir(var* local, gc& ngc) { - var handle = local[1]; - if (!handle.objchk("dir")) { - return nas_err("readdir", "not a valid dir handle"); - } -#ifdef _MSC_VER - WIN32_FIND_DATAA data; - if (!FindNextFileA(handle.obj().ptr,&data)) { - return nil; - } - return ngc.newstr(data.cFileName); -#else - dirent* p = readdir((DIR*)handle.obj().ptr); - return p? ngc.newstr(p->d_name):nil; -#endif -} - -var builtin_closedir(var* local, gc& ngc) { - var handle = local[1]; - if (!handle.objchk("dir")) { - return nas_err("closedir", "not a valid dir handle"); - } - handle.obj().clear(); - return nil; -} - -var builtin_chdir(var* local, gc& ngc) { - var path = local[1]; - if (path.type!=vm_str) { - return var::num((f64)-1); - } - return var::num((f64)chdir(path.str().c_str())); -} - -var builtin_environ(var* local, gc& ngc) { - var res = ngc.temp = ngc.alloc(vm_vec); - auto& vec = res.vec().elems; - for(char** env = environ; *env; ++env) { - vec.push_back(ngc.newstr(*env)); - } - ngc.temp = nil; - return res; -} - -var builtin_getcwd(var* local, gc& ngc) { - char buf[1024]; - if (!getcwd(buf, sizeof(buf))) { - return nil; - } - return ngc.newstr(buf); -} - -var builtin_getenv(var* local, gc& ngc) { - var envvar = local[1]; - if (envvar.type!=vm_str) { - return nas_err("getenv", "\"envvar\" must be string"); - } - char* res = getenv(envvar.str().c_str()); - return res? ngc.newstr(res):nil; -} - -var builtin_dlopen(var* local, gc& ngc) { - var dlname = local[1]; - if (dlname.type!=vm_str) { - return nas_err("dlopen", "\"libname\" must be string"); - } -#ifdef _WIN32 - wchar_t* str = new wchar_t[dlname.str().size()+1]; - if (!str) { - return nas_err("dlopen", "malloc failed"); - } - memset(str, 0, sizeof(wchar_t)*dlname.str().size()+1); - mbstowcs(str, dlname.str().c_str(),dlname.str().size()+1); - void* ptr = LoadLibraryA(dlname.str().c_str()); - delete []str; -#else - void* ptr = dlopen(dlname.str().c_str(), RTLD_LOCAL|RTLD_LAZY); -#endif - if (!ptr) { - return nas_err("dlopen", "cannot open dynamic lib <"+dlname.str()+">"); - } - var ret = ngc.temp = ngc.alloc(vm_hash); - var lib = ngc.alloc(vm_obj); - lib.obj().set("dylib", dylib_destructor, ptr); - ret.hash().elems["lib"] = lib; - -#ifdef _WIN32 - void* func = (void*)GetProcAddress((HMODULE)lib.obj().ptr, "get"); -#else - void* func = dlsym(lib.obj().ptr, "get"); -#endif - if (!func) { - return nas_err("dlopen", "cannot find function"); - } - // get function pointer by name - module_func_info* tbl = ((get_func_ptr)func)(); - 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("faddr", func_addr_destructor, p); - ret.hash().elems[tbl[i].name] = tmp; - } - - ngc.temp = nil; - return ret; -} - -var builtin_dlclose(var* local, gc& ngc) { - var libptr = local[1]; - if (!libptr.objchk("dylib")) { - return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); - } - libptr.obj().clear(); - return nil; -} - -var builtin_dlcallv(var* local, gc& ngc) { - var fp = local[1]; - var args = local[2]; - if (!fp.objchk("faddr")) { - return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); - } - auto& vec = args.vec().elems; - return ((module_func)fp.obj().ptr)(vec.data(), vec.size(), &ngc); -} - -var builtin_dlcall(var* local, gc& ngc) { - var fp = local[1]; - if (!fp.objchk("faddr")) { - return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); - } - - var* local_frame_start = local+2; - usize local_frame_size = ngc.rctx->top-local_frame_start; - // arguments' stored place begins at local +2 - return ((module_func)fp.obj().ptr)( - local_frame_start, - local_frame_size, - &ngc); -} - var builtin_platform(var* local, gc& ngc) { if (is_windows()) { return ngc.newstr("windows"); @@ -854,20 +645,6 @@ nasal_builtin_table builtin[] = { {"__char", builtin_char}, {"__values", builtin_values}, {"__sleep", builtin_sleep}, - {"__pipe", builtin_pipe}, - {"__fork", builtin_fork}, - {"__waitpid", builtin_waitpid}, - {"__opendir", builtin_opendir}, - {"__readdir", builtin_readdir}, - {"__closedir", builtin_closedir}, - {"__chdir", builtin_chdir}, - {"__environ", builtin_environ}, - {"__getcwd", builtin_getcwd}, - {"__getenv", builtin_getenv}, - {"__dlopen", builtin_dlopen}, - {"__dlclose", builtin_dlclose}, - {"__dlcallv", builtin_dlcallv}, - {"__dlcall", builtin_dlcall}, {"__platform", builtin_platform}, {"__arch", builtin_arch}, {"__md5", builtin_md5}, diff --git a/src/nasal_builtin.h b/src/nasal_builtin.h index c6c5a7a..1948997 100644 --- a/src/nasal_builtin.h +++ b/src/nasal_builtin.h @@ -3,32 +3,20 @@ #include "nasal.h" #include "nasal_gc.h" -#ifndef _MSC_VER -#include -#include -#else -#define F_OK 0 // fuck msc +#ifdef _MSC_VER #pragma warning (disable:4566) // i know i'm using utf-8, fuck you #pragma warning (disable:4244) #pragma warning (disable:4267) #pragma warning (disable:4996) #define _CRT_SECURE_NO_DEPRECATE 1 #define _CRT_NONSTDC_NO_DEPRECATE 1 -#include -#include #endif #include #include #include -#ifdef _WIN32 -#include -#else -#include -#include -#endif - +// for environ #if defined __APPLE__ #include #define environ (*_NSGetEnviron()) @@ -67,20 +55,6 @@ var builtin_chr(var*, gc&); var builtin_char(var*, gc&); var builtin_values(var*, gc&); var builtin_sleep(var*, gc&); -var builtin_pipe(var*, gc&); -var builtin_fork(var*, gc&); -var builtin_waitpid(var*, gc&); -var builtin_opendir(var*, gc&); -var builtin_readdir(var*, gc&); -var builtin_closedir(var*, gc&); -var builtin_chdir(var*, gc&); -var builtin_environ(var*, gc&); -var builtin_getcwd(var*, gc&); -var builtin_getenv(var*, gc&); -var builtin_dlopen(var*, gc&); -var builtin_dlclose(var*, gc&); -var builtin_dlcallv(var*, gc&); -var builtin_dlcall(var*, gc&); var builtin_platform(var*, gc&); var builtin_arch(var*, gc&); // md5 related functions diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index 5557078..4523adf 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -1,23 +1,5 @@ #include "nasal_gc.h" -void dir_entry_destructor(void* ptr) { -#ifndef _MSC_VER - closedir((DIR*)ptr); -#else - FindClose(ptr); -#endif -} - -void dylib_destructor(void* ptr) { -#ifdef _WIN32 - FreeLibrary((HMODULE)ptr); -#else - dlclose(ptr); -#endif -} - -void func_addr_destructor(void* ptr) {} - var nas_vec::get_val(const i32 n) { i32 size = elems.size(); if (n<-size || n>=size) { diff --git a/src/nasal_gc.h b/src/nasal_gc.h index b83bca8..901db8e 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -180,10 +180,6 @@ public: } }; -void dir_entry_destructor(void*); -void dylib_destructor(void*); -void func_addr_destructor(void*); - struct nas_ghost { private: using destructor=void (*)(void*); diff --git a/src/unix_lib.cpp b/src/unix_lib.cpp index 6795bab..17408e3 100644 --- a/src/unix_lib.cpp +++ b/src/unix_lib.cpp @@ -1,5 +1,151 @@ #include "unix_lib.h" +const auto dir_type_name = "dir"; + +void dir_entry_destructor(void* ptr) { +#ifndef _MSC_VER + closedir((DIR*)ptr); +#else + FindClose(ptr); +#endif +} + +var builtin_pipe(var* local, gc& ngc) { +#ifndef _WIN32 + i32 fd[2]; + var res = ngc.alloc(vm_vec); + if (pipe(fd)==-1) { + return nas_err("pipe", "failed to create pipe"); + } + res.vec().elems.push_back(var::num((f64)fd[0])); + res.vec().elems.push_back(var::num((f64)fd[1])); + return res; +#endif + return nas_err("pipe", "not supported"); +} + +var builtin_fork(var* local, gc& ngc) { +#ifndef _WIN32 + f64 res=fork(); + if (res<0) { + return nas_err("fork", "failed to fork a process"); + } + return var::num((f64)res); +#endif + return nas_err("fork", "not supported"); +} + +var builtin_waitpid(var* local, gc& ngc) { + var pid = local[1]; + var nohang = local[2]; + if (pid.type!=vm_num || nohang.type!=vm_num) { + return nas_err("waitpid", "pid and nohang must be number"); + } +#ifndef _WIN32 + i32 ret_pid,status; + ret_pid = waitpid(pid.num(),&status,nohang.num()==0? 0:WNOHANG); + var vec = ngc.alloc(vm_vec); + vec.vec().elems.push_back(var::num((f64)ret_pid)); + vec.vec().elems.push_back(var::num((f64)status)); + return vec; +#endif + return nas_err("waitpid", "not supported"); +} + +var builtin_opendir(var* local, gc& ngc) { + var path = local[1]; + if (path.type!=vm_str) { + return nas_err("opendir", "\"path\" must be string"); + } +#ifdef _MSC_VER + WIN32_FIND_DATAA data; + HANDLE p; + p = FindFirstFileA((path.str()+"\\*.*").c_str(),&data); + if (p==INVALID_HANDLE_VALUE) { + return nas_err("opendir", "cannot open dir <"+path.str()+">"); + } +#else + DIR* p = opendir(path.str().c_str()); + if (!p) { + return nas_err("opendir", "cannot open dir <"+path.str()+">"); + } +#endif + var ret = ngc.alloc(vm_obj); + ret.obj().set(dir_type_name, dir_entry_destructor, p); + return ret; +} + +var builtin_readdir(var* local, gc& ngc) { + var handle = local[1]; + if (!handle.objchk(dir_type_name)) { + return nas_err("readdir", "not a valid dir handle"); + } +#ifdef _MSC_VER + WIN32_FIND_DATAA data; + if (!FindNextFileA(handle.obj().ptr,&data)) { + return nil; + } + return ngc.newstr(data.cFileName); +#else + dirent* p = readdir((DIR*)handle.obj().ptr); + return p? ngc.newstr(p->d_name):nil; +#endif +} + +var builtin_closedir(var* local, gc& ngc) { + var handle = local[1]; + if (!handle.objchk(dir_type_name)) { + return nas_err("closedir", "not a valid dir handle"); + } + handle.obj().clear(); + return nil; +} + +var builtin_chdir(var* local, gc& ngc) { + var path = local[1]; + if (path.type!=vm_str) { + return var::num((f64)-1); + } + return var::num((f64)chdir(path.str().c_str())); +} + +var builtin_environ(var* local, gc& ngc) { + var res = ngc.temp = ngc.alloc(vm_vec); + auto& vec = res.vec().elems; + for(char** env = environ; *env; ++env) { + vec.push_back(ngc.newstr(*env)); + } + ngc.temp = nil; + return res; +} + +var builtin_getcwd(var* local, gc& ngc) { + char buf[1024]; + if (!getcwd(buf, sizeof(buf))) { + return nil; + } + return ngc.newstr(buf); +} + +var builtin_getenv(var* local, gc& ngc) { + var envvar = local[1]; + if (envvar.type!=vm_str) { + return nas_err("getenv", "\"envvar\" must be string"); + } + char* res = getenv(envvar.str().c_str()); + return res? ngc.newstr(res):nil; +} + nasal_builtin_table unix_lib_native[] = { + {"__pipe", builtin_pipe}, + {"__fork", builtin_fork}, + {"__waitpid", builtin_waitpid}, + {"__opendir", builtin_opendir}, + {"__readdir", builtin_readdir}, + {"__closedir", builtin_closedir}, + {"__chdir", builtin_chdir}, + {"__environ", builtin_environ}, + {"__getcwd", builtin_getcwd}, + {"__getenv", builtin_getenv}, {nullptr, nullptr} }; \ No newline at end of file diff --git a/src/unix_lib.h b/src/unix_lib.h index 48fd3fd..e69da51 100644 --- a/src/unix_lib.h +++ b/src/unix_lib.h @@ -4,4 +4,33 @@ #include "nasal_gc.h" #include "nasal_builtin.h" +#ifndef _MSC_VER +#include +#include +#else +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#include +#include +#endif + +#ifdef _WIN32 +#include +#else +#include +#endif + +void dir_entry_destructor(void*); + +var builtin_pipe(var*, gc&); +var builtin_fork(var*, gc&); +var builtin_waitpid(var*, gc&); +var builtin_opendir(var*, gc&); +var builtin_readdir(var*, gc&); +var builtin_closedir(var*, gc&); +var builtin_chdir(var*, gc&); +var builtin_environ(var*, gc&); +var builtin_getcwd(var*, gc&); +var builtin_getenv(var*, gc&); + extern nasal_builtin_table unix_lib_native[]; \ No newline at end of file diff --git a/std/unix.nas b/std/unix.nas index b42914a..9639400 100644 --- a/std/unix.nas +++ b/std/unix.nas @@ -1,6 +1,9 @@ # unix.nas # 2023 by ValKmjolnir +var _S_IFDIR = 0x4000; +var _S_IFREG = 0x8000; + var pipe = func() { return __pipe; } @@ -22,13 +25,11 @@ var waitpid = func(pid, nohang = 0) { } var isdir = func(path) { - # S_IFDIR 0x4000 - return !!bits.u32_and(io.stat(path)[2],0x4000); + return !!bits.u32_and(io.stat(path)[2], _S_IFDIR); } var isfile = func(path) { - # S_IFREG 0x8000 - return !!bits.u32_and(io.stat(path)[2],0x8000); + return !!bits.u32_and(io.stat(path)[2], _S_IFREG); } var opendir = func(path) {