summaryrefslogtreecommitdiff
path: root/src/ulib
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-01-03 02:19:57 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-01-03 02:19:57 +0800
commit210025560c80b48af4875af199f183ad709e3bf0 (patch)
treeeb11aeb7b641187f207e3b572c5184cf3526b463 /src/ulib
parentbde87490d61135dcaa94d9b1489ff6c39876d169 (diff)
parent10614e04929a6d109a5e90524e446b637aaf0c13 (diff)
downloadlume-210025560c80b48af4875af199f183ad709e3bf0.tar.gz
lume-210025560c80b48af4875af199f183ad709e3bf0.tar.xz
Merge pull request #4 from Richard-Qin-001/dev/shell
Rebuilt the system's underlying structure; it is now stable enough to merge. The system now supports a read-only file system and has a simple shell implemented.
Diffstat (limited to 'src/ulib')
-rw-r--r--src/ulib/assert.c8
-rw-r--r--src/ulib/cxx.cc31
-rw-r--r--src/ulib/iostream.cpp8
-rw-r--r--src/ulib/stdio.c1052
-rw-r--r--src/ulib/stdlib.c539
-rw-r--r--src/ulib/string.c331
6 files changed, 1969 insertions, 0 deletions
diff --git a/src/ulib/assert.c b/src/ulib/assert.c
new file mode 100644
index 0000000..ca2da84
--- /dev/null
+++ b/src/ulib/assert.c
@@ -0,0 +1,8 @@
+#include "stdio.h"
+#include "stdlib.h"
+
+void __assert_fail(const char *expr, const char *file, int line, const char *func)
+{
+ fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
+ abort();
+} \ No newline at end of file
diff --git a/src/ulib/cxx.cc b/src/ulib/cxx.cc
new file mode 100644
index 0000000..6c892ab
--- /dev/null
+++ b/src/ulib/cxx.cc
@@ -0,0 +1,31 @@
+#include "ulib/stdlib.h"
+
+void *operator new(unsigned long n)
+{
+ return malloc(n);
+}
+
+void *operator new[](unsigned long n)
+{
+ return malloc(n);
+}
+
+void operator delete(void *p)
+{
+ free(p);
+}
+
+void operator delete[](void *p)
+{
+ free(p);
+}
+
+void operator delete(void *p, unsigned long)
+{
+ free(p);
+}
+
+void operator delete[](void *p, unsigned long)
+{
+ free(p);
+} \ No newline at end of file
diff --git a/src/ulib/iostream.cpp b/src/ulib/iostream.cpp
new file mode 100644
index 0000000..d5394f9
--- /dev/null
+++ b/src/ulib/iostream.cpp
@@ -0,0 +1,8 @@
+#include "ulib/iostream"
+
+namespace std
+{
+ istream cin(stdin);
+ ostream cout(stdout);
+ ostream cerr(stderr);
+} // namespace std
diff --git a/src/ulib/stdio.c b/src/ulib/stdio.c
new file mode 100644
index 0000000..f8e7a9a
--- /dev/null
+++ b/src/ulib/stdio.c
@@ -0,0 +1,1052 @@
+#include "ulib/stdio.h"
+#include "ulib/string.h"
+#include "ulib/stdlib.h"
+
+/* Include STB Sprintf Implementation */
+#define STB_SPRINTF_IMPLEMENTATION
+#include "ulib/stb_sprintf.h"
+
+const int STDIN_FD = 0;
+const int STDOUT_FD = 1;
+const int STDERR_FD = 2;
+
+
+
+extern int open(const char *path, int flags);
+extern int close(int fd);
+extern int read(int fd, void *buf, uint64 count);
+extern int write(int fd, const void *buf, uint64 count);
+extern int lseek(int fd, int offset, int whence);
+
+static int isspace(int c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
+}
+
+/* Core Formatting Implementation */
+
+static int _ul_to_str_invert(char *buf, uint64 val, int base, int uppercase)
+{
+ int i = 0;
+ const char *digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
+ if (val == 0)
+ {
+ buf[i++] = '0';
+ return i;
+ }
+ while (val != 0)
+ {
+ buf[i++] = digits[val % base];
+ val /= base;
+ }
+ return i;
+}
+
+typedef struct
+{
+ char *buf;
+ uint64 limit;
+ uint64 written;
+ FILE *stream;
+} _OutContext;
+
+static void _out_char(_OutContext *ctx, char c)
+{
+ if (ctx->stream)
+ {
+ fputc(c, ctx->stream);
+ ctx->written++;
+ }
+ else
+ {
+ if (ctx->limit > 0 && ctx->written < ctx->limit - 1)
+ {
+ ctx->buf[ctx->written] = c;
+ }
+ ctx->written++;
+ }
+}
+
+static int _vprintf_core(_OutContext *ctx, const char *format, va_list ap)
+{
+ const char *p = format;
+ char num_buf[32];
+
+ while (*p)
+ {
+ if (*p != '%')
+ {
+ _out_char(ctx, *p++);
+ continue;
+ }
+ p++;
+
+ int flag_left = 0, flag_zero = 0, flag_plus = 0, flag_space = 0, flag_hash = 0;
+ while (1)
+ {
+ if (*p == '-')
+ flag_left = 1;
+ else if (*p == '0')
+ flag_zero = 1;
+ else if (*p == '+')
+ flag_plus = 1;
+ else if (*p == ' ')
+ flag_space = 1;
+ else if (*p == '#')
+ flag_hash = 1;
+ else
+ break;
+ p++;
+ }
+
+ int width = 0;
+ if (*p == '*')
+ {
+ width = va_arg(ap, int);
+ if (width < 0)
+ {
+ flag_left = 1;
+ width = -width;
+ }
+ p++;
+ }
+ else
+ {
+ while (*p >= '0' && *p <= '9')
+ {
+ width = width * 10 + (*p - '0');
+ p++;
+ }
+ }
+
+ int precision = -1;
+ if (*p == '.')
+ {
+ p++;
+ if (*p == '*')
+ {
+ precision = va_arg(ap, int);
+ p++;
+ }
+ else
+ {
+ precision = 0;
+ while (*p >= '0' && *p <= '9')
+ {
+ precision = precision * 10 + (*p - '0');
+ p++;
+ }
+ }
+ }
+
+ int len_mod = 0;
+ if (*p == 'l')
+ {
+ len_mod = 1;
+ p++;
+ if (*p == 'l')
+ {
+ len_mod = 2;
+ p++;
+ }
+ }
+ else if (*p == 'z')
+ {
+ len_mod = 2;
+ p++;
+ }
+
+ char spec = *p++;
+ if (!spec)
+ break;
+
+ if (spec == 'd' || spec == 'i' || spec == 'u' || spec == 'x' || spec == 'X' || spec == 'p')
+ {
+ uint64 val;
+ int is_signed = (spec == 'd' || spec == 'i');
+ int base = (spec == 'x' || spec == 'X' || spec == 'p') ? 16 : 10;
+
+ if (spec == 'p')
+ val = (uint64)va_arg(ap, void *);
+ else if (len_mod == 2)
+ val = is_signed ? (uint64)va_arg(ap, int64) : va_arg(ap, uint64);
+ else if (len_mod == 1)
+ val = is_signed ? (uint64)va_arg(ap, long) : (uint64)va_arg(ap, unsigned long);
+ else
+ val = is_signed ? (uint64)((int64)va_arg(ap, int)) : (uint64)va_arg(ap, uint32);
+
+ char sign_char = 0;
+ if (is_signed)
+ {
+ int64 sval = (int64)val;
+ if (sval < 0)
+ {
+ sign_char = '-';
+ val = (uint64)(-sval);
+ }
+ else if (flag_plus)
+ sign_char = '+';
+ else if (flag_space)
+ sign_char = ' ';
+ }
+
+ int digit_len = _ul_to_str_invert(num_buf, val, base, (spec == 'X'));
+ if (precision >= 0)
+ flag_zero = 0;
+ int prec_zeros = (precision > digit_len) ? precision - digit_len : 0;
+ if (precision == 0 && val == 0)
+ digit_len = 0;
+
+ int prefix_len = sign_char ? 1 : 0;
+ char *prefix_str = NULL;
+ if (spec == 'p' || (flag_hash && val != 0 && (spec == 'x' || spec == 'X')))
+ {
+ prefix_str = (spec == 'X') ? "0X" : "0x";
+ prefix_len += 2;
+ }
+
+ int padding = (width > prefix_len + prec_zeros + digit_len) ? width - (prefix_len + prec_zeros + digit_len) : 0;
+
+ if (!flag_left && !flag_zero)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ if (sign_char)
+ _out_char(ctx, sign_char);
+ if (prefix_str)
+ {
+ _out_char(ctx, prefix_str[0]);
+ _out_char(ctx, prefix_str[1]);
+ }
+ int total_zeros = prec_zeros + ((flag_zero && !flag_left) ? padding : 0);
+ for (int i = 0; i < total_zeros; i++)
+ _out_char(ctx, '0');
+ for (int i = digit_len - 1; i >= 0; i--)
+ _out_char(ctx, num_buf[i]);
+ if (flag_left)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ }
+ else if (spec == 'f' || spec == 'F' || spec == 'e' || spec == 'E' || spec == 'g' || spec == 'G')
+ {
+ char fmt_tmp[32];
+ int f_idx = 0;
+ fmt_tmp[f_idx++] = '%';
+ if (flag_left)
+ fmt_tmp[f_idx++] = '-';
+ if (flag_zero)
+ fmt_tmp[f_idx++] = '0';
+ if (flag_plus)
+ fmt_tmp[f_idx++] = '+';
+ if (flag_space)
+ fmt_tmp[f_idx++] = ' ';
+ if (flag_hash)
+ fmt_tmp[f_idx++] = '#';
+ if (width > 0)
+ f_idx += sprintf(&fmt_tmp[f_idx], "%d", width);
+ if (precision >= 0)
+ f_idx += sprintf(&fmt_tmp[f_idx], ".%d", precision);
+ fmt_tmp[f_idx++] = spec;
+ fmt_tmp[f_idx] = '\0';
+ double f_val = va_arg(ap, double);
+ char f_buf[128];
+ stbsp_snprintf(f_buf, sizeof(f_buf), fmt_tmp, f_val);
+ for (int i = 0; f_buf[i] != '\0'; i++)
+ _out_char(ctx, f_buf[i]);
+ }
+ else if (spec == 's')
+ {
+ const char *s = va_arg(ap, char *);
+ if (!s)
+ s = "(null)";
+ int len = 0;
+ const char *tmp = s;
+ while (*tmp && (precision < 0 || len < precision))
+ {
+ tmp++;
+ len++;
+ }
+ int padding = (width > len) ? width - len : 0;
+ if (!flag_left)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ for (int i = 0; i < len; i++)
+ _out_char(ctx, s[i]);
+ if (flag_left)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ }
+ else if (spec == 'c')
+ {
+ char c = (char)va_arg(ap, int);
+ int padding = (width > 1) ? width - 1 : 0;
+ if (!flag_left)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ _out_char(ctx, c);
+ if (flag_left)
+ for (int i = 0; i < padding; i++)
+ _out_char(ctx, ' ');
+ }
+ else
+ {
+ _out_char(ctx, '%');
+ if (spec != '%')
+ _out_char(ctx, spec);
+ }
+ }
+ return (int)ctx->written;
+}
+
+int vsnprintf(char *str, uint64 size, const char *format, va_list ap)
+{
+ _OutContext ctx;
+ ctx.buf = str;
+ ctx.limit = size;
+ ctx.written = 0;
+ ctx.stream = NULL;
+ _vprintf_core(&ctx, format, ap);
+ if (size > 0)
+ {
+ if (ctx.written < size)
+ str[ctx.written] = '\0';
+ else
+ str[size - 1] = '\0';
+ }
+ return (int)ctx.written;
+}
+int snprintf(char *str, uint64 size, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int ret = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return ret;
+}
+int sprintf(char *str, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int ret = vsnprintf(str, (uint64)-1, format, ap);
+ va_end(ap);
+ return ret;
+}
+int printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _OutContext ctx;
+ ctx.buf = NULL;
+ ctx.limit = 0;
+ ctx.written = 0;
+ ctx.stream = stdout;
+ _vprintf_core(&ctx, format, ap);
+ va_end(ap);
+ return (int)ctx.written;
+}
+
+/* Core Function Implementation */
+
+typedef struct
+{
+ const char *buf;
+ int fd;
+ uint64 pos;
+ int ungotten;
+} _InContext;
+
+static int _in_char(_InContext *ctx)
+{
+ if (ctx->ungotten >= 0)
+ {
+ int c = ctx->ungotten;
+ ctx->ungotten = -1;
+ return c;
+ }
+ if (ctx->fd == -1)
+ {
+ if (ctx->buf[ctx->pos] == '\0')
+ return -1;
+ return (unsigned char)ctx->buf[ctx->pos++];
+ }
+ char c;
+ if (read(ctx->fd, &c, 1) == 1)
+ return (unsigned char)c;
+ return -1;
+}
+
+static void _unget_char(_InContext *ctx, int c)
+{
+ if (c != -1)
+ ctx->ungotten = c;
+}
+static void _skip_space(_InContext *ctx)
+{
+ int c;
+ while ((c = _in_char(ctx)) != -1)
+ {
+ if (!isspace(c))
+ {
+ _unget_char(ctx, c);
+ break;
+ }
+ }
+}
+
+static double _simple_strtod(const char *str, char **endptr)
+{
+ double val = 0.0;
+ int sign = 1;
+ if (*str == '-')
+ {
+ sign = -1;
+ str++;
+ }
+ else if (*str == '+')
+ str++;
+ while (*str >= '0' && *str <= '9')
+ {
+ val = val * 10.0 + (*str - '0');
+ str++;
+ }
+ if (*str == '.')
+ {
+ str++;
+ double div = 10.0;
+ while (*str >= '0' && *str <= '9')
+ {
+ val += (*str - '0') / div;
+ div *= 10.0;
+ str++;
+ }
+ }
+ if (*str == 'e' || *str == 'E')
+ {
+ str++;
+ int esign = 1;
+ if (*str == '-')
+ {
+ esign = -1;
+ str++;
+ }
+ else if (*str == '+')
+ str++;
+ int eval = 0;
+ while (*str >= '0' && *str <= '9')
+ {
+ eval = eval * 10 + (*str - '0');
+ str++;
+ }
+ double p = 1.0;
+ while (eval--)
+ p *= 10.0;
+ if (esign == 1)
+ val *= p;
+ else
+ val /= p;
+ }
+ if (endptr)
+ *endptr = (char *)str;
+ return sign * val;
+}
+
+static int _vscanf_core(_InContext *ctx, const char *format, va_list ap)
+{
+ int assigned = 0;
+ const char *p = format;
+ while (*p)
+ {
+ if (isspace(*p))
+ {
+ _skip_space(ctx);
+ while (isspace(*p))
+ p++;
+ continue;
+ }
+ if (*p != '%')
+ {
+ _skip_space(ctx);
+ int c = _in_char(ctx);
+ if (c != *p)
+ {
+ _unget_char(ctx, c);
+ return assigned;
+ }
+ p++;
+ continue;
+ }
+ p++;
+ int suppress = 0;
+ if (*p == '*')
+ {
+ suppress = 1;
+ p++;
+ }
+ int width = -1;
+ while (*p >= '0' && *p <= '9')
+ {
+ if (width == -1)
+ width = 0;
+ width = width * 10 + (*p - '0');
+ p++;
+ }
+ int len_mod = 0;
+ if (*p == 'l')
+ {
+ len_mod = 1;
+ p++;
+ if (*p == 'l')
+ {
+ len_mod = 2;
+ p++;
+ }
+ }
+ else if (*p == 'h')
+ {
+ p++;
+ if (*p == 'h')
+ p++;
+ }
+ char spec = *p++;
+ if (!spec)
+ break;
+
+ if (spec == 'd' || spec == 'i' || spec == 'u' || spec == 'x')
+ {
+ _skip_space(ctx);
+ char num_buf[64];
+ int i = 0, c = _in_char(ctx);
+ if (c == '-' || c == '+')
+ {
+ num_buf[i++] = (char)c;
+ c = _in_char(ctx);
+ }
+ int base = (spec == 'x') ? 16 : (spec == 'i' ? 0 : 10);
+ while (c != -1 && i < 63)
+ {
+ int digit = (c >= '0' && c <= '9');
+ int hex = (base == 16 || base == 0) && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
+ int x = (c == 'x' || c == 'X');
+ if (base == 0 && i == 1 && num_buf[0] == '0' && x)
+ base = 16;
+ if (width > 0 && i >= width)
+ break;
+ if (digit || hex || x)
+ {
+ num_buf[i++] = (char)c;
+ c = _in_char(ctx);
+ }
+ else
+ break;
+ }
+ num_buf[i] = '\0';
+ _unget_char(ctx, c);
+ if (i == 0)
+ return assigned;
+ if (!suppress)
+ {
+ int64 val = strtoll(num_buf, NULL, base);
+ if (len_mod == 2)
+ *va_arg(ap, int64 *) = val;
+ else if (len_mod == 1)
+ *va_arg(ap, long *) = (long)val;
+ else
+ *va_arg(ap, int *) = (int)val;
+ assigned++;
+ }
+ }
+ else if (spec == 'f' || spec == 'F' || spec == 'e' || spec == 'E' || spec == 'g' || spec == 'G')
+ {
+ _skip_space(ctx);
+ char num_buf[64];
+ int i = 0, c = _in_char(ctx);
+ if (c == '-' || c == '+')
+ {
+ num_buf[i++] = (char)c;
+ c = _in_char(ctx);
+ }
+ while (c != -1 && i < 63)
+ {
+ if ((c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-')
+ {
+ num_buf[i++] = (char)c;
+ c = _in_char(ctx);
+ }
+ else
+ break;
+ }
+ num_buf[i] = '\0';
+ _unget_char(ctx, c);
+ if (i == 0)
+ return assigned;
+ if (!suppress)
+ {
+ double val = _simple_strtod(num_buf, NULL);
+ if (len_mod == 1)
+ *va_arg(ap, double *) = val;
+ else
+ *va_arg(ap, float *) = (float)val;
+ assigned++;
+ }
+ }
+ else if (spec == 's')
+ {
+ _skip_space(ctx);
+ char *buf = suppress ? NULL : va_arg(ap, char *);
+ int i = 0, c = _in_char(ctx);
+ while (c != -1 && !isspace(c))
+ {
+ if (width > 0 && i >= width)
+ break;
+ if (!suppress)
+ buf[i] = (char)c;
+ i++;
+ c = _in_char(ctx);
+ }
+ if (!suppress)
+ buf[i] = '\0';
+ _unget_char(ctx, c);
+ if (i > 0 && !suppress)
+ assigned++;
+ }
+ else if (spec == 'c')
+ {
+ int count = (width > 0) ? width : 1;
+ char *buf = suppress ? NULL : va_arg(ap, char *);
+ for (int i = 0; i < count; i++)
+ {
+ int c = _in_char(ctx);
+ if (c == -1)
+ return assigned;
+ if (!suppress)
+ buf[i] = (char)c;
+ }
+ if (!suppress)
+ assigned++;
+ }
+ }
+ return assigned;
+}
+
+int sscanf(const char *str, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _InContext ctx;
+ ctx.buf = str;
+ ctx.fd = -1;
+ ctx.pos = 0;
+ ctx.ungotten = -1;
+ int ret = _vscanf_core(&ctx, format, ap);
+ va_end(ap);
+ return ret;
+}
+int scanf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _InContext ctx;
+ ctx.buf = NULL;
+ ctx.fd = STDIN_FD;
+ ctx.pos = 0;
+ ctx.ungotten = -1;
+ int ret = _vscanf_core(&ctx, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+/* FILE Stream Implementation */
+
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100
+#define O_TRUNC 01000
+#define O_APPEND 02000
+
+
+static FILE _stdin = {.fd = 0, .buf_mode = 1};
+static FILE _stdout = {.fd = 1, .buf_mode = 1};
+static FILE _stderr = {.fd = 2, .buf_mode = 2};
+
+FILE *stdin = &_stdin;
+FILE *stdout = &_stdout;
+FILE *stderr = &_stderr;
+
+FILE *fopen(const char *filename, const char *mode)
+{
+ int flags = 0;
+ if (strcmp(mode, "r") == 0)
+ flags = O_RDONLY;
+ else if (strcmp(mode, "w") == 0)
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
+ else if (strcmp(mode, "a") == 0)
+ flags = O_WRONLY | O_CREAT | O_APPEND;
+ else if (strcmp(mode, "r+") == 0)
+ flags = O_RDWR;
+ else
+ return NULL;
+
+ int64 fd = open(filename, flags);
+ if (fd < 0)
+ return NULL;
+
+ FILE *f = (FILE *)malloc(sizeof(FILE));
+ if (!f)
+ {
+ close(fd);
+ return NULL;
+ }
+
+ memset(f, 0, sizeof(FILE));
+ f->fd = (int)fd;
+ f->flags = flags;
+
+ if (fd == 1)
+ f->buf_mode = 1;
+ else if (fd == 2)
+ f->buf_mode = 2;
+ else
+ f->buf_mode = 0;
+ return f;
+}
+
+int fclose(FILE *stream)
+{
+ if (!stream)
+ return -1;
+ fflush(stream);
+ if (stream != stdin && stream != stdout && stream != stderr)
+ {
+ close(stream->fd);
+ free(stream);
+ }
+ return 0;
+}
+
+int fflush(FILE *stream)
+{
+ if (!stream)
+ return EOF;
+
+ if (stream->buf_write_pos > 0)
+ {
+ int64 ret = write(stream->fd, stream->buffer, stream->buf_write_pos);
+ if (ret < stream->buf_write_pos)
+ {
+ stream->error = 1;
+ stream->buf_write_pos = 0;
+ return EOF;
+ }
+ stream->buf_write_pos = 0;
+ }
+ return 0;
+}
+
+int fprintf(FILE *stream, const char *format, ...)
+{
+ if (!stream)
+ return -1;
+ va_list ap;
+ va_start(ap, format);
+ _OutContext ctx;
+ ctx.buf = NULL;
+ ctx.limit = 0;
+ ctx.written = 0;
+ ctx.stream = stream;
+ _vprintf_core(&ctx, format, ap);
+ va_end(ap);
+ return (int)ctx.written;
+}
+
+int fscanf(FILE *stream, const char *format, ...)
+{
+ if (!stream)
+ return -1;
+ va_list ap;
+ va_start(ap, format);
+ _InContext ctx;
+ ctx.buf = NULL;
+ ctx.fd = stream->fd;
+ ctx.pos = 0;
+ ctx.ungotten = -1;
+ int ret = _vscanf_core(&ctx, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+int fputc(int c, FILE *stream)
+{
+ if (!stream)
+ return EOF;
+ if (stream->buf_mode == 2)
+ {
+ char ch = (char)c;
+ if (write(stream->fd, &ch, 1) != 1)
+ {
+ stream->error = 1;
+ return EOF;
+ }
+ return c;
+ }
+
+ stream->buffer[stream->buf_write_pos++] = (char)c;
+
+ if (stream->buf_write_pos >= BUFSIZ)
+ {
+ fflush(stream);
+ }
+ else if (stream->buf_mode == 1 && c == '\n')
+ {
+ fflush(stream);
+ }
+
+ return c;
+}
+
+int fputs(const char *s, FILE *stream)
+{
+ if (!stream)
+ return -1;
+ while (*s)
+ {
+ if (fputc(*s++, stream) == EOF)
+ return EOF;
+ }
+ return 0;
+}
+
+int fgetc(FILE *stream)
+{
+ if (!stream)
+ return EOF;
+
+ if (stream->buf_write_pos > 0)
+ {
+ fflush(stream);
+ }
+
+ if (stream->buf_read_pos < stream->buf_read_cnt)
+ {
+ return (unsigned char)stream->buffer[stream->buf_read_pos++];
+ }
+
+ int64 ret = read(stream->fd, stream->buffer, BUFSIZ);
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ stream->eof = 1;
+ else
+ stream->error = 1;
+ return EOF;
+ }
+
+ stream->buf_read_cnt = (int)ret;
+ stream->buf_read_pos = 0;
+ return (unsigned char)stream->buffer[stream->buf_read_pos++];
+}
+
+char *fgets(char *str, int n, FILE *stream)
+{
+ if (!stream || n <= 0)
+ return NULL;
+ int i = 0, c;
+ while (i < n - 1)
+ {
+ c = fgetc(stream);
+ if (c == -1)
+ {
+ if (i == 0)
+ return NULL;
+ break;
+ }
+ str[i++] = (char)c;
+ if (c == '\n')
+ break;
+ }
+ str[i] = '\0';
+ return str;
+}
+
+uint64 fread(void *ptr, uint64 size, uint64 nmemb, FILE *stream)
+{
+ if (!stream || size == 0 || nmemb == 0)
+ return 0;
+
+ uint64 total_bytes = size * nmemb;
+ uint64 bytes_read = 0;
+ char *dst = (char *)ptr;
+
+ if (stream->buf_write_pos > 0)
+ fflush(stream);
+
+ while (bytes_read < total_bytes)
+ {
+ if (stream->buf_read_pos < stream->buf_read_cnt)
+ {
+ uint64 available = stream->buf_read_cnt - stream->buf_read_pos;
+ uint64 remaining = total_bytes - bytes_read;
+ uint64 to_copy = (available < remaining) ? available : remaining;
+
+ memcpy(dst + bytes_read, stream->buffer + stream->buf_read_pos, to_copy);
+
+ stream->buf_read_pos += to_copy;
+ bytes_read += to_copy;
+ }
+ else
+ {
+ uint64 remaining = total_bytes - bytes_read;
+
+ if (remaining >= BUFSIZ)
+ {
+ int64 ret = read(stream->fd, dst + bytes_read, remaining);
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ stream->eof = 1;
+ else
+ stream->error = 1;
+ return bytes_read / size;
+ }
+ bytes_read += ret;
+ }
+ else
+ {
+ stream->buf_read_pos = 0;
+ stream->buf_read_cnt = 0;
+ int64 ret = read(stream->fd, stream->buffer, BUFSIZ);
+
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ stream->eof = 1;
+ else
+ stream->error = 1;
+ return bytes_read / size;
+ }
+ stream->buf_read_cnt = (int)ret;
+ }
+ }
+ }
+ return bytes_read / size;
+}
+
+uint64 fwrite(const void *ptr, uint64 size, uint64 nmemb, FILE *stream)
+{
+ if (!stream || !ptr || size == 0 || nmemb == 0)
+ return 0;
+ uint64 total_bytes = size * nmemb;
+ const char *src = (const char *)ptr;
+ uint64 bytes_written = 0;
+
+ if (stream->buf_mode == 2)
+ {
+ while (bytes_written < total_bytes)
+ {
+ int64 ret = write(stream->fd, src + bytes_written, total_bytes - bytes_written);
+ if (ret <= 0)
+ {
+ stream->error = 1;
+ break;
+ }
+ bytes_written += ret;
+ }
+ return bytes_written / size;
+ }
+
+ while (bytes_written < total_bytes)
+ {
+ uint64 space_left = BUFSIZ - stream->buf_write_pos;
+ uint64 remaining = total_bytes - bytes_written;
+
+ if (remaining <= space_left)
+ {
+ memcpy(stream->buffer + stream->buf_write_pos, src + bytes_written, remaining);
+ stream->buf_write_pos += remaining;
+ bytes_written += remaining;
+ if (stream->buf_write_pos == BUFSIZ)
+ fflush(stream);
+ }
+ else
+ {
+ memcpy(stream->buffer + stream->buf_write_pos, src + bytes_written, space_left);
+ stream->buf_write_pos += space_left;
+ bytes_written += space_left;
+ fflush(stream);
+ }
+ }
+
+ return bytes_written / size;
+}
+
+int fseek(FILE *stream, long offset, int whence)
+{
+ if (!stream)
+ return -1;
+
+ if (stream->buf_write_pos > 0)
+ {
+ fflush(stream);
+ }
+ stream->buf_read_pos = 0;
+ stream->buf_read_cnt = 0;
+ stream->eof = 0;
+
+ if (lseek(stream->fd, offset, whence) < 0)
+ {
+ stream->error = 1;
+ return -1;
+ }
+ return 0;
+}
+long ftell(FILE *stream)
+{
+ if (!stream)
+ return -1L;
+ int64 ret = lseek(stream->fd, 0, SEEK_CUR);
+ if (ret < 0)
+ {
+ stream->error = 1;
+ return -1L;
+ }
+ return (long)ret;
+}
+void rewind(FILE *stream)
+{
+ if (stream)
+ {
+ fseek(stream, 0, SEEK_SET);
+ stream->error = 0;
+ }
+}
+
+int feof(FILE *stream)
+{
+ return (stream) ? stream->eof : 1;
+}
+int ferror(FILE *stream)
+{
+ return (stream) ? stream->error : 1;
+}
+void clearerr(FILE *stream)
+{
+ if (stream)
+ {
+ stream->error = 0;
+ stream->eof = 0;
+ }
+}
+
+int ungetc(int c, FILE *stream)
+{
+ if (!stream || c == EOF)
+ return EOF;
+
+ if (stream->buf_read_pos > 0)
+ {
+ stream->buf_read_pos--;
+ stream->buffer[stream->buf_read_pos] = (char)c;
+ stream->eof = 0;
+ return c;
+ }
+ return EOF;
+} \ No newline at end of file
diff --git a/src/ulib/stdlib.c b/src/ulib/stdlib.c
new file mode 100644
index 0000000..89d5a08
--- /dev/null
+++ b/src/ulib/stdlib.c
@@ -0,0 +1,539 @@
+#include "ulib/stdlib.h"
+#include "ulib/string.h"
+#include "ulib/ctypes.h"
+
+extern int sys_exit(int status);
+extern void *sbrk(long increment);
+
+#undef errno
+int errno = 0;
+
+#define ATEXIT_MAX 32
+static void (*__atexit_funcs[ATEXIT_MAX])(void);
+static int __atexit_func_count = 0;
+
+int atexit(void (*function)(void))
+{
+ if (__atexit_func_count >= ATEXIT_MAX)
+ return -1;
+ __atexit_funcs[__atexit_func_count++] = function;
+ return 0;
+}
+
+int exit(int status)
+{
+ while (__atexit_func_count > 0)
+ {
+ (__atexit_funcs[--__atexit_func_count])();
+ }
+ sys_exit(status);
+
+ while (1)
+ ;
+ return 0;
+}
+
+void abort(void)
+{
+ exit(127);
+}
+
+char *getenv(const char *name)
+{
+ /* None */
+ return NULL;
+}
+
+int system(const char *command)
+{
+ /* None */
+ return -1;
+}
+
+/* Memory Management */
+#define ALIGNMENT 16
+#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
+
+typedef struct header
+{
+ size_t size;
+ struct header *next;
+} header_t;
+
+static header_t base;
+static header_t *freep = NULL;
+
+
+#define LOCK()
+#define UNLOCK()
+
+void free(void *ptr)
+{
+ header_t *bp, *p;
+
+ if (!ptr)
+ return;
+
+
+ bp = (header_t *)ptr - 1;
+
+ LOCK();
+
+
+ for (p = freep; !(bp > p && bp < p->next); p = p->next)
+ {
+ if (p >= p->next && (bp > p || bp < p->next))
+ break;
+ }
+
+ if ((char *)bp + bp->size == (char *)p->next)
+ {
+ bp->size += p->next->size;
+ bp->next = p->next->next;
+ }
+ else
+ {
+ bp->next = p->next;
+ }
+
+ if ((char *)p + p->size == (char *)bp)
+ {
+ p->size += bp->size;
+ p->next = bp->next;
+ }
+ else
+ {
+ p->next = bp;
+ }
+
+ freep = p;
+ UNLOCK();
+}
+
+static header_t *morecore(size_t nu)
+{
+ char *cp;
+ header_t *up;
+
+ if (nu < 4096)
+ nu = 4096;
+
+ nu = ALIGN(nu);
+
+ cp = (char *)sbrk(nu);
+ if (cp == (void *)-1)
+ return NULL;
+
+ up = (header_t *)cp;
+ up->size = nu;
+
+ free((void *)(up + 1));
+ return freep;
+}
+
+void *malloc(size_t size)
+{
+ header_t *p, *prevp;
+
+ if (size == 0)
+ return NULL;
+
+ size = ALIGN(size + sizeof(header_t));
+
+ LOCK();
+
+ if ((prevp = freep) == NULL)
+ {
+ base.next = freep = prevp = &base;
+ base.size = 0;
+ }
+
+ for (p = prevp->next;; prevp = p, p = p->next)
+ {
+ if (p->size >= size)
+ {
+ if (p->size == size)
+ {
+ prevp->next = p->next;
+ }
+ else
+ {
+ p->size -= size;
+
+ p = (header_t *)((char *)p + p->size);
+
+ p->size = size;
+ }
+ freep = prevp;
+ UNLOCK();
+ return (void *)(p + 1);
+ }
+
+ if (p == freep)
+ {
+ if ((p = morecore(size)) == NULL)
+ {
+ UNLOCK();
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ }
+}
+
+void *calloc(size_t nmemb, size_t size)
+{
+ size_t total;
+ if (__builtin_mul_overflow(nmemb, size, &total))
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ void *p = malloc(total);
+ if (p)
+ memset(p, 0, total);
+ return p;
+}
+
+void *realloc(void *ptr, size_t size)
+{
+ if (!ptr)
+ return malloc(size);
+ if (size == 0)
+ {
+ free(ptr);
+ return NULL;
+ }
+
+ header_t *bp = (header_t *)ptr - 1;
+ size_t new_size = ALIGN(size + sizeof(header_t));
+
+ if (bp->size >= new_size)
+ return ptr;
+
+ void *new_ptr = malloc(size);
+ if (!new_ptr)
+ return NULL;
+
+ memcpy(new_ptr, ptr, bp->size - sizeof(header_t));
+ free(ptr);
+ return new_ptr;
+}
+
+/* String Conversion*/
+
+unsigned long long strtoull(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ unsigned long long cutoff;
+ int c;
+ int neg = 0, any, cutlim;
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ if (endptr)
+ *endptr = (char *)nptr;
+ errno = 0; /* EINVAL */
+ return 0;
+ }
+
+ do
+ {
+ c = *s++;
+ } while (isspace(c));
+
+ if (c == '-')
+ {
+ neg = 1;
+ c = *s++;
+ }
+ else if (c == '+')
+ {
+ c = *s++;
+ }
+
+ if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X'))
+ {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0' ? 8 : 10);
+
+ cutoff = ULLONG_MAX / (unsigned long long)base;
+ cutlim = ULLONG_MAX % (unsigned long long)base;
+
+ for (acc = 0, any = 0;; c = *s++)
+ {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+
+ if (c >= base)
+ break;
+
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else
+ {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+
+ if (any < 0)
+ {
+ acc = ULLONG_MAX;
+ errno = ERANGE;
+ }
+ else if (neg)
+ acc = -acc;
+
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+
+ return acc;
+}
+
+long long strtoll(const char *nptr, char **endptr, int base)
+{
+ const char *s = nptr;
+ unsigned long long acc;
+ int c, neg = 0;
+
+ do
+ {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-')
+ neg = 1;
+
+ acc = strtoull(nptr, endptr, base);
+
+ if (errno == ERANGE && acc == ULLONG_MAX)
+ return neg ? LLONG_MIN : LLONG_MAX;
+
+ if (!neg && acc > (unsigned long long)LLONG_MAX)
+ {
+ errno = ERANGE;
+ return LLONG_MAX;
+ }
+ if (neg && acc > (unsigned long long)LLONG_MAX + 1)
+ {
+ errno = ERANGE;
+ return LLONG_MIN;
+ }
+
+ return neg ? -(long long)acc : (long long)acc;
+}
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ unsigned long long ret = strtoull(nptr, endptr, base);
+ if (ret > ULONG_MAX)
+ {
+ errno = ERANGE;
+ return ULONG_MAX;
+ }
+ return (unsigned long)ret;
+}
+
+long strtol(const char *nptr, char **endptr, int base)
+{
+ long long ret = strtoll(nptr, endptr, base);
+ if (ret > LONG_MAX)
+ {
+ errno = ERANGE;
+ return LONG_MAX;
+ }
+ if (ret < LONG_MIN)
+ {
+ errno = ERANGE;
+ return LONG_MIN;
+ }
+ return (long)ret;
+}
+
+int atoi(const char *nptr) { return (int)strtol(nptr, NULL, 10); }
+long atol(const char *nptr) { return strtol(nptr, NULL, 10); }
+long long atoll(const char *nptr) { return strtoll(nptr, NULL, 10); }
+
+double strtod(const char *nptr, char **endptr)
+{
+ double val = 0.0;
+ int sign = 1;
+ const char *s = nptr;
+
+ while (isspace(*s))
+ s++;
+ if (*s == '-')
+ {
+ sign = -1;
+ s++;
+ }
+ else if (*s == '+')
+ s++;
+
+ while (isdigit(*s))
+ {
+ val = val * 10.0 + (*s - '0');
+ s++;
+ }
+ if (*s == '.')
+ {
+ double factor = 1.0;
+ s++;
+ while (isdigit(*s))
+ {
+ factor *= 0.1;
+ val += (*s - '0') * factor;
+ s++;
+ }
+ }
+
+ if (endptr)
+ *endptr = (char *)s;
+ return val * sign;
+}
+
+double atof(const char *nptr) { return strtod(nptr, NULL); }
+float strtof(const char *nptr, char **endptr) { return (float)strtod(nptr, endptr); }
+
+/* Sort & Search */
+
+static void swap_bytes(char *a, char *b, size_t size)
+{
+ char temp;
+ while (size--)
+ {
+ temp = *a;
+ *a++ = *b;
+ *b++ = temp;
+ }
+}
+
+void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
+{
+ if (nmemb < 2 || size == 0)
+ return;
+
+ char *base_ptr = (char *)base;
+ char *pivot = base_ptr + (nmemb - 1) * size;
+ char *i = base_ptr;
+ char *j = base_ptr;
+
+ /* Partition */
+ for (; j < pivot; j += size)
+ {
+ if (compar(j, pivot) < 0)
+ {
+ if (i != j)
+ swap_bytes(i, j, size);
+ i += size;
+ }
+ }
+ swap_bytes(i, pivot, size);
+
+ /* Recurse */
+ size_t left_count = (i - base_ptr) / size;
+ qsort(base, left_count, size, compar);
+ qsort(i + size, nmemb - left_count - 1, size, compar);
+}
+
+void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
+{
+ size_t l = 0, u = nmemb;
+ while (l < u)
+ {
+ size_t idx = (l + u) / 2;
+ const void *p = (void *)((const char *)base + (idx * size));
+ int cmp = compar(key, p);
+ if (cmp < 0)
+ u = idx;
+ else if (cmp > 0)
+ l = idx + 1;
+ else
+ return (void *)p;
+ }
+ return NULL;
+}
+
+/* Math & Mics */
+
+int abs(int j) { return (j < 0) ? -j : j; }
+long labs(long j) { return (j < 0) ? -j : j; }
+long long llabs(long long j) { return (j < 0) ? -j : j; }
+
+div_t div(int numer, int denom)
+{
+ div_t res = {numer / denom, numer % denom};
+ return res;
+}
+ldiv_t ldiv(long numer, long denom)
+{
+ ldiv_t res = {numer / denom, numer % denom};
+ return res;
+}
+lldiv_t lldiv(long long numer, long long denom)
+{
+ lldiv_t res = {numer / denom, numer % denom};
+ return res;
+}
+
+static unsigned long next = 1;
+int rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)(next / 65536) % 32768;
+}
+void srand(unsigned int seed) { next = seed; }
+
+/* Stub */
+int mblen(const char *s, size_t n) { return (s && *s && n) ? 1 : 0; }
+int mbtowc(wchar_t *pwc, const char *s, size_t n)
+{
+ if (!s)
+ return 0;
+ if (n == 0)
+ return -1;
+ if (pwc)
+ *pwc = (wchar_t)*s;
+ return (*s != 0);
+}
+int wctomb(char *s, wchar_t wchar)
+{
+ if (!s)
+ return 0;
+ *s = (char)wchar;
+ return 1;
+}
+size_t mbstowcs(wchar_t *dest, const char *src, size_t n)
+{
+ size_t i = 0;
+ while (src[i] && i < n)
+ {
+ dest[i] = (wchar_t)src[i];
+ i++;
+ }
+ if (i < n)
+ dest[i] = 0;
+ return i;
+}
+size_t wcstombs(char *dest, const wchar_t *src, size_t n)
+{
+ size_t i = 0;
+ while (src[i] && i < n)
+ {
+ dest[i] = (char)src[i];
+ i++;
+ }
+ if (i < n)
+ dest[i] = 0;
+ return i;
+} \ No newline at end of file
diff --git a/src/ulib/string.c b/src/ulib/string.c
new file mode 100644
index 0000000..5fc1cbd
--- /dev/null
+++ b/src/ulib/string.c
@@ -0,0 +1,331 @@
+#include "ulib/string.h"
+#include "ulib/stdlib.h"
+
+
+/* Memory Manipulation Functions */
+
+void *memset(void *dst, int c, size_t n)
+{
+ char *cdst = (char *)dst;
+ for (size_t i = 0; i < n; i++)
+ cdst[i] = (char)c;
+ return dst;
+}
+
+void *memmove(void *vdst, const void *vsrc, size_t n)
+{
+ char *dst = (char *)vdst;
+ const char *src = (const char *)vsrc;
+ if (dst == src)
+ return vdst;
+
+ if (src > dst)
+ {
+ while (n--)
+ *dst++ = *src++;
+ }
+ else
+ {
+ dst += n;
+ src += n;
+ while (n-- > 0)
+ *--dst = *--src;
+ }
+ return vdst;
+}
+
+void *memcpy(void *vdst, const void *vsrc, size_t n)
+{
+ return memmove(vdst, vsrc, n);
+}
+
+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 *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;
+}
+
+/* String Manipulation Functions */
+
+size_t strlen(const char *s)
+{
+ const char *p = s;
+ while (*p)
+ p++;
+ return (size_t)(p - s);
+}
+
+char *strcpy(char *dst, const char *src)
+{
+ char *os = dst;
+ while ((*dst++ = *src++) != 0)
+ ;
+ return os;
+}
+
+char *strncpy(char *dst, const char *src, size_t n)
+{
+ char *os = dst;
+ size_t i;
+
+ for (i = 0; i < n && src[i] != '\0'; i++)
+ dst[i] = src[i];
+
+ for (; i < n; i++)
+ dst[i] = '\0';
+
+ return os;
+}
+
+char *strcat(char *dst, const char *src)
+{
+ char *os = dst;
+ while (*dst)
+ dst++;
+ while ((*dst++ = *src++) != 0)
+ ;
+ return os;
+}
+
+char *strncat(char *dst, const char *src, size_t n)
+{
+ char *os = dst;
+ size_t dest_len = strlen(dst);
+ size_t i;
+
+ dst += dest_len;
+
+ for (i = 0; i < n && src[i] != '\0'; i++)
+ dst[i] = src[i];
+
+ dst[i] = '\0';
+
+ return os;
+}
+
+int strcmp(const char *p, const char *q)
+{
+ while (*p && *p == *q)
+ {
+ p++;
+ q++;
+ }
+ return (int)((unsigned char)*p - (unsigned char)*q);
+}
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ if (n == 0)
+ return 0;
+
+ while (n-- > 0 && *s1 && *s1 == *s2)
+ {
+ if (n == 0 || *s1 == '\0')
+ break;
+ s1++;
+ s2++;
+ }
+ return (int)((unsigned char)*s1 - (unsigned char)*s2);
+}
+
+char *strchr(const char *s, int c)
+{
+ while (*s != (char)c)
+ {
+ if (!*s++)
+ return NULL;
+ }
+ return (char *)s;
+}
+
+char *strrchr(const char *s, int c)
+{
+ const char *last = NULL;
+ do
+ {
+ if (*s == (char)c)
+ last = s;
+ } while (*s++);
+
+ return (char *)last;
+}
+
+
+char *strstr(const char *haystack, const char *needle)
+{
+ size_t n_len = strlen(needle);
+ if (n_len == 0)
+ return (char *)haystack;
+
+ for (; *haystack; haystack++)
+ {
+ if (*haystack != *needle)
+ continue;
+
+ if (strncmp(haystack, needle, n_len) == 0)
+ return (char *)haystack;
+ }
+ return NULL;
+}
+
+char *strdup(const char *s)
+{
+ size_t len = strlen(s) + 1;
+ char *new_str = (char *)malloc(len);
+ if (new_str == NULL)
+ return NULL;
+
+ return (char *)memcpy(new_str, s, len);
+}
+
+size_t strlcpy(char *dst, const char *src, size_t size)
+{
+ size_t src_len = strlen(src);
+
+ if (size > 0)
+ {
+ size_t copy_len = (src_len >= size) ? size - 1 : src_len;
+ memcpy(dst, src, copy_len);
+ dst[copy_len] = '\0';
+ }
+
+ return src_len;
+}
+
+size_t strlcat(char *dst, const char *src, size_t size)
+{
+ size_t dst_len = 0;
+ size_t src_len = strlen(src);
+
+ while (dst_len < size && dst[dst_len] != '\0')
+ dst_len++;
+
+ if (dst_len == size)
+ return size + src_len;
+
+ size_t space_left = size - dst_len;
+ size_t copy_len = (src_len >= space_left) ? space_left - 1 : src_len;
+
+ memcpy(dst + dst_len, src, copy_len);
+ dst[dst_len + copy_len] = '\0';
+
+ return dst_len + src_len;
+}
+
+
+size_t strspn(const char *s, const char *accept)
+{
+ const char *p = s;
+ const char *a;
+
+ while (*p)
+ {
+ for (a = accept; *a; a++)
+ {
+ if (*p == *a)
+ break;
+ }
+ if (*a == '\0')
+ return (size_t)(p - s);
+ p++;
+ }
+ return (size_t)(p - s);
+}
+
+size_t strcspn(const char *s, const char *reject)
+{
+ const char *p = s;
+ const char *r;
+
+ while (*p)
+ {
+ for (r = reject; *r; r++)
+ {
+ if (*p == *r)
+ return (size_t)(p - s);
+ }
+ p++;
+ }
+ return (size_t)(p - s);
+}
+
+char *strpbrk(const char *s, const char *accept)
+{
+ const char *a;
+ while (*s)
+ {
+ for (a = accept; *a; a++)
+ {
+ if (*s == *a)
+ return (char *)s;
+ }
+ s++;
+ }
+ return NULL;
+}
+
+char *strtok(char *str, const char *delim)
+{
+ static char *olds;
+ char *token;
+
+ if (str == NULL)
+ str = olds;
+
+ str += strspn(str, delim);
+ if (*str == '\0')
+ {
+ olds = str;
+ return NULL;
+ }
+
+ token = str;
+ str = strpbrk(token, delim);
+
+ if (str == NULL)
+ {
+ olds = strchr(token, '\0');
+ }
+ else
+ {
+ *str = '\0';
+ olds = str + 1;
+ }
+
+ return token;
+}
+
+char *strerror(int errnum)
+{
+
+ switch (errnum)
+ {
+ case 0:
+ return "Success";
+ // case EINVAL: return "Invalid argument";
+ case ENOMEM: return "Out of memory";
+
+ default:
+ return "Unknown error";
+ }
+} \ No newline at end of file