diff --git a/src/userland/apps/mqjs/build.zig b/src/userland/apps/mqjs/build.zig new file mode 100644 index 00000000..28fbdfa1 --- /dev/null +++ b/src/userland/apps/mqjs/build.zig @@ -0,0 +1,29 @@ +const std = @import("std"); +const AshetOS = @import("AshetOS"); + +pub fn build(b: *std.Build) void { + const target = AshetOS.standardTargetOption(b); + const optimize = b.standardOptimizeOption(.{}); + + const sdk = AshetOS.init(b, "AshetOS", .{ .target = target }); + + const mqjs = b.dependency("mqjs", .{ + .target = target.resolve_target(b), + .optimize = .ReleaseSafe, + }); + + const mqjs_mod = mqjs.module("mqjs"); + + const app = sdk.addApp(.{ + .name = "hello-world", + .target = target, + .optimize = optimize, + .root_source_file = b.path("hello-world.zig"), + .code_model = .default, // C code fails with clang error ".small not found" + .link_libc = true, + }); + + app.exe.root_module.addImport("mqjs", mqjs_mod); + + sdk.installApp(app, .{}); +} diff --git a/src/userland/apps/mqjs/build.zig.zon b/src/userland/apps/mqjs/build.zig.zon new file mode 100644 index 00000000..8b404785 --- /dev/null +++ b/src/userland/apps/mqjs/build.zig.zon @@ -0,0 +1,14 @@ +.{ + .name = .mqjs, + .fingerprint = 0xeb25510e1a54d4fa, + .version = "0.1.0", + .paths = .{ "build.zig", "build.zig.zon", "src" }, + .dependencies = .{ + .AshetOS = .{ + .path = "../../libs/libAshetOS", + }, + .mqjs = .{ + .path = "../../../../vendor/mqjs", + }, + }, +} diff --git a/src/userland/apps/mqjs/hello-world.zig b/src/userland/apps/mqjs/hello-world.zig new file mode 100644 index 00000000..29b58b16 --- /dev/null +++ b/src/userland/apps/mqjs/hello-world.zig @@ -0,0 +1,8 @@ +const std = @import("std"); +const ashet = @import("ashet"); + +pub usingnamespace ashet.core; + +pub fn main() !void { + try ashet.process.debug.log_writer(.notice).writeAll("Hello, World!\r\n"); +} diff --git a/src/userland/libs/libAshetOS/build.zig b/src/userland/libs/libAshetOS/build.zig index 989de29d..29883c6f 100644 --- a/src/userland/libs/libAshetOS/build.zig +++ b/src/userland/libs/libAshetOS/build.zig @@ -48,6 +48,7 @@ pub fn init(b: *std.Build, dependency_name: []const u8, args: struct { .owning_builder = b, .dependency = dep, + .libc_file = dep.namedLazyPath("libc.txt"), .ashex_tool_exe = dep.artifact("ashet-exe"), .ashet_module = dep.module("ashet"), .linker_script = dep.path("application.ld"), @@ -72,6 +73,8 @@ pub const AshetSdk = struct { ashex_tool_exe: *std.Build.Step.Compile, mkicon_exe: *std.Build.Step.Compile, + libc_file: std.Build.LazyPath, + syscall_library: std.Build.LazyPath, ashet_module: *std.Build.Module, linker_script: std.Build.LazyPath, @@ -120,6 +123,8 @@ pub const AshetSdk = struct { .win32_manifest = null, }); + exe.setLibCFile(sdk.libc_file); + // if (zig_target.result.cpu.arch.isThumb()) { // // Disable LTO on arm as it fails hard // exe.want_lto = false; @@ -254,7 +259,6 @@ pub const ExecutableOptions = struct { }; pub fn build(b: *std.Build) void { - // Targets: const debug_step = b.step("debug", "Installs a debug executable for disassembly"); @@ -288,6 +292,15 @@ pub fn build(b: *std.Build) void { // Build: + const genfile_exe = b.addExecutable(.{ + .name = "genfile", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/genfile.zig"), + .target = b.graph.host, + .optimize = .Debug, + }), + }); + const gen_binding_exe = b.addExecutable(.{ .name = "gen_abi_binding", .target = b.graph.host, @@ -312,8 +325,33 @@ pub fn build(b: *std.Build) void { const target = ashet_target.resolve_target(b); - const sub_build = b.addSystemCommand(&.{ b.graph.zig_exe, "build-lib" }); + // Libraries + const libc = b.addStaticLibrary(.{ + .name = "c", + .root_module = b.createModule(.{ + .target = target, + .optimize = .ReleaseSafe, + .root_source_file = b.path("libc/src/libc.zig"), + .single_threaded = true, + }), + }); + libc.root_module.addIncludePath(b.path("libc/include/")); + libc.root_module.addIncludePath(b.path("libc/sys_include/")); + b.installArtifact(libc); + + const gen_libc_file = b.addRunArtifact(genfile_exe); + gen_libc_file.addPrefixedDirectoryArg("include_dir=", b.path("libc/include/")); + gen_libc_file.addPrefixedDirectoryArg("sys_include_dir=", b.path("libc/sys_include/")); + gen_libc_file.addPrefixedDirectoryArg("crt_dir=", b.path("libc/crt0")); // TODO: The directory that contains `crt1.o` or `crt2.o`. + gen_libc_file.addArg("msvc_lib_dir="); // Not required + gen_libc_file.addArg("kernel32_lib_dir="); // Not required + gen_libc_file.addArg("gcc_dir="); // Not required + + const libc_txt_path = gen_libc_file.captureStdOut(); + b.addNamedLazyPath("libc.txt", libc_txt_path); + + const sub_build = b.addSystemCommand(&.{ b.graph.zig_exe, "build-lib" }); sub_build.addArg("-static"); sub_build.addArg("-fPIC"); sub_build.addArg("-O"); diff --git a/src/userland/libs/libAshetOS/build.zig.zon b/src/userland/libs/libAshetOS/build.zig.zon index 777347f5..da3c9eea 100644 --- a/src/userland/libs/libAshetOS/build.zig.zon +++ b/src/userland/libs/libAshetOS/build.zig.zon @@ -20,5 +20,9 @@ .libashet = .{ .path = "module", }, + .libc = .{ + .url = "https://github.com/ZigEmbeddedGroup/microzig/releases/download/0.14.4/foundationlibc.tar.gz", + .hash = "foundationlibc-0.0.0-LAEuPNWTAADpACdmCKeEZZocc6PNjE99VjX97X85tghY", + }, }, } diff --git a/src/userland/libs/libAshetOS/libc/.clang-format b/src/userland/libs/libAshetOS/libc/.clang-format new file mode 100644 index 00000000..8951bebb --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/.clang-format @@ -0,0 +1,26 @@ +--- +Language: Cpp +BasedOnStyle: LLVM + +# basic indentation is 4 spaces, indented by spaces: +IndentWidth: 4 +TabWidth: 4 +UseTab: Never + +# use east const for better readability: +QualifierAlignment: Right + +# do not tack pointer to type nor value: +PointerAlignment: Middle + +# align function names and keep them apart at least one line +AlignConsecutiveDeclarations: AcrossEmptyLines + +# we sort includes to prevent merge conflicts: +SortIncludes: CaseSensitive + +# disable column limit: +ColumnLimit: 0 + +--- + diff --git a/src/userland/libs/libAshetOS/libc/include/assert.h b/src/userland/libs/libAshetOS/libc/include/assert.h new file mode 100644 index 00000000..74ab2cde --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/assert.h @@ -0,0 +1,48 @@ +#ifndef _FOUNDATION_LIBC_ASSERT_H_ +#define _FOUNDATION_LIBC_ASSERT_H_ + +#include "foundation/builtins.h" + +extern FOUNDATION_LIBC_NORETURN void foundation_libc_assert(char const * assertion, char const * file, unsigned line); + +#if FOUNDATION_LIBC_ASSERT == FOUNDATION_LIBC_ASSERT_DEFAULT + +#define assert(expr) \ + do { \ + if ((expr) == 0) { \ + foundation_libc_assert(#expr, __FILE__, __LINE__); \ + } \ + } while (0) + +#elif FOUNDATION_LIBC_ASSERT == FOUNDATION_LIBC_ASSERT_NOFILE + +#define assert(expr) \ + do { \ + if ((expr) == 0) { \ + foundation_libc_assert(#expr, "", __LINE__); \ + } \ + } while (0) + +#elif FOUNDATION_LIBC_ASSERT == FOUNDATION_LIBC_ASSERT_NOMSG + +#define assert(expr) \ + do { \ + if ((expr) == 0) { \ + foundation_libc_assert("", "", __LINE__); \ + } \ + } while (0) + +#elif FOUNDATION_LIBC_ASSERT == FOUNDATION_LIBC_ASSERT_EXPECTED + +#define assert(expr) FOUNDATION_LIBC_EXPECT(expr) + +#else +#error "bad definition of FOUNDATION_LIBC_ASSERT_DEFAULT!" +#endif + +#if !defined(__cplusplus) +#undef static_assert +#define static_assert FOUNDATION_LIBC_STATIC_ASSERT +#endif + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/ctype.h b/src/userland/libs/libAshetOS/libc/include/ctype.h new file mode 100644 index 00000000..c4e7caac --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/ctype.h @@ -0,0 +1,21 @@ +#ifndef _FOUNDATION_LIBC_CTYPE_H_ +#define _FOUNDATION_LIBC_CTYPE_H_ + +#define EOF (-1) + +int isalnum(int c); +int isalpha(int c); +int isblank(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); +int tolower(int c); +int toupper(int c); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/errno.h b/src/userland/libs/libAshetOS/libc/include/errno.h new file mode 100644 index 00000000..f00e1f1f --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/errno.h @@ -0,0 +1,12 @@ +#ifndef _FOUNDATION_LIBC_ERRNO_H_ +#define _FOUNDATION_LIBC_ERRNO_H_ + +#define EDOM 1 +#define EILSEQ 2 +#define ERANGE 3 + +#define errno (*__get_errno()) + +int * __get_errno(void); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/foundation/builtins.h b/src/userland/libs/libAshetOS/libc/include/foundation/builtins.h new file mode 100644 index 00000000..a5b57b96 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/foundation/builtins.h @@ -0,0 +1,39 @@ +#ifndef _FOUNDATION_LIBC_BUILTINS_H_ +#define _FOUNDATION_LIBC_BUILTINS_H_ + +#include + +#define FOUNDATION_LIBC_ASSERT_DEFAULT 0 +#define FOUNDATION_LIBC_ASSERT_NOFILE 1 +#define FOUNDATION_LIBC_ASSERT_NOMSG 2 +#define FOUNDATION_LIBC_ASSERT_EXPECTED 3 + +#ifndef FOUNDATION_LIBC_ASSERT +#define FOUNDATION_LIBC_ASSERT FOUNDATION_LIBC_ASSERT_DEFAULT +#endif + +#define FOUNDATION_LIBC_STATIC_ASSERT _Static_assert + +#if defined(__clang__) + +#define FOUNDATION_LIBC_NORETURN __attribute__((__noreturn__)) +#define FOUNDATION_LIBC_EXPECT(expr) (__builtin_expect(!(expr), 0)) + +#elif defined(__GNUC__) || defined(__GNUG__) + +#define FOUNDATION_LIBC_NORETURN __attribute__((__noreturn__)) +#define FOUNDATION_LIBC_EXPECT(expr) (__builtin_expect(!(expr), 0)) + +#elif defined(_MSC_VER) + +#define FOUNDATION_LIBC_NORETURN __declspec(noreturn) +#define FOUNDATION_LIBC_EXPECT(expr) (__assume((expr))) + +#else + +#define FOUNDATION_LIBC_NORETURN +#define FOUNDATION_LIBC_EXPECT(expr) + +#endif + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/foundation/libc.h b/src/userland/libs/libAshetOS/libc/include/foundation/libc.h new file mode 100644 index 00000000..7b245c80 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/foundation/libc.h @@ -0,0 +1,25 @@ +#ifndef _FOUNDATION_LIBC_INTERNALS_H_ +#define _FOUNDATION_LIBC_INTERNALS_H_ + +#include + +/// +/// Panic handler for undefined, but catchable behaviour in safe modes. +/// +/// This will be invoked when Zig detects undefined behaviour at runtime, +/// or when foundation libc can recognize illegal arguments. +/// +/// The function receives a non-terminated pointer to the panic message +/// with `msg_len` bytes of UTF-8 encoded payload. +/// +/// It has a weak default implementation shipped, so just implement this +/// function to plug in your own custom behaviour. +/// The default implementation is done by invoking a `trap` instruction to +/// emit an illegal instruction or otherwise crash the program execution. +/// +/// NOTE: This function must never return, because otherwise, the undefined +/// behaviour will be actually undefined! +/// +void foundation_libc_panic_handler(char const * msg_ptr, size_t msg_len); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/inttypes.h b/src/userland/libs/libAshetOS/libc/include/inttypes.h new file mode 100644 index 00000000..37421afc --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/inttypes.h @@ -0,0 +1,220 @@ +#ifndef _FOUNDATION_LIBC_INTTYPES_H_ +#define _FOUNDATION_LIBC_INTTYPES_H_ + +// TODO: mquickjs includes inttypes.h, but not stdint.h +#include + +typedef struct _ashet_imaxdiv { + intmax_t rem; + intmax_t quot; +} imaxdiv_t; + +intmax_t imaxabs(intmax_t); +imaxdiv_t imaxdiv(intmax_t, intmax_t); + +intmax_t strtoimax(char const * __restrict, char ** __restrict, int); +uintmax_t strtoumax(char const * __restrict, char ** __restrict, int); + +intmax_t wcstoimax(wchar_t const * __restrict, wchar_t ** __restrict, int); +uintmax_t wcstoumax(wchar_t const * __restrict, wchar_t ** __restrict, int); + +#if UINTPTR_MAX == UINT64_MAX +#define __PRI64 "l" +#define __PRIPTR "l" +#else +#define __PRI64 "ll" +#define __PRIPTR "" +#endif + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64 "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64 "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 __PRI64 "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64 "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64 "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 __PRI64 "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64 "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64 "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 __PRI64 "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64 "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64 "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 __PRI64 "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64 "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64 "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 __PRI64 "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64 "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64 "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 __PRI64 "X" + +#define PRIdMAX __PRI64 "d" +#define PRIiMAX __PRI64 "i" +#define PRIoMAX __PRI64 "o" +#define PRIuMAX __PRI64 "u" +#define PRIxMAX __PRI64 "x" +#define PRIXMAX __PRI64 "X" + +#define PRIdPTR __PRIPTR "d" +#define PRIiPTR __PRIPTR "i" +#define PRIoPTR __PRIPTR "o" +#define PRIuPTR __PRIPTR "u" +#define PRIxPTR __PRIPTR "x" +#define PRIXPTR __PRIPTR "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64 "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64 "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 "d" +#define SCNdFAST32 "d" +#define SCNdFAST64 __PRI64 "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64 "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64 "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 "i" +#define SCNiFAST32 "i" +#define SCNiFAST64 __PRI64 "i" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64 "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64 "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 "u" +#define SCNuFAST32 "u" +#define SCNuFAST64 __PRI64 "u" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64 "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64 "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 "o" +#define SCNoFAST32 "o" +#define SCNoFAST64 __PRI64 "o" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64 "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64 "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 "x" +#define SCNxFAST32 "x" +#define SCNxFAST64 __PRI64 "x" + +#define SCNdMAX __PRI64 "d" +#define SCNiMAX __PRI64 "i" +#define SCNoMAX __PRI64 "o" +#define SCNuMAX __PRI64 "u" +#define SCNxMAX __PRI64 "x" + +#define SCNdPTR __PRIPTR "d" +#define SCNiPTR __PRIPTR "i" +#define SCNoPTR __PRIPTR "o" +#define SCNuPTR __PRIPTR "u" +#define SCNxPTR __PRIPTR "x" + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/math.h b/src/userland/libs/libAshetOS/libc/include/math.h new file mode 100644 index 00000000..3e088cdc --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/math.h @@ -0,0 +1,220 @@ +#ifndef _FOUNDATION_LIBC_MATH_H_ +#define _FOUNDATION_LIBC_MATH_H_ + +typedef float float_t; +typedef double double_t; + +#define FLT_EVAL_METHOD () + +#define HUGE_VAL __builtin_huge_val() +#define HUGE_VALF __builtin_huge_valf() +#define HUGE_VALL __builtin_huge_vall() + +#define INFINITY __builtin_inff() +#define NAN __builtin_nanf("") + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + +#define FP_FAST_FMA () +#define FP_FAST_FMAF () +#define FP_FAST_FMAL () + +#define FP_ILOGB0 () +#define FP_ILOGBNAN () + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 + +#define math_errhandling 0 // TODO: Implement this + +#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x) +#define isfinite(x) __builtin_isfinite(x) +#define isinf(x) __builtin_isinf_sign(x) +#define isnan(x) __builtin_isnan(x) +#define isnormal(x) __builtin_isnormal(x) +#define signbit(x) __builtin_signbit(x) + +double acos(double x); +float acosf(float x); +long double acosl(long double x); +double asin(double x); +float asinf(float x); +long double asinl(long double x); +double atan(double x); +float atanf(float x); +long double atanl(long double x); +double atan2(double y, double x); +float atan2f(float y, float x); +long double atan2l(long double y, long double x); +double cos(double x); +float cosf(float x); +long double cosl(long double x); +double sin(double x); +float sinf(float x); +long double sinl(long double x); +double tan(double x); +float tanf(float x); +long double tanl(long double x); +double acosh(double x); +float acoshf(float x); +long double acoshl(long double x); +double asinh(double x); +float asinhf(float x); +long double asinhl(long double x); +double atanh(double x); +float atanhf(float x); +long double atanhl(long double x); +double cosh(double x); +float coshf(float x); +long double coshl(long double x); +double sinh(double x); +float sinhf(float x); +long double sinhl(long double x); +double tanh(double x); +float tanhf(float x); +long double tanhl(long double x); +double exp(double x); +float expf(float x); +long double expl(long double x); +double exp2(double x); +float exp2f(float x); +long double exp2l(long double x); +double expm1(double x); +float expm1f(float x); +long double expm1l(long double x); +double frexp(double value, int * exp); +float frexpf(float value, int * exp); +long double frexpl(long double value, int * exp); +int ilogb(double x); +int ilogbf(float x); +int ilogbl(long double x); +double ldexp(double x, int exp); +float ldexpf(float x, int exp); +long double ldexpl(long double x, int exp); +double log(double x); +float logf(float x); +long double logl(long double x); +double log10(double x); +float log10f(float x); +long double log10l(long double x); +double log1p(double x); +float log1pf(float x); +long double log1pl(long double x); +double log2(double x); +float log2f(float x); +long double log2l(long double x); +double logb(double x); +float logbf(float x); +long double logbl(long double x); +double modf(double value, double * iptr); +float modff(float value, float * iptr); +long double modfl(long double value, long double * iptr); +double scalbn(double x, int n); +float scalbnf(float x, int n); +long double scalbnl(long double x, int n); +double scalbln(double x, long int n); +float scalblnf(float x, long int n); +long double scalblnl(long double x, long int n); +double cbrt(double x); +float cbrtf(float x); +long double cbrtl(long double x); +double fabs(double x); +float fabsf(float x); +long double fabsl(long double x); +double hypot(double x, double y); +float hypotf(float x, float y); +long double hypotl(long double x, long double y); +double pow(double x, double y); +float powf(float x, float y); +long double powl(long double x, long double y); +double sqrt(double x); +float sqrtf(float x); +long double sqrtl(long double x); +double erf(double x); +float erff(float x); +long double erfl(long double x); +double erfc(double x); +float erfcf(float x); +long double erfcl(long double x); +double lgamma(double x); +float lgammaf(float x); +long double lgammal(long double x); +double tgamma(double x); +float tgammaf(float x); +long double tgammal(long double x); +double ceil(double x); +float ceilf(float x); +long double ceill(long double x); +double floor(double x); +float floorf(float x); +long double floorl(long double x); +double nearbyint(double x); +float nearbyintf(float x); +long double nearbyintl(long double x); +double rint(double x); +float rintf(float x); +long double rintl(long double x); +long int lrint(double x); +long int lrintf(float x); +long int lrintl(long double x); +long long int llrint(double x); +long long int llrintf(float x); +long long int llrintl(long double x); +double round(double x); +float roundf(float x); +long double roundl(long double x); +long int lround(double x); +long int lroundf(float x); +long int lroundl(long double x); +long long int llround(double x); +long long int llroundf(float x); +long long int llroundl(long double x); +double trunc(double x); +float truncf(float x); +long double truncl(long double x); +double fmod(double x, double y); +float fmodf(float x, float y); +long double fmodl(long double x, long double y); +double remainder(double x, double y); +float remainderf(float x, float y); +long double remainderl(long double x, long double y); +double remquo(double x, double y, int * quo); +float remquof(float x, float y, int * quo); +long double remquol(long double x, long double y, int * quo); +double copysign(double x, double y); +float copysignf(float x, float y); +long double copysignl(long double x, long double y); +double nan(char const * tagp); +float nanf(char const * tagp); +long double nanl(char const * tagp); +double nextafter(double x, double y); +float nextafterf(float x, float y); +long double nextafterl(long double x, long double y); +double nexttoward(double x, long double y); +float nexttowardf(float x, long double y); +long double nexttowardl(long double x, long double y); +double fdim(double x, double y); +float fdimf(float x, float y); +long double fdiml(long double x, long double y); +double fmax(double x, double y); +float fmaxf(float x, float y); +long double fmaxl(long double x, long double y); +double fmin(double x, double y); +float fminf(float x, float y); +long double fminl(long double x, long double y); +double fma(double x, double y, double z); +float fmaf(float x, float y, float z); +long double fmal(long double x, long double y, long double z); + +#define isgreater(x, y) __builtin_isgreater(x, y) +#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) +#define isless(x, y) __builtin_isless(x, y) +#define islessequal(x, y) __builtin_islessequal(x, y) +#define islessgreater(x, y) __builtin_islessgreater(x, y) +#define isunordered(x, y) __builtin_isunordered(x, y) + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/setjmp.h b/src/userland/libs/libAshetOS/libc/include/setjmp.h new file mode 100644 index 00000000..e3fa6c6e --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/setjmp.h @@ -0,0 +1,11 @@ +#ifndef _FOUNDATION_LIBC_SETJMP_H_ +#define _FOUNDATION_LIBC_SETJMP_H_ + +typedef unsigned int jmp_buf[1]; + +int setjmp(jmp_buf) __attribute__((__returns_twice__)); +_Noreturn void longjmp(jmp_buf env, int val); + +#define setjmp setjmp // must be a macro + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/stdio.h b/src/userland/libs/libAshetOS/libc/include/stdio.h new file mode 100644 index 00000000..e5fa2966 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/stdio.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +typedef struct { + int dummy; +} FILE; + +typedef struct { + int dummy; +} fpos_t; + +#define _IOFBF () /* see description */ +#define _IOLBF () /* see description */ +#define _IONBF () /* see description */ +#define BUFSIZ () /* see description */ +#define EOF () /* see description */ +#define FOPEN_MAX () /* see description */ +#define FILENAME_MAX ()/* see description */ +#define L_tmpnam () /* see description */ +#define SEEK_CUR () /* see description */ +#define SEEK_END () /* see description */ +#define SEEK_SET () /* see description */ +#define TMP_MAX () /* see description */ + +extern FILE _ashetos_stdin; +extern FILE _ashetos_stdout; +extern FILE _ashetos_stderr; + +#define stdin (&_ashetos_stdin) +#define stdout (&_ashetos_stdout) +#define stderr (&_ashetos_stderr) + +#define _PRINTF_NAN_LEN_MAX /* see description */ + +int remove(const char * filename); +int rename(char const * old, char const * new); +FILE * tmpfile(void); +char * tmpnam(char * s); +int fclose(FILE * stream); +int fflush(FILE * stream); +FILE * fopen(char const * restrict filename, char const * restrict mode); +FILE * freopen(char const * restrict filename, char const * restrict mode, + FILE * restrict stream); +void setbuf(FILE * restrict stream, char * restrict buf); +int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size); +int printf(char const * restrict format, ...); +int scanf(char const * restrict format, ...); +int snprintf(char * restrict s, size_t n, char const * restrict format, ...); +int sprintf(char * restrict s, char const * restrict format, ...); +int sscanf(char const * restrict s, char const * restrict format, ...); +int vfprintf(FILE * restrict stream, char const * restrict format, va_list arg); +int vfscanf(FILE * restrict stream, char const * restrict format, va_list arg); +int vprintf(char const * restrict format, va_list arg); +int vscanf(char const * restrict format, va_list arg); +int vsnprintf(char * restrict s, size_t n, char const * restrict format, va_list arg); +int vsprintf(char * restrict s, char const * restrict format, va_list arg); +int vsscanf(char const * restrict s, char const * restrict format, va_list arg); +int fgetc(FILE * stream); +char * fgets(char * restrict s, int n, FILE * restrict stream); +int fputc(int c, FILE * stream); +int fputs(char const * restrict s, FILE * restrict stream); +int getc(FILE * stream); +int getchar(void); +int putc(int c, FILE * stream); +int putchar(int c); +int puts(char const * s); +int ungetc(int c, FILE * stream); +size_t fread(void * restrict ptr, size_t size, size_t nmemb, + FILE * restrict stream); +size_t fwrite(void const * restrict ptr, size_t size, size_t nmemb, + FILE * restrict stream); +int fgetpos(FILE * restrict stream, fpos_t * restrict pos); +int fseek(FILE * stream, long int offset, int whence); +int fsetpos(FILE * stream, fpos_t const * pos); +long int ftell(FILE * stream); +void rewind(FILE * stream); +void clearerr(FILE * stream); +int feof(FILE * stream); +int ferror(FILE * stream); +void perror(char const * s); +int fprintf(FILE * restrict stream, char const * restrict format, ...); +int fscanf(FILE * restrict stream, char const * restrict format, ...); diff --git a/src/userland/libs/libAshetOS/libc/include/stdlib.h b/src/userland/libs/libAshetOS/libc/include/stdlib.h new file mode 100644 index 00000000..6e64d0f1 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/stdlib.h @@ -0,0 +1,79 @@ +#ifndef _FOUNDATION_LIBC_STDLIB_H_ +#define _FOUNDATION_LIBC_STDLIB_H_ + +#include +#include + +// TODO: void call_once(once_flag * flag, void (*func)(void)); + +double atof(char const * nptr); +int atoi(char const * nptr); +long int atol(char const * nptr); +long long int atoll(char const * nptr); +int strfromd(char * restrict s, size_t n, char const * restrict format, double fp); +int strfromf(char * restrict s, size_t n, char const * restrict format, float fp); +int strfroml(char * restrict s, size_t n, char const * restrict format, long double fp); +double strtod(char const * restrict nptr, char ** restrict endptr); +float strtof(char const * restrict nptr, char ** restrict endptr); +long double strtold(char const * restrict nptr, char ** restrict endptr); +long int strtol(char const * restrict nptr, char ** restrict endptr, int base); +long long int strtoll(char const * restrict nptr, char ** restrict endptr, int base); +unsigned long int strtoul(char const * restrict nptr, char ** restrict endptr, int base); +unsigned long long int strtoull(char const * restrict nptr, + char ** restrict endptr, int base); +int rand(void); +void srand(unsigned int seed); +void * aligned_alloc(size_t alignment, size_t size); +void * calloc(size_t nmemb, size_t size); +void free(void * ptr); +void free_sized(void * ptr, size_t size); +void free_aligned_sized(void * ptr, size_t alignment, size_t size); +void * malloc(size_t size); +void * realloc(void * ptr, size_t size); +[[noreturn]] void abort(void); +int atexit(void (*func)(void)); +int at_quick_exit(void (*func)(void)); +[[noreturn]] void exit(int status); +[[noreturn]] void _Exit(int status); +char * getenv(char const * name); +[[noreturn]] void quick_exit(int status); +int system(char const * string); +// void * bsearch(void const * key, void const * ptr, size_t count, size_t size, +// int (*comp)(void const *, void const *)); + +// void * bsearch_s(void const * key, void const * ptr, rsize_t count, rsize_t size, +// int (*comp)(void const *, void const *, void *), +// void * context); + +void qsort(void * base, size_t nmemb, size_t size, + int (*compar)(void const *, void const *)); +int abs(int j); +long int labs(long int j); +long long int llabs(long long int j); + +typedef struct _ashet_div { + int quot; + int rem; +} div_t; +div_t div(int numer, int denom); + +typedef struct _ashet_ldiv { + long quot; + long rem; +} ldiv_t; +ldiv_t ldiv(long int numer, long int denom); + +typedef struct _ashet_lldiv { + long long quot; + long long rem; +} lldiv_t; +lldiv_t lldiv(long long int numer, long long int denom); + +int mblen(char const * s, size_t n); +int mbtowc(wchar_t * restrict pwc, char const * restrict s, size_t n); +int wctomb(char * s, wchar_t wc); +size_t mbstowcs(wchar_t * restrict pwcs, char const * restrict s, size_t n); +size_t wcstombs(char * restrict s, wchar_t const * restrict pwcs, size_t n); +size_t memalignment(void const * p); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/string.h b/src/userland/libs/libAshetOS/libc/include/string.h new file mode 100644 index 00000000..0392b02d --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/string.h @@ -0,0 +1,30 @@ +#ifndef _FOUNDATION_LIBC_STRING_H_ +#define _FOUNDATION_LIBC_STRING_H_ + +#include + +void * memchr(void const * s, int c, size_t n); +int memcmp(void const * s1, void const * s2, size_t n); +void * memcpy(void * restrict s1, void const * restrict s2, size_t n); +void * memmove(void * s1, void const * s2, size_t n); +void * memset(void * s, int c, size_t n); +char * strcat(char * restrict s1, char const * restrict s2); +char * strchr(char const * str, int ch); +int strcmp(char const * s1, char const * s2); +char * strcpy(char * restrict s1, char const * restrict s2); +size_t strcspn(char const * s1, char const * s2); +char * strerror(int errnum); +size_t strlen(char const * str); +char * strncat(char * restrict s1, char const * restrict s2, size_t n); +int strncmp(char const * lhs, char const * rhs, size_t count); +char * strncpy(char * restrict s1, char const * restrict s2, size_t n); +char * strpbrk(char const * s1, char const * s2); +char * strrchr(char const * s, int c); +size_t strspn(char const * s1, char const * s2); +char * strstr(char const * s1, char const * s2); +char * strtok(char * restrict s1, char const * restrict s2); + +// locale dependent: size_t strxfrm(char * restrict s1, const char * restrict +// s2, size_t n); locale dependent: int strcoll(const char *s1, const char *s2); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/tgmath.h b/src/userland/libs/libAshetOS/libc/include/tgmath.h new file mode 100644 index 00000000..a6a0c603 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/tgmath.h @@ -0,0 +1,4 @@ +#ifndef _FOUNDATION_LIBC_TGMATH_H_ +#define _FOUNDATION_LIBC_TGMATH_H_ + +#endif diff --git a/src/userland/libs/libAshetOS/libc/include/uchar.h b/src/userland/libs/libAshetOS/libc/include/uchar.h new file mode 100644 index 00000000..634470ca --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/include/uchar.h @@ -0,0 +1,18 @@ +#ifndef _FOUNDATION_LIBC_UCHAR_H_ +#define _FOUNDATION_LIBC_UCHAR_H_ + +#include + +typedef struct { + int dummy; // TODO: fill in internal multi-byte conversion state +} mbstate_t; + +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; + +size_t mbrtoc16(char16_t * restrict pc16, char const * restrict s, size_t n, mbstate_t * restrict ps); +size_t c16rtomb(char * restrict s, char16_t c16, mbstate_t * restrict ps); +size_t mbrtoc32(char32_t * restrict pc32, char const * restrict s, size_t n, mbstate_t * restrict ps); +size_t c32rtomb(char * restrict s, char32_t c32, mbstate_t * restrict ps); + +#endif diff --git a/src/userland/libs/libAshetOS/libc/src/libc.zig b/src/userland/libs/libAshetOS/libc/src/libc.zig new file mode 100644 index 00000000..d3788af5 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/libc.zig @@ -0,0 +1,89 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub const h = @cImport({ + @cInclude("assert.h"); + @cInclude("ctype.h"); + @cInclude("errno.h"); + @cInclude("inttypes.h"); + @cInclude("math.h"); + @cInclude("setjmp.h"); + @cInclude("stdlib.h"); + @cInclude("string.h"); + @cInclude("tgmath.h"); + @cInclude("uchar.h"); + + @cInclude("foundation/libc.h"); +}); + +comptime { + // Some assertions over the target platform: + std.debug.assert(@bitSizeOf(c_char) == 8); + + // Ensure hierarchy: + std.debug.assert(@bitSizeOf(c_short) >= @bitSizeOf(c_char)); + std.debug.assert(@bitSizeOf(c_int) >= @bitSizeOf(c_short)); + std.debug.assert(@bitSizeOf(c_long) >= @bitSizeOf(c_int)); + std.debug.assert(@bitSizeOf(c_longlong) >= @bitSizeOf(c_long)); + + // Ensure same-sized signed and unsigned + std.debug.assert(@bitSizeOf(c_ushort) == @bitSizeOf(c_short)); + std.debug.assert(@bitSizeOf(c_uint) == @bitSizeOf(c_int)); + std.debug.assert(@bitSizeOf(c_ulong) == @bitSizeOf(c_long)); + std.debug.assert(@bitSizeOf(c_ulonglong) == @bitSizeOf(c_longlong)); +} + +comptime { + // Drag in all implementations, so they are compiled: + _ = @import("modules/assert.zig"); + _ = @import("modules/ctype.zig"); + _ = @import("modules/errno.zig"); + _ = @import("modules/math.zig"); + _ = @import("modules/setjmp.zig"); + _ = @import("modules/stdlib.zig"); + _ = @import("modules/string.zig"); + _ = @import("modules/uchar.zig"); +} + +/// Invokes safety-checked undefined behaviour, use this to implement +/// UB checks in the libc itself. +pub fn undefined_behaviour(comptime string: []const u8) noreturn { + switch (builtin.mode) { + // In debug mode, trigger a breakpoint so it's easier to detect the situation + // of the undefined behaviour: + .Debug => { + @breakpoint(); + @panic("UNDEFINED BEHAVIOUR: " ++ string); + }, + + // Safe modes have nice messages with + .ReleaseSafe => @panic("UNDEFINED BEHAVIOUR DETECTED: " ++ string), + + .ReleaseSmall => @panic("UB"), + + .ReleaseFast => unreachable, + } +} + +/// Zig panic handler, forwards panics to `foundation_libc_panic_handler`. +pub fn panic(msg: []const u8, maybe_error_return_trace: ?*std.builtin.StackTrace, maybe_return_address: ?usize) noreturn { + _ = maybe_error_return_trace; + _ = maybe_return_address; + h.foundation_libc_panic_handler(msg.ptr, msg.len); + unreachable; +} + +/// default implementation for `foundation_libc_panic_handler`. +fn fallback_panic_handler(msg_ptr: [*]const u8, msg_len: usize) callconv(.c) noreturn { + _ = msg_ptr; + _ = msg_len; + @trap(); +} +comptime { + const ptr = &fallback_panic_handler; + @export(ptr, std.builtin.ExportOptions{ + .name = "foundation_libc_panic_handler", + .linkage = .weak, + .visibility = .default, + }); +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/assert.zig b/src/userland/libs/libAshetOS/libc/src/modules/assert.zig new file mode 100644 index 00000000..436760ae --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/assert.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +export fn foundation_libc_assert( + assertion: ?[*:0]const u8, + file: ?[*:0]const u8, + line: c_uint, +) noreturn { + switch (builtin.mode) { + .Debug, .ReleaseSafe => { + var buf: [256]u8 = undefined; + const str = std.fmt.bufPrint(&buf, "assertion failed: '{?s}' in file {?s} line {}", .{ assertion, file, line }) catch { + @panic("assertion failed"); + }; + @panic(str); + }, + .ReleaseSmall => @panic("assertion failed"), + .ReleaseFast => unreachable, + } +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/ctype.zig b/src/userland/libs/libAshetOS/libc/src/modules/ctype.zig new file mode 100644 index 00000000..1f613311 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/ctype.zig @@ -0,0 +1,127 @@ +//! implementation of `ctype.h` +//! +//! The header declares several functions useful for classifying and mapping +//! characters. In all cases the argument is an int, the value of which shall be +//! representable as an unsigned char or shall equal the value of the macro EOF. If the +//! argument has any other value, the behavior is undefined. +//! + +const std = @import("std"); +const libc = @import("../libc.zig"); + +// Use an alias to std.ascii to allow potential future replacement +// of the locale implementation: +const locale = std.ascii; + +const EOF = libc.h.EOF; + +/// Convert input to u8, undefined behaviour +fn conv(c: c_int) ?u8 { + if (c == EOF) + return null; + return std.math.cast(u8, c) orelse libc.undefined_behaviour("passed a value that is not unsigned char nor EOF to a ctype function"); +} + +/// The isalnum function tests for any character for which isalpha or isdigit is true. +export fn isalnum(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isAlphanumeric(u)); +} + +/// The isalpha function tests for any character for which isupper or islower is true, +/// or any character that is one of a locale-specific set of alphabetic characters for which +/// none of iscntrl, isdigit, ispunct, or isspace is true.200) In the "C" locale, +/// isalpha returns true only for the characters for which isupper or islower is true. +export fn isalpha(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isAlphabetic(u)); +} + +/// The isblank function tests for any character that is a standard blank character or is one +/// of a locale-specific set of characters for which isspace is true and that is used to +/// separate words within a line of text. The standard blank characters are the following: +/// space (' '), and horizontal tab ('\t'). In the "C" locale, isblank returns true only +/// for the standard blank characters. +export fn isblank(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(u == ' ' or u == '\t'); +} + +/// The iscntrl function tests for any control character. +export fn iscntrl(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isControl(u)); +} + +/// The isdigit function tests for any decimal-digit character (as defined in 5.2.1). +export fn isdigit(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isDigit(u)); +} + +/// The isgraph function tests for any printing character except space (' '). +export fn isgraph(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isPrint(u) and (c != ' ')); +} + +/// The islower function tests for any character that is a lowercase letter or is one of a +/// locale-specific set of characters for which none of iscntrl, isdigit, ispunct, or +/// isspace is true. In the "C" locale, islower returns true only for the lowercase +/// letters (as defined in 5.2.1). +export fn islower(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isLower(u)); +} + +/// The isprint function tests for any printing character including space (' '). +export fn isprint(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isPrint(u)); +} + +/// The ispunct function tests for any printing character that is one of a locale-specific set +/// of punctuation characters for which neither isspace nor isalnum is true. In the "C" +/// locale, ispunct returns true for every printing character for which neither isspace +/// nor isalnum is true. +export fn ispunct(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(!locale.isWhitespace(u) and !locale.isAlphanumeric(u)); +} + +/// The isspace function tests for any character that is a standard white-space character or +/// is one of a locale-specific set of characters for which isalnum is false. The standard +/// white-space characters are the following: space (' '), form feed ('\f'), new-line +/// ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). In the +/// "C" locale, isspace returns true only for the standard white-space characters. +export fn isspace(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isWhitespace(u)); +} + +/// The isupper function tests for any character that is an uppercase letter or is one of a +/// locale-specific set of characters for which none of iscntrl, isdigit, ispunct, or +/// isspace is true. In the "C" locale, isupper returns true only for the uppercase +/// letters (as defined in 5.2.1). +export fn isupper(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isUpper(u)); +} + +/// The isxdigit function tests for any hexadecimal-digit character (as defined in 6.4.4.1). +export fn isxdigit(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return @intFromBool(locale.isHex(u)); +} + +/// The tolower function converts an uppercase letter to a corresponding lowercase letter. +export fn tolower(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return locale.toLower(u); +} + +/// The toupper function converts a lowercase letter to a corresponding uppercase letter. +export fn toupper(c: c_int) c_int { + const u = conv(c) orelse return EOF; + return locale.toUpper(u); +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/errno.zig b/src/userland/libs/libAshetOS/libc/src/modules/errno.zig new file mode 100644 index 00000000..a1f4c1ac --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/errno.zig @@ -0,0 +1,17 @@ +//! implementation of `errno.h` + +const std = @import("std"); +const builtin = @import("builtin"); + +const storage = if (builtin.single_threaded) + struct { + var errno: c_int = 0; // regular variable on single-threaded systems + } +else + struct { + threadlocal var errno: c_int = 0; // thread-local variable on multi-threaded systems + }; + +export fn __get_errno() *c_int { + return &storage.errno; +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/math.zig b/src/userland/libs/libAshetOS/libc/src/modules/math.zig new file mode 100644 index 00000000..1a3da769 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/math.zig @@ -0,0 +1,3 @@ +//! implementation of `math.h` + +const std = @import("std"); diff --git a/src/userland/libs/libAshetOS/libc/src/modules/setjmp.zig b/src/userland/libs/libAshetOS/libc/src/modules/setjmp.zig new file mode 100644 index 00000000..6e0b0ea3 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/setjmp.zig @@ -0,0 +1,3 @@ +//! implementation of `setjmp.h` + +const std = @import("std"); diff --git a/src/userland/libs/libAshetOS/libc/src/modules/stdlib.zig b/src/userland/libs/libAshetOS/libc/src/modules/stdlib.zig new file mode 100644 index 00000000..b3375800 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/stdlib.zig @@ -0,0 +1,17 @@ +//! implementation of `stdlib.h` + +const std = @import("std"); + +/// https://en.cppreference.com/w/c/string/byte/atoi +export fn atoi(str: ?[*:0]const c_char) c_int { + const s = str orelse return 0; + + var i: usize = 0; + while (std.ascii.isWhitespace(@bitCast(s[i]))) { + i += 1; + } + + const slice = std.mem.sliceTo(s + i, 0); + + return std.fmt.parseInt(c_int, @ptrCast(slice), 10) catch return 0; +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/string.zig b/src/userland/libs/libAshetOS/libc/src/modules/string.zig new file mode 100644 index 00000000..d17ce7f0 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/string.zig @@ -0,0 +1,69 @@ +//! implementation of `string.h` + +const std = @import("std"); + +// Implemented in compiler_rt: +// * memcpy +// * memset + +// TODO: memchr +// TODO: memcmp +// TODO: memmove +// TODO: strcat +// TODO: strcmp +// TODO: strcpy +// TODO: strcspn +// TODO: strerror +// TODO: strncat +// TODO: strncpy +// TODO: strpbrk +// TODO: strrchr +// TODO: strspn +// TODO: strstr + +/// https://en.cppreference.com/w/c/string/byte/strchr +export fn strchr(str: ?[*:0]const c_char, ch: c_int) ?[*:0]c_char { + const s = str orelse return null; + + const searched: c_char = @bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(ch))))); + + var i: usize = 0; + while (true) { + const actual = s[i]; + if (actual == searched) + return @constCast(s + i); + if (actual == 0) + return null; + i += 1; + } +} + +/// https://en.cppreference.com/w/c/string/byte/strlen +export fn strlen(str: ?[*:0]const c_char) usize { + const s = str orelse return 0; + return std.mem.len(s); +} + +/// https://en.cppreference.com/w/c/string/byte/strncmp +export fn strncmp(lhs: ?[*:0]const c_char, rhs: ?[*:0]const c_char, count: usize) c_int { + const lhs_s: [*:0]const u8 = @ptrCast(lhs orelse return if (rhs != null) 1 else 0); + const rhs_s: [*:0]const u8 = @ptrCast(rhs orelse return if (lhs != null) -1 else 0); + + var i: usize = 0; + while (i < count) { + const l = lhs_s[i]; + const r = rhs_s[i]; + + const d = @as(c_int, l) - @as(c_int, r); + if (d != 0) + return d; + + if (l == 0 and r == 0) + return 0; + std.debug.assert(l != 0); + std.debug.assert(r != 0); + + i += 1; + } + return 0; +} diff --git a/src/userland/libs/libAshetOS/libc/src/modules/uchar.zig b/src/userland/libs/libAshetOS/libc/src/modules/uchar.zig new file mode 100644 index 00000000..7b4706d6 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/src/modules/uchar.zig @@ -0,0 +1,3 @@ +//! implementation of `uchar.h` + +const std = @import("std"); diff --git a/src/userland/libs/libAshetOS/libc/sys_include/sys/time.h b/src/userland/libs/libAshetOS/libc/sys_include/sys/time.h new file mode 100644 index 00000000..6ba53ab5 --- /dev/null +++ b/src/userland/libs/libAshetOS/libc/sys_include/sys/time.h @@ -0,0 +1,3 @@ +#pragma once + +// TODO: Required by mquickjs \ No newline at end of file diff --git a/src/userland/libs/libAshetOS/src/genfile.zig b/src/userland/libs/libAshetOS/src/genfile.zig new file mode 100644 index 00000000..1bc62757 --- /dev/null +++ b/src/userland/libs/libAshetOS/src/genfile.zig @@ -0,0 +1,43 @@ +const std = @import("std"); + +pub fn main() !u8 { + var arena: std.heap.ArenaAllocator = .init(std.heap.page_allocator); + const allocator = arena.allocator(); + + const argv = try std.process.argsAlloc(allocator); + std.debug.assert(argv.len >= 1); + + var stdout = std.io.getStdOut().writer(); + + for (argv[1..]) |data| { + try stdout.print("{s}\n", .{data}); + } + + return 0; +} + +// # The directory that contains `stdlib.h`. +// # On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null` +// include_dir=/usr/include + +// # The system-specific include directory. May be the same as `include_dir`. +// # On Windows it's the directory that includes `vcruntime.h`. +// # On POSIX it's the directory that includes `sys/errno.h`. +// sys_include_dir=/usr/include + +// # The directory that contains `crt1.o` or `crt2.o`. +// # On POSIX, can be found with `cc -print-file-name=crt1.o`. +// # Not needed when targeting MacOS. +// crt_dir=/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib + +// # The directory that contains `vcruntime.lib`. +// # Only needed when targeting MSVC on Windows. +// msvc_lib_dir= + +// # The directory that contains `kernel32.lib`. +// # Only needed when targeting MSVC on Windows. +// kernel32_lib_dir= + +// # The directory that contains `crtbeginS.o` and `crtendS.o` +// # Only needed when targeting Haiku. +// gcc_dir= diff --git a/vendor/mqjs/build.zig b/vendor/mqjs/build.zig new file mode 100644 index 00000000..347fd774 --- /dev/null +++ b/vendor/mqjs/build.zig @@ -0,0 +1,114 @@ +const std = @import("std"); + +const host_flags: []const []const u8 = &.{ + "-Wall", + "-g", + "-MMD", + "-D_GNU_SOURCE", + "-fno-math-errno", + "-fno-trapping-math", + "-fno-sanitize=undefined", // TODO: Fix this upstream! +}; + +const c_flags: []const []const u8 = &.{ + "-Wall", + "-g", + "-MMD", + "-D_GNU_SOURCE", + "-fno-math-errno", + "-fno-trapping-math", + "-fno-sanitize=undefined", // TODO: Fix this upstream! + // "USE_SOFTFLOAT" may be required on some targets? +}; + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const upstream = b.dependency("upstream", .{}); + + const stdlib_mod = b.createModule(.{ + .target = b.graph.host, + .optimize = .ReleaseSafe, + .link_libc = true, + }); + stdlib_mod.addCSourceFiles(.{ + .files = &.{ + "mqjs_stdlib.c", + "mquickjs_build.c", + }, + .flags = host_flags, + .root = upstream.path("."), + }); + + const stdlib_exe = b.addExecutable(.{ + .name = "mqjs_stdlib", + .root_module = stdlib_mod, + }); + b.installArtifact(stdlib_exe); + + const mqjs_build_flags: []const []const u8 = switch (target.result.ptrBitWidth()) { + 16 => @panic("16 bit builds not supported."), + 32 => comptime &.{"-m32"}, + 64 => comptime &.{}, + else => unreachable, + }; + const gen_atom_h_run = b.addRunArtifact(stdlib_exe); + gen_atom_h_run.addArg("-a"); + gen_atom_h_run.addArgs(mqjs_build_flags); + const mquickjs_atom_h_path = gen_atom_h_run.captureStdOut(); + + const gen_stdlib_h_run = b.addRunArtifact(stdlib_exe); + gen_stdlib_h_run.addArgs(mqjs_build_flags); + const mquickjs_stdlib_h_path = gen_stdlib_h_run.captureStdOut(); + + const include_dir = b.addWriteFiles(); + _ = include_dir.addCopyFile(mquickjs_atom_h_path, "mquickjs_atom.h"); + _ = include_dir.addCopyFile(mquickjs_stdlib_h_path, "mqjs_stdlib.h"); + + const mqjs_mod = b.addModule("mqjs", .{ + .root_source_file = null, + .target = target, + .optimize = optimize, + .link_libc = false, + }); + mqjs_mod.addIncludePath(upstream.path(".")); + mqjs_mod.addIncludePath(include_dir.getDirectory()); + mqjs_mod.addCSourceFiles(.{ + .files = &.{ + "mquickjs.c", + "dtoa.c", + "libm.c", + "cutils.c", + }, + .flags = c_flags, + .root = upstream.path("."), + }); + + const mqjs_cli_mod = b.createModule(.{ + .root_source_file = null, + .target = target, + .optimize = optimize, + .link_libc = true, + .imports = &.{ + .{ .name = "mqjs", .module = mqjs_mod }, + }, + }); + + mqjs_cli_mod.addCSourceFiles(.{ + .files = &.{ + "mqjs.c", + "readline_tty.c", + "readline.c", + }, + .flags = c_flags, + .root = upstream.path("."), + }); + + const mqjs_exe = b.addExecutable(.{ + .name = "mqjs", + .root_module = mqjs_cli_mod, + }); + + b.installArtifact(mqjs_exe); +} diff --git a/vendor/mqjs/build.zig.zon b/vendor/mqjs/build.zig.zon new file mode 100644 index 00000000..d443ca19 --- /dev/null +++ b/vendor/mqjs/build.zig.zon @@ -0,0 +1,15 @@ +.{ + .name = .mqjs, + .fingerprint = 0xeb25510e67a6f94b, + .version = "2026.1.4", + .paths = .{ + "build.zig", + "build.zig.zon", + }, + .dependencies = .{ + .upstream = .{ + .url = "git+https://github.com/bellard/mquickjs.git#767e5db54241f0b53193a04aea193c823a9e3121", + .hash = "N-V-__8AAH_KDgAc_2J3w461iC-aXVoZUUf3cikp2GONAVnb", + }, + }, +}