userspace: Rewrite everything

Everything.

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-01-04 06:27:54 +02:00
parent dea36a0228
commit 6dae34debd
135 changed files with 11707 additions and 5286 deletions

View File

@ -1,22 +0,0 @@
// extern void (*__preinit_array_start[])(void) __attribute__((weak));
// extern void (*__preinit_array_end[])(void) __attribute__((weak));
// extern void (*__init_array_start[])(void) __attribute__((weak));
// extern void (*__init_array_end[])(void) __attribute__((weak));
// extern void (*__fini_array_start []) (void) __attribute__((weak));
// extern void (*__fini_array_end []) (void) __attribute__((weak));
typedef void (*fct)(void);
extern fct __init_array_start[0], __init_array_end[0];
extern fct __fini_array_start[0], __fini_array_end[0];
void __libc_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __libc_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}

View File

@ -1,35 +0,0 @@
#include "lock.hpp"
#include <stdio.h>
void LockClass::DeadLock(SpinLockData Lock)
{
fprintf(stdout, "Potential deadlock in lock '%s' held by '%s'! %ld locks in queue.",
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count);
}
int LockClass::Lock(const char *FunctionName)
{
LockData.AttemptingToGet = FunctionName;
Retry:
unsigned int i = 0;
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
;
if (i >= 0x10000000)
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
__sync_synchronize();
return 0;
}
int LockClass::Unlock()
{
__sync_synchronize();
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
LockData.Count--;
IsLocked = false;
return 0;
}

View File

@ -1,47 +1,36 @@
# Config file
include ../../../config.mk
default:
$(error Do not run this Makefile directly!)
NAME=c
DYNAMIC_NAME := libc.so
STATIC_NAME := libc.a
ifeq ($(USERSPACE_STATIC_LIBS), 1)
OBJECT_NAME := lib$(NAME).a
else
OBJECT_NAME := lib$(NAME).so
endif
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
OUTPUT_DIR=../../out/lib/
SYSROOT = --sysroot=../../out/
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
AR = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ar
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
S_SOURCES = $(shell find ./ -type f -name '*.S')
OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${S_SOURCES:.S=.o}
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
ifeq ($(OSARCH), amd64)
ASM_ARCH := elf64
else ifeq ($(OSARCH), i386)
ASM_ARCH := elf32
endif
CFLAGS := -fvisibility=hidden -fPIC -I../include -I../../out/include
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
endif
build: $(OBJECT_NAME)
build: $(DYNAMIC_NAME) $(STATIC_NAME)
$(OBJECT_NAME): $(OBJ)
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
$(DYNAMIC_NAME): $(OBJ)
$(info Linking $@)
ifeq ($(USERSPACE_STATIC_LIBS), 1)
$(AR) rcs $(OUTPUT_DIR)$@ $(OBJ)
else
$(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@
endif
$(CC) -nostdlib -shared -fPIC -fPIE -e _start -Wl,-soname,$(DYNAMIC_NAME) $(SYSROOT) $(OBJ) -o $(DYNAMIC_NAME)
cp $(DYNAMIC_NAME) $(OUTPUT_DIR)$(DYNAMIC_NAME)
$(STATIC_NAME): $(OBJ)
$(info Linking $@)
$(AR) -rcs $(STATIC_NAME) $(OBJ)
cp $(STATIC_NAME) $(OUTPUT_DIR)$(STATIC_NAME)
%.o: %.c
$(info Compiling $<)
@ -56,4 +45,4 @@ endif
$(AS) -c $< -o $@
clean:
rm -f $(OBJ)
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -1,23 +0,0 @@
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
extern void __libc_init_array(void);
extern void __libc_fini_array(void);
extern void __libc_init_std(void);
extern void __libc_fini_std(void);
PUBLIC void __libc_init(void)
{
__libc_init_array();
__libc_init_std();
}
PUBLIC void _exit(int Code)
{
__libc_fini_std();
__libc_fini_array();
syscall1(sc_exit, (long)Code);
while (1)
;
}

View File

@ -1,23 +0,0 @@
#include <dlfcn.h>
static char *error = "Not implemented";
__attribute__((weak)) void *dlopen(const char *filename, int flags)
{
return NULL;
}
__attribute__((weak)) void *dlsym(void *handle, const char *symbol)
{
return NULL;
}
__attribute__((weak)) int dlclose(void *handle)
{
return -1;
}
__attribute__((weak)) char *dlerror(void)
{
return error;
}

34
Userspace/libc/src/init.c Normal file
View File

@ -0,0 +1,34 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
int __init_pthread(void);
void __init_stdio(void);
__attribute__((visibility("default"))) void __libc_init(void)
{
__init_pthread();
__init_stdio();
}
__attribute__((visibility("default"))) void _exit(int Code)
{
call_exit(Code);
while (1)
;
}

View File

@ -1,50 +0,0 @@
#ifndef __FENNIX_KERNEL_LOCK_H__
#define __FENNIX_KERNEL_LOCK_H__
#include <types.h>
#ifdef __cplusplus
/** @brief Please use this macro to create a new lock. */
class LockClass
{
struct SpinLockData
{
uint64_t LockData = 0x0;
const char *CurrentHolder = "(nul)";
const char *AttemptingToGet = "(nul)";
uint64_t Count = 0;
};
void DeadLock(SpinLockData Lock);
private:
SpinLockData LockData;
bool IsLocked = false;
public:
SpinLockData *GetLockData() { return &LockData; }
int Lock(const char *FunctionName);
int Unlock();
};
/** @brief Please use this macro to create a new smart lock. */
class SmartLockClass
{
private:
LockClass *LockPointer = nullptr;
public:
SmartLockClass(LockClass &Lock, const char *FunctionName)
{
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~SmartLockClass() { this->LockPointer->Unlock(); }
};
/** @brief Create a new lock (can be used with SmartCriticalSection). */
#define NewLock(Name) LockClass Name
/** @brief Simple lock that is automatically released when the scope ends. */
#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__)
#endif // __cplusplus
#endif // !__FENNIX_KERNEL_LOCK_H__

View File

@ -1,5 +1,152 @@
/* TODO: Show a message or something */
int _start()
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_end[])(void) __attribute__((weak));
const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
#ifndef LIBC_GIT_COMMIT
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
#endif
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
};
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
int main(int argc, char *argv[], char *envp[])
{
(void)argc;
(void)argv;
(void)envp;
/* FIXME: show printf license notice and some help and commands? */
return -1;
}

View File

@ -0,0 +1,10 @@
This code is released into the public domain. Use this code at your own
risk. Feel free to use it for whatever purpose you want. I take no responsibilty or
whatever if anything goes wrong. Use it at your own risk.
If you have any fixes or patches, please email me.
Durand Miller <clutter@djm.co.za>

View File

@ -1,30 +0,0 @@
#include <types.h>
#include "../lock.hpp"
#include "../../../../Kernel/syscalls.h"
NewLock(liballocLock);
extern "C" int liballoc_lock()
{
return liballocLock.Lock(__FUNCTION__);
}
extern "C" int liballoc_unlock()
{
return liballocLock.Unlock();
}
extern "C" void *liballoc_alloc(size_t Pages)
{
return (void *)syscall6(sc_mmap, NULL,
Pages * 0x1000,
sc_PROT_READ | sc_PROT_WRITE,
sc_MAP_ANONYMOUS | sc_MAP_PRIVATE,
-1, 0);
}
extern "C" int liballoc_free(void *Address, size_t Pages)
{
return syscall2(sc_munmap, (uintptr_t)Address, Pages * 0x1000);
}

View File

