lib: c: combine libc and ulibc

libc is now made up of several independent components, each of which is individually compiled into a static library.
they are then all combined into a single shared library.
This commit is contained in:
2026-03-06 20:12:58 +00:00
parent 267b893bf4
commit 68714fa0e5
33 changed files with 1695 additions and 8483 deletions

View File

@@ -0,0 +1,107 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stddef.h>
#include <stdint.h>
typedef uintptr_t word;
#define wsize sizeof(word)
#define wmask (wsize - 1)
void *memcpy(void *dst0, const void *src0, size_t length)
{
char *dst = dst0;
const char *src = src0;
size_t t;
if (length == 0 || dst == src) /* nothing to do */
goto done;
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) \
if (t) \
TLOOP1(s)
#define TLOOP1(s) \
do { \
s; \
} while (--t)
if ((uintptr_t)dst < (uintptr_t)src) {
/*
* Copy forward.
*/
t = (uintptr_t)src; /* only need low bits */
if ((t | (uintptr_t)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (uintptr_t)src;
if ((t | (uintptr_t)dst) & wmask) {
if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
t = length;
else
t &= wmask;
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
done:
return (dst0);
}

View File

@@ -0,0 +1,13 @@
#include <stddef.h>
void *memset(void *str, int c, size_t n)
{
unsigned char val = (unsigned char)c;
unsigned char *buf = str;
for (size_t i = 0; i < n; i++) {
buf[i] = val;
}
return str;
}

View File

@@ -0,0 +1,21 @@
int strcmp(const char *s1, const char *s2)
{
int i;
for (i = 0; s1[i] == s2[i]; i++)
if (s1[i] == '\0')
return 0;
return s1[i] - s2[i];
}
int strncmp(const char *s1, const char *s2, unsigned long n)
{
for (; n > 0; s1++, s2++, --n)
if (*s1 != *s2)
return ((*(unsigned char *)s1 < *(unsigned char *)s2)
? -1
: 1);
else if (*s1 == '\0')
return 0;
return 0;
}

View File

@@ -0,0 +1,342 @@
#include <errno.h>
const char *strerror(int errnum)
{
switch (errnum) {
case SUCCESS:
return "Success";
case EPERM:
return "Operation not permitted";
case ENOENT:
return "No such file or directory";
case ESRCH:
return "No such process";
case EINTR:
return "Interrupted system call";
case EIO:
return "Input/output error";
case ENXIO:
return "Device not configured";
case E2BIG:
return "Argument list too long";
case ENOEXEC:
return "Exec format error";
case EBADF:
return "Bad file descriptor";
case ECHILD:
return "No child processes";
case EDEADLK:
return "Resource deadlock avoided";
case ENOMEM:
return "Cannot allocate memory";
case EACCES:
return "Permission denied";
case EFAULT:
return "Bad address";
case ENOTBLK:
return "Block device required";
case EBUSY:
return "Resource busy";
case EEXIST:
return "File exists";
case EXDEV:
return "Cross-device link";
case ENODEV:
return "Operation not supported by device";
case ENOTDIR:
return "Not a directory";
case EISDIR:
return "Is a directory";
case EINVAL:
return "Invalid argument";
case ENFILE:
return "Too many open files in system";
case EMFILE:
return "Too many open files";
case ENOTTY:
return "Inappropriate ioctl for device";
case ETXTBSY:
return "Text file busy";
case EFBIG:
return "File too large";
case ENOSPC:
return "No space left on device";
case ESPIPE:
return "Illegal seek";
case EROFS:
return "Read-only file system";
case EMLINK:
return "Too many links";
case EPIPE:
return "Broken pipe";
case EDOM:
return "Numerical argument out of domain";
case ERANGE:
return "Result too large";
case EAGAIN:
return "Resource temporarily unavailable";
case EINPROGRESS:
return "Operation now in progress";
case EALREADY:
return "Operation already in progress";
case ENOTSOCK:
return "Socket operation on non-socket";
case EDESTADDRREQ:
return "Destination address required";
case EMSGSIZE:
return "Message too long";
case EPROTOTYPE:
return "Protocol wrong type for socket";
case ENOPROTOOPT:
return "Protocol not available";
case EPROTONOSUPPORT:
return "Protocol not supported";
case ESOCKTNOSUPPORT:
return "Socket type not supported";
case ENOTSUP:
return "Operation not supported";
case EPFNOSUPPORT:
return "Protocol family not supported";
case EAFNOSUPPORT:
return "Address family not supported by protocol family";
case EADDRINUSE:
return "Address already in use";
case EADDRNOTAVAIL:
return "Can't assign requested address";
case ENETDOWN:
return "Network is down";
case ENETUNREACH:
return "Network is unreachable";
case ENETRESET:
return "Network dropped connection on reset";
case ECONNABORTED:
return "Software caused connection abort";
case ECONNRESET:
return "Connection reset by peer";
case ENOBUFS:
return "No buffer space available";
case EISCONN:
return "Socket is already connected";
case ENOTCONN:
return "Socket is not connected";
case ESHUTDOWN:
return "Can't send after socket shutdown";
case ETOOMANYREFS:
return "Too many references: can't splice";
case ETIMEDOUT:
return "Operation timed out";
case ECONNREFUSED:
return "Connection refused";
case ELOOP:
return "Too many levels of symbolic links";
case ENAMETOOLONG:
return "File name too long";
case EHOSTDOWN:
return "Host is down";
case EHOSTUNREACH:
return "No route to host";
case ENOTEMPTY:
return "Directory not empty";
case EPROCLIM:
return "Too many processes";
case EUSERS:
return "Too many users";
case EDQUOT:
return "Disc quota exceeded";
case ESTALE:
return "Stale NFS file handle";
case EREMOTE:
return "Too many levels of remote in path";
case EBADRPC:
return "RPC struct is bad";
case ERPCMISMATCH:
return "RPC version wrong";
case EPROGUNAVAIL:
return "RPC prog. not avail";
case EPROGMISMATCH:
return "Program version wrong";
case EPROCUNAVAIL:
return "Bad procedure for program";
case ENOLCK:
return "No locks available";
case ENOSYS:
return "Function not implemented";
case EFTYPE:
return "Inappropriate file type or format";
case EAUTH:
return "Authentication error";
case ENEEDAUTH:
return "Need authenticator";
case EPWROFF:
return "Device power is off";
case EDEVERR:
return "Device error";
case EOVERFLOW:
return "Value too large to be stored in data type";
case EBADEXEC:
return "Bad executable (or shared library)";
case EBADARCH:
return "Bad CPU type in executable";
case ESHLIBVERS:
return "Shared library version mismatch";
case EBADMACHO:
return "Malformed Mach-o file";
case ECANCELED:
return "Operation canceled";
case EIDRM:
return "Identifier removed";
case ENOMSG:
return "No message of desired type";
case EILSEQ:
return "Illegal byte sequence";
case ENOATTR:
return "Attribute not found";
case EBADMSG:
return "Bad message";
case EMULTIHOP:
return "EMULTIHOP (Reserved)";
case ENODATA:
return "No message available on STREAM";
case ENOLINK:
return "ENOLINK (Reserved)";
case ENOSR:
return "No STREAM resources";
case ENOSTR:
return "Not a STREAM";
case EPROTO:
return "Protocol error";
case ETIME:
return "STREAM ioctl timeout";
case EOPNOTSUPP:
return "Operation not supported on socket";
case ENOPOLICY:
return "Policy not found";
case ENOTRECOVERABLE:
return "State not recoverable";
case EOWNERDEAD:
return "Previous owner died";
case EQFULL:
return "Interface output queue is full";
default:
return "Unknown error";
}
}
#define ENUM_STR(x) \
case x: \
return #x
const char *strerror_code(int errnum)
{
switch (errnum) {
ENUM_STR(SUCCESS);
ENUM_STR(EPERM);
ENUM_STR(ENOENT);
ENUM_STR(ESRCH);
ENUM_STR(EINTR);
ENUM_STR(EIO);
ENUM_STR(ENXIO);
ENUM_STR(E2BIG);
ENUM_STR(ENOEXEC);
ENUM_STR(EBADF);
ENUM_STR(ECHILD);
ENUM_STR(EDEADLK);
ENUM_STR(ENOMEM);
ENUM_STR(EACCES);
ENUM_STR(EFAULT);
ENUM_STR(ENOTBLK);
ENUM_STR(EBUSY);
ENUM_STR(EEXIST);
ENUM_STR(EXDEV);
ENUM_STR(ENODEV);
ENUM_STR(ENOTDIR);
ENUM_STR(EISDIR);
ENUM_STR(EINVAL);
ENUM_STR(ENFILE);
ENUM_STR(EMFILE);
ENUM_STR(ENOTTY);
ENUM_STR(ETXTBSY);
ENUM_STR(EFBIG);
ENUM_STR(ENOSPC);
ENUM_STR(ESPIPE);
ENUM_STR(EROFS);
ENUM_STR(EMLINK);
ENUM_STR(EPIPE);
ENUM_STR(EDOM);
ENUM_STR(ERANGE);
ENUM_STR(EAGAIN);
ENUM_STR(EINPROGRESS);
ENUM_STR(EALREADY);
ENUM_STR(ENOTSOCK);
ENUM_STR(EDESTADDRREQ);
ENUM_STR(EMSGSIZE);
ENUM_STR(EPROTOTYPE);
ENUM_STR(ENOPROTOOPT);
ENUM_STR(EPROTONOSUPPORT);
ENUM_STR(ESOCKTNOSUPPORT);
ENUM_STR(ENOTSUP);
ENUM_STR(EPFNOSUPPORT);
ENUM_STR(EAFNOSUPPORT);
ENUM_STR(EADDRINUSE);
ENUM_STR(EADDRNOTAVAIL);
ENUM_STR(ENETDOWN);
ENUM_STR(ENETUNREACH);
ENUM_STR(ENETRESET);
ENUM_STR(ECONNABORTED);
ENUM_STR(ECONNRESET);
ENUM_STR(ENOBUFS);
ENUM_STR(EISCONN);
ENUM_STR(ENOTCONN);
ENUM_STR(ESHUTDOWN);
ENUM_STR(ETOOMANYREFS);
ENUM_STR(ETIMEDOUT);
ENUM_STR(ECONNREFUSED);
ENUM_STR(ELOOP);
ENUM_STR(ENAMETOOLONG);
ENUM_STR(EHOSTDOWN);
ENUM_STR(EHOSTUNREACH);
ENUM_STR(ENOTEMPTY);
ENUM_STR(EPROCLIM);
ENUM_STR(EUSERS);
ENUM_STR(EDQUOT);
ENUM_STR(ESTALE);
ENUM_STR(EREMOTE);
ENUM_STR(EBADRPC);
ENUM_STR(ERPCMISMATCH);
ENUM_STR(EPROGUNAVAIL);
ENUM_STR(EPROGMISMATCH);
ENUM_STR(EPROCUNAVAIL);
ENUM_STR(ENOLCK);
ENUM_STR(ENOSYS);
ENUM_STR(EFTYPE);
ENUM_STR(EAUTH);
ENUM_STR(ENEEDAUTH);
ENUM_STR(EPWROFF);
ENUM_STR(EDEVERR);
ENUM_STR(EOVERFLOW);
ENUM_STR(EBADEXEC);
ENUM_STR(EBADARCH);
ENUM_STR(ESHLIBVERS);
ENUM_STR(EBADMACHO);
ENUM_STR(ECANCELED);
ENUM_STR(EIDRM);
ENUM_STR(ENOMSG);
ENUM_STR(EILSEQ);
ENUM_STR(ENOATTR);
ENUM_STR(EBADMSG);
ENUM_STR(EMULTIHOP);
ENUM_STR(ENODATA);
ENUM_STR(ENOLINK);
ENUM_STR(ENOSR);
ENUM_STR(ENOSTR);
ENUM_STR(EPROTO);
ENUM_STR(ETIME);
ENUM_STR(EOPNOTSUPP);
ENUM_STR(ENOPOLICY);
ENUM_STR(ENOTRECOVERABLE);
ENUM_STR(EOWNERDEAD);
ENUM_STR(EQFULL);
default:
return "";
}
}

View File

@@ -0,0 +1,11 @@
#include <string.h>
size_t strlen(const char *str)
{
size_t res = 0;
while (str[res]) {
res++;
}
return res;
}