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:
14
std/assert.h
Normal file
14
std/assert.h
Normal 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
32
std/limits.h
Normal 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
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
18
std/src/std_js_imports.h
Normal 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
21
std/src/std_main.c
Normal 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
370
std/src/std_memset.c
Normal 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
65
std/src/std_printf.c
Normal 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
18
std/stdarg.h
Normal 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
20
std/stddef.h
Normal 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
132
std/stdint.h
Normal 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
27
std/stdio.h
Normal 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
56
std/string.h
Normal 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
19
std/uchar.h
Normal 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
|
||||
Reference in New Issue
Block a user