✨ split dylib and unix lib
This commit is contained in:
parent
527cb5277b
commit
e131c8da4b
|
@ -1,5 +1,105 @@
|
||||||
#include "dylib_lib.h"
|
#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[] = {
|
nasal_builtin_table dylib_lib_native[] = {
|
||||||
|
{"__dlopen", builtin_dlopen},
|
||||||
|
{"__dlclose", builtin_dlclose},
|
||||||
|
{"__dlcallv", builtin_dlcallv},
|
||||||
|
{"__dlcall", builtin_dlcall},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
|
@ -4,4 +4,19 @@
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "nasal_builtin.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[];
|
extern nasal_builtin_table dylib_lib_native[];
|
|
@ -411,215 +411,6 @@ var builtin_sleep(var* local, gc& ngc) {
|
||||||
return nil;
|
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) {
|
var builtin_platform(var* local, gc& ngc) {
|
||||||
if (is_windows()) {
|
if (is_windows()) {
|
||||||
return ngc.newstr("windows");
|
return ngc.newstr("windows");
|
||||||
|
@ -854,20 +645,6 @@ nasal_builtin_table builtin[] = {
|
||||||
{"__char", builtin_char},
|
{"__char", builtin_char},
|
||||||
{"__values", builtin_values},
|
{"__values", builtin_values},
|
||||||
{"__sleep", builtin_sleep},
|
{"__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},
|
{"__platform", builtin_platform},
|
||||||
{"__arch", builtin_arch},
|
{"__arch", builtin_arch},
|
||||||
{"__md5", builtin_md5},
|
{"__md5", builtin_md5},
|
||||||
|
|
|
@ -3,32 +3,20 @@
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <unistd.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#else
|
|
||||||
#define F_OK 0 // fuck msc
|
|
||||||
#pragma warning (disable:4566) // i know i'm using utf-8, fuck you
|
#pragma warning (disable:4566) // i know i'm using utf-8, fuck you
|
||||||
#pragma warning (disable:4244)
|
#pragma warning (disable:4244)
|
||||||
#pragma warning (disable:4267)
|
#pragma warning (disable:4267)
|
||||||
#pragma warning (disable:4996)
|
#pragma warning (disable:4996)
|
||||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||||
#include <io.h>
|
|
||||||
#include <direct.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#ifdef _WIN32
|
// for environ
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined __APPLE__
|
#if defined __APPLE__
|
||||||
#include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
#define environ (*_NSGetEnviron())
|
#define environ (*_NSGetEnviron())
|
||||||
|
@ -67,20 +55,6 @@ var builtin_chr(var*, gc&);
|
||||||
var builtin_char(var*, gc&);
|
var builtin_char(var*, gc&);
|
||||||
var builtin_values(var*, gc&);
|
var builtin_values(var*, gc&);
|
||||||
var builtin_sleep(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_platform(var*, gc&);
|
||||||
var builtin_arch(var*, gc&);
|
var builtin_arch(var*, gc&);
|
||||||
// md5 related functions
|
// md5 related functions
|
||||||
|
|
|
@ -1,23 +1,5 @@
|
||||||
#include "nasal_gc.h"
|
#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) {
|
var nas_vec::get_val(const i32 n) {
|
||||||
i32 size = elems.size();
|
i32 size = elems.size();
|
||||||
if (n<-size || n>=size) {
|
if (n<-size || n>=size) {
|
||||||
|
|
|
@ -180,10 +180,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void dir_entry_destructor(void*);
|
|
||||||
void dylib_destructor(void*);
|
|
||||||
void func_addr_destructor(void*);
|
|
||||||
|
|
||||||
struct nas_ghost {
|
struct nas_ghost {
|
||||||
private:
|
private:
|
||||||
using destructor=void (*)(void*);
|
using destructor=void (*)(void*);
|
||||||
|
|
146
src/unix_lib.cpp
146
src/unix_lib.cpp
|
@ -1,5 +1,151 @@
|
||||||
#include "unix_lib.h"
|
#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[] = {
|
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}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
|
@ -4,4 +4,33 @@
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "nasal_builtin.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[];
|
extern nasal_builtin_table unix_lib_native[];
|
|
@ -1,6 +1,9 @@
|
||||||
# unix.nas
|
# unix.nas
|
||||||
# 2023 by ValKmjolnir
|
# 2023 by ValKmjolnir
|
||||||
|
|
||||||
|
var _S_IFDIR = 0x4000;
|
||||||
|
var _S_IFREG = 0x8000;
|
||||||
|
|
||||||
var pipe = func() {
|
var pipe = func() {
|
||||||
return __pipe;
|
return __pipe;
|
||||||
}
|
}
|
||||||
|
@ -22,13 +25,11 @@ var waitpid = func(pid, nohang = 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var isdir = func(path) {
|
var isdir = func(path) {
|
||||||
# S_IFDIR 0x4000
|
return !!bits.u32_and(io.stat(path)[2], _S_IFDIR);
|
||||||
return !!bits.u32_and(io.stat(path)[2],0x4000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var isfile = func(path) {
|
var isfile = func(path) {
|
||||||
# S_IFREG 0x8000
|
return !!bits.u32_and(io.stat(path)[2], _S_IFREG);
|
||||||
return !!bits.u32_and(io.stat(path)[2],0x8000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var opendir = func(path) {
|
var opendir = func(path) {
|
||||||
|
|
Loading…
Reference in New Issue