split dylib and unix lib

This commit is contained in:
ValKmjolnir 2023-08-11 00:48:57 +08:00
parent 527cb5277b
commit e131c8da4b
9 changed files with 297 additions and 277 deletions

View File

@ -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 <get> 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}
};

View File

@ -4,4 +4,19 @@
#include "nasal_gc.h"
#include "nasal_builtin.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#include <sys/wait.h>
#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[];

View File

@ -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 <get> 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},

View File

@ -3,32 +3,20 @@
#include "nasal.h"
#include "nasal_gc.h"
#ifndef _MSC_VER
#include <unistd.h>
#include <dirent.h>
#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 <io.h>
#include <direct.h>
#endif
#include <sstream>
#include <cmath>
#include <thread>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#include <sys/wait.h>
#endif
// for environ
#if defined __APPLE__
#include <crt_externs.h>
#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

View File

@ -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) {

View File

@ -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*);

View File

@ -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}
};

View File

@ -4,4 +4,33 @@
#include "nasal_gc.h"
#include "nasal_builtin.h"
#ifndef _MSC_VER
#include <unistd.h>
#include <dirent.h>
#else
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#include <io.h>
#include <direct.h>
#endif
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/wait.h>
#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[];

View File

@ -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) {