Browse Source

completed sys api

Nicolas Cannasse 9 năm trước cách đây
mục cha
commit
5c03a4d38f
1 tập tin đã thay đổi với 395 bổ sung1 xóa
  1. 395 1
      src/std/sys.c

+ 395 - 1
src/std/sys.c

@@ -20,13 +20,71 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #include <hl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
-#ifndef HL_WIN
+#ifdef HL_WIN
+#	include <windows.h>
+#	include <direct.h>
+#	include <conio.h>
+#	define getenv _wgetenv
+#	define putenv _wputenv
+#	define getcwd(buf,size) (void*)(int_val)GetCurrentDirectoryW(size,buf)
+#	define chdir	!SetCurrentDirectoryW
+#	define system	_wsystem
+typedef struct _stat32 pstat;
+#	define stat		_wstat32
+#	define unlink	_wunlink
+#	define rename	_wrename
+#	define mkdir(path,mode)	_wmkdir(path)
+#	define rmdir	_wrmdir
+#else
+#	include <errno.h>
+#	include <unistd.h>
+#	include <dirent.h>
+#	include <limits.h>
+#	include <termios.h>
 #	include <sys/time.h>
 #	include <sys/times.h>
+#	include <sys/wait.h>
+#	include <xlocale.h>
 #	define HL_UTF8PATH
 #endif
 
