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