authorgravatar for ntamtam614@gmail.comNeel <ntamtam614@gmail.com> 2026-02-11 21:49:48-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-12 21:35:36-08:00
log5132d78e8385cbadc888275761258a1fca27b6f0
treed80ab86bf3bb54c55377ecb314ce66d6a2047406
parent4a3adaaa23faa1ae22fa72389850f04ece2570ca

libc: implement insque and remque in Zig

Implements insque() and remque() doubly-linked list functions in lib/c/search.zig and removes musl C implementation. Contributes to #30978

5 files changed, 68 insertions(+), 34 deletions(-)

lib/c.zig+1
......@@ -68,6 +68,7 @@ comptime {
6868 _ = @import("c/malloc.zig");
6969 }
7070 _ = @import("c/math.zig");
71 _ = @import("c/search.zig");
7172 _ = @import("c/stdlib.zig");
7273 _ = @import("c/string.zig");
7374 _ = @import("c/strings.zig");
lib/c/search.zig created+67
......@@ -0,0 +1,67 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const symbol = @import("../c.zig").symbol;
4
5comptime {
6 if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
7 symbol(&insque, "insque");
8 symbol(&remque, "remque");
9 }
10}
11
12const Node = extern struct {
13 next: ?*Node,
14 prev: ?*Node,
15};
16
17fn insque(element: *anyopaque, pred: ?*anyopaque) callconv(.c) void {
18 const e: *Node = @ptrCast(@alignCast(element));
19
20 if (pred) |p_ptr| {
21 const p: *Node = @ptrCast(@alignCast(p_ptr));
22 e.next = p.next;
23 e.prev = p;
24 p.next = e;
25
26 if (e.next) |next| {
27 next.prev = e;
28 }
29 } else {
30 e.next = null;
31 e.prev = null;
32 }
33}
34
35fn remque(element: *anyopaque) callconv(.c) void {
36 const e: *Node = @ptrCast(@alignCast(element));
37
38 if (e.next) |next| next.prev = e.prev;
39 if (e.prev) |prev| prev.next = e.next;
40}
41
42test "insque and remque" {
43 var first = Node{ .next = null, .prev = null };
44 var second = Node{ .next = null, .prev = null };
45 var third = Node{ .next = null, .prev = null };
46
47 insque(&first, null);
48 try std.testing.expectEqual(@as(?*Node, null), first.next);
49 try std.testing.expectEqual(@as(?*Node, null), first.prev);
50
51 insque(&second, &first);
52 try std.testing.expectEqual(@as(?*Node, &second), first.next);
53 try std.testing.expectEqual(@as(?*Node, &first), second.prev);
54
55 insque(&third, &first);
56 try std.testing.expectEqual(@as(?*Node, &third), first.next);
57 try std.testing.expectEqual(@as(?*Node, &second), third.next);
58 try std.testing.expectEqual(@as(?*Node, &first), third.prev);
59 try std.testing.expectEqual(@as(?*Node, &third), second.prev);
60
61 remque(&third);
62 try std.testing.expectEqual(@as(?*Node, &second), first.next);
63 try std.testing.expectEqual(@as(?*Node, &first), second.prev);
64
65 remque(&second);
66 try std.testing.expectEqual(@as(?*Node, null), first.next);
67}
lib/libc/musl/src/search/insque.c deleted-32
......@@ -1,32 +0,0 @@
1#include <search.h>
2
3struct node {
4 struct node *next;
5 struct node *prev;
6};
7
8void insque(void *element, void *pred)
9{
10 struct node *e = element;
11 struct node *p = pred;
12
13 if (!p) {
14 e->next = e->prev = 0;
15 return;
16 }
17 e->next = p->next;
18 e->prev = p;
19 p->next = e;
20 if (e->next)
21 e->next->prev = e;
22}
23
24void remque(void *element)
25{
26 struct node *e = element;
27
28 if (e->next)
29 e->next->prev = e->prev;
30 if (e->prev)
31 e->prev->next = e->next;
32}
src/libs/musl.zig-1
......@@ -1296,7 +1296,6 @@ const src_files = [_][]const u8{
12961296 "musl/src/sched/sched_setscheduler.c",
12971297 "musl/src/sched/sched_yield.c",
12981298 "musl/src/search/hsearch.c",
1299 "musl/src/search/insque.c",
13001299 "musl/src/search/lsearch.c",
13011300 "musl/src/search/tdelete.c",
13021301 "musl/src/search/tdestroy.c",
src/libs/wasi_libc.zig-1
......@@ -848,7 +848,6 @@ const libc_top_half_src_files = [_][]const u8{
848848 "musl/src/regex/fnmatch.c",
849849 "musl/src/regex/regerror.c",
850850 "musl/src/search/hsearch.c",
851 "musl/src/search/insque.c",
852851 "musl/src/search/lsearch.c",
853852 "musl/src/search/tdelete.c",
854853 "musl/src/search/tdestroy.c",