mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 10:45:48 +08:00
Merge pull request #23529 from alexrp/2879-groundwork
Introduce libzigc for libc function implementations in Zig
This commit is contained in:
293 files changed
+165
-297
No files matched your search
@@ -476,8 +476,8 @@ pub fn build(b: *std.Build) !void {
|
||||
.test_target_filters = test_target_filters,
|
||||
.test_extra_targets = test_extra_targets,
|
||||
.root_src = "lib/c.zig",
|
||||
.name = "universal-libc",
|
||||
.desc = "Run the universal libc tests",
|
||||
.name = "zigc",
|
||||
.desc = "Run the zigc tests",
|
||||
.optimize_modes = optimization_modes,
|
||||
.include_paths = &.{},
|
||||
.skip_single_threaded = true,
|
||||
|
||||
@@ -1,180 +1,33 @@
|
||||
//! This is Zig's multi-target implementation of libc.
|
||||
//! When builtin.link_libc is true, we need to export all the functions and
|
||||
//! provide an entire C API.
|
||||
//!
|
||||
//! When `builtin.link_libc` is true, we need to export all the functions and
|
||||
//! provide a libc API compatible with the target (e.g. musl, wasi-libc, ...).
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const math = std.math;
|
||||
const isNan = std.math.isNan;
|
||||
const maxInt = std.math.maxInt;
|
||||
const native_os = builtin.os.tag;
|
||||
const native_arch = builtin.cpu.arch;
|
||||
const native_abi = builtin.abi;
|
||||
const std = @import("std");
|
||||
|
||||
const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .strong;
|
||||
|
||||
const is_wasm = switch (native_arch) {
|
||||
.wasm32, .wasm64 => true,
|
||||
else => false,
|
||||
};
|
||||
const is_freestanding = switch (native_os) {
|
||||
.freestanding, .other => true,
|
||||
else => false,
|
||||
};
|
||||
// Avoid dragging in the runtime safety mechanisms into this .o file, unless
|
||||
// we're trying to test zigc.
|
||||
pub const panic = if (builtin.is_test)
|
||||
std.debug.FullPanic(std.debug.defaultPanic)
|
||||
else
|
||||
std.debug.no_panic;
|
||||
|
||||
comptime {
|
||||
if (is_freestanding and is_wasm and builtin.link_libc) {
|
||||
@export(&wasm_start, .{ .name = "_start", .linkage = .strong });
|
||||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
||||
// Files specific to musl and wasi-libc.
|
||||
_ = @import("c/string.zig");
|
||||
}
|
||||
|
||||
if (builtin.link_libc) {
|
||||
@export(&strcmp, .{ .name = "strcmp", .linkage = linkage });
|
||||
@export(&strncmp, .{ .name = "strncmp", .linkage = linkage });
|
||||
@export(&strerror, .{ .name = "strerror", .linkage = linkage });
|
||||
@export(&strlen, .{ .name = "strlen", .linkage = linkage });
|
||||
@export(&strcpy, .{ .name = "strcpy", .linkage = linkage });
|
||||
@export(&strncpy, .{ .name = "strncpy", .linkage = linkage });
|
||||
@export(&strcat, .{ .name = "strcat", .linkage = linkage });
|
||||
@export(&strncat, .{ .name = "strncat", .linkage = linkage });
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid dragging in the runtime safety mechanisms into this .o file,
|
||||
// unless we're trying to test this file.
|
||||
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
@branchHint(.cold);
|
||||
_ = error_return_trace;
|
||||
if (builtin.is_test) {
|
||||
std.debug.panic("{s}", .{msg});
|
||||
}
|
||||
switch (native_os) {
|
||||
.freestanding, .other, .amdhsa, .amdpal => while (true) {},
|
||||
else => std.os.abort(),
|
||||
}
|
||||
}
|
||||
|
||||
extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
||||
fn wasm_start() callconv(.c) void {
|
||||
_ = main(0, undefined);
|
||||
}
|
||||
|
||||
fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.c) [*:0]u8 {
|
||||
var i: usize = 0;
|
||||
while (src[i] != 0) : (i += 1) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
dest[i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
test "strcpy" {
|
||||
var s1: [9:0]u8 = undefined;
|
||||
|
||||
s1[0] = 0;
|
||||
_ = strcpy(&s1, "foobarbaz");
|
||||
try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0));
|
||||
}
|
||||
|
||||
fn strncpy(dest: [*:0]u8, src: [*:0]const u8, n: usize) callconv(.c) [*:0]u8 {
|
||||
var i: usize = 0;
|
||||
while (i < n and src[i] != 0) : (i += 1) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
while (i < n) : (i += 1) {
|
||||
dest[i] = 0;
|
||||
if (builtin.target.isMuslLibC()) {
|
||||
// Files specific to musl.
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
test "strncpy" {
|
||||
var s1: [9:0]u8 = undefined;
|
||||
|
||||
s1[0] = 0;
|
||||
_ = strncpy(&s1, "foobarbaz", @sizeOf(@TypeOf(s1)));
|
||||
try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0));
|
||||
}
|
||||
|
||||
fn strcat(dest: [*:0]u8, src: [*:0]const u8) callconv(.c) [*:0]u8 {
|
||||
var dest_end: usize = 0;
|
||||
while (dest[dest_end] != 0) : (dest_end += 1) {}
|
||||
|
||||
var i: usize = 0;
|
||||
while (src[i] != 0) : (i += 1) {
|
||||
dest[dest_end + i] = src[i];
|
||||
if (builtin.target.isWasiLibC()) {
|
||||
// Files specific to wasi-libc.
|
||||
}
|
||||
dest[dest_end + i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
test "strcat" {
|
||||
var s1: [9:0]u8 = undefined;
|
||||
|
||||
s1[0] = 0;
|
||||
_ = strcat(&s1, "foo");
|
||||
_ = strcat(&s1, "bar");
|
||||
_ = strcat(&s1, "baz");
|
||||
try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0));
|
||||
}
|
||||
|
||||
fn strncat(dest: [*:0]u8, src: [*:0]const u8, avail: usize) callconv(.c) [*:0]u8 {
|
||||
var dest_end: usize = 0;
|
||||
while (dest[dest_end] != 0) : (dest_end += 1) {}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < avail and src[i] != 0) : (i += 1) {
|
||||
dest[dest_end + i] = src[i];
|
||||
if (builtin.target.isMinGW()) {
|
||||
// Files specific to MinGW-w64.
|
||||
}
|
||||
dest[dest_end + i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
test "strncat" {
|
||||
var s1: [9:0]u8 = undefined;
|
||||
|
||||
s1[0] = 0;
|
||||
_ = strncat(&s1, "foo1111", 3);
|
||||
_ = strncat(&s1, "bar1111", 3);
|
||||
_ = strncat(&s1, "baz1111", 3);
|
||||
try std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.sliceTo(&s1, 0));
|
||||
}
|
||||
|
||||
fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int {
|
||||
return switch (std.mem.orderZ(u8, s1, s2)) {
|
||||
.lt => -1,
|
||||
.eq => 0,
|
||||
.gt => 1,
|
||||
};
|
||||
}
|
||||
|
||||
fn strlen(s: [*:0]const u8) callconv(.c) usize {
|
||||
return std.mem.len(s);
|
||||
}
|
||||
|
||||
fn strncmp(_l: [*:0]const u8, _r: [*:0]const u8, _n: usize) callconv(.c) c_int {
|
||||
if (_n == 0) return 0;
|
||||
var l = _l;
|
||||
var r = _r;
|
||||
var n = _n - 1;
|
||||
while (l[0] != 0 and r[0] != 0 and n != 0 and l[0] == r[0]) {
|
||||
l += 1;
|
||||
r += 1;
|
||||
n -= 1;
|
||||
}
|
||||
return @as(c_int, l[0]) - @as(c_int, r[0]);
|
||||
}
|
||||
|
||||
fn strerror(errnum: c_int) callconv(.c) [*:0]const u8 {
|
||||
_ = errnum;
|
||||
return "TODO strerror implementation";
|
||||
}
|
||||
|
||||
test "strncmp" {
|
||||
try std.testing.expect(strncmp("a", "b", 1) < 0);
|
||||
try std.testing.expect(strncmp("a", "c", 1) < 0);
|
||||
try std.testing.expect(strncmp("b", "a", 1) > 0);
|
||||
try std.testing.expect(strncmp("\xff", "\x02", 1) > 0);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test)
|
||||
.internal
|
||||
else
|
||||
.strong;
|
||||
|
||||
/// Determines the symbol's visibility to other objects.
|
||||
/// For WebAssembly this allows the symbol to be resolved to other modules, but will not
|
||||
/// export it to the host runtime.
|
||||
pub const visibility: std.builtin.SymbolVisibility = if (builtin.cpu.arch.isWasm() and linkage != .internal)
|
||||
.hidden
|
||||
else
|
||||
.default;
|
||||
@@ -0,0 +1,45 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const common = @import("common.zig");
|
||||
|
||||
comptime {
|
||||
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strlen, .{ .name = "strlen", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
|
||||
fn strcmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
|
||||
// We need to perform unsigned comparisons.
|
||||
return switch (std.mem.orderZ(u8, @ptrCast(s1), @ptrCast(s2))) {
|
||||
.lt => -1,
|
||||
.eq => 0,
|
||||
.gt => 1,
|
||||
};
|
||||
}
|
||||
|
||||
fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
|
||||
if (n == 0) return 0;
|
||||
|
||||
var l: [*:0]const u8 = @ptrCast(s1);
|
||||
var r: [*:0]const u8 = @ptrCast(s2);
|
||||
var i = n - 1;
|
||||
|
||||
while (l[0] != 0 and r[0] != 0 and i != 0 and l[0] == r[0]) {
|
||||
l += 1;
|
||||
r += 1;
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
return @as(c_int, l[0]) - @as(c_int, r[0]);
|
||||
}
|
||||
|
||||
test strncmp {
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
|
||||
}
|
||||
|
||||
fn strlen(s: [*:0]const c_char) callconv(.c) usize {
|
||||
return std.mem.len(s);
|
||||
}
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
int strcmp(const char *l, const char *r)
|
||||
{
|
||||
for (; *l==*r && *l; l++, r++);
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
}
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define ALIGN (sizeof(size_t))
|
||||
#define ONES ((size_t)-1/UCHAR_MAX)
|
||||
#define HIGHS (ONES * (UCHAR_MAX/2+1))
|
||||
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *a = s;
|
||||
#ifdef __GNUC__
|
||||
typedef size_t __attribute__((__may_alias__)) word;
|
||||
const word *w;
|
||||
for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
|
||||
for (w = (const void *)s; !HASZERO(*w); w++);
|
||||
s = (const void *)w;
|
||||
#endif
|
||||
for (; *s; s++);
|
||||
return s-a;
|
||||
}
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
int strncmp(const char *_l, const char *_r, size_t n)
|
||||
{
|
||||
const unsigned char *l=(void *)_l, *r=(void *)_r;
|
||||
if (!n--) return 0;
|
||||
for (; *l && *r && n && *l == *r ; l++, r++, n--);
|
||||
return *l - *r;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 293 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user