From 291371a4946496817077e219a592113f48725fa9 Mon Sep 17 00:00:00 2001 From: Maryam Tahhan Date: Mon, 25 Nov 2024 05:39:14 -0500 Subject: [PATCH 1/2] chore: update pre-commit hooks Run pre-commit autoupdate and add a monthly workflow to update hooks. Signed-off-by: Maryam Tahhan --- .github/workflows/pre-commit-auto-update.yml | 25 ++++++++++++++++++++ .pre-commit-config.yaml | 6 ++--- 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/pre-commit-auto-update.yml diff --git a/.github/workflows/pre-commit-auto-update.yml b/.github/workflows/pre-commit-auto-update.yml new file mode 100644 index 00000000..5c766196 --- /dev/null +++ b/.github/workflows/pre-commit-auto-update.yml @@ -0,0 +1,25 @@ +name: Pre-commit auto-update +on: # yamllint disable-line rule:truthy + schedule: + - cron: 0 0 1 * * +jobs: + auto-update: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit autoupdate + run: pre-commit autoupdate + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update/pre-commit-autoupdate + title: Auto-update pre-commit hooks + commit-message: Auto-update pre-commit hooks + body: | + Update pre-commit hooks to latest version + labels: dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c6226fbb..3458e378 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -12,13 +12,13 @@ repos: hooks: - id: yamllint - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.6 + rev: v19.1.4 hooks: - id: clang-format types_or: [c++, c] args: [-i, --style=file] - repo: https://github.com/DavidAnson/markdownlint-cli2 - rev: v0.9.2 + rev: v0.15.0 hooks: - id: markdownlint-cli2-rules-docker - repo: https://github.com/codespell-project/codespell From c1a0236305860e30eebd4f9cd8c210f629503d3c Mon Sep 17 00:00:00 2001 From: Maryam Tahhan Date: Mon, 25 Nov 2024 06:36:40 -0500 Subject: [PATCH 2/2] chore: update and run clang Signed-off-by: Maryam Tahhan --- .github/workflows/clang-format.yml | 4 +-- .pre-commit-config.yaml | 2 +- lib/cnet/netlink/netlink_private.h | 6 ++--- lib/cnet/tcp/cnet_tcp.h | 18 ++++--------- lib/core/hash/cne_hash_crc.h | 2 +- lib/core/ring/cne_ring.c | 2 +- lib/include/cne_common.h | 20 +++++++------- lib/include/cne_rwlock.h | 5 +--- lib/include/cne_spinlock.h | 10 ++----- lib/usr/app/cli/cli.h | 13 ++++----- lib/usr/app/jcfg/jcfg.h | 8 +++--- lib/usr/clib/acl/cne_acl.h | 2 +- lib/usr/clib/cthread/cthread_cond.h | 8 +++--- lib/usr/clib/cthread/cthread_pool.h | 12 ++++++--- lib/usr/clib/cthread/cthread_sched.h | 9 ++++--- lib/usr/clib/utils/crc32.h | 4 +-- test/common/test.h | 40 ++++++++-------------------- 17 files changed, 68 insertions(+), 97 deletions(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 708ded06..1ddb6200 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -10,9 +10,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: DoozyX/clang-format-lint-action@v0.18 + - uses: DoozyX/clang-format-lint-action@v0.18.2 with: source: '.' exclude: 'examples/vpp-plugin' extensions: 'h,cpp,c,cc' - clangFormatVersion: 17 + clangFormatVersion: 18.1.8 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3458e378..e0ce66c5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: hooks: - id: yamllint - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.4 + rev: v18.1.8 hooks: - id: clang-format types_or: [c++, c] diff --git a/lib/cnet/netlink/netlink_private.h b/lib/cnet/netlink/netlink_private.h index 7323137c..11c95e08 100644 --- a/lib/cnet/netlink/netlink_private.h +++ b/lib/cnet/netlink/netlink_private.h @@ -14,10 +14,8 @@ extern "C" { #endif -#define DUMP_PARAMS_INIT(info, dump) \ - { \ - .dp_type = dump, .dp_fd = stdout, .dp_dump_msgtype = 1, .dp_data = info \ - } +#define DUMP_PARAMS_INIT(info, dump) \ + {.dp_type = dump, .dp_fd = stdout, .dp_dump_msgtype = 1, .dp_data = info} #define NL_DEBUG(...) \ do { \ diff --git a/lib/cnet/tcp/cnet_tcp.h b/lib/cnet/tcp/cnet_tcp.h index c64d9903..d1441422 100644 --- a/lib/cnet/tcp/cnet_tcp.h +++ b/lib/cnet/tcp/cnet_tcp.h @@ -135,11 +135,9 @@ typedef enum { TCPS_TIME_WAIT /**< Connection is in time wait state */ } tcb_state_t; -#define TCP_INPUT_STATES \ - { \ - "Free", "Closed", "Listen", "SYN Sent", "SYN Rcvd", "Established", "CloseWait", "Fin1", \ - "Closing", "LastAck", "Fin2", "TimeWait", "DeleteTCB" \ - } +#define TCP_INPUT_STATES \ + {"Free", "Closed", "Listen", "SYN Sent", "SYN Rcvd", "Established", "CloseWait", \ + "Fin1", "Closing", "LastAck", "Fin2", "TimeWait", "DeleteTCB"} #define TCPS_HAVE_RCVD_SYN(s) ((s) >= TCPS_SYN_RCVD) #define TCPS_HAVE_ESTABLISHED (s)((s) >= TCPS_ESTABLISHED) @@ -163,10 +161,7 @@ enum { }; /* Keep in bit order with above enums */ -#define TCP_FLAGS \ - { \ - "FIN", "SYN", "RST", "PSH", "ACK", "URG" \ - } +#define TCP_FLAGS {"FIN", "SYN", "RST", "PSH", "ACK", "URG"} // clang-format off /* State of the flags for all possible states in TCP */ @@ -190,10 +185,7 @@ enum { /* TCP Output Events to drive the output Finite State Machine. */ enum { SEND_EVENT, PERSIST_EVENT, RETRANSMIT_EVENT, DELETE_EVENT }; -#define TCP_OUTPUT_EVENTS \ - { \ - "Send", "Persist", "Rexmit", "Delete" \ - } +#define TCP_OUTPUT_EVENTS {"Send", "Persist", "Rexmit", "Delete"} /* TCP Option values */ enum { diff --git a/lib/core/hash/cne_hash_crc.h b/lib/core/hash/cne_hash_crc.h index 2e1900db..3d941c83 100644 --- a/lib/core/hash/cne_hash_crc.h +++ b/lib/core/hash/cne_hash_crc.h @@ -296,7 +296,7 @@ static const uint32_t crc32c_tables[8][256] = {{ // clang-format on #define CRC32_UPD(crc, n) \ - (crc32c_tables[(n)][(crc) & 0xFF] ^ crc32c_tables[(n)-1][((crc) >> 8) & 0xFF]) + (crc32c_tables[(n)][(crc) & 0xFF] ^ crc32c_tables[(n) - 1][((crc) >> 8) & 0xFF]) static inline uint32_t crc32c_1byte(uint8_t data, uint32_t init_val) diff --git a/lib/core/ring/cne_ring.c b/lib/core/ring/cne_ring.c index 94418ac8..f567929d 100644 --- a/lib/core/ring/cne_ring.c +++ b/lib/core/ring/cne_ring.c @@ -27,7 +27,7 @@ #include "ring_private.h" // for cne_ring, cne_ring_headtail, CNE_... /* true if x is a power of 2 */ -#define POWEROF2(x) ((((x)-1) & (x)) == 0) +#define POWEROF2(x) ((((x) - 1) & (x)) == 0) #define RING_DFLT_ELEM_SZ sizeof(void *) /** The default ring element size*/ ssize_t diff --git a/lib/include/cne_common.h b/lib/include/cne_common.h index 68b7ae51..0091fda2 100644 --- a/lib/include/cne_common.h +++ b/lib/include/cne_common.h @@ -149,7 +149,7 @@ typedef uint16_t unaligned_uint16_t; */ #define CNE_SET_USED(x) (void)(x) -#define cne_roundup(_x, _y) ((((_x) + ((_y)-1)) / (_y)) * (_y)) +#define cne_roundup(_x, _y) ((((_x) + ((_y) - 1)) / (_y)) * (_y)) #define cne_ctz(_v) __builtin_ctz(_v) #define cne_prefixbits(_v) ((__typeof__(_v))(sizeof(_v) * 8) - cne_ctz(_v)) #define cne_numbytes(_v) ((cne_prefixbits(_v) + 7) / 8) @@ -269,7 +269,7 @@ typedef uint16_t unaligned_uint16_t; * bigger than the first parameter. Second parameter must be a * power-of-two value. */ -#define CNE_ALIGN_FLOOR(val, align) (typeof(val))((val) & (~((typeof(val))((align)-1)))) +#define CNE_ALIGN_FLOOR(val, align) (typeof(val))((val) & (~((typeof(val))((align) - 1)))) /** * Macro to align a pointer to a given power-of-two. The resultant @@ -278,7 +278,7 @@ typedef uint16_t unaligned_uint16_t; * must be a power-of-two value. */ #define CNE_PTR_ALIGN_CEIL(ptr, align) \ - CNE_PTR_ALIGN_FLOOR((typeof(ptr))CNE_PTR_ADD(ptr, (align)-1), align) + CNE_PTR_ALIGN_FLOOR((typeof(ptr))CNE_PTR_ADD(ptr, (align) - 1), align) /** * Macro to align a value to a given power-of-two. The resultant value @@ -286,7 +286,7 @@ typedef uint16_t unaligned_uint16_t; * than the first parameter. Second parameter must be a power-of-two * value. */ -#define CNE_ALIGN_CEIL(val, align) CNE_ALIGN_FLOOR(((val) + ((typeof(val))(align)-1)), align) +#define CNE_ALIGN_CEIL(val, align) CNE_ALIGN_FLOOR(((val) + ((typeof(val))(align) - 1)), align) /** * Macro to align a pointer to a given power-of-two. The resultant @@ -312,7 +312,7 @@ typedef uint16_t unaligned_uint16_t; * than the first parameter. */ #define CNE_ALIGN_MUL_CEIL(v, mul) \ - (((v + (typeof(v))(mul)-1) / ((typeof(v))(mul))) * (typeof(v))(mul)) + (((v + (typeof(v))(mul) - 1) / ((typeof(v))(mul))) * (typeof(v))(mul)) /** * Macro to align a value to the multiple of given value. The resultant @@ -397,7 +397,7 @@ __extension__ typedef uint64_t CNE_MARKER64[0]; /** Physical address */ typedef uint64_t phys_addr_t; -#define CNE_BAD_PHYS_ADDR ((phys_addr_t)-1) +#define CNE_BAD_PHYS_ADDR ((phys_addr_t) - 1) /** * IO virtual address type. @@ -407,7 +407,7 @@ typedef uint64_t phys_addr_t; * Otherwise, in virtual mode (IOVA as VA), an IOMMU may do the translation. */ typedef uint64_t cne_iova_t; -#define CNE_BAD_IOVA ((cne_iova_t)-1) +#define CNE_BAD_IOVA ((cne_iova_t) - 1) /** * Combines 32b inputs most significant set bits into the least @@ -459,7 +459,7 @@ cne_combine64ms1b(uint64_t v) /** * Macro to return 1 if n is a power of 2, 0 otherwise */ -#define CNE_IS_POWER_OF_2(n) ((n) && !(((n)-1) & (n))) +#define CNE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n))) /** * Returns true if n is a power of 2 @@ -773,7 +773,9 @@ cne_log2_u64(uint64_t v) #define CNE_FMT_TAIL(fmt, ...) __VA_ARGS__ /** Mask value of type "tp" for the first "ln" bit set. */ -#define CNE_LEN2MASK(ln, tp) ((tp)((uint64_t)-1 >> (sizeof(uint64_t) * CHAR_BIT - (ln)))) +// clang-format off +#define CNE_LEN2MASK(ln, tp) ((tp)((uint64_t) - 1 >> (sizeof(uint64_t) * CHAR_BIT - (ln)))) +// clang-format on /** Number of elements in the array. */ #define CNE_DIM(a) (int)(sizeof(a) / sizeof((a)[0])) diff --git a/lib/include/cne_rwlock.h b/lib/include/cne_rwlock.h index 76425338..d2a4d880 100644 --- a/lib/include/cne_rwlock.h +++ b/lib/include/cne_rwlock.h @@ -62,10 +62,7 @@ typedef struct __cne_lockable { /** * A static rwlock initializer. */ -#define CNE_RWLOCK_INITIALIZER \ - { \ - 0 \ - } +#define CNE_RWLOCK_INITIALIZER {0} /** * Initialize the rwlock to an unlocked state. diff --git a/lib/include/cne_spinlock.h b/lib/include/cne_spinlock.h index 3eb9e4be..55ffee38 100644 --- a/lib/include/cne_spinlock.h +++ b/lib/include/cne_spinlock.h @@ -47,10 +47,7 @@ typedef struct { /** * A static spinlock initializer. */ -#define CNE_SPINLOCK_INITIALIZER \ - { \ - 0 \ - } +#define CNE_SPINLOCK_INITIALIZER {0} /** * Initialize the spinlock to an unlocked state. @@ -189,10 +186,7 @@ typedef struct { /** * A static recursive spinlock initializer. */ -#define CNE_SPINLOCK_RECURSIVE_INITIALIZER \ - { \ - CNE_SPINLOCK_INITIALIZER, -1, 0 \ - } +#define CNE_SPINLOCK_RECURSIVE_INITIALIZER {CNE_SPINLOCK_INITIALIZER, -1, 0} /** * Initialize the recursive spinlock to an unlocked state. diff --git a/lib/usr/app/cli/cli.h b/lib/usr/app/cli/cli.h index 92d9b017..a7e37ed7 100644 --- a/lib/usr/app/cli/cli.h +++ b/lib/usr/app/cli/cli.h @@ -63,10 +63,7 @@ typedef enum { } node_type_t; /* Keep this list in sync with the node_type_t enum above */ -#define CLI_NODE_TYPES \ - { \ - "Unknown", "Directory", "Command", "File", "Alias", "String", NULL \ - } +#define CLI_NODE_TYPES {"Unknown", "Directory", "Command", "File", "Alias", "String", NULL} enum { CLI_EXE_TYPE = (CLI_CMD_NODE | CLI_ALIAS_NODE), @@ -203,25 +200,25 @@ struct cli_cmd { const char *name; /**< Name of command */ cli_cfunc_t cfunc; /**< Function pointer */ const char *short_desc; /**< Short description */ -}; /**< List of commands for cli_add_cmds() */ +}; /**< List of commands for cli_add_cmds() */ struct cli_alias { const char *name; /**< Name of command */ const char *alias_atr; /**< Alias string */ const char *short_desc; /**< Short description */ -}; /**< List of alias for cli_add_aliases() */ +}; /**< List of alias for cli_add_aliases() */ struct cli_file { const char *name; /**< Name of command */ cli_ffunc_t ffunc; /**< Read/Write function pointer */ const char *short_desc; /**< Short description */ -}; /**< List of alias for cli_add_aliases() */ +}; /**< List of alias for cli_add_aliases() */ struct cli_str { const char *name; /**< Name of command */ cli_sfunc_t sfunc; /**< Function pointer */ const char *string; /**< Default string */ -}; /**< List of commands for cli_add_str() */ +}; /**< List of commands for cli_add_str() */ struct cli_tree { node_type_t type; /**< type of node to create */ diff --git a/lib/usr/app/jcfg/jcfg.h b/lib/usr/app/jcfg/jcfg.h index aff71571..7d6afbd8 100644 --- a/lib/usr/app/jcfg/jcfg.h +++ b/lib/usr/app/jcfg/jcfg.h @@ -56,10 +56,10 @@ struct json_object; * * @note: make sure this matches the jcfg_cb_type_t enum order. */ -#define JCFG_TAG_NAMES \ - { \ - APP_TAG, DEFAULT_TAG, OPTION_TAG, UMEM_TAG, LPORT_TAG, LGROUP_TAG, THREAD_TAG, \ - LPORT_GROUP_TAG, USER_TAG, \ +#define JCFG_TAG_NAMES \ + { \ + APP_TAG, DEFAULT_TAG, OPTION_TAG, UMEM_TAG, LPORT_TAG, \ + LGROUP_TAG, THREAD_TAG, LPORT_GROUP_TAG, USER_TAG, \ } /** diff --git a/lib/usr/clib/acl/cne_acl.h b/lib/usr/clib/acl/cne_acl.h index 799a11ca..f799023a 100644 --- a/lib/usr/clib/acl/cne_acl.h +++ b/lib/usr/clib/acl/cne_acl.h @@ -96,7 +96,7 @@ enum { }; #define CNE_ACL_MASKLEN_TO_BITMASK(v, s) \ - ((v) == 0 ? (v) : (typeof(v))((uint64_t)-1 << ((s) * CHAR_BIT - (v)))) + ((v) == 0 ? (v) : (typeof(v))((uint64_t) - 1 << ((s) * CHAR_BIT - (v)))) /** * Miscellaneous data for ACL rule. diff --git a/lib/usr/clib/cthread/cthread_cond.h b/lib/usr/clib/cthread/cthread_cond.h index d90c5fc1..163876d3 100644 --- a/lib/usr/clib/cthread/cthread_cond.h +++ b/lib/usr/clib/cthread/cthread_cond.h @@ -47,9 +47,11 @@ struct cthread_cond { char name[MAX_COND_NAME_SIZE]; /**< Name of the condition variable */ } __cne_cache_aligned; -#define CTHREAD_COND_INIT(name) \ - { \ - .name = #name, .blocked = NULL, .sched = NULL, \ +#define CTHREAD_COND_INIT(name) \ + { \ + .name = #name, \ + .blocked = NULL, \ + .sched = NULL, \ } #ifdef __cplusplus diff --git a/lib/usr/clib/cthread/cthread_pool.h b/lib/usr/clib/cthread/cthread_pool.h index 90a0be7f..8cae8696 100644 --- a/lib/usr/clib/cthread/cthread_pool.h +++ b/lib/usr/clib/cthread/cthread_pool.h @@ -168,7 +168,8 @@ _qnode_pool_insert(struct qnode_pool *p, struct qnode *n) * @return * NULL on error or qnode pointer */ -static inline struct qnode *__attribute__((always_inline)) _pool_remove(struct qnode_pool *p) +static inline struct qnode *__attribute__((always_inline)) +_pool_remove(struct qnode_pool *p) { struct qnode *head; struct qnode *tail = p->tail; @@ -212,7 +213,8 @@ static inline struct qnode *__attribute__((always_inline)) _pool_remove(struct q * @return * The qnode removed from queue or NULL on error */ -static inline struct qnode *__attribute__((always_inline)) _qnode_pool_remove(struct qnode_pool *p) +static inline struct qnode *__attribute__((always_inline)) +_qnode_pool_remove(struct qnode_pool *p) { struct qnode *n; @@ -230,7 +232,8 @@ static inline struct qnode *__attribute__((always_inline)) _qnode_pool_remove(st * Allocate a node from the pool * If the pool is empty add mode nodes */ -static inline struct qnode *__attribute__((always_inline)) _qnode_alloc(void) +static inline struct qnode *__attribute__((always_inline)) +_qnode_alloc(void) { struct qnode_pool *p = (THIS_SCHED)->qnode_pool; int prealloc_size = p->pre_alloc; @@ -263,7 +266,8 @@ static inline struct qnode *__attribute__((always_inline)) _qnode_alloc(void) /* * free a queue node to the per scheduler pool from which it came */ -static inline void __attribute__((always_inline)) _qnode_free(struct qnode *n) +static inline void __attribute__((always_inline)) +_qnode_free(struct qnode *n) { struct qnode_pool *p = n->pool; diff --git a/lib/usr/clib/cthread/cthread_sched.h b/lib/usr/clib/cthread/cthread_sched.h index 6445238c..850f11fa 100644 --- a/lib/usr/clib/cthread/cthread_sched.h +++ b/lib/usr/clib/cthread/cthread_sched.h @@ -101,14 +101,16 @@ _sched_now(void) return 1; } -static inline void __attribute__((always_inline)) _affinitize(void) +static inline void __attribute__((always_inline)) +_affinitize(void) { struct cthread *ct = THIS_CTHREAD; cthread_switch(&(THIS_SCHED)->ctx, &ct->ctx); } -static inline void __attribute__((always_inline)) _suspend(void) +static inline void __attribute__((always_inline)) +_suspend(void) { struct cthread *ct = THIS_CTHREAD; @@ -117,7 +119,8 @@ static inline void __attribute__((always_inline)) _suspend(void) (THIS_SCHED)->nb_blocked_threads--; } -static inline void __attribute__((always_inline)) _reschedule(void) +static inline void __attribute__((always_inline)) +_reschedule(void) { struct cthread *ct = THIS_CTHREAD; diff --git a/lib/usr/clib/utils/crc32.h b/lib/usr/clib/utils/crc32.h index ab45b10c..be55bb32 100644 --- a/lib/usr/clib/utils/crc32.h +++ b/lib/usr/clib/utils/crc32.h @@ -43,8 +43,8 @@ extern const uint32_t crc32_tab[]; #define rounddown(x, y) (((x) / (y)) * (y)) -#define rounddown2(x, y) ((x) & (~((y)-1))) /* if y is power of two */ -#define roundup2(x, y) (((x) + ((y)-1)) & (~((y)-1))) /* if y is power of two */ +#define rounddown2(x, y) ((x) & (~((y) - 1))) /* if y is power of two */ +#define roundup2(x, y) (((x) + ((y) - 1)) & (~((y) - 1))) /* if y is power of two */ static __inline uint32_t crc32_raw(const void *buf, size_t size, uint32_t crc) diff --git a/test/common/test.h b/test/common/test.h index cb970f16..7c36c3ac 100644 --- a/test/common/test.h +++ b/test/common/test.h @@ -116,35 +116,17 @@ struct unit_test_case { unsigned enabled; }; -#define TEST_CASE(fn) \ - { \ - NULL, NULL, fn, #fn, 1 \ - } - -#define TEST_CASE_NAMED(name, fn) \ - { \ - NULL, NULL, fn, name, 1 \ - } - -#define TEST_CASE_ST(setup, teardown, testcase) \ - { \ - setup, teardown, testcase, #testcase, 1 \ - } - -#define TEST_CASE_DISABLED(fn) \ - { \ - NULL, NULL, fn, #fn, 0 \ - } - -#define TEST_CASE_ST_DISABLED(setup, teardown, testcase) \ - { \ - setup, teardown, testcase, #testcase, 0 \ - } - -#define TEST_CASES_END() \ - { \ - NULL, NULL, NULL, NULL, 0 \ - } +#define TEST_CASE(fn) {NULL, NULL, fn, #fn, 1} + +#define TEST_CASE_NAMED(name, fn) {NULL, NULL, fn, name, 1} + +#define TEST_CASE_ST(setup, teardown, testcase) {setup, teardown, testcase, #testcase, 1} + +#define TEST_CASE_DISABLED(fn) {NULL, NULL, fn, #fn, 0} + +#define TEST_CASE_ST_DISABLED(setup, teardown, testcase) {setup, teardown, testcase, #testcase, 0} + +#define TEST_CASES_END() {NULL, NULL, NULL, NULL, 0} static inline void debug_hexdump(FILE *file, const char *title, const void *buf, size_t len)