Got a basic WebAssembly module compiling with support for calling jsStdPrint through printf implementation (provided by stb_sprintf.h). We have a single function "HelloFromWasm" exported for testing purposes. Pulled in a bunch of standard library headers from PigCore's wasm layer.

This commit is contained in:
Taylor Robbins (Piggybank Studios)
2025-08-28 09:44:32 -07:00
parent aa2faca658
commit deae3ccd12
20 changed files with 2882 additions and 85 deletions

14
std/assert.h Normal file
View File

@@ -0,0 +1,14 @@
/*
File: assert.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _ASSERT_H
#define _ASSERT_H
#define assert(condition) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, nullptr); } } while(0)
//NOTE: assert_msg is not a standard function but we want to be able to pass a message to jsStdAssertFailure so we added this variant
#define assert_msg(condition, message) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, (message)); } } while(0)
#endif // _ASSERT_H

32
std/limits.h Normal file
View File

@@ -0,0 +1,32 @@
/*
File: limits.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _LIMITS_H
#define _LIMITS_H
#define CHAR_MIN (-128)
#define CHAR_MAX 127
#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define UCHAR_MAX 255
#define SHRT_MIN (-1-0x7fff)
#define SHRT_MAX 0x7fff
#define USHRT_MAX 0xffff
#define INT_MIN (-1-0x7fffffff)
#define INT_MAX 0x7fffffff
#define UINT_MAX 0xffffffffU
#define LONG_MIN (-LONG_MAX-1)
#define LONG_MAX __LONG_MAX
#define ULONG_MAX (2UL*LONG_MAX+1)
#define LLONG_MIN (-LLONG_MAX-1)
#define LLONG_MAX 0x7fffffffffffffffLL
#define ULLONG_MAX (2ULL*LLONG_MAX+1)
//TODO: Define PAGESIZE?
#endif // _LIMITS_H

1906
std/src/stb_sprintf.h Normal file

File diff suppressed because it is too large Load Diff

18
std/src/std_js_imports.h Normal file
View File

@@ -0,0 +1,18 @@
/*
File: std_js_imports.h
Author: Taylor Robbins
Date: 08\28\2025
Description:
** Holds the declarations for functions that we expect to be imported by the Javascript glue code and imported to the module when it's loaded
*/
#ifndef _STD_JS_IMPORTS_H
#define _STD_JS_IMPORTS_H
MAYBE_EXTERN_C void jsStdPrint(const char* messageStrPntr, int messageLength);
MAYBE_EXTERN_C _Noreturn void jsStdAbort(const char* messageStrPntr, int exitCode);
MAYBE_EXTERN_C _Noreturn void jsStdAssertFailure(const char* filePathPntr, int fileLineNum, const char* funcNamePntr, const char* conditionStrPntr, const char* messageStrPntr);
MAYBE_EXTERN_C void jsStdDebugBreak();
MAYBE_EXTERN_C void jsStdGrowMemory(unsigned int numPages);
#endif // _STD_JS_IMPORTS_H

21
std/src/std_main.c Normal file
View File

@@ -0,0 +1,21 @@
/*
File: std_main.c
Author: Taylor Robbins
Date: 08\28\2025
Description:
** Contains the implementations for all standard library functions that are declared in the headers in the parent folder
*/
#include <limits.h>
#include <stdint.h>
#include <uchar.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include "std_js_imports.h"
#include "std_memset.c"
#include "std_printf.c"

370
std/src/std_memset.c Normal file
View File

