Compare commits

...

2 Commits

Author SHA1 Message Date
649c2c0968 removed RESULT_ERROR_FMT, see RESULT_ERROR_HEAP for reason 2026-06-08 00:34:50 +05:00
efa4a24304 added path_fix_separators 2026-06-07 22:45:02 +05:00
10 changed files with 77 additions and 36 deletions

View File

@@ -85,14 +85,24 @@ typedef struct Result_ {
ErrorCodePage_name(CODE_PAGE), CODE), \
.u = 0 \
}
#define RESULT_ERROR_CODE_FMT(CODE_PAGE, CODE, FORMAT, ARGS...) \
RESULT_ERROR_CODE(CODE_PAGE, CODE, str_from_cstr(sprintf_malloc(FORMAT ,##ARGS)), true)
#define RESULT_ERROR_CODE_HEAP(CODE_PAGE, CODE, CHAR_PTR_HEAP) \
RESULT_ERROR_CODE(CODE_PAGE, CODE, str_from_cstr(CHAR_PTR_HEAP), true)
#define RESULT_ERROR(MSG, IS_MSG_ON_HEAP) \
RESULT_ERROR_CODE(NONE, 0, MSG, IS_MSG_ON_HEAP);
#define RESULT_ERROR_LITERAL(MSG) \
RESULT_ERROR(STR((MSG)), false)
#define RESULT_ERROR_FMT(FORMAT, ARGS...) \
RESULT_ERROR_CODE_FMT(NONE, 0, FORMAT ,##ARGS)
#define RESULT_ERROR_LITERAL(CHAR_LITERAL) \
RESULT_ERROR(STR((CHAR_LITERAL)), false)
/// WARNING: make sure CHAR_PTR_HEAP is a variable
/// Anti-Example:
/// Defer(free(key));
/// Return RESULT_ERROR_HEAP(sprintf_malloc("key not found: %s", key))
/// SEGFAULT!!!!
/// key was destroyed by Return before sprintf_malloc was called
#define RESULT_ERROR_HEAP(CHAR_PTR_HEAP) \
RESULT_ERROR(str_from_cstr(CHAR_PTR_HEAP), true)
#define RESULT_ERROR_ERRNO() \
RESULT_ERROR_CODE(LIBC_ERRNO, errno, str_from_cstr(strerror_malloc(errno)), true)

View File

@@ -31,6 +31,9 @@
#define path_notseps "\\"
#endif
// @brief replaces path_notsep with path_sep
void path_fix_separators(str* path);
/// @brief removes part of path after path_sep (including path_sep)
/// @return pointer to a segment of path.data or "." if no path_sep has been found
str path_dirname(str path);

View File

@@ -90,6 +90,10 @@ str hex_to_str(Array(u8) buf, bool uppercase);
void str_trim(str* line, bool set_zero_at_end);
/// replaces all occurences of `fragment` in `s` with `replacement`
void str_replaceChar(str* s, char fragment, char replacement);
///@return s[0..n]
static inline str str_sliceBefore(str s, u32 n){
return str_construct(s.data, n, false);

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env bash
CBUILD_VERSION=2.3.0
CBUILD_VERSION=2.3.5
PROJECT="tlibc"
CMP_C="gcc"
CMP_CPP="g++"
STD_C="c11"
STD_C="c99"
STD_CPP="c++11"
WARN_C="-Wall -Wextra
WARN_COMMON="-Wall -Wextra
-Wduplicated-branches
-Wduplicated-cond
-Wformat=2
@@ -15,8 +15,10 @@ WARN_C="-Wall -Wextra
-Werror=return-type
-Werror=pointer-arith
-Werror=init-self
-Wno-maybe-uninitialized"
WARN_C="$WARN_COMMON
-Werror=incompatible-pointer-types"
WARN_CPP="$WARN_C"
WARN_CPP="$WARN_COMMON"
SRC_C="$(find src -name '*.c')"
SRC_CPP="$(find src -name '*.cpp')"
@@ -35,21 +37,24 @@ OBJDIR="obj"
OUTDIR="bin"
STATIC_LIB_FILE="$PROJECT.a"
INCLUDE="-I./include"
INCLUDE="-Iinclude"
DEFINES=""
# OS-specific options
case "$OS" in
WINDOWS)
EXEC_FILE="$PROJECT.exe"
SHARED_LIB_FILE="$PROJECT.dll"
INCLUDE="$INCLUDE "
LINKER_LIBS="-luuid"
INCLUDE="$INCLUDE "
DEFINES="$DEFINES "
;;
LINUX)
EXEC_FILE="$PROJECT"
SHARED_LIB_FILE="$PROJECT.so"
INCLUDE="$INCLUDE "
LINKER_LIBS=""
INCLUDE="$INCLUDE "
DEFINES="$DEFINES "
;;
*)
error "operating system $OS has no configuration variants"
@@ -66,7 +71,9 @@ case "$TASK" in
# -fprofile-use enables compiler to use profiling info files to optimize executable
# -fprofile-prefix-path sets path where profiling info about objects are be saved
# -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections"
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use
-fprofile-prefix-path=$(realpath $OBJDIR)/objects
-fdata-sections -ffunction-sections -Wl,--gc-sections $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=""
@@ -75,7 +82,7 @@ case "$TASK" in
;;
# creates executable with debug info and no optimizations
build_exec_dbg)
C_ARGS="-O0 -g3"
C_ARGS="-O0 -g3 $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=""
@@ -84,7 +91,7 @@ case "$TASK" in
;;
# creates shared library
build_shared_lib)
C_ARGS="-O2 -fpic -flto -shared"
C_ARGS="-O2 -fpic -flto -shared $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
PRE_TASK_SCRIPT=""
@@ -93,7 +100,7 @@ case "$TASK" in
;;
# creates shared library with debug symbols and no optimizations
build_shared_lib_dbg)
C_ARGS="-O0 -g3 -fpic -shared"
C_ARGS="-O0 -g3 -fpic -shared $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
PRE_TASK_SCRIPT=""
@@ -102,7 +109,7 @@ case "$TASK" in
;;
# creates static library
build_static_lib)
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections"
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections $DEFINES"
CPP_ARGS="$C_ARGS"
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
@@ -110,7 +117,7 @@ case "$TASK" in
;;
# creates static library with debug symbols and no optimizations
build_static_lib_dbg)
C_ARGS="-O0 -g3"
C_ARGS="-O0 -g3 $DEFINES"
CPP_ARGS="$C_ARGS"
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
@@ -134,7 +141,8 @@ case "$TASK" in
# -pg adds code to executable, that generates file containing function call info (gmon.out)
# -fprofile-generate generates executable with profiling code
# -fprofile-prefix-path sets path where profiling info about objects will be saved
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate
-fprofile-prefix-path=$(realpath $OBJDIR)/objects $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
@@ -150,7 +158,7 @@ case "$TASK" in
# https://github.com/msys2/MINGW-packages/issues/8503#issuecomment-1365475205
C_ARGS="-O0 -g -pg -no-pie -fno-omit-frame-pointer
-fno-inline-functions -fno-inline-functions-called-once
-fno-optimize-sibling-calls -fopenmp"
-fno-optimize-sibling-calls -fopenmp $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
@@ -164,7 +172,7 @@ case "$TASK" in
callgrind)
OUTDIR="$OUTDIR/callgrind"
# -pg adds code to executable, that generates file containing function call info (gmon.out)
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
C_ARGS="-O2 -flto=auto -fuse-linker-plugin $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
@@ -174,7 +182,7 @@ case "$TASK" in
# compiles executable with sanitizers and executes it to find errors and warnings
sanitize)
OUTDIR="$OUTDIR/sanitize"
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
C_ARGS="-O0 -g3 -fsanitize=undefined,address $DEFINES"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"

