luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

libc.c (30450B)


      1 #include <stddef.h>
      2 #include <stdint.h>
      3 #include <stdarg.h>
      4 #include <time.h>
      5 #include <locale.h>
      6 
      7 /* Forward declarations for types used in stubs */
      8 typedef long off_t;
      9 #define EOF (-1)
     10 
     11 /* Global errno */
     12 int errno = 0;
     13 
     14 /* ========== String Functions ========== */
     15 
     16 void *memcpy(void *dest, const void *src, size_t n) {
     17     unsigned char *d = dest;
     18     const unsigned char *s = src;
     19     while (n--) *d++ = *s++;
     20     return dest;
     21 }
     22 
     23 void *memset(void *s, int c, size_t n) {
     24     unsigned char *p = s;
     25     while (n--) *p++ = (unsigned char)c;
     26     return s;
     27 }
     28 
     29 void *memmove(void *dest, const void *src, size_t n) {
     30     unsigned char *d = dest;
     31     const unsigned char *s = src;
     32     if (d < s) {
     33         while (n--) *d++ = *s++;
     34     } else {
     35         d += n;
     36         s += n;
     37         while (n--) *--d = *--s;
     38     }
     39     return dest;
     40 }
     41 
     42 int memcmp(const void *s1, const void *s2, size_t n) {
     43     const unsigned char *p1 = s1, *p2 = s2;
     44     while (n--) {
     45         if (*p1 != *p2) return *p1 - *p2;
     46         p1++; p2++;
     47     }
     48     return 0;
     49 }
     50 
     51 size_t strlen(const char *s) {
     52     size_t len = 0;
     53     while (*s++) len++;
     54     return len;
     55 }
     56 
     57 char *strcpy(char *dest, const char *src) {
     58     char *ret = dest;
     59     while ((*dest++ = *src++));
     60     return ret;
     61 }
     62 
     63 char *strncpy(char *dest, const char *src, size_t n) {
     64     size_t i;
     65     for (i = 0; i < n && src[i] != '\0'; i++)
     66         dest[i] = src[i];
     67     for (; i < n; i++)
     68         dest[i] = '\0';
     69     return dest;
     70 }
     71 
     72 int strcmp(const char *s1, const char *s2) {
     73     while (*s1 && (*s1 == *s2)) {
     74         s1++; s2++;
     75     }
     76     return *(unsigned char *)s1 - *(unsigned char *)s2;
     77 }
     78 
     79 int strncmp(const char *s1, const char *s2, size_t n) {
     80     while (n && *s1 && (*s1 == *s2)) {
     81         s1++; s2++; n--;
     82     }
     83     if (n == 0) return 0;
     84     return *(unsigned char *)s1 - *(unsigned char *)s2;
     85 }
     86 
     87 char *strchr(const char *s, int c) {
     88     while (*s != (char)c) {
     89         if (!*s++) return NULL;
     90     }
     91     return (char *)s;
     92 }
     93 
     94 char *strrchr(const char *s, int c) {
     95     const char *last = NULL;
     96     do {
     97         if (*s == (char)c) last = s;
     98     } while (*s++);
     99     return (char *)last;
    100 }
    101 
    102 char *strstr(const char *haystack, const char *needle) {
    103     if (!*needle) return (char *)haystack;
    104 
    105     for (; *haystack; haystack++) {
    106         const char *h = haystack;
    107         const char *n = needle;
    108 
    109         while (*h && *n && (*h == *n)) {
    110             h++;
    111             n++;
    112         }
    113 
    114         if (!*n) return (char *)haystack;
    115     }
    116 
    117     return NULL;
    118 }
    119 
    120 int tolower(int c) {
    121     if (c >= 'A' && c <= 'Z')
    122         return c + ('a' - 'A');
    123     return c;
    124 }
    125 
    126 int toupper(int c) {
    127     if (c >= 'a' && c <= 'z')
    128         return c - ('a' - 'A');
    129     return c;
    130 }
    131 
    132 /* ========== Memory Allocation ========== */
    133 
    134 /*
    135  * Free-list allocator with block coalescing
    136  * Each block has a header with size and free/used flag
    137  * Free blocks are linked in a free list for reuse
    138  */
    139 
    140 #define HEAP_SIZE (384 * 1024 * 1024)  /* 384 MB heap for LuaJIT + ramdisk + apps */
    141 static uint8_t heap[HEAP_SIZE] __attribute__((aligned(4096)));
    142 
    143 /* Block header - stored before each allocation */
    144 typedef struct block_header {
    145     size_t size;                    /* Size of user data (not including header) */
    146     struct block_header *next_free; /* Next free block (only valid if free) */
    147     uint32_t magic;                 /* Magic number for validation */
    148     uint32_t is_free;               /* 1 if free, 0 if allocated */
    149 } block_header_t;
    150 
    151 #define BLOCK_MAGIC 0xDEADBEEF
    152 #define HEADER_SIZE ((sizeof(block_header_t) + 15) & ~15)  /* Aligned header size */
    153 #define MIN_BLOCK_SIZE 32  /* Minimum user data size */
    154 
    155 /* Free list head */
    156 static block_header_t *free_list = NULL;
    157 static int heap_initialized = 0;
    158 static size_t heap_end = 0;  /* Current end of used heap */
    159 
    160 extern void terminal_writestring(const char *);
    161 extern void terminal_putchar(char);
    162 
    163 static void print_hex(unsigned long val) {
    164     char buf[16];
    165     int i = 0;
    166     if (val == 0) {
    167         terminal_putchar('0');
    168         return;
    169     }
    170     while (val > 0 && i < 16) {
    171         int digit = val & 0xF;
    172         buf[i++] = (digit < 10) ? '0' + digit : 'a' + digit - 10;
    173         val >>= 4;
    174     }
    175     while (i > 0) terminal_putchar(buf[--i]);
    176 }
    177 
    178 /* Initialize heap if needed */
    179 static void heap_init(void) {
    180     if (heap_initialized) return;
    181     heap_initialized = 1;
    182     heap_end = 0;
    183     free_list = NULL;
    184 }
    185 
    186 /* Get header from user pointer */
    187 static inline block_header_t *get_header(void *ptr) {
    188     return (block_header_t *)((uint8_t *)ptr - HEADER_SIZE);
    189 }
    190 
    191 /* Get user pointer from header */
    192 static inline void *get_user_ptr(block_header_t *header) {
    193     return (void *)((uint8_t *)header + HEADER_SIZE);
    194 }
    195 
    196 /* Find a free block that fits, using first-fit strategy */
    197 static block_header_t *find_free_block(size_t size) {
    198     block_header_t *curr = free_list;
    199     block_header_t *prev = NULL;
    200 
    201     while (curr) {
    202         if (curr->size >= size) {
    203             /* Remove from free list */
    204             if (prev) {
    205                 prev->next_free = curr->next_free;
    206             } else {
    207                 free_list = curr->next_free;
    208             }
    209             curr->next_free = NULL;
    210             curr->is_free = 0;
    211             return curr;
    212         }
    213         prev = curr;
    214         curr = curr->next_free;
    215     }
    216     return NULL;
    217 }
    218 
    219 /* Allocate a new block from the heap end */
    220 static block_header_t *alloc_new_block(size_t size) {
    221     size_t total_size = HEADER_SIZE + size;
    222 
    223     if (heap_end + total_size > HEAP_SIZE) {
    224         return NULL;  /* Out of memory */
    225     }
    226 
    227     block_header_t *header = (block_header_t *)&heap[heap_end];
    228     heap_end += total_size;
    229 
    230     header->size = size;
    231     header->next_free = NULL;
    232     header->magic = BLOCK_MAGIC;
    233     header->is_free = 0;
    234 
    235     return header;
    236 }
    237 
    238 void *malloc(size_t size) {
    239     if (size == 0) return NULL;
    240 
    241     heap_init();
    242 
    243     /* Align size to 16 bytes, with minimum */
    244     size = (size + 15) & ~15;
    245     if (size < MIN_BLOCK_SIZE) size = MIN_BLOCK_SIZE;
    246 
    247     /* Try to find a free block first */
    248     block_header_t *header = find_free_block(size);
    249 
    250     if (!header) {
    251         /* No suitable free block, allocate new */
    252         header = alloc_new_block(size);
    253         if (!header) {
    254             terminal_writestring("MALLOC OOM: size=");
    255             print_hex(size);
    256             terminal_writestring(" heap_end=");
    257             print_hex(heap_end);
    258             terminal_writestring("\n");
    259             return NULL;
    260         }
    261     }
    262 
    263     void *ptr = get_user_ptr(header);
    264     memset(ptr, 0, header->size);  /* Zero initialize */
    265     return ptr;
    266 }
    267 
    268 void free(void *ptr) {
    269     if (!ptr) return;
    270 
    271     block_header_t *header = get_header(ptr);
    272 
    273     /* Validate the block */
    274     if (header->magic != BLOCK_MAGIC) {
    275         terminal_writestring("FREE: invalid pointer (bad magic)\n");
    276         return;
    277     }
    278 
    279     if (header->is_free) {
    280         terminal_writestring("FREE: double free detected\n");
    281         return;
    282     }
    283 
    284     /* Mark as free and add to free list (front insertion) */
    285     header->is_free = 1;
    286     header->next_free = free_list;
    287     free_list = header;
    288 }
    289 
    290 void *realloc(void *ptr, size_t size) {
    291     if (!ptr) return malloc(size);
    292 
    293     if (size == 0) {
    294         free(ptr);
    295         return NULL;
    296     }
    297 
    298     block_header_t *header = get_header(ptr);
    299 
    300     /* Validate */
    301     if (header->magic != BLOCK_MAGIC) {
    302         terminal_writestring("REALLOC: invalid pointer\n");
    303         return NULL;
    304     }
    305 
    306     /* If current block is large enough, reuse it */
    307     size_t aligned_size = (size + 15) & ~15;
    308     if (aligned_size < MIN_BLOCK_SIZE) aligned_size = MIN_BLOCK_SIZE;
    309 
    310     if (header->size >= aligned_size) {
    311         return ptr;  /* Current block is big enough */
    312     }
    313 
    314     /* Need to allocate new block */
    315     void *new_ptr = malloc(size);
    316     if (new_ptr) {
    317         memcpy(new_ptr, ptr, header->size);  /* Copy old data */
    318         free(ptr);
    319     }
    320     return new_ptr;
    321 }
    322 
    323 void *calloc(size_t nmemb, size_t size) {
    324     size_t total = nmemb * size;
    325     void *ptr = malloc(total);
    326     /* malloc already zeros memory */
    327     return ptr;
    328 }
    329 
    330 /* ========== Program Termination ========== */
    331 
    332 void abort(void) {
    333     while (1) {
    334         __asm__ volatile ("cli; hlt");
    335     }
    336 }
    337 
    338 void exit(int status) {
    339     (void)status;
    340     while (1) {
    341         __asm__ volatile ("cli; hlt");
    342     }
    343 }
    344 
    345 /* ========== Math Functions ========== */
    346 
    347 int abs(int n) {
    348     return n < 0 ? -n : n;
    349 }
    350 
    351 long labs(long n) {
    352     return n < 0 ? -n : n;
    353 }
    354 
    355 /* ========== String to Number Conversion ========== */
    356 
    357 int atoi(const char *nptr) {
    358     int result = 0;
    359     int sign = 1;
    360 
    361     while (*nptr == ' ' || *nptr == '\t') nptr++;
    362 
    363     if (*nptr == '-') {
    364         sign = -1;
    365         nptr++;
    366     } else if (*nptr == '+') {
    367         nptr++;
    368     }
    369 
    370     while (*nptr >= '0' && *nptr <= '9') {
    371         result = result * 10 + (*nptr - '0');
    372         nptr++;
    373     }
    374 
    375     return sign * result;
    376 }
    377 
    378 long strtol(const char *nptr, char **endptr, int base) {
    379     long result = 0;
    380     int sign = 1;
    381 
    382     while (*nptr == ' ' || *nptr == '\t') nptr++;
    383 
    384     if (*nptr == '-') {
    385         sign = -1;
    386         nptr++;
    387     } else if (*nptr == '+') {
    388         nptr++;
    389     }
    390 
    391     if (base == 0) {
    392         if (*nptr == '0') {
    393             nptr++;
    394             if (*nptr == 'x' || *nptr == 'X') {
    395                 base = 16;
    396                 nptr++;
    397             } else {
    398                 base = 8;
    399             }
    400         } else {
    401             base = 10;
    402         }
    403     }
    404 
    405     while (*nptr) {
    406         int digit;
    407         if (*nptr >= '0' && *nptr <= '9') digit = *nptr - '0';
    408         else if (*nptr >= 'a' && *nptr <= 'z') digit = *nptr - 'a' + 10;
    409         else if (*nptr >= 'A' && *nptr <= 'Z') digit = *nptr - 'A' + 10;
    410         else break;
    411 
    412         if (digit >= base) break;
    413         result = result * base + digit;
    414         nptr++;
    415     }
    416 
    417     if (endptr) *endptr = (char *)nptr;
    418     return sign * result;
    419 }
    420 
    421 unsigned long strtoul(const char *nptr, char **endptr, int base) {
    422     unsigned long result = 0;
    423 
    424     while (*nptr == ' ' || *nptr == '\t') nptr++;
    425 
    426     if (*nptr == '+') nptr++;
    427 
    428     if (base == 0) {
    429         if (*nptr == '0') {
    430             nptr++;
    431             if (*nptr == 'x' || *nptr == 'X') {
    432                 base = 16;
    433                 nptr++;
    434             } else {
    435                 base = 8;
    436             }
    437         } else {
    438             base = 10;
    439         }
    440     }
    441 
    442     while (*nptr) {
    443         int digit;
    444         if (*nptr >= '0' && *nptr <= '9') digit = *nptr - '0';
    445         else if (*nptr >= 'a' && *nptr <= 'z') digit = *nptr - 'a' + 10;
    446         else if (*nptr >= 'A' && *nptr <= 'Z') digit = *nptr - 'A' + 10;
    447         else break;
    448 
    449         if (digit >= base) break;
    450         result = result * base + digit;
    451         nptr++;
    452     }
    453 
    454     if (endptr) *endptr = (char *)nptr;
    455     return result;
    456 }
    457 
    458 double strtod(const char *nptr, char **endptr) {
    459     /* Very basic implementation - doesn't handle exponents */
    460     double result = 0.0;
    461     double sign = 1.0;
    462 
    463     while (*nptr == ' ' || *nptr == '\t') nptr++;
    464 
    465     if (*nptr == '-') {
    466         sign = -1.0;
    467         nptr++;
    468     } else if (*nptr == '+') {
    469         nptr++;
    470     }
    471 
    472     while (*nptr >= '0' && *nptr <= '9') {
    473         result = result * 10.0 + (*nptr - '0');
    474         nptr++;
    475     }
    476 
    477     if (*nptr == '.') {
    478         double frac = 0.1;
    479         nptr++;
    480         while (*nptr >= '0' && *nptr <= '9') {
    481             result += (*nptr - '0') * frac;
    482             frac *= 0.1;
    483             nptr++;
    484         }
    485     }
    486 
    487     if (endptr) *endptr = (char *)nptr;
    488     return sign * result;
    489 }
    490 
    491 /* ========== Random Numbers ========== */
    492 
    493 static unsigned int rand_seed = 1;
    494 
    495 int rand(void) {
    496     rand_seed = rand_seed * 1103515245 + 12345;
    497     return (rand_seed / 65536) % 32768;
    498 }
    499 
    500 void srand(unsigned int seed) {
    501     rand_seed = seed;
    502 }
    503 
    504 /* ========== Character Classification ========== */
    505 
    506 int isalnum(int c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
    507 int isalpha(int c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
    508 int isdigit(int c) { return c >= '0' && c <= '9'; }
    509 int isxdigit(int c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
    510 int islower(int c) { return c >= 'a' && c <= 'z'; }
    511 int isupper(int c) { return c >= 'A' && c <= 'Z'; }
    512 int isspace(int c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; }
    513 int isprint(int c) { return c >= 0x20 && c <= 0x7E; }
    514 int isgraph(int c) { return c > 0x20 && c <= 0x7E; }
    515 int iscntrl(int c) { return (c >= 0 && c < 0x20) || c == 0x7F; }
    516 int ispunct(int c) { return isgraph(c) && !isalnum(c); }
    517 
    518 /* ========== stdio Functions (Stubs) ========== */
    519 
    520 typedef struct _FILE {
    521     int dummy;
    522 } FILE;
    523 
    524 FILE __stdio_files[3];
    525 FILE *stdin = &__stdio_files[0];
    526 FILE *stdout = &__stdio_files[1];
    527 FILE *stderr = &__stdio_files[2];
    528 
    529 /* Simple printf implementation */
    530 extern void terminal_writestring(const char *);
    531 extern void terminal_putchar(char);
    532 
    533 static void print_num(long long num, int base, int is_signed) {
    534     char buf[32];
    535     int i = 0;
    536     int is_negative = 0;
    537 
    538     if (num == 0) {
    539         terminal_putchar('0');
    540         return;
    541     }
    542 
    543     if (is_signed && num < 0) {
    544         is_negative = 1;
    545         num = -num;
    546     }
    547 
    548     while (num > 0) {
    549         int digit = num % base;
    550         buf[i++] = (digit < 10) ? '0' + digit : 'a' + digit - 10;
    551         num /= base;
    552     }
    553 
    554     if (is_negative) terminal_putchar('-');
    555     while (i > 0) terminal_putchar(buf[--i]);
    556 }
    557 
    558 int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
    559     size_t pos = 0;
    560 
    561     while (*format && pos < size - 1) {
    562         if (*format == '%') {
    563             format++;
    564             if (*format == 'd' || *format == 'i') {
    565                 int val = va_arg(ap, int);
    566                 char buf[32];
    567                 int len = 0;
    568                 int is_neg = val < 0;
    569                 if (is_neg) val = -val;
    570                 do {
    571                     buf[len++] = '0' + (val % 10);
    572                     val /= 10;
    573                 } while (val && len < 31);
    574                 if (is_neg && pos < size - 1) str[pos++] = '-';
    575                 while (len > 0 && pos < size - 1) str[pos++] = buf[--len];
    576             } else if (*format == 'u') {
    577                 unsigned int val = va_arg(ap, unsigned int);
    578                 char buf[32];
    579                 int len = 0;
    580                 do {
    581                     buf[len++] = '0' + (val % 10);
    582                     val /= 10;
    583                 } while (val && len < 31);
    584                 while (len > 0 && pos < size - 1) str[pos++] = buf[--len];
    585             } else if (*format == 's') {
    586                 const char *s = va_arg(ap, const char *);
    587                 while (*s && pos < size - 1) str[pos++] = *s++;
    588             } else if (*format == 'c') {
    589                 if (pos < size - 1) str[pos++] = (char)va_arg(ap, int);
    590             } else if (*format == '%') {
    591                 if (pos < size - 1) str[pos++] = '%';
    592             }
    593             format++;
    594         } else {
    595             str[pos++] = *format++;
    596         }
    597     }
    598 
    599     if (size > 0) str[pos] = '\0';
    600     return pos;
    601 }
    602 
    603 int vsprintf(char *str, const char *format, va_list ap) {
    604     return vsnprintf(str, (size_t)-1, format, ap);
    605 }
    606 
    607 int snprintf(char *str, size_t size, const char *format, ...) {
    608     va_list ap;
    609     va_start(ap, format);
    610     int ret = vsnprintf(str, size, format, ap);
    611     va_end(ap);
    612     return ret;
    613 }
    614 
    615 int sprintf(char *str, const char *format, ...) {
    616     va_list ap;
    617     va_start(ap, format);
    618     int ret = vsprintf(str, format, ap);
    619     va_end(ap);
    620     return ret;
    621 }
    622 
    623 int vprintf(const char *format, va_list ap) {
    624     while (*format) {
    625         if (*format == '%') {
    626             format++;
    627             if (*format == 'd' || *format == 'i') {
    628                 print_num(va_arg(ap, int), 10, 1);
    629             } else if (*format == 'u') {
    630                 print_num(va_arg(ap, unsigned int), 10, 0);
    631             } else if (*format == 'x') {
    632                 print_num(va_arg(ap, unsigned int), 16, 0);
    633             } else if (*format == 's') {
    634                 terminal_writestring(va_arg(ap, const char *));
    635             } else if (*format == 'c') {
    636                 terminal_putchar((char)va_arg(ap, int));
    637             } else if (*format == '%') {
    638                 terminal_putchar('%');
    639             }
    640             format++;
    641         } else {
    642             terminal_putchar(*format++);
    643         }
    644     }
    645     return 0;
    646 }
    647 
    648 int printf(const char *format, ...) {
    649     va_list ap;
    650     va_start(ap, format);
    651     int ret = vprintf(format, ap);
    652     va_end(ap);
    653     return ret;
    654 }
    655 
    656 int fprintf(FILE *stream, const char *format, ...) {
    657     (void)stream;
    658     va_list ap;
    659     va_start(ap, format);
    660     int ret = vprintf(format, ap);
    661     va_end(ap);
    662     return ret;
    663 }
    664 
    665 int vfprintf(FILE *stream, const char *format, va_list ap) {
    666     (void)stream;
    667     return vprintf(format, ap);
    668 }
    669 
    670 int puts(const char *s) {
    671     terminal_writestring(s);
    672     terminal_putchar('\n');
    673     return 0;
    674 }
    675 
    676 int putchar(int c) {
    677     terminal_putchar(c);
    678     return c;
    679 }
    680 
    681 int fputs(const char *s, FILE *stream) {
    682     (void)stream;
    683     terminal_writestring(s);
    684     return 0;
    685 }
    686 
    687 int fputc(int c, FILE *stream) {
    688     (void)stream;
    689     terminal_putchar(c);
    690     return c;
    691 }
    692 
    693 FILE *fopen(const char *pathname, const char *mode) {
    694     (void)pathname; (void)mode;
    695     return NULL;
    696 }
    697 
    698 int fclose(FILE *stream) {
    699     (void)stream;
    700     return 0;
    701 }
    702 
    703 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    704     (void)ptr; (void)size; (void)nmemb; (void)stream;
    705     return 0;
    706 }
    707 
    708 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
    709     (void)ptr; (void)size; (void)nmemb; (void)stream;
    710     return 0;
    711 }
    712 
    713 int fseek(FILE *stream, long offset, int whence) {
    714     (void)stream; (void)offset; (void)whence;
    715     return -1;
    716 }
    717 
    718 long ftell(FILE *stream) {
    719     (void)stream;
    720     return -1;
    721 }
    722 
    723 void rewind(FILE *stream) {
    724     (void)stream;
    725 }
    726 
    727 int feof(FILE *stream) {
    728     (void)stream;
    729     return 0;
    730 }
    731 
    732 int ferror(FILE *stream) {
    733     (void)stream;
    734     return 0;
    735 }
    736 
    737 int fflush(FILE *stream) {
    738     (void)stream;
    739     return 0;
    740 }
    741 
    742 /* ========== Locale ========== */
    743 
    744 static struct lconv locale_conv = {
    745     .decimal_point = ".",
    746     .thousands_sep = "",
    747     .grouping = ""
    748 };
    749 
    750 char *setlocale(int category, const char *locale) {
    751     (void)category; (void)locale;
    752     return "C";
    753 }
    754 
    755 struct lconv *localeconv(void) {
    756     return &locale_conv;
    757 }
    758 
    759 /* ========== Time ========== */
    760 
    761 time_t time(time_t *t) {
    762     time_t dummy = 0;
    763     if (t) *t = dummy;
    764     return dummy;
    765 }
    766 
    767 clock_t clock(void) {
    768     return 0;
    769 }
    770 
    771 time_t mktime(struct tm *tm) {
    772     (void)tm;
    773     return 0;
    774 }
    775 
    776 char *getenv(const char *name) {
    777     (void)name;
    778     return NULL;
    779 }
    780 
    781 int system(const char *command) {
    782     (void)command;
    783     return -1;
    784 }
    785 
    786 struct tm *localtime_r(const time_t *timep, struct tm *result) {
    787     (void)timep;
    788     if (result) memset(result, 0, sizeof(struct tm));
    789     return result;
    790 }
    791 
    792 struct tm *gmtime_r(const time_t *timep, struct tm *result) {
    793     (void)timep;
    794     if (result) memset(result, 0, sizeof(struct tm));
    795     return result;
    796 }
    797 
    798 size_t strftime(char *s, size_t max, const char *format, const struct tm *tm) {
    799     (void)format; (void)tm;
    800     if (max > 0) s[0] = '\0';
    801     return 0;
    802 }
    803 
    804 int mkstemp64(char *template) {
    805     (void)template;
    806     errno = 38; /* ENOSYS */
    807     return -1;
    808 }
    809 
    810 int rename(const char *oldpath, const char *newpath) {
    811     (void)oldpath; (void)newpath;
    812     errno = 38; /* ENOSYS */
    813     return -1;
    814 }
    815 
    816 int remove(const char *pathname) {
    817     (void)pathname;
    818     errno = 38; /* ENOSYS */
    819     return -1;
    820 }
    821 
    822 FILE *tmpfile64(void) {
    823     return NULL;
    824 }
    825 
    826 FILE *popen(const char *command, const char *type) {
    827     (void)command; (void)type;
    828     return NULL;
    829 }
    830 
    831 int pclose(FILE *stream) {
    832     (void)stream;
    833     return -1;
    834 }
    835 
    836 double difftime(time_t time1, time_t time0) {
    837     return (double)(time1 - time0);
    838 }
    839 
    840 int ungetc(int c, FILE *stream) {
    841     (void)c; (void)stream;
    842     return EOF;
    843 }
    844 
    845 int __isoc99_fscanf(FILE *stream, const char *format, ...) {
    846     (void)stream; (void)format;
    847     return EOF;
    848 }
    849 
    850 int setvbuf(FILE *stream, char *buf, int mode, size_t size) {
    851     (void)stream; (void)buf; (void)mode; (void)size;
    852     return 0;
    853 }
    854 
    855 int fseeko64(FILE *stream, off_t offset, int whence) {
    856     (void)stream; (void)offset; (void)whence;
    857     return -1;
    858 }
    859 
    860 off_t ftello64(FILE *stream) {
    861     (void)stream;
    862     return -1;
    863 }
    864 
    865 void clearerr(FILE *stream) {
    866     (void)stream;
    867 }
    868 
    869 int getc(FILE *stream) {
    870     (void)stream;
    871     return EOF;
    872 }
    873 
    874 /* ========== setjmp/longjmp ========== */
    875 
    876 int setjmp(int env[6]) {
    877     __asm__ volatile (
    878         "movl %%ebx, 0(%0)\n"
    879         "movl %%esi, 4(%0)\n"
    880         "movl %%edi, 8(%0)\n"
    881         "movl %%ebp, 12(%0)\n"
    882         "leal 4(%%esp), %%eax\n"
    883         "movl %%eax, 16(%0)\n"
    884         "movl (%%esp), %%eax\n"
    885         "movl %%eax, 20(%0)\n"
    886         : : "r"(env) : "eax"
    887     );
    888     return 0;
    889 }
    890 
    891 void longjmp(int env[6], int val) {
    892     __asm__ volatile (
    893         "movl %1, %%eax\n"
    894         "testl %%eax, %%eax\n"
    895         "jnz 1f\n"
    896         "incl %%eax\n"
    897         "1:\n"
    898         "movl 0(%0), %%ebx\n"
    899         "movl 4(%0), %%esi\n"
    900         "movl 8(%0), %%edi\n"
    901         "movl 12(%0), %%ebp\n"
    902         "movl 16(%0), %%esp\n"
    903         "jmp *20(%0)\n"
    904         : : "r"(env), "m"(val) : "eax"
    905     );
    906     __builtin_unreachable();
    907 }
    908 
    909 /* ========== Additional Functions for LuaJIT ========== */
    910 
    911 /* Additional types needed */
    912 typedef long ssize_t;
    913 typedef long off_t;
    914 
    915 void *memchr(const void *s, int c, size_t n) {
    916     const unsigned char *p = s;
    917     while (n--) {
    918         if (*p == (unsigned char)c) return (void *)p;
    919         p++;
    920     }
    921     return NULL;
    922 }
    923 
    924 int *__errno_location(void) {
    925     return &errno;
    926 }
    927 
    928 /* Math function stubs - use GCC builtins where possible */
    929 double fabs(double x) { return __builtin_fabs(x); }
    930 double floor(double x) { return __builtin_floor(x); }
    931 double ceil(double x) { return __builtin_ceil(x); }
    932 double sqrt(double x) { return __builtin_sqrt(x); }
    933 double fmod(double x, double y) { return __builtin_fmod(x, y); }
    934 double pow(double x, double y) { return __builtin_pow(x, y); }
    935 double exp(double x) { return __builtin_exp(x); }
    936 double log(double x) { return __builtin_log(x); }
    937 double log2(double x) { return __builtin_log2(x); }
    938 double log10(double x) { return __builtin_log10(x); }
    939 double sin(double x) { return __builtin_sin(x); }
    940 double cos(double x) { return __builtin_cos(x); }
    941 double tan(double x) { return __builtin_tan(x); }
    942 double asin(double x) { return __builtin_asin(x); }
    943 double acos(double x) { return __builtin_acos(x); }
    944 double atan(double x) { return __builtin_atan(x); }
    945 double atan2(double y, double x) { return __builtin_atan2(y, x); }
    946 double sinh(double x) { return __builtin_sinh(x); }
    947 double cosh(double x) { return __builtin_cosh(x); }
    948 double tanh(double x) { return __builtin_tanh(x); }
    949 double ldexp(double x, int exp) { return __builtin_ldexp(x, exp); }
    950 
    951 float fabsf(float x) { return __builtin_fabsf(x); }
    952 float floorf(float x) { return __builtin_floorf(x); }
    953 float ceilf(float x) { return __builtin_ceilf(x); }
    954 float sqrtf(float x) { return __builtin_sqrtf(x); }
    955 float fmodf(float x, float y) { return __builtin_fmodf(x, y); }
    956 float powf(float x, float y) { return __builtin_powf(x, y); }
    957 
    958 /* System call stubs - these will fail but won't crash */
    959 /* Linux syscall numbers */
    960 #define SYS_getrandom 318
    961 
    962 long syscall(long number, ...) {
    963     /* Debug - FIRST thing to see if we even enter */
    964     extern void terminal_writestring(const char*);
    965     terminal_writestring("LIBC: syscall() ENTERED\n");
    966 
    967     va_list args;
    968     va_start(args, number);
    969 
    970     terminal_writestring("LIBC: checking number\n");
    971     if (number == SYS_getrandom) {
    972         terminal_writestring("LIBC: number is SYS_getrandom!\n");
    973         /* getrandom(void *buf, size_t buflen, unsigned int flags) */
    974         void *buf = va_arg(args, void*);
    975         size_t buflen = va_arg(args, size_t);
    976         unsigned int flags = va_arg(args, unsigned int);
    977         va_end(args);
    978 
    979         /* Debug */
    980         terminal_writestring("LIBC: about to call int 0x80\n");
    981 
    982         /* Make system call via int 0x80 */
    983         long ret;
    984         __asm__ volatile (
    985             "int $0x80"
    986             : "=a"(ret)
    987             : "a"(2), "b"(buf), "c"(buflen), "d"(flags)  /* syscall 2 = SYSCALL_GETRANDOM */
    988         );
    989 
    990         /* Debug return value */
    991         terminal_writestring("LIBC: syscall returned ");
    992         char num[16];
    993         int i = 0;
    994         long n = ret;
    995         if (n < 0) {
    996             terminal_writestring("-");
    997             n = -n;
    998         }
    999         do { num[i++] = '0' + (n % 10); n /= 10; } while (n > 0);
   1000         while (i > 0) {
   1001             char c = num[--i];
   1002             extern void terminal_putchar(char);
   1003             terminal_putchar(c);
   1004         }
   1005         terminal_putchar('\n');
   1006 
   1007         return ret;
   1008     }
   1009 
   1010     va_end(args);
   1011     errno = 38; /* ENOSYS */
   1012     return -1;
   1013 }
   1014 
   1015 int open64(const char *pathname, int flags, ...) {
   1016     (void)pathname; (void)flags;
   1017     errno = 38; /* ENOSYS */
   1018     return -1;
   1019 }
   1020 
   1021 ssize_t read(int fd, void *buf, size_t count) {
   1022     (void)fd; (void)buf; (void)count;
   1023     errno = 38; /* ENOSYS */
   1024     return -1;
   1025 }
   1026 
   1027 int close(int fd) {
   1028     (void)fd;
   1029     return 0;
   1030 }
   1031 
   1032 /* mmap - memory map stub (uses our allocator with block headers) */
   1033 /* All memory is executable in bare metal x86, so PROT_EXEC works automatically */
   1034 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
   1035     (void)addr; (void)fd; (void)offset;
   1036 
   1037     terminal_writestring("MMAP: len=");
   1038     print_hex(length);
   1039     terminal_writestring(" prot=");
   1040     print_hex(prot);
   1041     terminal_writestring(" flags=");
   1042     print_hex(flags);
   1043     terminal_writestring("\n");
   1044 
   1045     /* Allocate from our heap - LuaJIT uses this heavily */
   1046     if (length == 0) {
   1047         errno = 22; /* EINVAL */
   1048         terminal_writestring("MMAP: length=0, FAIL\n");
   1049         return (void *)-1;
   1050     }
   1051 
   1052     /* Align to page boundary (4KB) */
   1053     size_t aligned_length = (length + 4095) & ~4095;
   1054 
   1055     /* Use malloc which now supports free */
   1056     void *ptr = malloc(aligned_length);
   1057     if (!ptr) {
   1058         terminal_writestring("MMAP OOM: need=");
   1059         print_hex(aligned_length);
   1060         terminal_writestring(" heap_end=");
   1061         print_hex(heap_end);
   1062         terminal_writestring("\n");
   1063         errno = 12; /* ENOMEM */
   1064         return (void *)-1;
   1065     }
   1066 
   1067     terminal_writestring("MMAP OK: ptr=");
   1068     print_hex((unsigned long)ptr);
   1069     terminal_writestring(" used=");
   1070     print_hex(heap_end);
   1071     terminal_writestring("/");
   1072     print_hex(HEAP_SIZE);
   1073     terminal_writestring("\n");
   1074 
   1075     return ptr;
   1076 }
   1077 
   1078 void *mmap64(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
   1079     /* Just call regular mmap */
   1080     return mmap(addr, length, prot, flags, fd, offset);
   1081 }
   1082 
   1083 int munmap(void *addr, size_t length) {
   1084     (void)length;
   1085     /* Actually free the memory now */
   1086     if (addr) {
   1087         free(addr);
   1088     }
   1089     return 0;
   1090 }
   1091 
   1092 int mprotect(void *addr, size_t len, int prot) {
   1093     (void)addr; (void)len; (void)prot;
   1094     return 0;
   1095 }
   1096 
   1097 /* Dynamic loading stubs */
   1098 void *dlopen(const char *filename, int flags) {
   1099     (void)filename; (void)flags;
   1100     return NULL;
   1101 }
   1102 
   1103 void *dlsym(void *handle, const char *symbol) {
   1104     (void)handle; (void)symbol;
   1105     return NULL;
   1106 }
   1107 
   1108 int dlclose(void *handle) {
   1109     (void)handle;
   1110     return 0;
   1111 }
   1112 
   1113 char *dlerror(void) {
   1114     return "Dynamic loading not supported";
   1115 }
   1116 
   1117 FILE *fopen64(const char *pathname, const char *mode) {
   1118     (void)pathname; (void)mode;
   1119     return NULL;
   1120 }
   1121 
   1122 char *fgets(char *s, int size, FILE *stream) {
   1123     (void)s; (void)size; (void)stream;
   1124     return NULL;
   1125 }
   1126 
   1127 /* Unwind stubs for exception handling */
   1128 typedef void *_Unwind_Exception_Ptr;
   1129 typedef void *_Unwind_Context_Ptr;
   1130 typedef int _Unwind_Reason_Code;
   1131 
   1132 void _Unwind_SetGR(_Unwind_Context_Ptr ctx, int index, unsigned long val) {
   1133     (void)ctx; (void)index; (void)val;
   1134 }
   1135 
   1136 void _Unwind_SetIP(_Unwind_Context_Ptr ctx, unsigned long val) {
   1137     (void)ctx; (void)val;
   1138 }
   1139 
   1140 void _Unwind_DeleteException(_Unwind_Exception_Ptr exc) {
   1141     (void)exc;
   1142 }
   1143 
   1144 void __deregister_frame(void *fde) {
   1145     (void)fde;
   1146 }
   1147 
   1148 void __register_frame(void *fde) {
   1149     (void)fde;
   1150 }
   1151 
   1152 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception_Ptr exc) {
   1153     (void)exc;
   1154     return 5; /* _URC_END_OF_STACK */
   1155 }
   1156 
   1157 unsigned long _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr ctx) {
   1158     (void)ctx;
   1159     return 0;
   1160 }
   1161 
   1162 unsigned long _Unwind_GetIP(_Unwind_Context_Ptr ctx) {
   1163     (void)ctx;
   1164     return 0;
   1165 }
   1166 
   1167 unsigned long _Unwind_GetRegionStart(_Unwind_Context_Ptr ctx) {
   1168     (void)ctx;
   1169     return 0;
   1170 }
   1171 
   1172 unsigned long _Unwind_GetCFA(_Unwind_Context_Ptr ctx) {
   1173     (void)ctx;
   1174     return 0;
   1175 }
   1176 
   1177 /* Signal handling stubs */
   1178 typedef void (*sighandler_t)(int);
   1179 
   1180 struct itimerval {
   1181     struct timeval {
   1182         long tv_sec;
   1183         long tv_usec;
   1184     } it_interval, it_value;
   1185 };
   1186 
   1187 struct sigaction {
   1188     sighandler_t sa_handler;
   1189     unsigned long sa_flags;
   1190     void (*sa_restorer)(void);
   1191     unsigned long sa_mask[16];
   1192 };
   1193 
   1194 int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) {
   1195     (void)which; (void)new_value; (void)old_value;
   1196     return -1;
   1197 }
   1198 
   1199 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) {
   1200     (void)signum; (void)act; (void)oldact;
   1201     return 0;
   1202 }
   1203 
   1204 int sigemptyset(unsigned long *set) {
   1205     *set = 0;
   1206     return 0;
   1207 }
   1208 
   1209 /* String functions */
   1210 char *strerror(int errnum) {
   1211     (void)errnum;
   1212     return "Error";
   1213 }
   1214 
   1215 int putc(int c, FILE *stream) {
   1216     (void)stream;
   1217     terminal_putchar(c);
   1218     return c;
   1219 }
   1220 
   1221 /* More math functions */
   1222 double frexp(double x, int *exp) {
   1223     (void)x; (void)exp;
   1224     *exp = 0;
   1225     return x;
   1226 }
   1227 
   1228 double modf(double x, double *iptr) {
   1229     double int_part = (double)(long)x;
   1230     *iptr = int_part;
   1231     return x - int_part;
   1232 }
   1233 
   1234 /* Memory remapping - allocate new and copy, free old */
   1235 void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ...) {
   1236     (void)flags;
   1237 
   1238     if (new_size == 0) {
   1239         errno = 22; /* EINVAL */
   1240         return (void *)-1;
   1241     }
   1242 
   1243     /* Align to page boundary */
   1244     new_size = (new_size + 4095) & ~4095;
   1245 
   1246     /* Allocate new memory using our allocator */
   1247     void *new_ptr = malloc(new_size);
   1248     if (!new_ptr) {
   1249         errno = 12; /* ENOMEM */
   1250         return (void *)-1;
   1251     }
   1252 
   1253     /* Copy old data */
   1254     if (old_address && old_size > 0) {
   1255         size_t copy_size = old_size < new_size ? old_size : new_size;
   1256         memcpy(new_ptr, old_address, copy_size);
   1257         /* Free the old memory */
   1258         free(old_address);
   1259     }
   1260 
   1261     return new_ptr;
   1262 }