@ -0,0 +1,78 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
/* Taken directly from https://github.com/blanham/liballoc/blob/master/linux.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
#if !defined(MAP_FAILED)
#define MAP_FAILED ((char *)-1)
#endif
#ifndef MAP_NORESERVE
#ifdef MAP_AUTORESRV
#define MAP_NORESERVE MAP_AUTORESRV
#else
#define MAP_NORESERVE 0
#endif
#endif
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int page_size = -1;
int liballoc_lock()
{
pthread_mutex_lock(&mutex);
return 0;
}
int liballoc_unlock()
{
pthread_mutex_unlock(&mutex);
return 0;
}
void *liballoc_alloc(int pages)
{
if (page_size < 0)
page_size = getpagesize();
unsigned int size = pages * page_size;
char *p2 = (char *)mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);
if (p2 == MAP_FAILED)
return NULL;
if (mprotect(p2, size, PROT_READ | PROT_WRITE) != 0)
{
munmap(p2, size);
return NULL;
}
return p2;
}
int liballoc_free(void *ptr, int pages)
{
return munmap(ptr, pages * page_size);
}

View File

@ -43,17 +43,11 @@
#define LIBALLOC_MAGIC 0xc001c0de
#define LIBALLOC_DEAD 0xdeaddead
// #define LIBALLOCDEBUG 1
#define LIBALLOCINFO 1
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
#include <stdio.h>
#include <stdlib.h>
// #include <debug.h>
#define FLUSH() fflush(stdout)
#define atexit(x) atexit(x)
// #define printf(m, ...) trace(m, ##__VA_ARGS__)
#endif
@ -131,10 +125,10 @@ static void *liballoc_memcpy(void *s1, const void *s2, size_t n)
return s1;
}
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
static void liballoc_dump()
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
struct liballoc_major *maj = l_memRoot;
struct liballoc_minor *min = NULL;
#endif
@ -146,7 +140,7 @@ static void liballoc_dump()
printf("liballoc: Error count: %i\n", l_errorCount);
printf("liballoc: Possible overruns: %i\n", l_possibleOverruns);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
while (maj != NULL)
{
printf("liballoc: %x: total = %i, used = %i\n",
@ -198,7 +192,7 @@ static struct liballoc_major *allocate_new_page(unsigned int size)
if (maj == NULL)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: liballoc_alloc( %i ) return NULL\n", st);
FLUSH();
#endif
@ -214,7 +208,7 @@ static struct liballoc_major *allocate_new_page(unsigned int size)
l_allocated += maj->size;
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: Resource allocated %x of %i pages (%i bytes) for %i size.\n", maj, st, maj->size, size);
printf("liballoc: Total memory usage = %i KB\n", (int)((l_allocated / (1024))));
@ -248,7 +242,7 @@ void *PREFIX(malloc)(size_t req_size)
if (size == 0)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: alloc( 0 ) called from %x\n",
__builtin_return_address(0));
FLUSH();
@ -259,8 +253,8 @@ void *PREFIX(malloc)(size_t req_size)
if (l_memRoot == NULL)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#ifdef LIBALLOCDEBUG
#if defined DEBUG || defined INFO
#ifdef DEBUG
printf("liballoc: initialization of liballoc " VERSION "\n");
#endif
atexit(liballoc_dump);
@ -272,20 +266,20 @@ void *PREFIX(malloc)(size_t req_size)
if (l_memRoot == NULL)
{
liballoc_unlock();
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: initial l_memRoot initialization failed\n", p);
FLUSH();
#endif
return NULL;
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: set up first memory major %x\n", l_memRoot);
FLUSH();
#endif
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: %x PREFIX(malloc)( %i ): ",
__builtin_return_address(0),
size);
@ -326,7 +320,7 @@ void *PREFIX(malloc)(size_t req_size)
// CASE 1: There is not enough space in this major block.
if (diff < (size + sizeof(struct liballoc_minor)))
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 1: Insufficient space in block %x\n", maj);
FLUSH();
#endif
@ -378,7 +372,7 @@ void *PREFIX(malloc)(size_t req_size)
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 2: returning %x\n", p);
FLUSH();
#endif
@ -414,7 +408,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 3: returning %x\n", p);
FLUSH();
#endif
@ -460,7 +454,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)min + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 4.1: returning %x\n", p);
FLUSH();
#endif
@ -499,7 +493,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)new_min + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 4.2: returning %x\n", p);
FLUSH();
#endif
@ -519,7 +513,7 @@ void *PREFIX(malloc)(size_t req_size)
// CASE 5: Block full! Ensure next block and loop.
if (maj->next == NULL)
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 5: block full\n");
FLUSH();
#endif
@ -545,11 +539,11 @@ void *PREFIX(malloc)(size_t req_size)
liballoc_unlock(); // release the lock
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("All cases exhausted. No memory available.\n");
FLUSH();
#endif
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size);
liballoc_dump();
FLUSH();
@ -565,7 +559,7 @@ void PREFIX(free)(void *ptr)
if (ptr == NULL)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: PREFIX(free)( NULL ) called from %x\n",
__builtin_return_address(0));
FLUSH();
@ -590,7 +584,7 @@ void PREFIX(free)(void *ptr)
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)))
{
l_possibleOverruns += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
min->magic,
LIBALLOC_MAGIC);
@ -600,7 +594,7 @@ void PREFIX(free)(void *ptr)
if (min->magic == LIBALLOC_DEAD)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
ptr,
__builtin_return_address(0));
@ -609,7 +603,7 @@ void PREFIX(free)(void *ptr)
}
else
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
ptr,
__builtin_return_address(0));
@ -622,7 +616,7 @@ void PREFIX(free)(void *ptr)
return;
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: %x PREFIX(free)( %x ): ",
__builtin_return_address(0),
ptr);
@ -674,7 +668,7 @@ void PREFIX(free)(void *ptr)
}
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("OK\n");
FLUSH();
#endif
@ -734,7 +728,7 @@ void *PREFIX(realloc)(void *p, size_t size)
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)))
{
l_possibleOverruns += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
min->magic,
LIBALLOC_MAGIC);
@ -744,7 +738,7 @@ void *PREFIX(realloc)(void *p, size_t size)
if (min->magic == LIBALLOC_DEAD)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
ptr,
__builtin_return_address(0));
@ -753,7 +747,7 @@ void *PREFIX(realloc)(void *p, size_t size)
}
else
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
ptr,
__builtin_return_address(0));

View File

@ -1,7 +1,9 @@
#ifndef _LIBALLOC_H
#define _LIBALLOC_H
#include <types.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdio.h>
/** \defgroup ALLOCHOOKS liballoc hooks
*
@ -17,6 +19,7 @@
// typedef unsigned long uintptr_t;
// This lets you prefix malloc and friends
// #define PREFIX(func) k##func
#define PREFIX(func) __##func
#ifdef __cplusplus

View File

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2014 Marco Paland
Copyright (c) 2021 Eyal Rozenberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,20 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
void putchar_(char c) { putc(c, stdout); }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/**
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
* 2021-2022, Haifa, Palestine/Israel
* 2021-2023, Haifa, Palestine/Israel
* @author (c) Marco Paland (info@paland.com)
* 2014-2019, PALANDesign Hannover, Germany
*
@ -9,8 +9,8 @@
* or ask one of the authors.
*
* @brief Small stand-alone implementation of the printf family of functions
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with
* a very limited resources.
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
* with a very limited resources.
*
* @note the implementations are thread-safe; re-entrant; use no functions from
* the standard library; and do not dynamically allocate any memory.
@ -39,27 +39,40 @@
#ifndef PRINTF_H_
#define PRINTF_H_
#include <types.h>
#ifdef __cplusplus
#include <cstdarg>
#include <cstddef>
extern "C"
{
#else
#include <stdarg.h>
#include <stddef.h>
#endif
#ifdef __GNUC__
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4)
#define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(__printf__, (one_based_format_index), (first_arg))))
#define ATTR_VPRINTF(one_based_format_index) ATTR_PRINTF((one_based_format_index), 0)
__attribute__((format(gnu_printf, (one_based_format_index), (first_arg))))
#else
#define ATTR_PRINTF((one_based_format_index), (first_arg))
#define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(printf, (one_based_format_index), (first_arg))))
#endif
#define ATTR_VPRINTF(one_based_format_index) \
ATTR_PRINTF((one_based_format_index), 0)
#else
#define ATTR_PRINTF(one_based_format_index, first_arg)
#define ATTR_VPRINTF(one_based_format_index)
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 0
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define printf_ printf
#define sprintf_ sprintf
#define vsprintf_ vsprintf
@ -69,126 +82,153 @@ extern "C"
#endif
// If you want to include this implementation file directly rather than
// link against, this will let you control the functions' visibility,
// link against it, this will let you control the functions' visibility,
// e.g. make them static so as not to clash with other objects also
// using them.
#ifndef PRINTF_VISIBILITY
#define PRINTF_VISIBILITY __attribute__((visibility("default")))
#define PRINTF_VISIBILITY
#endif
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you must provide an
* implementation if you wish to use the @ref printf / @ref vprintf function (and possibly
* for linking against the library, if your toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system call on a Unix-like
* system, or even libc's @ref putchar , for replicating actual functionality of libc's @ref printf
* function; but on an embedded system it may involve interaction with a special output device,
* like a UART, etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended to support the
* representation of either a proper character or EOF in a variable - but this is really not
* meaningful to pass into @ref putchar and is discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
int putchar(int c);
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you
* must provide an implementation if you wish to use the @ref printf / @ref
* vprintf function (and possibly for linking against the library, if your
* toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system
* call on a Unix-like * system, or even libc's @ref putchar , for replicating
* actual functionality of libc's @ref printf * function; but on an embedded
* system it may involve interaction with a special output device, like a UART,
* etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended
* to support the representation of either a proper character or EOF in a
* variable - but this is really not meaningful to pass into @ref putchar and is
* discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
void putchar_(char c);
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function - it invokes @ref putchar_
* rather than directly performing any I/O (which insulates it from any dependence on the operating system
* and external libraries).
*
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in @p format string
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf(const char *format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf(const char *format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function -
* it invokes @ref putchar_ * rather than directly performing any I/O (which
* insulates it from any dependence on the operating system * and external
* libraries).
*
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf_(const char *format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf_(const char *format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer bounds), please consider using
* the size-constrained variant, @ref snprintf / @ref vsnprintf , instead.
*
* @param s An array in which to store the formatted string. It must be large enough to fit the formatted
* output!
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer
* bounds), please consider using the size-constrained variant, @ref snprintf /
* @ref vsnprintf, instead.
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit the formatted output!
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf_(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf_(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large enough to fit either the
* entire formatted output, or at least @p n characters. Alternatively, it can be NULL, in which case
* nothing will be printed, and only the number of characters which _could_ have been printed is
* tallied and returned.
* @param n The maximum number of characters to write to the array, including a terminating null character
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters that COULD have been written into @p s, not counting the terminating
* null character. A value equal or larger than @p n indicates truncation. Only when the returned value
* is non-negative and less than @p n, the null-terminated string has been fully and successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit either the entire formatted output, or at least @p n
* characters. Alternatively, it can be NULL, in which case nothing will
* be printed, and only the number of characters which _could_ have been
* printed is tallied and returned.
* @param n The maximum number of characters to write to the array, including
* a terminating null character
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters that COULD have been written into @p s, not
* counting the terminating null character. A value equal or larger than
* @p n indicates truncation. Only when the returned value is non-negative
* and less than @p n, the null-terminated string has been fully and
* successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf_(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf_(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified dynamically
* (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p out with each call
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters for which the output f unction was invoked, not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified
* dynamically (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased
* additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p
* out with each call
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters for which the output f unction was invoked,
* not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#ifdef __cplusplus
} // extern "C"
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#undef printf_
#undef sprintf_
#undef vsprintf_
#undef snprintf_
#undef vsnprintf_
#undef vprintf_
#else
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define printf printf_
#define sprintf sprintf_
#define vsprintf vsprintf_
#define snprintf snprintf_
#define vsnprintf vsnprintf_
#define vprintf vprintf_
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif // PRINTF_H_
#endif // PRINTF_H_

View File

@ -1,11 +0,0 @@
#include <setjmp.h>
PUBLIC int setjmp(jmp_buf env)
{
return 0;
}
PUBLIC __attribute__((noreturn)) void longjmp(jmp_buf env, int value)
{
_exit(value);
}

View File

@ -0,0 +1,26 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
export void __assert_fail(const char *file, int line, const char *func)
{
printf("assertion failed: %s:%d:%s\n", file, line, func);
abort();
}

View File

@ -1,29 +0,0 @@
#include <ctype.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
{
c -= 'A';
c += 'a';
}
return c;
}
PUBLIC int toupper(int c)
{
if (c >= 'a' && c <= 'z')
{
c -= 'a';
c += 'A';
}
return c;
}
PUBLIC int isspace(int c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v';
}

View File

@ -1,10 +1,212 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/types.h> // For PUBLIC
int __local_stub_errno = 0;
PUBLIC int *__errno_location(void)
__iptr __check_errno(__iptr status, __iptr err)
{
return &__local_stub_errno;
if (status >= EOK)
return status;
pthread_self()->CurrentError = status;
return err;
}
export int *__errno_location(void)
{
return &pthread_self()->CurrentError;
}
export char *strerror(int errnum)
{
if (errnum < 0)
errnum = -errnum;
if (errnum > __ERRNO_MAX)
return (char *)"Not a valid error number";
switch (errnum)
{
case EOK:
return (char *)"No error";
case E2BIG:
return (char *)"Argument list too long";
case EACCES:
return (char *)"Permission denied";
case EADDRINUSE:
return (char *)"Address in use";
case EADDRNOTAVAIL:
return (char *)"Address not available";
case EAFNOSUPPORT:
return (char *)"Address family not supported";
case EAGAIN:
return (char *)"Resource unavailable, try again";
case EALREADY:
return (char *)"Connection already in progress";
case EBADF:
return (char *)"Bad file descriptor";
case EBADMSG:
return (char *)"Bad message";
case EBUSY:
return (char *)"Device or resource busy";
case ECANCELED:
return (char *)"Operation canceled";
case ECHILD:
return (char *)"No child processes";
case ECONNABORTED:
return (char *)"Connection aborted";
case ECONNREFUSED:
return (char *)"Connection refused";
case ECONNRESET:
return (char *)"Connection reset";
case EDEADLK:
return (char *)"Resource deadlock would occur";
case EDESTADDRREQ:
return (char *)"Destination address required";
case EDOM:
return (char *)"Mathematics argument out of domain of function";
case EDQUOT:
return (char *)"Reserved";
case EEXIST:
return (char *)"File exists";
case EFAULT:
return (char *)"Bad address";
case EFBIG:
return (char *)"File too large";
case EHOSTUNREACH:
return (char *)"Host is unreachable";
case EIDRM:
return (char *)"Identifier removed";
case EILSEQ:
return (char *)"Illegal byte sequence";
case EINPROGRESS:
return (char *)"Operation in progress";
case EINTR:
return (char *)"Interrupted function";
case EINVAL:
return (char *)"Invalid argument";
case EIO:
return (char *)"I/O error";
case EISCONN:
return (char *)"Socket is connected";
case EISDIR:
return (char *)"Is a directory";
case ELOOP:
return (char *)"Too many levels of symbolic links";
case EMFILE:
return (char *)"File descriptor value too large";
case EMLINK:
return (char *)"Too many links";
case EMSGSIZE:
return (char *)"Message too large";
case EMULTIHOP:
return (char *)"Reserved";
case ENAMETOOLONG:
return (char *)"Filename too long";
case ENETDOWN:
return (char *)"Network is down";
case ENETRESET:
return (char *)"Connection aborted by network";
case ENETUNREACH:
return (char *)"Network unreachable";
case ENFILE:
return (char *)"Too many files open in system";
case ENOBUFS:
return (char *)"No buffer space available";
case ENODATA:
return (char *)"No message available on the STREAM head read queue";
case ENODEV:
return (char *)"No such device";
case ENOENT:
return (char *)"No such file or directory";
case ENOEXEC:
return (char *)"Executable file format error";
case ENOLCK:
return (char *)"No locks available";
case ENOLINK:
return (char *)"Reserved";
case ENOMEM:
return (char *)"Not enough space";
case ENOMSG:
return (char *)"No message of the desired type";
case ENOPROTOOPT:
return (char *)"Protocol not available";
case ENOSPC:
return (char *)"No space left on device";
case ENOSR:
return (char *)"No STREAM resources";
case ENOSTR:
return (char *)"Not a STREAM";
case ENOSYS:
return (char *)"Functionality not supported";
case ENOTCONN:
return (char *)"The socket is not connected";
case ENOTDIR:
return (char *)"Not a directory or a symbolic link to a directory";
case ENOTEMPTY:
return (char *)"Directory not empty";
case ENOTRECOVERABLE:
return (char *)"State not recoverable";
case ENOTSOCK:
return (char *)"Not a socket";
case ENOTSUP:
return (char *)"Not supported";
case ENOTTY:
return (char *)"Inappropriate I/O control operation";
case ENXIO:
return (char *)"No such device or address";
case EOPNOTSUPP:
return (char *)"Operation not supported on socket";
case EOVERFLOW:
return (char *)"Value too large to be stored in data type";
case EOWNERDEAD:
return (char *)"Previous owner died";
case EPERM:
return (char *)"Operation not permitted";
case EPIPE:
return (char *)"Broken pipe";
case EPROTO:
return (char *)"Protocol error";
case EPROTONOSUPPORT:
return (char *)"Protocol not supported";
case EPROTOTYPE:
return (char *)"Protocol wrong type for socket";
case ERANGE:
return (char *)"Result too large";
case EROFS:
return (char *)"Read-only file system";
case ESPIPE:
return (char *)"Invalid seek";
case ESRCH:
return (char *)"No such process";
case ESTALE:
return (char *)"Reserved";
case ETIME:
return (char *)"Stream ioctl() timeout";
case ETIMEDOUT:
return (char *)"Connection timed out";
case ETXTBSY:
return (char *)"Text file busy";
case EWOULDBLOCK:
return (char *)"Operation would block";
case EXDEV:
return (char *)"Cross-device link";
default:
return (char *)"Unknown error";
}
}

View File

@ -1,132 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC FILE *stdin = NULL;
PUBLIC FILE *stdout = NULL;
PUBLIC FILE *stderr = NULL;
PUBLIC FILE *freopen(const char *filename, const char *mode, FILE *stream)
{
errno = ENOSYS;
return NULL;
}
PUBLIC FILE *fopen(const char *filename, const char *mode)
{
int fd = syscall2(sc_open, (uint64_t)filename, (uint64_t)mode);
if (fd < 0)
return NULL;
FILE *FilePtr = malloc(sizeof(FILE));
FilePtr->_fileno = fd;
return FilePtr;
}
PUBLIC size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (ptr == NULL || stream == NULL || size == 0 || nmemb == 0)
{
errno = EINVAL;
return 0;
}
syscall3(sc_lseek, stream->_fileno, stream->_offset, SEEK_SET);
return syscall3(sc_read, (uint64_t)stream->_fileno, (uint64_t)ptr, size * nmemb);
}
PUBLIC size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (ptr == NULL || stream == NULL || size == 0 || nmemb == 0)
{
errno = EINVAL;
return 0;
}
syscall3(sc_lseek, stream->_fileno, stream->_offset, SEEK_SET);
return syscall3(sc_write, (uint64_t)stream->_fileno, (uint64_t)ptr, size * nmemb);
}
PUBLIC int fclose(FILE *fp)
{
if (fp == NULL)
{
errno = EINVAL;
return EOF;
}
return syscall1(sc_close, fp->_fileno);
}
PUBLIC off_t fseek(FILE *stream, off_t offset, int whence)
{
if (stream == NULL || whence < 0 || whence > 2)
{
errno = EINVAL;
return -1;
}
off_t new_offset = syscall3(sc_lseek, stream->_fileno, offset, whence);
if (new_offset < 0)
return -1;
stream->_offset = new_offset;
return new_offset;
}
PUBLIC long ftell(FILE *stream)
{
return stream->_offset;
}
PUBLIC int fflush(FILE *stream)
{
if (stream == NULL)
{
errno = EINVAL;
return EOF;
}
errno = ENOSYS;
return EOF;
}
PUBLIC int fprintf(FILE *stream, const char *format, ...)
{
if (stream == NULL || format == NULL)
{
errno = EINVAL;
return -1;
}
va_list args;
va_start(args, format);
const int ret = vfprintf(stream, format, args);
va_end(args);
return ret;
}
PUBLIC void setbuf(FILE *stream, char *buf)
{
}
PUBLIC int vfprintf(FILE *stream, const char *format, va_list arg)
{
return 0;
}
PUBLIC int vsscanf(const char *s, const char *format, va_list arg)
{
}
PUBLIC int sscanf(const char *s, const char *format, ...)
{
va_list args;
va_start(args, format);
const int ret = vsscanf(s, format, args);
va_end(args);
return ret;
}

View File

@ -1,9 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int fgetc(FILE *stream)
{
}

View File

@ -1,34 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int fputc(int c, FILE *stream)
{
// FIXME
// if (stream == NULL)
// {
// errno = EBADF;
// return EOF;
// }
char str[2] = {c, '\0'};
// return syscall3(sys_KernelCTL, KCTL_PRINT, str, 0);
}
PUBLIC int putc(int c, FILE *stream) { return fputc(c, stream); }
PUBLIC int fputs(const char *s, FILE *stream)
{
for (int i = 0; s[i] != '\0'; i++)
fputc(s[i], stream);
}
PUBLIC int puts(const char *s)
{
for (int i = 0; s[i] != '\0'; i++)
fputc(s[i], stdout);
}
PUBLIC int putchar(int c) { return fputc(c, stdout); }
PUBLIC void perror(const char *s) { fputs(s, stderr); }

View File

@ -1,87 +0,0 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <fennix/syscall.h>
#include "../mem/liballoc_1_1.h"
PUBLIC void abort(void)
{
syscall1(sc_exit, -0xAB057);
while (1)
;
}
PUBLIC int atexit(void (*function)(void))
{
return 1;
}
PUBLIC void exit(int status)
{
_exit(status);
}
PUBLIC int atoi(const char *nptr)
{
uint64_t Length = strlen((char *)nptr);
if (nptr)
while (nptr[Length] != '\0')
++Length;
uint64_t OutBuffer = 0;
uint64_t Power = 1;
for (uint64_t i = Length; i > 0; --i)
{
OutBuffer += (nptr[i - 1] - 48) * Power;
Power *= 10;
}
return OutBuffer;
}
PUBLIC char **environ = NULL;
PUBLIC char *getenv(const char *name)
{
char **env = environ;
if (env == NULL)
return NULL;
size_t len = strlen(name);
while (*env != NULL)
{
if ((strncmp(*env, name, len) == 0) && ((*env)[len] == '='))
return &(*env)[len + 1];
++env;
}
}
PUBLIC void *malloc(size_t Size) { return PREFIX(malloc)(Size); }
PUBLIC void *realloc(void *Address, size_t Size) { return PREFIX(realloc)(Address, Size); }
PUBLIC void *calloc(size_t Count, size_t Size) { return PREFIX(calloc)(Count, Size); }
PUBLIC void free(void *Address)
{
PREFIX(free)
(Address);
}
PUBLIC int system(const char *command)
{
return -1;
}
PUBLIC double atof(const char *nptr)
{
// FIXME: This is a very bad implementation of atof.
uint64_t Length = strlen((char *)nptr);
if (nptr)
while (nptr[Length] != '\0')
++Length;
double OutBuffer = 0;
double Power = 1;
for (uint64_t i = Length; i > 0; --i)
{
OutBuffer += (nptr[i - 1] - 48) * Power;
Power *= 10;
}
return OutBuffer;
}

View File

@ -0,0 +1,121 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <errno.h>
export int pthread_attr_destroy(pthread_attr_t *);
export int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
export int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
export int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
export int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
export int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
export int pthread_attr_getscope(const pthread_attr_t *, int *);
export int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
export int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
export int pthread_attr_init(pthread_attr_t *);
export int pthread_attr_setdetachstate(pthread_attr_t *, int);
export int pthread_attr_setguardsize(pthread_attr_t *, size_t);
export int pthread_attr_setinheritsched(pthread_attr_t *, int);
export int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
export int pthread_attr_setschedpolicy(pthread_attr_t *, int);
export int pthread_attr_setscope(pthread_attr_t *, int);
export int pthread_attr_setstackaddr(pthread_attr_t *, void *);
export int pthread_attr_setstacksize(pthread_attr_t *, size_t);
export int pthread_cancel(pthread_t);
export void pthread_cleanup_push(void (*)(void *), void *);
export void pthread_cleanup_pop(int);
export int pthread_cond_broadcast(pthread_cond_t *);
export int pthread_cond_destroy(pthread_cond_t *);
export int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
export int pthread_cond_signal(pthread_cond_t *);
export int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
export int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
export int pthread_condattr_destroy(pthread_condattr_t *);
export int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
export int pthread_condattr_init(pthread_condattr_t *);
export int pthread_condattr_setpshared(pthread_condattr_t *, int);
export int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
export int pthread_detach(pthread_t);
export int pthread_equal(pthread_t, pthread_t);
export void pthread_exit(void *);
export int pthread_getconcurrency(void);
export int pthread_getschedparam(pthread_t, int *, struct sched_param *);
export void *pthread_getspecific(pthread_key_t);
export int pthread_join(pthread_t, void **);
export int pthread_key_create(pthread_key_t *, void (*)(void *));
export int pthread_key_delete(pthread_key_t);
export int pthread_mutex_destroy(pthread_mutex_t *);
export int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
export int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
export int pthread_mutex_lock(pthread_mutex_t *mutex)
{
if (mutex->locked)
return EBUSY;
mutex->locked = 1;
return 0;
}
export int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
export int pthread_mutex_trylock(pthread_mutex_t *);
export int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
if (!mutex->locked)
return EPERM;
mutex->locked = 0;
return 0;
}
export int pthread_mutexattr_destroy(pthread_mutexattr_t *);
export int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_init(pthread_mutexattr_t *);
export int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
export int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
export int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
export int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
export int pthread_once(pthread_once_t *, void (*)(void));
export int pthread_rwlock_destroy(pthread_rwlock_t *);
export int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
export int pthread_rwlock_rdlock(pthread_rwlock_t *);
export int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
export int pthread_rwlock_trywrlock(pthread_rwlock_t *);
export int pthread_rwlock_unlock(pthread_rwlock_t *);
export int pthread_rwlock_wrlock(pthread_rwlock_t *);
export int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
export int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
export int pthread_rwlockattr_init(pthread_rwlockattr_t *);
export int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
export pthread_t pthread_self(void)
{
pthread_t tid;
__asm__ __volatile__("mov %%fs:0, %0"
: "=r"(tid));
return tid;
}
export int pthread_setcancelstate(int, int *);
export int pthread_setcanceltype(int, int *);
export int pthread_setconcurrency(int);
export int pthread_setschedparam(pthread_t, int, const struct sched_param *);
export int pthread_setspecific(pthread_key_t, const void *);
export void pthread_testcancel(void);

View File

@ -0,0 +1,47 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <signal.h>
export int kill(pid_t pid, int sig)
{
return syscall2(SYS_KILL, pid, sig);
}
export int killpg(pid_t, int);
export void psiginfo(const siginfo_t *, const char *);
export void psignal(int, const char *);
export int pthread_kill(pthread_t, int);
export int pthread_sigmask(int, const sigset_t *restrict, sigset_t *restrict);
export int raise(int);
export int sig2str(int, char *);
export int sigaction(int, const struct sigaction *restrict, struct sigaction *restrict);
export int sigaddset(sigset_t *, int);
export int sigaltstack(const stack_t *restrict, stack_t *restrict);
export int sigdelset(sigset_t *, int);
export int sigemptyset(sigset_t *);
export int sigfillset(sigset_t *);
export int sigismember(const sigset_t *, int);
export void (*signal(int, void (*)(int)))(int);
export int sigpending(sigset_t *);
export int sigprocmask(int, const sigset_t *restrict, sigset_t *restrict);
export int sigqueue(pid_t, int, union sigval);
export int sigsuspend(const sigset_t *);
export int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict);
export int sigwait(const sigset_t *restrict, int *restrict);
export int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
export int str2sig(const char *restrict, int *restrict);

View File

@ -1,17 +0,0 @@
#include <spawn.h>
int posix_spawn(pid_t *pid, const char *path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[])
{
}
int posix_spawnp(pid_t *pid, const char *file,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[])
{
}

View File

@ -1,13 +0,0 @@
#include <stdio.h>
#include "../../../Kernel/syscalls.h"
void __libc_init_std(void)
{
/* FIXME: Temporal workaround */
// int IsCritical = syscall1(_KernelCTL, 6 /* KCTL_IS_CRITICAL */);
}
void __libc_fini_std(void)
{
}

