Files
kaguya 9a9b91c940 user: implement mlibc as the libc, finally.
It's finally done..

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
2026-05-02 03:31:49 -04:00

180 lines
3.6 KiB
C++

#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);
}