From 3ab64bed39128950d8600567c33f7081979dc0dd Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Mon, 23 Sep 2024 20:17:44 +0300 Subject: [PATCH] lib: Introduce unic unic is a small library of C functions that is currently written in plain C. It's purpose isn't to be fast, but "universal" - as in include as little architecture-specific code as possible. The old neatlibc still resides, but isn't being built. There is still more to do, including implementation of memory management, so keep it there for now. Signed-off-by: Ivaylo Ivanov --- Makefile | 2 +- lib/Makefile | 33 +------ lib/unic/stdbool.h | 18 ++++ lib/unic/stddef.h | 14 +++ lib/unic/string.c | 209 +++++++++++++++++++++++++++++++++++++++++++++ lib/unic/string.h | 42 +++++++++ 6 files changed, 286 insertions(+), 32 deletions(-) create mode 100644 lib/unic/stdbool.h create mode 100644 lib/unic/stddef.h create mode 100644 lib/unic/string.c create mode 100644 lib/unic/string.h diff --git a/Makefile b/Makefile index a5a6d8c..19a2825 100644 --- a/Makefile +++ b/Makefile @@ -199,7 +199,7 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -Wno-format-security \ -fno-delete-null-pointer-checks \ -Wno-builtin-declaration-mismatch -Wno-main -nostdinc \ - -I$(srctree)/lib/neatlibc + -I$(srctree)/lib/unic KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := KBUILD_AFLAGS := -D__ASSEMBLY__ diff --git a/lib/Makefile b/lib/Makefile index b4dc7fa..0a40e8d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,34 +4,5 @@ lib-$(CONFIG_SIMPLE_FB) += simplefb/simplefb.o # DEBUG lib-y += debug/debug.o -# Neatlibc (excluding signal and syscalls) -ifeq ($(ARCH), arm) -lib-y += neatlibcarm/arm/bits.o \ - neatlibcarm/arm/lmem.o \ - neatlibcarm/arm/string.o -else -lib-y += neatlibcaarch64/$(ARCH)/bits.o \ - neatlibcaarch64/$(ARCH)/lmem.o \ - neatlibcaarch64/$(ARCH)/string.o -endif - -lib-y += neatlibc/ctype.o \ - neatlibc/strftime.o \ - neatlibc/mkstemp.o \ - neatlibc/regex.o \ - neatlibc/rand.o \ - neatlibc/stdarg.o \ - neatlibc/memtst.o \ - neatlibc/dirent.o \ - neatlibc/localtime.o \ - neatlibc/malloc.o \ - neatlibc/termios.o \ - neatlibc/atoi.o \ - neatlibc/errno.o \ - neatlibc/stdio.o \ - neatlibc/stdlib.o \ - neatlibc/qsort.o \ - neatlibc/stringc.o \ - neatlibc/isatty.o \ - neatlibc/scanf.o \ - neatlibc/string.o +# unic (neatlibc still temporarily resides) +lib-y += unic/string.o diff --git a/lib/unic/stdbool.h b/lib/unic/stdbool.h new file mode 100644 index 0000000..5495fd5 --- /dev/null +++ b/lib/unic/stdbool.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2024, Ivaylo Ivanov + */ + +#ifndef STDBOOL_H_ /* Include guard */ +#define STDBOOL_H_ + +#define bool _Bool +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#endif // STDBOOL_H_ diff --git a/lib/unic/stddef.h b/lib/unic/stddef.h new file mode 100644 index 0000000..9c0243c --- /dev/null +++ b/lib/unic/stddef.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2024, Ivaylo Ivanov + */ + +#ifndef STDDEF_H_ /* Include guard */ +#define STDDEF_H_ + +#define NULL ((void *) 0) +#define offsetof(type, field) ((int) (&((type *) 0)->field)) + +typedef unsigned long size_t; + +#endif // STDDEF_H_ diff --git a/lib/unic/string.c b/lib/unic/string.c new file mode 100644 index 0000000..e90ed3f --- /dev/null +++ b/lib/unic/string.c @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2024, Ivaylo Ivanov + */ + +#include "stdbool.h" +#include "string.h" + +void *memcpy(void *s1, const void *s2, size_t n) +{ + char *dest = (char *)s1; + const char *src = (const char *)s2; + + while (n--) { + *dest++ = *src++; + } + + return s1; +} + +void *memmove(void *s1, const void *s2, size_t n) +{ + char *dest = (char *)s1; + const char *src = (const char *)s2; + + if (dest <= src) { + while (n--) { + *dest++ = *src++; + } + } else { + src += n; + dest += n; + + while (n--) { + *--dest = *--src; + } + } + + return s1; +} + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + + while (n--) { + if (*p1 != *p2) { + return *p1 - *p2; + } + + ++p1; + ++p2; + } + + return 0; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = (unsigned char *)s; + + while (n--) { + *p++ = (unsigned char)c; + } + + return s; +} + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *p = (const unsigned char *)s; + + while (n--) { + if (*p == (unsigned char)c) { + return (void *)p; + } + + ++p; + } + + return NULL; +} + +char *strcpy(char *s1, const char *s2) +{ + char *rc = s1; + + while ((*s1++ = *s2++)) { + /* EMPTY */ + } + + return rc; +} + +char *strncpy(char *s1, const char *s2, size_t n) +{ + char *rc = s1; + + while (n && (*s1++ = *s2++)) { + /* Cannot do "n--" in the conditional as size_t is unsigned and we have + to check it again for >0 in the next loop below, so we must not risk + underflow. + */ + --n; + } + + /* Checking against 1 as we missed the last --n in the loop above. */ + while (n-- > 1) { + *s1++ = '\0'; + } + + return rc; +} + +int strcmp(const char *s1, const char *s2) +{ + while ((*s1) && (*s1 == *s2)) { + ++s1; + ++s2; + } + + return (*(unsigned char *)s1 - *(unsigned char *)s2); +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + while (n && *s1 && (*s1 == *s2)) { + ++s1; + ++s2; + --n; + } + + if (n == 0) { + return 0; + } else { + return (*(unsigned char *)s1 - *(unsigned char *)s2); + } +} + +size_t strlen(const char *s) +{ + size_t rc = 0; + + while (s[rc]) { + ++rc; + } + + return rc; +} + +size_t strnlen(const char *s, size_t n) +{ + size_t rc = 0; + + while (rc < n && s[rc]) { + ++rc; + } + + return rc; +} + +char *strchr(const char *s, int c) +{ + do { + if (*s == (char)c) { + return (char *)s; + } + } while (*s++); + + return NULL; +} + +char *strrchr(const char *s, int c) +{ + size_t i = 0; + + while (s[i++]) { + /* EMPTY */ + } + + do { + if (s[--i] == (char)c) { + return (char *)s + i; + } + } while (i); + + return NULL; +} + +/* Very naive, no attempt to check for errors */ +long atol(const char *s) +{ + long val = 0; + bool neg = false; + + if (*s == '-') { + neg = true; + s++; + } + + while (*s >= '0' && *s <= '9') + val = (val * 10) + (*s++ - '0'); + + if (neg) + val = -val; + + return val; +} diff --git a/lib/unic/string.h b/lib/unic/string.h new file mode 100644 index 0000000..7308058 --- /dev/null +++ b/lib/unic/string.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2024, Ivaylo Ivanov + */ + +#ifndef STRING_H_ /* Include guard */ +#define STRING_H_ + +#include "stddef.h" + +void *memcpy(void *s1, const void *s2, size_t n); +void *memmove(void *s1, const void *s2, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +void *memset(void *s, int c, size_t n); +void *memchr(const void *s, int c, size_t n); +char *strcpy(char *s1, const char *s2); +char *strncpy(char *s1, const char *s2, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +long atol(const char *s); + +static inline int tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + else + return c; +} + +static inline int toupper(int c) +{ + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; + else + return c; +} + +#endif // STRING_H_