View File

@ -0,0 +1,343 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fennix/syscalls.h>
#include "../print/printf.h"
struct _IO_FILE *_i_open_files[256];
export FILE *stdin;
export FILE *stdout;
export FILE *stderr;
void __init_stdio(void)
{
stdin = malloc(sizeof(FILE));
stdin->fd = 0;
stdin->buffer = malloc(4096);
stdin->buffer_size = 4096;
stdin->buffer_pos = 0;
stdin->flags = _i_READ;
stdin->error = 0;
stdin->eof = 0;
stdout = malloc(sizeof(FILE));
stdout->fd = 1;
stdout->buffer = malloc(4096);
stdout->buffer_size = 4096;
stdout->buffer_pos = 0;
stdout->flags = _i_WRITE;
stdout->error = 0;
stdout->eof = 0;
stderr = malloc(sizeof(FILE));
stderr->fd = 2;
stderr->buffer = malloc(4096);
stderr->buffer_size = 4096;
stderr->buffer_pos = 0;
stderr->flags = _i_WRITE;
stderr->error = 0;
stderr->eof = 0;
_i_open_files[0] = stdin;
_i_open_files[1] = stdout;
_i_open_files[2] = stderr;
}
export void clearerr(FILE *);
export char *ctermid(char *);
export int dprintf(int, const char *restrict, ...);
export int fclose(FILE *stream)
{
if (!stream)
return EOF;
if (stream->buffer)
free(stream->buffer);
call_close(stream->fd);
_i_open_files[stream->fd] = NULL;
free(stream);
return 0;
}
export FILE *fdopen(int, const char *);
export int feof(FILE *);
export int ferror(FILE *);
export int fflush(FILE *stream)
{
if (!stream)
return EOF;
if (stream->flags & _i_WRITE)
{
if (stream->buffer_pos > 0)
{
ssize_t written = call_write(stream->fd, stream->buffer, stream->buffer_pos);
if (written < 0)
{
stream->error = 1;
return EOF;
}
stream->buffer_pos = 0;
}
}
else if (stream->flags & _i_READ)
{
stream->buffer_pos = 0;
stream->buffer_size = 0;
}
return 0;
}
export int fgetc(FILE *);
export int fgetpos(FILE *restrict, fpos_t *restrict);
export char *fgets(char *restrict, int, FILE *restrict);
export int fileno(FILE *);
export void flockfile(FILE *);
export FILE *fmemopen(void *restrict, size_t, const char *restrict);
export FILE *fopen(const char *restrict pathname, const char *restrict mode)
{
int flags = 0;
mode_t perm = 0;
if (strcmp(mode, "r") == 0)
flags = __SYS_O_RDONLY;
else if (strcmp(mode, "r+") == 0)
flags = __SYS_O_RDWR;
else if (strcmp(mode, "w") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "w+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "a") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_APPEND;
perm = 0644;
}
else if (strcmp(mode, "a+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_APPEND;
perm = 0644;
}
else
return NULL;
int fd = call_open(pathname, flags, perm);
if (fd < 0)
return NULL;
FILE *file = malloc(sizeof(FILE));
if (!file)
return NULL;
file->fd = fd;
file->buffer = malloc(4096);
file->buffer_size = 4096;
file->buffer_pos = 0;
file->flags = flags;
file->error = 0;
file->eof = 0;
_i_open_files[fd] = file;
return file;
}
export int fprintf(FILE *restrict, const char *restrict, ...);
export int fputc(int c, FILE *stream)
{
if (!stream || !(stream->flags & _i_WRITE))
return EOF;
stream->buffer[stream->buffer_pos++] = (char)c;
if (stream->buffer_pos >= stream->buffer_size)
{
if (fflush(stream) == EOF)
return EOF;
}
return (unsigned char)c;
}
export int fputs(const char *restrict s, FILE *restrict stream)
{
if (!stream || !(stream->flags & _i_WRITE))
return EOF;
while (*s)
{
if (fputc(*s++, stream) == EOF)
return EOF;
}
return 0;
}
export size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t total_bytes = size * nitems;
size_t bytes_read = 0;
while (bytes_read < total_bytes)
{
if (stream->buffer_pos >= stream->buffer_size)
{
int res = call_read(stream->fd, stream->buffer, stream->buffer_size);
if (res <= 0)
{
if (res == 0)
stream->eof = 1;
else
stream->error = 1;
break;
}
stream->buffer_pos = 0;
stream->buffer_size = res;
}
size_t bytes_to_copy = total_bytes - bytes_read;
size_t available = stream->buffer_size - stream->buffer_pos;
if (bytes_to_copy > available)
bytes_to_copy = available;
memcpy((char *)ptr + bytes_read, stream->buffer + stream->buffer_pos, bytes_to_copy);
stream->buffer_pos += bytes_to_copy;
bytes_read += bytes_to_copy;
}
return bytes_read / size;
}
export FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
export int fscanf(FILE *restrict, const char *restrict, ...);
export int fseek(FILE *stream, long offset, int whence)
{
int res = call_seek(stream->fd, offset, whence);
if (res < 0)
{
stream->error = 1;
return EOF;
}
stream->buffer_pos = 0;
stream->buffer_size = 0;
return 0;
}
export int fseeko(FILE *, off_t, int);
export int fsetpos(FILE *, const fpos_t *);
export long ftell(FILE *stream)
{
return call_tell(stream->fd);
}
export off_t ftello(FILE *);
export int ftrylockfile(FILE *);
export void funlockfile(FILE *);
export size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t total_bytes = size * nitems;
size_t bytes_written = 0;
while (bytes_written < total_bytes)
{
size_t bytes_to_copy = total_bytes - bytes_written;
size_t space_available = stream->buffer_size - stream->buffer_pos;
if (bytes_to_copy > space_available)
bytes_to_copy = space_available;
memcpy(stream->buffer + stream->buffer_pos, (const char *)ptr + bytes_written, bytes_to_copy);
stream->buffer_pos += bytes_to_copy;
bytes_written += bytes_to_copy;
if (stream->buffer_pos == stream->buffer_size)
{
if (call_write(stream->fd, stream->buffer, stream->buffer_size) != stream->buffer_size)
{
stream->error = 1;
break;
}
stream->buffer_pos = 0;
}
}
return bytes_written / size;
}
export int getc(FILE *);
export int getchar(void);
export int getc_unlocked(FILE *);
export int getchar_unlocked(void);
export ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
export ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
export FILE *open_memstream(char **, size_t *);
export int pclose(FILE *);
export void perror(const char *);
export FILE *popen(const char *, const char *);
export int printf(const char *restrict format, ...)
{
va_list args;
va_start(args, format);
int ret = vprintf_(format, args);
va_end(args);
return ret;
}
export int putc(int c, FILE *stream) { return fputc(c, stream); }
export int putchar(int c) { return putc(c, stdout); }
export int putc_unlocked(int c, FILE *stream) { return fputc(c, stream); }
export int putchar_unlocked(int c) { return putc_unlocked(c, stdout); }
export int puts(const char *s) { return fputs(s, stdout); }
export int remove(const char *);
export int rename(const char *, const char *);
export int renameat(int, const char *, int, const char *);
export void rewind(FILE *);
export int scanf(const char *restrict, ...);
export void setbuf(FILE *restrict, char *restrict);
export int setvbuf(FILE *restrict, char *restrict, int, size_t);
export int snprintf(char *restrict, size_t, const char *restrict, ...);
export int sprintf(char *restrict, const char *restrict, ...);
export int sscanf(const char *restrict, const char *restrict, ...);
export FILE *tmpfile(void);
export char *tmpnam(char *);
export int ungetc(int, FILE *);
export int vdprintf(int, const char *restrict, va_list);
export int vfprintf(FILE *restrict, const char *restrict, va_list);
export int vfscanf(FILE *restrict, const char *restrict, va_list);
export int vprintf(const char *restrict, va_list);
export int vscanf(const char *restrict, va_list);
export int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
export int vsprintf(char *restrict, const char *restrict, va_list);
export int vsscanf(const char *restrict, const char *restrict, va_list);

