Compare commits
5 Commits
main
...
f23f85e305
Author | SHA1 | Date | |
---|---|---|---|
|
f23f85e305 | ||
|
751192173f | ||
|
1108ed686e | ||
36e88ba84d | |||
0617ca2316 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,5 @@
|
|||||||
.cache
|
.cache
|
||||||
.vscode
|
.vscode
|
||||||
.venv
|
|
||||||
test
|
test
|
||||||
test.*
|
test.*
|
||||||
*.dSYM
|
*.dSYM
|
||||||
@@ -9,6 +8,4 @@ test.*
|
|||||||
*.obj
|
*.obj
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
libwapp-build
|
libwapp-build
|
||||||
dist
|
libwapp.so
|
||||||
*.vs
|
|
||||||
__pycache__
|
|
||||||
|
130
Makefile
130
Makefile
@@ -1,130 +0,0 @@
|
|||||||
.PHONY: help full prng testing uuid core primitives all clean builddir build-test run-test codegen install build-lib ccodegen
|
|
||||||
|
|
||||||
# External variables
|
|
||||||
CC = clang
|
|
||||||
CXX = clang++
|
|
||||||
AR = ar
|
|
||||||
BUILD_TYPE = Debug
|
|
||||||
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
|
|
||||||
INSTALL_PREFIX = dist
|
|
||||||
|
|
||||||
# Internal variables
|
|
||||||
override CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc
|
|
||||||
override LIBFLAGS = -fPIC
|
|
||||||
override CSTD := -std=gnu11
|
|
||||||
override CXXSTD := -std=gnu++11
|
|
||||||
override KERNEL := $(shell uname -s)
|
|
||||||
override MACHINE := $(shell uname -m)
|
|
||||||
override PLATFORM := $(KERNEL)_$(MACHINE)
|
|
||||||
override TEST_INCLUDE := -Isrc $(shell find tests -type d | xargs -I{} echo -n "-I{} ")
|
|
||||||
override TEST_SRC := $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")
|
|
||||||
override TEST_C_SRC := src/wapp.c $(TEST_SRC)
|
|
||||||
override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ")
|
|
||||||
override LIB_NAME := wapp
|
|
||||||
override OBJ_OUT := $(BUILD_DIR)/$(LIB_NAME).o
|
|
||||||
override LIB_OUT := $(BUILD_DIR)/lib$(LIB_NAME).a
|
|
||||||
override TEST_C_OUT := $(BUILD_DIR)/wapptest
|
|
||||||
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
|
|
||||||
override INCLUDE_INSTALL := $(INSTALL_PREFIX)/include/$(LIB_NAME)
|
|
||||||
override LIB_INSTALL := $(INSTALL_PREFIX)/lib
|
|
||||||
override HEADER_INSTALL_CMD := scripts/header_install.sh
|
|
||||||
|
|
||||||
ifeq ($(BUILD_TYPE),Debug)
|
|
||||||
override CFLAGS += -g -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
|
|
||||||
else ifeq ($(BUILD_TYPE),RelWithDebInfo)
|
|
||||||
override CFLAGS += -g -O2 -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
|
|
||||||
else ifeq ($(BUILD_TYPE),Release)
|
|
||||||
override CFLAGS += -O3
|
|
||||||
else
|
|
||||||
$(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'Debug', 'RelWithDebInfo' or 'Release')
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CC),gcc)
|
|
||||||
# Used to disable the "ASan runtime does not come first in initial library list" error when compiling with gcc
|
|
||||||
export ASAN_OPTIONS=verify_asan_link_order=0
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: clean builddir codegen run-c-test full run-cc-test
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "Available build variables:"
|
|
||||||
@echo " CC C compiler to use (Default: clang)."
|
|
||||||
@echo " CXX C++ compiler to use (Default: clang++)."
|
|
||||||
@echo " AR Archiving utility to use for building static libraries (Default: ar)."
|
|
||||||
@echo " BUILD_TYPE Build type. Choose from \`Debug\`, \`RelWithDebInfo\` or \`Release\` (Default: Debug)."
|
|
||||||
@echo " BUILD_DIR Directory where build files will be written."
|
|
||||||
@echo " INSTALL_PREFIX Prefix where library and include files will be installed."
|
|
||||||
@echo
|
|
||||||
@echo "Available targets:"
|
|
||||||
@echo " make Build, install and test the full wapp library."
|
|
||||||
@echo " make full Build and install the full wapp library."
|
|
||||||
@echo " make core Build and install only the \`core\` component of the wapp library with all its dependencies."
|
|
||||||
@echo " make prng Build and install only the \`prng\` component of the wapp library with all its dependencies."
|
|
||||||
@echo " make uuid Build and install only the \`uuid\` component of the wapp library with all its dependencies."
|
|
||||||
@echo " make testing Build and install only the \`testing\` component of the wapp library with all its dependencies."
|
|
||||||
@echo " make primitives Build and install only the \`primitives\` component of the wapp library with all its dependencies."
|
|
||||||
@echo " make clean Clean build directory."
|
|
||||||
@echo " make help Print this help message and exit."
|
|
||||||
|
|
||||||
full: LIB_SRC = src/wapp.c
|
|
||||||
full: INCLUDES = common core primitives prng testing uuid
|
|
||||||
full: install
|
|
||||||
|
|
||||||
prng: LIB_SRC = src/prng/wapp_prng.c
|
|
||||||
prng: INCLUDES = common prng
|
|
||||||
prng: install
|
|
||||||
|
|
||||||
testing: LIB_SRC = src/testing/wapp_testing.c
|
|
||||||
testing: INCLUDES = common core testing
|
|
||||||
testing: install
|
|
||||||
|
|
||||||
uuid: LIB_SRC = src/uuid/wapp_uuid.c
|
|
||||||
uuid: INCLUDES = common primitives prng
|
|
||||||
uuid: install
|
|
||||||
|
|
||||||
core: LIB_SRC = src/core/wapp_core.c
|
|
||||||
core: INCLUDES = common core primitives
|
|
||||||
core: install
|
|
||||||
|
|
||||||
primitives: LIB_SRC = src/primitives/wapp_primitives.c
|
|
||||||
primitives: INCLUDES = common primitives
|
|
||||||
primitives: install
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -rf $(BUILD_DIR)
|
|
||||||
|
|
||||||
builddir:
|
|
||||||
@mkdir -p $(BUILD_DIR)
|
|
||||||
|
|
||||||
build-c-test:
|
|
||||||
$(CC) $(CSTD) $(CFLAGS) $(TEST_INCLUDE) $(TEST_C_SRC) -o $(TEST_C_OUT)
|
|
||||||
|
|
||||||
run-c-test: build-c-test
|
|
||||||
@echo -e "\n\033[34;1mRUNNING C TESTS\033[0m"
|
|
||||||
@$(TEST_C_OUT)
|
|
||||||
@rm $(TEST_C_OUT)
|
|
||||||
|
|
||||||
build-cc-test:
|
|
||||||
$(CXX) $(CXXSTD) $(CFLAGS) $(TEST_INCLUDE) $(TEST_CXX_SRC) $(LIB_OUT) -o $(TEST_CXX_OUT)
|
|
||||||
|
|
||||||
run-cc-test: build-cc-test
|
|
||||||
@echo -e "\n\033[34;1mRUNNING C++ TESTS\033[0m"
|
|
||||||
@export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(BUILD_DIR) && $(TEST_CXX_OUT)
|
|
||||||
@rm $(TEST_CXX_OUT)
|
|
||||||
|
|
||||||
codegen:
|
|
||||||
python3 -m codegen
|
|
||||||
|
|
||||||
install: build-lib
|
|
||||||
@mkdir -p $(LIB_INSTALL)
|
|
||||||
@cp -v $(LIB_OUT) $(LIB_INSTALL)
|
|
||||||
@mkdir -p $(INCLUDE_INSTALL)
|
|
||||||
@bash $(HEADER_INSTALL_CMD) $(LIB_SRC) $(INCLUDE_INSTALL) $(INCLUDES)
|
|
||||||
|
|
||||||
build-lib: builddir
|
|
||||||
$(CC) -c $(CSTD) $(CFLAGS) $(LIBFLAGS) $(LIB_SRC) -o $(OBJ_OUT)
|
|
||||||
$(AR) r $(LIB_OUT) $(OBJ_OUT)
|
|
||||||
@rm $(OBJ_OUT)
|
|
||||||
|
|
||||||
ccodegen:
|
|
||||||
$(CC) $(CSTD) $(CFLAGS) $(LIBFLAGS) -Isrc/core src/core/wapp_core.c ccodegen/*.c -o ccgen
|
|
@@ -1,3 +1,3 @@
|
|||||||
# Wizard Apprentice Standard Library
|
# Wizard Apprentice Standard Library
|
||||||
|
|
||||||
A collection of useful C utilities for my projects
|
A collection of useful C/C++ utilities for my projects
|
||||||
|
68
build
68
build
@@ -1,69 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Colors
|
bear -- ./compile $@
|
||||||
RED="\033[0;31m"
|
|
||||||
BOLD="\033[1m"
|
|
||||||
NC="\033[0m" # No Color
|
|
||||||
|
|
||||||
BUILD_TYPE="Debug"
|
|
||||||
ACCEPTED_BUILD_TYPES=("Debug" "RelWithDebInfo" "Release")
|
|
||||||
KERNEL="$(uname -s)"
|
|
||||||
ARGS=""
|
|
||||||
|
|
||||||
join_array_elements() {
|
|
||||||
local IFS=","
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
contains() {
|
|
||||||
local item="$1"; shift
|
|
||||||
local e
|
|
||||||
for e; do
|
|
||||||
[[ "$e" == "$item" ]] && return 0
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
print_usage() {
|
|
||||||
echo -e "Usage: build [-b build_type] ..."
|
|
||||||
echo -e " Options:"
|
|
||||||
echo -e " -b, --build-type Choose from $(join_array_elements ${ACCEPTED_BUILD_TYPES[*]}) (Default: Debug)."
|
|
||||||
echo -e " -h, --help Print this message and exit"
|
|
||||||
}
|
|
||||||
|
|
||||||
while [[ $# > 0 ]];do
|
|
||||||
case $1 in
|
|
||||||
-b|--build-type)
|
|
||||||
BUILD_TYPE="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
print_usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*|-*|--*)
|
|
||||||
rest=("$@")
|
|
||||||
ARGS+=" ${rest[0]}"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if ! contains ${BUILD_TYPE} "${ACCEPTED_BUILD_TYPES[@]}"; then
|
|
||||||
echo -e "${RED}${BOLD}Unknown build type: ${BUILD_TYPE}${NC}\n"
|
|
||||||
print_usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $KERNEL == "Darwin" ]]; then
|
|
||||||
if [[ ! -d .venv ]]; then
|
|
||||||
python3 -m venv .venv
|
|
||||||
fi
|
|
||||||
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install scan-build
|
|
||||||
intercept-build make CC=intercept-cc CXX=intercept-c++ BUILD_TYPE=$BUILD_TYPE $ARGS
|
|
||||||
deactivate
|
|
||||||
else
|
|
||||||
bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS
|
|
||||||
fi
|
|
||||||
|
17
build.ps1
17
build.ps1
@@ -4,15 +4,11 @@ Param(
|
|||||||
|
|
||||||
$Compiler = "cl.exe"
|
$Compiler = "cl.exe"
|
||||||
|
|
||||||
$GeneralFlags = "/Wall /WX /wd4996 /wd4464 /wd5105 /std:c11"
|
$GeneralFlags = "/Wall /WX /wd4996"
|
||||||
$LibraryFlags = "/LD"
|
$LibraryFlags = "/LD"
|
||||||
|
|
||||||
$Kernel = (Get-ChildItem Env:OS).Value
|
$IncludeDirs = Get-ChildItem -Path src -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
|
||||||
$Machine = (Get-ChildItem Env:PROCESSOR_ARCHITECTURE).Value
|
$SrcFiles = Get-ChildItem -Path src -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
|
||||||
$Platform = "${Kernel}_${Machine}"
|
|
||||||
|
|
||||||
$IncludeDirs = "/I src"
|
|
||||||
$SrcFiles = "src/wapp.c"
|
|
||||||
|
|
||||||
$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
|
$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
|
||||||
$TestSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
|
$TestSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
|
||||||
@@ -25,7 +21,7 @@ If ($Release -eq $True) {
|
|||||||
$BuildType = "debug"
|
$BuildType = "debug"
|
||||||
}
|
}
|
||||||
|
|
||||||
$BuildDir = "./libwapp-build/${Platform}-${BuildType}"
|
$BuildDir = "./libwapp-build/windows-$BuildType"
|
||||||
$ObjDir = "$BuildDir/objects"
|
$ObjDir = "$BuildDir/objects"
|
||||||
$OutDir = "$BuildDir/output"
|
$OutDir = "$BuildDir/output"
|
||||||
$TestsDir = "$BuildDir/tests"
|
$TestsDir = "$BuildDir/tests"
|
||||||
@@ -45,9 +41,6 @@ mkdir -p $ObjDir > $null
|
|||||||
mkdir -p $OutDir > $null
|
mkdir -p $OutDir > $null
|
||||||
mkdir -p $TestsDir > $null
|
mkdir -p $TestsDir > $null
|
||||||
|
|
||||||
# Run code generation
|
|
||||||
Invoke-Expression "python -m codegen"
|
|
||||||
|
|
||||||
# Build and run tests
|
# Build and run tests
|
||||||
Invoke-Expression "$Compiler $GeneralFlags $IncludeDirs $TestIncludeDirs $SrcFiles $TestSrcFiles $TestOutputs" -ErrorAction Stop
|
Invoke-Expression "$Compiler $GeneralFlags $IncludeDirs $TestIncludeDirs $SrcFiles $TestSrcFiles $TestOutputs" -ErrorAction Stop
|
||||||
|
|
||||||
@@ -62,4 +55,4 @@ If ($Status -ne 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Build library
|
# Build library
|
||||||
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $SrcFiles $Objects $Outputs"
|
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $IncludeDirs $SrcFiles $Objects $Outputs"
|
||||||
|
@@ -1,522 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "datatypes.h"
|
|
||||||
#include "dbl_list.h"
|
|
||||||
#include "type_enums.h"
|
|
||||||
#include "wapp_core.h"
|
|
||||||
|
|
||||||
#define ERR_MSG "Not enough capacity in dst buffer"
|
|
||||||
#define CFILE_DISCLAIMER "/**\n" \
|
|
||||||
" * THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.\n" \
|
|
||||||
" */\n\n"
|
|
||||||
|
|
||||||
void cobject_to_string(Str8 *dst, const CObject *object) {
|
|
||||||
wapp_debug_assert(dst != NULL && object != NULL, "`allocator`, `dst` and `object` should not be NULL");
|
|
||||||
|
|
||||||
switch (object->kind) {
|
|
||||||
case COBJECT_CTYPE:
|
|
||||||
ctype_to_string(dst, object->object.c_type);
|
|
||||||
break;
|
|
||||||
case COBJECT_CQUALIFIER:
|
|
||||||
cqualifier_to_string(dst, object->object.c_qualifier);
|
|
||||||
break;
|
|
||||||
case COBJECT_CPOINTERTYPE:
|
|
||||||
cpointertype_to_string(dst, object->object.c_pointertype);
|
|
||||||
break;
|
|
||||||
case COBJECT_CPOINTER:
|
|
||||||
cpointer_to_string(dst, &(object->object.c_pointer));
|
|
||||||
break;
|
|
||||||
case COBJECT_CENUMVAL:
|
|
||||||
cenumval_to_string(dst, &(object->object.c_enumval));
|
|
||||||
break;
|
|
||||||
case COBJECT_CENUM:
|
|
||||||
cenum_to_string(dst, &(object->object.c_enum));
|
|
||||||
break;
|
|
||||||
case COBJECT_CMACRO:
|
|
||||||
cmacro_to_string(dst, &(object->object.c_macro));
|
|
||||||
break;
|
|
||||||
case COBJECT_CSTRUCT:
|
|
||||||
cstruct_to_string(dst, &(object->object.c_struct));
|
|
||||||
break;
|
|
||||||
case COBJECT_CUSERTYPE:
|
|
||||||
cusertype_to_string(dst, &(object->object.c_usertype));
|
|
||||||
break;
|
|
||||||
case COBJECT_CDATATYPE:
|
|
||||||
cdatatype_to_string(dst, &(object->object.c_datatype));
|
|
||||||
break;
|
|
||||||
case COBJECT_CARG:
|
|
||||||
carg_to_string(dst, &(object->object.c_arg));
|
|
||||||
break;
|
|
||||||
case COBJECT_CFUNC:
|
|
||||||
cfunc_to_string(dst, &(object->object.c_func));
|
|
||||||
break;
|
|
||||||
case COBJECT_CINCULDE:
|
|
||||||
cinclude_to_string(dst, &(object->object.c_include));
|
|
||||||
break;
|
|
||||||
case COBJECT_CHEADER:
|
|
||||||
cheader_to_string(dst, &(object->object.c_header));
|
|
||||||
break;
|
|
||||||
case COBJECT_CSOURCE:
|
|
||||||
csource_to_string(dst, &(object->object.c_source));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ctype_to_string(Str8 *dst, CType ctype) {
|
|
||||||
wapp_runtime_assert(ctypes[ctype].size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, &ctypes[ctype]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier) {
|
|
||||||
wapp_runtime_assert(cqualifiers[cqualifier].size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, &cqualifiers[cqualifier]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype) {
|
|
||||||
wapp_runtime_assert(cpointertypes[cpointertype].size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, &cpointertypes[cpointertype]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpointer_to_string(Str8 *dst, const CPointer *cpointer) {
|
|
||||||
wapp_debug_assert(dst != NULL && cpointer != NULL, "`dst` and `cpointer` should not be NULL");
|
|
||||||
|
|
||||||
u64 total_size = cpointertypes[cpointer->type].size + cqualifiers[cpointer->qualifier].size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(cpointertypes[cpointer->type]),
|
|
||||||
wapp_str8_varg(cqualifiers[cpointer->qualifier]));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) {
|
|
||||||
wapp_debug_assert(dst != NULL && cenumval != NULL, "`dst` and `cenumval` should not be NULL");
|
|
||||||
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_TINY);
|
|
||||||
u64 tmp_size = 0;
|
|
||||||
if (cenumval->value != NULL) {
|
|
||||||
wapp_str8_format(&tmp, " = %d", *(cenumval->value));
|
|
||||||
tmp_size = tmp.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 total_size = cenumval->name.size + tmp_size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(cenumval->name),
|
|
||||||
wapp_str8_varg(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cenum_to_string(Str8 *dst, const CEnum *cenum) {
|
|
||||||
wapp_debug_assert(dst != NULL && cenum != NULL, "`dst` and `cenum` should not be NULL");
|
|
||||||
|
|
||||||
Str8 header = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 values = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
Str8 footer = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
|
|
||||||
if (cenum->add_typedef) {
|
|
||||||
wapp_str8_copy_cstr_capped(&header, "typedef enum {\n");
|
|
||||||
wapp_str8_format(&footer, "} " WAPP_STR8_SPEC ";\n", wapp_str8_varg(cenum->name));
|
|
||||||
} else {
|
|
||||||
wapp_str8_format(&header, "enum " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cenum->name));
|
|
||||||
wapp_str8_copy_cstr_capped(&footer, "};\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cenum->values.node_count; ++i) {
|
|
||||||
cenumval_to_string(&tmp, wapp_cenumval_list_get(&(cenum->values), i)->item);
|
|
||||||
// Add 4 for extra characters
|
|
||||||
wapp_runtime_assert(tmp.size + 4 <= values.capacity - values.size, ERR_MSG);
|
|
||||||
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(" "));
|
|
||||||
wapp_str8_concat_capped(&values, &tmp);
|
|
||||||
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(",\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 total_size = header.size + values.size + footer.size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(header),
|
|
||||||
wapp_str8_varg(values),
|
|
||||||
wapp_str8_varg(footer));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmacro_to_string(Str8 *dst, const CMacro *cmacro) {
|
|
||||||
wapp_debug_assert(dst != NULL && cmacro != NULL, "`dst` and `cmacro` should not be NULL");
|
|
||||||
|
|
||||||
Str8 def = wapp_str8_lit("#define ");
|
|
||||||
u64 total_size = def.size + cmacro->name.size + cmacro->value.size + 1; // Add 1 for newline
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC "\n",
|
|
||||||
wapp_str8_varg(def),
|
|
||||||
wapp_str8_varg(cmacro->name),
|
|
||||||
wapp_str8_varg(cmacro->value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cstruct_to_string(Str8 *dst, const CStruct *cstruct) {
|
|
||||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
|
||||||
|
|
||||||
Str8 declaration = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 definition = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
|
|
||||||
declare_cstruct(&declaration, cstruct);
|
|
||||||
define_cstruct(&definition, cstruct);
|
|
||||||
|
|
||||||
u64 total_size = declaration.size + definition.size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(declaration), wapp_str8_varg(definition));
|
|
||||||
}
|
|
||||||
|
|
||||||
void declare_cstruct(Str8 *dst, const CStruct *cstruct) {
|
|
||||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
|
||||||
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
wapp_str8_format(&tmp,
|
|
||||||
"typedef struct " WAPP_STR8_SPEC " " WAPP_STR8_SPEC ";\n",
|
|
||||||
wapp_str8_varg(cstruct->name),
|
|
||||||
wapp_str8_varg(cstruct->typedef_name.size > 0 ? cstruct->typedef_name : cstruct->name));
|
|
||||||
|
|
||||||
wapp_runtime_assert(tmp.size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void define_cstruct(Str8 *dst, const CStruct *cstruct) {
|
|
||||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
|
||||||
|
|
||||||
Str8 definition = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 args = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
Str8 footer = wapp_str8_lit_ro("};\n");
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
|
||||||
|
|
||||||
wapp_str8_format(&definition, "struct " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cstruct->name));
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cstruct->args.node_count; ++i) {
|
|
||||||
carg_to_string(&tmp, wapp_carg_list_get(&(cstruct->args), i)->item);
|
|
||||||
// Add 4 for extra characters
|
|
||||||
wapp_runtime_assert(tmp.size + 4 <= args.capacity - args.size, ERR_MSG);
|
|
||||||
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(" "));
|
|
||||||
wapp_str8_concat_capped(&args, &tmp);
|
|
||||||
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(";\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 total_size = definition.size + args.size + footer.size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(definition),
|
|
||||||
wapp_str8_varg(args),
|
|
||||||
wapp_str8_varg(footer));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cusertype_to_string(Str8 *dst, const CUserType *cusertype) {
|
|
||||||
wapp_debug_assert(dst != NULL && cusertype != NULL, "`dst` and `cusertype` should not be NULL");
|
|
||||||
|
|
||||||
switch (cusertype->kind) {
|
|
||||||
case CUSERTYPE_CENUM:
|
|
||||||
cenum_to_string(dst, &(cusertype->type.c_enum));
|
|
||||||
break;
|
|
||||||
case CUSERTYPE_CSTRUCT:
|
|
||||||
cstruct_to_string(dst, &(cusertype->type.c_struct));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype) {
|
|
||||||
wapp_debug_assert(dst != NULL && cdatatype != NULL, "`dst` and `cdatatype` should not be NULL");
|
|
||||||
|
|
||||||
switch (cdatatype->kind) {
|
|
||||||
case CDATATYPE_CTYPE:
|
|
||||||
ctype_to_string(dst, cdatatype->type.c_type);
|
|
||||||
break;
|
|
||||||
case CDATATYPE_CUSERTYPE:
|
|
||||||
cusertype_to_string(dst, &(cdatatype->type.c_usertype));
|
|
||||||
break;
|
|
||||||
case CDATATYPE_STR:
|
|
||||||
wapp_runtime_assert(cdatatype->type.str.size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, &(cdatatype->type.str));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void carg_to_string(Str8 *dst, const CArg *carg) {
|
|
||||||
wapp_debug_assert(dst != NULL && carg != NULL, "`dst` and `carg` should not be NULL");
|
|
||||||
|
|
||||||
Str8 qualifier = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
|
||||||
Str8 type = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 pointer = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
|
||||||
Str8 array = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
|
||||||
|
|
||||||
cqualifier_to_string(&qualifier, carg->qualifier);
|
|
||||||
cdatatype_to_string(&type, &(carg->type));
|
|
||||||
wapp_str8_concat_capped(&type, &wapp_str8_lit_ro(" "));
|
|
||||||
cpointer_to_string(&pointer, &(carg->pointer));
|
|
||||||
if (carg->is_array) { wapp_str8_copy_cstr_capped(&array, "[]"); }
|
|
||||||
|
|
||||||
u64 total_size = qualifier.size + type.size + pointer.size + array.size + carg->name.size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
|
||||||
wapp_str8_varg(qualifier), wapp_str8_varg(type), wapp_str8_varg(pointer),
|
|
||||||
wapp_str8_varg(carg->name), wapp_str8_varg(array));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cfunc_to_string(Str8 *dst, const CFunc *cfunc) {
|
|
||||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
|
||||||
|
|
||||||
Str8 qualifiers = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 args = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
Str8 ret_type = wapp_str8_buf(CCGEN_BUF_SMALL);
|
|
||||||
Str8 pointer = wapp_str8_buf(CCGEN_BUF_SMALL);
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
|
||||||
CQualifier *qf = NULL;
|
|
||||||
CArg *arg = NULL;
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cfunc->qualifiers.node_count; ++i) {
|
|
||||||
qf = wapp_cqualifier_list_get(&(cfunc->qualifiers), i)->item;
|
|
||||||
if (*qf == CQUALIFIER_NONE) { continue; }
|
|
||||||
|
|
||||||
cqualifier_to_string(&tmp, *qf);
|
|
||||||
|
|
||||||
wapp_runtime_assert(tmp.size + 1 <= qualifiers.capacity - qualifiers.size, ERR_MSG);
|
|
||||||
if (qualifiers.size > 0) { wapp_str8_concat_capped(&qualifiers, &wapp_str8_lit_ro(" ")); }
|
|
||||||
|
|
||||||
wapp_str8_concat_capped(&qualifiers, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cfunc->args.node_count; ++i) {
|
|
||||||
arg = wapp_carg_list_get(&(cfunc->args), i)->item;
|
|
||||||
carg_to_string(&tmp, arg);
|
|
||||||
|
|
||||||
wapp_runtime_assert(tmp.size + 2 <= args.capacity - args.size, ERR_MSG);
|
|
||||||
wapp_str8_concat_capped(&args, &tmp);
|
|
||||||
if (i + 1 < cfunc->args.node_count) { wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(", ")); }
|
|
||||||
}
|
|
||||||
|
|
||||||
cdatatype_to_string(&ret_type, &(cfunc->ret_type));
|
|
||||||
cpointer_to_string(&pointer, &(cfunc->pointer));
|
|
||||||
|
|
||||||
u64 total_size = cfunc->name.size + qualifiers.size + args.size + ret_type.size + pointer.size + 4;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC WAPP_STR8_SPEC "(" WAPP_STR8_SPEC ")",
|
|
||||||
wapp_str8_varg(qualifiers),
|
|
||||||
wapp_str8_varg(ret_type),
|
|
||||||
wapp_str8_varg(pointer),
|
|
||||||
wapp_str8_varg(cfunc->name),
|
|
||||||
wapp_str8_varg(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
void declare_cfunc(Str8 *dst, const CFunc *cfunc) {
|
|
||||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
|
||||||
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
cfunc_to_string(&tmp, cfunc);
|
|
||||||
|
|
||||||
wapp_runtime_assert(tmp.size + 2 <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst, WAPP_STR8_SPEC ";\n", wapp_str8_varg(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void define_cfunc(Str8 *dst, const CFunc *cfunc) {
|
|
||||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
|
||||||
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
cfunc_to_string(&tmp, cfunc);
|
|
||||||
|
|
||||||
wapp_runtime_assert(tmp.size + cfunc->body.size + 8 <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst, WAPP_STR8_SPEC " {\n" WAPP_STR8_SPEC "\n}\n\n",
|
|
||||||
wapp_str8_varg(tmp), wapp_str8_varg(cfunc->body));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cinclude_to_string(Str8 *dst, const CInclude *cinclude) {
|
|
||||||
wapp_debug_assert(dst != NULL && cinclude != NULL, "`dst` and `cinclude` should not be NULL");
|
|
||||||
|
|
||||||
Str8 header_str = wapp_str8_buf(CCGEN_BUF_LARGE);
|
|
||||||
if (!cheaderinclude_to_string(&header_str, &(cinclude->header))) { return; }
|
|
||||||
|
|
||||||
Str8 inc = wapp_str8_lit("#include ");
|
|
||||||
Str8 open_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
|
|
||||||
Str8 close_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
|
|
||||||
|
|
||||||
if (cinclude->is_local) {
|
|
||||||
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("\""));
|
|
||||||
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro("\""));
|
|
||||||
if (cinclude->same_dir) { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("./")); }
|
|
||||||
} else {
|
|
||||||
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("<"));
|
|
||||||
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro(">"));
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 total_size = header_str.size + inc.size + open_symbol.size + close_symbol.size;
|
|
||||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst,
|
|
||||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC "\n",
|
|
||||||
wapp_str8_varg(inc),
|
|
||||||
wapp_str8_varg(open_symbol),
|
|
||||||
wapp_str8_varg(header_str),
|
|
||||||
wapp_str8_varg(close_symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cheader_to_string(Str8 *dst, const CHeader *cheader) {
|
|
||||||
wapp_debug_assert(dst != NULL && cheader != NULL, "`dst` and `cheader` should not be NULL");
|
|
||||||
|
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
|
|
||||||
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
|
|
||||||
wapp_runtime_assert(output != NULL, "Failed to allocate buffer");
|
|
||||||
|
|
||||||
Str8 header_guard_name = wapp_str8_buf(CCGEN_BUF_SMALL);
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
|
|
||||||
// ADD HEADER GUARD AND START C LINKAGE
|
|
||||||
wapp_str8_to_upper(&header_guard_name, &(cheader->name));
|
|
||||||
wapp_str8_concat_capped(&header_guard_name, &wapp_str8_lit_ro("_H"));
|
|
||||||
wapp_str8_format(&tmp, "#ifndef " WAPP_STR8_SPEC "\n#define " WAPP_STR8_SPEC "\n\n"
|
|
||||||
"#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n",
|
|
||||||
wapp_str8_varg(header_guard_name), wapp_str8_varg(header_guard_name));
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->includes.node_count; ++i) {
|
|
||||||
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(cheader->includes), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (cheader->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->macros.node_count; ++i) {
|
|
||||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->macros), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (cheader->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
if (cheader->cpp_macros.node_count > 0) {
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#ifdef WAPP_PLATFORM_CPP\n"));
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->cpp_macros.node_count; ++i) {
|
|
||||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->cpp_macros), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#else\n"));
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->c_macros.node_count; ++i) {
|
|
||||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->c_macros), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#endif // !WAPP_PLATFORM_CPP\n\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->decl_types.node_count; ++i) {
|
|
||||||
declare_cstruct(&tmp, wapp_cstruct_list_get(&(cheader->decl_types), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (cheader->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->types.node_count; ++i) {
|
|
||||||
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(cheader->types), i)->item);
|
|
||||||
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < cheader->funcs.node_count; ++i) {
|
|
||||||
declare_cfunc(&tmp, wapp_cfunc_list_get(&(cheader->funcs), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// END C LINKAGE AND CLOSE HEADER GUARD
|
|
||||||
wapp_str8_format(&tmp, "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
|
||||||
"#endif // !" WAPP_STR8_SPEC "\n", wapp_str8_varg(header_guard_name));
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
|
|
||||||
wapp_runtime_assert(output->size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, output);
|
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
void csource_to_string(Str8 *dst, const CSource *csource) {
|
|
||||||
wapp_debug_assert(dst != NULL && csource != NULL, "`dst` and `csource` should not be NULL");
|
|
||||||
|
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
|
|
||||||
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
|
|
||||||
Str8 *internal_funcs_def = wapp_str8_alloc_buf(&arena, KB(16));
|
|
||||||
wapp_runtime_assert(output != NULL && internal_funcs_def != NULL, "Failed to allocate buffer");
|
|
||||||
|
|
||||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
|
||||||
|
|
||||||
for (u64 i = 0; i < csource->includes.node_count; ++i) {
|
|
||||||
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(csource->includes), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (csource->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < csource->macros.node_count; ++i) {
|
|
||||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(csource->macros), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (csource->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < csource->decl_types.node_count; ++i) {
|
|
||||||
declare_cstruct(&tmp, wapp_cstruct_list_get(&(csource->decl_types), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
if (csource->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < csource->types.node_count; ++i) {
|
|
||||||
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(csource->types), i)->item);
|
|
||||||
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Str8RO _wapp_intern = wapp_str8_lit_ro("wapp_intern ");
|
|
||||||
for (u64 i = 0; i < csource->internal_funcs.node_count; ++i) {
|
|
||||||
declare_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &_internal);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
|
|
||||||
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, internal_funcs_def, &_internal);
|
|
||||||
wapp_str8_alloc_concat(&arena, internal_funcs_def, &tmp);
|
|
||||||
}
|
|
||||||
if (csource->internal_funcs.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
|
||||||
|
|
||||||
for (u64 i = 0; i < csource->funcs.node_count; ++i) {
|
|
||||||
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->funcs), i)->item);
|
|
||||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_runtime_assert(output->size + internal_funcs_def->size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_copy_str8_capped(dst, output);
|
|
||||||
wapp_str8_concat_capped(dst, internal_funcs_def);
|
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude) {
|
|
||||||
wapp_debug_assert(dst != NULL && cheaderinclude != NULL, "`dst` and `cheaderinclude` should not be NULL");
|
|
||||||
|
|
||||||
switch (cheaderinclude->kind) {
|
|
||||||
case C_HEADER_INCLUDE_STR:
|
|
||||||
wapp_runtime_assert(cheaderinclude->header.name.size <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(dst, WAPP_STR8_SPEC, wapp_str8_varg(cheaderinclude->header.name));
|
|
||||||
return true;
|
|
||||||
case C_HEADER_INCLUDE_HEADER:
|
|
||||||
// Take extension into account
|
|
||||||
wapp_runtime_assert(cheaderinclude->header.header.name.size + 2 <= dst->capacity, ERR_MSG);
|
|
||||||
wapp_str8_format(
|
|
||||||
dst,
|
|
||||||
WAPP_STR8_SPEC ".%s",
|
|
||||||
wapp_str8_varg(cheaderinclude->header.header.name),
|
|
||||||
cheaderinclude->header.header.extension == CFILE_EXT_H ? "h" : "c"
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
@@ -1,280 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef DATATYPES_H
|
|
||||||
#define DATATYPES_H
|
|
||||||
|
|
||||||
#include "wapp_core.h"
|
|
||||||
#include "dbl_list.h"
|
|
||||||
#include "type_enums.h"
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_MIN
|
|
||||||
#define CCGEN_BUF_MIN 16
|
|
||||||
#endif // !CCGEN_BUF_MIN
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_TINY
|
|
||||||
#define CCGEN_BUF_TINY 32
|
|
||||||
#endif // !CCGEN_BUF_TINY
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_SMALL
|
|
||||||
#define CCGEN_BUF_SMALL 512
|
|
||||||
#endif // !CCGEN_BUF_SMALL
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_MEDIUM
|
|
||||||
#define CCGEN_BUF_MEDIUM 1024
|
|
||||||
#endif // !CCGEN_BUF_MEDIUM
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_LARGE
|
|
||||||
#define CCGEN_BUF_LARGE 4096
|
|
||||||
#endif // !CCGEN_BUF_LARGE
|
|
||||||
|
|
||||||
#ifndef CCGEN_BUF_MAX
|
|
||||||
#define CCGEN_BUF_MAX 8192
|
|
||||||
#endif // !CCGEN_BUF_MAX
|
|
||||||
|
|
||||||
#define CENUM(NAME, VALUES, TYPEDEF) ((CEnum){ .name = (NAME), .values = (VALUES), .add_typedef = (TYPEDEF) })
|
|
||||||
#define CSTRUCT(NAME, ARGS, TYPEDEF_NAME_PTR) ((CStruct){ .name = (NAME), .args = (ARGS), .typedef_name = (TYPEDEF_NAME_PTR) })
|
|
||||||
|
|
||||||
#define CUSERTYPE_ENUM(ENUM) ((CUserType){ .kind = CUSERTYPE_CENUM, .type.c_enum = ENUM })
|
|
||||||
#define CUSERTYPE_STRUCT(STRUCT) ((CUserType){ .kind = CUSERTYPE_CSTRUCT, .type.c_struct = STRUCT })
|
|
||||||
|
|
||||||
#define CDATATYPE_CTYPE(VALUE) ((CDataType){ .kind = CDATATYPE_CTYPE, .type.c_type = (VALUE) })
|
|
||||||
#define CDATATYPE_USERTYPE(USERTYPE) ((CDataType){ .kind = CDATATYPE_CUSERTYPE, .type.c_usertype = (USERTYPE) })
|
|
||||||
#define CDATATYPE_STR(STR) ((CDataType){ .kind = CDATATYPE_STR, .type.str = (STR) })
|
|
||||||
|
|
||||||
#define CHEADERINCLUDE_STR(NAME) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_STR, .header.name = (NAME) })
|
|
||||||
#define CHEADERINCLUDE_CHEADER(CHEADER) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_HEADER, .header.header = (CHEADER) })
|
|
||||||
|
|
||||||
#define COBJECT_TYPE(VALUE) \
|
|
||||||
((CObject){ .kind = COBJECT_CTYPE, .object.c_type = (VALUE) })
|
|
||||||
#define COBJECT_QUALIFIER(VALUE) \
|
|
||||||
((CObject){ .kind = COBJECT_CQUALIFIER, .object.c_qualifier = (VALUE) })
|
|
||||||
#define COBJECT_POINTERTYPE(VALUE) \
|
|
||||||
((CObject){ .kind = COBJECT_CPOINTERTYPE, .object.c_pointertype = (VALUE) })
|
|
||||||
#define COBJECT_POINTER(CPOINTER) \
|
|
||||||
((CObject){ .kind = COBJECT_CPOINTER, .object.c_pointer = (CPOINTER) })
|
|
||||||
#define COBJECT_ENUMVAL(CENUMVAL) \
|
|
||||||
((CObject){ .kind = COBJECT_CENUMVAL, .object.c_enumval = (CENUMVAL) })
|
|
||||||
#define COBJECT_ENUM(ENUM) \
|
|
||||||
((CObject){ .kind = COBJECT_CENUM, .object.c_enum = (ENUM) })
|
|
||||||
#define COBJECT_MACRO(CMACRO) \
|
|
||||||
((CObject){ .kind = COBJECT_CMACRO, .object.c_macro = (CMACRO) })
|
|
||||||
#define COBJECT_STRUCT(STRUCT) \
|
|
||||||
((CObject){ .kind = COBJECT_CSTRUCT, .object.c_struct = STRUCT })
|
|
||||||
#define COBJECT_USERTYPE(USERTYPE) \
|
|
||||||
((CObject){ .kind = COBJECT_CUSERTYPE, .object.c_usertype = (USERTYPE) })
|
|
||||||
#define COBJECT_DATATYPE(DATATYPE) \
|
|
||||||
((CObject){ .kind = COBJECT_CDATATYPE, .object.c_datatype = (DATATYPE) })
|
|
||||||
#define COBJECT_ARG(CARG) \
|
|
||||||
((CObject){ .kind = COBJECT_CARG, .object.c_arg = (CARG) })
|
|
||||||
#define COBJECT_FUNC(CFUNC) \
|
|
||||||
((CObject){ .kind = COBJECT_CFUNC, .object.c_func = (CFUNC) })
|
|
||||||
#define COBJECT_INCULDE(CINCLUDE) \
|
|
||||||
((CObject){ .kind = COBJECT_CINCULDE, .object.c_include = (CINCLUDE) })
|
|
||||||
#define COBJECT_HEADER(CHEADER) \
|
|
||||||
((CObject){ .kind = COBJECT_CHEADER, .object.c_header = (CHEADER) })
|
|
||||||
#define COBJECT_SOURCE(CSOURCE) \
|
|
||||||
((CObject){ .kind = COBJECT_CSOURCE, .object.c_source = (CSOURCE) })
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CUSERTYPE_CENUM,
|
|
||||||
CUSERTYPE_CSTRUCT,
|
|
||||||
|
|
||||||
COUNT_CUSERTYPEKIND,
|
|
||||||
} CUserTypeKind;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CDATATYPE_CTYPE,
|
|
||||||
CDATATYPE_CUSERTYPE,
|
|
||||||
CDATATYPE_STR,
|
|
||||||
|
|
||||||
COUNT_CDATATYPEKIND,
|
|
||||||
} CDataTypeKind;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CFILE_EXT_H,
|
|
||||||
CFILE_EXT_C,
|
|
||||||
|
|
||||||
COUNT_CFILE_EXT,
|
|
||||||
} CFileExtension;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
C_HEADER_INCLUDE_STR,
|
|
||||||
C_HEADER_INCLUDE_HEADER,
|
|
||||||
|
|
||||||
COUNT_CHEADERINCLUDEKIND,
|
|
||||||
} CHeaderIncludeKind;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
COBJECT_CTYPE,
|
|
||||||
COBJECT_CQUALIFIER,
|
|
||||||
COBJECT_CPOINTERTYPE,
|
|
||||||
COBJECT_CPOINTER,
|
|
||||||
COBJECT_CENUMVAL,
|
|
||||||
COBJECT_CENUM,
|
|
||||||
COBJECT_CMACRO,
|
|
||||||
COBJECT_CSTRUCT,
|
|
||||||
COBJECT_CUSERTYPE,
|
|
||||||
COBJECT_CDATATYPE,
|
|
||||||
COBJECT_CARG,
|
|
||||||
COBJECT_CFUNC,
|
|
||||||
COBJECT_CINCULDE,
|
|
||||||
COBJECT_CHEADER,
|
|
||||||
COBJECT_CSOURCE,
|
|
||||||
|
|
||||||
COUNT_COBJECTKIND,
|
|
||||||
} CObjectKind;
|
|
||||||
|
|
||||||
typedef struct cpointer CPointer;
|
|
||||||
typedef struct cenumval CEnumVal;
|
|
||||||
typedef struct cenum CEnum;
|
|
||||||
typedef struct cmacro CMacro;
|
|
||||||
typedef struct cstruct CStruct;
|
|
||||||
typedef struct cusertype CUserType;
|
|
||||||
typedef struct cdatatype CDataType;
|
|
||||||
typedef struct carg CArg;
|
|
||||||
typedef struct cfunc CFunc;
|
|
||||||
typedef struct cheader_include CHeaderInclude;
|
|
||||||
typedef struct cinclude CInclude;
|
|
||||||
typedef struct cheader CHeader;
|
|
||||||
typedef struct csource CSource;
|
|
||||||
typedef struct cobject CObject;
|
|
||||||
|
|
||||||
struct cpointer {
|
|
||||||
CPointerType type;
|
|
||||||
CQualifier qualifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cenumval {
|
|
||||||
Str8 name;
|
|
||||||
i32 *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cenum {
|
|
||||||
Str8 name;
|
|
||||||
CEnumValList values;
|
|
||||||
b32 add_typedef;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cmacro {
|
|
||||||
Str8 name;
|
|
||||||
Str8 value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cstruct {
|
|
||||||
Str8 name;
|
|
||||||
CArgList args;
|
|
||||||
Str8 typedef_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cusertype {
|
|
||||||
CUserTypeKind kind;
|
|
||||||
union {
|
|
||||||
CEnum c_enum;
|
|
||||||
CStruct c_struct;
|
|
||||||
} type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cdatatype {
|
|
||||||
CDataTypeKind kind;
|
|
||||||
union {
|
|
||||||
CType c_type;
|
|
||||||
CUserType c_usertype;
|
|
||||||
Str8 str;
|
|
||||||
} type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct carg {
|
|
||||||
Str8 name;
|
|
||||||
CDataType type;
|
|
||||||
CPointer pointer;
|
|
||||||
CQualifier qualifier;
|
|
||||||
b32 is_array;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cfunc {
|
|
||||||
Str8 name;
|
|
||||||
CDataType ret_type;
|
|
||||||
CArgList args;
|
|
||||||
Str8 body;
|
|
||||||
CPointer pointer;
|
|
||||||
CQualifierList qualifiers;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CFILE_ARGS \
|
|
||||||
Str8 name; \
|
|
||||||
CFileExtension extension; \
|
|
||||||
CIncludeList includes; \
|
|
||||||
CUserTypeList types; \
|
|
||||||
CFuncList funcs; \
|
|
||||||
CStructList decl_types; \
|
|
||||||
CMacroList macros; \
|
|
||||||
CMacroList c_macros; \
|
|
||||||
CMacroList cpp_macros \
|
|
||||||
|
|
||||||
struct cheader {
|
|
||||||
CFILE_ARGS;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct csource {
|
|
||||||
CFILE_ARGS;
|
|
||||||
CFuncList internal_funcs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cheader_include {
|
|
||||||
CHeaderIncludeKind kind;
|
|
||||||
union {
|
|
||||||
Str8 name;
|
|
||||||
CHeader header;
|
|
||||||
} header;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cinclude {
|
|
||||||
CHeaderInclude header;
|
|
||||||
b32 is_local;
|
|
||||||
b32 same_dir;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cobject {
|
|
||||||
CObjectKind kind;
|
|
||||||
union {
|
|
||||||
CType c_type;
|
|
||||||
CQualifier c_qualifier;
|
|
||||||
CPointerType c_pointertype;
|
|
||||||
CPointer c_pointer;
|
|
||||||
CEnumVal c_enumval;
|
|
||||||
CEnum c_enum;
|
|
||||||
CMacro c_macro;
|
|
||||||
CStruct c_struct;
|
|
||||||
CUserType c_usertype;
|
|
||||||
CDataType c_datatype;
|
|
||||||
CArg c_arg;
|
|
||||||
CFunc c_func;
|
|
||||||
CInclude c_include;
|
|
||||||
CHeader c_header;
|
|
||||||
CSource c_source;
|
|
||||||
} object;
|
|
||||||
};
|
|
||||||
|
|
||||||
void cobject_to_string(Str8 *dst, const CObject *object);
|
|
||||||
void ctype_to_string(Str8 *dst, CType ctype);
|
|
||||||
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier);
|
|
||||||
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype);
|
|
||||||
void cpointer_to_string(Str8 *dst, const CPointer *cpointer);
|
|
||||||
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval);
|
|
||||||
void cenum_to_string(Str8 *dst, const CEnum *cenum);
|
|
||||||
void cmacro_to_string(Str8 *dst, const CMacro *cmacro);
|
|
||||||
void cstruct_to_string(Str8 *dst, const CStruct *cstruct);
|
|
||||||
void declare_cstruct(Str8 *dst, const CStruct *cstruct);
|
|
||||||
void define_cstruct(Str8 *dst, const CStruct *cstruct);
|
|
||||||
void cusertype_to_string(Str8 *dst, const CUserType *cusertype);
|
|
||||||
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype);
|
|
||||||
void carg_to_string(Str8 *dst, const CArg *carg);
|
|
||||||
void cfunc_to_string(Str8 *dst, const CFunc *cfunc);
|
|
||||||
void declare_cfunc(Str8 *dst, const CFunc *cfunc);
|
|
||||||
void define_cfunc(Str8 *dst, const CFunc *cfunc);
|
|
||||||
void cinclude_to_string(Str8 *dst, const CInclude *cinclude);
|
|
||||||
void cheader_to_string(Str8 *dst, const CHeader *cheader);
|
|
||||||
void csource_to_string(Str8 *dst, const CSource *csource);
|
|
||||||
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude);
|
|
||||||
|
|
||||||
#endif // !DATATYPES_H
|
|
1526
ccodegen/dbl_list.c
1526
ccodegen/dbl_list.c
File diff suppressed because it is too large
Load Diff
@@ -1,222 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef CCGEN_DBL_LIST_H
|
|
||||||
#define CCGEN_DBL_LIST_H
|
|
||||||
|
|
||||||
#include "wapp_core.h"
|
|
||||||
#include "type_enums.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
#define wapp_cenumval_list_node(ITEM_PTR) CEnumValNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_carg_list_node(ITEM_PTR) CArgNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cqualifier_list_node(ITEM_PTR) CQualifierNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cinclude_list_node(ITEM_PTR) CIncludeNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cusertype_list_node(ITEM_PTR) CUserTypeNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cfunc_list_node(ITEM_PTR) CFuncNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cstruct_list_node(ITEM_PTR) CStructNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_cmacro_list_node(ITEM_PTR) CMacroNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#else
|
|
||||||
#define wapp_cenumval_list_node(ITEM_PTR) ((CEnumValNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_carg_list_node(ITEM_PTR) ((CArgNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cqualifier_list_node(ITEM_PTR) ((CQualifierNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cinclude_list_node(ITEM_PTR) ((CIncludeNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cusertype_list_node(ITEM_PTR) ((CUserTypeNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cfunc_list_node(ITEM_PTR) ((CFuncNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cstruct_list_node(ITEM_PTR) ((CStructNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_cmacro_list_node(ITEM_PTR) ((CMacroNode){.item = ITEM_PTR})
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
typedef struct cenumval CEnumVal;
|
|
||||||
typedef struct carg CArg;
|
|
||||||
typedef struct cinclude CInclude;
|
|
||||||
typedef struct cusertype CUserType;
|
|
||||||
typedef struct cfunc CFunc;
|
|
||||||
typedef struct cstruct CStruct;
|
|
||||||
typedef struct cmacro CMacro;
|
|
||||||
|
|
||||||
typedef struct CEnumValNode CEnumValNode;
|
|
||||||
struct CEnumValNode {
|
|
||||||
CEnumVal *item;
|
|
||||||
CEnumValNode *prev;
|
|
||||||
CEnumValNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CEnumValList CEnumValList;
|
|
||||||
struct CEnumValList {
|
|
||||||
CEnumValNode *first;
|
|
||||||
CEnumValNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CArgNode CArgNode;
|
|
||||||
struct CArgNode {
|
|
||||||
CArg *item;
|
|
||||||
CArgNode *prev;
|
|
||||||
CArgNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CArgList CArgList;
|
|
||||||
struct CArgList {
|
|
||||||
CArgNode *first;
|
|
||||||
CArgNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CQualifierNode CQualifierNode;
|
|
||||||
struct CQualifierNode {
|
|
||||||
CQualifier *item;
|
|
||||||
CQualifierNode *prev;
|
|
||||||
CQualifierNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CQualifierList CQualifierList;
|
|
||||||
struct CQualifierList {
|
|
||||||
CQualifierNode *first;
|
|
||||||
CQualifierNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CIncludeNode CIncludeNode;
|
|
||||||
struct CIncludeNode {
|
|
||||||
CInclude *item;
|
|
||||||
CIncludeNode *prev;
|
|
||||||
CIncludeNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CIncludeList CIncludeList;
|
|
||||||
struct CIncludeList {
|
|
||||||
CIncludeNode *first;
|
|
||||||
CIncludeNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CUserTypeNode CUserTypeNode;
|
|
||||||
struct CUserTypeNode {
|
|
||||||
CUserType *item;
|
|
||||||
CUserTypeNode *prev;
|
|
||||||
CUserTypeNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CUserTypeList CUserTypeList;
|
|
||||||
struct CUserTypeList {
|
|
||||||
CUserTypeNode *first;
|
|
||||||
CUserTypeNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CFuncNode CFuncNode;
|
|
||||||
struct CFuncNode {
|
|
||||||
CFunc *item;
|
|
||||||
CFuncNode *prev;
|
|
||||||
CFuncNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CFuncList CFuncList;
|
|
||||||
struct CFuncList {
|
|
||||||
CFuncNode *first;
|
|
||||||
CFuncNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CStructNode CStructNode;
|
|
||||||
struct CStructNode {
|
|
||||||
CStruct *item;
|
|
||||||
CStructNode *prev;
|
|
||||||
CStructNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CStructList CStructList;
|
|
||||||
struct CStructList {
|
|
||||||
CStructNode *first;
|
|
||||||
CStructNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CMacroNode CMacroNode;
|
|
||||||
struct CMacroNode {
|
|
||||||
CMacro *item;
|
|
||||||
CMacroNode *prev;
|
|
||||||
CMacroNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CMacroList CMacroList;
|
|
||||||
struct CMacroList {
|
|
||||||
CMacroNode *first;
|
|
||||||
CMacroNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
CEnumValNode *wapp_cenumval_list_get(const CEnumValList *list, u64 index);
|
|
||||||
void wapp_cenumval_list_push_front(CEnumValList *list, CEnumValNode *node);
|
|
||||||
void wapp_cenumval_list_push_back(CEnumValList *list, CEnumValNode *node);
|
|
||||||
void wapp_cenumval_list_insert(CEnumValList *list, CEnumValNode *node, u64 index);
|
|
||||||
CEnumValNode *wapp_cenumval_list_pop_front(CEnumValList *list);
|
|
||||||
CEnumValNode *wapp_cenumval_list_pop_back(CEnumValList *list);
|
|
||||||
CEnumValNode *wapp_cenumval_list_remove(CEnumValList *list, u64 index);
|
|
||||||
void wapp_cenumval_list_empty(CEnumValList *list);
|
|
||||||
CArgNode *wapp_carg_list_get(const CArgList *list, u64 index);
|
|
||||||
void wapp_carg_list_push_front(CArgList *list, CArgNode *node);
|
|
||||||
void wapp_carg_list_push_back(CArgList *list, CArgNode *node);
|
|
||||||
void wapp_carg_list_insert(CArgList *list, CArgNode *node, u64 index);
|
|
||||||
CArgNode *wapp_carg_list_pop_front(CArgList *list);
|
|
||||||
CArgNode *wapp_carg_list_pop_back(CArgList *list);
|
|
||||||
CArgNode *wapp_carg_list_remove(CArgList *list, u64 index);
|
|
||||||
void wapp_carg_list_empty(CArgList *list);
|
|
||||||
CQualifierNode *wapp_cqualifier_list_get(const CQualifierList *list, u64 index);
|
|
||||||
void wapp_cqualifier_list_push_front(CQualifierList *list, CQualifierNode *node);
|
|
||||||
void wapp_cqualifier_list_push_back(CQualifierList *list, CQualifierNode *node);
|
|
||||||
void wapp_cqualifier_list_insert(CQualifierList *list, CQualifierNode *node, u64 index);
|
|
||||||
CQualifierNode *wapp_cqualifier_list_pop_front(CQualifierList *list);
|
|
||||||
CQualifierNode *wapp_cqualifier_list_pop_back(CQualifierList *list);
|
|
||||||
CQualifierNode *wapp_cqualifier_list_remove(CQualifierList *list, u64 index);
|
|
||||||
void wapp_cqualifier_list_empty(CQualifierList *list);
|
|
||||||
CIncludeNode *wapp_cinclude_list_get(const CIncludeList *list, u64 index);
|
|
||||||
void wapp_cinclude_list_push_front(CIncludeList *list, CIncludeNode *node);
|
|
||||||
void wapp_cinclude_list_push_back(CIncludeList *list, CIncludeNode *node);
|
|
||||||
void wapp_cinclude_list_insert(CIncludeList *list, CIncludeNode *node, u64 index);
|
|
||||||
CIncludeNode *wapp_cinclude_list_pop_front(CIncludeList *list);
|
|
||||||
CIncludeNode *wapp_cinclude_list_pop_back(CIncludeList *list);
|
|
||||||
CIncludeNode *wapp_cinclude_list_remove(CIncludeList *list, u64 index);
|
|
||||||
void wapp_cinclude_list_empty(CIncludeList *list);
|
|
||||||
CUserTypeNode *wapp_cusertype_list_get(const CUserTypeList *list, u64 index);
|
|
||||||
void wapp_cusertype_list_push_front(CUserTypeList *list, CUserTypeNode *node);
|
|
||||||
void wapp_cusertype_list_push_back(CUserTypeList *list, CUserTypeNode *node);
|
|
||||||
void wapp_cusertype_list_insert(CUserTypeList *list, CUserTypeNode *node, u64 index);
|
|
||||||
CUserTypeNode *wapp_cusertype_list_pop_front(CUserTypeList *list);
|
|
||||||
CUserTypeNode *wapp_cusertype_list_pop_back(CUserTypeList *list);
|
|
||||||
CUserTypeNode *wapp_cusertype_list_remove(CUserTypeList *list, u64 index);
|
|
||||||
void wapp_cusertype_list_empty(CUserTypeList *list);
|
|
||||||
CFuncNode *wapp_cfunc_list_get(const CFuncList *list, u64 index);
|
|
||||||
void wapp_cfunc_list_push_front(CFuncList *list, CFuncNode *node);
|
|
||||||
void wapp_cfunc_list_push_back(CFuncList *list, CFuncNode *node);
|
|
||||||
void wapp_cfunc_list_insert(CFuncList *list, CFuncNode *node, u64 index);
|
|
||||||
CFuncNode *wapp_cfunc_list_pop_front(CFuncList *list);
|
|
||||||
CFuncNode *wapp_cfunc_list_pop_back(CFuncList *list);
|
|
||||||
CFuncNode *wapp_cfunc_list_remove(CFuncList *list, u64 index);
|
|
||||||
void wapp_cfunc_list_empty(CFuncList *list);
|
|
||||||
CStructNode *wapp_cstruct_list_get(const CStructList *list, u64 index);
|
|
||||||
void wapp_cstruct_list_push_front(CStructList *list, CStructNode *node);
|
|
||||||
void wapp_cstruct_list_push_back(CStructList *list, CStructNode *node);
|
|
||||||
void wapp_cstruct_list_insert(CStructList *list, CStructNode *node, u64 index);
|
|
||||||
CStructNode *wapp_cstruct_list_pop_front(CStructList *list);
|
|
||||||
CStructNode *wapp_cstruct_list_pop_back(CStructList *list);
|
|
||||||
CStructNode *wapp_cstruct_list_remove(CStructList *list, u64 index);
|
|
||||||
void wapp_cstruct_list_empty(CStructList *list);
|
|
||||||
CMacroNode *wapp_cmacro_list_get(const CMacroList *list, u64 index);
|
|
||||||
void wapp_cmacro_list_push_front(CMacroList *list, CMacroNode *node);
|
|
||||||
void wapp_cmacro_list_push_back(CMacroList *list, CMacroNode *node);
|
|
||||||
void wapp_cmacro_list_insert(CMacroList *list, CMacroNode *node, u64 index);
|
|
||||||
CMacroNode *wapp_cmacro_list_pop_front(CMacroList *list);
|
|
||||||
CMacroNode *wapp_cmacro_list_pop_back(CMacroList *list);
|
|
||||||
CMacroNode *wapp_cmacro_list_remove(CMacroList *list, u64 index);
|
|
||||||
void wapp_cmacro_list_empty(CMacroList *list);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !DBL_LIST_H
|
|
@@ -1,10 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "datatypes.h"
|
|
||||||
#include "type_enums.h"
|
|
||||||
#include "wapp_core.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,84 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef TYPE_ENUMS_H
|
|
||||||
#define TYPE_ENUMS_H
|
|
||||||
|
|
||||||
#include "wapp_core.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CTYPE_VOID,
|
|
||||||
CTYPE_B32,
|
|
||||||
CTYPE_CHAR,
|
|
||||||
CTYPE_C8,
|
|
||||||
CTYPE_C16,
|
|
||||||
CTYPE_C32,
|
|
||||||
CTYPE_I8,
|
|
||||||
CTYPE_I16,
|
|
||||||
CTYPE_I32,
|
|
||||||
CTYPE_I64,
|
|
||||||
CTYPE_U8,
|
|
||||||
CTYPE_U16,
|
|
||||||
CTYPE_U32,
|
|
||||||
CTYPE_U64,
|
|
||||||
CTYPE_F32,
|
|
||||||
CTYPE_F64,
|
|
||||||
CTYPE_F128,
|
|
||||||
CTYPE_IPTR,
|
|
||||||
CTYPE_UPTR,
|
|
||||||
|
|
||||||
COUNT_CTYPE,
|
|
||||||
} CType;
|
|
||||||
wapp_intern Str8RO ctypes[COUNT_CTYPE] = {
|
|
||||||
[CTYPE_VOID] = wapp_str8_lit_ro("void"),
|
|
||||||
[CTYPE_B32] = wapp_str8_lit_ro("b32"),
|
|
||||||
[CTYPE_CHAR] = wapp_str8_lit_ro("char"),
|
|
||||||
[CTYPE_C8] = wapp_str8_lit_ro("c8"),
|
|
||||||
[CTYPE_C16] = wapp_str8_lit_ro("c16"),
|
|
||||||
[CTYPE_C32] = wapp_str8_lit_ro("c32"),
|
|
||||||
[CTYPE_I8] = wapp_str8_lit_ro("i8"),
|
|
||||||
[CTYPE_I16] = wapp_str8_lit_ro("i16"),
|
|
||||||
[CTYPE_I32] = wapp_str8_lit_ro("i32"),
|
|
||||||
[CTYPE_I64] = wapp_str8_lit_ro("i64"),
|
|
||||||
[CTYPE_U8] = wapp_str8_lit_ro("u8"),
|
|
||||||
[CTYPE_U16] = wapp_str8_lit_ro("u16"),
|
|
||||||
[CTYPE_U32] = wapp_str8_lit_ro("u32"),
|
|
||||||
[CTYPE_U64] = wapp_str8_lit_ro("u64"),
|
|
||||||
[CTYPE_F32] = wapp_str8_lit_ro("f32"),
|
|
||||||
[CTYPE_F64] = wapp_str8_lit_ro("f64"),
|
|
||||||
[CTYPE_F128] = wapp_str8_lit_ro("f128"),
|
|
||||||
[CTYPE_IPTR] = wapp_str8_lit_ro("iptr"),
|
|
||||||
[CTYPE_UPTR] = wapp_str8_lit_ro("uptr"),
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CQUALIFIER_NONE,
|
|
||||||
CQUALIFIER_CONST,
|
|
||||||
CQUALIFIER_EXTERNAL,
|
|
||||||
CQUALIFIER_INTERNAL,
|
|
||||||
CQUALIFIER_PERSISTENT,
|
|
||||||
|
|
||||||
COUNT_CQUALIFIER,
|
|
||||||
} CQualifier;
|
|
||||||
wapp_intern Str8RO cqualifiers[COUNT_CQUALIFIER] = {
|
|
||||||
[CQUALIFIER_NONE] = wapp_str8_lit_ro(""),
|
|
||||||
[CQUALIFIER_CONST] = wapp_str8_lit_ro("const "),
|
|
||||||
[CQUALIFIER_EXTERNAL] = wapp_str8_lit_ro("wapp_extern "),
|
|
||||||
[CQUALIFIER_INTERNAL] = wapp_str8_lit_ro("wapp_intern "),
|
|
||||||
[CQUALIFIER_PERSISTENT] = wapp_str8_lit_ro("wapp_persist "),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CPOINTERTYPE_NONE,
|
|
||||||
CPOINTERTYPE_SINGLE,
|
|
||||||
CPOINTERTYPE_DOUBLE,
|
|
||||||
|
|
||||||
COUNT_CPOINTERTYPE,
|
|
||||||
} CPointerType;
|
|
||||||
wapp_intern Str8RO cpointertypes[COUNT_CPOINTERTYPE] = {
|
|
||||||
[CPOINTERTYPE_NONE] = wapp_str8_lit_ro(""),
|
|
||||||
[CPOINTERTYPE_SINGLE] = wapp_str8_lit_ro("*"),
|
|
||||||
[CPOINTERTYPE_DOUBLE] = wapp_str8_lit_ro("**"),
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !TYPE_ENUMS_H
|
|
@@ -1,60 +0,0 @@
|
|||||||
import json
|
|
||||||
from typing import Dict
|
|
||||||
from pathlib import Path
|
|
||||||
from codegen.datatypes import CDataType, CStruct
|
|
||||||
from codegen.constants import WAPP_REPO_ROOT, DBL_LIST_DATA, ARRAY_DATA
|
|
||||||
from codegen.dbl_list.make_dbl_list import DblListData, make_dbl_list
|
|
||||||
from codegen.array.make_array import ArrayData, make_array
|
|
||||||
|
|
||||||
|
|
||||||
def main(types_file: Path | None):
|
|
||||||
dbl_list_datatypes: Dict[CDataType, DblListData] = {}
|
|
||||||
array_datatypes: Dict[CDataType, ArrayData] = {}
|
|
||||||
|
|
||||||
if types_file is not None:
|
|
||||||
with types_file.open("r") as infile:
|
|
||||||
datatypes = json.load(infile)
|
|
||||||
dbl_list_data = datatypes.get(DBL_LIST_DATA)
|
|
||||||
array_data = datatypes.get(ARRAY_DATA)
|
|
||||||
|
|
||||||
if dbl_list_data is not None and isinstance(dbl_list_data, dict):
|
|
||||||
dbl_list_datatypes = {k: DblListData.from_dict(v) for k, v in dbl_list_data.items()}
|
|
||||||
|
|
||||||
if array_data is not None and isinstance(array_data, dict):
|
|
||||||
array_datatypes = {k: ArrayData.from_dict(v) for k, v in array_data.items()}
|
|
||||||
|
|
||||||
make_dbl_list(dbl_list_datatypes)
|
|
||||||
make_array(array_datatypes)
|
|
||||||
|
|
||||||
# Save example types file
|
|
||||||
custom_struct = CStruct(name="custom_type", cargs=[], typedef_name="CustomType")
|
|
||||||
example = {
|
|
||||||
DBL_LIST_DATA: {
|
|
||||||
"CustomType": DblListData(
|
|
||||||
node_typename="CustomTypeNode",
|
|
||||||
list_typename="CustomTypeList",
|
|
||||||
hdr_decl_types=[custom_struct],
|
|
||||||
).to_dict()
|
|
||||||
},
|
|
||||||
ARRAY_DATA: {
|
|
||||||
"CustomType": ArrayData(
|
|
||||||
array_typename="CustomTypeArray",
|
|
||||||
hdr_decl_types=[custom_struct],
|
|
||||||
).to_dict()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
example_file = WAPP_REPO_ROOT / "codegen_custom_data_example.json"
|
|
||||||
with example_file.open("w") as outfile:
|
|
||||||
json.dump(example, outfile, indent=2)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
|
|
||||||
parser = ArgumentParser()
|
|
||||||
parser.add_argument("-f", "--types-file", type=Path, help="JSON file containing custom types for codegen")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
main(args.types_file)
|
|
@@ -1,435 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import List, Dict, Any, Type
|
|
||||||
from codegen.constants import WAPP_SRC_ROOT
|
|
||||||
from codegen.utils import load_func_body_from_file, convert_to_relative
|
|
||||||
from codegen.datatypes import (
|
|
||||||
CDataType,
|
|
||||||
CMacro,
|
|
||||||
CStruct,
|
|
||||||
CFunc,
|
|
||||||
CHeader,
|
|
||||||
CSource,
|
|
||||||
CArg,
|
|
||||||
CType,
|
|
||||||
CPointer,
|
|
||||||
CPointerType,
|
|
||||||
CQualifier,
|
|
||||||
CInclude,
|
|
||||||
SerialisableDataclass,
|
|
||||||
get_datatype_string,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ArrayData(SerialisableDataclass):
|
|
||||||
array_typename: str
|
|
||||||
hdr_decl_types: List[CStruct] = field(default_factory=list)
|
|
||||||
src_decl_types: List[CStruct] = field(default_factory=list)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["ArrayData"], d: Dict[str, Any]) -> "ArrayData":
|
|
||||||
data = ArrayData(**d)
|
|
||||||
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
|
|
||||||
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def make_array(user_datatypes: Dict[CDataType, ArrayData] = {}):
|
|
||||||
def __format_func_body(
|
|
||||||
filename: Path,
|
|
||||||
type_string: str,
|
|
||||||
type_string_upper: str,
|
|
||||||
type_string_lower: str,
|
|
||||||
array_typename: str
|
|
||||||
):
|
|
||||||
return load_func_body_from_file(filename).format(
|
|
||||||
T=type_string,
|
|
||||||
ArrayType=array_typename,
|
|
||||||
Tupper=type_string_upper,
|
|
||||||
Tlower=type_string_lower,
|
|
||||||
)
|
|
||||||
|
|
||||||
out_dir = WAPP_SRC_ROOT / "primitives" / "array"
|
|
||||||
out_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
common_includes: List[CInclude] = [
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "primitives" / "mem_allocator" / "mem_allocator.h", out_dir)).replace("\\", "/"),
|
|
||||||
local=True,
|
|
||||||
),
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "misc" / "misc_utils.h", out_dir)).replace("\\", "/"),
|
|
||||||
local=True,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
common_decl_types: List[CStruct] = []
|
|
||||||
|
|
||||||
datatypes: dict[CDataType, ArrayData] = {
|
|
||||||
CType.VOID: ArrayData(array_typename="GenericArray"),
|
|
||||||
"void *": ArrayData(array_typename="VoidPArray"),
|
|
||||||
"Str8": ArrayData(
|
|
||||||
array_typename="Str8Array",
|
|
||||||
hdr_decl_types=[
|
|
||||||
CStruct(name="str8", cargs=[], typedef_name="Str8"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _type in CType:
|
|
||||||
if _type == CType.VOID:
|
|
||||||
continue
|
|
||||||
|
|
||||||
type_title = _type.value.title()
|
|
||||||
datatypes[_type] = ArrayData(
|
|
||||||
array_typename=f"{type_title}Array",
|
|
||||||
)
|
|
||||||
|
|
||||||
datatypes.update(user_datatypes)
|
|
||||||
|
|
||||||
snippets_dir = Path(__file__).parent / "snippets"
|
|
||||||
|
|
||||||
header = CHeader(
|
|
||||||
name="array",
|
|
||||||
decl_types=[*common_decl_types],
|
|
||||||
includes=[],
|
|
||||||
types=[],
|
|
||||||
funcs=[]
|
|
||||||
)
|
|
||||||
|
|
||||||
source = CSource(
|
|
||||||
name=header.name,
|
|
||||||
decl_types=[*common_decl_types],
|
|
||||||
includes=[
|
|
||||||
CInclude(header, local=True, same_dir=True),
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
|
|
||||||
local=True
|
|
||||||
),
|
|
||||||
CInclude(header="stddef.h"),
|
|
||||||
],
|
|
||||||
internal_funcs=[],
|
|
||||||
funcs=header.funcs
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(common_includes) > 0:
|
|
||||||
header.includes.extend(common_includes)
|
|
||||||
source.includes.extend(common_includes)
|
|
||||||
|
|
||||||
|
|
||||||
generic_funcs = []
|
|
||||||
|
|
||||||
for _type, array_data in datatypes.items():
|
|
||||||
type_string = get_datatype_string(_type)
|
|
||||||
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
|
|
||||||
type_string_upper = clean_type_string.upper()
|
|
||||||
type_string_lower = clean_type_string.lower()
|
|
||||||
|
|
||||||
array = CStruct(
|
|
||||||
name=array_data.array_typename,
|
|
||||||
cargs=[
|
|
||||||
CArg(name="items", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
CArg(name="count", _type=CType.U64),
|
|
||||||
CArg(name="capacity", _type=CType.U64),
|
|
||||||
CArg(name="item_size", _type=CType.U64),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(_type, CType) and _type == CType.VOID:
|
|
||||||
alloc_capacity_func = CFunc(
|
|
||||||
name=f"_array_alloc_capacity",
|
|
||||||
ret_type=array,
|
|
||||||
args=[
|
|
||||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="capacity", _type=CType.U64),
|
|
||||||
CArg(name="item_size", _type=CType.U64),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "alloc_capacity",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
generic_funcs.append(alloc_capacity_func)
|
|
||||||
else:
|
|
||||||
stack_array_cmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array(...)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "stack_array",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
stack_array_cppmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array(...)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "stack_array_cpp",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
stack_capacity_array_cmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "stack_capacity_array",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
stack_capacity_array_cppmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "stack_capacity_array_cpp",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
alloc_capacity_array_macro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "alloc_capacity_macro",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
array_pop_cmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "array_pop_macro",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
array_pop_cppmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "array_pop_macro_cpp",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
get_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_get",
|
|
||||||
ret_type=type_string,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="index", _type=CType.U64),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "array_get",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
set_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_set",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="index", _type=CType.U64),
|
|
||||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "array_set",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
append_capped_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_append_capped",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "append_capped",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
extend_capped_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_extend_capped",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "extend_capped",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
clear_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_clear",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "clear",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
copy_capped_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_copy_capped",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "copy_capped",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
append_alloc_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_append_alloc",
|
|
||||||
ret_type=array,
|
|
||||||
args=[
|
|
||||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "append_alloc",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
extend_alloc_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_extend_alloc",
|
|
||||||
ret_type=array,
|
|
||||||
args=[
|
|
||||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "extend_alloc",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
copy_alloc_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_array_copy_alloc",
|
|
||||||
ret_type=array,
|
|
||||||
args=[
|
|
||||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "copy_alloc",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
pop_func = CFunc(
|
|
||||||
name=f"_{type_string_lower}_array_pop",
|
|
||||||
ret_type=type_string,
|
|
||||||
args=[
|
|
||||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "array_pop",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
array_typename=array_data.array_typename,
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
header.macros.extend([
|
|
||||||
alloc_capacity_array_macro,
|
|
||||||
])
|
|
||||||
header.c_macros.extend([
|
|
||||||
stack_array_cmacro,
|
|
||||||
stack_capacity_array_cmacro,
|
|
||||||
array_pop_cmacro,
|
|
||||||
])
|
|
||||||
header.cpp_macros.extend([
|
|
||||||
stack_array_cppmacro,
|
|
||||||
stack_capacity_array_cppmacro,
|
|
||||||
array_pop_cppmacro,
|
|
||||||
])
|
|
||||||
header.funcs.extend([
|
|
||||||
get_func,
|
|
||||||
set_func,
|
|
||||||
append_capped_func,
|
|
||||||
extend_capped_func,
|
|
||||||
clear_func,
|
|
||||||
copy_capped_func,
|
|
||||||
append_alloc_func,
|
|
||||||
extend_alloc_func,
|
|
||||||
copy_alloc_func,
|
|
||||||
pop_func,
|
|
||||||
])
|
|
||||||
|
|
||||||
header.decl_types.extend(array_data.hdr_decl_types)
|
|
||||||
header.types.extend([array])
|
|
||||||
|
|
||||||
source.decl_types.extend(array_data.src_decl_types)
|
|
||||||
source.funcs = header.funcs
|
|
||||||
|
|
||||||
|
|
||||||
header.funcs.extend(generic_funcs)
|
|
||||||
header.save(out_dir)
|
|
||||||
source.save(out_dir)
|
|
@@ -1,15 +0,0 @@
|
|||||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
|
||||||
|
|
||||||
u64 allocation_size = sizeof({ArrayType}) + item_size * capacity;
|
|
||||||
{ArrayType} *array = wapp_mem_allocator_alloc(allocator, allocation_size);
|
|
||||||
if (!array) {{
|
|
||||||
goto RETURN_GENERIC_ARRAY_ALLOC;
|
|
||||||
}}
|
|
||||||
|
|
||||||
array->items = ({T} *)((u8 *)array + sizeof({ArrayType}));
|
|
||||||
array->count = 0;
|
|
||||||
array->capacity = capacity;
|
|
||||||
array->item_size = item_size;
|
|
||||||
|
|
||||||
RETURN_GENERIC_ARRAY_ALLOC:
|
|
||||||
return array;
|
|
@@ -1 +0,0 @@
|
|||||||
(({ArrayType} *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof({T})))
|
|
@@ -1,18 +0,0 @@
|
|||||||
wapp_debug_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
|
||||||
|
|
||||||
{ArrayType} *output = array;
|
|
||||||
|
|
||||||
if (array->count >= array->capacity) {{
|
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
|
||||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
|
|
||||||
if (!output) {{
|
|
||||||
output = array;
|
|
||||||
goto RETURN_{Tupper}_ARRAY_APPEND_ALLOC;
|
|
||||||
}}
|
|
||||||
wapp_{Tlower}_array_copy_capped(array, output);
|
|
||||||
}}
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_append_capped(output, item);
|
|
||||||
|
|
||||||
RETURN_{Tupper}_ARRAY_APPEND_ALLOC:
|
|
||||||
return output;
|
|
@@ -1,5 +0,0 @@
|
|||||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
|
||||||
wapp_runtime_assert(array->count < array->capacity, "`array` is full");
|
|
||||||
|
|
||||||
u64 index = (array->count)++;
|
|
||||||
wapp_{Tlower}_array_set(array, index, item);
|
|
@@ -1,5 +0,0 @@
|
|||||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
|
||||||
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
|
|
||||||
|
|
||||||
u8 *ptr = (u8 *)(array->items) + (array->item_size * index);
|
|
||||||
return ({T} *)ptr;
|
|
@@ -1,4 +0,0 @@
|
|||||||
u64 index = array->count - 1;
|
|
||||||
{T} *out = wapp_{Tlower}_array_get(array, index);
|
|
||||||
--(array->count);
|
|
||||||
return out;
|
|
@@ -1,4 +0,0 @@
|
|||||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
|
||||||
*_{Tlower}_array_pop(ARRAY_PTR) : \
|
|
||||||
({T}){{0}} \
|
|
||||||
)
|
|
@@ -1,4 +0,0 @@
|
|||||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
|
||||||
*_{Tlower}_array_pop(ARRAY_PTR) : \
|
|
||||||
{T}{{}} \
|
|
||||||
)
|
|
@@ -1,3 +0,0 @@
|
|||||||
{T} *ptr = wapp_{Tlower}_array_get(array, index);
|
|
||||||
|
|
||||||
memcpy((void *)ptr, (void *)item, array->item_size);
|
|
@@ -1,2 +0,0 @@
|
|||||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
|
||||||
array->count = 0;
|
|
@@ -1,18 +0,0 @@
|
|||||||
wapp_debug_assert(allocator != NULL && src != NULL && dst != NULL, "`allocator`, `src` and `dst` should not be NULL");
|
|
||||||
|
|
||||||
{ArrayType} *output = dst;
|
|
||||||
|
|
||||||
if (src->count >= dst->capacity) {{
|
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
|
||||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, src->item_size);
|
|
||||||
if (!output) {{
|
|
||||||
output = dst;
|
|
||||||
goto RETURN_{Tupper}_ARRAY_COPY_ALLOC;
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_clear(output);
|
|
||||||
wapp_{Tlower}_array_copy_capped(src, output);
|
|
||||||
|
|
||||||
RETURN_{Tupper}_ARRAY_COPY_ALLOC:
|
|
||||||
return output;
|
|
@@ -1,22 +0,0 @@
|
|||||||
wapp_debug_assert(src != NULL && dst != NULL, "`src` and `dst` should not be NULL");
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_clear(dst);
|
|
||||||
|
|
||||||
{T} *item;
|
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
|
||||||
// MSVC Spectre mitigation warnings
|
|
||||||
u64 to_copy = src->count < dst->capacity ? src->count : dst->capacity;
|
|
||||||
u64 item_index = 0;
|
|
||||||
b32 running = true;
|
|
||||||
while (running) {{
|
|
||||||
item = wapp_{Tlower}_array_get(src, item_index);
|
|
||||||
++item_index;
|
|
||||||
running = item_index < to_copy;
|
|
||||||
|
|
||||||
if (!item) {{
|
|
||||||
continue;
|
|
||||||
}}
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_append_capped(dst, item);
|
|
||||||
}}
|
|
@@ -1,19 +0,0 @@
|
|||||||
wapp_debug_assert(allocator != NULL && array != NULL && other != NULL, "`allocator`, `array` and `other` should not be NULL");
|
|
||||||
|
|
||||||
{ArrayType} *output = array;
|
|
||||||
|
|
||||||
u64 remaining_capacity = array->capacity - array->count;
|
|
||||||
if (other->count >= remaining_capacity) {{
|
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
|
||||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
|
|
||||||
if (!output) {{
|
|
||||||
output = array;
|
|
||||||
goto RETURN_{Tupper}_ARRAY_EXTEND_ALLOC;
|
|
||||||
}}
|
|
||||||
wapp_{Tlower}_array_copy_capped(array, output);
|
|
||||||
}}
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_extend_capped(output, other);
|
|
||||||
|
|
||||||
RETURN_{Tupper}_ARRAY_EXTEND_ALLOC:
|
|
||||||
return output;
|
|
@@ -1,23 +0,0 @@
|
|||||||
wapp_debug_assert(array != NULL && other != NULL, "`array` and `other` should not be NULL");
|
|
||||||
|
|
||||||
u64 remaining_capacity = array->capacity - array->count;
|
|
||||||
wapp_runtime_assert(other->count < remaining_capacity, "`array` does not have enough capacity");
|
|
||||||
|
|
||||||
{T} *item;
|
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
|
||||||
// MSVC Spectre mitigation warnings
|
|
||||||
u64 items_to_add = other->count;
|
|
||||||
u64 item_index = 0;
|
|
||||||
b32 running = true;
|
|
||||||
while (running) {{
|
|
||||||
item = wapp_{Tlower}_array_get(other, item_index);
|
|
||||||
++item_index;
|
|
||||||
running = item_index < items_to_add;
|
|
||||||
|
|
||||||
if (!item) {{
|
|
||||||
continue;
|
|
||||||
}}
|
|
||||||
|
|
||||||
wapp_{Tlower}_array_append_capped(array, item);
|
|
||||||
}}
|
|
@@ -1,6 +0,0 @@
|
|||||||
(({ArrayType}){{ \
|
|
||||||
.items = ({T}[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)]){{__VA_ARGS__}}, \
|
|
||||||
.count = wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
|
|
||||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
|
|
||||||
.item_size = sizeof({T}) \
|
|
||||||
}})
|
|
@@ -1,9 +0,0 @@
|
|||||||
([&]() {{ \
|
|
||||||
wapp_persist {T} buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)] = {{__VA_ARGS__}}; \
|
|
||||||
return {ArrayType}{{ \
|
|
||||||
buf, \
|
|
||||||
wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
|
|
||||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
|
|
||||||
sizeof({T}) \
|
|
||||||
}}; \
|
|
||||||
}}())
|
|
@@ -1 +0,0 @@
|
|||||||
(({ArrayType}){{.items = ({T}[CAPACITY]){{0}}, .count = 0, .capacity = CAPACITY, .item_size = sizeof({T})}})
|
|
@@ -1,4 +0,0 @@
|
|||||||
([&]() {{ \
|
|
||||||
wapp_persist {T} buf[CAPACITY] = {{}}; \
|
|
||||||
return {ArrayType}{{buf, 0, CAPACITY, sizeof({T})}}; \
|
|
||||||
}}())
|
|
@@ -1,10 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Paths
|
|
||||||
PACKAGE_DIR = Path(__file__).parent.resolve()
|
|
||||||
WAPP_REPO_ROOT = PACKAGE_DIR.parent
|
|
||||||
WAPP_SRC_ROOT = WAPP_REPO_ROOT / "src"
|
|
||||||
|
|
||||||
# Dictionary Keys
|
|
||||||
DBL_LIST_DATA = "dbl_list_data"
|
|
||||||
ARRAY_DATA = "array_data"
|
|
@@ -1,503 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Optional, Union, List, Dict, Type, Any, TypeVar, cast
|
|
||||||
from dataclasses import dataclass, asdict, field, fields
|
|
||||||
|
|
||||||
from codegen.constants import WAPP_SRC_ROOT
|
|
||||||
from codegen.utils import convert_to_relative
|
|
||||||
|
|
||||||
E = TypeVar("E", bound="Enum")
|
|
||||||
S = TypeVar("S", bound="SerialisableDataclass")
|
|
||||||
F = TypeVar("F", bound="CFile")
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SerialisableDataclass:
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
|
||||||
d = asdict(self)
|
|
||||||
for f in fields(self):
|
|
||||||
member = getattr(self, f.name)
|
|
||||||
|
|
||||||
if isinstance(member, list):
|
|
||||||
d[f.name] = [self.__serialise_member(i) for i in member]
|
|
||||||
else:
|
|
||||||
d[f.name] = self.__serialise_member(member)
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
def __serialise_member(self, member: Any) -> Any:
|
|
||||||
if isinstance(member, Enum):
|
|
||||||
return member.value
|
|
||||||
elif isinstance(member, SerialisableDataclass):
|
|
||||||
return member.to_dict()
|
|
||||||
|
|
||||||
return member
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def to_enum_value(value: Any, _type: Type[E]) -> "E":
|
|
||||||
if isinstance(value, _type):
|
|
||||||
return value
|
|
||||||
|
|
||||||
return _type(value)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def to_c_usertype(value: dict[str, Any]) -> "CUserType":
|
|
||||||
try:
|
|
||||||
output = CStruct.from_dict(value)
|
|
||||||
except TypeError:
|
|
||||||
output = CEnum.from_dict(value)
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def to_cdatatype(value: Any) -> "CDataType":
|
|
||||||
if isinstance(value, dict):
|
|
||||||
output = SerialisableDataclass.to_c_usertype(value)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
output = CType(value)
|
|
||||||
except ValueError:
|
|
||||||
output = value
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type[S], d: Dict[str, Any]) -> "S":
|
|
||||||
return cls(**d)
|
|
||||||
|
|
||||||
|
|
||||||
class CType(Enum):
|
|
||||||
VOID = "void"
|
|
||||||
BOOL = "b32"
|
|
||||||
CHAR = "char"
|
|
||||||
C8 = "c8"
|
|
||||||
C16 = "c16"
|
|
||||||
C32 = "c32"
|
|
||||||
I8 = "i8"
|
|
||||||
I16 = "i16"
|
|
||||||
I32 = "i32"
|
|
||||||
I64 = "i64"
|
|
||||||
U8 = "u8"
|
|
||||||
U16 = "u16"
|
|
||||||
U32 = "u32"
|
|
||||||
U64 = "u64"
|
|
||||||
F32 = "f32"
|
|
||||||
F64 = "f64"
|
|
||||||
F128 = "f128"
|
|
||||||
IPTR = "iptr"
|
|
||||||
UPTR = "uptr"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
class CQualifier(Enum):
|
|
||||||
NONE = ""
|
|
||||||
CONST = "const "
|
|
||||||
EXTERNAL = "wapp_extern "
|
|
||||||
INTERNAL = "wapp_intern "
|
|
||||||
PERSISTENT = "wapp_persist "
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
class CPointerType(Enum):
|
|
||||||
NONE = ""
|
|
||||||
SINGLE = "*"
|
|
||||||
DOUBLE = "**"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CPointer(SerialisableDataclass):
|
|
||||||
_type: CPointerType = CPointerType.NONE
|
|
||||||
qualifier: CQualifier = CQualifier.NONE
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return str(self._type) + str(self.qualifier)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CPointer"], d: Dict[str, Any]) -> "CPointer":
|
|
||||||
ptr = CPointer(**d)
|
|
||||||
ptr._type = CPointer.to_enum_value(ptr._type, CPointerType)
|
|
||||||
ptr.qualifier = CPointer.to_enum_value(ptr.qualifier, CQualifier)
|
|
||||||
return ptr
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CEnumVal(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
value: Optional[int] = None
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.name + "" if self.value is None else f" = {self.value}"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CEnum(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
values: List[CEnumVal]
|
|
||||||
typedef: bool = False
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
if self.typedef:
|
|
||||||
header = "typedef enum {\n"
|
|
||||||
footer = f"}} {self.name};\n"
|
|
||||||
else:
|
|
||||||
header = f"enum {self.name} {{\n"
|
|
||||||
footer = "};\n"
|
|
||||||
|
|
||||||
values = ""
|
|
||||||
for value in self.values:
|
|
||||||
values += f" {str(value)},\n"
|
|
||||||
|
|
||||||
return header + values + footer
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CEnum"], d: Dict[str, Any]) -> "CEnum":
|
|
||||||
e = CEnum(**d)
|
|
||||||
e.values = [CEnumVal.from_dict(v) for v in e.values if isinstance(v, dict)]
|
|
||||||
return e
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CMacro(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
value: str
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"#define {self.name} {self.value}\n"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CStruct(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
cargs: List["CArg"]
|
|
||||||
typedef_name: Optional[str] = None
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.declare() + self.define()
|
|
||||||
|
|
||||||
def declare(self) -> str:
|
|
||||||
declaration = f"typedef struct {self.name} {self.typedef_name if self.typedef_name is not None else self.name};\n"
|
|
||||||
return declaration
|
|
||||||
|
|
||||||
def define(self):
|
|
||||||
definition = f"struct {self.name} {{\n"
|
|
||||||
args = ""
|
|
||||||
for arg in self.cargs:
|
|
||||||
args += f" {str(arg)};\n"
|
|
||||||
footer = "};\n"
|
|
||||||
|
|
||||||
return definition + args + footer;
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CStruct"], d: Dict[str, Any]) -> "CStruct":
|
|
||||||
s = CStruct(**d)
|
|
||||||
s.cargs = [CArg.from_dict(v) for v in s.cargs if isinstance(v, dict)]
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
CUserType = Union[CStruct, CEnum]
|
|
||||||
CDataType = Union[CType, CUserType, str]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CArg(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
_type: CDataType
|
|
||||||
array: bool = False
|
|
||||||
pointer: CPointer = field(default_factory=CPointer)
|
|
||||||
qualifier: CQualifier = CQualifier.NONE
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
qualifier = str(self.qualifier)
|
|
||||||
_type = get_datatype_string(self._type) + " "
|
|
||||||
pointer = str(self.pointer)
|
|
||||||
array = "[]" if self.array else ""
|
|
||||||
|
|
||||||
return qualifier + _type + pointer + self.name + array
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CArg"], d: Dict[str, Any]) -> "CArg":
|
|
||||||
arg = CArg(**d)
|
|
||||||
arg._type = CArg.to_cdatatype(arg._type)
|
|
||||||
|
|
||||||
if isinstance(arg.pointer, dict):
|
|
||||||
arg.pointer = CPointer.from_dict(arg.pointer)
|
|
||||||
|
|
||||||
arg.qualifier = CArg.to_enum_value(arg.qualifier, CQualifier)
|
|
||||||
|
|
||||||
return arg
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CFunc(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
ret_type: CDataType
|
|
||||||
args: List[CArg]
|
|
||||||
body: str
|
|
||||||
pointer: CPointer = field(default_factory=CPointer)
|
|
||||||
qualifiers: List[CQualifier] = field(default_factory=list)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
qualifiers = ""
|
|
||||||
for qualifier in self.qualifiers:
|
|
||||||
if qualifier == CQualifier.NONE:
|
|
||||||
continue
|
|
||||||
if len(qualifiers) > 0:
|
|
||||||
qualifiers += " "
|
|
||||||
qualifiers += f"{str(qualifier)}"
|
|
||||||
|
|
||||||
args = ""
|
|
||||||
for i, arg in enumerate(self.args):
|
|
||||||
args += f"{str(arg)}"
|
|
||||||
if i + 1 < len(self.args):
|
|
||||||
args += ", "
|
|
||||||
|
|
||||||
return qualifiers + get_datatype_string(self.ret_type) + " " + str(self.pointer) + self.name + f"({args})"
|
|
||||||
|
|
||||||
def declare(self) -> str:
|
|
||||||
return f"{str(self)};\n"
|
|
||||||
|
|
||||||
def define(self) -> str:
|
|
||||||
return f"{str(self)} {{\n{self.body}\n}}\n\n"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CFunc"], d: Dict[str, Any]) -> "CFunc":
|
|
||||||
f = CFunc(**d)
|
|
||||||
f.ret_type = CFunc.to_cdatatype(f.ret_type)
|
|
||||||
f.args = [CArg.from_dict(v) for v in f.args if isinstance(v, dict)]
|
|
||||||
f.qualifiers = [CFunc.to_enum_value(v, CQualifier) for v in f.qualifiers]
|
|
||||||
|
|
||||||
if isinstance(f.pointer, dict):
|
|
||||||
f.pointer = CPointer.from_dict(f.pointer)
|
|
||||||
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CInclude(SerialisableDataclass):
|
|
||||||
header: Union[str, "CHeader"]
|
|
||||||
local: bool = False
|
|
||||||
same_dir: bool = False
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
if isinstance(self.header, CHeader):
|
|
||||||
name = f"{self.header.name}.{self.header.extension}"
|
|
||||||
else:
|
|
||||||
name = self.header
|
|
||||||
|
|
||||||
if self.local:
|
|
||||||
open_symbol = '"'
|
|
||||||
close_symbol = '"'
|
|
||||||
|
|
||||||
if self.same_dir:
|
|
||||||
name = f"./{name}"
|
|
||||||
else:
|
|
||||||
open_symbol = '<'
|
|
||||||
close_symbol = '>'
|
|
||||||
|
|
||||||
return f"#include {open_symbol}{name}{close_symbol}\n"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CInclude"], d: Dict[str, Any]) -> "CInclude":
|
|
||||||
inc = CInclude(**d)
|
|
||||||
|
|
||||||
if isinstance(inc.header, dict):
|
|
||||||
inc.header = CHeader.from_dict(inc.header)
|
|
||||||
|
|
||||||
return inc
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CFile(SerialisableDataclass):
|
|
||||||
name: str
|
|
||||||
extension: str
|
|
||||||
includes: List[CInclude] = field(default_factory=list)
|
|
||||||
types: List[CUserType] = field(default_factory=list)
|
|
||||||
funcs: List[CFunc] = field(default_factory=list)
|
|
||||||
decl_types: List[CStruct] = field(default_factory=list)
|
|
||||||
macros: List[CMacro] = field(default_factory=list)
|
|
||||||
c_macros: List[CMacro] = field(default_factory=list)
|
|
||||||
cpp_macros: List[CMacro] = field(default_factory=list)
|
|
||||||
|
|
||||||
def save(self, output_dir: Path):
|
|
||||||
self.includes.extend(
|
|
||||||
[
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "aliases" / "aliases.h", output_dir)).replace("\\", "/"),
|
|
||||||
local=True,
|
|
||||||
),
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "platform" / "platform.h", output_dir)).replace("\\", "/"),
|
|
||||||
local=True,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
output_file = output_dir / f"{self.name}.{self.extension}"
|
|
||||||
with open(output_file, "w+") as outfile:
|
|
||||||
outfile.write(str(self))
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return """\
|
|
||||||
/**
|
|
||||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
|
|
||||||
*/
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CFile"], d: Dict[str, Any]) -> "CFile":
|
|
||||||
f = CFile(**d)
|
|
||||||
f.deserialise_c_file_data()
|
|
||||||
|
|
||||||
return f
|
|
||||||
|
|
||||||
def deserialise_c_file_data(self) -> None:
|
|
||||||
self.includes = [CInclude.from_dict(v) for v in self.includes if isinstance(v, dict)]
|
|
||||||
self.types = [CFile.to_c_usertype(v) for v in self.types if isinstance(v, dict)]
|
|
||||||
self.funcs = [CFunc.from_dict(v) for v in self.funcs if isinstance(v, dict)]
|
|
||||||
self.decl_types = [CStruct.from_dict(v) for v in self.decl_types if isinstance(v, dict)]
|
|
||||||
self.macros = [CMacro.from_dict(v) for v in self.macros if isinstance(v, dict)]
|
|
||||||
self.c_macros = [CMacro.from_dict(v) for v in self.c_macros if isinstance(v, dict)]
|
|
||||||
self.cpp_macros = [CMacro.from_dict(v) for v in self.cpp_macros if isinstance(v, dict)]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CHeader(CFile):
|
|
||||||
extension: str = "h"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
name_upper = self.name.upper()
|
|
||||||
header_guard_name = f"{name_upper}_H"
|
|
||||||
header_guard_open = f"#ifndef {header_guard_name}\n#define {header_guard_name}\n\n"
|
|
||||||
header_guard_close = f"#endif // !{header_guard_name}\n"
|
|
||||||
|
|
||||||
c_linkage_open = "#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
|
||||||
c_linkage_close = "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
|
||||||
|
|
||||||
includes = _get_includes_string(self.includes)
|
|
||||||
|
|
||||||
macros = ""
|
|
||||||
for macro in self.macros:
|
|
||||||
macros += str(macro)
|
|
||||||
if len(macros) > 0:
|
|
||||||
macros += "\n"
|
|
||||||
|
|
||||||
if len(self.cpp_macros) > 0:
|
|
||||||
macros += "#ifdef WAPP_PLATFORM_CPP\n"
|
|
||||||
for macro in self.cpp_macros:
|
|
||||||
macros += str(macro)
|
|
||||||
macros += "#else\n"
|
|
||||||
for macro in self.c_macros:
|
|
||||||
macros += str(macro)
|
|
||||||
macros += "#endif // !WAPP_PLATFORM_CPP\n\n"
|
|
||||||
|
|
||||||
forward_declarations = ""
|
|
||||||
for _type in self.decl_types:
|
|
||||||
forward_declarations += _type.declare()
|
|
||||||
if len(forward_declarations) > 0:
|
|
||||||
forward_declarations += "\n"
|
|
||||||
|
|
||||||
types = ""
|
|
||||||
for _type in self.types:
|
|
||||||
types += str(_type) + "\n"
|
|
||||||
|
|
||||||
funcs = ""
|
|
||||||
for func in self.funcs:
|
|
||||||
funcs += func.declare()
|
|
||||||
|
|
||||||
return (
|
|
||||||
super().__str__() +
|
|
||||||
header_guard_open +
|
|
||||||
includes +
|
|
||||||
c_linkage_open +
|
|
||||||
macros +
|
|
||||||
forward_declarations +
|
|
||||||
types +
|
|
||||||
funcs +
|
|
||||||
c_linkage_close +
|
|
||||||
header_guard_close
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CHeader"], d: Dict[str, Any]) -> "CHeader":
|
|
||||||
return cast("CHeader", super().from_dict(d))
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class CSource(CFile):
|
|
||||||
extension: str = "c"
|
|
||||||
internal_funcs: List[CFunc] = field(default_factory=list)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
includes = _get_includes_string(self.includes)
|
|
||||||
|
|
||||||
macros = ""
|
|
||||||
for macro in self.macros:
|
|
||||||
macros += str(macro)
|
|
||||||
if len(macros) > 0:
|
|
||||||
macros += "\n"
|
|
||||||
|
|
||||||
forward_declarations = ""
|
|
||||||
for _type in self.decl_types:
|
|
||||||
forward_declarations += _type.declare()
|
|
||||||
if len(forward_declarations) > 0:
|
|
||||||
forward_declarations += "\n"
|
|
||||||
|
|
||||||
types = ""
|
|
||||||
for _type in self.types:
|
|
||||||
types += str(_type) + "\n"
|
|
||||||
|
|
||||||
internal_funcs_decl = ""
|
|
||||||
internal_funcs_def = ""
|
|
||||||
for func in self.internal_funcs:
|
|
||||||
internal_funcs_decl += func.declare()
|
|
||||||
internal_funcs_def += func.define()
|
|
||||||
|
|
||||||
if len(internal_funcs_decl) > 0:
|
|
||||||
internal_funcs_decl += "\n"
|
|
||||||
|
|
||||||
funcs = ""
|
|
||||||
for func in self.funcs:
|
|
||||||
funcs += func.define()
|
|
||||||
|
|
||||||
return (
|
|
||||||
super().__str__() +
|
|
||||||
includes +
|
|
||||||
macros +
|
|
||||||
forward_declarations +
|
|
||||||
types +
|
|
||||||
internal_funcs_decl +
|
|
||||||
funcs +
|
|
||||||
internal_funcs_def
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["CSource"], d: Dict[str, Any]) -> "CSource":
|
|
||||||
s = CSource(**d)
|
|
||||||
s.deserialise_c_file_data()
|
|
||||||
s.internal_funcs = [CFunc.from_dict(v) for v in s.funcs if isinstance(v, dict)]
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def get_datatype_string(_type: CDataType) -> str:
|
|
||||||
if isinstance(_type, CType):
|
|
||||||
return str(_type)
|
|
||||||
elif isinstance(_type, CStruct) or isinstance(_type, CEnum):
|
|
||||||
return _type.name
|
|
||||||
elif isinstance(_type, str):
|
|
||||||
return _type
|
|
||||||
|
|
||||||
|
|
||||||
def _get_includes_string(includes: List[CInclude]) -> str:
|
|
||||||
output = ""
|
|
||||||
for include in sorted(includes, key=lambda inc: inc.local, reverse=True):
|
|
||||||
output += str(include)
|
|
||||||
if len(output) > 0:
|
|
||||||
output += "\n"
|
|
||||||
|
|
||||||
return output
|
|
@@ -1,339 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import List, Dict, Any, Type
|
|
||||||
from codegen.constants import WAPP_SRC_ROOT
|
|
||||||
from codegen.utils import load_func_body_from_file, convert_to_relative
|
|
||||||
from codegen.datatypes import (
|
|
||||||
CDataType,
|
|
||||||
CMacro,
|
|
||||||
CStruct,
|
|
||||||
CFunc,
|
|
||||||
CHeader,
|
|
||||||
CSource,
|
|
||||||
CArg,
|
|
||||||
CType,
|
|
||||||
CPointer,
|
|
||||||
CPointerType,
|
|
||||||
CQualifier,
|
|
||||||
CInclude,
|
|
||||||
SerialisableDataclass,
|
|
||||||
get_datatype_string,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DblListData(SerialisableDataclass):
|
|
||||||
node_typename: str
|
|
||||||
list_typename: str
|
|
||||||
hdr_decl_types: List[CStruct] = field(default_factory=list)
|
|
||||||
src_decl_types: List[CStruct] = field(default_factory=list)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls: Type["DblListData"], d: Dict[str, Any]) -> "DblListData":
|
|
||||||
data = DblListData(**d)
|
|
||||||
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
|
|
||||||
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def make_dbl_list(user_datatypes: Dict[CDataType, DblListData] = {}):
|
|
||||||
def __format_func_body(
|
|
||||||
filename: Path,
|
|
||||||
type_string: str,
|
|
||||||
type_string_upper: str,
|
|
||||||
type_string_lower: str,
|
|
||||||
node_typename: str,
|
|
||||||
list_typename: str
|
|
||||||
):
|
|
||||||
return load_func_body_from_file(filename).format(
|
|
||||||
T=type_string,
|
|
||||||
NodeType=node_typename,
|
|
||||||
ListType=list_typename,
|
|
||||||
Tupper=type_string_upper,
|
|
||||||
Tlower=type_string_lower,
|
|
||||||
)
|
|
||||||
|
|
||||||
out_dir = WAPP_SRC_ROOT / "primitives" / "dbl_list"
|
|
||||||
out_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
common_decl_types: List[CStruct] = []
|
|
||||||
|
|
||||||
datatypes: dict[CDataType, DblListData] = {
|
|
||||||
CType.VOID: DblListData(node_typename="GenericNode", list_typename="GenericList"),
|
|
||||||
"void *": DblListData(node_typename="VoidPNode", list_typename="VoidPList"),
|
|
||||||
"Str8": DblListData(
|
|
||||||
node_typename="Str8Node",
|
|
||||||
list_typename="Str8List",
|
|
||||||
hdr_decl_types=[
|
|
||||||
CStruct(name="str8", cargs=[], typedef_name="Str8"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _type in CType:
|
|
||||||
if _type == CType.VOID:
|
|
||||||
continue
|
|
||||||
|
|
||||||
type_title = _type.value.title()
|
|
||||||
datatypes[_type] = DblListData(
|
|
||||||
node_typename=f"{type_title}Node",
|
|
||||||
list_typename=f"{type_title}List",
|
|
||||||
)
|
|
||||||
|
|
||||||
datatypes.update(user_datatypes)
|
|
||||||
|
|
||||||
snippets_dir = Path(__file__).parent / "snippets"
|
|
||||||
|
|
||||||
header = CHeader(
|
|
||||||
name="dbl_list",
|
|
||||||
decl_types=[*common_decl_types],
|
|
||||||
includes=[],
|
|
||||||
types=[],
|
|
||||||
funcs=[]
|
|
||||||
)
|
|
||||||
|
|
||||||
source = CSource(
|
|
||||||
name=header.name,
|
|
||||||
decl_types=[*common_decl_types],
|
|
||||||
includes=[
|
|
||||||
CInclude(header, local=True, same_dir=True),
|
|
||||||
CInclude(
|
|
||||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
|
|
||||||
local=True
|
|
||||||
),
|
|
||||||
CInclude(header="stddef.h"),
|
|
||||||
],
|
|
||||||
internal_funcs=[],
|
|
||||||
funcs=header.funcs
|
|
||||||
)
|
|
||||||
|
|
||||||
for _type, dbl_list_data in datatypes.items():
|
|
||||||
type_string = get_datatype_string(_type)
|
|
||||||
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
|
|
||||||
type_string_upper = clean_type_string.upper()
|
|
||||||
type_string_lower = clean_type_string.lower()
|
|
||||||
|
|
||||||
node = CStruct(
|
|
||||||
name=dbl_list_data.node_typename,
|
|
||||||
cargs=[
|
|
||||||
CArg(name="item", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
node.cargs.extend([
|
|
||||||
CArg(name="prev", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
CArg(name="next", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
])
|
|
||||||
|
|
||||||
dl_list = CStruct(
|
|
||||||
name=dbl_list_data.list_typename,
|
|
||||||
cargs=[
|
|
||||||
CArg(name="first", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
CArg(name="last", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
|
||||||
CArg(name="node_count", _type=CType.U64),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
header.types.extend([node, dl_list])
|
|
||||||
header.decl_types.extend(dbl_list_data.hdr_decl_types)
|
|
||||||
source.decl_types.extend(dbl_list_data.src_decl_types)
|
|
||||||
if isinstance(_type, CType) and _type == CType.VOID:
|
|
||||||
# Don't define any functions for the generic node and list
|
|
||||||
continue
|
|
||||||
|
|
||||||
node_cmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_node",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
node_cppmacro = CMacro(
|
|
||||||
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
|
|
||||||
value=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_node_cpp",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
get_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_get",
|
|
||||||
ret_type=node,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
|
||||||
CArg(name="index", _type=CType.U64),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_get",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
push_front_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_push_front",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_push_front",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
push_back_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_push_back",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_push_back",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
insert_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_insert",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="index", _type=CType.U64),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_insert",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
pop_front_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_pop_front",
|
|
||||||
ret_type=node,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_pop_front",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
pop_back_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_pop_back",
|
|
||||||
ret_type=node,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_pop_back",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
remove_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_remove",
|
|
||||||
ret_type=node,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
CArg(name="index", _type=CType.U64),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_remove",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
pointer=CPointer(CPointerType.SINGLE),
|
|
||||||
)
|
|
||||||
|
|
||||||
empty_func = CFunc(
|
|
||||||
name=f"wapp_{type_string_lower}_list_empty",
|
|
||||||
ret_type=CType.VOID,
|
|
||||||
args=[
|
|
||||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "list_empty",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
node_to_list_func = CFunc(
|
|
||||||
name=f"{type_string_lower}_node_to_list",
|
|
||||||
ret_type=dl_list,
|
|
||||||
args=[
|
|
||||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
|
||||||
],
|
|
||||||
body=__format_func_body(
|
|
||||||
filename=snippets_dir / "node_to_list",
|
|
||||||
type_string=type_string,
|
|
||||||
type_string_upper=type_string_upper,
|
|
||||||
type_string_lower=type_string_lower,
|
|
||||||
node_typename=dbl_list_data.node_typename,
|
|
||||||
list_typename=dbl_list_data.list_typename
|
|
||||||
),
|
|
||||||
qualifiers=[CQualifier.INTERNAL],
|
|
||||||
)
|
|
||||||
|
|
||||||
header.c_macros.append(node_cmacro)
|
|
||||||
header.cpp_macros.append(node_cppmacro)
|
|
||||||
header.funcs.extend([
|
|
||||||
get_func,
|
|
||||||
push_front_func,
|
|
||||||
push_back_func,
|
|
||||||
insert_func,
|
|
||||||
pop_front_func,
|
|
||||||
pop_back_func,
|
|
||||||
remove_func,
|
|
||||||
empty_func,
|
|
||||||
])
|
|
||||||
|
|
||||||
source.internal_funcs.append(node_to_list_func)
|
|
||||||
source.funcs = header.funcs
|
|
||||||
|
|
||||||
header.save(out_dir)
|
|
||||||
source.save(out_dir)
|
|
@@ -1,6 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
|
||||||
|
|
||||||
u64 count = list->node_count;
|
|
||||||
for (u64 i = 0; i < count; ++i) {{
|
|
||||||
wapp_{Tlower}_list_pop_back(list);
|
|
||||||
}}
|
|
@@ -1,11 +0,0 @@
|
|||||||
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
|
|
||||||
|
|
||||||
{NodeType} *output = NULL;
|
|
||||||
{NodeType} *current = list->first;
|
|
||||||
for (u64 i = 1; i <= index; ++i) {{
|
|
||||||
current = current->next;
|
|
||||||
}}
|
|
||||||
|
|
||||||
output = current;
|
|
||||||
|
|
||||||
return output;
|
|
@@ -1,26 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
|
||||||
|
|
||||||
if (index == 0) {{
|
|
||||||
wapp_{Tlower}_list_push_front(list, node);
|
|
||||||
return;
|
|
||||||
}} else if (index == list->node_count) {{
|
|
||||||
wapp_{Tlower}_list_push_back(list, node);
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
|
|
||||||
{NodeType} *dst_node = wapp_{Tlower}_list_get(list, index);
|
|
||||||
if (!dst_node) {{
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
|
|
||||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
|
||||||
|
|
||||||
{NodeType} *prev = dst_node->prev;
|
|
||||||
|
|
||||||
dst_node->prev = node_list.last;
|
|
||||||
prev->next = node_list.first;
|
|
||||||
|
|
||||||
node_list.first->prev = prev;
|
|
||||||
node_list.last->next = dst_node;
|
|
@@ -1 +0,0 @@
|
|||||||
(({NodeType}){{.item = ITEM_PTR}})
|
|
@@ -1 +0,0 @@
|
|||||||
{NodeType}{{ITEM_PTR, nullptr, nullptr}}
|
|
@@ -1,22 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
|
||||||
|
|
||||||
{NodeType} *output = NULL;
|
|
||||||
|
|
||||||
if (list->node_count == 0) {{
|
|
||||||
goto RETURN_{Tupper}_LIST_POP_BACK;
|
|
||||||
}}
|
|
||||||
|
|
||||||
output = list->last;
|
|
||||||
|
|
||||||
if (list->node_count == 1) {{
|
|
||||||
*list = ({ListType}){{0}};
|
|
||||||
goto RETURN_{Tupper}_LIST_POP_BACK;
|
|
||||||
}}
|
|
||||||
|
|
||||||
--(list->node_count);
|
|
||||||
list->last = output->prev;
|
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
|
||||||
|
|
||||||
RETURN_{Tupper}_LIST_POP_BACK:
|
|
||||||
return output;
|
|
@@ -1,22 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
|
||||||
|
|
||||||
{NodeType} *output = NULL;
|
|
||||||
|
|
||||||
if (list->node_count == 0) {{
|
|
||||||
goto RETURN_{Tupper}_LIST_POP_FRONT;
|
|
||||||
}}
|
|
||||||
|
|
||||||
output = list->first;
|
|
||||||
|
|
||||||
if (list->node_count == 1) {{
|
|
||||||
*list = ({ListType}){{0}};
|
|
||||||
goto RETURN_{Tupper}_LIST_POP_FRONT;
|
|
||||||
}}
|
|
||||||
|
|
||||||
--(list->node_count);
|
|
||||||
list->first = output->next;
|
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
|
||||||
|
|
||||||
RETURN_{Tupper}_LIST_POP_FRONT:
|
|
||||||
return output;
|
|
@@ -1,18 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
|
||||||
|
|
||||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
|
||||||
|
|
||||||
if (list->node_count == 0) {{
|
|
||||||
*list = node_list;
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
|
||||||
|
|
||||||
{NodeType} *last = list->last;
|
|
||||||
if (last) {{
|
|
||||||
last->next = node_list.first;
|
|
||||||
}}
|
|
||||||
|
|
||||||
list->last = node_list.last;
|
|
||||||
node_list.first->prev = last;
|
|
@@ -1,18 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
|
||||||
|
|
||||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
|
||||||
|
|
||||||
if (list->node_count == 0) {{
|
|
||||||
*list = node_list;
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
|
||||||
|
|
||||||
{NodeType} *first = list->first;
|
|
||||||
if (first) {{
|
|
||||||
first->prev = node_list.last;
|
|
||||||
}}
|
|
||||||
|
|
||||||
list->first = node_list.first;
|
|
||||||
node_list.last->next = first;
|
|
@@ -1,26 +0,0 @@
|
|||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
|
||||||
|
|
||||||
{NodeType} *output = NULL;
|
|
||||||
|
|
||||||
if (index == 0) {{
|
|
||||||
output = wapp_{Tlower}_list_pop_front(list);
|
|
||||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
|
||||||
}} else if (index == list->node_count) {{
|
|
||||||
output = wapp_{Tlower}_list_pop_back(list);
|
|
||||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
|
||||||
}}
|
|
||||||
|
|
||||||
output = wapp_{Tlower}_list_get(list, index);
|
|
||||||
if (!output) {{
|
|
||||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
|
||||||
}}
|
|
||||||
|
|
||||||
output->prev->next = output->next;
|
|
||||||
output->next->prev = output->prev;
|
|
||||||
|
|
||||||
--(list->node_count);
|
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
|
||||||
|
|
||||||
RETURN_{Tupper}_LIST_REMOVE:
|
|
||||||
return output;
|
|
@@ -1,13 +0,0 @@
|
|||||||
{ListType} output = {{.first = node, .last = node, .node_count = 1}};
|
|
||||||
|
|
||||||
while (output.first->prev != NULL) {{
|
|
||||||
output.first = output.first->prev;
|
|
||||||
++(output.node_count);
|
|
||||||
}}
|
|
||||||
|
|
||||||
while (output.last->next != NULL) {{
|
|
||||||
output.last = output.last->next;
|
|
||||||
++(output.node_count);
|
|
||||||
}}
|
|
||||||
|
|
||||||
return output;
|
|
@@ -1,18 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def load_func_body_from_file(filename: Path) -> str:
|
|
||||||
with open(filename, "r") as infile:
|
|
||||||
return infile.read().rstrip()
|
|
||||||
|
|
||||||
|
|
||||||
def convert_to_relative(path: Path, target: Path) -> Path:
|
|
||||||
major = sys.version_info.major
|
|
||||||
minor = sys.version_info.minor
|
|
||||||
|
|
||||||
if major >= 3 and minor >= 12:
|
|
||||||
return path.relative_to(target, walk_up=True)
|
|
||||||
else:
|
|
||||||
return Path(os.path.relpath(str(path), start=str(target)))
|
|
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"dbl_list_data": {
|
|
||||||
"CustomType": {
|
|
||||||
"node_typename": "CustomTypeNode",
|
|
||||||
"list_typename": "CustomTypeList",
|
|
||||||
"hdr_decl_types": [
|
|
||||||
{
|
|
||||||
"name": "custom_type",
|
|
||||||
"cargs": [],
|
|
||||||
"typedef_name": "CustomType"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src_decl_types": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"array_data": {
|
|
||||||
"CustomType": {
|
|
||||||
"array_typename": "CustomTypeArray",
|
|
||||||
"hdr_decl_types": [
|
|
||||||
{
|
|
||||||
"name": "custom_type",
|
|
||||||
"cargs": [],
|
|
||||||
"typedef_name": "CustomType"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src_decl_types": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
61
compile
Executable file
61
compile
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_TYPE="debug"
|
||||||
|
|
||||||
|
while [[ $# > 0 ]];do
|
||||||
|
case $1 in
|
||||||
|
--release)
|
||||||
|
BUILD_TYPE="release"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*|-*|--*)
|
||||||
|
echo "Unknown option $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
CC=clang
|
||||||
|
CFLAGS="-Wall -Werror -pedantic"
|
||||||
|
LIBFLAGS="-fPIC -shared"
|
||||||
|
|
||||||
|
INCLUDE="$(find src -type d | xargs -I{} echo -n "-I{} ")"
|
||||||
|
SRC="$(find src -type f -name "*.c" | xargs -I{} echo -n "{} ")"
|
||||||
|
|
||||||
|
TEST_INCLUDE="$(find tests -type d | xargs -I{} echo -n "-I{} ")"
|
||||||
|
TEST_SRC="$(find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")"
|
||||||
|
|
||||||
|
BUILD_DIR="libwapp-build/posix-$BUILD_TYPE"
|
||||||
|
if [[ -d $BUILD_DIR ]]; then
|
||||||
|
rm -rf $BUILD_DIR
|
||||||
|
fi
|
||||||
|
mkdir -p $BUILD_DIR
|
||||||
|
|
||||||
|
if [[ $BUILD_TYPE == "release" ]]; then
|
||||||
|
CFLAGS+=" -O3"
|
||||||
|
else
|
||||||
|
CFLAGS+=" -g -fsanitize=address -fsanitize=undefined"
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUT="$BUILD_DIR/libwapp.so"
|
||||||
|
TEST_OUT="$BUILD_DIR/wapptest"
|
||||||
|
|
||||||
|
# Compile tests
|
||||||
|
if [[ $(echo $TEST_SRC | xargs) != "" ]]; then
|
||||||
|
(set -x ; $CC $CFLAGS $INCLUDE $TEST_INCLUDE $SRC $TEST_SRC -o $TEST_OUT)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run tests and exit on failure
|
||||||
|
if [[ -f $TEST_OUT ]]; then
|
||||||
|
$TEST_OUT
|
||||||
|
STATUS="$?"
|
||||||
|
|
||||||
|
rm $TEST_OUT
|
||||||
|
|
||||||
|
if [[ $STATUS != "0" ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compile library
|
||||||
|
(set -x ; $CC $CFLAGS $LIBFLAGS $INCLUDE $SRC -o $OUT)
|
@@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(dirname $0)"
|
|
||||||
LIB_SRC="$1"
|
|
||||||
INSTALL_PREFIX="$2"
|
|
||||||
shift 2
|
|
||||||
INCLUDES="$@"
|
|
||||||
|
|
||||||
mkdir -p "$INSTALL_PREFIX"
|
|
||||||
|
|
||||||
BASE_INCLUDE_DIR="$(dirname "$LIB_SRC")"
|
|
||||||
find $BASE_INCLUDE_DIR -maxdepth 1 -type f -name "*.h" -exec cp -v {} "$INSTALL_PREFIX" \;
|
|
||||||
|
|
||||||
cd "$SCRIPT_DIR/../src"
|
|
||||||
for INCLUDE in $INCLUDES; do
|
|
||||||
for f in $(find "$INCLUDE" -type f -name "*.h"); do
|
|
||||||
DST="$INSTALL_PREFIX/$(dirname $f)"
|
|
||||||
mkdir -p "$DST"
|
|
||||||
cp -v "$f" "$DST"
|
|
||||||
done
|
|
||||||
done
|
|
@@ -1,47 +1,13 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef ALIASES_H
|
#ifndef ALIASES_H
|
||||||
#define ALIASES_H
|
#define ALIASES_H
|
||||||
|
|
||||||
#include "../platform/platform.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
|
||||||
#include <uchar.h>
|
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
|
||||||
#define c8 char8_t
|
|
||||||
#else
|
|
||||||
#define c8 uint8_t
|
|
||||||
#endif // !WAPP_PLATFORM_C23_VERSION
|
|
||||||
|
|
||||||
#define c16 char16_t
|
|
||||||
#define c32 char32_t
|
|
||||||
#else
|
|
||||||
#define c8 uint8_t
|
|
||||||
#define c16 uint16_t
|
|
||||||
#define c32 uint32_t
|
|
||||||
#endif // !WAPP_PLATFORM_C11_VERSION
|
|
||||||
|
|
||||||
#define u8 uint8_t
|
#define u8 uint8_t
|
||||||
#define u16 uint16_t
|
#define u16 uint16_t
|
||||||
#define u32 uint32_t
|
#define u32 uint32_t
|
||||||
#define u64 uint64_t
|
#define u64 uint64_t
|
||||||
|
|
||||||
#define b32 uint32_t
|
|
||||||
|
|
||||||
#ifndef WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifndef false
|
|
||||||
#define false (b32)0
|
|
||||||
#endif // !false
|
|
||||||
|
|
||||||
#ifndef true
|
|
||||||
#define true (b32)1
|
|
||||||
#endif // !true
|
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#define i8 int8_t
|
#define i8 int8_t
|
||||||
#define i16 int16_t
|
#define i16 int16_t
|
||||||
#define i32 int32_t
|
#define i32 int32_t
|
||||||
@@ -54,14 +20,14 @@
|
|||||||
#define uptr uintptr_t
|
#define uptr uintptr_t
|
||||||
#define iptr intptr_t
|
#define iptr intptr_t
|
||||||
|
|
||||||
#define wapp_extern extern
|
#define external extern
|
||||||
#define wapp_intern static
|
#define internal static
|
||||||
#define wapp_persist static
|
#define persistent static
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
#define wapp_class_mem static
|
#define class_mem static
|
||||||
#define BEGIN_C_LINKAGE extern "C" {
|
#define BEGIN_C_LINKAGE extern "C" {
|
||||||
#define END_C_LINKAGE }
|
#define END_C_LINKAGE }
|
||||||
#endif // WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !ALIASES_H
|
#endif // !ALIASES_H
|
||||||
|
@@ -1,41 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef WAPP_ASSERT_H
|
|
||||||
#define WAPP_ASSERT_H
|
|
||||||
|
|
||||||
#include "../aliases/aliases.h"
|
|
||||||
#include "../platform/platform.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
|
||||||
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
|
||||||
|
|
||||||
#ifdef WAPP_DEBUG_ASSERT
|
|
||||||
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
|
||||||
#else
|
|
||||||
#define wapp_debug_assert(EXPR, MSG)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
|
||||||
if (!(EXPR)) { \
|
|
||||||
fprintf( \
|
|
||||||
stderr, \
|
|
||||||
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
|
||||||
__FILE__, __LINE__, __func__, \
|
|
||||||
EXPR, MSG \
|
|
||||||
); \
|
|
||||||
abort(); \
|
|
||||||
} \
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !WAPP_ASSERT_H
|
|
@@ -1,13 +1,7 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef MISC_UTILS_H
|
#ifndef MISC_UTILS_H
|
||||||
#define MISC_UTILS_H
|
#define MISC_UTILS_H
|
||||||
|
|
||||||
#include "../aliases/aliases.h"
|
#include "aliases.h"
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#define KB(SIZE) (SIZE * 1024ull)
|
#define KB(SIZE) (SIZE * 1024ull)
|
||||||
#define MB(SIZE) (KB(SIZE) * 1024)
|
#define MB(SIZE) (KB(SIZE) * 1024)
|
||||||
@@ -16,41 +10,4 @@ BEGIN_C_LINKAGE
|
|||||||
|
|
||||||
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||||
|
|
||||||
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
|
||||||
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
|
||||||
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
|
|
||||||
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
|
||||||
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
|
|
||||||
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
|
||||||
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
|
||||||
( \
|
|
||||||
U64_RSHIFT_OR_32( \
|
|
||||||
U64_RSHIFT_OR_16( \
|
|
||||||
U64_RSHIFT_OR_8( \
|
|
||||||
U64_RSHIFT_OR_4( \
|
|
||||||
U64_RSHIFT_OR_2( \
|
|
||||||
U64_RSHIFT_OR_1(X - 1) \
|
|
||||||
) \
|
|
||||||
) \
|
|
||||||
) \
|
|
||||||
) \
|
|
||||||
) \
|
|
||||||
) + 1 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
#define wapp_misc_utils_va_args_count(T, ...) va_args_count<T>(__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define wapp_misc_utils_va_args_count(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
constexpr u64 va_args_count(Args&&...) {
|
|
||||||
return sizeof...(Args);
|
|
||||||
}
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !MISC_UTILS_H
|
#endif // !MISC_UTILS_H
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef PLATFORM_H
|
#ifndef PLATFORM_H
|
||||||
#define PLATFORM_H
|
#define PLATFORM_H
|
||||||
|
|
||||||
@@ -60,55 +58,4 @@
|
|||||||
#error "Unrecognised platform"
|
#error "Unrecognised platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define WAPP_PLATFORM_CPP
|
|
||||||
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
|
||||||
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
|
||||||
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
|
||||||
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
|
||||||
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
|
||||||
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
|
||||||
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
|
||||||
|
|
||||||
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP98
|
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP11
|
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP14
|
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP17
|
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP20
|
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
|
||||||
#define WAPP_PLATFORM_CPP23
|
|
||||||
#else
|
|
||||||
#error "Unrecognised C++ version"
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define WAPP_PLATFORM_C
|
|
||||||
|
|
||||||
#if defined(__STDC_VERSION__)
|
|
||||||
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
|
||||||
#define WAPP_PLATFORM_C99_VERSION 199901L
|
|
||||||
#define WAPP_PLATFORM_C11_VERSION 201112L
|
|
||||||
#define WAPP_PLATFORM_C17_VERSION 201710L
|
|
||||||
#define WAPP_PLATFORM_C23_VERSION 202311L
|
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
|
||||||
#define WAPP_PLATFORM_C99
|
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
|
||||||
#define WAPP_PLATFORM_C11
|
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
|
||||||
#define WAPP_PLATFORM_C17
|
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
|
||||||
#define WAPP_PLATFORM_C23
|
|
||||||
#else
|
|
||||||
#error "Unrecognised C version"
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define WAPP_PLATFORM_C89
|
|
||||||
#endif
|
|
||||||
#endif // !__cplusplus
|
|
||||||
|
|
||||||
#endif // !PLATFORM_H
|
#endif // !PLATFORM_H
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef WAPP_COMMON_H
|
|
||||||
#define WAPP_COMMON_H
|
|
||||||
|
|
||||||
#include "aliases/aliases.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "misc/misc_utils.h"
|
|
||||||
#include "platform/platform.h"
|
|
||||||
|
|
||||||
#endif // !WAPP_COMMON_H
|
|
@@ -1,103 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "../os/cpath/cpath.h"
|
|
||||||
#include "../../common/assert/assert.h"
|
|
||||||
#include "../../common/aliases/aliases.h"
|
|
||||||
#include "../../primitives/array/array.h"
|
|
||||||
#include "../../primitives/strings/str8/str8.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
File *wapp_file_open(Str8RO *filepath, FileAccessMode mode) {
|
|
||||||
wapp_persist const char *modes[FILE_ACCESS_MODE_COUNT] = {
|
|
||||||
[WAPP_FA_MODE_R] = "r",
|
|
||||||
[WAPP_FA_MODE_W] = "w",
|
|
||||||
[WAPP_FA_MODE_A] = "a",
|
|
||||||
[WAPP_FA_MODE_R_EX] = "r+",
|
|
||||||
[WAPP_FA_MODE_W_EX] = "w+",
|
|
||||||
[WAPP_FA_MODE_A_EX] = "a+",
|
|
||||||
[WAPP_FA_MODE_RB] = "rb",
|
|
||||||
[WAPP_FA_MODE_WB] = "wb",
|
|
||||||
[WAPP_FA_MODE_AB] = "ab",
|
|
||||||
[WAPP_FA_MODE_RB_EX] = "rb+",
|
|
||||||
[WAPP_FA_MODE_WB_EX] = "wb+",
|
|
||||||
[WAPP_FA_MODE_AB_EX] = "ab+",
|
|
||||||
[WAPP_FA_MODE_WX] = "wx",
|
|
||||||
[WAPP_FA_MODE_WX_EX] = "wx+",
|
|
||||||
[WAPP_FA_MODE_WBX] = "wbx",
|
|
||||||
[WAPP_FA_MODE_WBX_EX] = "wbx+",
|
|
||||||
};
|
|
||||||
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
|
||||||
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
|
|
||||||
|
|
||||||
memset(tmp, 0, WAPP_PATH_MAX);
|
|
||||||
memcpy(tmp, filepath->buf, filepath->size);
|
|
||||||
|
|
||||||
return fopen((const char *)tmp, modes[mode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 wapp_file_get_current_position(File *file) {
|
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
|
||||||
return (u64)ftell(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin) {
|
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
|
||||||
return fseek(file, offset, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 wapp_file_get_length(File *file) {
|
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
|
||||||
|
|
||||||
u64 current = wapp_file_get_current_position(file);
|
|
||||||
|
|
||||||
wapp_file_seek(file, 0, WAPP_SEEK_END);
|
|
||||||
|
|
||||||
u64 output = ftell(file);
|
|
||||||
|
|
||||||
// Restore position
|
|
||||||
wapp_file_seek(file, current, WAPP_SEEK_START);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count) {
|
|
||||||
wapp_debug_assert(dst != NULL && dst->items != NULL && file != NULL,
|
|
||||||
"`dst`, `dst->items` and `file` should not be NULL.");
|
|
||||||
|
|
||||||
u64 file_length = wapp_file_get_length(file);
|
|
||||||
u64 dst_byte_capacity = dst->item_size * dst->capacity;
|
|
||||||
u64 req_byte_count = item_count * dst->item_size;
|
|
||||||
u64 copy_byte_count = 0;
|
|
||||||
|
|
||||||
if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) {
|
|
||||||
copy_byte_count = req_byte_count;
|
|
||||||
} else {
|
|
||||||
copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst->count = fread(dst->items, sizeof(u8), copy_byte_count, file) / dst->item_size;
|
|
||||||
|
|
||||||
return dst->count;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count) {
|
|
||||||
wapp_debug_assert(src != NULL && src->items != NULL && file != NULL,
|
|
||||||
"`src`, `src->items` and `file` should not be NULL.");
|
|
||||||
|
|
||||||
u64 src_byte_count = src->count * src->item_size;
|
|
||||||
u64 req_byte_count = item_count * src->item_size;
|
|
||||||
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
|
|
||||||
|
|
||||||
return fwrite(src->items, sizeof(u8), to_copy, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
i32 wapp_file_flush(File *file) {
|
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
|
||||||
return fflush(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
i32 wapp_file_close(File *file) {
|
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
|
||||||
return fclose(file);
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef FILE_H
|
|
||||||
#define FILE_H
|
|
||||||
|
|
||||||
#include "../../common/aliases/aliases.h"
|
|
||||||
#include "../../primitives/array/array.h"
|
|
||||||
#include "../../primitives/strings/str8/str8.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
#define wapp_file_item_to_array(ITEM) (GenericArray{&(ITEM), 1, 1, sizeof(ITEM)})
|
|
||||||
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
|
|
||||||
*((TYPE *)((ARRAY).items)) : \
|
|
||||||
TYPE{})
|
|
||||||
#else
|
|
||||||
#define wapp_file_item_to_array(ITEM) ((GenericArray){.items = &(ITEM), \
|
|
||||||
.count = 1, \
|
|
||||||
.capacity = 1, \
|
|
||||||
.item_size = sizeof(ITEM)})
|
|
||||||
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
|
|
||||||
*((TYPE *)((ARRAY).items)) : \
|
|
||||||
(TYPE){0})
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
typedef FILE File;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
WAPP_FA_MODE_R, // Equivalent to r
|
|
||||||
WAPP_FA_MODE_W, // Equivalent to w
|
|
||||||
WAPP_FA_MODE_A, // Equivalent to a
|
|
||||||
WAPP_FA_MODE_R_EX, // Equivalent to r+
|
|
||||||
WAPP_FA_MODE_W_EX, // Equivalent to w+
|
|
||||||
WAPP_FA_MODE_A_EX, // Equivalent to a+
|
|
||||||
WAPP_FA_MODE_RB, // Equivalent to rb
|
|
||||||
WAPP_FA_MODE_WB, // Equivalent to wb
|
|
||||||
WAPP_FA_MODE_AB, // Equivalent to ab
|
|
||||||
WAPP_FA_MODE_RB_EX, // Equivalent to rb+
|
|
||||||
WAPP_FA_MODE_WB_EX, // Equivalent to wb+
|
|
||||||
WAPP_FA_MODE_AB_EX, // Equivalent to ab+
|
|
||||||
WAPP_FA_MODE_WX, // Equivalent to wx
|
|
||||||
WAPP_FA_MODE_WX_EX, // Equivalent to wx+
|
|
||||||
WAPP_FA_MODE_WBX, // Equivalent to wbx
|
|
||||||
WAPP_FA_MODE_WBX_EX, // Equivalent to wbx+
|
|
||||||
|
|
||||||
FILE_ACCESS_MODE_COUNT,
|
|
||||||
} FileAccessMode;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
WAPP_SEEK_START = SEEK_SET,
|
|
||||||
WAPP_SEEK_CURRENT = SEEK_CUR,
|
|
||||||
WAPP_SEEK_END = SEEK_END,
|
|
||||||
} FileSeekOrigin;
|
|
||||||
|
|
||||||
File *wapp_file_open(Str8RO *filename, FileAccessMode mode);
|
|
||||||
u64 wapp_file_get_current_position(File *file);
|
|
||||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin);
|
|
||||||
u64 wapp_file_get_length(File *file);
|
|
||||||
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count);
|
|
||||||
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count);
|
|
||||||
i32 wapp_file_flush(File *file);
|
|
||||||
i32 wapp_file_close(File *file);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !FILE_H
|
|
@@ -1,35 +1,49 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "mem_allocator.h"
|
#include "mem_allocator.h"
|
||||||
#include "../../common/aliases/aliases.h"
|
|
||||||
#include "../../common/assert/assert.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Allocator API definitions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
|
if (!allocator || !(allocator->alloc)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return allocator->alloc(size, allocator->obj);
|
return allocator->alloc(size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
|
if (!allocator || !(allocator->alloc_aligned)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
|
if (!allocator || !(allocator->realloc)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||||
u64 new_size, u64 alignment) {
|
u64 new_size, u64 alignment) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
|
if (!allocator || !(allocator->realloc_aligned)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr) {
|
||||||
if (!allocator || !(allocator->free)) {
|
if (!allocator || !(allocator->free)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator->free(ptr, size, allocator->obj);
|
allocator->free(ptr, allocator->obj);
|
||||||
}
|
}
|
55
src/core/mem/allocator/mem_allocator.h
Normal file
55
src/core/mem/allocator/mem_allocator.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef MEM_ALLOCATOR_H
|
||||||
|
#define MEM_ALLOCATOR_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Allocator function pointer types
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
|
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
||||||
|
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
|
||||||
|
typedef void *(MemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||||
|
typedef void *(MemReallocAlignedFunc)(void *ptr, u64 old_size, u64 new_size, u64 alignment, void *alloc_obj);
|
||||||
|
typedef void(MemFreeFunc)(void **ptr, void *alloc_obj);
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Allocator type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
|
typedef struct allocator Allocator;
|
||||||
|
struct allocator {
|
||||||
|
void *obj;
|
||||||
|
MemAllocFunc *alloc;
|
||||||
|
MemAllocAlignedFunc *alloc_aligned;
|
||||||
|
MemReallocFunc *realloc;
|
||||||
|
MemReallocAlignedFunc *realloc_aligned;
|
||||||
|
MemFreeFunc *free;
|
||||||
|
};
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Allocator API declarations
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
|
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size);
|
||||||
|
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment);
|
||||||
|
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size);
|
||||||
|
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||||
|
u64 new_size, u64 alignment);
|
||||||
|
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !MEM_ALLOCATOR_H
|
@@ -1,11 +1,8 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "mem_arena.h"
|
#include "mem_arena.h"
|
||||||
#include "../utils/mem_utils.h"
|
#include "aliases.h"
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "misc_utils.h"
|
||||||
#include "../../../common/assert/assert.h"
|
#include "mem_utils.h"
|
||||||
#include "../../../common/misc/misc_utils.h"
|
#include <stdbool.h>
|
||||||
#include "../../os/mem/mem_os.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -21,14 +18,14 @@ struct arena {
|
|||||||
u8 *buf;
|
u8 *buf;
|
||||||
u8 *offset;
|
u8 *offset;
|
||||||
u64 capacity;
|
u64 capacity;
|
||||||
b32 committed;
|
bool committed;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(b32));
|
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(bool));
|
||||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||||
};
|
};
|
||||||
|
|
||||||
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
|
bool wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, bool zero_buffer) {
|
||||||
if (!arena || *arena || base_capacity == 0) {
|
if (!arena || *arena || base_capacity == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -39,11 +36,7 @@ b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags f
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 arena_capacity = wapp_misc_utils_u64_round_up_pow2(
|
u64 arena_capacity = base_capacity >= ARENA_MINIMUM_CAPACITY ? base_capacity : ARENA_MINIMUM_CAPACITY;
|
||||||
base_capacity >= ARENA_MINIMUM_CAPACITY ?
|
|
||||||
base_capacity :
|
|
||||||
ARENA_MINIMUM_CAPACITY
|
|
||||||
);
|
|
||||||
|
|
||||||
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
||||||
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
||||||
@@ -65,7 +58,9 @@ void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
if (!arena) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
u8 *alloc_start = arena->offset;
|
u8 *alloc_start = arena->offset;
|
||||||
|
|
||||||
@@ -78,13 +73,13 @@ void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
|||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
if (!(arena->committed)) {
|
if (!(arena->committed)) {
|
||||||
wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
output = (u8 *)wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
||||||
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
||||||
WAPP_MEM_INIT_UNINITIALISED);
|
WAPP_MEM_INIT_INITIALISED);
|
||||||
}
|
}
|
||||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
#else
|
||||||
|
|
||||||
memset(output, 0, size);
|
memset(output, 0, size);
|
||||||
|
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
return (void *)output;
|
return (void *)output;
|
||||||
}
|
}
|
||||||
@@ -124,14 +119,18 @@ void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_clear(Arena *arena) {
|
void wapp_mem_arena_clear(Arena *arena) {
|
||||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
if (!arena) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(arena->buf, 0, arena->offset - arena->buf);
|
memset(arena->buf, 0, arena->offset - arena->buf);
|
||||||
arena->offset = arena->buf;
|
arena->offset = arena->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_destroy(Arena **arena) {
|
void wapp_mem_arena_destroy(Arena **arena) {
|
||||||
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
|
if (!arena) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Arena *arena_ptr = *arena;
|
Arena *arena_ptr = *arena;
|
||||||
if (arena_ptr->buf) {
|
if (arena_ptr->buf) {
|
||||||
|
@@ -1,15 +1,13 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef MEM_ARENA_H
|
#ifndef MEM_ARENA_H
|
||||||
#define MEM_ARENA_H
|
#define MEM_ARENA_H
|
||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "aliases.h"
|
||||||
#include "../../../common/platform/platform.h"
|
#include "mem_utils.h"
|
||||||
#include "../../os/mem/mem_os.h"
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
typedef struct arena Arena;
|
typedef struct arena Arena;
|
||||||
|
|
||||||
@@ -27,7 +25,7 @@ typedef struct arena Arena;
|
|||||||
* control over how the Arena is initialised. Wrapper macros are provided for
|
* control over how the Arena is initialised. Wrapper macros are provided for
|
||||||
* easier use.
|
* easier use.
|
||||||
*/
|
*/
|
||||||
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 zero_buffer);
|
bool wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, bool zero_buffer);
|
||||||
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
||||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
|
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
|
||||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size);
|
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size);
|
||||||
@@ -35,8 +33,8 @@ void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64
|
|||||||
void wapp_mem_arena_clear(Arena *arena);
|
void wapp_mem_arena_clear(Arena *arena);
|
||||||
void wapp_mem_arena_destroy(Arena **arena);
|
void wapp_mem_arena_destroy(Arena **arena);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !MEM_ARENA_H
|
#endif // !MEM_ARENA_H
|
||||||
|
@@ -1,20 +1,27 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "mem_arena_allocator.h"
|
#include "mem_arena_allocator.h"
|
||||||
#include "mem_arena.h"
|
#include "mem_arena.h"
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../os/mem/mem_os.h"
|
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_alloc(u64 size, void *alloc_obj);
|
/***************************************************************************/ //
|
||||||
wapp_intern inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
wapp_intern inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
////// Arena Allocator wrappers declarations
|
||||||
wapp_intern inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
|
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj);
|
||||||
|
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
||||||
|
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||||
|
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||||
void *alloc_obj);
|
void *alloc_obj);
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Arena Allocator API definitions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
|
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, bool zero_buffer) {
|
||||||
Allocator allocator = {0};
|
Allocator allocator = {0};
|
||||||
b32 initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
bool initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
||||||
if (!initialised) {
|
if (!initialised) {
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
@@ -36,23 +43,28 @@ void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
|||||||
*allocator = (Allocator){0};
|
*allocator = (Allocator){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/ //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// Arena Allocator wrappers definitions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/***************************************************************************/ //
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_alloc(arena, size);
|
return wapp_mem_arena_alloc(arena, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||||
void *alloc_obj) {
|
void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
||||||
|
@@ -1,16 +1,14 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef MEM_ARENA_ALLOCATOR_H
|
#ifndef MEM_ARENA_ALLOCATOR_H
|
||||||
#define MEM_ARENA_ALLOCATOR_H
|
#define MEM_ARENA_ALLOCATOR_H
|
||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "aliases.h"
|
||||||
#include "../../../common/platform/platform.h"
|
#include "mem_utils.h"
|
||||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
#include "mem_allocator.h"
|
||||||
#include "../../os/mem/mem_os.h"
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#define wapp_mem_arena_allocator_init(base_capacity) \
|
#define wapp_mem_arena_allocator_init(base_capacity) \
|
||||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
||||||
@@ -32,12 +30,12 @@ BEGIN_C_LINKAGE
|
|||||||
* The `wapp_mem_arena_allocator_init_custom` provides the most control over how
|
* The `wapp_mem_arena_allocator_init_custom` provides the most control over how
|
||||||
* the Arena is initialised. Wrapper macros are provided for easier use.
|
* the Arena is initialised. Wrapper macros are provided for easier use.
|
||||||
*/
|
*/
|
||||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b32 zero_buffer);
|
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, bool zero_buffer);
|
||||||
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
||||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !MEM_ARENA_ALLOCATOR_H
|
#endif // !MEM_ARENA_ALLOCATOR_H
|
||||||
|
62
src/core/mem/libc/mem_libc_allocator.c
Normal file
62
src/core/mem/libc/mem_libc_allocator.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "mem_libc_allocator.h"
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "mem_allocator.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
internal inline void *mem_libc_alloc(u64 size, void *alloc_obj);
|
||||||
|
// TODO (Abdelrahman): aligned_alloc isn't implemented on Windows. Revisit later
|
||||||
|
#if 0
|
||||||
|
internal inline void *mem_libc_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
||||||
|
#endif
|
||||||
|
internal inline void *mem_libc_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||||
|
internal inline void mem_libc_free(void **ptr, void *alloc_obj);
|
||||||
|
|
||||||
|
Allocator wapp_mem_libc_allocator(void) {
|
||||||
|
return (Allocator){
|
||||||
|
.obj = NULL,
|
||||||
|
.alloc = mem_libc_alloc,
|
||||||
|
.alloc_aligned = NULL,
|
||||||
|
.realloc = mem_libc_realloc,
|
||||||
|
.realloc_aligned = NULL,
|
||||||
|
.free = mem_libc_free,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline void *mem_libc_alloc(u64 size, void *alloc_obj) {
|
||||||
|
(void)alloc_obj; // Silence unused warnings
|
||||||
|
return calloc(1, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
internal inline void *mem_libc_alloc_aligned(u64 size, u64 alignment,
|
||||||
|
void *alloc_obj) {
|
||||||
|
(void)alloc_obj; // Silence unused warnings
|
||||||
|
|
||||||
|
void *output = aligned_alloc(alignment, size);
|
||||||
|
if (output) {
|
||||||
|
memset(output, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal inline void *mem_libc_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
||||||
|
// Silence unused warnings
|
||||||
|
(void)alloc_obj;
|
||||||
|
(void)new_size;
|
||||||
|
|
||||||
|
return realloc(ptr, old_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline void mem_libc_free(void **ptr, void *alloc_obj) {
|
||||||
|
(void)alloc_obj; // Silence unused warnings
|
||||||
|
|
||||||
|
if (!ptr || !(*ptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(*ptr);
|
||||||
|
*ptr = NULL;
|
||||||
|
}
|
16
src/core/mem/libc/mem_libc_allocator.h
Normal file
16
src/core/mem/libc/mem_libc_allocator.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef MEM_LIBC_H
|
||||||
|
#define MEM_LIBC_H
|
||||||
|
|
||||||
|
#include "mem_allocator.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
Allocator wapp_mem_libc_allocator(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !MEM_LIBC_H
|
@@ -1,26 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "mem_utils.h"
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/assert/assert.h"
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
wapp_intern b32 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
|
||||||
|
|
||||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
|
||||||
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
|
|
||||||
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
|
|
||||||
|
|
||||||
uptr p = (uptr)ptr;
|
|
||||||
uptr align = (uptr)alignment;
|
|
||||||
|
|
||||||
// Similar to p % align, but it's a faster implementation that works fine
|
|
||||||
// because align is guaranteed to be a power of 2
|
|
||||||
uptr modulo = p & (align - 1);
|
|
||||||
|
|
||||||
if (modulo != 0) {
|
|
||||||
p += align - modulo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void *)p;
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef MEM_UTILS_H
|
|
||||||
#define MEM_UTILS_H
|
|
||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !MEM_UTILS_H
|
|
@@ -1,135 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "cpath.h"
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/misc/misc_utils.h"
|
|
||||||
#include "../../mem/arena/mem_arena_allocator.h"
|
|
||||||
#include "../../../primitives/dbl_list/dbl_list.h"
|
|
||||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
|
||||||
#include "../../../primitives/strings/str8/str8.h"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
|
||||||
if (!dst || !parts) {
|
|
||||||
return CPATH_JOIN_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parts->node_count == 0) {
|
|
||||||
return CPATH_JOIN_EMPTY_PARTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str8 separator = wapp_str8_buf(4);
|
|
||||||
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
|
||||||
|
|
||||||
u64 required_capacity = parts->node_count * separator.size + wapp_str8_list_total_size(parts);
|
|
||||||
if (dst->capacity < required_capacity) {
|
|
||||||
return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle first node
|
|
||||||
const Str8Node *first_node = wapp_str8_list_get(parts, 0);
|
|
||||||
wapp_str8_copy_str8_capped(dst, first_node->item);
|
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
|
||||||
// MSVC Spectre mitigation warnings
|
|
||||||
const Str8Node *node = first_node;
|
|
||||||
u64 node_index = 1;
|
|
||||||
b32 running = node_index < parts->node_count;
|
|
||||||
while (running && node->next) {
|
|
||||||
node = node->next;
|
|
||||||
if (node->item->size == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst->size > 0) {
|
|
||||||
char dst_last = wapp_str8_get(dst, dst->size - 1);
|
|
||||||
char node_start = wapp_str8_get(node->item, 0);
|
|
||||||
b32 add_path_sep = dst_last != WAPP_PATH_SEP && node_start != WAPP_PATH_SEP;
|
|
||||||
|
|
||||||
if (add_path_sep) {
|
|
||||||
wapp_str8_concat_capped(dst, &separator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_concat_capped(dst, node->item);
|
|
||||||
|
|
||||||
++node_index;
|
|
||||||
running = node_index < parts->node_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CPATH_JOIN_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
|
||||||
Str8 *output = NULL;
|
|
||||||
if (!allocator || !path) {
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 absolute = wapp_str8_get(path, 0) == WAPP_PATH_SEP;
|
|
||||||
Str8 separator = wapp_str8_buf(4);
|
|
||||||
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
|
||||||
|
|
||||||
if (path->size == 0) {
|
|
||||||
output = wapp_str8_alloc_buf(allocator, 16);
|
|
||||||
if (!output) {
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (levels < 1) {
|
|
||||||
output = wapp_str8_alloc_str8(allocator, path);
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
|
|
||||||
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
|
||||||
if (!parts) {
|
|
||||||
goto RETURN_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (levels >= parts->node_count) {
|
|
||||||
output = wapp_str8_alloc_buf(allocator, 16);
|
|
||||||
if (!output) {
|
|
||||||
goto LIST_CLEANUP_DIRUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
|
||||||
} else {
|
|
||||||
for (u64 i = 0; i < levels; ++i) {
|
|
||||||
wapp_str8_list_pop_back(parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 alignment = sizeof(void *) * 2;
|
|
||||||
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
|
|
||||||
u64 modulo = alloc_size & (alignment - 1);
|
|
||||||
alloc_size += alignment - modulo;
|
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
|
||||||
if (output) {
|
|
||||||
if (absolute) {
|
|
||||||
wapp_str8_push_back(output, WAPP_PATH_SEP);
|
|
||||||
}
|
|
||||||
|
|
||||||
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
|
||||||
if (joined) {
|
|
||||||
wapp_str8_concat_capped(output, joined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_CLEANUP_DIRUP:
|
|
||||||
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
|
||||||
|
|
||||||
RETURN_DIRUP:
|
|
||||||
return output;
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef CPATH_H
|
|
||||||
#define CPATH_H
|
|
||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/platform/platform.h"
|
|
||||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
|
||||||
#include "../../../primitives/strings/str8/str8.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
|
||||||
#include <limits.h>
|
|
||||||
#define WAPP_PATH_SEP '/'
|
|
||||||
#define WAPP_PATH_MAX PATH_MAX
|
|
||||||
#elif defined(WAPP_PLATFORM_WINDOWS)
|
|
||||||
#include <windows.h>
|
|
||||||
#define WAPP_PATH_SEP '\\'
|
|
||||||
#define WAPP_PATH_MAX MAX_PATH
|
|
||||||
#else
|
|
||||||
#error "Unrecognised platform"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define wapp_cpath_dirname(ALLOCATOR, PATH) dirup(ALLOCATOR, PATH, 1)
|
|
||||||
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
CPATH_JOIN_SUCCESS = 0,
|
|
||||||
CPATH_JOIN_INVALID_ARGS,
|
|
||||||
CPATH_JOIN_EMPTY_PARTS,
|
|
||||||
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
|
||||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !CPATH_H
|
|
@@ -1,30 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "mem_os.h"
|
|
||||||
#include "mem_os_ops.h"
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/platform/platform.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
|
||||||
#include "win/mem_os_win.h"
|
|
||||||
#elif defined(WAPP_PLATFORM_POSIX)
|
|
||||||
#include "posix/mem_os_posix.h"
|
|
||||||
#else
|
|
||||||
#error "Unrecognised platform"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
|
||||||
void *output = mem_util_allocate(addr, size, access, flags, type);
|
|
||||||
|
|
||||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
|
||||||
memset(output, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wapp_mem_util_free(void *ptr, u64 size) {
|
|
||||||
mem_util_free(ptr, size);
|
|
||||||
}
|
|
@@ -1,33 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef MEM_OS_H
|
|
||||||
#define MEM_OS_H
|
|
||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#include "mem_os_ops.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
|
||||||
#include "win/mem_os_win.h"
|
|
||||||
#elif defined(WAPP_PLATFORM_POSIX)
|
|
||||||
#include "posix/mem_os_posix.h"
|
|
||||||
#else
|
|
||||||
#error "Unrecognised platform"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
|
||||||
void wapp_mem_util_free(void *ptr, u64 size);
|
|
||||||
|
|
||||||
wapp_extern void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
|
||||||
wapp_extern void mem_util_free(void *ptr, u64 size);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !MEM_OS_H
|
|
@@ -1,101 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "commander.h"
|
|
||||||
#include "commander_output.h"
|
|
||||||
#include "../utils/shell_utils.h"
|
|
||||||
#include "../../../mem/arena/mem_arena_allocator.h"
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../common/misc/misc_utils.h"
|
|
||||||
#include "../../../../primitives/dbl_list/dbl_list.h"
|
|
||||||
#include "../../../../primitives/mem_allocator/mem_allocator.h"
|
|
||||||
#include "../../../../primitives/strings/str8/str8.h"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define CMD_BUF_LEN 8192
|
|
||||||
#define OUT_BUF_LEN 4096
|
|
||||||
|
|
||||||
wapp_intern inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
|
|
||||||
wapp_intern inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
|
|
||||||
|
|
||||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
|
|
||||||
if (!cmd) {
|
|
||||||
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(KB(500));
|
|
||||||
|
|
||||||
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
|
|
||||||
if (!cmd_str) {
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
|
||||||
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect output
|
|
||||||
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
|
|
||||||
|
|
||||||
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
|
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_intern inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
|
|
||||||
char cmd_buf[CMD_BUF_LEN] = {0};
|
|
||||||
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
|
|
||||||
|
|
||||||
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
|
|
||||||
if (!fp) {
|
|
||||||
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CMDResult output;
|
|
||||||
|
|
||||||
CMDError err = get_command_output(fp, out_handling, out_buf);
|
|
||||||
if (err > SHELL_ERR_NO_ERROR) {
|
|
||||||
output = CMD_NO_EXIT(err);
|
|
||||||
goto EXECUTE_COMMAND_CLOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
i32 st = EXIT_SUCCESS;
|
|
||||||
err = get_output_status(fp, &st);
|
|
||||||
if (err > SHELL_ERR_NO_ERROR) {
|
|
||||||
output = CMD_NO_EXIT(err);
|
|
||||||
goto EXECUTE_COMMAND_CLOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process is already closed in get_output_status
|
|
||||||
fp = NULL;
|
|
||||||
|
|
||||||
output = (CMDResult){
|
|
||||||
.exited = true,
|
|
||||||
.exit_code = st,
|
|
||||||
.error = SHELL_ERR_NO_ERROR,
|
|
||||||
};
|
|
||||||
|
|
||||||
EXECUTE_COMMAND_CLOSE:
|
|
||||||
if (fp) {
|
|
||||||
wapp_shell_utils_pclose(fp);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_intern inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
|
|
||||||
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
|
|
||||||
|
|
||||||
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
|
|
||||||
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
|
||||||
if (out.size >= out_buf->capacity) {
|
|
||||||
return SHELL_ERR_OUT_BUF_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_str8_concat_capped(out_buf, &out);
|
|
||||||
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
|
||||||
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SHELL_ERR_NO_ERROR;
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef COMMANDER_H
|
|
||||||
#define COMMANDER_H
|
|
||||||
|
|
||||||
#include "commander_output.h"
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
#include "../../../../primitives/strings/str8/str8.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
|
|
||||||
|
|
||||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd);
|
|
||||||
|
|
||||||
wapp_extern CMDError get_output_status(FILE *fp, i32 *status_out);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !COMMANDER_H
|
|
@@ -1,36 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "../../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../../common/platform/platform.h"
|
|
||||||
#include "../../../../../primitives/strings/str8/str8.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
|
||||||
|
|
||||||
#include "../terminal_colours.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
wapp_intern Str8RO colours[COUNT_TERM_COLOUR] = {
|
|
||||||
[WAPP_TERM_COLOUR_FG_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[30m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_RED] = wapp_str8_lit_ro_initialiser_list("\033[31m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[32m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[34m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[36m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[35m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[33m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[37m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[90m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_RED] = wapp_str8_lit_ro_initialiser_list("\033[91m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[92m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[94m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[96m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[95m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[93m"),
|
|
||||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[97m"),
|
|
||||||
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
|
|
||||||
};
|
|
||||||
|
|
||||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
|
||||||
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
|
@@ -1,18 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#include "termcolour.h"
|
|
||||||
#include "terminal_colours.h"
|
|
||||||
#include "../../../../primitives/strings/str8/str8.h"
|
|
||||||
|
|
||||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
|
|
||||||
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_coloured_text(text, colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wapp_shell_termcolour_clear_colour(void) {
|
|
||||||
Str8RO empty = wapp_str8_lit_ro("");
|
|
||||||
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef TERM_COLOUR_H
|
|
||||||
#define TERM_COLOUR_H
|
|
||||||
|
|
||||||
#include "terminal_colours.h"
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
#include "../../../../primitives/strings/str8/str8.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour);
|
|
||||||
void wapp_shell_termcolour_clear_colour(void);
|
|
||||||
|
|
||||||
wapp_extern void print_coloured_text(Str8RO *text, TerminalColour colour);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !TERM_COLOUR_H
|
|
27
src/core/strings/str8/str8.c
Normal file
27
src/core/strings/str8/str8.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include "str8.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Str8 wapp_str8_lit(char *str) {
|
||||||
|
if (!str) {
|
||||||
|
return (Str8){.capacity = 0, .size = 0, .buf = (u8 *)""};
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 size = strlen(str);
|
||||||
|
return (Str8){.capacity = size, .size = size, .buf = (u8 *)str};
|
||||||
|
}
|
||||||
|
|
||||||
|
char wapp_str8_get(const Str8 *str, u64 index) {
|
||||||
|
if (index >= str->size) {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char)(str->buf[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_str8_set(Str8 *str, u64 index, char c) {
|
||||||
|
if (index >= str->size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
str->buf[index] = (u8)c;
|
||||||
|
}
|
25
src/core/strings/str8/str8.h
Normal file
25
src/core/strings/str8/str8.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STR8_H
|
||||||
|
#define STR8_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !__cplusplus
|
||||||
|
|
||||||
|
typedef struct str8 Str8;
|
||||||
|
struct str8 {
|
||||||
|
u64 capacity;
|
||||||
|
u64 size;
|
||||||
|
u8 *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
Str8 wapp_str8_lit(char *str);
|
||||||
|
char wapp_str8_get(const Str8 *str, u64 index);
|
||||||
|
void wapp_str8_set(Str8 *str, u64 index, char c);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !__cplusplus
|
||||||
|
|
||||||
|
#endif // !STR8_H
|
@@ -1,23 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef WAPP_CORE_C
|
|
||||||
#define WAPP_CORE_C
|
|
||||||
|
|
||||||
#include "wapp_core.h"
|
|
||||||
#include "file/file.c"
|
|
||||||
#include "os/shell/termcolour/posix/termcolour_posix.c"
|
|
||||||
#include "os/shell/termcolour/win/termcolour_win.c"
|
|
||||||
#include "os/shell/termcolour/termcolour.c"
|
|
||||||
#include "os/shell/commander/posix/commander_posix.c"
|
|
||||||
#include "os/shell/commander/win/commander_win.c"
|
|
||||||
#include "os/shell/commander/commander.c"
|
|
||||||
#include "os/cpath/cpath.c"
|
|
||||||
#include "os/mem/posix/mem_os_posix.c"
|
|
||||||
#include "os/mem/win/mem_os_win.c"
|
|
||||||
#include "os/mem/mem_os.c"
|
|
||||||
#include "mem/utils/mem_utils.c"
|
|
||||||
#include "mem/arena/mem_arena.c"
|
|
||||||
#include "mem/arena/mem_arena_allocator.c"
|
|
||||||
#include "../primitives/wapp_primitives.c"
|
|
||||||
|
|
||||||
#endif // !WAPP_CORE_C
|
|
@@ -1,23 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef WAPP_CORE_H
|
|
||||||
#define WAPP_CORE_H
|
|
||||||
|
|
||||||
#include "file/file.h"
|
|
||||||
#include "os/shell/termcolour/termcolour.h"
|
|
||||||
#include "os/shell/termcolour/terminal_colours.h"
|
|
||||||
#include "os/shell/commander/commander.h"
|
|
||||||
#include "os/shell/commander/commander_output.h"
|
|
||||||
#include "os/shell/utils/shell_utils.h"
|
|
||||||
#include "os/cpath/cpath.h"
|
|
||||||
#include "os/mem/posix/mem_os_posix.h"
|
|
||||||
#include "os/mem/win/mem_os_win.h"
|
|
||||||
#include "os/mem/mem_os_ops.h"
|
|
||||||
#include "os/mem/mem_os.h"
|
|
||||||
#include "mem/utils/mem_utils.h"
|
|
||||||
#include "mem/arena/mem_arena_allocator.h"
|
|
||||||
#include "mem/arena/mem_arena.h"
|
|
||||||
#include "../common/wapp_common.h"
|
|
||||||
#include "../primitives/wapp_primitives.h"
|
|
||||||
|
|
||||||
#endif // !WAPP_CORE_H
|
|
92
src/os/cpath/cpath.c
Normal file
92
src/os/cpath/cpath.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#include "cpath.h"
|
||||||
|
#include "aliases.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void join_root_and_leaf(const char *root, const char *leaf, char *dst);
|
||||||
|
|
||||||
|
void join_path(char *dst, u64 count, ...) {
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, count);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < count; ++i) {
|
||||||
|
join_root_and_leaf(dst, va_arg(args, const char *), dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dirup(char *dst, u64 levels, const char *path) {
|
||||||
|
if (levels < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 copy_count = 0;
|
||||||
|
u64 sep_count = 0;
|
||||||
|
|
||||||
|
u64 full_length;
|
||||||
|
u64 length;
|
||||||
|
length = full_length = strlen(path);
|
||||||
|
|
||||||
|
if (length > 1 && path[length - 1] == PATH_SEP) {
|
||||||
|
--length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i64 i = length - 1; i >= 0; --i) {
|
||||||
|
if (path[i] == PATH_SEP) {
|
||||||
|
++sep_count;
|
||||||
|
copy_count = i + 1;
|
||||||
|
|
||||||
|
if (sep_count == levels) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp[256];
|
||||||
|
snprintf(tmp, 2, "%c", PATH_SEP);
|
||||||
|
// NOTE (Abdelrahman): Conditions stored in variables to silence MSVC warning C5045
|
||||||
|
bool insufficient_levels = sep_count < levels;
|
||||||
|
bool path_to_copy_is_separator = strncmp(path, tmp, copy_count) != 0;
|
||||||
|
if (insufficient_levels && path_to_copy_is_separator) {
|
||||||
|
copy_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst == path) {
|
||||||
|
memset(&dst[copy_count], 0, full_length - copy_count);
|
||||||
|
} else {
|
||||||
|
u64 dst_length = strlen(dst);
|
||||||
|
memset(dst, 0, dst_length);
|
||||||
|
strncpy(dst, path, copy_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 final_length = strlen(dst);
|
||||||
|
if (final_length > 1) {
|
||||||
|
dst[final_length - 1] = '\0';
|
||||||
|
} else if (final_length == 0) {
|
||||||
|
dst[0] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void join_root_and_leaf(const char *root, const char *leaf, char *dst) {
|
||||||
|
u64 root_length = strlen(root);
|
||||||
|
u64 leaf_length = strlen(leaf);
|
||||||
|
|
||||||
|
memcpy(dst, root, root_length);
|
||||||
|
|
||||||
|
if (leaf_length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 copy_start = root_length;
|
||||||
|
|
||||||
|
if (root_length > 0 && root[root_length - 1] != PATH_SEP && leaf[0] != PATH_SEP) {
|
||||||
|
dst[root_length] = PATH_SEP;
|
||||||
|
++copy_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(dst[copy_start]), leaf, leaf_length);
|
||||||
|
}
|
32
src/os/cpath/cpath.h
Normal file
32
src/os/cpath/cpath.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef CPATH_H
|
||||||
|
#define CPATH_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
#define PATH_SEP '/'
|
||||||
|
#elif defined(WAPP_PLATFORM_WINDOWS)
|
||||||
|
#define PATH_SEP '\\'
|
||||||
|
#else
|
||||||
|
#error "Unrecognised platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUMPARTS(...) (sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1)
|
||||||
|
|
||||||
|
#define wapp_cpath_join_path(DST, ...) join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__)
|
||||||
|
#define wapp_cpath_dirname(DST, PATH) dirup(DST, 1, PATH)
|
||||||
|
#define wapp_cpath_dirup(DST, COUNT, PATH) dirup(DST, COUNT, PATH)
|
||||||
|
|
||||||
|
void join_path(char *dst, u64 count, ...);
|
||||||
|
void dirup(char *dst, u64 levels, const char *path);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !CPATH_H
|
53
src/os/mem/mem_utils.c
Normal file
53
src/os/mem/mem_utils.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "mem_utils.h"
|
||||||
|
#include "mem_utils_ops.h"
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||||
|
#include "mem_utils_win.h"
|
||||||
|
#elif defined(WAPP_PLATFORM_POSIX)
|
||||||
|
#include "mem_utils_posix.h"
|
||||||
|
#else
|
||||||
|
#error "Unrecognised platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal bool is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
||||||
|
|
||||||
|
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
||||||
|
if (!ptr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(is_power_of_two(alignment));
|
||||||
|
|
||||||
|
uptr p = (uptr)ptr;
|
||||||
|
uptr align = (uptr)alignment;
|
||||||
|
|
||||||
|
// Similar to p % align, but it's a faster implementation that works fine
|
||||||
|
// because align is guaranteed to be a power of 2
|
||||||
|
uptr modulo = p & (align - 1);
|
||||||
|
|
||||||
|
if (modulo != 0) {
|
||||||
|
p += align - modulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||||
|
void *output = mem_util_allocate(addr, size, access, flags, type);
|
||||||
|
|
||||||
|
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||||
|
memset(output, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_mem_util_free(void *ptr, u64 size) {
|
||||||
|
mem_util_free(ptr, size);
|
||||||
|
}
|
32
src/os/mem/mem_utils.h
Normal file
32
src/os/mem/mem_utils.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef MEM_UTILS_H
|
||||||
|
#define MEM_UTILS_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#include "mem_utils_ops.h"
|
||||||
|
|
||||||
|
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||||
|
#include "mem_utils_win.h"
|
||||||
|
#elif defined(WAPP_PLATFORM_POSIX)
|
||||||
|
#include "mem_utils_posix.h"
|
||||||
|
#else
|
||||||
|
#error "Unrecognised platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
|
||||||
|
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||||
|
void wapp_mem_util_free(void *ptr, u64 size);
|
||||||
|
|
||||||
|
external void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||||
|
external void mem_util_free(void *ptr, u64 size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !MEM_UTILS_H
|
@@ -1,13 +1,9 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#ifndef MEM_UTILS_OPS_H
|
||||||
|
#define MEM_UTILS_OPS_H
|
||||||
|
|
||||||
#ifndef MEM_OS_OPS_H
|
#ifdef __cplusplus
|
||||||
#define MEM_OS_OPS_H
|
|
||||||
|
|
||||||
#include "../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
typedef enum mem_access {
|
typedef enum mem_access {
|
||||||
WAPP_MEM_ACCESS_NONE,
|
WAPP_MEM_ACCESS_NONE,
|
||||||
@@ -23,8 +19,8 @@ typedef enum mem_init_type {
|
|||||||
WAPP_MEM_INIT_INITIALISED,
|
WAPP_MEM_INIT_INITIALISED,
|
||||||
} MemInitType;
|
} MemInitType;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !MEM_OS_OPS_H
|
#endif // !MEM_UTILS_OPS_H
|
@@ -1,15 +1,13 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
#include "mem_os_posix.h"
|
#include "mem_utils_ops.h"
|
||||||
#include "../mem_os_ops.h"
|
#include "mem_utils_posix.h"
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
wapp_intern const i32 access_types[] = {
|
internal const i32 access_types[] = {
|
||||||
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
||||||
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
||||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
||||||
@@ -19,7 +17,6 @@ wapp_intern const i32 access_types[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||||
(void)type;
|
|
||||||
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
@@ -1,13 +1,11 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#ifndef MEM_UTILS_POSIX_H
|
||||||
|
#define MEM_UTILS_POSIX_H
|
||||||
|
|
||||||
#ifndef MEM_OS_POSIX_H
|
#include "platform.h"
|
||||||
#define MEM_OS_POSIX_H
|
|
||||||
|
|
||||||
#include "../../../../common/platform/platform.h"
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
@@ -28,8 +26,8 @@ typedef enum mem_alloc_flags {
|
|||||||
|
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#endif // !MEM_OS_POSIX_H
|
#endif // !MEM_UTILS_POSIX_H
|
@@ -1,18 +1,16 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include "mem_os_win.h"
|
#include "mem_utils_ops.h"
|
||||||
#include "../mem_os_ops.h"
|
#include "mem_utils_win.h"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <memoryapi.h>
|
#include <memoryapi.h>
|
||||||
|
|
||||||
wapp_intern const i32 access_types[] = {
|
internal const i32 access_types[] = {
|
||||||
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
||||||
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
||||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
@@ -1,13 +1,11 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#ifndef MEM_UTILS_WIN_H
|
||||||
|
#define MEM_UTILS_WIN_H
|
||||||
|
|
||||||
#ifndef MEM_OS_WIN_H
|
#include "platform.h"
|
||||||
#define MEM_OS_WIN_H
|
|
||||||
|
|
||||||
#include "../../../../common/platform/platform.h"
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
@@ -22,8 +20,8 @@ typedef enum mem_alloc_flags {
|
|||||||
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#endif // !MEM_OS_WIN_H
|
#endif // !MEM_UTILS_WIN_H
|
118
src/os/shell/commander/commander.c
Normal file
118
src/os/shell/commander/commander.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include "commander.h"
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "shell_utils.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define CMD_BUF_LEN 8192
|
||||||
|
#define OUT_BUF_LEN 4096
|
||||||
|
|
||||||
|
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len, va_list args);
|
||||||
|
internal inline CMDResult execute_command(const char *cmd, CMDOutHandling out_handling, char *out_buf,
|
||||||
|
u64 buf_size);
|
||||||
|
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, char *out_buf,
|
||||||
|
u64 buf_size);
|
||||||
|
|
||||||
|
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, buf_size);
|
||||||
|
|
||||||
|
char cmd[CMD_BUF_LEN] = {0};
|
||||||
|
CMDError err = build_command_from_args(cmd, CMD_BUF_LEN, args);
|
||||||
|
if (err > SHELL_ERR_NO_ERROR) {
|
||||||
|
va_end(args);
|
||||||
|
return CMD_NO_EXIT(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return execute_command(cmd, out_handling, out_buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len,
|
||||||
|
va_list args) {
|
||||||
|
u64 size = 0;
|
||||||
|
u64 arg_len = 0;
|
||||||
|
|
||||||
|
const char *arg = va_arg(args, const char *);
|
||||||
|
while (arg) {
|
||||||
|
arg_len = strlen(arg);
|
||||||
|
if (arg_len >= buf_len - size) {
|
||||||
|
return SHELL_ERR_CMD_BUF_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(cmd, arg);
|
||||||
|
cmd[size + arg_len] = ' ';
|
||||||
|
|
||||||
|
size += arg_len + 1;
|
||||||
|
|
||||||
|
arg = va_arg(args, const char *);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHELL_ERR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline CMDResult execute_command(const char *cmd,
|
||||||
|
CMDOutHandling out_handling,
|
||||||
|
char *out_buf, u64 buf_size) {
|
||||||
|
FILE *fp = wapp_shell_utils_popen(cmd, "r");
|
||||||
|
if (!fp) {
|
||||||
|
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMDResult output;
|
||||||
|
|
||||||
|
CMDError err = get_command_output(fp, out_handling, out_buf, buf_size);
|
||||||
|
if (err > SHELL_ERR_NO_ERROR) {
|
||||||
|
output = CMD_NO_EXIT(err);
|
||||||
|
goto EXECUTE_COMMAND_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 st = EXIT_SUCCESS;
|
||||||
|
err = get_output_status(fp, &st);
|
||||||
|
if (err > SHELL_ERR_NO_ERROR) {
|
||||||
|
output = CMD_NO_EXIT(err);
|
||||||
|
goto EXECUTE_COMMAND_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process is already closed in get_output_status
|
||||||
|
fp = NULL;
|
||||||
|
|
||||||
|
output = (CMDResult){
|
||||||
|
.exited = true,
|
||||||
|
.exit_code = st,
|
||||||
|
.error = SHELL_ERR_NO_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
EXECUTE_COMMAND_CLOSE:
|
||||||
|
if (fp) {
|
||||||
|
wapp_shell_utils_pclose(fp);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline CMDError get_command_output(FILE *fp,
|
||||||
|
CMDOutHandling out_handling,
|
||||||
|
char *out_buf, u64 buf_size) {
|
||||||
|
char out[OUT_BUF_LEN] = {0};
|
||||||
|
u64 max_out_length = OUT_BUF_LEN - 1;
|
||||||
|
|
||||||
|
u64 buf_filled = 0;
|
||||||
|
while (fgets(out, (i32)max_out_length, fp)) {
|
||||||
|
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
||||||
|
buf_filled += strlen(out);
|
||||||
|
if (buf_filled >= buf_size) {
|
||||||
|
return SHELL_ERR_OUT_BUF_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(out_buf, out);
|
||||||
|
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
||||||
|
printf("%s", out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHELL_ERR_NO_ERROR;
|
||||||
|
}
|
26
src/os/shell/commander/commander.h
Normal file
26
src/os/shell/commander/commander.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef COMMANDER_H
|
||||||
|
#define COMMANDER_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "commander_output.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
|
||||||
|
#define wapp_shell_commander_execute(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, ...) \
|
||||||
|
run_command(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, __VA_ARGS__, "2>&1", NULL)
|
||||||
|
|
||||||
|
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...);
|
||||||
|
|
||||||
|
external CMDError get_output_status(FILE *fp, i32 *status_out);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !COMMANDER_H
|
@@ -1,14 +1,13 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef COMMANDER_OUTPUT_H
|
#ifndef COMMANDER_OUTPUT_H
|
||||||
#define COMMANDER_OUTPUT_H
|
#define COMMANDER_OUTPUT_H
|
||||||
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
#include "aliases.h"
|
||||||
#include "../../../../common/platform/platform.h"
|
#include "platform.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_OUTPUT_DISCARD,
|
SHELL_OUTPUT_DISCARD,
|
||||||
@@ -18,8 +17,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_ERR_NO_ERROR,
|
SHELL_ERR_NO_ERROR,
|
||||||
SHELL_ERR_INVALID_ARGS,
|
SHELL_ERR_CMD_BUF_FULL,
|
||||||
SHELL_ERR_ALLOCATION_FAIL,
|
|
||||||
SHELL_ERR_PROC_START_FAIL,
|
SHELL_ERR_PROC_START_FAIL,
|
||||||
SHELL_ERR_OUT_BUF_FULL,
|
SHELL_ERR_OUT_BUF_FULL,
|
||||||
SHELL_ERR_PROC_EXIT_FAIL,
|
SHELL_ERR_PROC_EXIT_FAIL,
|
||||||
@@ -29,16 +27,16 @@ typedef struct commander_result CMDResult;
|
|||||||
struct commander_result {
|
struct commander_result {
|
||||||
i32 exit_code;
|
i32 exit_code;
|
||||||
CMDError error;
|
CMDError error;
|
||||||
b32 exited;
|
bool exited;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
#include "../../../../common/misc/misc_utils.h"
|
#include "misc_utils.h"
|
||||||
wapp_misc_utils_padding_size(sizeof(b32) + sizeof(i32) + sizeof(CMDError));
|
wapp_misc_utils_padding_size(sizeof(bool) + sizeof(i32) + sizeof(CMDError));
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !COMMANDER_OUTPUT_H
|
#endif // !COMMANDER_OUTPUT_H
|
@@ -1,12 +1,10 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "../../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
#include "../commander_output.h"
|
#include "commander_output.h"
|
||||||
#include "../../utils/shell_utils.h"
|
#include "shell_utils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@@ -1,12 +1,10 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "../../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include "../commander_output.h"
|
#include "commander_output.h"
|
||||||
#include "../../utils/shell_utils.h"
|
#include "shell_utils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
33
src/os/shell/termcolour/posix/termcolour_posix.c
Normal file
33
src/os/shell/termcolour/posix/termcolour_posix.c
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
|
#include "terminal_colours.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
internal const char *colours[COUNT_TERM_COLOUR] = {
|
||||||
|
[WAPP_TERM_COLOUR_FG_BLACK] = "\033[30m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_RED] = "\033[31m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_GREEN] = "\033[32m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BLUE] = "\033[34m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_CYAN] = "\033[36m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_MAGENTA] = "\033[35m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_YELLOW] = "\033[33m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_WHITE] = "\033[37m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_BLACK] = "\033[90m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_RED] = "\033[91m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_GREEN] = "\033[92m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_BLUE] = "\033[94m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_CYAN] = "\033[96m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = "\033[95m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = "\033[93m",
|
||||||
|
[WAPP_TERM_COLOUR_FG_BR_WHITE] = "\033[97m",
|
||||||
|
[WAPP_TERM_COLOUR_CLEAR] = "\033[0m",
|
||||||
|
};
|
||||||
|
|
||||||
|
void print_coloured_text(const char *text, TerminalColour colour) {
|
||||||
|
printf("%s%s", colours[colour], text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_POSIX
|
14
src/os/shell/termcolour/termcolour.c
Normal file
14
src/os/shell/termcolour/termcolour.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include "termcolour.h"
|
||||||
|
#include "terminal_colours.h"
|
||||||
|
|
||||||
|
void wapp_shell_termcolour_print_text(const char *text, TerminalColour colour) {
|
||||||
|
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_coloured_text(text, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_shell_termcolour_clear_colour(void) {
|
||||||
|
print_coloured_text("", WAPP_TERM_COLOUR_CLEAR);
|
||||||
|
}
|
20
src/os/shell/termcolour/termcolour.h
Normal file
20
src/os/shell/termcolour/termcolour.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef TERM_COLOUR_H
|
||||||
|
#define TERM_COLOUR_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
#include "terminal_colours.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
void wapp_shell_termcolour_print_text(const char *text, TerminalColour colour);
|
||||||
|
void wapp_shell_termcolour_clear_colour(void);
|
||||||
|
|
||||||
|
external void print_coloured_text(const char *text, TerminalColour colour);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // !TERM_COLOUR_H
|
@@ -1,14 +1,9 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef TERMINAL_COLOURS_H
|
#ifndef TERMINAL_COLOURS_H
|
||||||
#define TERMINAL_COLOURS_H
|
#define TERMINAL_COLOURS_H
|
||||||
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
#ifdef __cplusplus
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WAPP_TERM_COLOUR_FG_BLACK,
|
WAPP_TERM_COLOUR_FG_BLACK,
|
||||||
@@ -32,8 +27,8 @@ typedef enum {
|
|||||||
COUNT_TERM_COLOUR,
|
COUNT_TERM_COLOUR,
|
||||||
} TerminalColour;
|
} TerminalColour;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef __cplusplus
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // !TERMINAL_COLOURS_H
|
#endif // !TERMINAL_COLOURS_H
|
@@ -1,13 +1,10 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
#include "aliases.h"
|
||||||
|
#include "platform.h"
|
||||||
#include "../../../../../common/aliases/aliases.h"
|
|
||||||
#include "../../../../../common/platform/platform.h"
|
|
||||||
#include "../../../../../primitives/strings/str8/str8.h"
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include "../terminal_colours.h"
|
#include "misc_utils.h"
|
||||||
#include "../../../../../common/misc/misc_utils.h"
|
#include "terminal_colours.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@@ -22,9 +19,9 @@ struct termcolour_data {
|
|||||||
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
||||||
};
|
};
|
||||||
|
|
||||||
wapp_intern void init_data(TermcolourData *data);
|
internal void init_data(TermcolourData *data);
|
||||||
|
|
||||||
wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
|
internal WORD colours[COUNT_TERM_COLOUR] = {
|
||||||
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
||||||
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
||||||
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
||||||
@@ -43,8 +40,8 @@ wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
|
|||||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
void print_coloured_text(const char *text, TerminalColour colour) {
|
||||||
wapp_persist TermcolourData data = {0};
|
persistent TermcolourData data = {0};
|
||||||
if (data.handle == 0) {
|
if (data.handle == 0) {
|
||||||
init_data(&data);
|
init_data(&data);
|
||||||
}
|
}
|
||||||
@@ -56,10 +53,10 @@ void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetConsoleTextAttribute(data.handle, data.current_colour);
|
SetConsoleTextAttribute(data.handle, data.current_colour);
|
||||||
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
|
printf("%s", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void init_data(TermcolourData *data) {
|
internal void init_data(TermcolourData *data) {
|
||||||
// create handle
|
// create handle
|
||||||
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
@@ -1,16 +1,9 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef SHELL_UTILS_H
|
#ifndef SHELL_UTILS_H
|
||||||
#define SHELL_UTILS_H
|
#define SHELL_UTILS_H
|
||||||
|
|
||||||
#include "../../../../common/aliases/aliases.h"
|
#include "platform.h"
|
||||||
#include "../../../../common/platform/platform.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
BEGIN_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
#define wapp_shell_utils_popen _popen
|
#define wapp_shell_utils_popen _popen
|
||||||
#define wapp_shell_utils_pclose _pclose
|
#define wapp_shell_utils_pclose _pclose
|
||||||
@@ -19,8 +12,4 @@ BEGIN_C_LINKAGE
|
|||||||
#define wapp_shell_utils_pclose pclose
|
#define wapp_shell_utils_pclose pclose
|
||||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
END_C_LINKAGE
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
#endif // !SHELL_UTILS_H
|
#endif // !SHELL_UTILS_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user