generalization of syscalls
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
#include "../std.h"
|
||||
#include "../str.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <tgmath.h>
|
||||
|
||||
void *com_std_alloc(void *ptr, size_t size) {
|
||||
@@ -19,3 +22,50 @@ double com_std_sqrt(double v) { return sqrt(v); }
|
||||
double com_std_fabs(double v) { return fabs(v); }
|
||||
double com_std_sin(double v) { return sin(v); }
|
||||
double com_std_cos(double v) { return cos(v); }
|
||||
|
||||
com_std_fd com_std_open(char *path, uint32_t flags) {
|
||||
com_std_assert(flags != 0);
|
||||
char *mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE ? "r+"
|
||||
: flags & COM_STD_OPEN_READ ? "r"
|
||||
: "w";
|
||||
return fopen(path, mode);
|
||||
}
|
||||
|
||||
bool com_std_write(com_std_fd fd, char *data, uint32_t bytes) {
|
||||
com_std_assert(fd != NULL && data != NULL && bytes != 0);
|
||||
bool s = fwrite(data, 1, bytes, fd) == bytes;
|
||||
fflush(fd);
|
||||
return s;
|
||||
}
|
||||
|
||||
int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) {
|
||||
com_std_assert(fd != NULL && data != NULL && upto != 0);
|
||||
return fread(data, 1, upto, fd);
|
||||
}
|
||||
|
||||
bool com_std_sfwd(com_std_fd fd, uint32_t bytes) {
|
||||
com_std_assert(fd != NULL && bytes != 0);
|
||||
return fseek(fd, bytes, SEEK_CUR) == 0;
|
||||
}
|
||||
|
||||
com_std_fd com_std_socket(bool isnetwork) {
|
||||
if (!isnetwork) {
|
||||
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
return fdopen(sockfd, "w+b");
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
|
||||
com_std_assert(address != NULL);
|
||||
if (!isnetwork) {
|
||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||
__builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address));
|
||||
return connect(fileno(fd), (struct sockaddr *)&addr, sizeof(addr)) == 0;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void com_std_exit(uint32_t status) { exit(status); }
|
||||
|
||||
void com_std_close(com_std_fd fd) { fclose(fd); }
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
AMD64 specific Linux std parts.
|
||||
*/
|
||||
|
||||
#include "linux.c"
|
||||
|
||||
#include "../std.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
inline com_std_fd com_std_open(char *path, uint32_t flags) {
|
||||
com_std_assert(flags != 0);
|
||||
uint32_t mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE
|
||||
? O_RDWR
|
||||
: flags & COM_STD_OPEN_READ ? O_RDONLY
|
||||
: O_WRONLY;
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(2), "D"(path), "S"(mode)
|
||||
: "rcx", "r11", "memory");
|
||||
if (ret <= 0) /* Mark NULL, removing error code */
|
||||
ret = 0;
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
inline bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(1), "D"(fd), "S"(data), "d"(bytes)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret == bytes;
|
||||
}
|
||||
|
||||
inline int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(0), "D"(fd), "S"(data), "d"(upto)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(8), "D"(fd), "S"(bytes), "d"(SEEK_CUR)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret >= 0; /* TODO: Check whether offset is bytes offset exactly? */
|
||||
}
|
||||
|
||||
inline com_std_fd com_std_socket(bool isnetwork) {
|
||||
if (!isnetwork) {
|
||||
int32_t sockfd;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(sockfd)
|
||||
: "a"(41), "D"(AF_UNIX), "S"(SOCK_STREAM), "d"(0)
|
||||
: "rcx", "r11", "memory");
|
||||
if (sockfd < 0)
|
||||
sockfd = 0;
|
||||
return (void *)(int64_t)sockfd;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
|
||||
com_std_assert(address != NULL);
|
||||
if (!isnetwork) {
|
||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||
__builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address));
|
||||
int32_t ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(42), "D"(fd), "S"(&addr), "d"(sizeof addr)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret == 0;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline void com_std_exit(uint32_t status) {
|
||||
__asm__ volatile("syscall" : : "a"(60), "D"(status) : "rcx", "r11", "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
inline void com_std_close(com_std_fd fd) {
|
||||
__asm__ volatile("syscall" : : "a"(3), "D"(fd) : "rcx", "r11", "memory");
|
||||
}
|
||||
+8
-4
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
Generic linux std parts.
|
||||
*/
|
||||
|
||||
#include "../def.h"
|
||||
#include "../std.h"
|
||||
#include "../str.h"
|
||||
@@ -8,18 +12,18 @@ void *com_std_alloc(void *ptr, size_t size) { return NULL; }
|
||||
void com_std_assert(bool holds) {
|
||||
/* TODO: Write line info to stderr as well. */
|
||||
if (!holds)
|
||||
com_std_syscall(__NR_exit, -1, 0, 0);
|
||||
com_std_exit(-1);
|
||||
}
|
||||
|
||||
/* TODO: Figure out a way to make it easy to deal with. */
|
||||
void com_std_printf(char const *fmt, ...) {
|
||||
com_std_syscall(1, 1, (intptr_t)fmt, com_str_ext_len(fmt));
|
||||
com_std_write((void *)1, fmt, com_str_ext_len(fmt));
|
||||
}
|
||||
|
||||
void com_std_print_str(char const *str, uint32_t len, bool newline) {
|
||||
com_std_syscall(1, 1, (intptr_t)str, len);
|
||||
com_std_write((void *)1, str, len);
|
||||
if (newline)
|
||||
com_std_syscall(1, 1, (intptr_t)"\n", 1);
|
||||
com_std_write((void *)1, "\n", 1);
|
||||
}
|
||||
|
||||
double com_std_sqrt(double v) { return __builtin_sqrt(v); }
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "../std.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *com_std_alloc(void *ptr, size_t size) { return NULL; }
|
||||
void com_std_assert(bool holds) {}
|
||||
void com_std_printf(char const *fmt, ...) {}
|
||||
@@ -15,6 +18,24 @@ double com_std_sin(double v) { return 0; }
|
||||
double com_std_cos(double v) { return 0; }
|
||||
#endif
|
||||
|
||||
com_std_fd com_std_open(char *path, uint32_t flags) { return NULL; }
|
||||
bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) {
|
||||
return false;
|
||||
}
|
||||
int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { return -1; }
|
||||
bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { return false; }
|
||||
com_std_fd com_std_socket(bool isnetwork) { return NULL; }
|
||||
bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
|
||||
return false;
|
||||
}
|
||||
void com_std_exit(uint32_t status) {
|
||||
__builtin_trap();
|
||||
while (1) {
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
void com_std_close(com_std_fd fd) { return; }
|
||||
|
||||
// void memcpy(void *__restrict dest, const void *__restrict src, size_t n) {
|
||||
// __builtin_memcpy(dest, src, n);
|
||||
// };
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#define COM_BIN_NAT_ENDIAN (1 << 2)
|
||||
|
||||
typedef struct com_bin_interface {
|
||||
/* Attempts to read exactly N bytes, returns false if it cannot. */
|
||||
/* Attempts to read exactly N bytes, return false if it cannot. */
|
||||
bool (*readn)(void *ctx, char *into, uint32_t bytes);
|
||||
bool (*skipn)(void *ctx, uint32_t bytes);
|
||||
} com_bin_interface;
|
||||
|
||||
+13
-13
@@ -10,21 +10,21 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX
|
||||
#include <sys/syscall.h>
|
||||
|
||||
static inline long com_std_syscall(long number, long arg1, long arg2,
|
||||
long arg3) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(number), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/* Generic system interface, linux/bsd derived. */
|
||||
typedef void *com_std_fd;
|
||||
#define COM_STD_OPEN_READ (1 << 0)
|
||||
#define COM_STD_OPEN_WRITE (1 << 1)
|
||||
com_std_fd com_std_open(char *path, uint32_t flags);
|
||||
bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes);
|
||||
int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto);
|
||||
bool com_std_sfwd(com_std_fd fd, uint32_t bytes);
|
||||
com_std_fd com_std_socket(bool isnetwork);
|
||||
bool com_std_connect(com_std_fd sock, bool isnetwork, char *address);
|
||||
void com_std_exit(uint32_t status) __attribute__((noreturn));
|
||||
void com_std_close(com_std_fd fd);
|
||||
|
||||
/* TODO: Remove, use buffer semantics instead. */
|
||||
/* Instead have a mmap functions here. */
|
||||
/* Note: Freeing is done by passing 0 size to pointer. */
|
||||
void *com_std_alloc(void *ptr, size_t size);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user