View File

@ -0,0 +1,105 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include "../mem/liballoc_1_1.h"
#define MAX_ATEXIT_FUNCS 32
typedef void (*atexit_func_t)(void);
static atexit_func_t __atexit_funcs[MAX_ATEXIT_FUNCS];
static int __num_atexit_funcs = 0;
export long a64l(const char *);
export _Noreturn void abort(void)
{
kill(getpid(), SIGABRT);
__builtin_unreachable();
}
export int abs(int);
export int atexit(void (*func)(void))
{
if (__num_atexit_funcs >= MAX_ATEXIT_FUNCS)
return -1;
__atexit_funcs[__num_atexit_funcs++] = func;
return 0;
}
export double atof(const char *);
export int atoi(const char *);
export long int atol(const char *);
export void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
export void *calloc(size_t, size_t);
export div_t div(int, int);
export double drand48(void);
export char *ecvt(double, int, int *, int *);
export double erand48(unsigned short int[3]);
export void exit(int status)
{
for (int i = __num_atexit_funcs - 1; i >= 0; --i)
__atexit_funcs[i]();
_exit(status);
__builtin_unreachable();
}
export char *fcvt(double, int, int *, int *);
export void free(void *ptr) { return PREFIX(free)(ptr); }
export char *gcvt(double, int, char *);
export char *getenv(const char *);
export int getsubopt(char **, char *const *, char **);
export int grantpt(int);
export char *initstate(unsigned int, char *, size_t);
export long int jrand48(unsigned short int[3]);
export char *l64a(long);
export long int labs(long int);
export void lcong48(unsigned short int[7]);
export ldiv_t ldiv(long int, long int);
export long int lrand48(void);
export void *malloc(size_t size) { return PREFIX(malloc)(size); }
export int mblen(const char *, size_t);
export size_t mbstowcs(wchar_t *, const char *, size_t);
export int mbtowc(wchar_t *, const char *, size_t);
export char *mktemp(char *);
export int mkstemp(char *);
export long int mrand48(void);
export long int nrand48(unsigned short int[3]);
export char *ptsname(int);
export int putenv(char *);
export void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
export int rand(void);
export int rand_r(unsigned int *);
export long random(void);
export void *realloc(void *, size_t);
export char *realpath(const char *, char *);
export unsigned short int seed48(unsigned short int[3]);
export void setkey(const char *);
export char *setstate(const char *);
export void srand(unsigned int);
export void srand48(long int);
export void srandom(unsigned);
export double strtod(const char *, char **);
export long int strtol(const char *, char **, int);
export unsigned long int strtoul(const char *, char **, int);
export int system(const char *);
export int ttyslot(void);
export int unlockpt(int);
export void *valloc(size_t);
export size_t wcstombs(char *, const wchar_t *, size_t);
export int wctomb(char *, wchar_t);

