Compare commits

...

2 Commits

Author SHA1 Message Date
82a6293f21 added macro try_handle() 2026-01-13 18:20:01 +05:00
c4fd22542d fixed IGNORE_RESULT macro bug 2026-01-09 09:47:41 +05:00

View File

@@ -73,8 +73,11 @@ typedef struct Result_ {
/// Warning can be suppressed by IGNORE_RESULT /// Warning can be suppressed by IGNORE_RESULT
#define Result(T) Result_ ATTRIBUTE_WARN_UNUSED_RESULT #define Result(T) Result_ ATTRIBUTE_WARN_UNUSED_RESULT
#define ResultVar(T) Result_ #define ResultVar(T) Result_
// for some stupid reason gcc requires more than 3 levels of macros to concat token with line number
#define _ignore_var_name(N) CAT2(__ignored_, N)
///USAGE: IGNORE_RESULT trySomething(); ///USAGE: IGNORE_RESULT trySomething();
#define IGNORE_RESULT Result_ __ignored_##__LINE__ ATTRIBUTE_UNUSED = #define IGNORE_RESULT Result_ _ignore_var_name(__LINE__) ATTRIBUTE_UNUSED =
#define RESULT_ERROR_CODE(CODE_PAGE, CODE, MSG, IS_MSG_ON_HEAP) (Result_){ \ #define RESULT_ERROR_CODE(CODE_PAGE, CODE, MSG, IS_MSG_ON_HEAP) (Result_){ \
@@ -97,55 +100,61 @@ typedef struct Result_ {
#define RESULT_VOID (Result_){ .error = NULL, .u = 0 } #define RESULT_VOID (Result_){ .error = NULL, .u = 0 }
#define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V } #define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V }
#define try(VAR, RESULT_FIELD, RSLT_CALL) \
_try(VAR, RESULT_FIELD, RSLT_CALL, __LINE__)
#define try_void(RSLT_CALL) \
_try_void(RSLT_CALL, __LINE__)
#define try_fatal(VAR, RESULT_FIELD, RSLT_CALL) \
_try_fatal(VAR, RESULT_FIELD, RSLT_CALL, __LINE__)
#define try_fatal_void(RSLT_CALL) \
_try_fatal_void(RSLT_CALL, __LINE__)
#define try_handle(VAR, RESULT_FIELD, RSLT_CALL, HANDLER) \
_try_handle(VAR, RESULT_FIELD, RSLT_CALL, HANDLER, __LINE__)
#define try_handle_void(RSLT_CALL, HANDLER) \
_try_handle_void(RSLT_CALL, HANDLER, __LINE__)
#define try_stderrcode(RSLT_CALL) \
_try_stderrcode(RSLT_CALL, __LINE__)
#define try_fatal_stderrcode(RSLT_CALL) \
_try_fatal_stderrcode(RSLT_CALL, __LINE__)
#define _rname(N) __r_##N #define _rname(N) __r_##N
#define try(VAR, RESULT_FIELD, RSLT_CALL) _try(VAR, RESULT_FIELD, RSLT_CALL, __LINE__) #define _try_handle(VAR, RESULT_FIELD, RSLT_CALL, HANDLER, N) \
#define try_fatal(VAR, RESULT_FIELD, RSLT_CALL) _try_fatal(VAR, RESULT_FIELD, RSLT_CALL, __LINE__) Result_ _rname(N) = RSLT_CALL;\
#define try_void(RSLT_CALL) _try_void(RSLT_CALL, __LINE__) if(_rname(N).error){\
#define try_fatal_void(RSLT_CALL) _try_fatal_void(RSLT_CALL, __LINE__) Error_addCallPos(_rname(N).error, ErrorCallPos_here());\
#define try_stderrcode(RSLT_CALL) _try_stderrcode(RSLT_CALL, __LINE__) HANDLER(_rname(N));\
#define try_fatal_stderrcode(RSLT_CALL) _try_fatal_stderrcode(RSLT_CALL, __LINE__) }\
VAR = _rname(N).RESULT_FIELD;
#define _try_handle_void(RSLT_CALL, HANDLER, N) \
Result_ _rname(N) = RSLT_CALL;\
if(_rname(N).error){\
Error_addCallPos(_rname(N).error, ErrorCallPos_here());\
HANDLER(_rname(N));\
}\
#define _try__handler(R) Return R
#define _try(VAR, RESULT_FIELD, RSLT_CALL, N) \ #define _try(VAR, RESULT_FIELD, RSLT_CALL, N) \
Result_ _rname(N) = RSLT_CALL;\ _try_handle(VAR, RESULT_FIELD, RSLT_CALL, _try__handler, N)
if(_rname(N).error){\ #define _try_void(RSLT_CALL, N) \
Error_addCallPos(_rname(N).error, ErrorCallPos_here());\ _try_handle_void(RSLT_CALL, _try__handler, N)
Return _rname(N);\
};\
VAR = _rname(N).RESULT_FIELD;
#define _try_void(RSLT_CALL, N) do {\
Result_ _rname(N) = RSLT_CALL;\
if(_rname(N).error){\
Error_addCallPos(_rname(N).error, ErrorCallPos_here());\
Return _rname(N);\
};\
} while(0)
#define _try_fatal__handler(R) Error_printAndExit(R.error)
#define _try_fatal(VAR, RESULT_FIELD, RSLT_CALL, N) \ #define _try_fatal(VAR, RESULT_FIELD, RSLT_CALL, N) \
Result_ _rname(N) = RSLT_CALL;\ _try_handle(VAR, RESULT_FIELD, RSLT_CALL, _try_fatal__handler, N)
if(_rname(N).error){\ #define _try_fatal_void(RSLT_CALL, N) \
Error_addCallPos(_rname(N).error, ErrorCallPos_here());\ _try_handle_void(RSLT_CALL, _try_fatal__handler, N)
Error_printAndExit(_rname(N).error);\
};\
VAR = _rname(N).RESULT_FIELD;
#define _try_fatal_void(RSLT_CALL, N) do {\ #define _try_stderrcode(CALL, N) \
Result_ _rname(N) = RSLT_CALL;\
if(_rname(N).error){\
Error_addCallPos(_rname(N).error, ErrorCallPos_here());\
Error_printAndExit(_rname(N).error);\
};\
} while(0)
#define _try_stderrcode(CALL, N) do {\
int _rname(N) = CALL;\ int _rname(N) = CALL;\
if(_rname(N) != 0){\ if(_rname(N) != 0){\
Return RESULT_ERROR_CODE(LIBC_ERRNO, _rname(N), str_from_cstr(strerror_malloc(_rname(N))), true);\ Return RESULT_ERROR_CODE(LIBC_ERRNO, _rname(N), str_from_cstr(strerror_malloc(_rname(N))), true);\
}\ }\
} while(0)
#define _try_fatal_stderrcode(CALL, N) do {\ #define _try_fatal_stderrcode(CALL, N) \
int _rname(N) = CALL;\ int _rname(N) = CALL;\
if(_rname(N) != 0){\ if(_rname(N) != 0){\
Error_printAndExit(Error_create(\ Error_printAndExit(Error_create(\
@@ -154,6 +163,5 @@ typedef struct Result_ {
ErrorCodePage_name(LIBC_ERRNO), _rname(N)\ ErrorCodePage_name(LIBC_ERRNO), _rname(N)\
));\ ));\
}\ }\
} while(0)
#define try_assert(EXPR) if(!(EXPR)) { Return RESULT_ERROR_LITERAL("assertion must be true: " #EXPR); } #define try_assert(EXPR) if(!(EXPR)) { Return RESULT_ERROR_LITERAL("assertion must be true: " #EXPR); }