#include <syscall.h>

static inline int syscall1(int num, uint32_t arg1) {
    int ret;
    asm volatile (
        "int $0x80"
        : "=a"(ret)
        : "a"(num), "b"(arg1)
        : "memory"
    );
    return ret;
}

static inline int syscall3(int num, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
    int ret;
    asm volatile (
        "int $0x80"
        : "=a"(ret)
        : "a"(num), "b"(arg1), "c"(arg2), "d"(arg3)
        : "memory"
    );
    return ret;
}

void exit(int status) {
    syscall1(SYS_EXIT, (uint32_t)status);
    while(1);
}

int open(const char* path) {
    return syscall3(SYS_OPEN, (uint32_t)path, 0, 0);
}

int write(int fd, const void* buf, size_t cnt) {
    return syscall3(SYS_WRITE, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt);
}

int read(int fd, void* buf, size_t cnt) {
    return syscall3(SYS_READ, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt);
}

int lseek(int fd, size_t offset, int whence) {
    return syscall3(SYS_LSEEK, (uint32_t)fd, offset, whence);
}

int close(int fd) {
    return syscall1(SYS_CLOSE, fd);
}

int pty(int* slave) {
    return syscall1(SYS_PTY, (uint32_t)slave);
}

int fork() {
    return syscall1(SYS_FORK, 0);
}

int exec(const char* path) {
    return syscall1(SYS_EXEC, (uint32_t)path);
}

int dup2(int src, int dst) {
    return syscall3(SYS_DUP2, src, dst, 0);
}

int waitpid(int pid, int* status) {
    return syscall3(SYS_WAIT, pid, (uint32_t)status, 0);
}

void* sbrk(int32_t increment) {
    return (void*)syscall1(SYS_SBRK, increment);
}

int brk(void *addr) {
    return syscall1(SYS_BRK, (uint32_t)addr);
}