View File

@ -0,0 +1,86 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <string.h>
export void *memccpy(void *restrict, const void *restrict, int, size_t);
export void *memchr(const void *, int, size_t);
export int memcmp(const void *, const void *, size_t);
export void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
{
unsigned char *dest = (unsigned char *)s1;
const unsigned char *src = (const unsigned char *)s2;
while (n >= sizeof(unsigned long))
{
*(unsigned long *)dest = *(const unsigned long *)src;
dest += sizeof(unsigned long);
src += sizeof(unsigned long);
n -= sizeof(unsigned long);
}
while (n--)
*dest++ = *src++;
return s1;
}
export void *memmem(const void *, size_t, const void *, size_t);
export void *memmove(void *, const void *, size_t);
export void *memset(void *, int, size_t);
export char *stpcpy(char *restrict, const char *restrict);
export char *stpncpy(char *restrict, const char *restrict, size_t);
export char *strcat(char *restrict, const char *restrict);
export char *strchr(const char *, int);
export int strcmp(const char *s1, const char *s2)
{
while (*s1 && (*s1 == *s2))
{
s1++;
s2++;
}
return *(unsigned char *)s1 - *(unsigned char *)s2;
}
export int strcoll(const char *, const char *);
export int strcoll_l(const char *, const char *, locale_t);
export char *strcpy(char *restrict, const char *restrict);
export size_t strcspn(const char *, const char *);
export char *strdup(const char *);
export char *strerror(int);
export char *strerror_l(int, locale_t);
export int strerror_r(int, char *, size_t);
export size_t strlcat(char *restrict, const char *restrict, size_t);
export size_t strlcpy(char *restrict, const char *restrict, size_t);
export size_t strlen(const char *);
export char *strncat(char *restrict, const char *restrict, size_t);
export int strncmp(const char *, const char *, size_t);
export char *strncpy(char *restrict, const char *restrict, size_t);
export char *strndup(const char *, size_t);
export size_t strnlen(const char *, size_t);
export char *strpbrk(const char *, const char *);
export char *strrchr(const char *, int);
export char *strsignal(int);
export size_t strspn(const char *, const char *);
export char *strstr(const char *, const char *);
export char *strtok(char *restrict, const char *restrict);
export char *strtok_r(char *restrict, const char *restrict, char **restrict);
export size_t strxfrm(char *restrict, const char *restrict, size_t);
export size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);

