1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2026-06-21 01:34:15 +02:00

[PBCKP-245] fu_utils: compilable under MinGW

This commit is contained in:
Yura Sokolov
2022-09-12 12:24:25 +03:00
parent 585a069a63
commit 4b08603d5a
13 changed files with 179 additions and 105 deletions
+2 -2
View File
@@ -51,14 +51,14 @@ BORROWED_C_SRC := \
src/bin/pg_basebackup/streamutil.c \
src/bin/pg_basebackup/walmethods.c
OBJS += src/fu_util/impl/ft_impl.o src/fu_util/impl/fo_impl.o
BORROW_DIR := src/borrowed
BORROWED_H := $(addprefix $(BORROW_DIR)/, $(notdir $(BORROWED_H_SRC)))
BORROWED_C := $(addprefix $(BORROW_DIR)/, $(notdir $(BORROWED_C_SRC)))
OBJS += $(patsubst %.c, %.o, $(BORROWED_C))
EXTRA_CLEAN := $(BORROWED_H) $(BORROWED_C) $(BORROW_DIR) borrowed.mk
OBJS += src/fu_util/impl/ft_impl.o src/fu_util/impl/fo_impl.o
# off-source build support
ifneq ($(abspath $(CURDIR))/, $(top_pbk_srcdir))
VPATH := $(top_pbk_srcdir)
+22 -2
View File
@@ -5,6 +5,7 @@ set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS true)
include(CheckCSourceCompiles)
include(CheckFunctionExists)
add_library(fu_utils impl/ft_impl.c impl/fo_impl.c)
@@ -12,12 +13,21 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(fu_utils PRIVATE Threads::Threads)
if(CMAKE_USE_PTHREADS_INIT)
target_compile_definitions(fu_utils PRIVATE USE_PTHREADS)
else()
message(FATAL_ERROR "Need pthread support to build")
endif()
CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R)
# Detect for installed beautiful https://github.com/ianlancetaylor/libbacktrace
include_directories(.)
if(NOT CMAKE_C_COMPILER MATCHES tcc)
find_library(LIBBACKTRACE backtrace)
if(LIBBACKTRACE)
set(CMAKE_REQUIRED_LIBRARIES backtrace)
target_link_libraries(fu_utils PRIVATE backtrace)
check_c_source_compiles("
#include <backtrace.h>
int main(void) {
@@ -30,11 +40,21 @@ if(NOT CMAKE_C_COMPILER MATCHES tcc)
endif()
endif()
endif()
check_include_file(execinfo.h HAVE_EXECINFO_H)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions")
if(HAVE_EXECINFO_H)
target_compile_definitions(fu_utils PRIVATE HAVE_EXECINFO_H)
endif()
if(HAVE_STRERROR_R)
target_compile_definitions(fu_utils PRIVATE HAVE_STRERROR_R)
endif()
configure_file(fu_utils_cfg.h.in fu_utils_cfg.h)
target_include_directories(fu_utils INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(fu_utils PRIVATE "${PROJECT_BINARY_DIR}")
target_link_libraries(fu_utils PUBLIC backtrace)
install(TARGETS fu_utils DESTINATION lib)
install(FILES fm_util.h ft_util.h fo_obj.h
@@ -43,4 +63,4 @@ install(FILES fm_util.h ft_util.h fo_obj.h
DESTINATION include/fu_utils)
install(FILES impl/ft_impl.h impl/fo_impl.h DESTINATION include/fu_utils/impl)
add_subdirectory(test)
add_subdirectory(test)
+41 -45
View File
@@ -24,6 +24,9 @@
/****************************************/
// LOGIC
#define fm_true 1
#define fm_false 0
#define fm_compl(v) fm_cat(fm_compl_, v)
#define fm_compl_0 1
#define fm_compl_1 0
@@ -81,38 +84,56 @@
#define fm_tail(...) fm__tail(__VA_ARGS__)
#define fm__tail(x, ...) __VA_ARGS__
#define fm_or_default(...) \
fm_iif(fm_va_01(__VA_ARGS__))(__VA_ARGS__)
#define fm_va_single(...) fm__va_single(__VA_ARGS__, fm__comma)
#define fm_va_many(...) fm__va_many(__VA_ARGS__, fm__comma)
#define fm__va_single(x, y, ...) fm__va_result(y, 1, 0)
#define fm__va_many(x, y, ...) fm__va_result(y, 0, 1)
#define fm__va_result(x, y, res, ...) res
#define fm__va_result(...) fm__va_result_fin(__VA_ARGS__)
#define fm__va_result_fin(x, y, res, ...) res
#define fm_no_va fm_is_empty
#define fm_va_01 fm_isnt_empty
#ifndef FM_USE_STRICT
#if defined(__STRICT_ANSI__) || defined(_MSC_VER) /* well, clang-cl doesn't allow to distinguish std mode */
#define FM_USE_STRICT
#endif
#endif
#ifndef FM_USE_STRICT
#define fm_is_empty(...) fm__is_empty(__VA_ARGS__)
#define fm__is_empty(...) fm_va_single(~, ##__VA_ARGS__)
#define fm_isnt_empty(...) fm__isnt_empty(__VA_ARGS__)
#define fm__isnt_empty(...) fm_va_many(~, ##__VA_ARGS__)
#define fm_va_01n(...) fm_cat3(fm__va_01n_, fm__isnt_empty(__VA_ARGS__), fm_va_many(__VA_ARGS__))
#define fm__va_01n_00 0
#define fm__va_01n_10 1
#define fm__va_01n_11 n
#if !__STRICT_ANSI__
#define fm_is_empty(...) fm__is_empty(__VA_ARGS__)
#define fm__is_empty(...) fm_va_single(~, ##__VA_ARGS__)
#define fm_isnt_empty(...) fm__isnt_empty(__VA_ARGS__)
#define fm__isnt_empty(...) fm_va_many(~, ##__VA_ARGS__)
#define fm_when_isnt_empty(...) fm_cat(fm__when_, fm__isnt_empty(__VA_ARGS__))
#else
#define fm_is_empty(...) fm_and(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__))
#define fm_isnt_empty(...) fm_nand(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__))
#define fm__is_emptyfirst(x, ...) fm_iif(fm_is_tuple(x))(0)(fm__is_emptyfirst_impl(x))
#define fm__is_emptyfirst_impl(x,...) fm_tuple_2((\
fm__is_emptyfirst_do1 x (fm__is_emptyfirst_do2), 1, 0))
#define fm__is_emptyfirst_impl(x,...) fm__va_result(\
fm__is_emptyfirst_do1 x (fm__is_emptyfirst_do2), 1, 0)
#define fm__is_emptyfirst_do1(F) F()
#define fm__is_emptyfirst_do2(...) ,
#define fm_when_isnt_empty(...) fm_cat(fm__when_, fm_isnt_empty(__VA_ARGS__))
#define fm_va_01n(...) fm_cat3(fm__va_01n_, fm__is_emptyfirst(__VA_ARGS__), fm_va_many(__VA_ARGS__))
#define fm__va_01n_10 0
#define fm__va_01n_00 1
#define fm__va_01n_01 n
#define fm__va_01n_11 n
#endif
#define fm_when_isnt_empty(...) fm_cat(fm__when_, fm__isnt_empty(__VA_ARGS__))
#define fm_or_default(...) \
fm_iif(fm_va_01(__VA_ARGS__))(__VA_ARGS__)
#define fm_va_comma(...) \
fm_when_isnt_empty(__VA_ARGS__)(fm__comma)
#define fm_va_comma_fun(...) \
@@ -127,23 +148,6 @@
#define fm__is_tuple_help(...) ,
#define fm__is_tuple_(...) fm__is_tuple_choose(__VA_ARGS__)
#define fm_tuple_expand(x) fm_expand x
#define fm_tuple_tag(x) fm_head x
#define fm_tuple_data(x) fm_tail x
#define fm_tuple_0(x) fm_head x
#define fm_tuple_1(x) fm__tuple_1 x
#define fm__tuple_1(_0, _1, ...) _1
#define fm_tuple_2(x) fm__tuple_2 x
#define fm__tuple_2(_0, _1, _2, ...) _2
#define fm_tuple_tag_or_0(x) fm__tuple_tag_or_0_(fm__tuple_tag_or_0_help x, 0)
#define fm__tuple_tag_or_0_(...) fm__tuple_tag_or_0_choose(__VA_ARGS__)
#define fm__tuple_tag_or_0_choose(a,x,...) x
#define fm__tuple_tag_or_0_help(tag, ...) , tag
#define fm_dispatch_tag_or_0(prefix, x) \
fm_cat(prefix, fm_tuple_tag_or_0(x))
/****************************************/
// Iteration
@@ -160,20 +164,18 @@
// recursion handle : delay macro expansion to next recursion iteration
#define fm_recurs(id) id fm_empty fm_empty() ()
#define fm_recurs2(a,b) fm_cat fm_empty fm_empty() () (a,b)
#define fm_recurs2(a,b) fm_cat fm_empty() (a,b)
#define fm_defer(id) id fm_empty()
#define fm_foreach_join(join, macro, ...) \
fm_foreach_join_(fm_empty, join, macro, __VA_ARGS__)
#define fm_foreach_join_(join1, join2, macro, ...) \
fm_cat(fm_foreach_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, __VA_ARGS__)
fm_cat(fm_foreach_join_, fm_va_01n(__VA_ARGS__))(fm_empty, join, macro, __VA_ARGS__)
#define fm_foreach_join_0(join1, join2, macro, ...)
#define fm_foreach_join_1(join1, join2, macro, x) \
join1() macro(x)
#define fm_foreach_join_n(join1, join2, macro, x, y, ...) \
join1() macro(x) \
join2() macro(y) \
fm_recurs2(fm_, foreach_join_) (join2, join2, macro, __VA_ARGS__)
fm_recurs2(fm_foreach_join_, fm_va_01n(__VA_ARGS__))(join2, join2, macro, __VA_ARGS__)
#define fm_foreach(macro, ...) \
fm_foreach_join(fm_empty, macro, __VA_ARGS__)
@@ -181,16 +183,14 @@
fm_foreach_join(fm_comma, macro, __VA_ARGS__)
#define fm_foreach_arg_join(join, macro, arg, ...) \
fm_foreach_arg_join_(fm_empty, join, macro, arg, __VA_ARGS__)
#define fm_foreach_arg_join_(join1, join2, macro, arg, ...) \
fm_cat(fm_foreach_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__)
fm_cat(fm_foreach_arg_join_, fm_va_01n(__VA_ARGS__))(fm_empty, join, macro, arg, __VA_ARGS__)
#define fm_foreach_arg_join_0(join1, join2, macro, ...)
#define fm_foreach_arg_join_1(join1, join2, macro, arg, x) \
join1() macro(arg, x)
#define fm_foreach_arg_join_n(join1, join2, macro, arg, x, y, ...) \
join1() macro(arg, x) \
join2() macro(arg, y) \
fm_recurs2(fm_, foreach_arg_join_) (join2, join2, macro, arg, __VA_ARGS__)
fm_recurs2(fm_foreach_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__)
#define fm_foreach_arg(macro, arg, ...) \
fm_foreach_arg_join(fm_empty, macro, arg, __VA_ARGS__)
@@ -198,16 +198,14 @@
fm_foreach_arg_join(fm_comma, macro, arg, __VA_ARGS__)
#define fm_foreach_tuple_join(join, macro, ...) \
fm_foreach_tuple_join_(fm_empty, join, macro, __VA_ARGS__)
#define fm_foreach_tuple_join_(join1, join2, macro, ...) \
fm_cat(fm_foreach_tuple_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, __VA_ARGS__)
fm_cat(fm_foreach_tuple_join_, fm_va_01n(__VA_ARGS__))(fm_empty, join, macro, __VA_ARGS__)
#define fm_foreach_tuple_join_0(join1, join2, macro, ...)
#define fm_foreach_tuple_join_1(join1, join2, macro, x) \
join1() macro x
#define fm_foreach_tuple_join_n(join1, join2, macro, x, y, ...) \
join1() macro x \
join2() macro y \
fm_recurs2(fm_, foreach_tuple_join_) (join2, join2, macro, __VA_ARGS__)
fm_recurs2(fm_foreach_tuple_join_, fm_va_01n(__VA_ARGS__))(join2, join2, macro, __VA_ARGS__)
#define fm_foreach_tuple(macro, ...) \
fm_foreach_tuple_join(fm_empty, macro, __VA_ARGS__)
@@ -215,16 +213,14 @@
fm_foreach_tuple_join(fm_comma, macro, __VA_ARGS__)
#define fm_foreach_tuple_arg_join(join, macro, arg, ...) \
fm_foreach_tuple_arg_join_(fm_empty, join, macro, arg, __VA_ARGS__)
#define fm_foreach_tuple_arg_join_(join1, join2, macro, arg, ...) \
fm_cat(fm_foreach_tuple_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__)
fm_cat(fm_foreach_tuple_arg_join_, fm_va_01n(__VA_ARGS__))(fm_empty, join, macro, arg, __VA_ARGS__)
#define fm_foreach_tuple_arg_join_0(join1, join2, macro, ...)
#define fm_foreach_tuple_arg_join_1(join1, join2, macro, arg, x) \
join1() fm_apply(macro, arg, fm_expand x)
#define fm_foreach_tuple_arg_join_n(join1, join2, macro, arg, x, y, ...) \
join1() fm_apply(macro, arg, fm_expand x) \
join2() fm_apply(macro, arg, fm_expand y) \
fm_recurs2(fm_, foreach_tuple_arg_join_) (join2, join2, macro, arg, __VA_ARGS__)
fm_recurs2(fm_foreach_tuple_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__)
#define fm_foreach_tuple_arg(macro, arg, ...) \
fm_foreach_tuple_arg_join(fm_empty, macro, arg, __VA_ARGS__)
-1
View File
@@ -7,7 +7,6 @@
typedef void* fobj_t;
#include <ft_util.h>
#include <ft_ar_examples.h>
/*
* Pointer to "object*.
+9 -2
View File
@@ -1,5 +1,7 @@
/* vim: set expandtab autoindent cindent ts=4 sw=4 sts=4 */
#include <ft_util.h>
#ifndef FU_UTIL_H
#error "ft_util.h should be included"
#endif
/*
* Accepts 2 macroses:
@@ -176,7 +178,12 @@
#define ft_array_walk fm_cat(ft_array_pref, _walk)
#define ft_array_walk_r fm_cat(ft_array_pref, _walk_r)
#define HUGE_SIZE ((uint64_t)UINT_MAX << 16)
#if __SIZEOF_SIZE_T__ < 8
#define HUGE_SIZE ((size_t)UINT_MAX >> 2)
#else
#define HUGE_SIZE ((size_t)UINT_MAX << 16)
#endif
#ifndef NDEBUG
/* try to catch uninitialized vars */
#define ft_slice_invariants(slc) \
+5 -2
View File
@@ -1,3 +1,8 @@
/* vim: set expandtab autoindent cindent ts=4 sw=4 sts=4 */
#ifndef FU_UTIL_H
#error "ft_util.h should be included"
#endif
/*
* Sort template.
* Accepts four macrosses:
@@ -39,8 +44,6 @@
*
*/
#include <ft_util.h>
#define ft_func_bsearch fm_cat(ft_bsearch_, FT_SEARCH)
#define ft_func_bsearch_r fm_cat3(ft_bsearch_, FT_SEARCH, _r)
#define ft_func_search fm_cat(ft_search_, FT_SEARCH)
+16 -9
View File
@@ -1,24 +1,29 @@
/* vim: set expandtab autoindent cindent ts=4 sw=4 sts=4 */
#ifndef FU_UTIL_H
#define FU_UTIL_H
#define FU_UTIL_H 1
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdarg.h>
#include <sys/types.h>
/* trick to find ssize_t even on windows and strict ansi mode */
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#else
#include <sys/types.h>
#define SSIZE_MAX ((ssize_t)((SIZE_MAX) >> 1))
#if !defined(WIN32) && defined(_WIN32)
#define WIN32 _WIN32
#endif
#endif
#include <memory.h>
#include <limits.h>
#include <fm_util.h>
#include <stdarg.h>
#ifdef __GNUC__
#define ft_gcc_const __attribute__((const))
@@ -29,7 +34,7 @@ typedef SSIZE_T ssize_t;
#define ft_gcc_malloc(free, idx) __attribute__((malloc))
#endif
#define ft_unused __attribute__((unused))
#define ft_gnu_printf(fmt, arg) __attribute__((format(printf,fmt,arg)))
#define ft_gnu_printf(fmt, arg) __attribute__((format(gnu_printf,fmt,arg)))
#define ft_likely(x) __builtin_expect(!!(x), 1)
#define ft_unlikely(x) __builtin_expect(!!(x), 0)
#define ft_always_inline __attribute__((always_inline))
@@ -103,6 +108,7 @@ typedef void ft_gnu_printf(4, 0) (*ft_log_hook_t)(enum FT_LOG_LEVEL,
/*
* Initialize logging in main executable file.
* Pass custom hook or NULL.
* In MinGW if built with libbacktrace, pass executable path (argv[0]).
*/
#define ft_init_log(hook) ft__init_log(hook, __FILE__)
@@ -135,7 +141,7 @@ const char* ft__truncate_log_filename(const char *file);
#define ft_dbg_enabled() ft__dbg_enabled()
#define ft_dbg_assert(x, ...) ft__dbg_assert(x, #x, __VA_ARGS__)
#define ft_assert(x, ...) ft__assert(x, #x, __VA_ARGS__)
#define ft_assert(x, ...) ft__assert(x, #x, ##__VA_ARGS__)
#define ft_assyscall(syscall, ...) ft__assyscall(syscall, fm_uniq(res), __VA_ARGS__)
/* threadsafe strerror */
@@ -305,13 +311,14 @@ typedef struct ft_bytes_t {
} ft_bytes_t;
ft_inline ft_bytes_t ft_bytes(void* ptr, size_t len) {
return (ft_bytes_t){.ptr = ptr, .len = len};
return (ft_bytes_t){.ptr = (char*)ptr, .len = len};
}
ft_inline void ft_bytes_consume(ft_bytes_t *bytes, size_t cut);
ft_inline void ft_bytes_move(ft_bytes_t *dest, ft_bytes_t *src);
// String utils
extern size_t ft_strlcpy(char *dest, const char* src, size_t dest_size);
/*
* Concat strings regarding destination buffer size.
* Note: if dest already full and doesn't contain \0n character, then fatal log is issued.
@@ -411,7 +418,7 @@ extern bool ft_strbuf_vcatf (ft_strbuf_t *buf, const char *fmt, va_list
* Use it if format string comes from user.
*/
ft_gnu_printf(3, 0)
extern bool ft_strbuf_vcatf_err (ft_strbuf_t *buf, bool err[static 1],
extern bool ft_strbuf_vcatf_err (ft_strbuf_t *buf, bool err[1],
const char *fmt, va_list args);
/*
* Returns string which points into the buffer.
+13 -17
View File
@@ -5,13 +5,9 @@
#include <string.h>
#include <errno.h>
#ifdef WIN32
#define __thread __declspec(thread)
#endif
#include <pthread.h>
#include <fo_obj.h>
#include <ft_ar_examples.h>
#include <pthread.h>
/*
* We limits total number of methods, klasses and method implementations.
@@ -650,7 +646,7 @@ fobjStr*
fobj_newstr(ft_str_t s, enum FOBJ_STR_ALLOC ownership) {
fobjStr *str;
#if __SIZEOF_POINTER__ < 8
ft_assert(size < (1<<30)-2);
ft_assert(s.len < (1<<30)-2);
#else
ft_assert(s.len < UINT32_MAX-2);
#endif
@@ -871,13 +867,13 @@ fobj_format_int(ft_strbuf_t *buf, uint64_t i, bool _signed, const char *fmt) {
/* now add real suitable format */
switch (base) {
case 'x': strcat(tfmt + fmtlen, PRIx64); break;
case 'X': strcat(tfmt + fmtlen, PRIX64); break;
case 'o': strcat(tfmt + fmtlen, PRIo64); break;
case 'u': strcat(tfmt + fmtlen, PRIu64); break;
case 'd': strcat(tfmt + fmtlen, PRId64); break;
case 'x': ft_strlcat(tfmt, PRIx64, sizeof(tfmt)); break;
case 'X': ft_strlcat(tfmt, PRIX64, sizeof(tfmt)); break;
case 'o': ft_strlcat(tfmt, PRIo64, sizeof(tfmt)); break;
case 'u': ft_strlcat(tfmt, PRIu64, sizeof(tfmt)); break;
case 'd': ft_strlcat(tfmt, PRId64, sizeof(tfmt)); break;
default:
case 'i': strcat(tfmt + fmtlen, PRIi64); break;
case 'i': ft_strlcat(tfmt, PRIi64, sizeof(tfmt)); break;
}
switch (base) {
@@ -1082,11 +1078,11 @@ fobj__format_errmsg(const char* msg, fobj_err_kv_t *kvs) {
"ident is too long in message \"%s\"", msg);
ft_assert(formatdelim == NULL || closebrace - formatdelim <= 31,
"format is too long in message \"%s\"", msg);
strncpy(ident, cur, identlen);
memcpy(ident, cur, identlen);
ident[identlen] = 0;
formatlen = formatdelim ? closebrace - (formatdelim+1) : 0;
if (formatlen > 0) {
strncpy(format, formatdelim + 1, formatlen);
memcpy(format, formatdelim + 1, formatlen);
}
format[formatlen] = 0;
kv = kvs;
@@ -1293,11 +1289,11 @@ fobj_printkv(const char *fmt, ft_slc_fokv_t kvs) {
"ident is too long in format \"%s\"", fmt);
ft_assert(formatdelim == NULL || closebrace - formatdelim <= 31,
"format is too long in format \"%s\"", fmt);
strncpy(ident, cur, identlen);
memcpy(ident, cur, identlen);
ident[identlen] = 0;
formatlen = formatdelim ? closebrace - (formatdelim+1) : 0;
if (formatlen > 0) {
strncpy(format, formatdelim + 1, formatlen);
memcpy(format, formatdelim + 1, formatlen);
}
format[formatlen] = 0;
i = ft_search_fokv(kvs.ptr, kvs.len, ident, fobj_fokv_cmpc);
+1 -4
View File
@@ -2,10 +2,6 @@
#ifndef FOBJ_OBJ_PRIV2_H
#define FOBJ_OBJ_PRIV2_H
#include <ft_util.h>
#include <fo_obj.h>
#include <impl/fo_impl.h>
enum fobjStrType {
FOBJ_STR_SMALL = 1,
FOBJ_STR_UNOWNED,
@@ -57,6 +53,7 @@ fobj_getstr(fobjStr *str) {
return ft_str(str->ptr.ptr, str->ptr.len);
default:
ft_log(FT_FATAL, "Unknown fobj_str type %d", str->type);
return ft_str(NULL, 0);
}
}
+62 -20
View File
@@ -1,25 +1,35 @@
/* vim: set expandtab autoindent cindent ts=4 sw=4 sts=4 */
#include <stdlib.h>
#include <ft_util.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#if !defined(WIN32) || defined(__MINGW64__) || defined(__MINGW32__)
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#else
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#undef small
#include <process.h>
#include <signal.h>
#include <direct.h>
#undef near
#endif
#ifdef HAVE_LIBBACKTRACE
#include <backtrace.h>
#else
#if defined(__MINGW32__) || defined(__MINGW64__)
#include <libloaderapi.h>
#endif
#elif HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#ifdef WIN32
#define __thread __declspec(thread)
#else
#include <pthread.h>
#endif
#include <ft_util.h>
#define FT_LOG_MAX_FILES (1<<12)
@@ -100,12 +110,22 @@ ft_strlcat(char *dest, const char* src, size_t dest_size) {
ft_assert(dest_null, "destination has no zero byte");
if (dest_len < dest_size-1) {
size_t cpy_len = dest_size - dest_len - 1;
strncpy(dest+dest_len, src, cpy_len);
cpy_len = ft_min(cpy_len, strlen(src));
memcpy(dest+dest_len, src, cpy_len);
dest[dest_len + cpy_len] = '\0';
}
return dest_len + strlen(src);
}
size_t
ft_strlcpy(char *dest, const char* src, size_t dest_size) {
size_t cpy_len = dest_size - 1;
cpy_len = ft_min(cpy_len, strlen(src));
memcpy(dest, src, cpy_len);
dest[cpy_len] = '\0';
return strlen(src);
}
ft_str_t
ft_vasprintf(const char *fmt, va_list args) {
ft_strbuf_t buf = ft_strbuf_zero();
@@ -302,9 +322,23 @@ ft__base_log_filename(const char *file) {
static struct backtrace_state * volatile ft_btstate = NULL;
static pthread_once_t ft_btstate_once = PTHREAD_ONCE_INIT;
static void
ft_backtrace_err(void *data, const char *msg, int errnum)
{
fprintf(stderr, "ft_backtrace_err %s %d\n", msg, errnum);
}
static void
ft_backtrace_init(void) {
__atomic_store_n(&ft_btstate, backtrace_create_state(NULL, 0, NULL, NULL),
const char *app = NULL;
#if defined(__MINGW32__) || defined(__MINGW64__)
static char appbuf[2048] = {0};
/* 2048 should be enough, don't check error */
GetModuleFileNameA(0, appbuf, sizeof(appbuf)-1);
app = appbuf;
#endif
__atomic_store_n(&ft_btstate, backtrace_create_state(app, 1, ft_backtrace_err, NULL),
__ATOMIC_RELEASE);
}
@@ -315,9 +349,9 @@ ft_backtrace_add(void *data, uintptr_t pc,
struct ft_strbuf_t *buf = data;
ssize_t sz;
if (filename == NULL)
return 1;
return ft_strbuf_catf(buf, "\n%s:%-4d %s",
ft__truncate_log_filename(filename), lineno, function);
return 0;
return !ft_strbuf_catf(buf, "\n\t%s:%-4d\t%s",
ft__truncate_log_filename(filename), lineno, function ? function : "(unknown)");
}
#endif
@@ -355,9 +389,9 @@ ft_default_log(enum FT_LOG_LEVEL level, ft_source_position_t srcpos,
#ifdef HAVE_LIBBACKTRACE
if (__atomic_load_n(&ft_btstate, __ATOMIC_ACQUIRE) == NULL)
pthread_once(&ft_btstate_once, ft_backtrace_init);
backtrace_full(ft_btstate, 1, ft_backtrace_add, NULL, &buf);
#else
if (ft_btstate)
backtrace_full(ft_btstate, 0, ft_backtrace_add, NULL, &buf);
#elif defined(HAVE_EXECINFO_H)
void *backtr[32] = {0};
char **syms = NULL;
int i, n;
@@ -414,7 +448,15 @@ ft__log_fatal(ft_source_position_t srcpos, const char* error,
const char*
ft__strerror(int eno, char *buf, size_t len) {
#if !_GNU_SOURCE && (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
#ifndef HAVE_STRERROR_R
char *sbuf = strerror(eno);
if (sbuf == NULL) /* can this still happen anywhere? */
return NULL;
/* To minimize thread-unsafety hazard, copy into caller's buffer */
ft_strlcpy(buf, sbuf, len);
return buf;
#elif !_GNU_SOURCE && (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
int saveno = errno;
int e = strerror_r(eno, buf, len);
if (e != 0) {
+7
View File
@@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.11)
add_executable(fm fm.c)
add_executable(fm1 fm.c)
target_compile_options(fm1 PRIVATE -DFM_USE_STRICT=1)
add_executable(array array.c)
target_link_libraries(array fu_utils)
@@ -20,6 +25,8 @@ target_link_libraries(obj1 fu_utils)
enable_testing()
add_test(NAME fm COMMAND fm)
add_test(NAME fm1 COMMAND fm1)
add_test(NAME array COMMAND array)
add_test(NAME bsearch COMMAND bsearch)
add_test(NAME fuprintf COMMAND fuprintf)
+1
View File
@@ -285,6 +285,7 @@ int main(int argc, char** argv) {
ft_assert(fobj_streq_c(strf, "Some scary things cost > $$12.4800 $$"),
"String is '%s'", $tostr(strf));
ft_log(FT_ERROR, "and try backtrace");
logf("BEFORE EXIT");
}
-1
View File
@@ -20,7 +20,6 @@
Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
#include <alloca.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>