+#ifdef HL_UF8PATH
+typedef char pchar;
+#define pstrchr strchr
+#define pstrlen	strlen
+#else
+typedef uchar pchar;
+#define pstrchr wcschr
+#define pstrlen	ustrlen
+#endif
+
+#ifdef HL_MAC
+#	include <sys/syslimits.h>
+#	include <limits.h>
+#	include <mach-o/dyld.h>
+#endif
+
+#ifndef CLK_TCK
+#	define CLK_TCK	100
+#endif
+
+static pchar *pstrdup( const pchar *s, int len ) {
+	pchar *ret;
+	if( len < 0 ) len = (int)pstrlen(s);
+	ret = (pchar*)hl_gc_alloc_noptr(sizeof(pchar)*(len+1));
+	memcpy(ret,s,len*sizeof(pchar));
+	ret[len] = 0;
+	return ret;
+}
+
 HL_PRIM bool hl_sys_utf8_path() {
 #ifdef HL_UTF8_PATH
 	return true;
@@ -84,6 +142,342 @@ HL_PRIM int hl_random( int max ) {
 	return rand() % max;
 }
 
+vbyte *hl_sys_get_env( vbyte *v ) {
+	return (vbyte*)getenv((pchar*)v);
+}
+
+bool hl_sys_put_env( vbyte *e, vbyte *v ) {
+#ifdef HL_WIN
+	hl_buffer *b = hl_alloc_buffer();
+	hl_buffer_str(b,(uchar*)e);
+	hl_buffer_char(b,'=');
+	if( v ) hl_buffer_str(b,(uchar*)v);
+	return putenv(hl_buffer_content(b,NULL)) == 0;
+#else
+	if( v == NULL ) return unsetenv((char*)e) == 0;
+	return setenv((char*)e,(char*)v,1) == 0;
+#endif
+}
+
+#ifdef HL_MAC
+#	define environ (*_NSGetEnviron())
+#endif
+
+#ifdef HL_WIN
+#	undef environ
+#	define environ _wenviron
+#else
+extern char **environ;
+#endif
+
+varray *hl_sys_env() {
+	varray *a;
+	pchar **e = environ;
+	pchar **arr;
+	int count = 0;
+	while( *e ) {
+		pchar *x = pstrchr(*e,'=');
+		if( x == NULL ) {
+			e++;
+			continue;
+		}
+		count++;
+	}
+	a = hl_aalloc(&hlt_bytes,count*2);
+	e = environ;
+	arr = (pchar**)(a+1);
+	while( *e ) {
+		pchar *x = pstrchr(*e,'=');
+		if( x == NULL ) {
+			e++;
+			continue;
+		}
+		*arr++ = pstrdup(*e,(int)(x - *e));
+		*arr++ = pstrdup(x,-1);
+		e++;
+	}
+	return a;
+}
+
+
+void hl_sys_sleep( double f ) {
+#ifdef HL_WIN
+	Sleep((DWORD)(f * 1000));
+#else
+	struct timespec t;
+	t.tv_sec = (int)f;
+	t.tv_nsec = (int)((f - t.tv_sec) * 1e9);
+	nanosleep(&t,NULL);
+#endif
+}
+
+bool hl_sys_set_time_locale( vbyte *l ) {
+#ifdef HL_POSIX
+	locale_t lc, old;
+	lc = newlocale(LC_TIME_MASK,(char*)l,NULL);
+	if( lc == NULL ) return false;
+	old = uselocale(lc);
+	if( old == NULL ) {
+		freelocale(lc);
+		return false;
+	}
+	if( old != LC_GLOBAL_LOCALE )
+		freelocale(old);
+	return true;
+#else
+	return setlocale(LC_TIME,(char*)l) != NULL;
+#endif
+}
+
+
+vbyte *hl_sys_get_cwd() {
+	pchar buf[256];
+	int l;
+	if( getcwd(buf,256) == NULL )
+		return NULL;
+	l = (int)pstrlen(buf);
+	if( buf[l-1] != '/' && buf[l-1] != '\\' ) {
+		buf[l] = '/';
+		buf[l+1] = 0;
+	}
+	return (vbyte*)pstrdup(buf,-1);
+}
+
+bool hl_sys_set_cwd( vbyte *dir ) {
+	return chdir((pchar*)dir) == 0;
+}
+
+bool hl_sys_is64() {
+#ifdef HL_64
+	return true;
+#else
+	return false;
+#endif
+}
+
+int hl_sys_command( vbyte *cmd ) {
+#ifdef HL_WIN
+	return system((pchar*)cmd);
+#else
+	int status = system((pchar*)cmd);
+	return WEXITSTATUS(status) | (WTERMSIG(status) << 8);
+#endif
+}
+
+bool hl_sys_exists( vbyte *path ) {
+	pstat st;
+	return stat((pchar*)path,&st) == 0;
+}
+
+bool hl_sys_delete( vbyte *path ) {
+	return unlink((pchar*)path) == 0;
+}
+
+bool hl_sys_rename( vbyte *path, vbyte *newname ) {
+	return rename((pchar*)path,(pchar*)newname) == 0;
+}
+
+varray *hl_sys_stat( vbyte *path ) {
+	pstat s;
+	varray *a;
+	int *i;
+	if( stat((pchar*)path,&s) != 0 )
+		return NULL;
+	a = hl_aalloc(&hlt_i32,12);
+	i = (int*)(a+1);
+	*i++ = s.st_gid;
+	*i++ = s.st_uid;
+	*i++ = s.st_atime;
+	*i++ = s.st_mtime;
+	*i++ = s.st_ctime;
+	*i++ = s.st_size;
+	*i++ = s.st_dev;
+	*i++ = s.st_ino;
+	*i++ = s.st_nlink;
+	*i++ = s.st_rdev;
+	*i++ = s.st_mode;
+	return a;
+}
+
+bool hl_sys_is_dir( vbyte *path ) {
+	pstat s;
+	if( stat((pchar*)path,&s) != 0 )
+		return false;
+	return s.st_mode & S_IFDIR != 0;
+}
+
+bool hl_sys_create_dir( vbyte *path, int mode ) {
+	return mkdir((pchar*)path,mode) == 0;
+}
+
+bool hl_sys_remove_dir( vbyte *path ) {
+	return rmdir((pchar*)path) == 0;
+}
+
+double hl_sys_cpu_time() {
+#ifdef HL_WIN
+	FILETIME unused;
+	FILETIME stime;
+	FILETIME utime;
+	if( !GetProcessTimes(GetCurrentProcess(),&unused,&unused,&stime,&utime) )
+		return 0.;
+	return ((double)(utime.dwHighDateTime+stime.dwHighDateTime)) * 65.536 * 6.5536 + (((double)utime.dwLowDateTime + (double)stime.dwLowDateTime) / 10000000);
+#else
+	struct tms t;
+	times(&t);
+	return ((double)(t.tms_utime + t.tms_stime)) / CLK_TCK;
+#endif
+}
+
+double hl_sys_thread_cpu_time() {
+#if defined(HL_WIN)
+	FILETIME unused;
+	FILETIME utime;
+	if( !GetThreadTimes(GetCurrentThread(),&unused,&unused,&unused,&utime) )
+		return 0.;
+	return ((double)utime.dwHighDateTime) * 65.536 * 6.5536 + (((double)utime.dwLowDateTime) / 10000000);
+#elif defined(HL_MAC)
+	hl_error("sys_thread_cpu_time not implemented on OSX");
+	return 0.;
+#else
+	struct timespec t;
+	if( clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t) )
+		return 0.;
+	return t.tv_sec + t.tv_nsec * 1e-9;
+#endif
+}
+
+varray *hl_sys_read_dir( vbyte *_path ) {
+	pchar *path = (pchar*)_path;
+	int count = 0;
+	int pos = 0;
+	varray *a = NULL;
+	pchar **current = NULL;
+
+#ifdef HL_WIN
+	WIN32_FIND_DATAW d;
+	HANDLE handle;
+	hl_buffer *b = hl_alloc_buffer();
+	int len = pstrlen(path);
+	hl_buffer_str(b,path);
+	if( len && path[len-1] != '/' && path[len-1] != '\\' )
+		hl_buffer_str(b,USTR("/*.*"));
+	else
+		hl_buffer_str(b,USTR("*.*"));
+	path = hl_buffer_content(b,NULL);
+	handle = FindFirstFileW(path,&d);
+	if( handle == INVALID_HANDLE_VALUE )
+		return NULL;
+	while( true ) {
+		// skip magic dirs
+		if( d.cFileName[0] != '.' || (d.cFileName[1] != 0 && (d.cFileName[1] != '.' || d.cFileName[2] != 0)) ) {
+			if( pos == count ) {
+				int ncount = count == 0 ? 16 : count * 2;
+				varray *narr = hl_aalloc(&hlt_bytes,count);
+				pchar **ncur = (pchar**)(narr+1);
+				memcpy(ncur,current,count*sizeof(void*));
+				current = ncur;
+				a = narr;
+				count = ncount;
+			}
+			current[pos++] = pstrdup(d.cFileName,-1);
+		}
+		if( !FindNextFileW(handle,&d) )
+			break;
+	}
+	FindClose(handle);
+#else
+	DIR *d;
+	struct dirent *e;
+	d = opendir(path);
+	if( d == NULL )
+		return NULL;
+	while( true ) {
+		e = readdir(d);
+		if( e == NULL )
+			break;
+		// skip magic dirs
+		if( e->d_name[0] == '.' && (e->d_name[1] == 0 || (e->d_name[1] == '.' && e->d_name[2] == 0)) )
+			continue;
+		if( pos == count ) {
+			int ncount = count == 0 ? 16 : count * 2;
+			varray *narr = hl_aalloc(&hlt_bytes,count);
+			pchar **ncur = (pchar**)(narr+1);
+			memcpy(ncur,current,count*sizeof(void*));
+			current = ncur;
+			a = narr;
+			count = ncount;
+		}
+		current[pos++] = pstrdup(e->d_name,-1);
+	}
+	closedir(d);
+#endif
+	if( a == NULL ) a = hl_aalloc(&hlt_bytes,0);
+	a->size = pos;
+	return a;
+}
+
+vbyte *hl_sys_full_path( vbyte *path ) {
+#ifdef HL_WIN
+	pchar buf[MAX_PATH+1];
+	if( GetFullPathNameW((pchar*)path,MAX_PATH+1,buf,NULL) == 0 )
+		return NULL;
+	return (vbyte*)pstrdup(buf,-1);
+#else
+	pchar buf[PATH_MAX];
+	if( realpath((pchar*)path,buf) == NULL )
+		return NULL;
+	return (vbyte*)pstrdup(buf,-1);
+#endif
+}
+
+vbyte *hl_sys_exe_path() {
+#if defined(HL_WIN)
+	pchar path[MAX_PATH];
+	if( GetModuleFileNameW(NULL,path,MAX_PATH) == 0 )
+		return NULL;
+	return (vbyte*)pstrdup(path,-1);
+#elif defined(HL_MAC)
+	pchar path[PATH_MAX+1];
+	uint32_t path_len = PATH_MAX;
+	if( _NSGetExecutablePath(path, &path_len) )
+		return NULL;
+	return (vbyte*)pstrdup(path,-1);
+#else
+	const pchar *p = getenv("_");
+	if( p != NULL )
+		return (vbyte*)pstrdup(p,-1);
+	{
+		pchar path[PATH_MAX];
+		int length = readlink("/proc/self/exe", path, sizeof(path));
+		if( length < 0 )
+			return NULL;
+	    path[length] = '\0';
+		return (vbyte*)pstrdup(path,-1);
+	}
+#endif
+}
+
+int hl_sys_get_char( bool b ) {
+#	ifdef HL_WIN
+	return b?getche():getch();
+#	else
+	// took some time to figure out how to do that
+	// without relying on ncurses, which clear the
+	// terminal on initscr()
+	int c;
+	struct termios term, old;
+	tcgetattr(fileno(stdin), &old);
+	term = old;
+	cfmakeraw(&term);
+	tcsetattr(fileno(stdin), 0, &term);
+	c = getchar();
+	tcsetattr(fileno(stdin), 0, &old);
+	if( b ) fputc(c,stdout);
+	return c;
+#	endif
+}
+
 #ifndef HL_JIT
 
 #include <hlc.h>