mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-30 08:17:58 +00:00
feat(userspace/libc): complete <string.h> implementation
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
parent
2ae18af9a0
commit
4bb8ce6d00
@ -19,6 +19,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fennix/syscalls.h>
|
#include <fennix/syscalls.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
export void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n)
|
export void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n)
|
||||||
{
|
{
|
||||||
@ -145,15 +147,17 @@ export char *stpcpy(char *restrict s1, const char *restrict s2)
|
|||||||
|
|
||||||
export char *stpncpy(char *restrict s1, const char *restrict s2, size_t n)
|
export char *stpncpy(char *restrict s1, const char *restrict s2, size_t n)
|
||||||
{
|
{
|
||||||
char *dest = s1;
|
for (int i = 0; i < n; ++i)
|
||||||
while (n && (*dest++ = *s2++))
|
{
|
||||||
n--;
|
char buf = s2[i];
|
||||||
|
s1[i] = buf;
|
||||||
if (n)
|
if (buf != '\0')
|
||||||
while (--n)
|
continue;
|
||||||
*dest++ = '\0';
|
for (int j = i + 1; j < n; ++j)
|
||||||
|
s1[j] = '\0';
|
||||||
return dest - 1;
|
return s1 + i;
|
||||||
|
}
|
||||||
|
return s1 + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strcat(char *restrict s1, const char *restrict s2)
|
export char *strcat(char *restrict s1, const char *restrict s2)
|
||||||
@ -239,172 +243,173 @@ export char *strdup(const char *s)
|
|||||||
return new_str;
|
return new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
export char *strerror(int errnum)
|
/* already defined in src/std/errno.c */
|
||||||
{
|
// export char *strerror(int errnum)
|
||||||
static char unknown_error[32];
|
// {
|
||||||
switch (errnum)
|
// static char unknown_error[32];
|
||||||
{
|
// switch (errnum)
|
||||||
case 0:
|
// {
|
||||||
return "No error";
|
// case 0:
|
||||||
case E2BIG:
|
// return "No error";
|
||||||
return "Argument list too long";
|
// case E2BIG:
|
||||||
case EACCES:
|
// return "Argument list too long";
|
||||||
return "Permission denied";
|
// case EACCES:
|
||||||
case EADDRINUSE:
|
// return "Permission denied";
|
||||||
return "Address in use";
|
// case EADDRINUSE:
|
||||||
case EADDRNOTAVAIL:
|
// return "Address in use";
|
||||||
return "Address not available";
|
// case EADDRNOTAVAIL:
|
||||||
case EAFNOSUPPORT:
|
// return "Address not available";
|
||||||
return "Address family not supported";
|
// case EAFNOSUPPORT:
|
||||||
case EAGAIN:
|
// return "Address family not supported";
|
||||||
return "Resource temporarily unavailable";
|
// case EAGAIN:
|
||||||
case EALREADY:
|
// return "Resource temporarily unavailable";
|
||||||
return "Connection already in progress";
|
// case EALREADY:
|
||||||
case EBADF:
|
// return "Connection already in progress";
|
||||||
return "Bad file descriptor";
|
// case EBADF:
|
||||||
case EBADMSG:
|
// return "Bad file descriptor";
|
||||||
return "Bad message";
|
// case EBADMSG:
|
||||||
case EBUSY:
|
// return "Bad message";
|
||||||
return "Resource busy";
|
// case EBUSY:
|
||||||
case ECANCELED:
|
// return "Resource busy";
|
||||||
return "Operation canceled";
|
// case ECANCELED:
|
||||||
case ECHILD:
|
// return "Operation canceled";
|
||||||
return "No child process";
|
// case ECHILD:
|
||||||
case ECONNABORTED:
|
// return "No child process";
|
||||||
return "Connection aborted";
|
// case ECONNABORTED:
|
||||||
case ECONNREFUSED:
|
// return "Connection aborted";
|
||||||
return "Connection refused";
|
// case ECONNREFUSED:
|
||||||
case ECONNRESET:
|
// return "Connection refused";
|
||||||
return "Connection reset";
|
// case ECONNRESET:
|
||||||
case EDEADLK:
|
// return "Connection reset";
|
||||||
return "Resource deadlock would occur";
|
// case EDEADLK:
|
||||||
case EDESTADDRREQ:
|
// return "Resource deadlock would occur";
|
||||||
return "Destination address required";
|
// case EDESTADDRREQ:
|
||||||
case EDOM:
|
// return "Destination address required";
|
||||||
return "Domain error";
|
// case EDOM:
|
||||||
case EEXIST:
|
// return "Domain error";
|
||||||
return "File exists";
|
// case EEXIST:
|
||||||
case EFAULT:
|
// return "File exists";
|
||||||
return "Bad address";
|
// case EFAULT:
|
||||||
case EFBIG:
|
// return "Bad address";
|
||||||
return "File too large";
|
// case EFBIG:
|
||||||
case EHOSTUNREACH:
|
// return "File too large";
|
||||||
return "Host is unreachable";
|
// case EHOSTUNREACH:
|
||||||
case EIDRM:
|
// return "Host is unreachable";
|
||||||
return "Identifier removed";
|
// case EIDRM:
|
||||||
case EILSEQ:
|
// return "Identifier removed";
|
||||||
return "Illegal byte sequence";
|
// case EILSEQ:
|
||||||
case EINPROGRESS:
|
// return "Illegal byte sequence";
|
||||||
return "Operation in progress";
|
// case EINPROGRESS:
|
||||||
case EINTR:
|
// return "Operation in progress";
|
||||||
return "Interrupted function call";
|
// case EINTR:
|
||||||
case EINVAL:
|
// return "Interrupted function call";
|
||||||
return "Invalid argument";
|
// case EINVAL:
|
||||||
case EIO:
|
// return "Invalid argument";
|
||||||
return "Input/output error";
|
// case EIO:
|
||||||
case EISCONN:
|
// return "Input/output error";
|
||||||
return "Socket is connected";
|
// case EISCONN:
|
||||||
case EISDIR:
|
// return "Socket is connected";
|
||||||
return "Is a directory";
|
// case EISDIR:
|
||||||
case ELOOP:
|
// return "Is a directory";
|
||||||
return "Symbolic link loop";
|
// case ELOOP:
|
||||||
case EMFILE:
|
// return "Symbolic link loop";
|
||||||
return "File descriptor value too large or too many open streams";
|
// case EMFILE:
|
||||||
case EMLINK:
|
// return "File descriptor value too large or too many open streams";
|
||||||
return "Too many links";
|
// case EMLINK:
|
||||||
case EMSGSIZE:
|
// return "Too many links";
|
||||||
return "Message too large";
|
// case EMSGSIZE:
|
||||||
case ENAMETOOLONG:
|
// return "Message too large";
|
||||||
return "Filename too long";
|
// case ENAMETOOLONG:
|
||||||
case ENETDOWN:
|
// return "Filename too long";
|
||||||
return "Network is down";
|
// case ENETDOWN:
|
||||||
case ENETRESET:
|
// return "Network is down";
|
||||||
return "The connection was aborted by the network";
|
// case ENETRESET:
|
||||||
case ENETUNREACH:
|
// return "The connection was aborted by the network";
|
||||||
return "Network unreachable";
|
// case ENETUNREACH:
|
||||||
case ENFILE:
|
// return "Network unreachable";
|
||||||
return "Too many files open in system";
|
// case ENFILE:
|
||||||
case ENOBUFS:
|
// return "Too many files open in system";
|
||||||
return "No buffer space available";
|
// case ENOBUFS:
|
||||||
case ENODATA:
|
// return "No buffer space available";
|
||||||
return "No message available";
|
// case ENODATA:
|
||||||
case ENODEV:
|
// return "No message available";
|
||||||
return "No such device";
|
// case ENODEV:
|
||||||
case ENOENT:
|
// return "No such device";
|
||||||
return "No such file or directory";
|
// case ENOENT:
|
||||||
case ENOEXEC:
|
// return "No such file or directory";
|
||||||
return "Executable file format error";
|
// case ENOEXEC:
|
||||||
case ENOLCK:
|
// return "Executable file format error";
|
||||||
return "No locks available";
|
// case ENOLCK:
|
||||||
case ENOMEM:
|
// return "No locks available";
|
||||||
return "Not enough space";
|
// case ENOMEM:
|
||||||
case ENOMSG:
|
// return "Not enough space";
|
||||||
return "No message of the desired type";
|
// case ENOMSG:
|
||||||
case ENOPROTOOPT:
|
// return "No message of the desired type";
|
||||||
return "Protocol not available";
|
// case ENOPROTOOPT:
|
||||||
case ENOSPC:
|
// return "Protocol not available";
|
||||||
return "No space left on device";
|
// case ENOSPC:
|
||||||
case ENOSR:
|
// return "No space left on device";
|
||||||
return "No STREAM resources";
|
// case ENOSR:
|
||||||
case ENOSTR:
|
// return "No STREAM resources";
|
||||||
return "Not a STREAM";
|
// case ENOSTR:
|
||||||
case ENOSYS:
|
// return "Not a STREAM";
|
||||||
return "Functionality not supported";
|
// case ENOSYS:
|
||||||
case ENOTCONN:
|
// return "Functionality not supported";
|
||||||
return "Socket not connected";
|
// case ENOTCONN:
|
||||||
case ENOTDIR:
|
// return "Socket not connected";
|
||||||
return "Not a directory";
|
// case ENOTDIR:
|
||||||
case ENOTEMPTY:
|
// return "Not a directory";
|
||||||
return "Directory not empty";
|
// case ENOTEMPTY:
|
||||||
case ENOTRECOVERABLE:
|
// return "Directory not empty";
|
||||||
return "State not recoverable";
|
// case ENOTRECOVERABLE:
|
||||||
case ENOTSOCK:
|
// return "State not recoverable";
|
||||||
return "Not a socket";
|
// case ENOTSOCK:
|
||||||
case ENOTSUP:
|
// return "Not a socket";
|
||||||
return "Not supported";
|
// case ENOTSUP:
|
||||||
case ENOTTY:
|
// return "Not supported";
|
||||||
return "Inappropriate I/O control operation";
|
// case ENOTTY:
|
||||||
case ENXIO:
|
// return "Inappropriate I/O control operation";
|
||||||
return "No such device or address";
|
// case ENXIO:
|
||||||
case EOPNOTSUPP:
|
// return "No such device or address";
|
||||||
return "Operation not supported on socket";
|
// case EOPNOTSUPP:
|
||||||
case EOVERFLOW:
|
// return "Operation not supported on socket";
|
||||||
return "Value too large to be stored in data type";
|
// case EOVERFLOW:
|
||||||
case EOWNERDEAD:
|
// return "Value too large to be stored in data type";
|
||||||
return "Previous owner died";
|
// case EOWNERDEAD:
|
||||||
case EPERM:
|
// return "Previous owner died";
|
||||||
return "Operation not permitted";
|
// case EPERM:
|
||||||
case EPIPE:
|
// return "Operation not permitted";
|
||||||
return "Broken pipe";
|
// case EPIPE:
|
||||||
case EPROTO:
|
// return "Broken pipe";
|
||||||
return "Protocol error";
|
// case EPROTO:
|
||||||
case EPROTONOSUPPORT:
|
// return "Protocol error";
|
||||||
return "Protocol not supported";
|
// case EPROTONOSUPPORT:
|
||||||
case EPROTOTYPE:
|
// return "Protocol not supported";
|
||||||
return "Protocol wrong type for socket";
|
// case EPROTOTYPE:
|
||||||
case ERANGE:
|
// return "Protocol wrong type for socket";
|
||||||
return "Result too large";
|
// case ERANGE:
|
||||||
case EROFS:
|
// return "Result too large";
|
||||||
return "Read-only file system";
|
// case EROFS:
|
||||||
case ESPIPE:
|
// return "Read-only file system";
|
||||||
return "Invalid seek";
|
// case ESPIPE:
|
||||||
case ESRCH:
|
// return "Invalid seek";
|
||||||
return "No such process";
|
// case ESRCH:
|
||||||
case ETIME:
|
// return "No such process";
|
||||||
return "STREAM ioctl() timeout";
|
// case ETIME:
|
||||||
case ETIMEDOUT:
|
// return "STREAM ioctl() timeout";
|
||||||
return "Connection timed out";
|
// case ETIMEDOUT:
|
||||||
case ETXTBSY:
|
// return "Connection timed out";
|
||||||
return "Text file busy";
|
// case ETXTBSY:
|
||||||
case EWOULDBLOCK:
|
// return "Text file busy";
|
||||||
return "Operation would block";
|
// case EWOULDBLOCK:
|
||||||
case EXDEV:
|
// return "Operation would block";
|
||||||
return "Improper link";
|
// case EXDEV:
|
||||||
default:
|
// return "Improper link";
|
||||||
snprintf(unknown_error, sizeof(unknown_error), "Unknown error %d", errnum);
|
// default:
|
||||||
return unknown_error;
|
// snprintf(unknown_error, sizeof(unknown_error), "Unknown error %d", errnum);
|
||||||
}
|
// return unknown_error;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
export char *strerror_l(int errnum, locale_t locale);
|
export char *strerror_l(int errnum, locale_t locale);
|
||||||
|
|
||||||
@ -558,66 +563,66 @@ export char *strsignal(int signum)
|
|||||||
{
|
{
|
||||||
switch (signum)
|
switch (signum)
|
||||||
{
|
{
|
||||||
case __SYS_SIGNULL:
|
case SIGNULL:
|
||||||
return "NULL signal";
|
return "NULL signal";
|
||||||
case __SYS_SIGABRT:
|
case SIGABRT:
|
||||||
return "Aborted";
|
return "Aborted";
|
||||||
case __SYS_SIGALRM:
|
case SIGALRM:
|
||||||
return "Alarm clock";
|
return "Alarm clock";
|
||||||
case __SYS_SIGBUS:
|
case SIGBUS:
|
||||||
return "Bus error";
|
return "Bus error";
|
||||||
case __SYS_SIGCHLD:
|
case SIGCHLD:
|
||||||
return "Child status changed";
|
return "Child status changed";
|
||||||
case __SYS_SIGCONT:
|
case SIGCONT:
|
||||||
return "Continued";
|
return "Continued";
|
||||||
case __SYS_SIGFPE:
|
case SIGFPE:
|
||||||
return "Arithmetic exception";
|
return "Arithmetic exception";
|
||||||
case __SYS_SIGHUP:
|
case SIGHUP:
|
||||||
return "Hangup";
|
return "Hangup";
|
||||||
case __SYS_SIGILL:
|
case SIGILL:
|
||||||
return "Illegal instruction";
|
return "Illegal instruction";
|
||||||
case __SYS_SIGINT:
|
case SIGINT:
|
||||||
return "Interrupt";
|
return "Interrupt";
|
||||||
case __SYS_SIGKILL:
|
case SIGKILL:
|
||||||
return "Killed";
|
return "Killed";
|
||||||
case __SYS_SIGPIPE:
|
case SIGPIPE:
|
||||||
return "Broken pipe";
|
return "Broken pipe";
|
||||||
case __SYS_SIGQUIT:
|
case SIGQUIT:
|
||||||
return "Quit";
|
return "Quit";
|
||||||
case __SYS_SIGSEGV:
|
case SIGSEGV:
|
||||||
return "Segmentation fault";
|
return "Segmentation fault";
|
||||||
case __SYS_SIGSTOP:
|
case SIGSTOP:
|
||||||
return "Stopped (signal)";
|
return "Stopped (signal)";
|
||||||
case __SYS_SIGTERM:
|
case SIGTERM:
|
||||||
return "Terminated";
|
return "Terminated";
|
||||||
case __SYS_SIGTSTP:
|
case SIGTSTP:
|
||||||
return "Stopped (user)";
|
return "Stopped (user)";
|
||||||
case __SYS_SIGTTIN:
|
case SIGTTIN:
|
||||||
return "Stopped (tty input)";
|
return "Stopped (tty input)";
|
||||||
case __SYS_SIGTTOU:
|
case SIGTTOU:
|
||||||
return "Stopped (tty output)";
|
return "Stopped (tty output)";
|
||||||
case __SYS_SIGUSR1:
|
case SIGUSR1:
|
||||||
return "User defined signal 1";
|
return "User defined signal 1";
|
||||||
case __SYS_SIGUSR2:
|
case SIGUSR2:
|
||||||
return "User defined signal 2";
|
return "User defined signal 2";
|
||||||
case __SYS_SIGPOLL:
|
case SIGPOLL:
|
||||||
return "Pollable event occurred";
|
return "Pollable event occurred";
|
||||||
case __SYS_SIGPROF:
|
case SIGPROF:
|
||||||
return "Profiling timer expired";
|
return "Profiling timer expired";
|
||||||
case __SYS_SIGSYS:
|
case SIGSYS:
|
||||||
return "Bad system call";
|
return "Bad system call";
|
||||||
case __SYS_SIGTRAP:
|
case SIGTRAP:
|
||||||
return "Trace/breakpoint trap";
|
return "Trace/breakpoint trap";
|
||||||
case __SYS_SIGURG:
|
case SIGURG:
|
||||||
return "Urgent I/O condition";
|
return "Urgent I/O condition";
|
||||||
case __SYS_SIGVTALRM:
|
case SIGVTALRM:
|
||||||
return "Virtual timer expired";
|
return "Virtual timer expired";
|
||||||
case __SYS_SIGXCPU:
|
case SIGXCPU:
|
||||||
return "CPU time limit exceeded";
|
return "CPU time limit exceeded";
|
||||||
case __SYS_SIGXFSZ:
|
case SIGXFSZ:
|
||||||
return "File size limit exceeded";
|
return "File size limit exceeded";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return "Unknown signal";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user