summaryrefslogtreecommitdiff
path: root/stdlib/stdio.c
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-01-05 01:38:01 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-01-05 01:38:01 +0800
commit1e862099a13266da57ff7c6de11c1a11c42a8112 (patch)
tree90ee229c00a9ba71e60833ca0c8e9ca229cb0aae /stdlib/stdio.c
parent92ca8063f354d515e500b7cf99fb9cdca98c39d3 (diff)
parent51a788fa9e13ead0c504a1369797f8b49d73634c (diff)
downloadlume-1e862099a13266da57ff7c6de11c1a11c42a8112.tar.gz
lume-1e862099a13266da57ff7c6de11c1a11c42a8112.tar.xz
Merge pull request #7 from Richard-Qin-001/dev/shell
Important: License changed from MIT to GPL.
Diffstat (limited to 'stdlib/stdio.c')
-rw-r--r--stdlib/stdio.c1127
1 files changed, 0 insertions, 1127 deletions
diff --git a/stdlib/stdio.c b/stdlib/stdio.c
deleted file mode 100644
index aa13e25..0000000
--- a/stdlib/stdio.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-#include "stdio.h"
-
-/* Include STB Sprintf Implementation */
-#define STB_SPRINTF_IMPLEMENTATION
-#include "stb_sprintf.h"
-
-/* Syscall Implementation */
-
-const int64 STDIN_FD = 0;
-const int64 STDOUT_FD = 1;
-const int64 STDERR_FD = 2;
-
-#if defined(__x86_64__)
-
-const int64 SYS_read = 0;
-const int64 SYS_write = 1;
-const int64 SYS_open = 2;
-const int64 SYS_close = 3;
-const int64 SYS_lseek = 8;
-
-int64 write(int64 fd, const char *buf, uint64 count)
-{
- int64 ret;
- __asm__ volatile("syscall" : "=a"(ret) : "a"(SYS_write), "D"(fd), "S"(buf), "d"(count) : "rcx", "r11", "memory");
- return ret;
-}
-int64 read(int64 fd, char *buf, uint64 count)
-{
- int64 ret;
- __asm__ volatile("syscall" : "=a"(ret) : "a"(SYS_read), "D"(fd), "S"(buf), "d"(count) : "rcx", "r11", "memory");
- return ret;
-}
-int64 open(const char *path, int flags, int mode)
-{
- int64 ret;
- __asm__ volatile("syscall" : "=a"(ret) : "a"(SYS_open), "D"(path), "S"(flags), "d"(mode) : "rcx", "r11", "memory");
- return ret;
-}
-int64 close(int64 fd)
-{
- int64 ret;
- __asm__ volatile("syscall" : "=a"(ret) : "a"(SYS_close), "D"(fd) : "rcx", "r11", "memory");
- return ret;
-}
-int64 lseek(int64 fd, int64 offset, int whence)
-{
- int64 ret;
- __asm__ volatile("syscall" : "=a"(ret) : "a"(SYS_lseek), "D"(fd), "S"(offset), "d"(whence) : "rcx", "r11", "memory");
- return ret;
-}
-
-#elif defined(__riscv)
-
-const int64 SYS_read = 63;
-const int64 SYS_write = 64;
-const int64 SYS_open = 56; // openat
-const int64 SYS_close = 57;
-const int64 SYS_lseek = 62;
-
-int64 write(int64 fd, const char *buf, uint64 count)
-{
- register int64 a7 asm("a7") = SYS_write;
- register int64 a0 asm("a0") = fd;
- register int64 a1 asm("a1") = (int64)buf;
- register int64 a2 asm("a2") = count;
- __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a0), "r"(a1), "r"(a2) : "memory");
- return a0;
-}
-int64 read(int64 fd, char *buf, uint64 count)
-{
- register int64 a7 asm("a7") = SYS_read;
- register int64 a0 asm("a0") = fd;
- register int64 a1 asm("a1") = (int64)buf;
- register int64 a2 asm("a2") = count;
- __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a0), "r"(a1), "r"(a2) : "memory");
- return a0;
-}
-int64 open(const char *path, int flags, int mode)
-{
- register int64 a7 asm("a7") = SYS_open;
- register int64 a0 asm("a0") = -100; // AT_FDCWD
- register int64 a1 asm("a1") = (int64)path;
- register int64 a2 asm("a2") = flags;
- register int64 a3 asm("a3") = mode;
- __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3) : "memory");
- return a0;
-}
-int64 close(int64 fd)
-{
- register int64 a7 asm("a7") = SYS_close;
- register int64 a0 asm("a0") = fd;
- __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a0) : "memory");
- return a0;
-}
-int64 lseek(int64 fd, int64 offset, int whence)
-{
- register int64 a7 asm("a7") = SYS_lseek;
- register int64 a0 asm("a0") = fd;
- register int64 a1 asm("a1") = offset;
- register int64 a2 asm("a2") = whence;
- __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a0), "r"(a1), "r"(a2) : "memory");
- return a0;
-}
-
-#else
-#error "Architecture not supported"
-#endif
-
-/* Memory and String Functions */
-
-void *memset(void *dst, int c, uint64 n)
-{
- char *cdst = (char *)dst;
- for (uint64 i = 0; i < n; i++)
- cdst[i] = (char)c;
- return dst;
-}
-
-void *memmove(void *vdst, const void *vsrc, uint64 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, uint64 n) { return memmove(vdst, vsrc, n); }
-
-int memcmp(const void *s1, const void *s2, uint64 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;
-}
-
-uint64 strlen(const char *s)
-{
- const char *p = s;
- while (*p)
- p++;
- return (uint64)(p - s);
-}
-
-char *strcpy(char *dst, const char *src)
-{
- char *os = dst;
- while ((*dst++ = *src++) != 0)
- ;
- return os;
-}
-
-char *strcat(char *dst, const char *src)
-{
- char *os = dst;
- while (*dst)
- dst++;
- while ((*dst++ = *src++) != 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);
-}
-
-static int isspace(int c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
-}
-
-int64 strtoll(const char *str, char **endptr, int base)
-{
- const char *s = str;
- int64 acc = 0;
- int c;
- int neg = 0;
- int any = 0;
-
- while (isspace(*s))
- s++;
- if (*s == '-')
- {
- neg = 1;
- s++;
- }
- else if (*s == '+')
- {
- s++;
- }
-
- if ((base == 0 || base == 16) && *s == '0' && (s[1] == 'x' || s[1] == 'X'))
- {
- c = s[2];
- s += 2;
- base = 16;
- }
- else if (base == 0 && *s == '0')
- {
- base = 8;
- }
- else if (base == 0)
- {
- base = 10;
- }
-
- for (;; c = *s++)
- {
- c = *s;
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'A' && c <= 'Z')
- c -= 'A' - 10;
- else if (c >= 'a' && c <= 'z')
- c -= 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > (0x7FFFFFFFFFFFFFFFLL / base))
- any = -1;
- else
- {
- acc *= base;
- acc += c;
- any = 1;
- }
- }
- if (endptr != 0)
- *endptr = (char *)(any ? s : str);
- return (neg ? -acc : acc);
-}
-
-/* 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;
- int fd;
-} _OutContext;
-
-static void _out_char(_OutContext *ctx, char c)
-{
- if (ctx->fd != -1)
- {
- write(ctx->fd, &c, 1);
- 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.fd = -1;
- _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.fd = STDOUT_FD;
- _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
-
-#define MAX_FILES 8
-static FILE _file_pool[MAX_FILES];
-static FILE _stdin = {.fd = 0, .used = 1};
-static FILE _stdout = {.fd = 1, .used = 1};
-static FILE _stderr = {.fd = 2, .used = 1};
-
-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;
-
- FILE *f = NULL;
- for (int i = 0; i < MAX_FILES; i++)
- if (!_file_pool[i].used)
- {
- f = &_file_pool[i];
- break;
- }
- if (!f)
- return NULL;
-
- int64 fd = open(filename, flags, 0666);
- if (fd < 0)
- return NULL;
- f->fd = (int)fd;
- f->flags = flags;
- f->error = 0;
- f->eof = 0;
- f->used = 1;
- return f;
-}
-
-int fclose(FILE *stream)
-{
- if (!stream || !stream->used)
- return -1;
- if (stream == stdin || stream == stdout || stream == stderr)
- return 0;
- close(stream->fd);
- stream->used = 0;
- stream->fd = -1;
- return 0;
-}
-
-int fflush(FILE *stream) { 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.fd = stream->fd;
- _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 -1;
- char ch = (char)c;
- write(stream->fd, &ch, 1);
- return c;
-}
-
-int fputs(const char *s, FILE *stream)
-{
- if (!stream)
- return -1;
- write(stream->fd, s, strlen(s));
- return 0;
-}
-
-int fgetc(FILE *stream)
-{
- if (!stream)
- return -1;
- char c;
- if (read(stream->fd, &c, 1) == 1)
- return (unsigned char)c;
- stream->eof = 1;
- return -1;
-}
-
-char *fgets(char *str, int n, FILE *stream)
-{
- if (!stream || !stream->used || 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 || !stream->used || !ptr || size == 0 || nmemb == 0)
- return 0;
- uint64 total = size * nmemb, read_bytes = 0;
- char *p = (char *)ptr;
- while (read_bytes < total)
- {
- int64 ret = read(stream->fd, p + read_bytes, total - read_bytes);
- if (ret > 0)
- read_bytes += ret;
- else if (ret == 0)
- {
- stream->eof = 1;
- break;
- }
- else
- {
- stream->error = 1;
- break;
- }
- }
- return read_bytes / size;
-}
-
-uint64 fwrite(const void *ptr, uint64 size, uint64 nmemb, FILE *stream)
-{
- if (!stream || !stream->used || !ptr || size == 0 || nmemb == 0)
- return 0;
- uint64 total = size * nmemb, written = 0;
- const char *p = (const char *)ptr;
- while (written < total)
- {
- int64 ret = write(stream->fd, p + written, total - written);
- if (ret > 0)
- written += ret;
- else
- {
- stream->error = 1;
- break;
- }
- }
- return written / size;
-}
-
-int fseek(FILE *stream, long offset, int whence)
-{
- if (!stream || !stream->used)
- return -1;
- stream->eof = 0;
- if (lseek(stream->fd, offset, whence) < 0)
- {
- stream->error = 1;
- return -1;
- }
- return 0;
-}
-long ftell(FILE *stream)
-{
- if (!stream || !stream->used)
- 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->used) ? stream->eof : 1; }
-int ferror(FILE *stream) { return (stream && stream->used) ? stream->error : 1; }
-void clearerr(FILE *stream)
-{
- if (stream && stream->used)
- {
- stream->error = 0;
- stream->eof = 0;
- }
-} \ No newline at end of file