View File

@ -1,346 +0,0 @@
#include <stddef.h>
#include <sys/types.h> // For PUBLIC
/* Some of the functions are from musl library */
/* https://www.musl-libc.org/ */
/*
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
PUBLIC void *memcpy(void *dest, const void *src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
#ifdef __GNUC__
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LS >>
#define RS <<
#else
#define LS <<
#define RS >>
#endif
typedef uint32_t __attribute__((__may_alias__)) u32;
uint32_t w, x;
for (; (uintptr_t)s % 4 && n; n--)
*d++ = *s++;
if ((uintptr_t)d % 4 == 0)
{
for (; n >= 16; s += 16, d += 16, n -= 16)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
*(u32 *)(d + 4) = *(u32 *)(s + 4);
*(u32 *)(d + 8) = *(u32 *)(s + 8);
*(u32 *)(d + 12) = *(u32 *)(s + 12);
}
if (n & 8)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
*(u32 *)(d + 4) = *(u32 *)(s + 4);
d += 8;
s += 8;
}
if (n & 4)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
d += 4;
s += 4;
}
if (n & 2)
{
*d++ = *s++;
*d++ = *s++;
}
if (n & 1)
{
*d = *s;
}
return dest;
}
if (n >= 32)
{
switch ((uintptr_t)d % 4)
{
case 1:
{
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
n -= 3;
for (; n >= 17; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 1);
*(u32 *)(d + 0) = (w LS 24) | (x RS 8);
w = *(u32 *)(s + 5);
*(u32 *)(d + 4) = (x LS 24) | (w RS 8);
x = *(u32 *)(s + 9);
*(u32 *)(d + 8) = (w LS 24) | (x RS 8);
w = *(u32 *)(s + 13);
*(u32 *)(d + 12) = (x LS 24) | (w RS 8);
}
break;
}
case 2:
{
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
n -= 2;
for (; n >= 18; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 2);
*(u32 *)(d + 0) = (w LS 16) | (x RS 16);
w = *(u32 *)(s + 6);
*(u32 *)(d + 4) = (x LS 16) | (w RS 16);
x = *(u32 *)(s + 10);
*(u32 *)(d + 8) = (w LS 16) | (x RS 16);
w = *(u32 *)(s + 14);
*(u32 *)(d + 12) = (x LS 16) | (w RS 16);
}
break;
}
case 3:
{
w = *(u32 *)s;
*d++ = *s++;
n -= 1;
for (; n >= 19; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 3);
*(u32 *)(d + 0) = (w LS 8) | (x RS 24);
w = *(u32 *)(s + 7);
*(u32 *)(d + 4) = (x LS 8) | (w RS 24);
x = *(u32 *)(s + 11);
*(u32 *)(d + 8) = (w LS 8) | (x RS 24);
w = *(u32 *)(s + 15);
*(u32 *)(d + 12) = (x LS 8) | (w RS 24);
}
break;
}
default:
break;
}
}
if (n & 16)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 8)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 4)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 2)
{
*d++ = *s++;
*d++ = *s++;
}
if (n & 1)
{
*d = *s;
}
return dest;
#endif
for (; n; n--)
*d++ = *s++;
return dest;
}
PUBLIC void *memset(void *dest, int c, size_t n)
{
unsigned char *s = dest;
size_t k;
if (!n)
return dest;
s[0] = c;
s[n - 1] = c;
if (n <= 2)
return dest;
s[1] = c;
s[2] = c;
s[n - 2] = c;
s[n - 3] = c;
if (n <= 6)
return dest;
s[3] = c;
s[n - 4] = c;
if (n <= 8)
return dest;
k = -(uintptr_t)s & 3;
s += k;
n -= k;
n &= -4;
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) u32;
typedef uint64_t __attribute__((__may_alias__)) u64;
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
*(u32 *)(s + 0) = c32;
*(u32 *)(s + n - 4) = c32;
if (n <= 8)
return dest;
*(u32 *)(s + 4) = c32;
*(u32 *)(s + 8) = c32;
*(u32 *)(s + n - 12) = c32;
*(u32 *)(s + n - 8) = c32;
if (n <= 24)
return dest;
*(u32 *)(s + 12) = c32;
*(u32 *)(s + 16) = c32;
*(u32 *)(s + 20) = c32;
*(u32 *)(s + 24) = c32;
*(u32 *)(s + n - 28) = c32;
*(u32 *)(s + n - 24) = c32;
*(u32 *)(s + n - 20) = c32;
*(u32 *)(s + n - 16) = c32;
k = 24 + ((uintptr_t)s & 4);
s += k;
n -= k;
u64 c64 = c32 | ((u64)c32 << 32);
for (; n >= 32; n -= 32, s += 32)
{
*(u64 *)(s + 0) = c64;
*(u64 *)(s + 8) = c64;
*(u64 *)(s + 16) = c64;
*(u64 *)(s + 24) = c64;
}
#else
for (; n; n--, s++)
*s = c;
#endif
return dest;
}
PUBLIC void *memmove(void *dest, const void *src, size_t n)
{
#ifdef __GNUC__
typedef __attribute__((__may_alias__)) size_t WT;
#define WS (sizeof(WT))
#endif
char *d = dest;
const char *s = src;
if (d == s)
return d;
if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n)
return memcpy(d, s, n);
if (d < s)
{
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
{
while ((uintptr_t)d % WS)
{
if (!n--)
return dest;
*d++ = *s++;
}
for (; n >= WS; n -= WS, d += WS, s += WS)
*(WT *)d = *(WT *)s;
}
#endif
for (; n; n--)
*d++ = *s++;
}
else
{
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
{
while ((uintptr_t)(d + n) % WS)
{
if (!n--)
return dest;
d[n] = s[n];
}
while (n >= WS)
n -= WS, *(WT *)(d + n) = *(WT *)(s + n);
}
#endif
while (n)
n--, d[n] = s[n];
}
return dest;
}

View File

@ -1,125 +0,0 @@
#include <string.h>
#include "../../mem/liballoc_1_1.h"
PUBLIC size_t strlen(const char *str)
{
long unsigned i = 0;
if (str)
while (str[i] != '\0')
++i;
return i;
}
PUBLIC int strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
PUBLIC int strncmp(const char *s1, const char *s2, size_t n)
{
for (size_t i = 0; i < n; i++)
{
char c1 = s1[i], c2 = s2[i];
if (c1 != c2)
return c1 - c2;
if (!c1)
return 0;
}
return 0;
}
PUBLIC int strcasecmp(const char *s1, const char *s2)
{
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
int result;
if (p1 == p2)
return 0;
while ((result = tolower(*p1) - tolower(*p2++)) == 0)
if (*p1++ == '\0')
break;
return result;
}
PUBLIC int strncasecmp(const char *string1, const char *string2, size_t count)
{
if (count)
{
const unsigned char *s1 = (const unsigned char *)string1;
const unsigned char *s2 = (const unsigned char *)string2;
int result;
do
{
if ((result = tolower(*s1) - tolower(*s2++)) != 0 || !*s1++)
break;
} while (--count);
return result;
}
return 0;
}
PUBLIC char *strstr(const char *haystack, const char *needle)
{
const char *a = haystack, *b = needle;
while (1)
{
if (!*b)
return (char *)haystack;
if (!*a)
return NULL;
if (*a++ != *b++)
{
a = ++haystack;
b = needle;
}
}
}
PUBLIC char *strncpy(char *destination, const char *source, unsigned long num)
{
if (destination == NULL)
return NULL;
char *ptr = destination;
while (*source && num--)
{
*destination = *source;
destination++;
source++;
}
*destination = '\0';
return ptr;
}
PUBLIC char *strdup(const char *s)
{
char *buf = (char *)__malloc(strlen((char *)s) + 1);
strncpy(buf, s, strlen(s) + 1);
return buf;
}
PUBLIC char *strchr(char const *s, int c)
{
size_t len = strlen(s);
for (size_t i = 0; i < len; i++)
if (s[i] == c)
return (char *)s + i;
return NULL;
}
PUBLIC char *strrchr(char const *s, int c)
{
size_t len = strlen(s);
size_t pos = len;
while (s[pos] != c && pos-- != 0)
;
if (pos == len)
return NULL;
return (char *)s + pos;
}

View File

@ -0,0 +1,49 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sys/mman.h>
#include <fennix/syscalls.h>
#include <errno.h>
export int mlock(const void *, size_t);
export int mlockall(int);
export void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
return (void *)__check_errno((__iptr)call_mmap(addr, len, prot, flags, fildes, off), (__iptr)MAP_FAILED);
}
export int mprotect(void *addr, size_t len, int prot)
{
return __check_errno(call_mprotect(addr, len, prot), -1);
}
export int msync(void *, size_t, int);
export int munlock(const void *, size_t);
export int munlockall(void);
export int munmap(void *addr, size_t len)
{
return __check_errno(call_munmap(addr, len), -1);
}
export int posix_madvise(void *, size_t, int);
export int posix_mem_offset(const void *restrict, size_t, off_t *restrict, size_t *restrict, int *restrict);
export int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
export int posix_typed_mem_open(const char *, int, int);
export int shm_open(const char *, int, mode_t);
export int shm_unlink(const char *);

View File

@ -1,14 +0,0 @@
#include <sys/wait.h>
PUBLIC pid_t wait(int *wstatus)
{
return waitpid(-1, &wstatus, 0);
}
PUBLIC pid_t waitpid(pid_t pid, int *wstatus, int options)
{
}
PUBLIC int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
{
}

View File

@ -1,18 +0,0 @@
#include <sys/stat.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int mkdir(const char *path, mode_t mode)
{
return 0;
}
PUBLIC int remove(const char *pathname)
{
return 0;
}
PUBLIC int rename(const char *oldpath, const char *newpath)
{
return 0;
}

View File

@ -1,51 +0,0 @@
#include <unistd.h>
#include <stddef.h>
#include <errno.h>
#include "../../../Kernel/syscalls.h"
PUBLIC int execl(const char *pathname, const char *arg, ...)
{
errno = ENOSYS;
return -1;
}
PUBLIC int execlp(const char *file, const char *arg, ...)
{
errno = ENOSYS;
return -1;
}
PUBLIC int execle(const char *pathname, const char *arg, ...)
{
errno = ENOSYS;
return -1;
}
PUBLIC int execv(const char *pathname, char *const argv[])
{
errno = ENOSYS;
return -1;
}
PUBLIC int execvp(const char *file, char *const argv[])
{
errno = ENOSYS;
return -1;
}
PUBLIC int execvpe(const char *file, char *const argv[], char *const envp[])
{
errno = ENOSYS;
return -1;
}
PUBLIC int execve(const char *pathname, char *const argv[], char *const envp[])
{
errno = ENOSYS;
return -1;
}
PUBLIC pid_t fork(void)
{
return syscall0(sc_fork);
}

View File

@ -1,14 +0,0 @@
#include <unistd.h>
#include <stddef.h>
#include <errno.h>
#include "../../../Kernel/syscalls.h"
PUBLIC unsigned int sleep(unsigned int seconds)
{
// return syscall1(sys_Sleep, seconds * 1000000);
}
PUBLIC int usleep(useconds_t usec)
{
// return syscall1(sys_Sleep, usec);
}

View File

@ -0,0 +1,112 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <fennix/syscalls.h>
export char *optarg;
export int optind, opterr, optopt;
export int access(const char *, int);
export unsigned int alarm(unsigned int);
export int brk(void *);
export int chdir(const char *);
export int chroot(const char *);
export int chown(const char *, uid_t, gid_t);
export int close(int);
export size_t confstr(int, char *, size_t);
export char *crypt(const char *, const char *);
export char *ctermid(char *);
export char *cuserid(char *s);
export int dup(int);
export int dup2(int, int);
export void encrypt(char[64], int);
export int execl(const char *, const char *, ...);
export int execle(const char *, const char *, ...);
export int execlp(const char *, const char *, ...);
export int execv(const char *, char *const[]);
export int execve(const char *, char *const[], char *const[]);
export int execvp(const char *, char *const[]);
export void _exit(int);
export int fchown(int, uid_t, gid_t);
export int fchdir(int);
export int fdatasync(int);
export pid_t fork(void);
export long int fpathconf(int, int);
export int fsync(int);
export int ftruncate(int, off_t);
export char *getcwd(char *, size_t);
export int getdtablesize(void);
export gid_t getegid(void);
export uid_t geteuid(void);
export gid_t getgid(void);
export int getgroups(int, gid_t[]);
export long gethostid(void);
export char *getlogin(void);
export int getlogin_r(char *, size_t);
export int getopt(int, char *const[], const char *);
export int getpagesize(void) { return 0x1000; } /* TODO: getpagesize */
export char *getpass(const char *);
export pid_t getpgid(pid_t);
export pid_t getpgrp(void);
export pid_t getpid(void) { return syscall0(SYS_GETPID); }
export pid_t getppid(void) { return syscall0(SYS_GETPPID); }
export pid_t getsid(pid_t);
export uid_t getuid(void);
export char *getwd(char *);
export int isatty(int);
export int lchown(const char *, uid_t, gid_t);
export int link(const char *, const char *);
export int lockf(int, int, off_t);
export off_t lseek(int, off_t, int);
export int nice(int);
export long int pathconf(const char *, int);
export int pause(void);
export int pipe(int[2]);
export ssize_t pread(int, void *, size_t, off_t);
export int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
export ssize_t pwrite(int, const void *, size_t, off_t);
export ssize_t read(int, void *, size_t);
export int readlink(const char *, char *, size_t);
export int rmdir(const char *);
export void *sbrk(intptr_t);
export int setgid(gid_t);
export int setpgid(pid_t, pid_t);
export pid_t setpgrp(void);
export int setregid(gid_t, gid_t);
export int setreuid(uid_t, uid_t);
export pid_t setsid(void);
export int setuid(uid_t);
export unsigned int sleep(unsigned int);
export void swab(const void *, void *, ssize_t);
export int symlink(const char *, const char *);
export void sync(void);
export long int sysconf(int);
export pid_t tcgetpgrp(int);
export int tcsetpgrp(int, pid_t);
export int truncate(const char *, off_t);
export char *ttyname(int);
export int ttyname_r(int, char *, size_t);
export useconds_t ualarm(useconds_t, useconds_t);
export int unlink(const char *);
export int usleep(useconds_t);
export pid_t vfork(void);
export ssize_t write(int, const void *, size_t);

