You've already forked pg_probackup
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:
@@ -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)
|
||||
|
||||
@@ -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
@@ -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__)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
typedef void* fobj_t;
|
||||
|
||||
#include <ft_util.h>
|
||||
#include <ft_ar_examples.h>
|
||||
|
||||
/*
|
||||
* Pointer to "object*.
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user