From 4b178c0feb4c415be36be0e4c0def8c447ed42af Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Fri, 22 Nov 2019 22:17:54 +0100
Subject: Added the most awesome c lib

---
 src/mlibc/math.h            |   6 +
 src/mlibc/math/pow.c        |   9 +
 src/mlibc/stdio.h           |  10 +
 src/mlibc/stdio/printf.c    |  53 ++++++
 src/mlibc/stdio/writec.c    |   5 +
 src/mlibc/stdlib.h          |  22 +++
 src/mlibc/stdlib/atoi.c     |  23 +++
 src/mlibc/stdlib/htoa.c     |  29 +++
 src/mlibc/stdlib/htoi.c     |  22 +++
 src/mlibc/stdlib/itoa.c     |  43 +++++
 src/mlibc/stdlib/liballoc.c | 446 ++++++++++++++++++++++++++++++++++++++++++++
 src/mlibc/stdlib/liballoc.h |  24 +++
 src/mlibc/string.h          |  22 +++
 src/mlibc/string/strcat.c   |   9 +
 src/mlibc/string/strcati.c  |   7 +
 src/mlibc/string/strcmp.c   |   9 +
 src/mlibc/string/strcpy.c   |   8 +
 src/mlibc/string/strdisp.c  |  10 +
 src/mlibc/string/strdup.c   |   9 +
 src/mlibc/string/strinv.c   |  12 ++
 src/mlibc/string/strlen.c   |   7 +
 21 files changed, 785 insertions(+)
 create mode 100644 src/mlibc/math.h
 create mode 100644 src/mlibc/math/pow.c
 create mode 100644 src/mlibc/stdio.h
 create mode 100644 src/mlibc/stdio/printf.c
 create mode 100644 src/mlibc/stdio/writec.c
 create mode 100644 src/mlibc/stdlib.h
 create mode 100644 src/mlibc/stdlib/atoi.c
 create mode 100644 src/mlibc/stdlib/htoa.c
 create mode 100644 src/mlibc/stdlib/htoi.c
 create mode 100644 src/mlibc/stdlib/itoa.c
 create mode 100644 src/mlibc/stdlib/liballoc.c
 create mode 100644 src/mlibc/stdlib/liballoc.h
 create mode 100644 src/mlibc/string.h
 create mode 100644 src/mlibc/string/strcat.c
 create mode 100644 src/mlibc/string/strcati.c
 create mode 100644 src/mlibc/string/strcmp.c
 create mode 100644 src/mlibc/string/strcpy.c
 create mode 100644 src/mlibc/string/strdisp.c
 create mode 100644 src/mlibc/string/strdup.c
 create mode 100644 src/mlibc/string/strinv.c
 create mode 100644 src/mlibc/string/strlen.c

(limited to 'src/mlibc')

