|
1 | 1 | //! This is Zig's multi-target implementation of libc.
|
2 |
| -//! When builtin.link_libc is true, we need to export all the functions and |
3 |
| -//! provide an entire C API. |
| 2 | +//! |
| 3 | +//! When `builtin.link_libc` is true, we need to export all the functions and |
| 4 | +//! provide a libc API compatible with the target (e.g. musl, wasi-libc, ...). |
4 | 5 |
|
5 |
| -const std = @import("std"); |
6 | 6 | const builtin = @import("builtin");
|
7 |
| -const math = std.math; |
8 |
| -const isNan = std.math.isNan; |
9 |
| -const maxInt = std.math.maxInt; |
10 |
| -const native_os = builtin.os.tag; |
11 |
| -const native_arch = builtin.cpu.arch; |
12 |
| -const native_abi = builtin.abi; |
13 |
| - |
14 |
| -const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .strong; |
| 7 | +const std = @import("std"); |
15 | 8 |
|
16 |
| -const is_wasm = switch (native_arch) { |
17 |
| - .wasm32, .wasm64 => true, |
18 |
| - else => false, |
19 |
| -}; |
20 |
| -const is_freestanding = switch (native_os) { |
21 |
| - .freestanding, .other => true, |
22 |
| - else => false, |
23 |
| -}; |
| 9 | +// Avoid dragging in the runtime safety mechanisms into this .o file, unless |
| 10 | +// we're trying to test zigc. |
| 11 | +pub const panic = if (builtin.is_test) |
| 12 | + std.debug.FullPanic(std.debug.defaultPanic) |
| 13 | +else |
| 14 | + std.debug.no_panic; |
24 | 15 |
|
25 | 16 | comptime {
|
26 |
| - if (is_freestanding and is_wasm and builtin.link_libc) { |
27 |
| - @export(&wasm_start, .{ .name = "_start", .linkage = .strong }); |
28 |
| - } |
29 |
| - |
30 |
| - if (builtin.link_libc) { |
31 |
| - @export(&strcmp, .{ .name = "strcmp", .linkage = linkage }); |
32 |
| - @export(&strncmp, .{ .name = "strncmp", .linkage = linkage }); |
33 |
| - @export(&strerror, .{ .name = "strerror", .linkage = linkage }); |
34 |
| - @export(&strlen, .{ .name = "strlen", .linkage = linkage }); |
35 |
| - @export(&strcpy, .{ .name = "strcpy", .linkage = linkage }); |
36 |
| - @export(&strncpy, .{ .name = "strncpy", .linkage = linkage }); |
37 |
| - @export(&strcat, .{ .name = "strcat", .linkage = linkage }); |
38 |
| - @export(&strncat, .{ .name = "strncat", .linkage = linkage }); |
39 |
| - } |
40 |
| -} |
41 |
| - |
42 |
| -// Avoid dragging in the runtime safety mechanisms into this .o file, |
43 |
| -// unless we're trying to test this file. |
44 |
| -pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
45 |
| - @branchHint(.cold); |
46 |
| - _ = error_return_trace; |
47 |
| - if (builtin.is_test) { |
48 |
| - std.debug.panic("{s}", .{msg}); |
49 |
| - } |
50 |
| - switch (native_os) { |
51 |
| - .freestanding, .other, .amdhsa, .amdpal => while (true) {}, |
52 |
| - else => std.os.abort(), |
| 17 | + if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { |
| 18 | + // Files specific to musl and wasi-libc. |
| 19 | + _ = @import("c/string.zig"); |
53 | 20 | }
|
54 |
| -} |
55 |
| - |
56 |
| -extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int; |
57 |
| -fn wasm_start() callconv(.c) void { |
58 |
| - _ = main(0, undefined); |
59 |
| -} |
60 | 21 |
|
61 |
| -fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.c) [*:0]u8 { |
62 |
| - var i: usize = 0; |
63 |
| - while (src[i] != 0) : (i += 1) { |
64 |
| - dest[i] = src[i]; |
| 22 | + if (builtin.target.isMuslLibC()) { |
| 23 | + // Files specific to musl. |
65 | 24 | }
|
66 |
| - dest[i] = 0; |
67 | 25 |
|
68 |
| - return dest; |
69 |
| -} |
70 |
| - |
71 |
| -test "strcpy" { |
72 |
| - var s1: [9:0]u8 = undefined; |
73 |
| - |
74 |
| - s1[0] = 0; |
75 |
| - _ = strcpy(&s1, "foobarbaz"); |
76 |
| - try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0)); |
77 |
| -} |
78 |
| - |
79 |
| -fn strncpy(dest: [*:0]u8, src: [*:0]const u8, n: usize) callconv(.c) [*:0]u8 { |
80 |
| - var i: usize = 0; |
81 |
| - while (i < n and src[i] != 0) : (i += 1) { |
82 |
| - dest[i] = src[i]; |
83 |
| - } |
84 |
| - while (i < n) : (i += 1) { |
85 |
| - dest[i] = 0; |
| 26 | + if (builtin.target.isWasiLibC()) { |
| 27 | + // Files specific to wasi-libc. |
86 | 28 | }
|
87 | 29 |
|
88 |
| - return dest; |
89 |
| -} |
90 |
| - |
91 |
| -test "strncpy" { |
92 |
| - var s1: [9:0]u8 = undefined; |
93 |
| - |
94 |
| - s1[0] = 0; |
95 |
| - _ = strncpy(&s1, "foobarbaz", @sizeOf(@TypeOf(s1))); |
96 |
| - try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0)); |
97 |
| -} |
98 |
| - |
99 |
| -fn strcat(dest: [*:0]u8, src: [*:0]const u8) callconv(.c) [*:0]u8 { |
100 |
| - var dest_end: usize = 0; |
101 |
| - while (dest[dest_end] != 0) : (dest_end += 1) {} |
102 |
| - |
103 |
| - var i: usize = 0; |
104 |
| - while (src[i] != 0) : (i += 1) { |
105 |
| - dest[dest_end + i] = src[i]; |
| 30 | + if (builtin.target.isMinGW()) { |
| 31 | + // Files specific to MinGW-w64. |
106 | 32 | }
|
107 |
| - dest[dest_end + i] = 0; |
108 |
| - |
109 |
| - return dest; |
110 |
| -} |
111 |
| - |
112 |
| -test "strcat" { |
113 |
| - var s1: [9:0]u8 = undefined; |
114 |
| - |
115 |
| - s1[0] = 0; |
116 |
| - _ = strcat(&s1, "foo"); |
117 |
| - _ = strcat(&s1, "bar"); |
118 |
| - _ = strcat(&s1, "baz"); |
119 |
| - try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0)); |
120 |
| -} |
121 |
| - |
122 |
| -fn strncat(dest: [*:0]u8, src: [*:0]const u8, avail: usize) callconv(.c) [*:0]u8 { |
123 |
| - var dest_end: usize = 0; |
124 |
| - while (dest[dest_end] != 0) : (dest_end += 1) {} |
125 |
| - |
126 |
| - var i: usize = 0; |
127 |
| - while (i < avail and src[i] != 0) : (i += 1) { |
128 |
| - dest[dest_end + i] = src[i]; |
129 |
| - } |
130 |
| - dest[dest_end + i] = 0; |
131 |
| - |
132 |
| - return dest; |
133 |
| -} |
134 |
| - |
135 |
| -test "strncat" { |
136 |
| - var s1: [9:0]u8 = undefined; |
137 |
| - |
138 |
| - s1[0] = 0; |
139 |
| - _ = strncat(&s1, "foo1111", 3); |
140 |
| - _ = strncat(&s1, "bar1111", 3); |
141 |
| - _ = strncat(&s1, "baz1111", 3); |
142 |
| - try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0)); |
143 |
| -} |
144 |
| - |
145 |
| -fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int { |
146 |
| - return switch (std.mem.orderZ(u8, s1, s2)) { |
147 |
| - .lt => -1, |
148 |
| - .eq => 0, |
149 |
| - .gt => 1, |
150 |
| - }; |
151 |
| -} |
152 |
| - |
153 |
| -fn strlen(s: [*:0]const u8) callconv(.c) usize { |
154 |
| - return std.mem.len(s); |
155 |
| -} |
156 |
| - |
157 |
| -fn strncmp(_l: [*:0]const u8, _r: [*:0]const u8, _n: usize) callconv(.c) c_int { |
158 |
| - if (_n == 0) return 0; |
159 |
| - var l = _l; |
160 |
| - var r = _r; |
161 |
| - var n = _n - 1; |
162 |
| - while (l[0] != 0 and r[0] != 0 and n != 0 and l[0] == r[0]) { |
163 |
| - l += 1; |
164 |
| - r += 1; |
165 |
| - n -= 1; |
166 |
| - } |
167 |
| - return @as(c_int, l[0]) - @as(c_int, r[0]); |
168 |
| -} |
169 |
| - |
170 |
| -fn strerror(errnum: c_int) callconv(.c) [*:0]const u8 { |
171 |
| - _ = errnum; |
172 |
| - return "TODO strerror implementation"; |
173 |
| -} |
174 |
| - |
175 |
| -test "strncmp" { |
176 |
| - try std.testing.expect(strncmp("a", "b", 1) < 0); |
177 |
| - try std.testing.expect(strncmp("a", "c", 1) < 0); |
178 |
| - try std.testing.expect(strncmp("b", "a", 1) > 0); |
179 |
| - try std.testing.expect(strncmp("\xff", "\x02", 1) > 0); |
180 | 33 | }
|
0 commit comments