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

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