From aca40a69b041918612e2350a1a37935bad58eb82 Mon Sep 17 00:00:00 2001 From: huntedbytheirs Date: Sun, 30 Aug 2026 04:07:55 -0400 Subject: [PATCH] Add public headers Declarations for the string core, stdio, stdlib, unistd, errno, sys/types, and the raw syscall interface; the FILE layout stays private in src/internal.h. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- include/errno.h | 59 +++++++++++++++++++++++++++++++++++++++++++ include/stdio.h | 46 +++++++++++++++++++++++++++++++++ include/stdlib.h | 38 ++++++++++++++++++++++++++++ include/string.h | 32 +++++++++++++++++++++++ include/sys/syscall.h | 51 +++++++++++++++++++++++++++++++++++++ include/sys/types.h | 25 ++++++++++++++++++ include/unistd.h | 38 ++++++++++++++++++++++++++++ 7 files changed, 289 insertions(+) create mode 100644 include/errno.h create mode 100644 include/stdio.h create mode 100644 include/stdlib.h create mode 100644 include/string.h create mode 100644 include/sys/syscall.h create mode 100644 include/sys/types.h create mode 100644 include/unistd.h diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000..5677d41 --- /dev/null +++ b/include/errno.h @@ -0,0 +1,59 @@ +/* + * errno.h — error codes for nulsl-libc. + * + * Single-threaded for now: errno is a plain global. If nulsl-libc ever + * grows threads, this becomes a TLS slot or an __errno_location() + * indirection without changing any caller. + */ + +#ifndef _NULSL_ERRNO_H +#define _NULSL_ERRNO_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern int errno; + +/* The classic 1-34, values locked by Linux's errno(3) man page. */ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain */ +#define ERANGE 34 /* Math result not representable */ +#define ENOSYS 38 /* Function not implemented */ + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_ERRNO_H */ diff --git a/include/stdio.h b/include/stdio.h new file mode 100644 index 0000000..6144ba4 --- /dev/null +++ b/include/stdio.h @@ -0,0 +1,46 @@ +/* + * stdio.h — standard I/O for nulsl-libc. + * + * Minimal for now: unbuffered writes to a file descriptor, plus ENOSYS + * stubs for the buffered/formatting machinery that is still to come. + * A FILE is just a file descriptor until we grow a real buffering layer. + */ + +#ifndef _NULSL_STDIO_H +#define _NULSL_STDIO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define EOF (-1) + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +typedef struct nulsl_file FILE; + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; + +/* Real, unbuffered. */ +int puts(const char *s); +int putchar(int c); + +/* Stubs (see docs/architecture.md for the roadmap). */ +int printf(const char *fmt, ...); +FILE *fopen(const char *path, const char *mode); +int fclose(FILE *f); +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *f); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *f); +int fflush(FILE *f); + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_STDIO_H */ diff --git a/include/stdlib.h b/include/stdlib.h new file mode 100644 index 0000000..04ea357 --- /dev/null +++ b/include/stdlib.h @@ -0,0 +1,38 @@ +/* + * stdlib.h — general utilities for nulsl-libc. + * + * The memory functions are ENOSYS stubs until the brk-based allocator + * lands; atoi and the exit paths are already real. + */ + +#ifndef _NULSL_STDLIB_H +#define _NULSL_STDLIB_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +/* Stubs: brk()/mmap() allocator is on the roadmap. */ +void *malloc(size_t size); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); + +/* Real. */ +void exit(int status); +void abort(void); +int atoi(const char *s); + +/* Stub. */ +long strtol(const char *s, char **endptr, int base); + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_STDLIB_H */ diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..e99a467 --- /dev/null +++ b/include/string.h @@ -0,0 +1,32 @@ +/* + * string.h — memory and string operations. + * + * All functions here are real, tiny, and freestanding: no libc, no + * compiler builtins. They are the foundation everything else builds on. + */ + +#ifndef _NULSL_STRING_H +#define _NULSL_STRING_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +size_t strlen(const char *s); +int strcmp(const char *a, const char *b); +int strncmp(const char *a, const char *b, size_t n); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t n); + +void *memcpy(void *restrict dst, const void *restrict src, size_t n); +void *memmove(void *dst, const void *src, size_t n); +void *memset(void *dst, int c, size_t n); +int memcmp(const void *a, const void *b, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_STRING_H */ diff --git a/include/sys/syscall.h b/include/sys/syscall.h new file mode 100644 index 0000000..3ef4953 --- /dev/null +++ b/include/sys/syscall.h @@ -0,0 +1,51 @@ +/* + * sys/syscall.h — the raw syscall interface. + * + * syscall() is the ONLY place in nulsl-libc that talks the kernel ABI. + * Everything above it (read, write, exit, ...) is a wrapper. + * + * SYS_* constants below are the x86_64 numbers for the syscalls the libc + * itself wraps or its tests use. They are #ifndef-guarded so kernel UAPI + * headers can coexist. Extend the table as needed (docs/syscalls.md). + */ + +#ifndef _NULSL_SYS_SYSCALL_H +#define _NULSL_SYS_SYSCALL_H + +#ifdef __cplusplus +extern "C" { +#endif + +long syscall(long number, ...); + +/* x86_64 syscall numbers (Linux ABI). */ +#ifndef SYS_read +#define SYS_read 0 +#endif +#ifndef SYS_write +#define SYS_write 1 +#endif +#ifndef SYS_open +#define SYS_open 2 +#endif +#ifndef SYS_close +#define SYS_close 3 +#endif +#ifndef SYS_getpid +#define SYS_getpid 39 +#endif +#ifndef SYS_exit +#define SYS_exit 60 +#endif +#ifndef SYS_unlink +#define SYS_unlink 87 +#endif +#ifndef SYS_clock_gettime +#define SYS_clock_gettime 228 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_SYS_SYSCALL_H */ diff --git a/include/sys/types.h b/include/sys/types.h new file mode 100644 index 0000000..ec652e6 --- /dev/null +++ b/include/sys/types.h @@ -0,0 +1,25 @@ +/* + * sys/types.h — primitive system types for nulsl-libc. + */ + +#ifndef _NULSL_SYS_TYPES_H +#define _NULSL_SYS_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef long ssize_t; +typedef long off_t; +typedef long pid_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; +typedef unsigned long mode_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_SYS_TYPES_H */ diff --git a/include/unistd.h b/include/unistd.h new file mode 100644 index 0000000..ed1e66f --- /dev/null +++ b/include/unistd.h @@ -0,0 +1,38 @@ +/* + * unistd.h — POSIX system call wrappers for nulsl-libc. + * + * These are thin, real wrappers around the raw syscall() interface — see + * docs/syscalls.md. The kernel is the API; everything else is sugar. + */ + +#ifndef _NULSL_UNISTD_H +#define _NULSL_UNISTD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +/* Real syscall wrappers. */ +ssize_t read(int fd, void *buf, size_t count); +ssize_t write(int fd, const void *buf, size_t count); +int close(int fd); +pid_t getpid(void); +void _exit(int status) __attribute__((noreturn)); + +/* Stub. */ +int unlink(const char *path); + +/* Raw syscall entry point (also available here for convenience). */ +long syscall(long number, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _NULSL_UNISTD_H */