@@ -0,0 +1,370 @@
/*
File: std_memset.c
Author: Taylor Robbins
Date: 08\28\2025
Description:
** Holds implementations of functions like memset(), memcpy(), memmove(), etc.
*/
#define WORD_CONTAINS_ZERO(word) ((word)-((size_t)-1/UCHAR_MAX) & ~(word) & (((size_t)-1/UCHAR_MAX) * (UCHAR_MAX/2+1)))
#define MAX(left, right) ((left) > (right) ? (left) : (right))
#define MIN(left, right) ((left) < (right) ? (left) : (right))
typedef size_t __attribute__((__may_alias__)) a_size_t;
#define SIZEOF_A_SIZE_T sizeof(a_size_t)
typedef uint32_t __attribute__((__may_alias__)) a_u32;
typedef uint64_t __attribute__((__may_alias__)) a_u64;
#if !WASM_STD_USE_BUILTIN_MEMSET
void* _memset(void* pntr, int value, size_t numBytes)
{
unsigned char* charPntr = pntr;
size_t alignment;
// Fill head and tail with minimal branching. Each
// conditional ensures that all the subsequently used
// offsets are well-defined and in the pntr region.
if (!numBytes) { return pntr; }
charPntr[0] = value;
charPntr[numBytes-1] = value;
if (numBytes <= 2) { return pntr; }
charPntr[1] = value;
charPntr[2] = value;
charPntr[numBytes-2] = value;
charPntr[numBytes-3] = value;
if (numBytes <= 6) { return pntr; }
charPntr[3] = value;
charPntr[numBytes-4] = value;
if (numBytes <= 8) { return pntr; }
// Advance pointer to align it at a 4-byte boundary,
// and truncate numBytes to a multiple of 4. The previous code
// already took care of any head/tail that get cut off
// by the alignment.
alignment = (-(uintptr_t)charPntr & 3);
charPntr += alignment;
numBytes -= alignment;
numBytes &= -4;
a_u32 value32 = ((a_u32) - 1) / 255 * (unsigned char)value;
// In preparation to copy 32 bytes at a time, aligned on
// an 8-byte bounary, fill head/tail up to 28 bytes each.
// As in the initial byte-based head/tail fill, each
// conditional below ensures that the subsequent offsets
// are valid (e.g. !(numBytes<=24) implies numBytes>=28).
*(a_u32*)(charPntr + 0) = value32;
*(a_u32*)(charPntr + numBytes - 4) = value32;
if (numBytes <= 8) { return pntr; }
*(a_u32*)(charPntr + 4) = value32;
*(a_u32*)(charPntr + 8) = value32;
*(a_u32*)(charPntr + numBytes - 12) = value32;
*(a_u32*)(charPntr + numBytes - 8) = value32;
if (numBytes <= 24) { return pntr; }
*(a_u32*)(charPntr + 12) = value32;
*(a_u32*)(charPntr + 16) = value32;
*(a_u32*)(charPntr + 20) = value32;
*(a_u32*)(charPntr + 24) = value32;
*(a_u32*)(charPntr + numBytes - 28) = value32;
*(a_u32*)(charPntr + numBytes - 24) = value32;
*(a_u32*)(charPntr + numBytes - 20) = value32;
*(a_u32*)(charPntr + numBytes - 16) = value32;
// Align to a multiple of 8 so we can fill 64 bits at a time,
// and avoid writing the same bytes twice as much as is
// practical without introducing additional branching.
alignment = 24 + ((uintptr_t)charPntr & 4);
charPntr += alignment;
numBytes -= alignment;
// If this loop is reached, 28 tail bytes have already been
// filled, so any remainder when numBytes drops below 32 can be
// safely ignored.
a_u64 value64 = (value32 | ((a_u64)value32 << 32));
for (; numBytes >= 32; numBytes -= 32, charPntr += 32)
{
*(a_u64*)(charPntr + 0) = value64;
*(a_u64*)(charPntr + 8) = value64;
*(a_u64*)(charPntr + 16) = value64;
*(a_u64*)(charPntr + 24) = value64;
}
return pntr;
}
#endif //!WASM_STD_USE_BUILTIN_MEMSET
#if !WASM_STD_USE_BUILTIN_MEMCPY
void* _memcpy(void* dest, const void* source, size_t numBytes)
{
unsigned char* destCharPntr = dest;
const unsigned char* sourceCharPntr = source;
uint32_t wVarU32, xVarU32;
for (; (uintptr_t)sourceCharPntr % 4 && numBytes; numBytes--)
{
*destCharPntr++ = *sourceCharPntr++;
}
if ((uintptr_t)destCharPntr % 4 == 0)
{
for (; numBytes >= 16; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
{
*(a_u32*)(destCharPntr + 0) = *(a_u32*)(sourceCharPntr + 0);
*(a_u32*)(destCharPntr + 4) = *(a_u32*)(sourceCharPntr + 4);
*(a_u32*)(destCharPntr + 8) = *(a_u32*)(sourceCharPntr + 8);
*(a_u32*)(destCharPntr + 12) = *(a_u32*)(sourceCharPntr + 12);
}
if (numBytes & 8)
{
*(a_u32*)(destCharPntr + 0) = *(a_u32*)(sourceCharPntr + 0);
*(a_u32*)(destCharPntr + 4) = *(a_u32*)(sourceCharPntr + 4);
destCharPntr += 8;
sourceCharPntr += 8;
}
if (numBytes & 4)
{
*(a_u32*)(destCharPntr+0) = *(a_u32*)(sourceCharPntr + 0);
destCharPntr += 4;
sourceCharPntr += 4;
}
if (numBytes & 2)
{
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
}
if (numBytes & 1)
{
*destCharPntr = *sourceCharPntr;
}
return dest;
}
if (numBytes >= 32)
{
switch ((uintptr_t)destCharPntr % 4)
{
case 1:
{
wVarU32 = *(a_u32*)sourceCharPntr;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
numBytes -= 3;
for (; numBytes >= 17; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
{
xVarU32 = *(a_u32*)(sourceCharPntr + 1);
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 24) | (xVarU32 << 8));
wVarU32 = *(a_u32*)(sourceCharPntr + 5);
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 24) | (wVarU32 << 8));
xVarU32 = *(a_u32*)(sourceCharPntr + 9);
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 24) | (xVarU32 << 8));
wVarU32 = *(a_u32*)(sourceCharPntr + 13);
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 24) | (wVarU32 << 8));
}
} break;
case 2:
{
wVarU32 = *(a_u32*)sourceCharPntr;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
numBytes -= 2;
for (; numBytes >= 18; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
{
xVarU32 = *(a_u32*)(sourceCharPntr + 2);
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 16) | (xVarU32 << 16));
wVarU32 = *(a_u32*)(sourceCharPntr + 6);
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 16) | (wVarU32 << 16));
xVarU32 = *(a_u32*)(sourceCharPntr + 10);
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 16) | (xVarU32 << 16));
wVarU32 = *(a_u32*)(sourceCharPntr + 14);
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 16) | (wVarU32 << 16));
}
} break;
case 3:
{
wVarU32 = *(a_u32*)sourceCharPntr;
*destCharPntr++ = *sourceCharPntr++;
numBytes -= 1;
for (; numBytes >= 19; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
{
xVarU32 = *(a_u32*)(sourceCharPntr + 3);
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 8) | (xVarU32 << 24));
wVarU32 = *(a_u32*)(sourceCharPntr + 7);
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 8) | (wVarU32 << 24));
xVarU32 = *(a_u32*)(sourceCharPntr + 11);
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 8) | (xVarU32 << 24));
wVarU32 = *(a_u32*)(sourceCharPntr + 15);
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 8) | (wVarU32 << 24));
}
} break;
}
}
if (numBytes & 16)
{
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
}
if (numBytes & 8)
{
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
}
if (numBytes & 4)
{
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
}
if (numBytes & 2)
{
*destCharPntr++ = *sourceCharPntr++;
*destCharPntr++ = *sourceCharPntr++;
}
if (numBytes & 1)
{
*destCharPntr = *sourceCharPntr;
}
return dest;
}
#endif //!WASM_STD_USE_BUILTIN_MEMSET
#if !WASM_STD_USE_BUILTIN_MEMMOVE
void* _memmove(void* dest, const void* source, size_t numBytes)
{
char* destCharPntr = dest;
const char* sourceCharPntr = source;
if (destCharPntr == sourceCharPntr) { return destCharPntr; }
if ((uintptr_t)sourceCharPntr - (uintptr_t)destCharPntr - numBytes <= -2 * numBytes)
{
return memcpy(destCharPntr, sourceCharPntr, numBytes);
}
if (destCharPntr < sourceCharPntr)
{
if ((uintptr_t)sourceCharPntr % SIZEOF_A_SIZE_T == (uintptr_t)destCharPntr % SIZEOF_A_SIZE_T)
{
while ((uintptr_t)destCharPntr % SIZEOF_A_SIZE_T)
{
if (!numBytes--) { return dest; }
*destCharPntr++ = *sourceCharPntr++;
}
for (; numBytes >= SIZEOF_A_SIZE_T; numBytes -= SIZEOF_A_SIZE_T, destCharPntr += SIZEOF_A_SIZE_T, sourceCharPntr += SIZEOF_A_SIZE_T)
{
*(a_size_t*)destCharPntr = *(a_size_t*)sourceCharPntr;
}
}
for (; numBytes; numBytes--) { *destCharPntr++ = *sourceCharPntr++; }
}
else
{
if (((uintptr_t)sourceCharPntr % SIZEOF_A_SIZE_T) == ((uintptr_t)destCharPntr % SIZEOF_A_SIZE_T))
{
while ((uintptr_t)(destCharPntr + numBytes) % SIZEOF_A_SIZE_T)
{
if (!numBytes--) { return dest; }
destCharPntr[numBytes] = sourceCharPntr[numBytes];
}
while (numBytes >= SIZEOF_A_SIZE_T)
{
numBytes -= SIZEOF_A_SIZE_T;
*(a_size_t*)(destCharPntr+numBytes) = *(a_size_t*)(sourceCharPntr + numBytes);
}
}
while (numBytes)
{
numBytes--;
destCharPntr[numBytes] = sourceCharPntr[numBytes];
}
}
return dest;
}
#endif //!WASM_STD_USE_BUILTIN_MEMMOVE
int memcmp(const void* left, const void* right, size_t numBytes)
{
const unsigned char *leftByte = left, *rightByte = right;
for (; (numBytes && *leftByte == *rightByte); numBytes--, leftByte++, rightByte++);
return (numBytes ? *leftByte - *rightByte : 0);
}
int strcmp(const char* left, const char* right)
{
for (; *left == *right && *left; left++, right++);
return (*(unsigned char*)left - *(unsigned char*)right);
}
char* strcpy(char* dest, const char* source)
{
a_size_t* destWord;
const a_size_t* sourceWord;
if ((uintptr_t)source % sizeof(size_t) == (uintptr_t)dest % sizeof(size_t))
{
for (; (uintptr_t)source % sizeof(size_t); source++, dest++)
{
if (!(*dest=*source)) { return dest; }
}
destWord = (void*)dest;
sourceWord = (const void*)source;
for (; !WORD_CONTAINS_ZERO(*sourceWord); *destWord++ = *sourceWord++) { }
dest=(void*)destWord;
source=(const void*)sourceWord;
}
for (; (*dest=*source); source++, dest++) { }
return dest;
}
//TODO: Add strstr implementation!
int strncmp(const char* left, const char* right, size_t numBytes)
{
const unsigned char* leftPntr = (void*)left;
const unsigned char* rightPntr = (void*)right;
if (!numBytes--) { return 0; }
for (; (*leftPntr && *rightPntr && numBytes && *leftPntr == *rightPntr); leftPntr++, rightPntr++, numBytes--);
return *leftPntr - *rightPntr;
}
size_t strlen(const char* str)
{
const char* startPntr = str;
const a_size_t* wordPntr;
//Walk 1 character at a time until we are size_t aligned
for (; ((uintptr_t)str % sizeof(size_t)) != 0; str++)
{
if (!*str) { return str-startPntr; }
}
//Check size_t bytes at once with WORD_CONTAINS_ZERO
for (wordPntr = (const void *)str; !WORD_CONTAINS_ZERO(*wordPntr); wordPntr++) { }
str = (const void *)wordPntr;
//Walk 0-3 bytes until we find the 0 in the word
for (; *str; str++) { }
return (str - startPntr);
}

