user: implement mlibc as the libc, finally.
It's finally done.. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <bits/ensure.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <mlibc/debug.hpp>
|
||||
|
||||
char *strdup(const char *string) {
|
||||
auto num_bytes = strlen(string);
|
||||
|
||||
char *new_string = (char *)malloc(num_bytes + 1);
|
||||
if(!new_string) // TODO: set errno
|
||||
return nullptr;
|
||||
|
||||
memcpy(new_string, string, num_bytes);
|
||||
new_string[num_bytes] = 0;
|
||||
return new_string;
|
||||
}
|
||||
|
||||
char *strndup(const char *string, size_t max_size) {
|
||||
auto num_bytes = strnlen(string, max_size);
|
||||
char *new_string = (char *)malloc(num_bytes + 1);
|
||||
if(!new_string) // TODO: set errno
|
||||
return nullptr;
|
||||
|
||||
memcpy(new_string, string, num_bytes);
|
||||
new_string[num_bytes] = 0;
|
||||
return new_string;
|
||||
}
|
||||
|
||||
char *stpcpy(char *__restrict dest, const char *__restrict src) {
|
||||
auto n = strlen(src);
|
||||
memcpy(dest, src, n + 1);
|
||||
return dest + n;
|
||||
}
|
||||
|
||||
char *stpncpy(char *__restrict dest, const char *__restrict src, size_t n) {
|
||||
size_t nulls, copied, srcLen = strlen(src);
|
||||
if (n >= srcLen) {
|
||||
nulls = n - srcLen;
|
||||
copied = srcLen;
|
||||
} else {
|
||||
nulls = 0;
|
||||
copied = n;
|
||||
}
|
||||
|
||||
memcpy(dest, src, copied);
|
||||
memset(dest + srcLen, 0, nulls);
|
||||
return dest + n - nulls;
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t n) {
|
||||
size_t len = 0;
|
||||
while(len < n && s[len])
|
||||
++len;
|
||||
return len;
|
||||
}
|
||||
|
||||
char *strsep(char **m, const char *del) {
|
||||
__ensure(m);
|
||||
|
||||
auto tok = *m;
|
||||
if(!tok)
|
||||
return nullptr;
|
||||
|
||||
// Replace the following delimiter by a null-terminator.
|
||||
// After this loop: *p is null iff we reached the end of the string.
|
||||
auto p = tok;
|
||||
while(*p && !strchr(del, *p))
|
||||
p++;
|
||||
|
||||
if(*p) {
|
||||
*p = 0;
|
||||
*m = p + 1;
|
||||
}else{
|
||||
*m = nullptr;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
char *strsignal(int sig) {
|
||||
#define CASE_FOR(sigconst) case sigconst: s = #sigconst; break;
|
||||
const char *s;
|
||||
switch(sig) {
|
||||
CASE_FOR(SIGABRT)
|
||||
CASE_FOR(SIGFPE)
|
||||
CASE_FOR(SIGILL)
|
||||
CASE_FOR(SIGINT)
|
||||
CASE_FOR(SIGSEGV)
|
||||
CASE_FOR(SIGTERM)
|
||||
CASE_FOR(SIGPROF)
|
||||
CASE_FOR(SIGIO)
|
||||
CASE_FOR(SIGPWR)
|
||||
CASE_FOR(SIGALRM)
|
||||
CASE_FOR(SIGBUS)
|
||||
CASE_FOR(SIGCHLD)
|
||||
CASE_FOR(SIGCONT)
|
||||
CASE_FOR(SIGHUP)
|
||||
CASE_FOR(SIGKILL)
|
||||
CASE_FOR(SIGPIPE)
|
||||
CASE_FOR(SIGQUIT)
|
||||
CASE_FOR(SIGSTOP)
|
||||
CASE_FOR(SIGTSTP)
|
||||
CASE_FOR(SIGTTIN)
|
||||
CASE_FOR(SIGTTOU)
|
||||
CASE_FOR(SIGUSR1)
|
||||
CASE_FOR(SIGUSR2)
|
||||
CASE_FOR(SIGSYS)
|
||||
CASE_FOR(SIGTRAP)
|
||||
CASE_FOR(SIGURG)
|
||||
CASE_FOR(SIGVTALRM)
|
||||
CASE_FOR(SIGXCPU)
|
||||
CASE_FOR(SIGXFSZ)
|
||||
CASE_FOR(SIGWINCH)
|
||||
default:
|
||||
mlibc::infoLogger() << "mlibc: Unknown signal number " << sig << frg::endlog;
|
||||
s = "Unknown signal number";
|
||||
}
|
||||
return const_cast<char *>(s);
|
||||
}
|
||||
|
||||
char *strcasestr(const char *s, const char *pattern) {
|
||||
size_t plen = strlen(pattern);
|
||||
const char *p = s;
|
||||
while(*p) {
|
||||
// Need strncasecmp() to avoid checking past the end of a successful match.
|
||||
if(!strncasecmp(p, pattern, plen))
|
||||
return const_cast<char *>(p);
|
||||
++p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *memccpy(void *__restrict, const void *__restrict, int, size_t) {
|
||||
__ensure(!"Not implemented");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
// This implementation was taken from musl
|
||||
void *memrchr(const void *m, int c, size_t n) {
|
||||
const unsigned char *s = (const unsigned char *)m;
|
||||
c = (unsigned char)c;
|
||||
while(n--) {
|
||||
if(s[n] == c)
|
||||
return (void *)(s + n);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *strerror_l(int errnum, locale_t) {
|
||||
mlibc::infoLogger() << "mlibc: strerror_l locale is ignored!" << frg::endlog;
|
||||
return strerror(errnum);
|
||||
}
|
||||
|
||||
// BSD extensions.
|
||||
// Taken from musl
|
||||
size_t strlcpy(char *d, const char *s, size_t n) {
|
||||
char *d0 = d;
|
||||
|
||||
if(!n--)
|
||||
goto finish;
|
||||
for(; n && (*d=*s); n--, s++, d++);
|
||||
*d = 0;
|
||||
finish:
|
||||
return d-d0 + strlen(s);
|
||||
}
|
||||
|
||||
size_t strlcat(char *d, const char *s, size_t n) {
|
||||
size_t l = strnlen(d, n);
|
||||
if(l == n) {
|
||||
return l + strlen(s);
|
||||
}
|
||||
return l + strlcpy(d + l, s, n - l);
|
||||
}
|
||||
Reference in New Issue
Block a user