]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: ulibc DOOM-ready extensions — fseek, ftell, sprintf, sscanf, strdup, etc.
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 07:48:04 +0000 (04:48 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
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

user/ulibc/include/stdio.h
user/ulibc/include/stdlib.h
user/ulibc/include/string.h
user/ulibc/src/stdio.c
user/ulibc/src/stdlib.c
user/ulibc/src/string.c

index b750f2919018860fa2fb4713dce140194f3d9f04..050b529e49c706256ee13a499c576e8010f91b1e 100644 (file)
@@ -34,10 +34,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);
@@ -52,7 +61,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
index e52655c8fb1610702d79faa97e437566b584363f..3f486342ffd698c5971452368014afc8e22289e9 100644 (file)
@@ -19,6 +19,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
index 3c84dc40939f161c3ce9b050b23b53638fb0b748..8aa13a106ef7d131eab73251cdc9d459937ec90e 100644 (file)
@@ -25,5 +25,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
index f20b4cad6d727913a7cf7ac639db0eb4ebe6e1a7..de941ef40b8258df596fbffad85bbef3350521aa 100644 (file)
@@ -146,6 +146,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);
@@ -318,6 +351,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);
@@ -326,6 +367,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);
index fc65f2566171f98cb40f02a4e222324b8ae82677..87e4092e225d5aaf535a7a1cda1c4b34151d80f3 100644 (file)
@@ -115,6 +115,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);
 }
index e985da075ab9b10c877a408ae6c0129eabe79d80..2780f22205bef4b1b5a71c51eb5919ae7cfb1fae 100644 (file)
@@ -100,3 +100,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;
+}