65
std/src/std_printf.c Normal file
View File

@@ -0,0 +1,65 @@
/*
File: std_printf.c
Author: Taylor Robbins
Date: 08\28\2025
Description:
** None
*/
#define STB_SPRINTF_IMPLEMENTATION
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#include "stb_sprintf.h"
#pragma clang diagnostic pop
//TODO: Should we increase this buffer size? Or make it an option for the user to change? Or dynamically allocate from the stack? Or something else?
#define STD_PRINTF_BUFFER_SIZE 1024 //chars
char stdGlobalPrintBuffer[STD_PRINTF_BUFFER_SIZE];
int vsnprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, va_list args)
{
assert(bufferSize <= INT_MAX);
return stbsp_vsnprintf(bufferPntr, bufferSize, formatStr, args);
}
int vsprintf(char* restrict bufferPntr, const char* restrict formatStr, va_list args)
{
return vsnprintf(bufferPntr, INT_MAX, formatStr, args);
}
int vprintf(const char* restrict formatStr, va_list args)
{
int result = stbsp_vsnprintf(stdGlobalPrintBuffer, STD_PRINTF_BUFFER_SIZE, formatStr, args);
if (result > 0 && result < STD_PRINTF_BUFFER_SIZE)
{
stdGlobalPrintBuffer[result] = '\0'; //ensure null-termination
jsStdPrint(&stdGlobalPrintBuffer[0], result);
}
return result;
}
int snprintf(char* restrict bufferPntr, size_t bufferSize, const char* restrict formatStr, ...)
{
int result;
va_list args;
va_start(args, formatStr);
result = vsnprintf(bufferPntr, bufferSize, formatStr, args);
va_end(args);
return result;
}
int sprintf(char* restrict bufferPntr, const char* restrict formatStr, ...)
{
int result;
va_list args;
va_start(args, formatStr);
result = vsprintf(bufferPntr, formatStr, args);
va_end(args);
return result;
}
int printf(const char* restrict formatStr, ...)
{
int result;
va_list args;
va_start(args, formatStr);
result = vprintf(formatStr, args);
va_end(args);
return result;
}