View File

@@ -40,11 +40,11 @@ Result(bool) dir_create(cstr path){
#endif
{
char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
char* err = sprintf_malloc(
"Can't create dicectory '%s': %s",
path, errno_s);
free(errno_s);
Return err;
Return RESULT_ERROR_HEAP(err);
}
Return RESULT_VALUE(i, true);

View File

@@ -26,11 +26,11 @@ Result(FILE*) file_open(cstr file_name, cstr fopen_mode){
FILE* f = fopen(file_name, fopen_mode);
if(f == NULL){
char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
char* err = sprintf_malloc(
"Can't open (%s) file '%s': %s",
fopen_mode, file_name, errno_s);
free(errno_s);
return err;
return RESULT_ERROR_HEAP(err);
}
return RESULT_VALUE(p, f);
}
@@ -43,11 +43,11 @@ Result(FILE*) file_openOrCreateReadWrite(cstr file_name){
f = fopen(file_name, fopen_mode);
if(f == NULL){
char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
char* err = sprintf_malloc(
"Can't open (%s) file '%s': %s",
fopen_mode, file_name, errno_s);
free(errno_s);
return err;
return RESULT_ERROR_HEAP(err);
}
}
return RESULT_VALUE(p, f);
@@ -66,11 +66,11 @@ Result(i64) file_tellPos(FILE* f){
Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){
if(IFWIN(_fseeki64, fseeko64)(f, offset, (int)origin) != 0){
char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
char* err = sprintf_malloc(
"Can't seek (offset: "FMT_i64", origin: %i) in file: %s",
offset, origin, errno_s);
free(errno_s);
return err;
return RESULT_ERROR_HEAP(err);
}
return RESULT_VOID;
}
@@ -129,9 +129,10 @@ Result(void) file_readStructsExactly(FILE* f, void* dst, u64 struct_size, u64 ex
return RESULT_ERROR_ERRNO();
}
if(r != exact_count){
return RESULT_ERROR_FMT(
char* err = sprintf_malloc(
"read "FMT_u64" structures out of "FMT_u64,
r, exact_count);
return RESULT_ERROR_HEAP(err);
}
return RESULT_VOID;
}

View File

@@ -6,6 +6,10 @@
#else
#endif
void path_fix_separators(str* path){
str_replaceChar(path, path_notsep, path_sep);
}
str path_dirname(str path){
if(path.len == 0)
return path;

View File

@@ -175,3 +175,10 @@ void str_trim(str* line, bool set_zero_at_end){
line->isZeroTerminated = true;
}
}
void str_replaceChar(str* s, char fragment, char replacement){
for(u32 i = 0; i < s->len; i++){
if(s->data[i] == fragment)
s->data[i] = replacement;
}
}

View File

@@ -1,16 +1,19 @@
#include "tlibc/term.h"
#if defined(_WIN64) || defined(_WIN32)
#include <windows.h>
#define try_win_bool(EXPR) if(!(EXPR)) { Return RESULT_ERROR_FMT(#EXPR " failed with WindowsError %lu", GetLastError()); }
#define try_win_bool(EXPR) if(!(EXPR)) { \
char* err97774 = sprintf_malloc(#EXPR " failed with WindowsError %lu", GetLastError()); \
Return RESULT_ERROR_HEAP(err97774); \
}
#else
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#define try_zero_errno(EXPR) if((EXPR) != 0) { \
char* errno_s = strerror_malloc(errno); \
ResultVar(void) err = RESULT_ERROR_FMT(#EXPR " failed with errno: %s", strerror(errno)); \
char* err97775 = sprintf_malloc(#EXPR " failed with errno: %s", errno_s); \
free(errno_s); \
Return err; \
Return RESULT_ERROR_HEAP(err97775); \
}
#endif

View File

@@ -79,7 +79,8 @@ Result(void) DateTime_parse(cstr src, DateTime* dt){
&dt->d.year, &dt->d.month, &dt->d.month_day,
&dt->t.hour, &dt->t.min, &sec_f);
if(r != 6){
return RESULT_ERROR_FMT("attepmted to parse DateTime, got %i fields out of 6", r);
char* err = sprintf_malloc("attepmted to parse DateTime, got %i fields out of 6", r);
return RESULT_ERROR_HEAP(err);
}
dt->t.sec = (i32)sec_f;
dt->t.nsec = (sec_f - (i32)sec_f) * 1e9;