feat: port lua scripting language
This commit is contained in:
+12
-22
@@ -96,22 +96,9 @@ ALL_OBJS := $(TCC_OBJS) $(COMPAT_OBJS) $(ASM_OBJS)
|
||||
|
||||
TARGET := $(BINDIR)/tcc.elf
|
||||
|
||||
# ---- CRT objects (compiled for linking by TCC) ----
|
||||
|
||||
CRT_CFLAGS := \
|
||||
-std=gnu11 \
|
||||
-O2 \
|
||||
-nostdinc \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-PIC \
|
||||
-m64 \
|
||||
-march=x86-64 \
|
||||
-mno-red-zone \
|
||||
-fno-tree-loop-distribute-patterns \
|
||||
-isystem $(PROG_INC)/libc \
|
||||
-isystem $(shell $(CC) -print-file-name=include)
|
||||
# ---- CRT objects (staged from shared libc) ----
|
||||
|
||||
SHARED_CRT_DIR := $(LIBDIR)/libc
|
||||
CRT_DIR := ../../bin/lib/tcc/lib
|
||||
CRT_OBJS := $(CRT_DIR)/crt1.o $(CRT_DIR)/crti.o $(CRT_DIR)/crtn.o
|
||||
|
||||
@@ -133,17 +120,20 @@ $(OBJDIR)/%.o: %.S Makefile
|
||||
@mkdir -p $(OBJDIR)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(CRT_DIR)/crt1.o: crt/crt1.c
|
||||
@mkdir -p $(CRT_DIR)
|
||||
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
||||
$(SHARED_CRT_DIR)/liblibc.a $(SHARED_CRT_DIR)/crt1.o $(SHARED_CRT_DIR)/crti.o $(SHARED_CRT_DIR)/crtn.o:
|
||||
$(MAKE) -C $(SHARED_CRT_DIR)
|
||||
|
||||
$(CRT_DIR)/crti.o: crt/crti.c
|
||||
$(CRT_DIR)/crt1.o: $(SHARED_CRT_DIR)/crt1.o
|
||||
@mkdir -p $(CRT_DIR)
|
||||
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
||||
cp $< $@
|
||||
|
||||
$(CRT_DIR)/crtn.o: crt/crtn.c
|
||||
$(CRT_DIR)/crti.o: $(SHARED_CRT_DIR)/crti.o
|
||||
@mkdir -p $(CRT_DIR)
|
||||
$(CC) $(CRT_CFLAGS) -c $< -o $@
|
||||
cp $< $@
|
||||
|
||||
$(CRT_DIR)/crtn.o: $(SHARED_CRT_DIR)/crtn.o
|
||||
@mkdir -p $(CRT_DIR)
|
||||
cp $< $@
|
||||
|
||||
$(CRT_DIR)/libc.a: $(LIBDIR)/libc/liblibc.a
|
||||
@mkdir -p $(CRT_DIR)
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* crt1.c
|
||||
* C runtime startup for TCC-compiled programs on MontaukOS
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*
|
||||
* Provides _start, which:
|
||||
* 1. Gets command-line arguments from kernel
|
||||
* 2. Parses them into argc/argv
|
||||
* 3. Calls main(argc, argv)
|
||||
* 4. Calls exit(return value)
|
||||
*/
|
||||
|
||||
/* Syscall wrappers (inline asm, no header dependencies) */
|
||||
|
||||
static inline long _sys0(long nr) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall" : "=a"(ret) : "a"(nr)
|
||||
: "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long _sys1(long nr, long a1) {
|
||||
long ret;
|
||||
__asm__ volatile(
|
||||
"mov %[a1], %%rdi\n\t"
|
||||
"syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(nr), [a1] "r"(a1)
|
||||
: "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long _sys2(long nr, long a1, long a2) {
|
||||
long ret;
|
||||
__asm__ volatile(
|
||||
"mov %[a1], %%rdi\n\t"
|
||||
"mov %[a2], %%rsi\n\t"
|
||||
"syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(nr), [a1] "r"(a1), [a2] "r"(a2)
|
||||
: "rcx", "r11", "rdi", "rsi", "rdx", "r8", "r9", "r10", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SYS_EXIT 0
|
||||
#define SYS_GETARGS 25
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
void _start(void) {
|
||||
char argbuf[256];
|
||||
int len = (int)_sys2(SYS_GETARGS, (long)argbuf, (long)sizeof(argbuf));
|
||||
|
||||
char *argv[32];
|
||||
int argc = 0;
|
||||
|
||||
/* argv[0] = program name */
|
||||
argv[argc++] = "prog";
|
||||
|
||||
if (len > 0) {
|
||||
if (len > 255) len = 255;
|
||||
argbuf[len] = '\0';
|
||||
char *p = argbuf;
|
||||
while (*p && argc < 31) {
|
||||
while (*p == ' ') p++;
|
||||
if (*p == '\0') break;
|
||||
argv[argc++] = p;
|
||||
while (*p && *p != ' ') p++;
|
||||
if (*p) *p++ = '\0';
|
||||
}
|
||||
}
|
||||
argv[argc] = (void*)0;
|
||||
|
||||
int ret = main(argc, argv);
|
||||
_sys1(SYS_EXIT, (long)ret);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
* crti.c
|
||||
* Init section prologue (minimal for MontaukOS)
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
/* Empty -- MontaukOS userspace has no global constructors */
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
* crtn.c
|
||||
* Init section epilogue (minimal for MontaukOS)
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
/* Empty -- MontaukOS userspace has no global destructors */
|
||||
@@ -10,83 +10,9 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* ====================================================================
|
||||
setjmp / longjmp (implemented in setjmp.S)
|
||||
==================================================================== */
|
||||
|
||||
typedef unsigned long jmp_buf[8]; /* rbx, rbp, r12-r15, rsp, rip */
|
||||
|
||||
int setjmp(jmp_buf env);
|
||||
void longjmp(jmp_buf env, int val) __attribute__((noreturn));
|
||||
|
||||
/* ====================================================================
|
||||
time stubs (for __DATE__ / __TIME__ macros)
|
||||
==================================================================== */
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
static inline time_t time(time_t *t) {
|
||||
if (t) *t = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct tm *localtime(const time_t *t) {
|
||||
static struct tm tm0 = {
|
||||
.tm_sec = 0, .tm_min = 0, .tm_hour = 12,
|
||||
.tm_mday = 1, .tm_mon = 0, .tm_year = 126, /* 2026 */
|
||||
.tm_wday = 4, .tm_yday = 0, .tm_isdst = 0
|
||||
};
|
||||
(void)t;
|
||||
return &tm0;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
gettimeofday stub (for timing in tcc.c)
|
||||
==================================================================== */
|
||||
|
||||
struct timeval {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
|
||||
static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
if (tv) { tv->tv_sec = 0; tv->tv_usec = 0; }
|
||||
(void)tz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* getcwd is provided by libc now */
|
||||
char *getcwd(char *buf, size_t size);
|
||||
|
||||
/* ====================================================================
|
||||
POSIX file access stubs
|
||||
==================================================================== */
|
||||
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
#define X_OK 1
|
||||
#define F_OK 0
|
||||
|
||||
/* Check if file exists by trying to open it */
|
||||
int access(const char *path, int mode);
|
||||
|
||||
/* chmod - no-op on MontaukOS */
|
||||
static inline int chmod(const char *path, unsigned int mode) {
|
||||
(void)path; (void)mode;
|
||||
@@ -117,24 +43,6 @@ static inline char *realpath(const char *path, char *resolved) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
strtof / strtold stubs
|
||||
==================================================================== */
|
||||
|
||||
/* These are declared extern in tcc.h for non-Win32.
|
||||
We provide no-op stubs since the libc has no FP parse. */
|
||||
static inline float strtof(const char *nptr, char **endptr) {
|
||||
(void)nptr;
|
||||
if (endptr) *endptr = (char*)nptr;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static inline long double strtold(const char *nptr, char **endptr) {
|
||||
(void)nptr;
|
||||
if (endptr) *endptr = (char*)nptr;
|
||||
return 0.0L;
|
||||
}
|
||||
|
||||
/* dlfcn stubs not needed -- TCC_IS_NATIVE is disabled for MontaukOS */
|
||||
|
||||
/* ====================================================================
|
||||
@@ -158,38 +66,12 @@ static inline int unlink(const char *path) {
|
||||
return remove(path);
|
||||
}
|
||||
|
||||
/* fputc (should be in libc but isn't yet) */
|
||||
static inline int fputc(int c, FILE *stream) {
|
||||
unsigned char ch = (unsigned char)c;
|
||||
size_t n = fwrite(&ch, 1, 1, stream);
|
||||
return n == 1 ? c : -1;
|
||||
}
|
||||
|
||||
/* fdopen - MontaukOS doesn't have fd-to-FILE conversion.
|
||||
TCC uses fdopen after creating a file with open().
|
||||
We return NULL and let TCC fall back to error path,
|
||||
or we can use a workaround. */
|
||||
FILE *fdopen(int fd, const char *mode);
|
||||
|
||||
/* strerror */
|
||||
static inline const char *strerror(int errnum) {
|
||||
(void)errnum;
|
||||
return "error";
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
String functions missing from MontaukOS libc
|
||||
==================================================================== */
|
||||
|
||||
static inline char *strpbrk(const char *s, const char *accept) {
|
||||
for (; *s; s++) {
|
||||
for (const char *a = accept; *a; a++) {
|
||||
if (*s == *a) return (char *)s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
Process stubs
|
||||
==================================================================== */
|
||||
@@ -199,12 +81,4 @@ static inline int execvp(const char *file, char *const argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
Floating-point parsing and math
|
||||
==================================================================== */
|
||||
|
||||
double strtod(const char *nptr, char **endptr);
|
||||
double ldexp(double x, int n);
|
||||
long double ldexpl(long double x, int n);
|
||||
|
||||
#endif /* MONTAUK_COMPAT_H */
|
||||
|
||||
@@ -37,24 +37,9 @@ static inline long _sys2(long nr, long a1, long a2) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SYS_OPEN 6
|
||||
#define SYS_GETSIZE 8
|
||||
#define SYS_CLOSE 9
|
||||
#define SYS_GETARGS 25
|
||||
|
||||
/* ====================================================================
|
||||
access() - check if a file exists
|
||||
==================================================================== */
|
||||
|
||||
int access(const char *path, int mode) {
|
||||
(void)mode;
|
||||
if (path == NULL) return -1;
|
||||
int h = (int)_sys1(SYS_OPEN, (long)path);
|
||||
if (h < 0) return -1;
|
||||
_sys1(SYS_CLOSE, (long)h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
fdopen - wrap a raw fd in a FILE (needed by tccelf.c)
|
||||
==================================================================== */
|
||||
@@ -78,102 +63,6 @@ FILE *fdopen(int fd, const char *mode) {
|
||||
return f;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
Floating point support (needed by TCC for parsing float literals)
|
||||
==================================================================== */
|
||||
|
||||
double ldexp(double x, int n) {
|
||||
/* Use bit manipulation via union for exact results */
|
||||
if (x == 0.0 || n == 0) return x;
|
||||
while (n > 0) { x *= 2.0; n--; }
|
||||
while (n < 0) { x *= 0.5; n++; }
|
||||
return x;
|
||||
}
|
||||
|
||||
long double ldexpl(long double x, int n) {
|
||||
return (long double)ldexp((double)x, n);
|
||||
}
|
||||
|
||||
double strtod(const char *nptr, char **endptr) {
|
||||
double result = 0.0;
|
||||
double sign = 1.0;
|
||||
const char *s = nptr;
|
||||
|
||||
while (*s == ' ' || *s == '\t' || *s == '\n') s++;
|
||||
if (*s == '-') { sign = -1.0; s++; }
|
||||
else if (*s == '+') s++;
|
||||
|
||||
/* Integer part */
|
||||
while (*s >= '0' && *s <= '9')
|
||||
result = result * 10.0 + (*s++ - '0');
|
||||
|
||||
/* Fractional part */
|
||||
if (*s == '.') {
|
||||
s++;
|
||||
double frac = 0.1;
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
result += (*s++ - '0') * frac;
|
||||
frac *= 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Exponent */
|
||||
if (*s == 'e' || *s == 'E') {
|
||||
s++;
|
||||
int exp_sign = 1, exp_val = 0;
|
||||
if (*s == '-') { exp_sign = -1; s++; }
|
||||
else if (*s == '+') s++;
|
||||
while (*s >= '0' && *s <= '9')
|
||||
exp_val = exp_val * 10 + (*s++ - '0');
|
||||
double exp_mult = 1.0;
|
||||
for (int i = 0; i < exp_val; i++)
|
||||
exp_mult *= 10.0;
|
||||
if (exp_sign > 0) result *= exp_mult;
|
||||
else result /= exp_mult;
|
||||
}
|
||||
|
||||
/* Hex float (0x...p...) */
|
||||
if (nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) {
|
||||
s = nptr + 2;
|
||||
result = 0.0;
|
||||
while (1) {
|
||||
int d;
|
||||
if (*s >= '0' && *s <= '9') d = *s - '0';
|
||||
else if (*s >= 'a' && *s <= 'f') d = *s - 'a' + 10;
|
||||
else if (*s >= 'A' && *s <= 'F') d = *s - 'A' + 10;
|
||||
else break;
|
||||
result = result * 16.0 + d;
|
||||
s++;
|
||||
}
|
||||
if (*s == '.') {
|
||||
s++;
|
||||
double frac = 1.0 / 16.0;
|
||||
while (1) {
|
||||
int d;
|
||||
if (*s >= '0' && *s <= '9') d = *s - '0';
|
||||
else if (*s >= 'a' && *s <= 'f') d = *s - 'a' + 10;
|
||||
else if (*s >= 'A' && *s <= 'F') d = *s - 'A' + 10;
|
||||
else break;
|
||||
result += d * frac;
|
||||
frac /= 16.0;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
if (*s == 'p' || *s == 'P') {
|
||||
s++;
|
||||
int exp_sign = 1, exp_val = 0;
|
||||
if (*s == '-') { exp_sign = -1; s++; }
|
||||
else if (*s == '+') s++;
|
||||
while (*s >= '0' && *s <= '9')
|
||||
exp_val = exp_val * 10 + (*s++ - '0');
|
||||
result = ldexp(result, exp_sign * exp_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (endptr) *endptr = (char *)s;
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
strtoll / strtoull (needed by TCC, not in MontaukOS libc)
|
||||
==================================================================== */
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <setjmp.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "montauk_compat.h"
|
||||
|
||||
/* Stubs for functions in libc headers but not relevant here */
|
||||
|
||||
Reference in New Issue
Block a user