mirror of
https://github.com/ilyakooo0/Idris-dev.git
synced 2024-09-11 08:55:23 +03:00
Can't use MKBIGI for the result, since that'll be a negative number for the current time! So use MKBIGUI instead to ensure it stays unsigned.
303 lines
5.6 KiB
C
303 lines
5.6 KiB
C
#include "idris_stdfgn.h"
|
|
#include "idris_rts.h"
|
|
#include "idris_gmp.h"
|
|
#include "idris_gc.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef _WIN32
|
|
#include "windows/win_utils.h"
|
|
#else
|
|
#include <sys/select.h>
|
|
#endif
|
|
|
|
extern char** environ;
|
|
|
|
void putStr(char* str) {
|
|
printf("%s", str);
|
|
}
|
|
|
|
void *fileOpen(char *name, char *mode) {
|
|
#ifdef _WIN32
|
|
FILE *f = win32_u8fopen(name, mode);
|
|
#else
|
|
FILE *f = fopen(name, mode);
|
|
#endif
|
|
return (void *)f;
|
|
}
|
|
|
|
void fileClose(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
fclose(f);
|
|
}
|
|
|
|
int fileEOF(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
return feof(f);
|
|
}
|
|
|
|
int fileError(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
return ferror(f);
|
|
}
|
|
|
|
int fileRemove(const char *filename) {
|
|
return remove(filename);
|
|
}
|
|
|
|
int fileSize(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
int fd = fileno(f);
|
|
|
|
struct stat buf;
|
|
if (fstat(fd, &buf) == 0) {
|
|
return (int)(buf.st_size);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
VAL fileAccessTime(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
int fd = fileno(f);
|
|
|
|
struct stat buf;
|
|
if (fstat(fd, &buf) == 0) {
|
|
return MKBIGI(buf.st_atime);
|
|
} else {
|
|
return MKBIGI(-1);
|
|
}
|
|
}
|
|
|
|
VAL fileModifiedTime(VM* vm, void* h) {
|
|
FILE* f = (FILE*)h;
|
|
int fd = fileno(f);
|
|
|
|
struct stat buf;
|
|
if (fstat(fd, &buf) == 0) {
|
|
return MKBIGUI(vm, buf.st_mtime);
|
|
} else {
|
|
return MKBIGI(-1);
|
|
}
|
|
}
|
|
|
|
VAL fileStatusTime(void* h) {
|
|
FILE* f = (FILE*)h;
|
|
int fd = fileno(f);
|
|
|
|
struct stat buf;
|
|
if (fstat(fd, &buf) == 0) {
|
|
return MKBIGI(buf.st_ctime);
|
|
} else {
|
|
return MKBIGI(-1);
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
DIR* dirptr;
|
|
int error;
|
|
} DirInfo;
|
|
|
|
void* idris_dirOpen(char* dname) {
|
|
DIR *d = opendir(dname);
|
|
if (d == NULL) {
|
|
return NULL;
|
|
} else {
|
|
DirInfo* di = malloc(sizeof(DirInfo));
|
|
di->dirptr = d;
|
|
di->error = 0;
|
|
|
|
return (void*)di;
|
|
}
|
|
}
|
|
|
|
void idris_dirClose(void* h) {
|
|
DirInfo* di = (DirInfo*)h;
|
|
|
|
closedir(di->dirptr);
|
|
free(di);
|
|
}
|
|
|
|
char* idris_nextDirEntry(void* h) {
|
|
DirInfo* di = (DirInfo*)h;
|
|
struct dirent* de = readdir(di->dirptr);
|
|
|
|
if (de == NULL) {
|
|
di->error = -1;
|
|
return NULL;
|
|
} else {
|
|
return de->d_name;
|
|
}
|
|
}
|
|
|
|
int idris_mkdir(char* dname) {
|
|
#ifdef _WIN32
|
|
return mkdir(dname);
|
|
#else
|
|
return mkdir(dname, S_IRWXU | S_IRGRP | S_IROTH);
|
|
#endif
|
|
}
|
|
|
|
int idris_chdir(char* dname) {
|
|
return chdir(dname);
|
|
}
|
|
|
|
int idris_dirError(void *dptr) {
|
|
return ((DirInfo*)dptr)->error;
|
|
}
|
|
|
|
int idris_writeStr(void* h, char* str) {
|
|
FILE* f = (FILE*)h;
|
|
if (fputs(str, f) >= 0) {
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int fpoll(void* h)
|
|
{
|
|
#ifdef _WIN32
|
|
return win_fpoll(h);
|
|
#else
|
|
FILE* f = (FILE*)h;
|
|
fd_set x;
|
|
struct timeval timeout;
|
|
timeout.tv_sec = 1;
|
|
timeout.tv_usec = 0;
|
|
int fd = fileno(f);
|
|
|
|
FD_ZERO(&x);
|
|
FD_SET(fd, &x);
|
|
|
|
int r = select(fd+1, &x, 0, 0, &timeout);
|
|
return r;
|
|
#endif
|
|
}
|
|
|
|
void *do_popen(const char *cmd, const char *mode) {
|
|
#ifdef _WIN32
|
|
FILE *f = win32_u8popen(cmd, mode);
|
|
#else
|
|
FILE *f = popen(cmd, mode);
|
|
// int d = fileno(f);
|
|
// fcntl(d, F_SETFL, O_NONBLOCK);
|
|
#endif
|
|
return f;
|
|
}
|
|
|
|
int isNull(void* ptr) {
|
|
return ptr==NULL;
|
|
}
|
|
|
|
void* idris_stdin() {
|
|
return (void*)stdin;
|
|
}
|
|
|
|
char* getEnvPair(int i) {
|
|
return *(environ + i);
|
|
}
|
|
|
|
VAL idris_time() {
|
|
time_t t = time(NULL);
|
|
return MKBIGI(t);
|
|
}
|
|
|
|
VAL idris_clock(VM* vm) {
|
|
VAL result;
|
|
#ifdef _WIN32
|
|
int64_t sec, nsec;
|
|
win32_gettime(&sec, &nsec);
|
|
idris_constructor(result, vm, 0, 2, 0);
|
|
idris_setConArg(result, 0, MKBIGI(sec));
|
|
idris_setConArg(result, 1, MKBIGI(nsec));
|
|
#else
|
|
struct timespec ts;
|
|
// We're not checking the result here, which is of course bad, but
|
|
// CLOCK_REALTIME is required by POSIX at least!
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
idris_constructor(result, vm, 0, 2, 0);
|
|
idris_setConArg(result, 0, MKBIGI(ts.tv_sec));
|
|
idris_setConArg(result, 1, MKBIGI(ts.tv_nsec));
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
#ifndef SEL4
|
|
int idris_usleep(int usec) {
|
|
struct timespec t;
|
|
t.tv_sec = usec / 1000000;
|
|
t.tv_nsec = (usec % 1000000) * 1000;
|
|
|
|
return nanosleep(&t, NULL);
|
|
}
|
|
#endif // SEL4
|
|
|
|
VAL idris_mkFileError(VM* vm) {
|
|
VAL result;
|
|
switch(errno) {
|
|
// Make sure this corresponds to the FileError structure in
|
|
// Prelude.File
|
|
case ENOENT:
|
|
idris_constructor(result, vm, 3, 0, 0);
|
|
break;
|
|
case EACCES:
|
|
idris_constructor(result, vm, 4, 0, 0);
|
|
break;
|
|
default:
|
|
idris_constructor(result, vm, 0, 1, 0);
|
|
idris_setConArg(result, 0, MKINT((intptr_t)errno));
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void idris_forceGC(void* vm) {
|
|
idris_gc((VM*)vm);
|
|
}
|
|
|
|
typedef struct {
|
|
char* string;
|
|
int len;
|
|
} StrBuffer;
|
|
|
|
void* idris_makeStringBuffer(int len) {
|
|
StrBuffer* sb = malloc(sizeof(StrBuffer));
|
|
if (sb != NULL) {
|
|
sb->string = malloc(len);
|
|
sb->string[0] = '\0';
|
|
sb->len = 0;
|
|
}
|
|
return sb;
|
|
}
|
|
|
|
void idris_addToString(void* buffer, char* str) {
|
|
StrBuffer* sb = (StrBuffer*)buffer;
|
|
int len = strlen(str);
|
|
|
|
memcpy(sb->string + sb->len, str, len+1);
|
|
sb->len += len;
|
|
}
|
|
|
|
VAL idris_getString(VM* vm, void* buffer) {
|
|
StrBuffer* sb = (StrBuffer*)buffer;
|
|
|
|
VAL str = MKSTR(vm, sb->string);
|
|
free(sb->string);
|
|
free(sb);
|
|
return str;
|
|
}
|
|
|
|
VAL idris_currentDir() {
|
|
char cwd[1024];
|
|
if (getcwd(cwd, sizeof(cwd)) != NULL)
|
|
return MKSTR(get_vm(),cwd);
|
|
else
|
|
return MKSTR(get_vm(),"");
|
|
}
|