View File

@ -0,0 +1,60 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
static_assert(__SYS_PROT_READ == PROT_READ);
static_assert(__SYS_PROT_WRITE == PROT_WRITE);
static_assert(__SYS_PROT_EXEC == PROT_EXEC);
static_assert(__SYS_PROT_NONE == PROT_NONE);
static_assert(__SYS_MAP_SHARED == MAP_SHARED);
static_assert(__SYS_MAP_PRIVATE == MAP_PRIVATE);
static_assert(__SYS_MAP_FIXED == MAP_FIXED);
static_assert(__SYS_MAP_ANONYMOUS == MAP_ANONYMOUS);
static_assert(__SYS_MAP_ANON == MAP_ANON);
static_assert(__SYS_F_OK == F_OK);
static_assert(__SYS_R_OK == R_OK);
static_assert(__SYS_W_OK == W_OK);
static_assert(__SYS_X_OK == X_OK);
static_assert(sizeof(__SYS_clockid_t) == sizeof(clockid_t));
// static_assert(sizeof(__SYS_socklen_t) == sizeof(socklen_t));
static_assert(__SYS_SEEK_SET == SEEK_SET);
static_assert(__SYS_SEEK_CUR == SEEK_CUR);
static_assert(__SYS_SEEK_END == SEEK_END);
static_assert(__SYS_SA_NOCLDSTOP == SA_NOCLDSTOP);
static_assert(__SYS_SA_NOCLDWAIT == SA_NOCLDWAIT);
static_assert(__SYS_SA_SIGINFO == SA_SIGINFO);
static_assert(__SYS_SA_ONSTACK == SA_ONSTACK);
static_assert(__SYS_SA_RESTART == SA_RESTART);
static_assert(__SYS_SA_NODEFER == SA_NODEFER);
static_assert(__SYS_SA_RESETHAND == SA_RESETHAND);
static_assert(__SYS_CLOCK_MONOTONIC == CLOCK_MONOTONIC);
static_assert(__SYS_CLOCK_PROCESS_CPUTIME_ID == CLOCK_PROCESS_CPUTIME_ID);
static_assert(__SYS_CLOCK_REALTIME == CLOCK_REALTIME);
static_assert(__SYS_CLOCK_THREAD_CPUTIME_ID == CLOCK_THREAD_CPUTIME_ID);
// static_assert( == );

41
Userspace/libc/src/tls.c Normal file
View File

@ -0,0 +1,41 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <sys/types.h>
#include <inttypes.h>
#include <stddef.h>
#include <fennix/syscalls.h>
export __attribute__((naked, used, no_stack_protector)) void *__tls_get_addr(void *__data)
{
__asm__("ud2");
}
int __init_pthread(void)
{
__pthread *ptr = (__pthread *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
-1, 0);
call_prctl(__SYS_SET_FS, ptr, 0, 0, 0);
ptr->Self = ptr;
ptr->CurrentError = 0;
return 0;
}