diff options
Diffstat (limited to '')
-rw-r--r--source/cgit.mk2
-rw-r--r--source/filter.c9
-rw-r--r--source/shared.c8
-rw-r--r--source/shared.h5
-rw-r--r--source/ui-log.c4
5 files changed, 20 insertions, 8 deletions
diff --git a/source/cgit.mk b/source/cgit.mk
index 4109930..6e17737 100644
--- a/source/cgit.mk
+++ b/source/cgit.mk
@@ -34,7 +34,7 @@ $(CGIT_BUILD)/VERSION: force-version
# Pinned so a compiler moving its default, as GCC 15 did to gnu23, cannot
# change what the sources mean. The GNU dialect because git's headers use GNU
-# extensions and dlsym needs a non-conforming cast. Git keeps its own choice.
+# extensions. Git keeps its own choice.
CGIT_STD ?= gnu17
# CGIT_CFLAGS is tracked separately so that changing it does not force a rebuild
diff --git a/source/filter.c b/source/filter.c
index 3ffd077..5f96cc0 100644
--- a/source/filter.c
+++ b/source/filter.c
@@ -150,9 +150,14 @@ static struct cgit_filter *current_write_filter = NULL;
void cgit_init_filters(void)
{
- libc_write = dlsym(RTLD_NEXT, "write");
- if (!libc_write)
+ void *symbol = dlsym(RTLD_NEXT, "write");
+
+ if (!symbol)
die("Unable to find libc's write function");
+ // ISO C cannot convert an object pointer to a function pointer, while
+ // POSIX guarantees the two share a representation, so the bytes are
+ // copied across instead.
+ memcpy(&libc_write, &symbol, sizeof(libc_write));
}
/*
diff --git a/source/shared.c b/source/shared.c
index a6a5106..af848f6 100644
--- a/source/shared.c
+++ b/source/shared.c
@@ -123,7 +123,7 @@ static void release_mmfile(mmfile_t *file, const struct object_id *oid)
*/
static int emit_line(void *priv, mmbuffer_t *mb, int nbuf)
{
- linediff_fn emit = (linediff_fn)priv;
+ linediff_fn emit = *(linediff_fn *)priv;
int i;
for (i = 0; i < nbuf; i++) {
@@ -372,7 +372,7 @@ int cgit_refs_cb(const struct reference *ref, void *cb_data)
void cgit_diff_tree_cb(struct diff_queue_struct *q, struct diff_options *options, void *data)
{
- filepair_fn fn = (filepair_fn)data;
+ filepair_fn fn = *(filepair_fn *)data;
int i;
for (i = 0; i < q->nr; i++) {
@@ -443,7 +443,7 @@ int cgit_diff_files(const struct object_id *old_oid, const struct object_id *new
emit_params.ctxlen = context > 0 ? context : DEFAULT_DIFF_CONTEXT;
emit_params.flags = XDL_EMIT_FUNCNAMES;
emit_cb.out_line = emit_line;
- emit_cb.priv = fn;
+ emit_cb.priv = &fn;
xdl_diff(&old_file, &new_file, &diff_params, &emit_params, &emit_cb);
release_mmfile(&old_file, old_oid);
release_mmfile(&new_file, new_oid);
@@ -477,7 +477,7 @@ void cgit_diff_tree(const struct object_id *old_oid, const struct object_id *new
if (ignorews)
DIFF_XDL_SET(&opt, IGNORE_WHITESPACE);
opt.format_callback = cgit_diff_tree_cb;
- opt.format_callback_data = fn;
+ opt.format_callback_data = &fn;
if (prefix)
cgit_diff_limit_path(&opt, prefix);
diff_setup_done(&opt);
diff --git a/source/shared.h b/source/shared.h
index 129cfb7..46324a1 100644
--- a/source/shared.h
+++ b/source/shared.h
@@ -48,6 +48,11 @@ extern int cgit_refs_cb(const struct reference *ref, void *cb_data);
extern void cgit_free_commitinfo(struct commitinfo *info);
extern void cgit_free_taginfo(struct taginfo *info);
+/*
+ * A diff format callback that hands each filepair to the filepair_fn data
+ * points at. ISO C has no conversion between a function pointer and void *,
+ * so the function travels by address.
+ */
extern void cgit_diff_tree_cb(struct diff_queue_struct *q, struct diff_options *options, void *data);
/*
diff --git a/source/ui-log.c b/source/ui-log.c
index 9f21114..d23fcd4 100644
--- a/source/ui-log.c
+++ b/source/ui-log.c
@@ -93,6 +93,8 @@ static void follow_path(struct diff_filepair *pair)
*/
static int should_show(struct commit *commit, struct rev_info *revs)
{
+ // Static, because the walk keeps the address in its diff options.
+ static filepair_fn follow = follow_path;
struct commit_list *parents = commit->parents;
struct commit *parent;
int found = 0, saved_fmt;
@@ -128,7 +130,7 @@ static int should_show(struct commit *commit, struct rev_info *revs)
saved_fmt = revs->diffopt.output_format;
revs->diffopt.output_format = DIFF_FORMAT_CALLBACK;
revs->diffopt.format_callback = cgit_diff_tree_cb;
- revs->diffopt.format_callback_data = follow_path;
+ revs->diffopt.format_callback_data = &follow;
revs->diffopt.no_free = 1;
diff_flush(&revs->diffopt);
revs->diffopt.output_format = saved_fmt;