diff --git a/src/mlibc/math.h b/src/mlibc/math.h
new file mode 100644
index 0000000..c9abf7d
--- /dev/null
+++ b/src/mlibc/math.h
@@ -0,0 +1,6 @@
+#ifndef MELVIX_MATH_H
+#define MELVIX_MATH_H
+
+int pow(int base, int exp);
+
+#endif
diff --git a/src/mlibc/math/pow.c b/src/mlibc/math/pow.c
new file mode 100644
index 0000000..4f040bb
--- /dev/null
+++ b/src/mlibc/math/pow.c
@@ -0,0 +1,9 @@
+int pow(int base, int exp) {
+    if (exp < 0) return 0;
+
+    if (!exp) return 1;
+
+    int ret = base;
+    for (int i = 1; i < exp; i++) ret *= base;
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/stdio.h b/src/mlibc/stdio.h
new file mode 100644
index 0000000..ae377a2
--- /dev/null
+++ b/src/mlibc/stdio.h
@@ -0,0 +1,10 @@
+#ifndef MELVIX_STDIO_H
+#define MELVIX_STDIO_H
+
+// TODO: Input methods
+
+void writec(char c);
+
+void printf(const char *format, ...);
+
+#endif
diff --git a/src/mlibc/stdio/printf.c b/src/mlibc/stdio/printf.c
new file mode 100644
index 0000000..11516cf
--- /dev/null
+++ b/src/mlibc/stdio/printf.c
@@ -0,0 +1,53 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <mlibc/stdio.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+void __writes(const char *data) {
+    for (size_t i = 0; i < strlen(data); i++) writec(data[i]);
+}
+
+void printf(const char *fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+
+    uint8_t readyToFormat = 0;
+
+    char buff = 0;
+
+    for (; *fmt; fmt++) {
+        if (readyToFormat) {
+            if (*fmt == '%') {
+                writec('%');
+                readyToFormat = 0;
+                continue;
+            }
+
+            buff = *fmt;
+            if (buff == 's') {
+                const char *str = va_arg(args, const char*);
+                __writes(str);
+                readyToFormat = 0;
+            } else if (buff == 'x') {
+                char *p = htoa((uint32_t) va_arg(args, int));
+                __writes(p);
+                kfree(p);
+                readyToFormat = 0;
+            } else if (buff == 'd') {
+                char *p = itoa(va_arg(args, int));
+                __writes(p);
+                kfree(p);
+                readyToFormat = 0;
+            } else if (buff == 'c') {
+                writec((char) va_arg(args, int));
+                readyToFormat = 0;
+            }
+        } else {
+            if (*fmt == '%')
+                readyToFormat = 1;
+            else
+                writec(*fmt);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mlibc/stdio/writec.c b/src/mlibc/stdio/writec.c
new file mode 100644
index 0000000..60f69e8
--- /dev/null
+++ b/src/mlibc/stdio/writec.c
@@ -0,0 +1,5 @@
+#include <kernel/graphics/vesa.h>
+
+void writec(char c) {
+    vesa_draw_char(c);
+}
\ No newline at end of file
diff --git a/src/mlibc/stdlib.h b/src/mlibc/stdlib.h
new file mode 100644
index 0000000..7ae9c5a
--- /dev/null
+++ b/src/mlibc/stdlib.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_STDLIB_H
+#define MELVIX_STDLIB_H
+
+#include <stdint.h>
+
+#ifndef MELVIX_ALLOC_H
+#include <mlibc/stdlib/liballoc.h>
+#endif
+
+#ifndef MELVIX_STRING_H
+#include <mlibc/string.h>
+#endif
+
+char *itoa(int n);
+
+int atoi(char *str);
+
+char *htoa(uint32_t n);
+
+int htoi(char *str);
+
+#endif
diff --git a/src/mlibc/stdlib/atoi.c b/src/mlibc/stdlib/atoi.c
new file mode 100644
index 0000000..34f9991
--- /dev/null
+++ b/src/mlibc/stdlib/atoi.c
@@ -0,0 +1,23 @@
+#include <mlibc/math.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <mlibc/string.h>
+
+int atoi(char *str) {
+    size_t s_str = strlen(str);
+    if (!s_str) return 0;
+
+    uint8_t negative = 0;
+    if (str[0] == '-') negative = 1;
+
+    size_t i = 0;
+    if (negative) i++;
+
+    int ret = 0;
+    for (; i < s_str; i++) {
+        ret += (str[i] - '0') * pow(10, (s_str - i) - 1);
+    }
+
+    if (negative) ret *= -1;
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/stdlib/htoa.c b/src/mlibc/stdlib/htoa.c
new file mode 100644
index 0000000..5290c74
--- /dev/null
+++ b/src/mlibc/stdlib/htoa.c
@@ -0,0 +1,29 @@
+#include <stdint.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+static const char __HTOA_TABLE[] = "0123456789ABCDEF";
+
+char *htoa(uint32_t n) {
+    char *ret = kmalloc(10);
+
+    int i = 0;
+    while (n) {
+        ret[i++] = __HTOA_TABLE[n & 0xF];
+        n >>= 4;
+    }
+
+    if (!i) {
+        ret[0] = '0';
+        i++;
+    }
+
+    for (; i <= 9; i++) ret[i] = 0;
+
+    char *aux = strdup(ret);
+    kfree(ret);
+    ret = aux;
+
+    strinv(ret);
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/stdlib/htoi.c b/src/mlibc/stdlib/htoi.c
new file mode 100644
index 0000000..73a583b
--- /dev/null
+++ b/src/mlibc/stdlib/htoi.c
@@ -0,0 +1,22 @@
+#include <mlibc/math.h>
+#include <stddef.h>
+#include <mlibc/string.h>
+
+int htoi(char *str) {
+    size_t s_str = strlen(str);
+
+    size_t i = 0;
+    int ret = 0;
+    for (; i < s_str; i++) {
+        char c = str[i];
+        int aux = 0;
+        if (c >= '0' && c <= '9')
+            aux = c - '0';
+        else if (c >= 'A' && c <= 'F')
+            aux = (c - 'A') + 10;
+
+        ret += aux * pow(16, (s_str - i) - 1);
+    }
+
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/stdlib/itoa.c b/src/mlibc/stdlib/itoa.c
new file mode 100644
index 0000000..e9c40c1
--- /dev/null
+++ b/src/mlibc/stdlib/itoa.c
@@ -0,0 +1,43 @@
+#include <mlibc/math.h>
+#include <stdint.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+static const char __ITOA_TABLE[] = "0123456789";
+
+char *itoa(int n) {
+    // Special cases
+    if (!n) {
+        char *ret = kmalloc(2);
+        ret[0] = '0';
+        ret[1] = 0;
+        return ret;
+    }
+    uint8_t negative = (uint8_t) (n < 0);
+    if (negative) n *= -1;
+
+    // First get the number of digits.
+    int sz;
+    for (sz = 0; n % pow(10, sz) != n; sz++) {}
+
+    char *ret = kmalloc(sz + 1);
+
+    // Iterate all digits again.
+    for (int i = 0; i < sz; i++) {
+        int digit = (n % pow(10, i + 1)) / pow(10, i);
+        ret[i] = __ITOA_TABLE[digit];
+    }
+    ret[sz] = 0;
+
+    if (negative) {
+        char *aux = kmalloc(sz + 2);
+        strcpy(aux, ret);
+        aux[sz] = '-';
+        aux[sz + 1] = 0;
+        kfree(ret);
+        ret = aux;
+    }
+
+    strinv(ret);
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/stdlib/liballoc.c b/src/mlibc/stdlib/liballoc.c
new file mode 100644
index 0000000..f4015f2
--- /dev/null
+++ b/src/mlibc/stdlib/liballoc.c
@@ -0,0 +1,446 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <kernel/paging/paging.h>
+#include <mlibc/stdlib/liballoc.h>
+
+int liballoc_lock() {
+    // asm volatile ("cli");
+    return 0;
+}
+
+int liballoc_unlock() {
+    // asm volatile ("sti");
+    return 0;
+}
+
+void *liballoc_alloc(size_t p) {
+    uint32_t ptr = paging_alloc_pages((uint32_t) p);
+    return (void *) ptr;
+}
+
+int liballoc_free(void *ptr, size_t p) {
+    paging_set_free((uint32_t) ptr, (uint32_t) p);
+    return 0;
+}
+
+#define ALIGNMENT 16ul
+#define ALIGN_TYPE char
+#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
+#define USE_CASE1
+#define USE_CASE2
+#define USE_CASE3
+#define USE_CASE4
+#define USE_CASE5
+
+#define ALIGN(ptr) \
+        if ( ALIGNMENT > 1 ) { \
+            uintptr_t diff; \
+            ptr = (void*) ((uintptr_t) ptr + ALIGN_INFO); \
+            diff = (uintptr_t) ptr & (ALIGNMENT - 1); \
+            if (diff != 0) { \
+                diff = ALIGNMENT - diff; \
+                ptr = (void*) ((uintptr_t) ptr + diff); \
+            } \
+            *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
+        }
+
+#define UNALIGN(ptr) \
+        if (ALIGNMENT > 1) { \
+            uintptr_t diff = *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)); \
+            if (diff < (ALIGNMENT + ALIGN_INFO)) { \
+                ptr = (void*) ((uintptr_t) ptr - diff); \
+            } \
+        }
+
+#define LIBALLOC_MAGIC 0xc001c0de
+#define LIBALLOC_DEAD 0xdeaddead
+
+struct liballoc_major {
+    struct liballoc_major *prev;
+    struct liballoc_major *next;
+    unsigned int pages;
+    unsigned int size;
+    unsigned int usage;
+    struct liballoc_minor *first;
+};
+
+struct liballoc_minor {
+    struct liballoc_minor *prev;
+    struct liballoc_minor *next;
+    struct liballoc_major *block;
+    unsigned int magic;
+    unsigned int size;
+    unsigned int req_size;
+};
+
+static struct liballoc_major *l_memRoot = NULL;
+static struct liballoc_major *l_bestBet = NULL;
+
+static unsigned int l_pageSize = 4096;
+static unsigned int l_pageCount = 16;
+static unsigned long long l_allocated = 0;
+static unsigned long long l_inuse = 0;
+
+static long long l_warningCount = 0;
+static long long l_errorCount = 0;
+static long long l_possibleOverruns = 0;
+
+static void *liballoc_memset(void *s, int c, size_t n) {
+    unsigned int i;
+    for (i = 0; i < n; i++)
+        ((char *) s)[i] = c;
+
+    return s;
+}
+
+static void *liballoc_memcpy(void *s1, const void *s2, size_t n) {
+    char *cdest;
+    char *csrc;
+    unsigned int *ldest = (unsigned int *) s1;
+    unsigned int *lsrc = (unsigned int *) s2;
+
+    while (n >= sizeof(unsigned int)) {
+        *ldest++ = *lsrc++;
+        n -= sizeof(unsigned int);
+    }
+
+    cdest = (char *) ldest;
+    csrc = (char *) lsrc;
+
+    while (n > 0) {
+        *cdest++ = *csrc++;
+        n -= 1;
+    }
+    return s1;
+}
+
+static struct liballoc_major *allocate_new_page(unsigned int size) {
+    unsigned int st;
+    struct liballoc_major *maj;
+
+    st = size + sizeof(struct liballoc_major);
+    st += sizeof(struct liballoc_minor);
+
+    if ((st % l_pageSize) == 0)
+        st = st / (l_pageSize);
+    else
+        st = st / (l_pageSize) + 1;
+
+    if (st < l_pageCount) st = l_pageCount;
+
+    maj = (struct liballoc_major *) liballoc_alloc(st);
+
+    if (maj == NULL) {
+        l_warningCount += 1;
+        return NULL;
+    }
+
+    maj->prev = NULL;
+    maj->next = NULL;
+    maj->pages = st;
+    maj->size = st * l_pageSize;
+    maj->usage = sizeof(struct liballoc_major);
+    maj->first = NULL;
+
+    l_allocated += maj->size;
+
+    return maj;
+}
+
+void *PREFIX(malloc)(size_t req_size) {
+    int startedBet = 0;
+    unsigned long long bestSize = 0;
+    void *p = NULL;
+    uintptr_t diff;
+    struct liballoc_major *maj;
+    struct liballoc_minor *min;
+    struct liballoc_minor *new_min;
+    unsigned long size = req_size;
+
+    if (ALIGNMENT > 1) {
+        size += ALIGNMENT + ALIGN_INFO;
+    }
+
+    liballoc_lock();
+
+    if (size == 0) {
+        l_warningCount += 1;
+        liballoc_unlock();
+        return PREFIX(malloc)(1);
+    }
+
+    if (l_memRoot == NULL) {
+        l_memRoot = allocate_new_page(size);
+        if (l_memRoot == NULL) {
+            liballoc_unlock();
+            return NULL;
+        }
+    }
+
+    maj = l_memRoot;
+    startedBet = 0;
+
+    if (l_bestBet != NULL) {
+        bestSize = l_bestBet->size - l_bestBet->usage;
+
+        if (bestSize > (size + sizeof(struct liballoc_minor))) {
+            maj = l_bestBet;
+            startedBet = 1;
+        }
+    }
+
+    while (maj != NULL) {
+        diff = maj->size - maj->usage;
+        if (bestSize < diff) {
+            l_bestBet = maj;
+            bestSize = diff;
+        }
+
+#ifdef USE_CASE1
+        if (diff < (size + sizeof(struct liballoc_minor))) {
+            if (maj->next != NULL) {
+                maj = maj->next;
+                continue;
+            }
+
+            if (startedBet == 1) {
+                maj = l_memRoot;
+                startedBet = 0;
+                continue;
+            }
+
+            maj->next = allocate_new_page(size);
+            if (maj->next == NULL) break;
+            maj->next->prev = maj;
+            maj = maj->next;
+        }
+#endif
+
+#ifdef USE_CASE2
+        if (maj->first == NULL) {
+            maj->first = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major));
+
+            maj->first->magic = LIBALLOC_MAGIC;
+            maj->first->prev = NULL;
+            maj->first->next = NULL;
+            maj->first->block = maj;
+            maj->first->size = size;
+            maj->first->req_size = req_size;
+            maj->usage += size + sizeof(struct liballoc_minor);
+            l_inuse += size;
+            p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor));
+            ALIGN(p);
+            liballoc_unlock();
+            return p;
+        }
+#endif
+
+#ifdef USE_CASE3
+        diff = (uintptr_t) (maj->first);
+        diff -= (uintptr_t) maj;
+        diff -= sizeof(struct liballoc_major);
+
+        if (diff >= (size + sizeof(struct liballoc_minor))) {
+            maj->first->prev = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major));
+            maj->first->prev->next = maj->first;
+            maj->first = maj->first->prev;
+            maj->first->magic = LIBALLOC_MAGIC;
+            maj->first->prev = NULL;
+            maj->first->block = maj;
+            maj->first->size = size;
+            maj->first->req_size = req_size;
+            maj->usage += size + sizeof(struct liballoc_minor);
+            l_inuse += size;
+            p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor));
+            ALIGN(p);
+            liballoc_unlock();
+            return p;
+        }
+#endif
+
+#ifdef USE_CASE4
+        min = maj->first;
+
+        while (min != NULL) {
+            if (min->next == NULL) {
+                diff = (uintptr_t) (maj) + maj->size;
+                diff -= (uintptr_t) min;
+                diff -= sizeof(struct liballoc_minor);
+                diff -= min->size;
+                if (diff >= (size + sizeof(struct liballoc_minor))) {
+                    min->next = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size);
+                    min->next->prev = min;
+                    min = min->next;
+                    min->next = NULL;
+                    min->magic = LIBALLOC_MAGIC;
+                    min->block = maj;
+                    min->size = size;
+                    min->req_size = req_size;
+                    maj->usage += size + sizeof(struct liballoc_minor);
+                    l_inuse += size;
+                    p = (void *) ((uintptr_t) min + sizeof(struct liballoc_minor));
+                    ALIGN(p);
+                    liballoc_unlock();
+                    return p;
+                }
+            }
+
+            if (min->next != NULL) {
+                diff = (uintptr_t) (min->next);
+                diff -= (uintptr_t) min;
+                diff -= sizeof(struct liballoc_minor);
+                diff -= min->size;
+
+                if (diff >= (size + sizeof(struct liballoc_minor))) {
+                    new_min = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size);
+                    new_min->magic = LIBALLOC_MAGIC;
+                    new_min->next = min->next;
+                    new_min->prev = min;
+                    new_min->size = size;
+                    new_min->req_size = req_size;
+                    new_min->block = maj;
+                    min->next->prev = new_min;
+                    min->next = new_min;
+                    maj->usage += size + sizeof(struct liballoc_minor);
+                    l_inuse += size;
+                    p = (void *) ((uintptr_t) new_min + sizeof(struct liballoc_minor));
+                    ALIGN(p);
+                    liballoc_unlock();
+                    return p;
+                }
+            }
+
+            min = min->next;
+        }
+#endif
+
+#ifdef USE_CASE5
+        if (maj->next == NULL) {
+            if (startedBet == 1) {
+                maj = l_memRoot;
+                startedBet = 0;
+                continue;
+            }
+            maj->next = allocate_new_page(size);
+            if (maj->next == NULL) break;
+            maj->next->prev = maj;
+        }
+#endif
+        maj = maj->next;
+    }
+
+    liballoc_unlock();
+
+    return NULL;
+}
+
+void PREFIX(free)(void *ptr) {
+    struct liballoc_minor *min;
+    struct liballoc_major *maj;
+
+    if (ptr == NULL) {
+        l_warningCount += 1;
+        return;
+    }
+
+    UNALIGN(ptr);
+    liballoc_lock();
+
+    min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor));
+
+    if (min->magic != LIBALLOC_MAGIC) {
+        l_errorCount += 1;
+
+        if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
+            ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
+            ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
+            l_possibleOverruns += 1;
+        }
+
+        liballoc_unlock();
+        return;
+    }
+
+    maj = min->block;
+    l_inuse -= min->size;
+    maj->usage -= (min->size + sizeof(struct liballoc_minor));
+    min->magic = LIBALLOC_DEAD;
+
+    if (min->next != NULL) min->next->prev = min->prev;
+    if (min->prev != NULL) min->prev->next = min->next;
+    if (min->prev == NULL) maj->first = min->next;
+    if (maj->first == NULL) {
+        if (l_memRoot == maj) l_memRoot = maj->next;
+        if (l_bestBet == maj) l_bestBet = NULL;
+        if (maj->prev != NULL) maj->prev->next = maj->next;
+        if (maj->next != NULL) maj->next->prev = maj->prev;
+        l_allocated -= maj->size;
+        liballoc_free(maj, maj->pages);
+    } else {
+        if (l_bestBet != NULL) {
+            int bestSize = l_bestBet->size - l_bestBet->usage;
+            int majSize = maj->size - maj->usage;
+            if (majSize > bestSize) l_bestBet = maj;
+        }
+    }
+    liballoc_unlock();
+}
+
+void *PREFIX(calloc)(size_t nobj, size_t size) {
+    int real_size;
+    void *p;
+
+    real_size = nobj * size;
+
+    p = PREFIX(malloc)(real_size);
+
+    liballoc_memset(p, 0, real_size);
+
+    return p;
+}
+
+void *PREFIX(realloc)(void *p, size_t size) {
+    void *ptr;
+    struct liballoc_minor *min;
+    unsigned int real_size;
+
+    if (size == 0) {
+        PREFIX(free)(p);
+        return NULL;
+    }
+
+    if (p == NULL) return PREFIX(malloc)(size);
+
+    ptr = p;
+    UNALIGN(ptr);
+    liballoc_lock();
+    min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor));
+
+    if (min->magic != LIBALLOC_MAGIC) {
+        l_errorCount += 1;
+        if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
+            ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
+            ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
+            l_possibleOverruns += 1;
+        }
+
+        liballoc_unlock();
+        return NULL;
+    }
+
+    real_size = min->req_size;
+
+    if (real_size >= size) {
+        min->req_size = size;
+        liballoc_unlock();
+        return p;
+    }
+
+    liballoc_unlock();
+
+    ptr = PREFIX(malloc)(size);
+    liballoc_memcpy(ptr, p, real_size);
+    PREFIX(free)(p);
+
+    return ptr;
+}
diff --git a/src/mlibc/stdlib/liballoc.h b/src/mlibc/stdlib/liballoc.h
new file mode 100644
index 0000000..6ed9efb
--- /dev/null
+++ b/src/mlibc/stdlib/liballoc.h
@@ -0,0 +1,24 @@
+#ifndef MELVIX_ALLOC_H
+#define MELVIX_ALLOC_H
+
+#include <stddef.h>
+
+#define PREFIX(func) k ## func
+
+int liballoc_lock();
+
+int liballoc_unlock();
+
+void *liballoc_alloc(size_t);
+
+int liballoc_free(void *, size_t);
+
+void *PREFIX(malloc)(size_t);
+
+void *PREFIX(realloc)(void *, size_t);
+
+void *PREFIX(calloc)(size_t, size_t);
+
+void PREFIX(free)(void *);
+
+#endif
diff --git a/src/mlibc/string.h b/src/mlibc/string.h
new file mode 100644
index 0000000..fe925cb
--- /dev/null
+++ b/src/mlibc/string.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_STRING_H
+#define MELVIX_STRING_H
+
+#include <stddef.h>
+
+size_t strlen(const char *str);
+
+void strcpy(char *dest, const char *orig);
+
+void strdisp(char *str, int n);
+
+void strcat(char *dest, const char *orig);
+
+void strcati(char *dest, const char *orig);
+
+char strcmp(const char *a, const char *b);
+
+char *strdup(const char *orig);
+
+void strinv(char *str);
+
+#endif
diff --git a/src/mlibc/string/strcat.c b/src/mlibc/string/strcat.c
new file mode 100644
index 0000000..3cc56f1
--- /dev/null
+++ b/src/mlibc/string/strcat.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+
+void strcat(char *dest, const char *orig) {
+    size_t s_dest = strlen(dest);
+    size_t s_orig = strlen(orig);
+
+    for (size_t i = 0; i < s_orig; i++) dest[s_dest + i] = orig[i];
+    dest[s_dest + s_orig] = 0;
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strcati.c b/src/mlibc/string/strcati.c
new file mode 100644
index 0000000..d925eb7
--- /dev/null
+++ b/src/mlibc/string/strcati.c
@@ -0,0 +1,7 @@
+#include <mlibc/string.h>
+
+void strcati(char *dest, const char *orig) {
+    size_t s_orig = strlen(orig);
+    strdisp(dest, (int) s_orig);
+    for (size_t i = 0; i < s_orig; i++) dest[i] = orig[i];
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strcmp.c b/src/mlibc/string/strcmp.c
new file mode 100644
index 0000000..cc719da
--- /dev/null
+++ b/src/mlibc/string/strcmp.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+
+char strcmp(const char *a, const char *b) {
+    if (strlen(a) != strlen(b)) return 1;
+
+    for (size_t i = 0; i < strlen(a); i++) if (a[i] != b[i]) return 1;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strcpy.c b/src/mlibc/string/strcpy.c
new file mode 100644
index 0000000..5a1ff4e
--- /dev/null
+++ b/src/mlibc/string/strcpy.c
@@ -0,0 +1,8 @@
+#include <mlibc/string.h>
+
+void strcpy(char *dest, const char *orig) {
+    size_t s_orig = strlen(orig);
+
+    for (size_t i = 0; i < s_orig; i++) dest[i] = orig[i];
+    dest[s_orig] = 0;
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strdisp.c b/src/mlibc/string/strdisp.c
new file mode 100644
index 0000000..6feb4ca
--- /dev/null
+++ b/src/mlibc/string/strdisp.c
@@ -0,0 +1,10 @@
+#include <mlibc/string.h>
+
+void strdisponce(char *str) {
+    for (size_t i = sizeof(str) + 2; i > 0; i--) str[i] = str[i - 1];
+    str[0] = 0;
+}
+
+void strdisp(char *str, int n) {
+    for (int i = 0; i < n; i++) strdisponce(str);
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strdup.c b/src/mlibc/string/strdup.c
new file mode 100644
index 0000000..0cddd79
--- /dev/null
+++ b/src/mlibc/string/strdup.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+char *strdup(const char *orig) {
+    size_t s_orig = strlen(orig);
+    char *ret = kmalloc(s_orig + 1);
+    strcpy(ret, orig);
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strinv.c b/src/mlibc/string/strinv.c
new file mode 100644
index 0000000..c6dd7fd
--- /dev/null
+++ b/src/mlibc/string/strinv.c
@@ -0,0 +1,12 @@
+#include <mlibc/string.h>
+
+void strinv(char *str) {
+    size_t s_str = strlen(str);
+
+    int iterations = (int) s_str / 2;
+    for (int i = 0; i < iterations; i++) {
+        char aux = str[i];
+        str[i] = str[(s_str - i) - 1];
+        str[(s_str - i) - 1] = aux;
+    }
+}
\ No newline at end of file
diff --git a/src/mlibc/string/strlen.c b/src/mlibc/string/strlen.c
new file mode 100644
index 0000000..1143683
--- /dev/null
+++ b/src/mlibc/string/strlen.c
@@ -0,0 +1,7 @@
+#include <mlibc/string.h>
+
+size_t strlen(const char *str) {
+    size_t len = 0;
+    while (str[len]) len++;
+    return len;
+}
\ No newline at end of file
-- 
cgit v1.2.3