18
std/stdarg.h Normal file
View File

@@ -0,0 +1,18 @@
/*
File: stdarg.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _STDARG_H
#define _STDARG_H
typedef __builtin_va_list va_list;
typedef __builtin_va_list __isoc_va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
#define va_copy(d,s) __builtin_va_copy(d,s)
#endif // _STDARG_H

20
std/stddef.h Normal file
View File

@@ -0,0 +1,20 @@
/*
File: stddef.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _STDDEF_H
#define _STDDEF_H
#include <stdint.h>
#if LANGUAGE_IS_CPP
#define NULL nullptr
#else
#define NULL ((void*)0)
#endif
#define offsetof(type, member) __builtin_offsetof(type, member)
#endif // _STDDEF_H

132
std/stdint.h Normal file
View File

@@ -0,0 +1,132 @@
/*
File: stdint.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _STDINT_H
#define _STDINT_H
// +--------------------------------------------------------------+
// | Typedefs |
// +--------------------------------------------------------------+
#define _Addr long
#define _Int64 long long
#define _Reg long
#define __BYTE_ORDER __LITTLE_ENDIAN
#define __LONG_MAX 0x7FFFFFFFFFFFFFFFL
#if LANGUAGE_IS_C
#ifdef __WCHAR_TYPE__
typedef __WCHAR_TYPE__ wchar_t;
#else
typedef long wchar_t;
#endif
#endif
typedef float float_t;
typedef double double_t;
typedef unsigned _Addr size_t;
typedef unsigned _Addr uintptr_t;
typedef _Addr ptrdiff_t;
typedef _Addr ssize_t;
typedef _Addr intptr_t;
// typedef _Addr regoff_t;
// typedef _Reg register_t;
// typedef _Int64 time_t;
// typedef _Int64 suseconds_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed _Int64 int64_t;
typedef signed _Int64 intmax_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned _Int64 uint64_t;
typedef unsigned _Int64 u_int64_t;
typedef unsigned _Int64 uintmax_t;
// typedef unsigned mode_t;
// typedef unsigned _Reg nlink_t;
// typedef _Int64 off_t;
// typedef unsigned _Int64 ino_t;
// typedef unsigned _Int64 dev_t;
// typedef long blksize_t;
// typedef _Int64 blkcnt_t;
// typedef unsigned _Int64 fsblkcnt_t;
// typedef unsigned _Int64 fsfilcnt_t;
// typedef unsigned wint_t;
// typedef unsigned long wctype_t;
// typedef void * timer_t;
// typedef int clockid_t;
// typedef long clock_t;
// struct timeval { time_t tv_sec; suseconds_t tv_usec; };
// struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==__BIG_ENDIAN); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=__BIG_ENDIAN); };
// typedef int pid_t;
// typedef unsigned id_t;
// typedef unsigned uid_t;
// typedef unsigned gid_t;
// typedef int key_t;
// typedef unsigned useconds_t;
// +--------------------------------------------------------------+
// | MAX and MIN #defines |
// +--------------------------------------------------------------+
#define INT8_MIN (-1-0x7f)
#define INT16_MIN (-1-0x7fff)
#define INT32_MIN (-1-0x7fffffff)
#define INT64_MIN (-1-0x7fffffffffffffff)
#define INT8_MAX (0x7f)
#define INT16_MAX (0x7fff)
#define INT32_MAX (0x7fffffff)
#define INT64_MAX (0x7fffffffffffffff)
#define UINT8_MAX (0xff)
#define UINT16_MAX (0xffff)
#define UINT32_MAX (0xffffffffu)
#define UINT64_MAX (0xffffffffffffffffu)
// #define INT_FAST8_MIN INT8_MIN
// #define INT_FAST64_MIN INT64_MIN
// #define INT_LEAST8_MIN INT8_MIN
// #define INT_LEAST16_MIN INT16_MIN
// #define INT_LEAST32_MIN INT32_MIN
// #define INT_LEAST64_MIN INT64_MIN
// #define INT_FAST8_MAX INT8_MAX
// #define INT_FAST64_MAX INT64_MAX
// #define INT_LEAST8_MAX INT8_MAX
// #define INT_LEAST16_MAX INT16_MAX
// #define INT_LEAST32_MAX INT32_MAX
// #define INT_LEAST64_MAX INT64_MAX
// #define UINT_FAST8_MAX UINT8_MAX
// #define UINT_FAST64_MAX UINT64_MAX
// #define UINT_LEAST8_MAX UINT8_MAX
// #define UINT_LEAST16_MAX UINT16_MAX
// #define UINT_LEAST32_MAX UINT32_MAX
// #define UINT_LEAST64_MAX UINT64_MAX
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// #define WINT_MIN 0U
// #define WINT_MAX UINT32_MAX
#define WCHAR_MAX (0x7FFFFFFF+L'\0')
#define WCHAR_MIN (-1-0x7FFFFFFF+L'\0')
#define SIG_ATOMIC_MIN INT32_MIN
#define SIG_ATOMIC_MAX INT32_MAX
#endif // _STDINT_H

27
std/stdio.h Normal file
View File

@@ -0,0 +1,27 @@
/*
File: stdio.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _STDIO_H
#define _STDIO_H
#include <stdint.h>
#include <stdarg.h>
MAYBE_START_EXTERN_C
int vprintf(const char* formatStr, va_list args);
// TODO: int vfprintf(FILE*, const char*, va_list args);
int vsprintf(char* bufferPntr, const char* formatStr, va_list args);
int vsnprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, va_list args);
int printf(const char* formatStr, ...);
// TODO: int fprintf(FILE*, const char*, ...);
int sprintf(char* bufferPntr, const char* formatStr, ...);
int snprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, ...);
MAYBE_END_EXTERN_C
#endif // _STDIO_H

56
std/string.h Normal file
View File

@@ -0,0 +1,56 @@
/*
File: string.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _STRING_H
#define _STRING_H
#include <stdint.h>
#define WASM_STD_USE_BUILTIN_MEMSET 1
#define WASM_STD_USE_BUILTIN_MEMCPY 1
#define WASM_STD_USE_BUILTIN_MEMMOVE 1
MAYBE_START_EXTERN_C
#if WASM_STD_USE_BUILTIN_MEMSET
// Basically converts to memory.fill instruction
#define memset(pntr, value, numBytes) __builtin_memset((pntr), (value), (numBytes));
#else
void* _memset(void* pntr, int value, size_t numBytes);
#define memset(pntr, value, numBytes) _memset((pntr), (value), (numBytes))
#endif
#if WASM_STD_USE_BUILTIN_MEMCPY
// Basically converts to memory.copy instruction
#define memcpy(dest, source, numBytes) __builtin_memcpy((dest), (source), (numBytes));
#else
void* _memcpy(void* dest, const void* source, size_t numBytes);
#define memcpy(dest, source, numBytes) _memcpy((dest), (source), (numBytes))
#endif
#if WASM_STD_USE_BUILTIN_MEMMOVE
// Basically converts to memory.copy instruction
#define memmove(dest, source, numBytes) __builtin_memmove((dest), (source), (numBytes));
#else
void* _memmove(void* dest, const void* source, size_t numBytes);
#define memmove(dest, source, numBytes) _memmove((dest), (source), (numBytes))
#endif
int memcmp(const void* left, const void* right, size_t numBytes);
char* strcpy(char* dest, const char* source);
// TODO: char* strstr(const char* haystack, const char* needle);
int strcmp(const char* left, const char* right);
int strncmp(const char* left, const char* right, size_t numBytes);
size_t strlen(const char* str);
// TODO: size_t wcslen(const wchar_t* str);
//TODO: char *strchr (const char *, int); //NEEDED for slre.c
//TODO: char *strrchr (const char *, int); //NEEDED for slre.c
MAYBE_END_EXTERN_C
#endif // _STRING_H

19
std/uchar.h Normal file
View File

@@ -0,0 +1,19 @@
/*
File: uchar.h
Author: Taylor Robbins
Date: 08\28\2025
*/
#ifndef _UCHAR_H
#define _UCHAR_H
typedef unsigned short char16_t;
typedef unsigned char32_t;
// TODO: size_t c16rtomb(char *__restrict, char16_t, mbstate_t *__restrict);
// TODO: size_t mbrtoc16(char16_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict);
// TODO: size_t c32rtomb(char *__restrict, char32_t, mbstate_t *__restrict);
// TODO: size_t mbrtoc32(char32_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict);
#endif // _UCHAR_H