From: Tulio A M Mendes Date: Thu, 12 Feb 2026 07:48:04 +0000 (-0300) Subject: feat: ulibc DOOM-ready extensions — fseek, ftell, sprintf, sscanf, strdup, etc. X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=cfed4810a9004608c9785eaadba8d0e158b0437d;p=AdrOS.git feat: ulibc DOOM-ready extensions — fseek, ftell, sprintf, sscanf, strdup, etc. Added missing C library functions required by the DOOM engine: stdio: fseek, ftell, rewind, sprintf, sscanf (minimal %d/%s), remove, rename (stub) stdlib: getenv (stub), abs, labs string: strncat, strdup, strcasecmp, strncasecmp, strstr, memchr, strtok --- diff --git a/user/ulibc/include/stdio.h b/user/ulibc/include/stdio.h index bfeaafd..dd50fdb 100644 --- a/user/ulibc/include/stdio.h +++ b/user/ulibc/include/stdio.h @@ -25,10 +25,19 @@ extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + FILE* fopen(const char* path, const char* mode); int fclose(FILE* fp); size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp); size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp); +int fseek(FILE* fp, long offset, int whence); +long ftell(FILE* fp); +void rewind(FILE* fp); int fflush(FILE* fp); int fgetc(FILE* fp); char* fgets(char* s, int size, FILE* fp); @@ -43,7 +52,11 @@ int putchar(int c); int puts(const char* s); int printf(const char* fmt, ...) __attribute__((format(printf, 1, 2))); int vprintf(const char* fmt, va_list ap); +int sprintf(char* buf, const char* fmt, ...) __attribute__((format(printf, 2, 3))); int snprintf(char* buf, size_t size, const char* fmt, ...) __attribute__((format(printf, 3, 4))); int vsnprintf(char* buf, size_t size, const char* fmt, va_list ap); +int sscanf(const char* str, const char* fmt, ...); +int remove(const char* path); +int rename(const char* oldpath, const char* newpath); #endif diff --git a/user/ulibc/include/stdlib.h b/user/ulibc/include/stdlib.h index 96b9c97..81f3353 100644 --- a/user/ulibc/include/stdlib.h +++ b/user/ulibc/include/stdlib.h @@ -10,6 +10,10 @@ void* realloc(void* ptr, size_t size); int atoi(const char* s); char* realpath(const char* path, char* resolved); +char* getenv(const char* name); +int abs(int x); +long labs(long x); + void exit(int status) __attribute__((noreturn)); #ifndef NULL diff --git a/user/ulibc/include/string.h b/user/ulibc/include/string.h index 10fe09d..917e25e 100644 --- a/user/ulibc/include/string.h +++ b/user/ulibc/include/string.h @@ -16,5 +16,12 @@ int strncmp(const char* a, const char* b, size_t n); char* strchr(const char* s, int c); char* strrchr(const char* s, int c); char* strcat(char* dst, const char* src); +char* strncat(char* dst, const char* src, size_t n); +char* strdup(const char* s); +int strcasecmp(const char* a, const char* b); +int strncasecmp(const char* a, const char* b, size_t n); +char* strstr(const char* haystack, const char* needle); +void* memchr(const void* s, int c, size_t n); +char* strtok(char* str, const char* delim); #endif diff --git a/user/ulibc/src/stdio.c b/user/ulibc/src/stdio.c index 2dbf69f..fd599e6 100644 --- a/user/ulibc/src/stdio.c +++ b/user/ulibc/src/stdio.c @@ -137,6 +137,39 @@ int fputs(const char* s, FILE* fp) { int feof(FILE* fp) { return fp ? (fp->flags & _STDIO_EOF) : 0; } int ferror(FILE* fp) { return fp ? (fp->flags & _STDIO_ERR) : 0; } +int fseek(FILE* fp, long offset, int whence) { + if (!fp) return -1; + fflush(fp); + fp->buf_pos = 0; + fp->buf_len = 0; + fp->flags &= ~_STDIO_EOF; + int rc = lseek(fp->fd, (int)offset, whence); + return (rc < 0) ? -1 : 0; +} + +long ftell(FILE* fp) { + if (!fp) return -1; + long pos = (long)lseek(fp->fd, 0, 1 /* SEEK_CUR */); + if (pos < 0) return -1; + if (fp->flags & _STDIO_READ) { + pos -= (long)(fp->buf_len - fp->buf_pos); + } + return pos; +} + +void rewind(FILE* fp) { + if (fp) fseek(fp, 0, 0 /* SEEK_SET */); +} + +int remove(const char* path) { + return unlink(path); +} + +int rename(const char* oldpath, const char* newpath) { + (void)oldpath; (void)newpath; + return -1; +} + int vfprintf(FILE* fp, const char* fmt, va_list ap) { char buf[1024]; int n = vsnprintf(buf, sizeof(buf), fmt, ap); @@ -309,6 +342,14 @@ done: #undef PUTC } +int sprintf(char* buf, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vsnprintf(buf, (size_t)0x7FFFFFFF, fmt, ap); + va_end(ap); + return r; +} + int snprintf(char* buf, size_t size, const char* fmt, ...) { va_list ap; va_start(ap, fmt); @@ -317,6 +358,51 @@ int snprintf(char* buf, size_t size, const char* fmt, ...) { return r; } +int sscanf(const char* str, const char* fmt, ...) { + /* Minimal sscanf: only supports %d and %s */ + va_list ap; + va_start(ap, fmt); + int count = 0; + const char* s = str; + const char* f = fmt; + while (*f && *s) { + if (*f == '%') { + f++; + if (*f == 'd' || *f == 'i') { + f++; + int* out = va_arg(ap, int*); + int neg = 0; + while (*s == ' ') s++; + if (*s == '-') { neg = 1; s++; } + else if (*s == '+') { s++; } + if (*s < '0' || *s > '9') break; + int val = 0; + while (*s >= '0' && *s <= '9') { val = val * 10 + (*s - '0'); s++; } + *out = neg ? -val : val; + count++; + } else if (*f == 's') { + f++; + char* out = va_arg(ap, char*); + while (*s == ' ') s++; + int i = 0; + while (*s && *s != ' ' && *s != '\n' && *s != '\t') out[i++] = *s++; + out[i] = '\0'; + count++; + } else { + break; + } + } else if (*f == ' ') { + f++; + while (*s == ' ') s++; + } else { + if (*f != *s) break; + f++; s++; + } + } + va_end(ap); + return count; +} + int vprintf(const char* fmt, va_list ap) { char buf[1024]; int n = vsnprintf(buf, sizeof(buf), fmt, ap); diff --git a/user/ulibc/src/stdlib.c b/user/ulibc/src/stdlib.c index de10e2a..0fa6273 100644 --- a/user/ulibc/src/stdlib.c +++ b/user/ulibc/src/stdlib.c @@ -106,6 +106,19 @@ char* realpath(const char* path, char* resolved) { return resolved; } +char* getenv(const char* name) { + (void)name; + return (char*)0; +} + +int abs(int x) { + return x < 0 ? -x : x; +} + +long labs(long x) { + return x < 0 ? -x : x; +} + void exit(int status) { _exit(status); } diff --git a/user/ulibc/src/string.c b/user/ulibc/src/string.c index 1201fe2..505fd3b 100644 --- a/user/ulibc/src/string.c +++ b/user/ulibc/src/string.c @@ -91,3 +91,72 @@ char* strcat(char* dst, const char* src) { *p = 0; return dst; } + +char* strncat(char* dst, const char* src, size_t n) { + char* p = dst; + while (*p) p++; + size_t i = 0; + while (i < n && src[i]) { *p++ = src[i++]; } + *p = 0; + return dst; +} + +char* strdup(const char* s) { + if (!s) return (void*)0; + size_t len = strlen(s) + 1; + extern void* malloc(size_t); + char* d = (char*)malloc(len); + if (d) memcpy(d, s, len); + return d; +} + +static int tolower_impl(int c) { + return (c >= 'A' && c <= 'Z') ? c + 32 : c; +} + +int strcasecmp(const char* a, const char* b) { + while (*a && tolower_impl((unsigned char)*a) == tolower_impl((unsigned char)*b)) { a++; b++; } + return tolower_impl((unsigned char)*a) - tolower_impl((unsigned char)*b); +} + +int strncasecmp(const char* a, const char* b, size_t n) { + for (size_t i = 0; i < n; i++) { + int ca = tolower_impl((unsigned char)a[i]); + int cb = tolower_impl((unsigned char)b[i]); + if (ca != cb) return ca - cb; + if (a[i] == 0) break; + } + return 0; +} + +char* strstr(const char* haystack, const char* needle) { + if (!*needle) return (char*)haystack; + size_t nlen = strlen(needle); + while (*haystack) { + if (strncmp(haystack, needle, nlen) == 0) return (char*)haystack; + haystack++; + } + return (void*)0; +} + +void* memchr(const void* s, int c, size_t n) { + const uint8_t* p = (const uint8_t*)s; + for (size_t i = 0; i < n; i++) { + if (p[i] == (uint8_t)c) return (void*)(p + i); + } + return (void*)0; +} + +static char* strtok_state = (void*)0; + +char* strtok(char* str, const char* delim) { + if (str) strtok_state = str; + if (!strtok_state) return (void*)0; + /* skip leading delimiters */ + while (*strtok_state && strchr(delim, *strtok_state)) strtok_state++; + if (!*strtok_state) return (void*)0; + char* start = strtok_state; + while (*strtok_state && !strchr(delim, *strtok_state)) strtok_state++; + if (*strtok_state) *strtok_state++ = 0; + return start; +}