From c25d9417d34fc7745ed50fdfe2984895657254d5 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 7 Mar 2020 15:14:47 -0500
Subject: [PATCH 001/111] fix std.fs.makeDirAbsolute
closes #4671
---
lib/std/fs.zig | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 88806f69bb90121d8c67dbe4fccf4b3047580e30..3a1076d0830c09c16904f73ad7cd19dd4b3ceb4e 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -266,7 +266,7 @@ const default_new_dir_mode = 0o755;
/// Asserts that the path is absolute. See `Dir.makeDir` for a function that operates
/// on both absolute and relative paths.
pub fn makeDirAbsolute(absolute_path: []const u8) !void {
- assert(path.isAbsoluteC(absolute_path));
+ assert(path.isAbsolute(absolute_path));
return os.mkdir(absolute_path, default_new_dir_mode);
}
@@ -1669,6 +1669,8 @@ pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
}
test "" {
+ _ = makeDirAbsolute;
+ _ = makeDirAbsoluteZ;
_ = @import("fs/path.zig");
_ = @import("fs/file.zig");
_ = @import("fs/get_app_data_dir.zig");
--
2.54.0
From c5885f012a2d8785d505bb3ec03a8dfab99331d2 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 7 Mar 2020 23:37:07 +0100
Subject: [PATCH 002/111] std: Fix version detection on x86
Call xgetbv only if X{SAVE,RESTORE} and AVX are detected.
Closes #4670
---
lib/std/zig/system/x86.zig | 64 ++++++++++++++++++--------------------
1 file changed, 30 insertions(+), 34 deletions(-)
diff --git a/lib/std/zig/system/x86.zig b/lib/std/zig/system/x86.zig
index b7d2c6a22780e5087d28d98beb76cb6f0c240af2..c85b646f83666b5ab6c974783a5d597cf83b7c9e 100644
--- a/lib/std/zig/system/x86.zig
+++ b/lib/std/zig/system/x86.zig
@@ -30,18 +30,15 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_ta
leaf = cpuid(0x1, 0);
const brand_id = leaf.ebx & 0xff;
- var family: u32 = 0;
- var model: u32 = 0;
- { // Detect model and family
- family = (leaf.eax >> 8) & 0xf;
- model = (leaf.eax >> 4) & 0xf;
- if (family == 6 or family == 0xf) {
- if (family == 0xf) {
- family += (leaf.eax >> 20) & 0xff;
- }
- model += ((leaf.eax >> 16) & 0xf) << 4;
+ // Detect model and family
+ var family = (leaf.eax >> 8) & 0xf;
+ var model = (leaf.eax >> 4) & 0xf;
+ if (family == 6 or family == 0xf) {
+ if (family == 0xf) {
+ family += (leaf.eax >> 20) & 0xff;
}
+ model += ((leaf.eax >> 16) & 0xf) << 4;
}
// Now we detect the model.
@@ -330,11 +327,11 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
setFeature(cpu, .aes, bit(leaf.ecx, 25));
setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
- leaf.eax = getXCR0();
-
- const has_avx = bit(leaf.ecx, 27) and
+ // If the CPU supports XSAVE/XRESTORE (bit 27) and AVX (bit 28) also check
+ // if the AVX registers are saved & restored on context switch
+ const has_avx_save = bit(leaf.ecx, 27) and
bit(leaf.ecx, 28) and
- ((leaf.eax & 0x6) == 0x6);
+ ((getXCR0() & 0x6) == 0x6);
// LLVM approaches avx512_save by hardcoding it to true on Darwin,
// because the kernel saves the context even if the bit is not set.
@@ -358,14 +355,14 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
// set right now.
const has_avx512_save = switch (os_tag.isDarwin()) {
true => true,
- false => has_avx and ((leaf.eax & 0xE0) == 0xE0),
+ false => has_avx_save and ((leaf.eax & 0xE0) == 0xE0),
};
- setFeature(cpu, .avx, has_avx);
- setFeature(cpu, .fma, has_avx and bit(leaf.ecx, 12));
+ setFeature(cpu, .avx, has_avx_save);
+ setFeature(cpu, .fma, has_avx_save and bit(leaf.ecx, 12));
// Only enable XSAVE if OS has enabled support for saving YMM state.
- setFeature(cpu, .xsave, has_avx and bit(leaf.ecx, 26));
- setFeature(cpu, .f16c, has_avx and bit(leaf.ecx, 29));
+ setFeature(cpu, .xsave, has_avx_save and bit(leaf.ecx, 26));
+ setFeature(cpu, .f16c, has_avx_save and bit(leaf.ecx, 29));
leaf = cpuid(0x80000000, 0);
const max_ext_level = leaf.eax;
@@ -376,9 +373,9 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));
setFeature(cpu, .sse4a, bit(leaf.ecx, 6));
setFeature(cpu, .prfchw, bit(leaf.ecx, 8));
- setFeature(cpu, .xop, bit(leaf.ecx, 11) and has_avx);
+ setFeature(cpu, .xop, bit(leaf.ecx, 11) and has_avx_save);
setFeature(cpu, .lwp, bit(leaf.ecx, 15));
- setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx);
+ setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx_save);
setFeature(cpu, .tbm, bit(leaf.ecx, 21));
setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));
setFeature(cpu, .@"64bit", bit(leaf.edx, 29));
@@ -409,7 +406,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
setFeature(cpu, .sgx, bit(leaf.ebx, 2));
setFeature(cpu, .bmi, bit(leaf.ebx, 3));
// AVX2 is only supported if we have the OS save support from AVX.
- setFeature(cpu, .avx2, bit(leaf.ebx, 5) and has_avx);
+ setFeature(cpu, .avx2, bit(leaf.ebx, 5) and has_avx_save);
setFeature(cpu, .bmi2, bit(leaf.ebx, 8));
setFeature(cpu, .invpcid, bit(leaf.ebx, 10));
setFeature(cpu, .rtm, bit(leaf.ebx, 11));
@@ -435,8 +432,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
setFeature(cpu, .avx512vbmi2, bit(leaf.ecx, 6) and has_avx512_save);
setFeature(cpu, .shstk, bit(leaf.ecx, 7));
setFeature(cpu, .gfni, bit(leaf.ecx, 8));
- setFeature(cpu, .vaes, bit(leaf.ecx, 9) and has_avx);
- setFeature(cpu, .vpclmulqdq, bit(leaf.ecx, 10) and has_avx);
+ setFeature(cpu, .vaes, bit(leaf.ecx, 9) and has_avx_save);
+ setFeature(cpu, .vpclmulqdq, bit(leaf.ecx, 10) and has_avx_save);
setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);
setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);
setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);
@@ -487,7 +484,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
}
}
- if (max_level >= 0xD and has_avx) {
+ if (max_level >= 0xD and has_avx_save) {
leaf = cpuid(0xD, 0x1);
// Only enable XSAVE if OS has enabled support for saving YMM state.
setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));
@@ -518,20 +515,19 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
// Workaround for https://github.com/ziglang/zig/issues/215
// Inline assembly in zig only supports one output,
// so we pass a pointer to the struct.
- var cpuid_leaf = CpuidLeaf{ .eax = 0, .ebx = 0, .ecx = 0, .edx = 0 };
- const leaf_ptr = &cpuid_leaf;
+ var cpuid_leaf: CpuidLeaf = undefined;
// valid for both x86 and x86_64
asm volatile (
\\ cpuid
- \\ movl %%eax, (%[leaf_ptr])
+ \\ movl %%eax, 0(%[leaf_ptr])
\\ movl %%ebx, 4(%[leaf_ptr])
\\ movl %%ecx, 8(%[leaf_ptr])
\\ movl %%edx, 12(%[leaf_ptr])
:
: [leaf_id] "{eax}" (leaf_id),
[subid] "{ecx}" (subid),
- [leaf_ptr] "r" (leaf_ptr)
+ [leaf_ptr] "r" (&cpuid_leaf)
: "eax", "ebx", "ecx", "edx"
);
return cpuid_leaf;
@@ -539,11 +535,11 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
// Read control register 0 (XCR0). Used to detect features such as AVX.
fn getXCR0() u32 {
- return asm (
- \\ .byte 0x0F, 0x01, 0xD0
+ return asm volatile (
+ \\ xor %%ecx, %%ecx
+ \\ xgetbv
: [ret] "={eax}" (-> u32)
- : [number] "{eax}" (@as(u32, 0)),
- [number] "{edx}" (@as(u32, 0)),
- [number] "{ecx}" (@as(u32, 0))
+ :
+ : "eax", "edx", "ecx"
);
}
--
2.54.0
From 0720f338d4979578498aaa86766171774230a7e9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 7 Mar 2020 19:11:03 -0500
Subject: [PATCH 003/111] add std.event.Loop pread and faccessat
progress towards std lib tests passing with evented I/O mode
---
lib/std/event/loop.zig | 78 ++++++++++++++++++++++++++++++++++++++++++
lib/std/fs.zig | 2 +-
2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig
index e62f15d59ab51dcf546e6018aca04203a384944b..7db6fe98deb2a37d784cbd2916e194bba5b2221d 100644
--- a/lib/std/event/loop.zig
+++ b/lib/std/event/loop.zig
@@ -809,6 +809,28 @@ pub const Loop = struct {
return req_node.data.msg.readv.result;
}
+ /// Performs an async `os.pread` using a separate thread.
+ /// `fd` must block and not return EAGAIN.
+ pub fn pread(self: *Loop, fd: os.fd_t, buf: []u8, offset: u64) os.PReadError!usize {
+ var req_node = Request.Node{
+ .data = .{
+ .msg = .{
+ .pread = .{
+ .fd = fd,
+ .buf = buf,
+ .offset = offset,
+ .result = undefined,
+ },
+ },
+ .finish = .{ .TickNode = .{ .data = @frame() } },
+ },
+ };
+ suspend {
+ self.posixFsRequest(&req_node);
+ }
+ return req_node.data.msg.pread.result;
+ }
+
/// Performs an async `os.preadv` using a separate thread.
/// `fd` must block and not return EAGAIN.
pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64) os.ReadError!usize {
@@ -895,6 +917,35 @@ pub const Loop = struct {
return req_node.data.msg.pwritev.result;
}
+ /// Performs an async `os.faccessatZ` using a separate thread.
+ /// `fd` must block and not return EAGAIN.
+ pub fn faccessatZ(
+ self: *Loop,
+ dirfd: os.fd_t,
+ path_z: [*:0]const u8,
+ mode: u32,
+ flags: u32,
+ ) os.AccessError!void {
+ var req_node = Request.Node{
+ .data = .{
+ .msg = .{
+ .faccessat = .{
+ .dirfd = dirfd,
+ .path = path_z,
+ .mode = mode,
+ .flags = flags,
+ .result = undefined,
+ },
+ },
+ .finish = .{ .TickNode = .{ .data = @frame() } },
+ },
+ };
+ suspend {
+ self.posixFsRequest(&req_node);
+ }
+ return req_node.data.msg.faccessat.result;
+ }
+
fn workerRun(self: *Loop) void {
while (true) {
while (true) {
@@ -1038,6 +1089,9 @@ pub const Loop = struct {
.pwritev => |*msg| {
msg.result = noasync os.pwritev(msg.fd, msg.iov, msg.offset);
},
+ .pread => |*msg| {
+ msg.result = noasync os.pread(msg.fd, msg.buf, msg.offset);
+ },
.preadv => |*msg| {
msg.result = noasync os.preadv(msg.fd, msg.iov, msg.offset);
},
@@ -1047,6 +1101,9 @@ pub const Loop = struct {
.openat => |*msg| {
msg.result = noasync os.openatC(msg.fd, msg.path, msg.flags, msg.mode);
},
+ .faccessat => |*msg| {
+ msg.result = noasync os.faccessatZ(msg.dirfd, msg.path, msg.mode, msg.flags);
+ },
.close => |*msg| noasync os.close(msg.fd),
}
switch (node.data.finish) {
@@ -1120,10 +1177,12 @@ pub const Loop = struct {
write: Write,
writev: WriteV,
pwritev: PWriteV,
+ pread: PRead,
preadv: PReadV,
open: Open,
openat: OpenAt,
close: Close,
+ faccessat: FAccessAt,
/// special - means the fs thread should exit
end,
@@ -1161,6 +1220,15 @@ pub const Loop = struct {
pub const Error = os.PWriteError;
};
+ pub const PRead = struct {
+ fd: os.fd_t,
+ buf: []u8,
+ offset: usize,
+ result: Error!usize,
+
+ pub const Error = os.PReadError;
+ };
+
pub const PReadV = struct {
fd: os.fd_t,
iov: []const os.iovec,
@@ -1192,6 +1260,16 @@ pub const Loop = struct {
pub const Close = struct {
fd: os.fd_t,
};
+
+ pub const FAccessAt = struct {
+ dirfd: os.fd_t,
+ path: [*:0]const u8,
+ mode: u32,
+ flags: u32,
+ result: Error!void,
+
+ pub const Error = os.AccessError;
+ };
};
};
};
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 3a1076d0830c09c16904f73ad7cd19dd4b3ceb4e..1f20a14f744c3e904224ddb59035ce479a7e0a0c 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1365,7 +1365,7 @@ pub const Dir = struct {
else
@as(u32, os.F_OK);
const result = if (need_async_thread)
- std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode)
+ std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0)
else
os.faccessatZ(self.fd, sub_path, os_mode, 0);
return result;
--
2.54.0
From 6ac76bc25e2636bd9b2f7bb2fc5710e2aef4f8ed Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 7 Mar 2020 19:13:05 -0500
Subject: [PATCH 004/111] add missing errors to
std.os.windows.CreateDirectoryError
---
lib/std/os/windows.zig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index ba55845a4f5bd258ffaf4e5f1a8d0ab8501a7de7..d1201108dc4f577e40d398822022a8620ea31e87 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -591,6 +591,8 @@ pub const CreateDirectoryError = error{
FileNotFound,
NoDevice,
AccessDenied,
+ InvalidUtf8,
+ BadPathName,
Unexpected,
};
--
2.54.0
From cf38ce970155512577cfb0cc281d1a308af7e7e9 Mon Sep 17 00:00:00 2001
From: Jared Miller <1668550+Jared-Miller@users.noreply.github.com>
Date: Thu, 20 Feb 2020 15:25:24 -0500
Subject: [PATCH 005/111] Implement UTF-8 to UTF-16LE literal conversion
---
lib/std/unicode.zig | 68 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig
index 85c91602d0f217961e6a947b18050ca0cc2fa881..8ed51fa1451ce6385746b703df13493e49e9bb41 100644
--- a/lib/std/unicode.zig
+++ b/lib/std/unicode.zig
@@ -629,3 +629,71 @@ test "utf8ToUtf16LeWithNull" {
testing.expect(utf16[2] == 0);
}
}
+
+/// Converts a UTF-8 string literal into a UTF-16LE string literal.
+pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8) :0] u16 {
+ comptime {
+ const len: usize = calcUtf16LeLen(utf8);
+ var utf16le: [len :0]u16 = [_ :0]u16{0} ** len;
+ const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);
+ assert(len == utf16le_len);
+ return &utf16le;
+ }
+}
+
+/// Returns length of a supplied UTF-8 string literal. Asserts that the data is valid UTF-8.
+fn calcUtf16LeLen(utf8: []const u8) usize {
+ var src_i: usize = 0;
+ var dest_len: usize = 0;
+ while (src_i < utf8.len) {
+ const n = utf8ByteSequenceLength(utf8[src_i]) catch unreachable;
+ const next_src_i = src_i + n;
+ const codepoint = utf8Decode(utf8[src_i..next_src_i]) catch unreachable;
+ if (codepoint < 0x10000) {
+ dest_len += 1;
+ } else {
+ dest_len += 2;
+ }
+ src_i = next_src_i;
+ }
+ return dest_len;
+}
+
+test "utf8ToUtf16LeStringLiteral" {
+{
+ const bytes = [_:0]u16{ 0x41 };
+ const utf16 = utf8ToUtf16LeStringLiteral("A");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[1] == 0);
+ }
+ {
+ const bytes = [_:0]u16{ 0xD801, 0xDC37 };
+ const utf16 = utf8ToUtf16LeStringLiteral("𐐷");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[2] == 0);
+ }
+ {
+ const bytes = [_:0]u16{ 0x02FF };
+ const utf16 = utf8ToUtf16LeStringLiteral("\u{02FF}");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[1] == 0);
+ }
+ {
+ const bytes = [_:0]u16{ 0x7FF };
+ const utf16 = utf8ToUtf16LeStringLiteral("\u{7FF}");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[1] == 0);
+ }
+ {
+ const bytes = [_:0]u16{ 0x801 };
+ const utf16 = utf8ToUtf16LeStringLiteral("\u{801}");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[1] == 0);
+ }
+ {
+ const bytes = [_:0]u16{ 0xDBFF, 0xDFFF };
+ const utf16 = utf8ToUtf16LeStringLiteral("\u{10FFFF}");
+ testing.expectEqualSlices(u16, &bytes, utf16);
+ testing.expect(utf16[2] == 0);
+ }
+}
--
2.54.0
From 8b80cb3072536069d745d6f0bee03ed3ea0e523a Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 8 Mar 2020 03:52:52 -0400
Subject: [PATCH 006/111] Revert "translate-c remove redundant grouping, fix
nested loops without blocks."
This reverts commit abe7305e169be2047d65f96e6525d3828684f058.
---
src-self-hosted/translate_c.zig | 39 +++++++++++++++++++++++----------
test/translate_c.zig | 23 ++++---------------
2 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 41e4665ffe5a9c8d794d2c433b5170ebd03c8f0c..b13a0d4bf975e8f40448914d616fccfdf51dc2c9 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -2237,7 +2237,6 @@ fn transWhileLoop(
.id = .Loop,
};
while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);
- _ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base;
}
@@ -2347,10 +2346,8 @@ fn transForLoop(
try block_scope.?.block_node.statements.push(&while_node.base);
block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block_scope.?.block_node.base;
- } else {
- _ = try appendToken(rp.c, .Semicolon, ";");
+ } else
return &while_node.base;
- }
}
fn transSwitch(
@@ -5579,7 +5576,14 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
);
return error.ParseError;
}
- const deref = try transCreateNodePtrDeref(c, node);
+ // deref is often used together with casts so we group the lhs expression
+ const group = try c.a().create(ast.Node.GroupedExpression);
+ group.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = node,
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ const deref = try transCreateNodePtrDeref(c, &group.base);
node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
continue;
},
@@ -5623,7 +5627,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Ampersand => {
op_token = try appendToken(c, .Ampersand, "&");
- op_id = .BitAnd;
+ op_id .BitAnd;
},
.Plus => {
op_token = try appendToken(c, .Plus, "+");
@@ -5631,7 +5635,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Minus => {
op_token = try appendToken(c, .Minus, "-");
- op_id = .Sub;
+ op_id .Sub;
},
.AmpersandAmpersand => {
op_token = try appendToken(c, .Keyword_and, "and");
@@ -5703,7 +5707,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.BangEqual => {
op_token = try appendToken(c, .BangEqual, "!=");
- op_id = .BangEqual;
+ op_id = .BangEqual;
},
.EqualEqual => {
op_token = try appendToken(c, .EqualEqual, "==");
@@ -5756,12 +5760,25 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return &node.base;
},
.Asterisk => {
- const node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
- return try transCreateNodePtrDeref(c, node);
+ // deref is often used together with casts so we group the lhs expression
+ const group = try c.a().create(ast.Node.GroupedExpression);
+ group.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ return try transCreateNodePtrDeref(c, &group.base);
},
.Ampersand => {
+ // address of is often used together with casts so we group the rhs expression
const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
- node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
+ const group = try c.a().create(ast.Node.GroupedExpression);
+ group.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ node.rhs = &group.base;
return &node.base;
},
else => {
diff --git a/test/translate_c.zig b/test/translate_c.zig
index d4ee871793d0d71c0090586be9535c0633fb867d..01614ae9c9272e7b6c6fcf5931c14c3d292e8272 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,22 +3,6 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
- cases.add("nested loops without blocks",
- \\void foo() {
- \\ while (0) while (0) {}
- \\ for (;;) while (0);
- \\ for (;;) do {} while (0);
- \\}
- , &[_][]const u8{
- \\pub export fn foo() void {
- \\ while (@as(c_int, 0) != 0) while (@as(c_int, 0) != 0) {};
- \\ while (true) while (@as(c_int, 0) != 0) {};
- \\ while (true) while (true) {
- \\ if (!(@as(c_int, 0) != 0)) break;
- \\ };
- \\}
- });
-
cases.add("macro comma operator",
\\#define foo (foo, bar)
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
@@ -30,7 +14,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
\\ return blk: {
- \\ _ = &x;
+ \\ _ = &(x);
\\ _ = 3;
\\ _ = 4 == 4;
\\ _ = 5 * 6;
@@ -2009,7 +1993,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const DOT = a.b;
,
- \\pub const ARROW = a.*.b;
+ \\pub const ARROW = (a).*.b;
});
cases.add("array access",
@@ -2778,11 +2762,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
\\*_XPrivDisplay;
\\typedef struct _XDisplay Display;
- \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen)
+ \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen)
\\
, &[_][]const u8{
\\pub inline fn DefaultScreen(dpy: var) @TypeOf((if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen) {
\\ return (if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen;
\\}
});
+
}
--
2.54.0
From 9e60c89601ab205cd3e63215b318beb89ad1b471 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 8 Mar 2020 03:53:06 -0400
Subject: [PATCH 007/111] Revert "Translate C: Group generated casts"
This reverts commit 895672b3f96aab1f5bad3446f5186a047f29412c.
---
src-self-hosted/translate_c.zig | 41 ++++-----------------------------
test/run_translated_c.zig | 18 ---------------
test/translate_c.zig | 24 ++++---------------
3 files changed, 9 insertions(+), 74 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index b13a0d4bf975e8f40448914d616fccfdf51dc2c9..d24001cf9425efe4cd563d73f5da8f0329f95034 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -5424,15 +5424,12 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return error.ParseError;
}
- // TODO: It might be nice if we only did the alignCasting for opaque types
- //( if (@typeInfo(@TypeOf(x)) == .Pointer)
- // @ptrCast(dest, @alignCast(@alignOf(dest.Child), x))
+ //if (@typeInfo(@TypeOf(x)) == .Pointer)
+ // @ptrCast(dest, x)
//else if (@typeInfo(@TypeOf(x)) == .Integer)
// @intToPtr(dest, x)
//else
- // @as(dest, x) )
-
- const group_lparen = try appendToken(c, .LParen, "(");
+ // @as(dest, x)
const if_1 = try transCreateNodeIf(c);
const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
@@ -5452,30 +5449,9 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
if_1.condition = &cmp_1.base;
_ = try appendToken(c, .RParen, ")");
- const period_tok = try appendToken(c, .Period, ".");
- const child_ident = try transCreateNodeIdentifier(c, "Child");
- const inner_node_child = try c.a().create(ast.Node.InfixOp);
- inner_node_child.* = .{
- .op_token = period_tok,
- .lhs = inner_node,
- .op = .Period,
- .rhs = child_ident,
- };
-
- const align_of = try transCreateNodeBuiltinFnCall(c, "@alignOf");
- try align_of.params.push(&inner_node_child.base);
- align_of.rparen_token = try appendToken(c, .RParen, ")");
- // hack to get zig fmt to render a comma in builtin calls
- _ = try appendToken(c, .Comma, ",");
-
- const align_cast = try transCreateNodeBuiltinFnCall(c, "@alignCast");
- try align_cast.params.push(&align_of.base);
- try align_cast.params.push(node_to_cast);
- align_cast.rparen_token = try appendToken(c, .RParen, ")");
-
const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast");
try ptr_cast.params.push(inner_node);
- try ptr_cast.params.push(&align_cast.base);
+ try ptr_cast.params.push(node_to_cast);
ptr_cast.rparen_token = try appendToken(c, .RParen, ")");
if_1.body = &ptr_cast.base;
@@ -5516,14 +5492,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
as.rparen_token = try appendToken(c, .RParen, ")");
else_2.body = &as.base;
- const group_rparen = try appendToken(c, .RParen, ")");
- const grouped_expr = try c.a().create(ast.Node.GroupedExpression);
- grouped_expr.* = .{
- .lparen = group_lparen,
- .expr = &if_1.base,
- .rparen = group_rparen,
- };
- return &grouped_expr.base;
+ return &if_1.base;
},
else => {
const first_tok = it.list.at(0);
diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig
index 313a83705cfff31e0a4c46ed8ba2e6a85c7fff4f..629a850836ddc334f92eab5f87b2675d50897627 100644
--- a/test/run_translated_c.zig
+++ b/test/run_translated_c.zig
@@ -195,22 +195,4 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
-
- cases.add("cast from pointer to opaque type to struct",
- \\#include
- \\typedef struct
- \\{
- \\ int i;
- \\}
- \\StructType,*StructPtrType;
- \\
- \\typedef struct OpaqueStruct OpaqueStructTypedef;
- \\#define Macro(opaquePtr) (((StructPtrType)(opaquePtr))->i)
- \\int main(int argc, char **argv) {
- \\ StructType localStruct = {88};
- \\ OpaqueStructTypedef *opaquePtrToLocal = &localStruct;
- \\ printf("%d!\n", Macro(opaquePtrToLocal));
- \\ return 0;
- \\}
- , "88!\n");
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 01614ae9c9272e7b6c6fcf5931c14c3d292e8272..3d0843d272f96fb9e12a64419113c56a0591bf15 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1404,7 +1404,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{
- \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, @alignCast(@alignOf([*c]NRF_GPIO_Type.Child), NRF_GPIO_BASE)) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
+ \\pub const NRF_GPIO = if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
});
cases.add("basic macro function",
@@ -2588,11 +2588,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO(bar) baz((void *)(baz))
\\#define BAR (void*) a
, &[_][]const u8{
- \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, @alignCast(@alignOf(*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
- \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, @alignCast(@alignOf(*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
+ \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) {
+ \\ return baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz));
\\}
,
- \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, @alignCast(@alignOf(*c_void.Child), a)) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a));
+ \\pub const BAR = if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a);
});
cases.add("macro conditional operator",
@@ -2754,20 +2754,4 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return if (x > y) x else y;
\\}
});
-
- cases.add("Make sure casts are grouped",
- \\typedef struct
- \\{
- \\ int i;
- \\}
- \\*_XPrivDisplay;
- \\typedef struct _XDisplay Display;
- \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen)
- \\
- , &[_][]const u8{
- \\pub inline fn DefaultScreen(dpy: var) @TypeOf((if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen) {
- \\ return (if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen;
- \\}
- });
-
}
--
2.54.0
From b85bb152bf4c84a298200703d9a005ffcd1b24a0 Mon Sep 17 00:00:00 2001
From: daurnimator
Date: Sun, 8 Mar 2020 19:18:06 +1100
Subject: [PATCH 008/111] Fix grammar in error message
---
src/ir.cpp | 2 +-
test/compile_errors.zig | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 86d85303c03ffcc12f2645bb8baa1a6a5df8ee24..86a5cf06170cff95ab6d70159cf2832232e9fff6 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -30246,7 +30246,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
return ErrorSemanticAnalyzeFail;
} else if (elem_type->id == ZigTypeIdOpaque) {
ir_add_error(ira, &lazy_ptr_type->elem_type->base,
- buf_sprintf("C pointers cannot point opaque types"));
+ buf_sprintf("C pointers cannot point to opaque types"));
return ErrorSemanticAnalyzeFail;
} else if (lazy_ptr_type->is_allowzero) {
ir_add_error(ira, &lazy_ptr_type->elem_type->base,
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index f55931154771bc54610398be1989a0e38406da87..e402197a8e2effa4fb666ef9bbfbde08f6ddc67b 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1592,7 +1592,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var y: [*c]c_void = x;
\\}
, &[_][]const u8{
- "tmp.zig:3:16: error: C pointers cannot point opaque types",
+ "tmp.zig:3:16: error: C pointers cannot point to opaque types",
});
cases.add("directly embedding opaque type in struct and union",
--
2.54.0
From c8050a931c11e34bc6f4723eaed30f0a1bde5b14 Mon Sep 17 00:00:00 2001
From: daurnimator
Date: Sun, 8 Mar 2020 19:18:25 +1100
Subject: [PATCH 009/111] Strip trailing whitespace from src/ir.cpp
---
src/ir.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 86a5cf06170cff95ab6d70159cf2832232e9fff6..34f3ef26a73ec13d3ee82375f0ca12ebb95a58eb 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9014,7 +9014,7 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n
return irb->codegen->invalid_inst_src;
}
else_prong = prong_node;
- } else if (prong_item_count == 1 &&
+ } else if (prong_item_count == 1 &&
prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&
buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) {
if (underscore_prong) {
@@ -26068,7 +26068,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
if (array_type->data.pointer.ptr_len == PtrLenC) {
array_type = adjust_ptr_len(ira->codegen, array_type, PtrLenUnknown);
- // C pointers are allowzero by default.
+ // C pointers are allowzero by default.
// However, we want to be able to slice them without generating an allowzero slice (see issue #4401).
// To achieve this, we generate a runtime safety check and make the slice type non-allowzero.
if (array_type->data.pointer.allow_zero) {
@@ -26363,7 +26363,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
if (type_is_invalid(ptr_val->value->type))
return ira->codegen->invalid_inst_gen;
-
+
ir_build_assert_non_null(ira, &instruction->base.base, ptr_val);
}
--
2.54.0
From 5aa993cd617e0ae3cabc9c626e45a748857e2f2a Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sun, 8 Mar 2020 11:26:53 +0200
Subject: [PATCH 010/111] translate-c fix nested loops without blocks.
---
src-self-hosted/translate_c.zig | 51 +++++++++++++--------------------
test/translate_c.zig | 28 ++++++++++++++----
2 files changed, 42 insertions(+), 37 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index d24001cf9425efe4cd563d73f5da8f0329f95034..b2eb96f2ae023d4d5ebc56bfddaf26c4369b6b4f 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -2237,6 +2237,7 @@ fn transWhileLoop(
.id = .Loop,
};
while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);
+ _ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base;
}
@@ -2346,8 +2347,10 @@ fn transForLoop(
try block_scope.?.block_node.statements.push(&while_node.base);
block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block_scope.?.block_node.base;
- } else
+ } else {
+ _ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base;
+ }
}
fn transSwitch(
@@ -5431,6 +5434,8 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
//else
// @as(dest, x)
+ const lparen = try appendToken(c, .LParen, "(");
+
const if_1 = try transCreateNodeIf(c);
const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
@@ -5492,7 +5497,13 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
as.rparen_token = try appendToken(c, .RParen, ")");
else_2.body = &as.base;
- return &if_1.base;
+ const group_node = try c.a().create(ast.Node.GroupedExpression);
+ group_node.* = .{
+ .lparen = lparen,
+ .expr = &if_1.base,
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ return &group_node.base;
},
else => {
const first_tok = it.list.at(0);
@@ -5545,14 +5556,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
);
return error.ParseError;
}
- // deref is often used together with casts so we group the lhs expression
- const group = try c.a().create(ast.Node.GroupedExpression);
- group.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = node,
- .rparen = try appendToken(c, .RParen, ")"),
- };
- const deref = try transCreateNodePtrDeref(c, &group.base);
+ const deref = try transCreateNodePtrDeref(c, node);
node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
continue;
},
@@ -5596,7 +5600,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Ampersand => {
op_token = try appendToken(c, .Ampersand, "&");
- op_id .BitAnd;
+ op_id= .BitAnd;
},
.Plus => {
op_token = try appendToken(c, .Plus, "+");
@@ -5604,7 +5608,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Minus => {
op_token = try appendToken(c, .Minus, "-");
- op_id .Sub;
+ op_id= .Sub;
},
.AmpersandAmpersand => {
op_token = try appendToken(c, .Keyword_and, "and");
@@ -5676,19 +5680,17 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.BangEqual => {
op_token = try appendToken(c, .BangEqual, "!=");
- op_id = .BangEqual;
+ op_id = .BangEqual;
},
.EqualEqual => {
op_token = try appendToken(c, .EqualEqual, "==");
op_id = .EqualEqual;
},
.Slash => {
- // unsigned/float division uses the operator
op_id = .Div;
op_token = try appendToken(c, .Slash, "/");
},
.Percent => {
- // unsigned/float division uses the operator
op_id = .Mod;
op_token = try appendToken(c, .Percent, "%");
},
@@ -5729,25 +5731,12 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return &node.base;
},
.Asterisk => {
- // deref is often used together with casts so we group the lhs expression
- const group = try c.a().create(ast.Node.GroupedExpression);
- group.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
- .rparen = try appendToken(c, .RParen, ")"),
- };
- return try transCreateNodePtrDeref(c, &group.base);
+ const node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
+ return try transCreateNodePtrDeref(c, node);
},
.Ampersand => {
- // address of is often used together with casts so we group the rhs expression
const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
- const group = try c.a().create(ast.Node.GroupedExpression);
- group.* = .{
- .lparen = try appendToken(c, .LParen, "("),
- .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
- .rparen = try appendToken(c, .RParen, ")"),
- };
- node.rhs = &group.base;
+ node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
return &node.base;
},
else => {
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 3d0843d272f96fb9e12a64419113c56a0591bf15..a791d0ccad180f940f16398fa718629367d4ad4d 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,6 +3,22 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("nested loops without blocks",
+ \\void foo() {
+ \\ while (0) while (0) {}
+ \\ for (;;) while (0);
+ \\ for (;;) do {} while (0);
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() void {
+ \\ while (@as(c_int, 0) != 0) while (@as(c_int, 0) != 0) {};
+ \\ while (true) while (@as(c_int, 0) != 0) {};
+ \\ while (true) while (true) {
+ \\ if (!(@as(c_int, 0) != 0)) break;
+ \\ };
+ \\}
+ });
+
cases.add("macro comma operator",
\\#define foo (foo, bar)
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
@@ -14,7 +30,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
\\ return blk: {
- \\ _ = &(x);
+ \\ _ = &x;
\\ _ = 3;
\\ _ = 4 == 4;
\\ _ = 5 * 6;
@@ -1404,7 +1420,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{
- \\pub const NRF_GPIO = if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
+ \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
});
cases.add("basic macro function",
@@ -1993,7 +2009,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const DOT = a.b;
,
- \\pub const ARROW = (a).*.b;
+ \\pub const ARROW = a.*.b;
});
cases.add("array access",
@@ -2588,11 +2604,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO(bar) baz((void *)(baz))
\\#define BAR (void*) a
, &[_][]const u8{
- \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) {
- \\ return baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz));
+ \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
+ \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
\\}
,
- \\pub const BAR = if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a);
+ \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a));
});
cases.add("macro conditional operator",
--
2.54.0
From 692a974c3edd05944d33cd579bcb355cdd7199fc Mon Sep 17 00:00:00 2001
From: Vexu
Date: Sun, 8 Mar 2020 12:07:26 +0200
Subject: [PATCH 011/111] translate-c reject structs with VLAs
---
src-self-hosted/clang.zig | 1 +
src-self-hosted/translate_c.zig | 14 +++++++++++---
src/zig_clang.cpp | 20 ++++++++++++++++++++
src/zig_clang.h | 1 +
test/translate_c.zig | 9 +++++++++
5 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig
index bdaa8b86dc595eed940e394c8654de520a4726d5..3a3b4ac196fa1d467f2613b7b5947790c9d695cb 100644
--- a/src-self-hosted/clang.zig
+++ b/src-self-hosted/clang.zig
@@ -812,6 +812,7 @@ pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) str
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isConstantArrayType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;
+pub extern fn ZigClangType_isIncompleteOrZeroLengthArrayType(self: ?*const struct_ZigClangType, *const ZigClangASTContext) bool;
pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index b2eb96f2ae023d4d5ebc56bfddaf26c4369b6b4f..be3e43f3d71809fcc909cccb2a7111e259aaf387 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -793,6 +793,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
while (ZigClangRecordDecl_field_iterator_neq(it, end_it)) : (it = ZigClangRecordDecl_field_iterator_next(it)) {
const field_decl = ZigClangRecordDecl_field_iterator_deref(it);
const field_loc = ZigClangFieldDecl_getLocation(field_decl);
+ const field_qt = ZigClangFieldDecl_getType(field_decl);
if (ZigClangFieldDecl_isBitField(field_decl)) {
const opaque = try transCreateNodeOpaqueType(c);
@@ -801,6 +802,13 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
break :blk opaque;
}
+ if (ZigClangType_isIncompleteOrZeroLengthArrayType(qualTypeCanon(field_qt), c.clang_context)) {
+ const opaque = try transCreateNodeOpaqueType(c);
+ semicolon = try appendToken(c, .Semicolon, ";");
+ try emitWarning(c, field_loc, "{} demoted to opaque type - has variable length array", .{container_kind_name});
+ break :blk opaque;
+ }
+
var is_anon = false;
var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
@@ -809,7 +817,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
}
const field_name = try appendIdentifier(c, raw_name);
_ = try appendToken(c, .Colon, ":");
- const field_type = transQualType(rp, ZigClangFieldDecl_getType(field_decl), field_loc) catch |err| switch (err) {
+ const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) {
error.UnsupportedType => {
const opaque = try transCreateNodeOpaqueType(c);
semicolon = try appendToken(c, .Semicolon, ";");
@@ -5600,7 +5608,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Ampersand => {
op_token = try appendToken(c, .Ampersand, "&");
- op_id= .BitAnd;
+ op_id = .BitAnd;
},
.Plus => {
op_token = try appendToken(c, .Plus, "+");
@@ -5608,7 +5616,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.Minus => {
op_token = try appendToken(c, .Minus, "-");
- op_id= .Sub;
+ op_id = .Sub;
},
.AmpersandAmpersand => {
op_token = try appendToken(c, .Keyword_and, "and");
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index 8a1baa2d49f723ce157e9df54e62a2a94eb4b70a..c5ea182e87b2593f4211c2e96afa8e40ebcbc610 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -1881,6 +1881,26 @@ bool ZigClangType_isRecordType(const ZigClangType *self) {
return casted->isRecordType();
}
+bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self,
+ const struct ZigClangASTContext *ctx)
+{
+ auto casted_ctx = reinterpret_cast(ctx);
+ auto casted = reinterpret_cast(self);
+ auto casted_type = reinterpret_cast(self);
+ if (casted_type->isIncompleteArrayType())
+ return true;
+
+ clang::QualType elem_type = *casted;
+ while (const clang::ConstantArrayType *ArrayT = casted_ctx->getAsConstantArrayType(elem_type)) {
+ if (ArrayT->getSize() == 0)
+ return true;
+
+ elem_type = ArrayT->getElementType();
+ }
+
+ return false;
+}
+
bool ZigClangType_isConstantArrayType(const ZigClangType *self) {
auto casted = reinterpret_cast(self);
return casted->isConstantArrayType();
diff --git a/src/zig_clang.h b/src/zig_clang.h
index 2d9485ae9b8230df2a1fcf5c9be29c2d3002c75a..579812a84a6ab73c706762441a12dc2ed635937e 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -947,6 +947,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);
+ZIG_EXTERN_C bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self, const struct ZigClangASTContext *ctx);
ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self);
ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);
diff --git a/test/translate_c.zig b/test/translate_c.zig
index a791d0ccad180f940f16398fa718629367d4ad4d..209a301f8855adb8cd4dc99befd050f605e46a4f 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,6 +3,15 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("structs with VLAs are rejected",
+ \\struct foo { int x; int y[]; };
+ \\struct bar { int x; int y[0]; };
+ , &[_][]const u8{
+ \\pub const struct_foo = @OpaqueType();
+ ,
+ \\pub const struct_bar = @OpaqueType();
+ });
+
cases.add("nested loops without blocks",
\\void foo() {
\\ while (0) while (0) {}
--
2.54.0
From 2b1316954f169a88cfb694f4c1defc0d965455ea Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 8 Mar 2020 10:55:00 +0100
Subject: [PATCH 012/111] std: One more cpuid fix
Don't read from stale eax value, rework the logic a bit so that's clear
what's going on.
---
lib/std/zig/system/x86.zig | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/lib/std/zig/system/x86.zig b/lib/std/zig/system/x86.zig
index c85b646f83666b5ab6c974783a5d597cf83b7c9e..b4964596d2080920aad1de1ff76c34e53c2ac1c6 100644
--- a/lib/std/zig/system/x86.zig
+++ b/lib/std/zig/system/x86.zig
@@ -2,6 +2,12 @@ const std = @import("std");
const Target = std.Target;
const CrossTarget = std.zig.CrossTarget;
+const XCR0_XMM = 0x02;
+const XCR0_YMM = 0x04;
+const XCR0_MASKREG = 0x20;
+const XCR0_ZMM0_15 = 0x40;
+const XCR0_ZMM16_31 = 0x80;
+
fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {
const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));
@@ -12,6 +18,10 @@ inline fn bit(input: u32, offset: u5) bool {
return (input >> offset) & 1 != 0;
}
+inline fn hasMask(input: u32, mask: u32) bool {
+ return (input & mask) == mask;
+}
+
pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu {
var cpu = Target.Cpu{
.arch = arch,
@@ -309,7 +319,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
leaf = cpuid(1, 0);
- setFeature(cpu, .cx8, bit(leaf.edx, 8));
setFeature(cpu, .cx8, bit(leaf.edx, 8));
setFeature(cpu, .cmov, bit(leaf.edx, 15));
setFeature(cpu, .mmx, bit(leaf.edx, 23));
@@ -327,11 +336,13 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
setFeature(cpu, .aes, bit(leaf.ecx, 25));
setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
- // If the CPU supports XSAVE/XRESTORE (bit 27) and AVX (bit 28) also check
- // if the AVX registers are saved & restored on context switch
- const has_avx_save = bit(leaf.ecx, 27) and
- bit(leaf.ecx, 28) and
- ((getXCR0() & 0x6) == 0x6);
+ const has_xsave = bit(leaf.ecx, 27);
+ const has_avx = bit(leaf.ecx, 28);
+
+ // Make sure not to call xgetbv if xsave is not supported
+ const xcr0_eax = if (has_xsave and has_avx) getXCR0() else 0;
+
+ const has_avx_save = hasMask(xcr0_eax, XCR0_XMM | XCR0_YMM);
// LLVM approaches avx512_save by hardcoding it to true on Darwin,
// because the kernel saves the context even if the bit is not set.
@@ -355,7 +366,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
// set right now.
const has_avx512_save = switch (os_tag.isDarwin()) {
true => true,
- false => has_avx_save and ((leaf.eax & 0xE0) == 0xE0),
+ false => hasMask(xcr0_eax, XCR0_MASKREG | XCR0_ZMM0_15 | XCR0_ZMM16_31),
};
setFeature(cpu, .avx, has_avx_save);
@@ -530,6 +541,7 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
[leaf_ptr] "r" (&cpuid_leaf)
: "eax", "ebx", "ecx", "edx"
);
+
return cpuid_leaf;
}
--
2.54.0
From 7782c76bee0201227be730ae131171939f728538 Mon Sep 17 00:00:00 2001
From: xackus <14938807+xackus@users.noreply.github.com>
Date: Thu, 5 Mar 2020 08:32:09 +0100
Subject: [PATCH 013/111] fix failed assert on generic fn opaque return type
---
src/analyze.cpp | 42 ++++++++++++++++++++---------------------
src/analyze.hpp | 1 +
src/ir.cpp | 13 +++++++++++++
test/compile_errors.zig | 18 ++++++++++++++++--
4 files changed, 50 insertions(+), 24 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 7712f0f7070ab008afae5a31b5a98394124ab636..638a31ab5a2e6cb166e3b447c07ab67ad901befa 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1955,29 +1955,14 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
return g->builtin_types.entry_invalid;
}
- switch (specified_return_type->id) {
- case ZigTypeIdInvalid:
- zig_unreachable();
-
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- add_node_error(g, fn_proto->return_type,
- buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
- return g->builtin_types.entry_invalid;
-
- case ZigTypeIdOpaque:
- {
- ErrorMsg* msg = add_node_error(g, fn_proto->return_type,
- buf_sprintf("opaque return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
- Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name);
- if (tld != nullptr) {
- add_error_note(g, msg, tld->source_node, buf_sprintf("declared here"));
- }
- return g->builtin_types.entry_invalid;
+ if(!is_valid_return_type(specified_return_type)){
+ ErrorMsg* msg = add_node_error(g, fn_proto->return_type,
+ buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
+ Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name);
+ if (tld != nullptr) {
+ add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here"));
}
-
- default:
- break;
+ return g->builtin_types.entry_invalid;
}
if (fn_proto->auto_err_set) {
@@ -2049,6 +2034,19 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
return get_fn_type(g, &fn_type_id);
}
+bool is_valid_return_type(ZigType* type) {
+ switch (type->id) {
+ case ZigTypeIdInvalid:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdOpaque:
+ return false;
+ default:
+ return true;
+ }
+ zig_unreachable();
+}
+
bool type_is_invalid(ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
diff --git a/src/analyze.hpp b/src/analyze.hpp
index fded1e40526644a1292a596ab07b3acd7438021c..84d319bf5464ac7e63c81ff04f5823c718133a02 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -265,6 +265,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
bool fn_is_async(ZigFn *fn);
CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto);
+bool is_valid_return_type(ZigType* type);
Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
diff --git a/src/ir.cpp b/src/ir.cpp
index 34f3ef26a73ec13d3ee82375f0ca12ebb95a58eb..67eabf50402553693b51e80d1f498459d1ae5fc2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -19339,6 +19339,19 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
if (type_is_invalid(specified_return_type))
return ira->codegen->invalid_inst_gen;
+
+ if(!is_valid_return_type(specified_return_type)){
+ ErrorMsg *msg = ir_add_error(ira, source_instr,
+ buf_sprintf("call to generic function with return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
+ add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here"));
+
+ Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name);
+ if (tld != nullptr) {
+ add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("type declared here"));
+ }
+ return ira->codegen->invalid_inst_gen;
+ }
+
if (fn_proto_node->data.fn_proto.auto_err_set) {
ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn);
if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index e402197a8e2effa4fb666ef9bbfbde08f6ddc67b..006bd3ef7fe1e3e9c91ea889f5af6c28abe3edca 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -6539,8 +6539,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return error.InvalidValue;
\\}
, &[_][]const u8{
- "tmp.zig:2:18: error: opaque return type 'FooType' not allowed",
- "tmp.zig:1:1: note: declared here",
+ "tmp.zig:2:18: error: return type 'FooType' not allowed",
+ "tmp.zig:1:1: note: type declared here",
+ });
+
+ cases.add("generic function returning opaque type",
+ \\const FooType = @OpaqueType();
+ \\fn generic(comptime T: type) !T {
+ \\ return undefined;
+ \\}
+ \\export fn bar() void {
+ \\ _ = generic(FooType);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:6:16: error: call to generic function with return type 'FooType' not allowed",
+ "tmp.zig:2:1: note: function declared here",
+ "tmp.zig:1:1: note: type declared here",
});
cases.add( // fixed bug #2032
--
2.54.0
From 55077435bf53bb8273e1b23c1690798312d6abc6 Mon Sep 17 00:00:00 2001
From: LeRoyce Pearson
Date: Sun, 8 Mar 2020 14:27:49 -0600
Subject: [PATCH 014/111] Expose file inode (linux) and file index (windows)
---
lib/std/fs/file.zig | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 5b51f19f412cd669581cd60f92a26fc0cd03ee03..47f13080f4d40e6f57563163f201391bf5a417b1 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -28,6 +28,10 @@ pub const File = struct {
pub const async_block_allowed_no = if (io.is_async) false else {};
pub const Mode = os.mode_t;
+ pub const INode = switch (builtin.os.tag) {
+ .windows => os.windows.LARGE_INTEGER,
+ else => u64,
+ };
pub const default_mode = switch (builtin.os.tag) {
.windows => 0,
@@ -145,6 +149,7 @@ pub const File = struct {
}
pub const Stat = struct {
+ inode: INode,
size: u64,
mode: Mode,
@@ -174,6 +179,7 @@ pub const File = struct {
else => return windows.unexpectedStatus(rc),
}
return Stat{
+ .inode = info.InternalInformation.IndexNumber,
.size = @bitCast(u64, info.StandardInformation.EndOfFile),
.mode = 0,
.atime = windows.fromSysTime(info.BasicInformation.LastAccessTime),
@@ -187,6 +193,7 @@ pub const File = struct {
const mtime = st.mtime();
const ctime = st.ctime();
return Stat{
+ .inode = st.ino,
.size = @bitCast(u64, st.size),
.mode = st.mode,
.atime = @as(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
--
2.54.0
From e1c1ca99031a76b44ba1bdce0d10acb4513af8d6 Mon Sep 17 00:00:00 2001
From: LeRoyce Pearson
Date: Sun, 8 Mar 2020 15:47:50 -0600
Subject: [PATCH 015/111] Add documentation about Stat.inode
---
lib/std/fs/file.zig | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 47f13080f4d40e6f57563163f201391bf5a417b1..a4ce8986822af6e430f96af80df6237d8946e153 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -28,8 +28,13 @@ pub const File = struct {
pub const async_block_allowed_no = if (io.is_async) false else {};
pub const Mode = os.mode_t;
+
+ /// The type that is used to represent the inode/file index number. On windows this is a
+ /// LARGE_INTEGER (i64), and on linux this is a u64.
pub const INode = switch (builtin.os.tag) {
.windows => os.windows.LARGE_INTEGER,
+ // TODO: Handle possibility of 128 bit numbers? ReFS on windows server 2012 uses a 128 bit file
+ // index. See https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
else => u64,
};
@@ -149,7 +154,16 @@ pub const File = struct {
}
pub const Stat = struct {
+ /// A number that the system uses to point to the file metadata. This number is not guaranteed to be
+ /// unique across time, as some file systems may reuse an inode after it's file has been deleted.
+ /// Some systems may change the inode of a file over time.
+ ///
+ /// On Linux, the inode _is_ structure that stores the metadata, and the inode _number_ is what
+ /// you see here: the index number of the inode.
+ ///
+ /// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
inode: INode,
+
size: u64,
mode: Mode,
--
2.54.0
From 06d0dac0fb58c2d20036e34f5c1a1bc9c386c189 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 8 Mar 2020 19:48:35 +0100
Subject: [PATCH 016/111] ir: Prevent crash in compiler error
Anonymous containers have no struct_field->type AstNode set, let's
always use the field node itself to make the error messages consistent.
Closes #4691
---
src/analyze.cpp | 4 ++--
test/compile_errors.zig | 9 +++++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 7712f0f7070ab008afae5a31b5a98394124ab636..c7bd7094d7daf10f4b0be5ccdf1e8536b7a2e0ea 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2893,7 +2893,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
return ErrorSemanticAnalyzeFail;
}
if (field_is_opaque_type) {
- add_node_error(g, field_node->data.struct_field.type,
+ add_node_error(g, field_node,
buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
@@ -3185,7 +3185,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
return ErrorSemanticAnalyzeFail;
}
if (field_is_opaque_type) {
- add_node_error(g, field_node->data.struct_field.type,
+ add_node_error(g, field_node,
buf_create_from_str(
"opaque types have unknown size and therefore cannot be directly embedded in unions"));
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index e402197a8e2effa4fb666ef9bbfbde08f6ddc67b..2b74d8fc7712fd9c9fff6df37bff9fa8160c0a73 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1610,9 +1610,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn b() void {
\\ var bar: Bar = undefined;
\\}
+ \\export fn c() void {
+ \\ var baz: *@OpaqueType() = undefined;
+ \\ const qux = .{baz.*};
+ \\}
, &[_][]const u8{
- "tmp.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
- "tmp.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
+ "tmp.zig:3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
+ "tmp.zig:7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
+ "tmp.zig:17:22: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
});
cases.add("implicit cast between C pointer and Zig pointer - bad const/align/child",
--
2.54.0
From e2fd289a33bb35cf4b86daa4d80adb7cc0c2c2b0 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 3 Mar 2020 12:13:13 +0100
Subject: [PATCH 017/111] ir: Create usize result_loc for array subscript expr
Allow the subscript expression to infer the resulting type.
Closes #4169
---
src/ir.cpp | 14 +++++++++++---
test/compile_errors.zig | 4 ++--
test/stage1/behavior/array.zig | 18 +++++++++++++++++-
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 34f3ef26a73ec13d3ee82375f0ca12ebb95a58eb..110778fb9a04cfeb13117afb9a18e46c886c7d26 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -5910,10 +5910,18 @@ static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *
if (array_ref_instruction == irb->codegen->invalid_inst_src)
return array_ref_instruction;
+ // Create an usize-typed result location to hold the subscript value, this
+ // makes it possible for the compiler to infer the subscript expression type
+ // if needed
+ IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
+ ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc());
+
AstNode *subscript_node = node->data.array_access_expr.subscript;
- IrInstSrc *subscript_instruction = ir_gen_node(irb, subscript_node, scope);
- if (subscript_instruction == irb->codegen->invalid_inst_src)
- return subscript_instruction;
+ IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base);
+ if (subscript_value == irb->codegen->invalid_inst_src)
+ return irb->codegen->invalid_inst_src;
+
+ IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast);
IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
subscript_instruction, true, PtrLenSingle, nullptr);
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 2b74d8fc7712fd9c9fff6df37bff9fa8160c0a73..717793baaa1c00c9a6b65683b2fb91ae89d0d6e5 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -3610,11 +3610,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add("array access of non array",
\\export fn f() void {
\\ var bad : bool = undefined;
- \\ bad[bad] = bad[bad];
+ \\ bad[0] = bad[0];
\\}
\\export fn g() void {
\\ var bad : bool = undefined;
- \\ _ = bad[bad];
+ \\ _ = bad[0];
\\}
, &[_][]const u8{
"tmp.zig:3:8: error: array access of non-array type 'bool'",
diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig
index 7ac1e8197db591e3c6815c5a044abbac2aae23eb..da56864cc91b8ed1251784424d107e1fa5547e64 100644
--- a/test/stage1/behavior/array.zig
+++ b/test/stage1/behavior/array.zig
@@ -1,6 +1,8 @@
const std = @import("std");
-const expect = std.testing.expect;
+const testing = std.testing;
const mem = std.mem;
+const expect = testing.expect;
+const expectEqual = testing.expectEqual;
test "arrays" {
var array: [5]u32 = undefined;
@@ -360,3 +362,17 @@ test "access the null element of a null terminated array" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "type deduction for array subscript expression" {
+ const S = struct {
+ fn doTheTest() void {
+ var array = [_]u8{ 0x55, 0xAA };
+ var v0 = true;
+ expectEqual(@as(u8, 0xAA), array[if (v0) 1 else 0]);
+ var v1 = false;
+ expectEqual(@as(u8, 0x55), array[if (v1) 1 else 0]);
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
--
2.54.0
From cb84875eed42b4721de5b2cc356c4a6719eb0516 Mon Sep 17 00:00:00 2001
From: LeRoyce Pearson
Date: Sun, 8 Mar 2020 18:31:18 -0600
Subject: [PATCH 018/111] Define ino_t for systems not yet defining it
Also, use ino_t instead of u64 in fs.File.INode
---
lib/std/fs/file.zig | 2 +-
lib/std/os/bits/darwin.zig | 3 ++-
lib/std/os/bits/dragonfly.zig | 4 +++-
lib/std/os/bits/freebsd.zig | 3 ++-
lib/std/os/bits/linux/x86_64.zig | 3 ++-
lib/std/os/bits/netbsd.zig | 3 ++-
lib/std/os/bits/wasi.zig | 1 +
7 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index a4ce8986822af6e430f96af80df6237d8946e153..33307a9dd694f7ef6a9c46477034de3818ddcc63 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -35,7 +35,7 @@ pub const File = struct {
.windows => os.windows.LARGE_INTEGER,
// TODO: Handle possibility of 128 bit numbers? ReFS on windows server 2012 uses a 128 bit file
// index. See https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
- else => u64,
+ else => os.ino_t,
};
pub const default_mode = switch (builtin.os.tag) {
diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig
index fb933c6698d524b16ff43f436cd8488ce3525138..6808af0315f6d510a5fd7955b5c3cdd29c27b0ed 100644
--- a/lib/std/os/bits/darwin.zig
+++ b/lib/std/os/bits/darwin.zig
@@ -53,6 +53,7 @@ pub const mach_timebase_info_data = extern struct {
};
pub const off_t = i64;
+pub const ino_t = u64;
/// Renamed to Stat to not conflict with the stat function.
/// atime, mtime, and ctime have functions to return `timespec`,
@@ -64,7 +65,7 @@ pub const Stat = extern struct {
dev: i32,
mode: u16,
nlink: u16,
- ino: u64,
+ ino: ino_t,
uid: u32,
gid: u32,
rdev: i32,
diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig
index c6c23affa76d5c13f6169a826374dd87b1667c3a..27b2733b76d7c418ffe58d50db6ed8788c1ef88d 100644
--- a/lib/std/os/bits/dragonfly.zig
+++ b/lib/std/os/bits/dragonfly.zig
@@ -138,8 +138,10 @@ pub const MAP_SIZEALIGN = 262144;
pub const PATH_MAX = 1024;
+pub const ino_t = c_ulong;
+
pub const Stat = extern struct {
- ino: c_ulong,
+ ino: ino_t,
nlink: c_uint,
dev: c_uint,
mode: c_ushort,
diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig
index b7d14934f5e4b400151fed7265f634a68b3c19e0..02fe7e75b3f05f426f56985e9e952195598a11f6 100644
--- a/lib/std/os/bits/freebsd.zig
+++ b/lib/std/os/bits/freebsd.zig
@@ -98,6 +98,7 @@ pub const msghdr_const = extern struct {
};
pub const off_t = i64;
+pub const ino_t = u64;
/// Renamed to Stat to not conflict with the stat function.
/// atime, mtime, and ctime have functions to return `timespec`,
@@ -107,7 +108,7 @@ pub const off_t = i64;
/// methods to accomplish this.
pub const Stat = extern struct {
dev: u64,
- ino: u64,
+ ino: ino_t,
nlink: usize,
mode: u16,
diff --git a/lib/std/os/bits/linux/x86_64.zig b/lib/std/os/bits/linux/x86_64.zig
index 608f74e2d3111913d42b5194ed7554ca394209a7..e92591d94eac7309889de7c79890ed8277a6605d 100644
--- a/lib/std/os/bits/linux/x86_64.zig
+++ b/lib/std/os/bits/linux/x86_64.zig
@@ -481,6 +481,7 @@ pub const msghdr_const = extern struct {
};
pub const off_t = i64;
+pub const ino_t = u64;
/// Renamed to Stat to not conflict with the stat function.
/// atime, mtime, and ctime have functions to return `timespec`,
@@ -490,7 +491,7 @@ pub const off_t = i64;
/// methods to accomplish this.
pub const Stat = extern struct {
dev: u64,
- ino: u64,
+ ino: ino_t,
nlink: usize,
mode: u32,
diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig
index 89e0998d6d26fe5ab90967f71e4f7d66e4d0e166..735485695a4a591231b5a1b922e16aa1ba63403f 100644
--- a/lib/std/os/bits/netbsd.zig
+++ b/lib/std/os/bits/netbsd.zig
@@ -69,6 +69,7 @@ pub const msghdr_const = extern struct {
};
pub const off_t = i64;
+pub const ino_t = u64;
/// Renamed to Stat to not conflict with the stat function.
/// atime, mtime, and ctime have functions to return `timespec`,
@@ -79,7 +80,7 @@ pub const off_t = i64;
pub const Stat = extern struct {
dev: u64,
mode: u32,
- ino: u64,
+ ino: ino_t,
nlink: usize,
uid: u32,
diff --git a/lib/std/os/bits/wasi.zig b/lib/std/os/bits/wasi.zig
index f56e53504e32da1eb337f127e11457c41c8ab0f7..8fb85e1fcda19dcceeb342316cc19e9779fd9715 100644
--- a/lib/std/os/bits/wasi.zig
+++ b/lib/std/os/bits/wasi.zig
@@ -178,6 +178,7 @@ pub const FILESTAT_SET_MTIM: fstflags_t = 0x0004;
pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008;
pub const inode_t = u64;
+pub const ino_t = inode_t;
pub const linkcount_t = u32;
--
2.54.0
From 25d9ab95dd8a691963453c4507d519051eaebb0c Mon Sep 17 00:00:00 2001
From: LeRoyce Pearson
Date: Sun, 8 Mar 2020 21:52:36 -0600
Subject: [PATCH 019/111] Use os.ino_t for everything
Also, define ino_t for windows
---
lib/std/fs/file.zig | 11 +----------
lib/std/os/bits/windows.zig | 1 +
2 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 33307a9dd694f7ef6a9c46477034de3818ddcc63..8f7a46ad3e97144ad2c30dd80a88bb9f108a83c9 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -29,15 +29,6 @@ pub const File = struct {
pub const Mode = os.mode_t;
- /// The type that is used to represent the inode/file index number. On windows this is a
- /// LARGE_INTEGER (i64), and on linux this is a u64.
- pub const INode = switch (builtin.os.tag) {
- .windows => os.windows.LARGE_INTEGER,
- // TODO: Handle possibility of 128 bit numbers? ReFS on windows server 2012 uses a 128 bit file
- // index. See https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
- else => os.ino_t,
- };
-
pub const default_mode = switch (builtin.os.tag) {
.windows => 0,
else => 0o666,
@@ -162,7 +153,7 @@ pub const File = struct {
/// you see here: the index number of the inode.
///
/// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
- inode: INode,
+ inode: os.ino_t,
size: u64,
mode: Mode,
diff --git a/lib/std/os/bits/windows.zig b/lib/std/os/bits/windows.zig
index ba2725e0a94849dd8bb21e0c1276c56e25febad0..05486c8f7ba78f59aa92d823a2b37f230fa52c79 100644
--- a/lib/std/os/bits/windows.zig
+++ b/lib/std/os/bits/windows.zig
@@ -4,6 +4,7 @@ usingnamespace @import("../windows/bits.zig");
const ws2_32 = @import("../windows/ws2_32.zig");
pub const fd_t = HANDLE;
+pub const ino_t = LARGE_INTEGER;
pub const pid_t = HANDLE;
pub const mode_t = u0;
--
2.54.0
From 6f8d732599461aa816f545b658a068eceb6ac9bc Mon Sep 17 00:00:00 2001
From: Vexu
Date: Mon, 9 Mar 2020 11:02:16 +0200
Subject: [PATCH 020/111] update parsers to new noasync syntax
---
lib/std/zig/ast.zig | 29 ++++++++++++++++++--
lib/std/zig/parse.zig | 62 +++++++++++++++++++++++++-----------------
lib/std/zig/render.zig | 9 ++++--
src/all_types.hpp | 7 ++++-
src/ast_render.cpp | 8 ++++++
src/parser.cpp | 36 ++++++++++++++++--------
6 files changed, 108 insertions(+), 43 deletions(-)
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index bc4f6350d61247645af1d25d439ef208b0d24481..711806b810660e13dee19a710fc3f661294b9043 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -431,6 +431,7 @@ pub const Node = struct {
ContainerDecl,
Asm,
Comptime,
+ Noasync,
Block,
// Misc
@@ -1078,6 +1079,30 @@ pub const Node = struct {
}
};
+ pub const Noasync = struct {
+ base: Node = Node{ .id = .Noasync },
+ doc_comments: ?*DocComment,
+ noasync_token: TokenIndex,
+ expr: *Node,
+
+ pub fn iterate(self: *Noasync, index: usize) ?*Node {
+ var i = index;
+
+ if (i < 1) return self.expr;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: *const Noasync) TokenIndex {
+ return self.noasync_token;
+ }
+
+ pub fn lastToken(self: *const Noasync) TokenIndex {
+ return self.expr.lastToken();
+ }
+ };
+
pub const Payload = struct {
base: Node = Node{ .id = .Payload },
lpipe: TokenIndex,
@@ -1560,9 +1585,7 @@ pub const Node = struct {
pub const Op = union(enum) {
AddressOf,
ArrayType: ArrayInfo,
- Await: struct {
- noasync_token: ?TokenIndex = null,
- },
+ Await,
BitNot,
BoolNot,
Cancel,
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index cadf25eef6bf1132866bfe05d99869a7ad5cb160..5392c18dfe2f1f6ceba397361cfadd7864e41759 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -856,6 +856,7 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
/// / IfExpr
/// / KEYWORD_break BreakLabel? Expr?
/// / KEYWORD_comptime Expr
+/// / KEYWORD_noasync Expr
/// / KEYWORD_continue BreakLabel?
/// / KEYWORD_resume Expr
/// / KEYWORD_return Expr?
@@ -870,7 +871,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
const label = try parseBreakLabel(arena, it, tree);
const expr_node = try parseExpr(arena, it, tree);
const node = try arena.create(Node.ControlFlowExpression);
- node.* = Node.ControlFlowExpression{
+ node.* = .{
.ltoken = token,
.kind = Node.ControlFlowExpression.Kind{ .Break = label },
.rhs = expr_node,
@@ -883,7 +884,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
.ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
});
const node = try arena.create(Node.Comptime);
- node.* = Node.Comptime{
+ node.* = .{
.doc_comments = null,
.comptime_token = token,
.expr = expr_node,
@@ -891,10 +892,23 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
return &node.base;
}
+ if (eatToken(it, .Keyword_noasync)) |token| {
+ const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
+ .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
+ });
+ const node = try arena.create(Node.Noasync);
+ node.* = .{
+ .doc_comments = null,
+ .noasync_token = token,
+ .expr = expr_node,
+ };
+ return &node.base;
+ }
+
if (eatToken(it, .Keyword_continue)) |token| {
const label = try parseBreakLabel(arena, it, tree);
const node = try arena.create(Node.ControlFlowExpression);
- node.* = Node.ControlFlowExpression{
+ node.* = .{
.ltoken = token,
.kind = Node.ControlFlowExpression.Kind{ .Continue = label },
.rhs = null,
@@ -907,7 +921,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
.ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
});
const node = try arena.create(Node.PrefixOp);
- node.* = Node.PrefixOp{
+ node.* = .{
.op_token = token,
.op = Node.PrefixOp.Op.Resume,
.rhs = expr_node,
@@ -918,7 +932,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
if (eatToken(it, .Keyword_return)) |token| {
const expr_node = try parseExpr(arena, it, tree);
const node = try arena.create(Node.ControlFlowExpression);
- node.* = Node.ControlFlowExpression{
+ node.* = .{
.ltoken = token,
.kind = Node.ControlFlowExpression.Kind.Return,
.rhs = expr_node,
@@ -1126,19 +1140,18 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
/// SuffixExpr
/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
-/// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
- const maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);
+ const maybe_async = eatToken(it, .Keyword_async);
if (maybe_async) |async_token| {
const token_fn = eatToken(it, .Keyword_fn);
- if (async_token.ptr.id == .Keyword_async and token_fn != null) {
+ if (token_fn != null) {
// HACK: If we see the keyword `fn`, then we assume that
// we are parsing an async fn proto, and not a call.
// We therefore put back all tokens consumed by the async
// prefix...
putBackToken(it, token_fn.?);
- putBackToken(it, async_token.index);
+ putBackToken(it, async_token);
return parsePrimaryTypeExpr(arena, it, tree);
}
// TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
@@ -1167,7 +1180,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
.op = Node.SuffixOp.Op{
.Call = Node.SuffixOp.Op.Call{
.params = params.list,
- .async_token = async_token.index,
+ .async_token = async_token,
},
},
.rtoken = params.rparen,
@@ -1224,6 +1237,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
/// / IfTypeExpr
/// / INTEGER
/// / KEYWORD_comptime TypeExpr
+/// / KEYWORD_noasync TypeExpr
/// / KEYWORD_error DOT IDENTIFIER
/// / KEYWORD_false
/// / KEYWORD_null
@@ -1255,13 +1269,23 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
if (eatToken(it, .Keyword_comptime)) |token| {
const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
const node = try arena.create(Node.Comptime);
- node.* = Node.Comptime{
+ node.* = .{
.doc_comments = null,
.comptime_token = token,
.expr = expr,
};
return &node.base;
}
+ if (eatToken(it, .Keyword_noasync)) |token| {
+ const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
+ const node = try arena.create(Node.Noasync);
+ node.* = .{
+ .doc_comments = null,
+ .noasync_token = token,
+ .expr = expr,
+ };
+ return &node.base;
+ }
if (eatToken(it, .Keyword_error)) |token| {
const period = try expectToken(it, tree, .Period);
const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
@@ -1269,7 +1293,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
});
const global_error_set = try createLiteral(arena, Node.ErrorType, token);
const node = try arena.create(Node.InfixOp);
- node.* = Node.InfixOp{
+ node.* = .{
.op_token = period,
.lhs = global_error_set,
.op = Node.InfixOp.Op.Period,
@@ -1281,7 +1305,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token);
if (eatToken(it, .Keyword_anyframe)) |token| {
const node = try arena.create(Node.AnyFrameType);
- node.* = Node.AnyFrameType{
+ node.* = .{
.anyframe_token = token,
.result = null,
};
@@ -2180,18 +2204,6 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
.Ampersand => ops{ .AddressOf = {} },
.Keyword_try => ops{ .Try = {} },
.Keyword_await => ops{ .Await = .{} },
- .Keyword_noasync => if (eatToken(it, .Keyword_await)) |await_tok| {
- const node = try arena.create(Node.PrefixOp);
- node.* = Node.PrefixOp{
- .op_token = await_tok,
- .op = .{ .Await = .{ .noasync_token = token.index } },
- .rhs = undefined, // set by caller
- };
- return &node.base;
- } else {
- putBackToken(it, token.index);
- return null;
- },
else => {
putBackToken(it, token.index);
return null;
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index 625aef31319732cc1c540054277a61dccac11b77..ce9049e35bebabc1552b815f7c216bb16f482f1e 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -390,6 +390,12 @@ fn renderExpression(
try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
},
+ .Noasync => {
+ const noasync_node = @fieldParentPtr(ast.Node.Noasync, "base", base);
+
+ try renderToken(tree, stream, noasync_node.noasync_token, indent, start_col, Space.Space);
+ return renderExpression(allocator, stream, tree, indent, start_col, noasync_node.expr, space);
+ },
.Suspend => {
const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
@@ -590,9 +596,6 @@ fn renderExpression(
},
.Await => |await_info| {
- if (await_info.noasync_token) |tok| {
- try renderToken(tree, stream, tok, indent, start_col, Space.Space);
- }
try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
},
}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2a3ab2041a70b91cc7d086ca8a792132e2024d4d..ec839ffb4961701cd4d70c36540ad9c6f703fb0a 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -651,6 +651,7 @@ enum NodeType {
NodeTypeSwitchProng,
NodeTypeSwitchRange,
NodeTypeCompTime,
+ NodeTypeNoAsync,
NodeTypeBreak,
NodeTypeContinue,
NodeTypeAsmExpr,
@@ -991,6 +992,10 @@ struct AstNodeCompTime {
AstNode *expr;
};
+struct AstNodeNoAsync {
+ AstNode *expr;
+};
+
struct AsmOutput {
Buf *asm_symbolic_name;
Buf *constraint;
@@ -1148,7 +1153,6 @@ struct AstNodeErrorType {
};
struct AstNodeAwaitExpr {
- Token *noasync_token;
AstNode *expr;
};
@@ -1199,6 +1203,7 @@ struct AstNode {
AstNodeSwitchProng switch_prong;
AstNodeSwitchRange switch_range;
AstNodeCompTime comptime_expr;
+ AstNodeNoAsync noasync_expr;
AstNodeAsmExpr asm_expr;
AstNodeFieldAccessExpr field_access_expr;
AstNodePtrDerefExpr ptr_deref_expr;
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index d8d0d6c0e2a85d8352b537a2e7f95a1adc4b3160..6bc21ce970f0bf985978810ba81dcc68ec27fe3c 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -220,6 +220,8 @@ static const char *node_type_str(NodeType node_type) {
return "SwitchRange";
case NodeTypeCompTime:
return "CompTime";
+ case NodeTypeNoAsync:
+ return "NoAsync";
case NodeTypeBreak:
return "Break";
case NodeTypeContinue:
@@ -1091,6 +1093,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
render_node_grouped(ar, node->data.comptime_expr.expr);
break;
}
+ case NodeTypeNoAsync:
+ {
+ fprintf(ar->f, "noasync ");
+ render_node_grouped(ar, node->data.noasync_expr.expr);
+ break;
+ }
case NodeTypeForExpr:
{
if (node->data.for_expr.name != nullptr) {
diff --git a/src/parser.cpp b/src/parser.cpp
index 3a3e13f1d8291973a62fa0db0aa985f65096bbb3..7ff24db1849a173085719bd07f0e26cb673ebba9 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1237,6 +1237,7 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
// / IfExpr
// / KEYWORD_break BreakLabel? Expr?
// / KEYWORD_comptime Expr
+// / KEYWORD_noasync Expr
// / KEYWORD_continue BreakLabel?
// / KEYWORD_resume Expr
// / KEYWORD_return Expr?
@@ -1271,6 +1272,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
return res;
}
+ Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
+ if (noasync != nullptr) {
+ AstNode *expr = ast_expect(pc, ast_parse_expr);
+ AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
+ res->data.noasync_expr.expr = expr;
+ return res;
+ }
+
Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue);
if (continue_token != nullptr) {
Token *label = ast_parse_break_label(pc);
@@ -1459,13 +1468,11 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
// SuffixExpr
// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
-// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
- Token *async_token = eat_token(pc);
- bool is_async = async_token->id == TokenIdKeywordAsync;
- if (is_async || async_token->id == TokenIdKeywordNoAsync) {
- if (is_async && eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
+ Token *async_token = eat_token_if(pc, TokenIdKeywordAsync);
+ if (async_token) {
+ if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
// HACK: If we see the keyword `fn`, then we assume that
// we are parsing an async fn proto, and not a call.
// We therefore put back all tokens consumed by the async
@@ -1515,13 +1522,12 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
assert(args->type == NodeTypeFnCallExpr);
AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
- res->data.fn_call_expr.modifier = is_async ? CallModifierAsync : CallModifierNoAsync;
+ res->data.fn_call_expr.modifier = CallModifierAsync;
res->data.fn_call_expr.seen = false;
res->data.fn_call_expr.fn_ref_expr = child;
res->data.fn_call_expr.params = args->data.fn_call_expr.params;
return res;
}
- put_back_token(pc);
AstNode *res = ast_parse_primary_type_expr(pc);
if (res == nullptr)
@@ -1582,6 +1588,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
// / IfTypeExpr
// / INTEGER
// / KEYWORD_comptime TypeExpr
+// / KEYWORD_noasync TypeExpr
// / KEYWORD_error DOT IDENTIFIER
// / KEYWORD_false
// / KEYWORD_null
@@ -1683,6 +1690,14 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
return res;
}
+ Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
+ if (noasync != nullptr) {
+ AstNode *expr = ast_expect(pc, ast_parse_type_expr);
+ AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
+ res->data.noasync_expr.expr = expr;
+ return res;
+ }
+
Token *error = eat_token_if(pc, TokenIdKeywordError);
if (error != nullptr) {
Token *dot = expect_token(pc, TokenIdDot);
@@ -2599,14 +2614,10 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {
return res;
}
- Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync);
Token *await = eat_token_if(pc, TokenIdKeywordAwait);
if (await != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
- res->data.await_expr.noasync_token = noasync_token;
return res;
- } else if (noasync_token != nullptr) {
- put_back_token(pc);
}
return nullptr;
@@ -3125,6 +3136,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeCompTime:
visit_field(&node->data.comptime_expr.expr, visit, context);
break;
+ case NodeTypeNoAsync:
+ visit_field(&node->data.comptime_expr.expr, visit, context);
+ break;
case NodeTypeBreak:
// none
break;
--
2.54.0
From 3618256c97a9988f7d623eeabb667010ca30656f Mon Sep 17 00:00:00 2001
From: Vexu
Date: Mon, 9 Mar 2020 12:31:36 +0200
Subject: [PATCH 021/111] implement noasync scopes
---
src/all_types.hpp | 6 +++++
src/analyze.cpp | 9 +++++++
src/analyze.hpp | 1 +
src/codegen.cpp | 2 ++
src/ir.cpp | 52 +++++++++++++++++++++++++++++++++++++++--
test/compile_errors.zig | 9 +++++++
6 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index ec839ffb4961701cd4d70c36540ad9c6f703fb0a..14b99228ca1c3fe8ef1f2f15155f39840055267e 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2330,6 +2330,7 @@ enum ScopeId {
ScopeIdRuntime,
ScopeIdTypeOf,
ScopeIdExpr,
+ ScopeIdNoAsync,
};
struct Scope {
@@ -2462,6 +2463,11 @@ struct ScopeCompTime {
Scope base;
};
+// This scope is created for a noasync expression.
+// NodeTypeNoAsync
+struct ScopeNoAsync {
+ Scope base;
+};
// This scope is created for a function definition.
// NodeTypeFnDef
diff --git a/src/analyze.cpp b/src/analyze.cpp
index c7bd7094d7daf10f4b0be5ccdf1e8536b7a2e0ea..d924002426ec0efe1077554c47d7f8334244ae2e 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -106,6 +106,7 @@ static ScopeExpr *find_expr_scope(Scope *scope) {
case ScopeIdDecls:
case ScopeIdFnDef:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdVarDecl:
case ScopeIdCImport:
case ScopeIdSuspend:
@@ -226,6 +227,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {
return &scope->base;
}
+Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent) {
+ ScopeNoAsync *scope = heap::c_allocator.create();
+ init_scope(g, &scope->base, ScopeIdNoAsync, node, parent);
+ return &scope->base;
+}
+
Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) {
ScopeTypeOf *scope = heap::c_allocator.create();
init_scope(g, &scope->base, ScopeIdTypeOf, node, parent);
@@ -3755,6 +3762,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeCompTime:
preview_comptime_decl(g, node, decls_scope);
break;
+ case NodeTypeNoAsync:
case NodeTypeParamDecl:
case NodeTypeReturnExpr:
case NodeTypeDefer:
@@ -6176,6 +6184,7 @@ static void mark_suspension_point(Scope *scope) {
case ScopeIdDecls:
case ScopeIdFnDef:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdCImport:
case ScopeIdSuspend:
case ScopeIdTypeOf:
diff --git a/src/analyze.hpp b/src/analyze.hpp
index fded1e40526644a1292a596ab07b3acd7438021c..98d09d452f8d33d9ffa39dda9a5ea754f4de172b 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -125,6 +125,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
+Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);
Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index ef567c27aae7a2286e7520bc135fb9b3db4cd6a5..52ac2e79366723c0215f1d03041b114315b6750c 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -687,6 +687,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
case ScopeIdLoop:
case ScopeIdSuspend:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdRuntime:
case ScopeIdTypeOf:
case ScopeIdExpr:
@@ -3934,6 +3935,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
case ScopeIdLoop:
case ScopeIdSuspend:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdRuntime:
case ScopeIdTypeOf:
case ScopeIdExpr:
diff --git a/src/ir.cpp b/src/ir.cpp
index 110778fb9a04cfeb13117afb9a18e46c886c7d26..6a387e12e06e213939695d200af1819a431b6e26 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -4978,6 +4978,7 @@ static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_
case ScopeIdLoop:
case ScopeIdSuspend:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdRuntime:
case ScopeIdTypeOf:
case ScopeIdExpr:
@@ -5033,6 +5034,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope
case ScopeIdLoop:
case ScopeIdSuspend:
case ScopeIdCompTime:
+ case ScopeIdNoAsync:
case ScopeIdRuntime:
case ScopeIdTypeOf:
case ScopeIdExpr:
@@ -7307,6 +7309,31 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
zig_unreachable();
}
+static bool is_noasync_scope(Scope *scope) {
+ for (;;) {
+ switch (scope->id) {
+ case ScopeIdNoAsync:
+ return true;
+ case ScopeIdDefer:
+ case ScopeIdDeferExpr:
+ case ScopeIdDecls:
+ case ScopeIdFnDef:
+ case ScopeIdCompTime:
+ case ScopeIdVarDecl:
+ case ScopeIdCImport:
+ case ScopeIdSuspend:
+ return false;
+ case ScopeIdExpr:
+ case ScopeIdTypeOf:
+ case ScopeIdBlock:
+ case ScopeIdLoop:
+ case ScopeIdRuntime:
+ scope = scope->parent;
+ continue;
+ }
+ }
+}
+
static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval,
ResultLoc *result_loc)
{
@@ -7315,8 +7342,19 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,
if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
+ bool is_noasync = is_noasync_scope(scope);
+ CallModifier modifier = node->data.fn_call_expr.modifier;
+ if (is_noasync) {
+ if (modifier == CallModifierAsync) {
+ add_node_error(irb->codegen, node,
+ buf_sprintf("async call in noasync scope"));
+ return irb->codegen->invalid_inst_src;
+ }
+ modifier = CallModifierNoAsync;
+ }
+
AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
- return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, node->data.fn_call_expr.modifier,
+ return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier,
nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc);
}
@@ -9170,6 +9208,14 @@ static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNod
return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
}
+static IrInstSrc *ir_gen_noasync(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) {
+ assert(node->type == NodeTypeNoAsync);
+
+ Scope *child_scope = create_noasync_scope(irb->codegen, node, parent_scope);
+ // purposefully pass null for result_loc and let EndExpr handle it
+ return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
+}
+
static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
IrInstSrc *is_comptime;
if (ir_should_inline(irb->exec, break_scope)) {
@@ -9763,7 +9809,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
{
assert(node->type == NodeTypeAwaitExpr);
- bool is_noasync = node->data.await_expr.noasync_token != nullptr;
+ bool is_noasync = is_noasync_scope(scope);
AstNode *expr_node = node->data.await_expr.expr;
if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
@@ -9938,6 +9984,8 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
return ir_gen_switch_expr(irb, scope, node, lval, result_loc);
case NodeTypeCompTime:
return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc);
+ case NodeTypeNoAsync:
+ return ir_expr_wrap(irb, scope, ir_gen_noasync(irb, scope, node, lval), result_loc);
case NodeTypeErrorType:
return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);
case NodeTypeBreak:
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 717793baaa1c00c9a6b65683b2fb91ae89d0d6e5..7021f8155458a727963e75f393b8f91f207bfd2e 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest("combination of noasync and async",
+ \\export fn entry() void {
+ \\ noasync async foo();
+ \\}
+ \\fn foo() void {}
+ , &[_][]const u8{
+ "tmp.zig:2:13: error: async call in noasync scope",
+ });
+
cases.addTest("@TypeOf with no arguments",
\\export fn entry() void {
\\ _ = @TypeOf();
--
2.54.0
From 03c1431f9c0b651f3f1853f11112edc07555883d Mon Sep 17 00:00:00 2001
From: Vexu
Date: Mon, 9 Mar 2020 15:51:51 +0200
Subject: [PATCH 022/111] disallow resume and suspend in noasync scopes
---
lib/std/zig/ast.zig | 1 -
lib/std/zig/parse.zig | 16 ++++++++++++++--
src/ir.cpp | 44 ++++++++++++++++++++-----------------------
src/parser.cpp | 9 +++++++++
4 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 711806b810660e13dee19a710fc3f661294b9043..54115196674095a39f4676caba0014a5f2565bd4 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -1081,7 +1081,6 @@ pub const Node = struct {
pub const Noasync = struct {
base: Node = Node{ .id = .Noasync },
- doc_comments: ?*DocComment,
noasync_token: TokenIndex,
expr: *Node,
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index 5392c18dfe2f1f6ceba397361cfadd7864e41759..9a574c6231203a71a88762c2c3df460a2bbabf03 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -462,6 +462,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
/// Statement
/// <- KEYWORD_comptime? VarDecl
/// / KEYWORD_comptime BlockExprStatement
+/// / KEYWORD_noasync BlockExprStatement
/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
/// / KEYWORD_defer BlockExprStatement
/// / KEYWORD_errdefer BlockExprStatement
@@ -493,6 +494,19 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
return &node.base;
}
+ if (eatToken(it, .Keyword_noasync)) |noasync_token| {
+ const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, .{
+ .ExpectedBlockOrAssignment = .{ .token = it.index },
+ });
+
+ const node = try arena.create(Node.Noasync);
+ node.* = .{
+ .noasync_token = noasync_token,
+ .expr = block_expr,
+ };
+ return &node.base;
+ }
+
if (eatToken(it, .Keyword_suspend)) |suspend_token| {
const semicolon = eatToken(it, .Semicolon);
@@ -898,7 +912,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
});
const node = try arena.create(Node.Noasync);
node.* = .{
- .doc_comments = null,
.noasync_token = token,
.expr = expr_node,
};
@@ -1280,7 +1293,6 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
const node = try arena.create(Node.Noasync);
node.* = .{
- .doc_comments = null,
.noasync_token = token,
.expr = expr,
};
diff --git a/src/ir.cpp b/src/ir.cpp
index 6a387e12e06e213939695d200af1819a431b6e26..50ace888cda8926aecaff368ac6aa10263ed9be0 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -7309,29 +7309,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
zig_unreachable();
}
-static bool is_noasync_scope(Scope *scope) {
- for (;;) {
- switch (scope->id) {
- case ScopeIdNoAsync:
- return true;
- case ScopeIdDefer:
- case ScopeIdDeferExpr:
- case ScopeIdDecls:
- case ScopeIdFnDef:
- case ScopeIdCompTime:
- case ScopeIdVarDecl:
- case ScopeIdCImport:
- case ScopeIdSuspend:
- return false;
- case ScopeIdExpr:
- case ScopeIdTypeOf:
- case ScopeIdBlock:
- case ScopeIdLoop:
- case ScopeIdRuntime:
- scope = scope->parent;
- continue;
- }
+static ScopeNoAsync *get_scope_noasync(Scope *scope) {
+ while (scope) {
+ if (scope->id == ScopeIdNoAsync)
+ return (ScopeNoAsync *)scope;
+ if (scope->id == ScopeIdFnDef)
+ return nullptr;
+
+ scope = scope->parent;
}
+ return nullptr;
}
static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval,
@@ -7342,7 +7329,7 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,
if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
- bool is_noasync = is_noasync_scope(scope);
+ bool is_noasync = get_scope_noasync(scope) != nullptr;
CallModifier modifier = node->data.fn_call_expr.modifier;
if (is_noasync) {
if (modifier == CallModifierAsync) {
@@ -9796,6 +9783,10 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeResume);
+ if (get_scope_noasync(scope) != nullptr) {
+ add_node_error(irb->codegen, node, buf_sprintf("resume in noasync scope"));
+ return irb->codegen->invalid_inst_src;
+ }
IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr);
if (target_inst == irb->codegen->invalid_inst_src)
@@ -9809,7 +9800,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
{
assert(node->type == NodeTypeAwaitExpr);
- bool is_noasync = is_noasync_scope(scope);
+ bool is_noasync = get_scope_noasync(scope) != nullptr;
AstNode *expr_node = node->data.await_expr.expr;
if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
@@ -9855,6 +9846,11 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode
add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));
return irb->codegen->invalid_inst_src;
}
+ if (get_scope_noasync(parent_scope) != nullptr) {
+ add_node_error(irb->codegen, node, buf_sprintf("suspend in noasync scope"));
+ return irb->codegen->invalid_inst_src;
+ }
+
ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
if (existing_suspend_scope) {
if (!existing_suspend_scope->reported_err) {
diff --git a/src/parser.cpp b/src/parser.cpp
index 7ff24db1849a173085719bd07f0e26cb673ebba9..cdd254962eaface52651bb381ca9e6cfeb8bd065 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -876,6 +876,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
// Statement
// <- KEYWORD_comptime? VarDecl
// / KEYWORD_comptime BlockExprStatement
+// / KEYWORD_noasync BlockExprStatement
// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
// / KEYWORD_defer BlockExprStatement
// / KEYWORD_errdefer BlockExprStatement
@@ -899,6 +900,14 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
return res;
}
+ Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
+ if (noasync != nullptr) {
+ AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
+ AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
+ res->data.noasync_expr.expr = statement;
+ return res;
+ }
+
Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
if (suspend != nullptr) {
AstNode *statement = nullptr;
--
2.54.0
From 3fd2cd43678d52ca2f737d991edaddfd8b73c2a4 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Mon, 9 Mar 2020 18:38:54 +0200
Subject: [PATCH 023/111] add LemonBoy's test
---
src/codegen.cpp | 2 +-
test/compile_errors.zig | 10 ++++++++--
test/stage1/behavior/async_fn.zig | 16 ++++++++++++++++
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 52ac2e79366723c0215f1d03041b114315b6750c..a67b8dc00b728c8f49ffe96403bf302a40463643 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -969,7 +969,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
case PanicMsgIdResumedFnPendingAwait:
return buf_create_from_str("resumed an async function which can only be awaited");
case PanicMsgIdBadNoAsyncCall:
- return buf_create_from_str("async function called with noasync suspended");
+ return buf_create_from_str("async function called in noasync scope suspended");
case PanicMsgIdResumeNotSuspendedFn:
return buf_create_from_str("resumed a non-suspended function");
case PanicMsgIdBadSentinel:
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 7021f8155458a727963e75f393b8f91f207bfd2e..4434920224639ec4c5e069192aa369915c556408 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -4,11 +4,17 @@ const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("combination of noasync and async",
\\export fn entry() void {
- \\ noasync async foo();
+ \\ noasync {
+ \\ const bar = async foo();
+ \\ suspend;
+ \\ resume bar;
+ \\ }
\\}
\\fn foo() void {}
, &[_][]const u8{
- "tmp.zig:2:13: error: async call in noasync scope",
+ "tmp.zig:3:21: error: async call in noasync scope",
+ "tmp.zig:4:9: error: suspend in noasync scope",
+ "tmp.zig:5:9: error: resume in noasync scope",
});
cases.addTest("@TypeOf with no arguments",
diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig
index 6583adec6643bcaf631ba2e80eddb44fb496850f..6b99187563c5c905e9221f2fcbc6d36477d9dd45 100644
--- a/test/stage1/behavior/async_fn.zig
+++ b/test/stage1/behavior/async_fn.zig
@@ -1531,3 +1531,19 @@ test "noasync await" {
S.doTheTest();
expect(S.finished);
}
+
+test "noasync on function calls" {
+ const S0 = struct {
+ b: i32 = 42,
+ };
+ const S1 = struct {
+ fn c() S0 {
+ return S0{};
+ }
+ fn d() !S0 {
+ return S0{};
+ }
+ };
+ expectEqual(@as(i32, 42), noasync S1.c().b);
+ expectEqual(@as(i32, 42), (try noasync S1.d()).b);
+}
--
2.54.0
From 9b1b44b41c2b1efe272985af44eaae84b9c4af1c Mon Sep 17 00:00:00 2001
From: Ryan Liptak
Date: Mon, 9 Mar 2020 00:52:28 -0700
Subject: [PATCH 024/111] Windows: Fix std.fs.realpath/os.realpathW for
directories
---
lib/std/os.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/std/os.zig b/lib/std/os.zig
index a6c8b32ba9c522d31a4f4aa82c2c07c674bde942..460f0bee022b97c384eec04f5cadf5271e068553 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3077,7 +3077,7 @@ pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) Real
windows.FILE_SHARE_READ,
null,
windows.OPEN_EXISTING,
- windows.FILE_ATTRIBUTE_NORMAL,
+ windows.FILE_FLAG_BACKUP_SEMANTICS,
null,
);
defer windows.CloseHandle(h_file);
--
2.54.0
From 648f94c0275a85fece347ced013f89ee5eb5d800 Mon Sep 17 00:00:00 2001
From: daurnimator
Date: Mon, 9 Mar 2020 04:20:37 +1100
Subject: [PATCH 025/111] std: add some definitions for netlink sockets
---
lib/std/os/bits/linux.zig | 6 +
lib/std/os/bits/linux/netlink.zig | 498 ++++++++++++++++++++++++++++++
2 files changed, 504 insertions(+)
create mode 100644 lib/std/os/bits/linux/netlink.zig
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index c5a9a7d774e1dd81d43aa312193db99b1282f00e..e20e96181a6ca81391a1fa6dc1da2691b6868366 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -18,6 +18,8 @@ pub usingnamespace switch (builtin.arch) {
else => struct {},
};
+pub usingnamespace @import("linux/netlink.zig");
+
const is_mips = builtin.arch.isMIPS();
pub const pid_t = i32;
@@ -30,6 +32,10 @@ pub const NAME_MAX = 255;
pub const PATH_MAX = 4096;
pub const IOV_MAX = 1024;
+/// Largest hardware address length
+/// e.g. a mac address is a type of hardware address
+pub const MAX_ADDR_LEN = 32;
+
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
diff --git a/lib/std/os/bits/linux/netlink.zig b/lib/std/os/bits/linux/netlink.zig
new file mode 100644
index 0000000000000000000000000000000000000000..b40308d6fc9f7c0eee53e5a09b4c60144966577a
--- /dev/null
+++ b/lib/std/os/bits/linux/netlink.zig
@@ -0,0 +1,498 @@
+usingnamespace @import("../linux.zig");
+
+/// Routing/device hook
+pub const NETLINK_ROUTE = 0;
+
+/// Unused number
+pub const NETLINK_UNUSED = 1;
+
+/// Reserved for user mode socket protocols
+pub const NETLINK_USERSOCK = 2;
+
+/// Unused number, formerly ip_queue
+pub const NETLINK_FIREWALL = 3;
+
+/// socket monitoring
+pub const NETLINK_SOCK_DIAG = 4;
+
+/// netfilter/iptables ULOG
+pub const NETLINK_NFLOG = 5;
+
+/// ipsec
+pub const NETLINK_XFRM = 6;
+
+/// SELinux event notifications
+pub const NETLINK_SELINUX = 7;
+
+/// Open-iSCSI
+pub const NETLINK_ISCSI = 8;
+
+/// auditing
+pub const NETLINK_AUDIT = 9;
+
+pub const NETLINK_FIB_LOOKUP = 10;
+
+pub const NETLINK_CONNECTOR = 11;
+
+/// netfilter subsystem
+pub const NETLINK_NETFILTER = 12;
+
+pub const NETLINK_IP6_FW = 13;
+
+/// DECnet routing messages
+pub const NETLINK_DNRTMSG = 14;
+
+/// Kernel messages to userspace
+pub const NETLINK_KOBJECT_UEVENT = 15;
+
+pub const NETLINK_GENERIC = 16;
+
+// leave room for NETLINK_DM (DM Events)
+
+/// SCSI Transports
+pub const NETLINK_SCSITRANSPORT = 18;
+
+pub const NETLINK_ECRYPTFS = 19;
+
+pub const NETLINK_RDMA = 20;
+
+/// Crypto layer
+pub const NETLINK_CRYPTO = 21;
+
+/// SMC monitoring
+pub const NETLINK_SMC = 22;
+
+// Flags values
+
+/// It is request message.
+pub const NLM_F_REQUEST = 0x01;
+
+/// Multipart message, terminated by NLMSG_DONE
+pub const NLM_F_MULTI = 0x02;
+
+/// Reply with ack, with zero or error code
+pub const NLM_F_ACK = 0x04;
+
+/// Echo this request
+pub const NLM_F_ECHO = 0x08;
+
+/// Dump was inconsistent due to sequence change
+pub const NLM_F_DUMP_INTR = 0x10;
+
+/// Dump was filtered as requested
+pub const NLM_F_DUMP_FILTERED = 0x20;
+
+// Modifiers to GET request
+
+/// specify tree root
+pub const NLM_F_ROOT = 0x100;
+
+/// return all matching
+pub const NLM_F_MATCH = 0x200;
+
+/// atomic GET
+pub const NLM_F_ATOMIC = 0x400;
+pub const NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH;
+
+// Modifiers to NEW request
+
+/// Override existing
+pub const NLM_F_REPLACE = 0x100;
+
+/// Do not touch, if it exists
+pub const NLM_F_EXCL = 0x200;
+
+/// Create, if it does not exist
+pub const NLM_F_CREATE = 0x400;
+
+/// Add to end of list
+pub const NLM_F_APPEND = 0x800;
+
+// Modifiers to DELETE request
+
+/// Do not delete recursively
+pub const NLM_F_NONREC = 0x100;
+
+// Flags for ACK message
+
+/// request was capped
+pub const NLM_F_CAPPED = 0x100;
+
+/// extended ACK TVLs were included
+pub const NLM_F_ACK_TLVS = 0x200;
+
+pub const NetlinkMessageType = extern enum(u16) {
+ /// Nothing.
+ NOOP = 0x1,
+
+ /// Error
+ ERROR = 0x2,
+
+ /// End of a dump
+ DONE = 0x3,
+
+ /// Data lost
+ OVERRUN = 0x4,
+
+ /// < 0x10: reserved control messages
+ pub const MIN_TYPE = 0x10;
+
+ // rtlink types
+
+ RTM_NEWLINK = 16,
+ RTM_DELLINK,
+ RTM_GETLINK,
+ RTM_SETLINK,
+
+ RTM_NEWADDR = 20,
+ RTM_DELADDR,
+ RTM_GETADDR,
+
+ RTM_NEWROUTE = 24,
+ RTM_DELROUTE,
+ RTM_GETROUTE,
+
+ RTM_NEWNEIGH = 28,
+ RTM_DELNEIGH,
+ RTM_GETNEIGH,
+
+ RTM_NEWRULE = 32,
+ RTM_DELRULE,
+ RTM_GETRULE,
+
+ RTM_NEWQDISC = 36,
+ RTM_DELQDISC,
+ RTM_GETQDISC,
+
+ RTM_NEWTCLASS = 40,
+ RTM_DELTCLASS,
+ RTM_GETTCLASS,
+
+ RTM_NEWTFILTER = 44,
+ RTM_DELTFILTER,
+ RTM_GETTFILTER,
+
+ RTM_NEWACTION = 48,
+ RTM_DELACTION,
+ RTM_GETACTION,
+
+ RTM_NEWPREFIX = 52,
+
+ RTM_GETMULTICAST = 58,
+
+ RTM_GETANYCAST = 62,
+
+ RTM_NEWNEIGHTBL = 64,
+ RTM_GETNEIGHTBL = 66,
+ RTM_SETNEIGHTBL,
+
+ RTM_NEWNDUSEROPT = 68,
+
+ RTM_NEWADDRLABEL = 72,
+ RTM_DELADDRLABEL,
+ RTM_GETADDRLABEL,
+
+ RTM_GETDCB = 78,
+ RTM_SETDCB,
+
+ RTM_NEWNETCONF = 80,
+ RTM_DELNETCONF,
+ RTM_GETNETCONF = 82,
+
+ RTM_NEWMDB = 84,
+ RTM_DELMDB = 85,
+ RTM_GETMDB = 86,
+
+ RTM_NEWNSID = 88,
+ RTM_DELNSID = 89,
+ RTM_GETNSID = 90,
+
+ RTM_NEWSTATS = 92,
+ RTM_GETSTATS = 94,
+
+ RTM_NEWCACHEREPORT = 96,
+
+ RTM_NEWCHAIN = 100,
+ RTM_DELCHAIN,
+ RTM_GETCHAIN,
+
+ RTM_NEWNEXTHOP = 104,
+ RTM_DELNEXTHOP,
+ RTM_GETNEXTHOP,
+
+ _,
+};
+
+/// Netlink socket address
+pub const sockaddr_nl = extern struct {
+ family: sa_family_t = AF_NETLINK,
+ __pad1: c_ushort = 0,
+
+ /// port ID
+ pid: u32,
+
+ /// multicast groups mask
+ groups: u32,
+};
+
+/// Netlink message header
+/// Specified in RFC 3549 Section 2.3.2
+pub const nlmsghdr = extern struct {
+ /// Length of message including header
+ len: u32,
+
+ /// Message content
+ @"type": NetlinkMessageType,
+
+ /// Additional flags
+ flags: u16,
+
+ /// Sequence number
+ seq: u32,
+
+ /// Sending process port ID
+ pid: u32,
+};
+
+pub const ifinfomsg = extern struct {
+ family: u8,
+ __pad1: u8 = 0,
+
+ /// ARPHRD_*
+ @"type": c_ushort,
+
+ /// Link index
+ index: c_int,
+
+ /// IFF_* flags
+ flags: c_uint,
+
+ /// IFF_* change mask
+ /// is reserved for future use and should be always set to 0xFFFFFFFF.
+ change: c_uint = 0xFFFFFFFF,
+};
+
+pub const rtattr = extern struct {
+ /// Length of option
+ len: c_ushort,
+
+ /// Type of option
+ @"type": IFLA,
+
+ pub const ALIGNTO = 4;
+};
+
+pub const IFLA = extern enum(c_ushort) {
+ UNSPEC,
+ ADDRESS,
+ BROADCAST,
+ IFNAME,
+ MTU,
+ LINK,
+ QDISC,
+ STATS,
+ COST,
+ PRIORITY,
+ MASTER,
+
+ /// Wireless Extension event
+ WIRELESS,
+
+ /// Protocol specific information for a link
+ PROTINFO,
+
+ TXQLEN,
+ MAP,
+ WEIGHT,
+ OPERSTATE,
+ LINKMODE,
+ LINKINFO,
+ NET_NS_PID,
+ IFALIAS,
+
+ /// Number of VFs if device is SR-IOV PF
+ NUM_VF,
+
+ VFINFO_LIST,
+ STATS64,
+ VF_PORTS,
+ PORT_SELF,
+ AF_SPEC,
+
+ /// Group the device belongs to
+ GROUP,
+
+ NET_NS_FD,
+
+ /// Extended info mask, VFs, etc
+ EXT_MASK,
+
+ /// Promiscuity count: > 0 means acts PROMISC
+ PROMISCUITY,
+
+ NUM_TX_QUEUES,
+ NUM_RX_QUEUES,
+ CARRIER,
+ PHYS_PORT_ID,
+ CARRIER_CHANGES,
+ PHYS_SWITCH_ID,
+ LINK_NETNSID,
+ PHYS_PORT_NAME,
+ PROTO_DOWN,
+ GSO_MAX_SEGS,
+ GSO_MAX_SIZE,
+ PAD,
+ XDP,
+ EVENT,
+
+ NEW_NETNSID,
+ IF_NETNSID = 46,
+ TARGET_NETNSID = 46, // new alias
+
+ CARRIER_UP_COUNT,
+ CARRIER_DOWN_COUNT,
+ NEW_IFINDEX,
+ MIN_MTU,
+ MAX_MTU,
+
+ _,
+};
+
+pub const rtnl_link_ifmap = extern struct {
+ mem_start: u64,
+ mem_end: u64,
+ base_addr: u64,
+ irq: u16,
+ dma: u8,
+ port: u8,
+};
+
+pub const rtnl_link_stats = extern struct {
+ /// total packets received
+ rx_packets: u32,
+
+ /// total packets transmitted
+ tx_packets: u32,
+
+ /// total bytes received
+ rx_bytes: u32,
+
+ /// total bytes transmitted
+ tx_bytes: u32,
+
+ /// bad packets received
+ rx_errors: u32,
+
+ /// packet transmit problems
+ tx_errors: u32,
+
+ /// no space in linux buffers
+ rx_dropped: u32,
+
+ /// no space available in linux
+ tx_dropped: u32,
+
+ /// multicast packets received
+ multicast: u32,
+
+ collisions: u32,
+
+ // detailed rx_errors
+
+ rx_length_errors: u32,
+
+ /// receiver ring buff overflow
+ rx_over_errors: u32,
+
+ /// recved pkt with crc error
+ rx_crc_errors: u32,
+
+ /// recv'd frame alignment error
+ rx_frame_errors: u32,
+
+ /// recv'r fifo overrun
+ rx_fifo_errors: u32,
+
+ /// receiver missed packet
+ rx_missed_errors: u32,
+
+ // detailed tx_errors
+ tx_aborted_errors: u32,
+ tx_carrier_errors: u32,
+ tx_fifo_errors: u32,
+ tx_heartbeat_errors: u32,
+ tx_window_errors: u32,
+
+ // for cslip etc
+
+ rx_compressed: u32,
+ tx_compressed: u32,
+
+ /// dropped, no handler found
+ rx_nohandler: u32,
+};
+
+pub const rtnl_link_stats64 = extern struct {
+ /// total packets received
+ rx_packets: u64,
+
+ /// total packets transmitted
+ tx_packets: u64,
+
+ /// total bytes received
+ rx_bytes: u64,
+
+ /// total bytes transmitted
+ tx_bytes: u64,
+
+ /// bad packets received
+ rx_errors: u64,
+
+ /// packet transmit problems
+ tx_errors: u64,
+
+ /// no space in linux buffers
+ rx_dropped: u64,
+
+ /// no space available in linux
+ tx_dropped: u64,
+
+ /// multicast packets received
+ multicast: u64,
+
+ collisions: u64,
+
+ // detailed rx_errors
+
+ rx_length_errors: u64,
+
+ /// receiver ring buff overflow
+ rx_over_errors: u64,
+
+ /// recved pkt with crc error
+ rx_crc_errors: u64,
+
+ /// recv'd frame alignment error
+ rx_frame_errors: u64,
+
+ /// recv'r fifo overrun
+ rx_fifo_errors: u64,
+
+ /// receiver missed packet
+ rx_missed_errors: u64,
+
+ // detailed tx_errors
+ tx_aborted_errors: u64,
+ tx_carrier_errors: u64,
+ tx_fifo_errors: u64,
+ tx_heartbeat_errors: u64,
+ tx_window_errors: u64,
+
+ // for cslip etc
+
+ rx_compressed: u64,
+ tx_compressed: u64,
+
+ /// dropped, no handler found
+ rx_nohandler: u64,
+};
--
2.54.0
From 14bbb828326a8b08cf6680a44d992e64a5de34f5 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 23 Feb 2020 09:44:19 +0100
Subject: [PATCH 026/111] ir: Fix lazy comparison between @alignOf and zero
Closes #4527
---
src/ir.cpp | 15 +++++++++++++--
test/stage1/behavior/alignof.zig | 21 +++++++++++++++++++++
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 110778fb9a04cfeb13117afb9a18e46c886c7d26..3adf6d1e0cb742f93e0123c1f88c5ebd46f72070 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15565,9 +15565,20 @@ static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val
switch (val->data.x_lazy->id) {
case LazyValueIdInvalid:
zig_unreachable();
- case LazyValueIdAlignOf:
- *result = CmpGT;
+ case LazyValueIdAlignOf: {
+ LazyValueAlignOf *lazy_align_of = reinterpret_cast(val->data.x_lazy);
+ IrAnalyze *ira = lazy_align_of->ira;
+
+ uint32_t abi_align;
+ if ((err = type_val_resolve_abi_align(ira->codegen, source_node, lazy_align_of->target_type->value,
+ &abi_align)))
+ {
+ return err;
+ }
+
+ *result = (abi_align == 0) ? CmpEQ : CmpGT;
return ErrorNone;
+ }
case LazyValueIdSizeOf: {
LazyValueSizeOf *lazy_size_of = reinterpret_cast(val->data.x_lazy);
IrAnalyze *ira = lazy_size_of->ira;
diff --git a/test/stage1/behavior/alignof.zig b/test/stage1/behavior/alignof.zig
index f923fd935577b34837d86d2d4b2d474672aab0f8..96114ed560d438295e4d1efb7d4efed06ef551b3 100644
--- a/test/stage1/behavior/alignof.zig
+++ b/test/stage1/behavior/alignof.zig
@@ -15,3 +15,24 @@ test "@alignOf(T) before referencing T" {
comptime expect(@alignOf(Foo) == 4);
}
}
+
+test "comparison of @alignOf(T) against zero" {
+ {
+ const T = struct { x: u32 };
+ expect(!(@alignOf(T) == 0));
+ expect(@alignOf(T) != 0);
+ expect(!(@alignOf(T) < 0));
+ expect(!(@alignOf(T) <= 0));
+ expect(@alignOf(T) > 0);
+ expect(@alignOf(T) >= 0);
+ }
+ {
+ const T = struct {};
+ expect(@alignOf(T) == 0);
+ expect(!(@alignOf(T) != 0));
+ expect(!(@alignOf(T) < 0));
+ expect(@alignOf(T) <= 0);
+ expect(!(@alignOf(T) > 0));
+ expect(@alignOf(T) >= 0);
+ }
+}
--
2.54.0
From 7db6da7cb81c6b83804171e3791198a687881f43 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 9 Mar 2020 14:24:04 -0400
Subject: [PATCH 027/111] lazy_cmp_zero only resolves type is zero bits for
alignof
---
src/ir.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 3adf6d1e0cb742f93e0123c1f88c5ebd46f72070..7346492c9a6508b3358d48a0d034de3c533b99f3 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15569,14 +15569,14 @@ static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val
LazyValueAlignOf *lazy_align_of = reinterpret_cast(val->data.x_lazy);
IrAnalyze *ira = lazy_align_of->ira;
- uint32_t abi_align;
- if ((err = type_val_resolve_abi_align(ira->codegen, source_node, lazy_align_of->target_type->value,
- &abi_align)))
+ bool is_zero_bits;
+ if ((err = type_val_resolve_zero_bits(ira->codegen, lazy_align_of->target_type->value,
+ nullptr, nullptr, &is_zero_bits)))
{
return err;
}
- *result = (abi_align == 0) ? CmpEQ : CmpGT;
+ *result = is_zero_bits ? CmpEQ : CmpGT;
return ErrorNone;
}
case LazyValueIdSizeOf: {
--
2.54.0
From e7cc45642138472c29e09cd10e31962426c1aba5 Mon Sep 17 00:00:00 2001
From: xackus <14938807+xackus@users.noreply.github.com>
Date: Mon, 9 Mar 2020 19:36:15 +0100
Subject: [PATCH 028/111] better error messages and more tests
---
src/analyze.cpp | 2 +-
src/ir.cpp | 2 +-
test/compile_errors.zig | 22 ++++++++++++++++++++--
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 638a31ab5a2e6cb166e3b447c07ab67ad901befa..89e64ec54030ebc4d86940e38ed01bea8fda3667 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1957,7 +1957,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
if(!is_valid_return_type(specified_return_type)){
ErrorMsg* msg = add_node_error(g, fn_proto->return_type,
- buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
+ buf_sprintf("%s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name)));
Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name);
if (tld != nullptr) {
add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here"));
diff --git a/src/ir.cpp b/src/ir.cpp
index 67eabf50402553693b51e80d1f498459d1ae5fc2..d4db5455f0d71645f9862b14ccd94e9d8dbd5640 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -19342,7 +19342,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if(!is_valid_return_type(specified_return_type)){
ErrorMsg *msg = ir_add_error(ira, source_instr,
- buf_sprintf("call to generic function with return type '%s' not allowed", buf_ptr(&specified_return_type->name)));
+ buf_sprintf("call to generic function with %s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name)));
add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here"));
Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name);
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 006bd3ef7fe1e3e9c91ea889f5af6c28abe3edca..63a8a48beaa036d72d054f071f82873c5a27613c 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -6538,9 +6538,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn bar() !FooType {
\\ return error.InvalidValue;
\\}
+ \\export fn bav() !@TypeOf(null) {
+ \\ return error.InvalidValue;
+ \\}
+ \\export fn baz() !@TypeOf(undefined) {
+ \\ return error.InvalidValue;
+ \\}
, &[_][]const u8{
- "tmp.zig:2:18: error: return type 'FooType' not allowed",
+ "tmp.zig:2:18: error: Opaque return type 'FooType' not allowed",
"tmp.zig:1:1: note: type declared here",
+ "tmp.zig:5:18: error: Null return type '(null)' not allowed",
+ "tmp.zig:8:18: error: Undefined return type '(undefined)' not allowed",
});
cases.add("generic function returning opaque type",
@@ -6551,10 +6559,20 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn bar() void {
\\ _ = generic(FooType);
\\}
+ \\export fn bav() void {
+ \\ _ = generic(@TypeOf(null));
+ \\}
+ \\export fn baz() void {
+ \\ _ = generic(@TypeOf(undefined));
+ \\}
, &[_][]const u8{
- "tmp.zig:6:16: error: call to generic function with return type 'FooType' not allowed",
+ "tmp.zig:6:16: error: call to generic function with Opaque return type 'FooType' not allowed",
"tmp.zig:2:1: note: function declared here",
"tmp.zig:1:1: note: type declared here",
+ "tmp.zig:9:16: error: call to generic function with Null return type '(null)' not allowed",
+ "tmp.zig:2:1: note: function declared here",
+ "tmp.zig:12:16: error: call to generic function with Undefined return type '(undefined)' not allowed",
+ "tmp.zig:2:1: note: function declared here",
});
cases.add( // fixed bug #2032
--
2.54.0
From 1f44b29724b52433d84b43345a52da59f9220e62 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 9 Mar 2020 20:58:25 +0100
Subject: [PATCH 029/111] ir: Fix codegen of ?*T types where T is zero-sized
* Fix codegen for optional types that decay to a pointer, the type
behaves as a boolean
* Fix comptime evaluation of zero-sized arrays, always initialize the
internal array elements
Closes #4673
---
src/analyze.cpp | 34 +++++++++++++++++++++++++++++++
src/analyze.hpp | 1 +
src/codegen.cpp | 12 ++++++++++-
src/ir.cpp | 26 ++++++++---------------
test/stage1/behavior/optional.zig | 23 +++++++++++++++++++++
5 files changed, 77 insertions(+), 19 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d924002426ec0efe1077554c47d7f8334244ae2e..905a6a6f94d8322c486f81ea37fc1d95aac8b854 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -5797,6 +5797,7 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
ZigValue *result = g->pass1_arena->create();
result->type = type_entry;
result->special = ConstValSpecialStatic;
+
if (result->type->id == ZigTypeIdStruct) {
// The fields array cannot be left unpopulated
const ZigType *struct_type = result->type;
@@ -5808,6 +5809,22 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
assert(field_type != nullptr);
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
}
+ } else if (result->type->id == ZigTypeIdArray) {
+ // The elements array cannot be left unpopulated
+ ZigType *array_type = result->type;
+ ZigType *elem_type = array_type->data.array.child_type;
+ ZigValue *sentinel_value = array_type->data.array.sentinel;
+ const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
+
+ result->data.x_array.data.s_none.elements = g->pass1_arena->allocate(elem_count);
+ for (size_t i = 0; i < elem_count; i += 1) {
+ ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
+ copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
+ }
+ if (sentinel_value != nullptr) {
+ ZigValue *last_elem_val = &result->data.x_array.data.s_none.elements[elem_count - 1];
+ copy_const_val(g, last_elem_val, sentinel_value);
+ }
} else if (result->type->id == ZigTypeIdPointer) {
result->data.x_ptr.special = ConstPtrSpecialRef;
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
@@ -9537,6 +9554,23 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
}
}
+bool optional_value_is_null(ZigValue *val) {
+ assert(val->special == ConstValSpecialStatic);
+ if (get_src_ptr_type(val->type) != nullptr) {
+ if (val->data.x_ptr.special == ConstPtrSpecialNull) {
+ return true;
+ } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+ return val->data.x_ptr.data.hard_coded_addr.addr == 0;
+ } else {
+ return false;
+ }
+ } else if (is_opt_err_set(val->type)) {
+ return val->data.x_err_set == nullptr;
+ } else {
+ return val->data.x_optional == nullptr;
+ }
+}
+
bool type_is_numeric(ZigType *ty) {
switch (ty->id) {
case ZigTypeIdInvalid:
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 98d09d452f8d33d9ffa39dda9a5ea754f4de172b..0b48d357f66ee6efe3fb4e896c2631df3acbff89 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -198,6 +198,7 @@ size_t type_id_index(ZigType *entry);
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
LinkLib *create_link_lib(Buf *name);
LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
+bool optional_value_is_null(ZigValue *val);
uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry);
ZigType *get_align_amt_type(CodeGen *g);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a67b8dc00b728c8f49ffe96403bf302a40463643..22cb97520565ef44d0986e10e1f6b9e44648b38f 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6902,8 +6902,18 @@ check: switch (const_val->special) {
case ZigTypeIdOptional:
{
ZigType *child_type = type_entry->data.maybe.child_type;
+
if (get_src_ptr_type(type_entry) != nullptr) {
- return gen_const_val_ptr(g, const_val, name);
+ bool has_bits;
+ if ((err = type_has_bits2(g, child_type, &has_bits)))
+ codegen_report_errors_and_exit(g);
+
+ if (has_bits)
+ return gen_const_val_ptr(g, const_val, name);
+
+ // No bits, treat this value as a boolean
+ const unsigned bool_val = optional_value_is_null(const_val) ? 0 : 1;
+ return LLVMConstInt(LLVMInt1Type(), bool_val, false);
} else if (child_type->id == ZigTypeIdErrorSet) {
return gen_const_val_err_set(g, const_val, name);
} else if (!type_has_bits(g, child_type)) {
diff --git a/src/ir.cpp b/src/ir.cpp
index aab2bff813dad4a3329a2addfb90eeeaeb920372..e2cf13b77df64e55b5d8e3e6f2b8a44ee0874259 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15478,23 +15478,6 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
}
}
-static bool optional_value_is_null(ZigValue *val) {
- assert(val->special == ConstValSpecialStatic);
- if (get_src_ptr_type(val->type) != nullptr) {
- if (val->data.x_ptr.special == ConstPtrSpecialNull) {
- return true;
- } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
- return val->data.x_ptr.data.hard_coded_addr.addr == 0;
- } else {
- return false;
- }
- } else if (is_opt_err_set(val->type)) {
- return val->data.x_err_set == nullptr;
- } else {
- return val->data.x_optional == nullptr;
- }
-}
-
static void set_optional_value_to_null(ZigValue *val) {
assert(val->special == ConstValSpecialStatic);
if (val->type->id == ZigTypeIdNull) return; // nothing to do
@@ -17594,7 +17577,14 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV
ZigValue *init_val = nullptr;
if (instr_is_comptime(var_ptr) && var_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- init_val = const_ptr_pointee(ira, ira->codegen, var_ptr->value, decl_var_instruction->base.base.source_node);
+ ZigValue *ptr_val = ir_resolve_const(ira, var_ptr, UndefBad);
+ if (ptr_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ init_val = const_ptr_pointee(ira, ira->codegen, ptr_val, decl_var_instruction->base.base.source_node);
+ if (init_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
if (is_comptime_var) {
if (var->gen_is_const) {
var->const_value = init_val;
diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig
index fa002b707e854b2da8b7491444c0c156ec9112df..7dd48769dbe6551396f7be8165ede14f671ac1b0 100644
--- a/test/stage1/behavior/optional.zig
+++ b/test/stage1/behavior/optional.zig
@@ -175,3 +175,26 @@ test "0-bit child type coerced to optional return ptr result location" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "0-bit child type coerced to optional" {
+ const S = struct {
+ fn doTheTest() void {
+ var it: Foo = .{
+ .list = undefined,
+ };
+ expect(it.foo() != null);
+ }
+
+ const Empty = struct {};
+ const Foo = struct {
+ list: [10]Empty,
+
+ fn foo(self: *Foo) ?*Empty {
+ const data = &self.list[0];
+ return data;
+ }
+ };
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
--
2.54.0
From baec74645d8757f51f1ac14483daf4438e2d77bd Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 15:52:03 +0200
Subject: [PATCH 030/111] translate-c add daurnimator's pointer check to macro
cast
---
src-self-hosted/translate_c.zig | 21 ++++++++++++++++++++-
test/translate_c.zig | 8 ++++----
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index be3e43f3d71809fcc909cccb2a7111e259aaf387..949178b37f03cccf62eacb78f896d8b0ffaf874b 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -5437,7 +5437,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
//if (@typeInfo(@TypeOf(x)) == .Pointer)
// @ptrCast(dest, x)
- //else if (@typeInfo(@TypeOf(x)) == .Integer)
+ //else if (@typeInfo(@TypeOf(x)) == .Int and @typeInfo(dest) == .Pointer)
// @intToPtr(dest, x)
//else
// @as(dest, x)
@@ -5487,6 +5487,25 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
.rhs = try transCreateNodeEnumLiteral(c, "Int"),
};
if_2.condition = &cmp_2.base;
+ const cmp_4 = try c.a().create(ast.Node.InfixOp);
+ cmp_4.* = .{
+ .op_token = try appendToken(c, .Keyword_and, "and"),
+ .lhs = &cmp_2.base,
+ .op = .BoolAnd,
+ .rhs = undefined,
+ };
+ const type_id_3 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
+ try type_id_3.params.push(inner_node);
+ type_id_3.rparen_token = try appendToken(c, .LParen, ")");
+ const cmp_3 = try c.a().create(ast.Node.InfixOp);
+ cmp_3.* = .{
+ .op_token = try appendToken(c, .EqualEqual, "=="),
+ .lhs = &type_id_3.base,
+ .op = .EqualEqual,
+ .rhs = try transCreateNodeEnumLiteral(c, "Pointer"),
+ };
+ cmp_4.rhs = &cmp_3.base;
+ if_2.condition = &cmp_4.base;
else_1.body = &if_2.base;
_ = try appendToken(c, .RParen, ")");
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 209a301f8855adb8cd4dc99befd050f605e46a4f..7e70e698d95ee06f8e10e0531e716f378f1feb45 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1429,7 +1429,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{
- \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
+ \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int and @typeInfo([*c]NRF_GPIO_Type) == .Pointer) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
});
cases.add("basic macro function",
@@ -2613,11 +2613,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO(bar) baz((void *)(baz))
\\#define BAR (void*) a
, &[_][]const u8{
- \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
- \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
+ \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
+ \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
\\}
,
- \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a));
+ \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, a) else @as(*c_void, a));
});
cases.add("macro conditional operator",
--
2.54.0
From 4cace8f7c342b7d1b1f415cc28f48d5c98bada72 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 15:52:54 +0200
Subject: [PATCH 031/111] properly mangle shadowed primitive types
---
src-self-hosted/translate_c.zig | 6 +++---
test/translate_c.zig | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 949178b37f03cccf62eacb78f896d8b0ffaf874b..8af98a3bf0a2a30ff88e3d779aa062393b7a4b6a 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "_{}", .{var_name}) else var_name;
+ const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "_{}", .{typedef_name}) else typedef_name;
+ const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
if (mem.eql(u8, checked_name, "uint8_t"))
return transTypeDefAsBuiltin(c, typedef_decl, "u8")
@@ -4857,7 +4857,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
const name = try c.str(raw_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name;
+ const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
if (scope.containsNow(mangled_name)) {
continue;
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 7e70e698d95ee06f8e10e0531e716f378f1feb45..471e1eca51b21b8bfa95e8f3273e8885be0d31d1 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1601,7 +1601,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("shadowing primitive types",
\\unsigned anyerror = 2;
, &[_][]const u8{
- \\pub export var _anyerror: c_uint = @bitCast(c_uint, @as(c_int, 2));
+ \\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2));
});
cases.add("floats",
--
2.54.0
From cb4c488cbd1e02b88ca8e7466a0945691f06d4fd Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 15:57:57 +0200
Subject: [PATCH 032/111] translate-c support struct field alignment
---
src-self-hosted/clang.zig | 1 +
src-self-hosted/translate_c.zig | 20 +++++++++++++++++---
src/zig_clang.cpp | 10 ++++++++++
src/zig_clang.h | 1 +
test/translate_c.zig | 10 ++++++++++
5 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig
index 3a3b4ac196fa1d467f2613b7b5947790c9d695cb..ce2c7aea221e8fa9e828a3974589c8747e4e7612 100644
--- a/src-self-hosted/clang.zig
+++ b/src-self-hosted/clang.zig
@@ -765,6 +765,7 @@ pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClang
pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigClangFieldDecl) ?*const struct_ZigClangFieldDecl;
+pub extern fn ZigClangFieldDecl_getAlignedAttribute(field_decl: ?*const struct_ZigClangFieldDecl, *const ZigClangASTContext) c_uint;
pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 8af98a3bf0a2a30ff88e3d779aa062393b7a4b6a..f14ebe33061141fa3cd5f43b68d8150cbeee2050 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -632,7 +632,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
const align_expr = blk: {
const alignment = ZigClangVarDecl_getAlignedAttribute(var_decl, rp.c.clang_context);
if (alignment != 0) {
- _ = try appendToken(rp.c, .Keyword_linksection, "align");
+ _ = try appendToken(rp.c, .Keyword_align, "align");
_ = try appendToken(rp.c, .LParen, "(");
// Clang reports the alignment in bits
const expr = try transCreateNodeInt(rp.c, alignment / 8);
@@ -827,6 +827,20 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
else => |e| return e,
};
+ const align_expr = blk: {
+ const alignment = ZigClangFieldDecl_getAlignedAttribute(field_decl, rp.c.clang_context);
+ if (alignment != 0) {
+ _ = try appendToken(rp.c, .Keyword_align, "align");
+ _ = try appendToken(rp.c, .LParen, "(");
+ // Clang reports the alignment in bits
+ const expr = try transCreateNodeInt(rp.c, alignment / 8);
+ _ = try appendToken(rp.c, .RParen, ")");
+
+ break :blk expr;
+ }
+ break :blk null;
+ };
+
const field_node = try c.a().create(ast.Node.ContainerField);
field_node.* = .{
.doc_comments = null,
@@ -834,7 +848,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
.name_token = field_name,
.type_expr = field_type,
.value_expr = null,
- .align_expr = null,
+ .align_expr = align_expr,
};
if (is_anon) {
@@ -4607,7 +4621,7 @@ fn finishTransFnProto(
if (fn_decl) |decl| {
const alignment = ZigClangFunctionDecl_getAlignedAttribute(decl, rp.c.clang_context);
if (alignment != 0) {
- _ = try appendToken(rp.c, .Keyword_linksection, "align");
+ _ = try appendToken(rp.c, .Keyword_align, "align");
_ = try appendToken(rp.c, .LParen, "(");
// Clang reports the alignment in bits
const expr = try transCreateNodeInt(rp.c, alignment / 8);
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
index c5ea182e87b2593f4211c2e96afa8e40ebcbc610..ca93634aab969dcbf03fc9866b9e6da1d24edd65 100644
--- a/src/zig_clang.cpp
+++ b/src/zig_clang.cpp
@@ -1615,6 +1615,16 @@ unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self,
return 0;
}
+unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx) {
+ auto casted_self = reinterpret_cast(self);
+ auto casted_ctx = const_cast(reinterpret_cast(ctx));
+ if (const clang::AlignedAttr *AA = casted_self->getAttr()) {
+ return AA->getAlignment(*casted_ctx);
+ }
+ // Zero means no explicit alignment factor was specified
+ return 0;
+}
+
unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx) {
auto casted_self = reinterpret_cast(self);
auto casted_ctx = const_cast(reinterpret_cast(ctx));
diff --git a/src/zig_clang.h b/src/zig_clang.h
index 579812a84a6ab73c706762441a12dc2ed635937e..af4b04c7761769f68974aea4bedff37ea8c395c5 100644
--- a/src/zig_clang.h
+++ b/src/zig_clang.h
@@ -865,6 +865,7 @@ ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(cons
ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len);
ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx);
ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx);
+ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx);
ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self);
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 471e1eca51b21b8bfa95e8f3273e8885be0d31d1..e21c3c49ae92bff0460c9da81848309b8d460df5 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,6 +3,16 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("struct with aligned fields",
+ \\struct foo {
+ \\ __attribute__((aligned(1))) short bar;
+ \\};
+ , &[_][]const u8{
+ \\pub const struct_foo = extern struct {
+ \\ bar: c_short align(1),
+ \\};
+ });
+
cases.add("structs with VLAs are rejected",
\\struct foo { int x; int y[]; };
\\struct bar { int x; int y[0]; };
--
2.54.0
From 3e93dce0a12e8b09f2de30276364d9ee18c6ada0 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 10 Mar 2020 12:16:56 +0100
Subject: [PATCH 033/111] std: Fix detection of Linux kernel version
---
lib/std/os/bits/linux.zig | 12 ++++++------
lib/std/zig/system.zig | 11 +++++++++--
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index e20e96181a6ca81391a1fa6dc1da2691b6868366..2a58c144900359e26172bca347f1f232d5a637db 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -1296,12 +1296,12 @@ pub const io_uring_files_update = struct {
};
pub const utsname = extern struct {
- sysname: [65]u8,
- nodename: [65]u8,
- release: [65]u8,
- version: [65]u8,
- machine: [65]u8,
- domainname: [65]u8,
+ sysname: [64:0]u8,
+ nodename: [64:0]u8,
+ release: [64:0]u8,
+ version: [64:0]u8,
+ machine: [64:0]u8,
+ domainname: [64:0]u8,
};
pub const HOST_NAME_MAX = 64;
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index a4e065e1847e5d99b58aec3fe8ab1d73c3a8e16c..336dd0d3149652d5f0dcd3af10b4899edfe3fcec 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -201,8 +201,15 @@ pub const NativeTargetInfo = struct {
switch (Target.current.os.tag) {
.linux => {
const uts = std.os.uname();
- const release = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &uts.release));
- if (std.builtin.Version.parse(release)) |ver| {
+ const release = mem.toSliceConst(u8, &uts.release);
+ // The release field may have several other fields after the
+ // kernel version
+ const kernel_version = if (mem.indexOfScalar(u8, release, '-')) |pos|
+ release[0..pos]
+ else
+ release;
+
+ if (std.builtin.Version.parse(kernel_version)) |ver| {
os.version_range.linux.range.min = ver;
os.version_range.linux.range.max = ver;
} else |err| switch (err) {
--
2.54.0
From 90c232bbe8e53c09df14536def54b33d92ddd3c5 Mon Sep 17 00:00:00 2001
From: Jonathan Marler
Date: Tue, 10 Mar 2020 12:06:10 -0600
Subject: [PATCH 034/111] add allocSentinel function
---
lib/std/mem.zig | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 4da78295702d4adf673a794b2265d838259bb76f..3b4382c93206c72a11eb5433a84fc53e3828eecd 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -105,6 +105,20 @@ pub const Allocator = struct {
return self.alignedAlloc(T, null, n);
}
+ /// Allocates an array of `n + 1` items of type `T` and sets the first `n`
+ /// items to `undefined` and the last item to `sentinel`. Depending on the
+ /// Allocator implementation, it may be required to call `free` once the
+ /// memory is no longer needed, to avoid a resource leak. If the
+ /// `Allocator` implementation is unknown, then correct code will
+ /// call `free` when done.
+ ///
+ /// For allocating a single item, see `create`.
+ pub fn allocSentinel(self: *Allocator, comptime Elem: type, n: usize, comptime sentinel: Elem) Error![:sentinel]Elem {
+ var ptr = try self.alloc(Elem, n + 1);
+ ptr[n] = sentinel;
+ return ptr[0 .. n :sentinel];
+ }
+
pub fn alignedAlloc(
self: *Allocator,
comptime T: type,
--
2.54.0
From 1ad831a0ef22f354d4e1dd5073456a0683249846 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 20:02:22 +0200
Subject: [PATCH 035/111] fix zig fmt on noasync block
---
lib/std/zig/ast.zig | 56 ++++++++++++++++++++-----------------
lib/std/zig/parser_test.zig | 11 ++++++++
2 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 54115196674095a39f4676caba0014a5f2565bd4..95a772376d75760ffbdbd5e9a606ef917fa1714b 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -500,68 +500,72 @@ pub const Node = struct {
var n = base;
while (true) {
switch (n.id) {
- Id.Root,
- Id.ContainerField,
- Id.ParamDecl,
- Id.Block,
- Id.Payload,
- Id.PointerPayload,
- Id.PointerIndexPayload,
- Id.Switch,
- Id.SwitchCase,
- Id.SwitchElse,
- Id.FieldInitializer,
- Id.DocComment,
- Id.TestDecl,
+ .Root,
+ .ContainerField,
+ .ParamDecl,
+ .Block,
+ .Payload,
+ .PointerPayload,
+ .PointerIndexPayload,
+ .Switch,
+ .SwitchCase,
+ .SwitchElse,
+ .FieldInitializer,
+ .DocComment,
+ .TestDecl,
=> return false,
- Id.While => {
+ .While => {
const while_node = @fieldParentPtr(While, "base", n);
if (while_node.@"else") |@"else"| {
n = &@"else".base;
continue;
}
- return while_node.body.id != Id.Block;
+ return while_node.body.id != .Block;
},
- Id.For => {
+ .For => {
const for_node = @fieldParentPtr(For, "base", n);
if (for_node.@"else") |@"else"| {
n = &@"else".base;
continue;
}
- return for_node.body.id != Id.Block;
+ return for_node.body.id != .Block;
},
- Id.If => {
+ .If => {
const if_node = @fieldParentPtr(If, "base", n);
if (if_node.@"else") |@"else"| {
n = &@"else".base;
continue;
}
- return if_node.body.id != Id.Block;
+ return if_node.body.id != .Block;
},
- Id.Else => {
+ .Else => {
const else_node = @fieldParentPtr(Else, "base", n);
n = else_node.body;
continue;
},
- Id.Defer => {
+ .Defer => {
const defer_node = @fieldParentPtr(Defer, "base", n);
- return defer_node.expr.id != Id.Block;
+ return defer_node.expr.id != .Block;
},
- Id.Comptime => {
+ .Comptime => {
const comptime_node = @fieldParentPtr(Comptime, "base", n);
- return comptime_node.expr.id != Id.Block;
+ return comptime_node.expr.id != .Block;
},
- Id.Suspend => {
+ .Suspend => {
const suspend_node = @fieldParentPtr(Suspend, "base", n);
if (suspend_node.body) |body| {
- return body.id != Id.Block;
+ return body.id != .Block;
}
return true;
},
+ .Noasync => {
+ const noasync_node = @fieldParentPtr(Noasync, "base", n);
+ return noasync_node.expr.id != .Block;
+ },
else => return true,
}
}
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index 9a023bb525d6539fbb40b350ace5c96de9eaa517..ddea0fc57c55adff55785e0add4ccff4db2bad10 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -1,3 +1,14 @@
+test "zig fmt: noasync block" {
+ try testCanonical(
+ \\pub fn main() anyerror!void {
+ \\ noasync {
+ \\ var foo: Foo = .{ .bar = 42 };
+ \\ }
+ \\}
+ \\
+ );
+}
+
test "zig fmt: noasync await" {
try testCanonical(
\\fn foo() void {
--
2.54.0
From ba0e3be5cfa2f60f2f9d2a4eb319408f972796c2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 15:27:45 -0400
Subject: [PATCH 036/111] (breaking) rework stream abstractions
The main goal here is to make the function pointers comptime, so that we
don't have to do the crazy stuff with async function frames.
Since InStream, OutStream, and SeekableStream are already generic
across error sets, it's not really worse to make them generic across the
vtable as well.
See #764 for the open issue acknowledging that using generics for these
abstractions is a design flaw.
See #130 for the efforts to make these abstractions non-generic.
This commit also changes the OutStream API so that `write` returns
number of bytes written, and `writeAll` is the one that loops until the
whole buffer is written.
---
lib/std/buffer.zig | 11 ++
lib/std/child_process.zig | 10 +-
lib/std/debug.zig | 233 ++++++++++++++------------
lib/std/dwarf.zig | 161 +++++++++---------
lib/std/elf.zig | 48 ++++++
lib/std/fs.zig | 2 +-
lib/std/fs/file.zig | 94 +++--------
lib/std/io.zig | 219 ++++++------------------
lib/std/io/buffered_atomic_file.zig | 50 ++++++
lib/std/io/buffered_out_stream.zig | 56 +++++++
lib/std/io/c_out_stream.zig | 43 -----
lib/std/io/counting_out_stream.zig | 42 +++++
lib/std/io/fixed_buffer_stream.zig | 66 ++++++++
lib/std/io/in_stream.zig | 81 ++++-----
lib/std/io/out_stream.zig | 75 ++++-----
lib/std/io/seekable_stream.zig | 105 +++---------
lib/std/json/write_stream.zig | 32 ++--
lib/std/os.zig | 2 +-
lib/std/pdb.zig | 10 +-
lib/std/zig/ast.zig | 2 +-
lib/std/zig/render.zig | 139 ++++++++-------
src-self-hosted/libc_installation.zig | 4 +-
src-self-hosted/print_targets.zig | 13 +-
src-self-hosted/stage2.zig | 30 ++--
24 files changed, 752 insertions(+), 776 deletions(-)
create mode 100644 lib/std/io/buffered_atomic_file.zig
create mode 100644 lib/std/io/buffered_out_stream.zig
delete mode 100644 lib/std/io/c_out_stream.zig
create mode 100644 lib/std/io/counting_out_stream.zig
create mode 100644 lib/std/io/fixed_buffer_stream.zig
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index 9bf024191e42dbf804fdac4fd22e14468a1e6c15..a33670b6d3fc8c4b1ebf6d5d0aaecde5df4599fc 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -157,6 +157,17 @@ pub const Buffer = struct {
pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
}
+
+ pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
+ return .{ .context = self };
+ }
+
+ /// Same as `append` except it returns the number of bytes written, which is always the same
+ /// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API.
+ pub fn appendWrite(self: *Buffer, m: []const u8) !usize {
+ try self.append(m);
+ return m.len;
+ }
};
test "simple Buffer" {
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
index 4f5fc2b49694ad956eacc66c36e39b0294ce83dd..95619384b18a5574db9db01e45f15964d4d7cced 100644
--- a/lib/std/child_process.zig
+++ b/lib/std/child_process.zig
@@ -221,9 +221,9 @@ pub const ChildProcess = struct {
var stderr_file_in_stream = child.stderr.?.inStream();
// TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O).
- const stdout = try stdout_file_in_stream.stream.readAllAlloc(args.allocator, args.max_output_bytes);
+ const stdout = try stdout_file_in_stream.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stdout);
- const stderr = try stderr_file_in_stream.stream.readAllAlloc(args.allocator, args.max_output_bytes);
+ const stderr = try stderr_file_in_stream.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stderr);
return ExecResult{
@@ -857,8 +857,7 @@ fn writeIntFd(fd: i32, value: ErrInt) !void {
.io_mode = .blocking,
.async_block_allowed = File.async_block_allowed_yes,
};
- const stream = &file.outStream().stream;
- stream.writeIntNative(u64, @intCast(u64, value)) catch return error.SystemResources;
+ file.outStream().writeIntNative(u64, @intCast(u64, value)) catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
@@ -867,8 +866,7 @@ fn readIntFd(fd: i32) !ErrInt {
.io_mode = .blocking,
.async_block_allowed = File.async_block_allowed_yes,
};
- const stream = &file.inStream().stream;
- return @intCast(ErrInt, stream.readIntNative(u64) catch return error.SystemResources);
+ return @intCast(ErrInt, file.inStream().readIntNative(u64) catch return error.SystemResources);
}
/// Caller must free result.
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 558b7e051372c2d5cacb391a89972e126d1ad07a..5c564905193e42569a01e1b5c741c20a4e83299a 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -55,7 +55,7 @@ pub const LineInfo = struct {
var stderr_file: File = undefined;
var stderr_file_out_stream: File.OutStream = undefined;
-var stderr_stream: ?*io.OutStream(File.WriteError) = null;
+var stderr_stream: ?*File.OutStream = null;
var stderr_mutex = std.Mutex.init();
pub fn warn(comptime fmt: []const u8, args: var) void {
@@ -65,13 +65,13 @@ pub fn warn(comptime fmt: []const u8, args: var) void {
noasync stderr.print(fmt, args) catch return;
}
-pub fn getStderrStream() *io.OutStream(File.WriteError) {
+pub fn getStderrStream() *File.OutStream {
if (stderr_stream) |st| {
return st;
} else {
stderr_file = io.getStdErr();
stderr_file_out_stream = stderr_file.outStream();
- const st = &stderr_file_out_stream.stream;
+ const st = &stderr_file_out_stream;
stderr_stream = st;
return st;
}
@@ -408,15 +408,15 @@ pub const TTY = struct {
windows_api,
fn setColor(conf: Config, out_stream: var, color: Color) void {
- switch (conf) {
+ noasync switch (conf) {
.no_color => return,
.escape_codes => switch (color) {
- .Red => noasync out_stream.write(RED) catch return,
- .Green => noasync out_stream.write(GREEN) catch return,
- .Cyan => noasync out_stream.write(CYAN) catch return,
- .White, .Bold => noasync out_stream.write(WHITE) catch return,
- .Dim => noasync out_stream.write(DIM) catch return,
- .Reset => noasync out_stream.write(RESET) catch return,
+ .Red => out_stream.writeAll(RED) catch return,
+ .Green => out_stream.writeAll(GREEN) catch return,
+ .Cyan => out_stream.writeAll(CYAN) catch return,
+ .White, .Bold => out_stream.writeAll(WHITE) catch return,
+ .Dim => out_stream.writeAll(DIM) catch return,
+ .Reset => out_stream.writeAll(RESET) catch return,
},
.windows_api => if (builtin.os.tag == .windows) {
const S = struct {
@@ -455,7 +455,7 @@ pub const TTY = struct {
} else {
unreachable;
},
- }
+ };
}
};
};
@@ -565,38 +565,40 @@ fn printLineInfo(
tty_config: TTY.Config,
comptime printLineFromFile: var,
) !void {
- tty_config.setColor(out_stream, .White);
+ noasync {
+ tty_config.setColor(out_stream, .White);
- if (line_info) |*li| {
- try noasync out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
- } else {
- try noasync out_stream.write("???:?:?");
- }
+ if (line_info) |*li| {
+ try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
+ } else {
+ try out_stream.writeAll("???:?:?");
+ }
- tty_config.setColor(out_stream, .Reset);
- try noasync out_stream.write(": ");
- tty_config.setColor(out_stream, .Dim);
- try noasync out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
- tty_config.setColor(out_stream, .Reset);
- try noasync out_stream.write("\n");
+ tty_config.setColor(out_stream, .Reset);
+ try out_stream.writeAll(": ");
+ tty_config.setColor(out_stream, .Dim);
+ try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
+ tty_config.setColor(out_stream, .Reset);
+ try out_stream.writeAll("\n");
- // Show the matching source code line if possible
- if (line_info) |li| {
- if (noasync printLineFromFile(out_stream, li)) {
- if (li.column > 0) {
- // The caret already takes one char
- const space_needed = @intCast(usize, li.column - 1);
+ // Show the matching source code line if possible
+ if (line_info) |li| {
+ if (printLineFromFile(out_stream, li)) {
+ if (li.column > 0) {
+ // The caret already takes one char
+ const space_needed = @intCast(usize, li.column - 1);
- try noasync out_stream.writeByteNTimes(' ', space_needed);
- tty_config.setColor(out_stream, .Green);
- try noasync out_stream.write("^");
- tty_config.setColor(out_stream, .Reset);
+ try out_stream.writeByteNTimes(' ', space_needed);
+ tty_config.setColor(out_stream, .Green);
+ try out_stream.writeAll("^");
+ tty_config.setColor(out_stream, .Reset);
+ }
+ try out_stream.writeAll("\n");
+ } else |err| switch (err) {
+ error.EndOfFile, error.FileNotFound => {},
+ error.BadPathName => {},
+ else => return err,
}
- try noasync out_stream.write("\n");
- } else |err| switch (err) {
- error.EndOfFile, error.FileNotFound => {},
- error.BadPathName => {},
- else => return err,
}
}
}
@@ -609,21 +611,21 @@ pub const OpenSelfDebugInfoError = error{
};
/// TODO resources https://github.com/ziglang/zig/issues/4353
-/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
-/// make this `noasync fn` and remove the individual noasync calls.
pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
- if (builtin.strip_debug_info)
- return error.MissingDebugInfo;
- if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
- return noasync root.os.debug.openSelfDebugInfo(allocator);
- }
- switch (builtin.os.tag) {
- .linux,
- .freebsd,
- .macosx,
- .windows,
- => return DebugInfo.init(allocator),
- else => @compileError("openSelfDebugInfo unsupported for this platform"),
+ noasync {
+ if (builtin.strip_debug_info)
+ return error.MissingDebugInfo;
+ if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
+ return root.os.debug.openSelfDebugInfo(allocator);
+ }
+ switch (builtin.os.tag) {
+ .linux,
+ .freebsd,
+ .macosx,
+ .windows,
+ => return DebugInfo.init(allocator),
+ else => @compileError("openSelfDebugInfo unsupported for this platform"),
+ }
}
}
@@ -808,45 +810,64 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {
/// TODO resources https://github.com/ziglang/zig/issues/4353
pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo {
- const mapped_mem = try mapWholeFile(elf_file_path);
-
- var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);
- var efile = try noasync elf.Elf.openStream(
- allocator,
- @ptrCast(*DW.DwarfSeekableStream, &seekable_stream.seekable_stream),
- @ptrCast(*DW.DwarfInStream, &seekable_stream.stream),
- );
- defer noasync efile.close();
-
- const debug_info = (try noasync efile.findSection(".debug_info")) orelse
- return error.MissingDebugInfo;
- const debug_abbrev = (try noasync efile.findSection(".debug_abbrev")) orelse
- return error.MissingDebugInfo;
- const debug_str = (try noasync efile.findSection(".debug_str")) orelse
- return error.MissingDebugInfo;
- const debug_line = (try noasync efile.findSection(".debug_line")) orelse
- return error.MissingDebugInfo;
- const opt_debug_ranges = try noasync efile.findSection(".debug_ranges");
-
- var di = DW.DwarfInfo{
- .endian = efile.endian,
- .debug_info = try chopSlice(mapped_mem, debug_info.sh_offset, debug_info.sh_size),
- .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.sh_offset, debug_abbrev.sh_size),
- .debug_str = try chopSlice(mapped_mem, debug_str.sh_offset, debug_str.sh_size),
- .debug_line = try chopSlice(mapped_mem, debug_line.sh_offset, debug_line.sh_size),
- .debug_ranges = if (opt_debug_ranges) |debug_ranges|
- try chopSlice(mapped_mem, debug_ranges.sh_offset, debug_ranges.sh_size)
- else
- null,
- };
-
- try noasync DW.openDwarfDebugInfo(&di, allocator);
-
- return ModuleDebugInfo{
- .base_address = undefined,
- .dwarf = di,
- .mapped_memory = mapped_mem,
- };
+ noasync {
+ const mapped_mem = try mapWholeFile(elf_file_path);
+ const hdr = @ptrCast(*const elf.Ehdr, &mapped_mem[0]);
+ if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
+ if (hdr.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;
+
+ const endian: builtin.Endian = switch (hdr.e_ident[elf.EI_DATA]) {
+ elf.ELFDATA2LSB => .Little,
+ elf.ELFDATA2MSB => .Big,
+ else => return error.InvalidElfEndian,
+ };
+ assert(endian == std.builtin.endian); // this is our own debug info
+
+ const shoff = hdr.e_shoff;
+ const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx);
+ const header_strings = mapped_mem[str_section_off..str_section_off + hdr.e_shentsize];
+ const shdrs = @ptrCast([*]const elf.Shdr, @alignCast(@alignOf(elf.Shdr), &mapped_mem[shoff]))[0..hdr.e_shnum];
+
+ var opt_debug_info: ?[]const u8 = null;
+ var opt_debug_abbrev: ?[]const u8 = null;
+ var opt_debug_str: ?[]const u8 = null;
+ var opt_debug_line: ?[]const u8 = null;
+ var opt_debug_ranges: ?[]const u8 = null;
+
+ for (shdrs) |*shdr| {
+ if (shdr.sh_type == elf.SHT_NULL) continue;
+
+ const name = std.mem.span(@ptrCast([*:0]const u8, header_strings[shdr.sh_name..].ptr));
+ if (mem.eql(u8, name, ".debug_info")) {
+ opt_debug_info = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
+ } else if (mem.eql(u8, name, ".debug_abbrev")) {
+ opt_debug_abbrev = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
+ } else if (mem.eql(u8, name, ".debug_str")) {
+ opt_debug_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
+ } else if (mem.eql(u8, name, ".debug_line")) {
+ opt_debug_line = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
+ } else if (mem.eql(u8, name, ".debug_ranges")) {
+ opt_debug_ranges = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
+ }
+ }
+
+ var di = DW.DwarfInfo{
+ .endian = endian,
+ .debug_info = opt_debug_info orelse return error.MissingDebugInfo,
+ .debug_abbrev = opt_debug_abbrev orelse return error.MissingDebugInfo,
+ .debug_str = opt_debug_str orelse return error.MissingDebugInfo,
+ .debug_line = opt_debug_line orelse return error.MissingDebugInfo,
+ .debug_ranges = opt_debug_ranges,
+ };
+
+ try DW.openDwarfDebugInfo(&di, allocator);
+
+ return ModuleDebugInfo{
+ .base_address = undefined,
+ .dwarf = di,
+ .mapped_memory = mapped_mem,
+ };
+ }
}
/// TODO resources https://github.com/ziglang/zig/issues/4353
@@ -982,22 +1003,24 @@ const MachoSymbol = struct {
}
};
-fn mapWholeFile(path: []const u8) ![]const u8 {
- const file = try noasync fs.openFileAbsolute(path, .{ .always_blocking = true });
- defer noasync file.close();
+fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 {
+ noasync {
+ const file = try fs.openFileAbsolute(path, .{ .always_blocking = true });
+ defer file.close();
- const file_len = try math.cast(usize, try file.getEndPos());
- const mapped_mem = try os.mmap(
- null,
- file_len,
- os.PROT_READ,
- os.MAP_SHARED,
- file.handle,
- 0,
- );
- errdefer os.munmap(mapped_mem);
+ const file_len = try math.cast(usize, try file.getEndPos());
+ const mapped_mem = try os.mmap(
+ null,
+ file_len,
+ os.PROT_READ,
+ os.MAP_SHARED,
+ file.handle,
+ 0,
+ );
+ errdefer os.munmap(mapped_mem);
- return mapped_mem;
+ return mapped_mem;
+ }
}
pub const DebugInfo = struct {
diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig
index 32a49b68e0b8ec544edebe28bfcf048ca6756dd2..769f349e33e32d75e63c2ddb35f0ca2d0b810f29 100644
--- a/lib/std/dwarf.zig
+++ b/lib/std/dwarf.zig
@@ -11,9 +11,6 @@ const ArrayList = std.ArrayList;
usingnamespace @import("dwarf_bits.zig");
-pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror);
-pub const DwarfInStream = io.InStream(anyerror);
-
const PcRange = struct {
start: u64,
end: u64,
@@ -239,7 +236,7 @@ const LineNumberProgram = struct {
}
};
-fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
+fn readInitialLength(in_stream: var, is_64: *bool) !u64 {
const first_32_bits = try in_stream.readIntLittle(u32);
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
@@ -414,40 +411,42 @@ pub const DwarfInfo = struct {
}
fn scanAllFunctions(di: *DwarfInfo) !void {
- var s = io.SliceSeekableInStream.init(di.debug_info);
+ var stream = io.fixedBufferStream(di.debug_info);
+ const in = &stream.inStream();
+ const seekable = &stream.seekableStream();
var this_unit_offset: u64 = 0;
- while (this_unit_offset < try s.seekable_stream.getEndPos()) {
- s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) {
+ while (this_unit_offset < try seekable.getEndPos()) {
+ seekable.seekTo(this_unit_offset) catch |err| switch (err) {
error.EndOfStream => unreachable,
else => return err,
};
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
+ const unit_length = try readInitialLength(in, &is_64);
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try s.stream.readInt(u16, di.endian);
+ const version = try in.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
+ const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);
- const address_size = try s.stream.readByte();
+ const address_size = try in.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
- const compile_unit_pos = try s.seekable_stream.getPos();
+ const compile_unit_pos = try seekable.getPos();
const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset);
- try s.seekable_stream.seekTo(compile_unit_pos);
+ try seekable.seekTo(compile_unit_pos);
const next_unit_pos = this_unit_offset + next_offset;
- while ((try s.seekable_stream.getPos()) < next_unit_pos) {
- const die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse continue;
+ while ((try seekable.getPos()) < next_unit_pos) {
+ const die_obj = (try di.parseDie(in, abbrev_table, is_64)) orelse continue;
defer die_obj.attrs.deinit();
- const after_die_offset = try s.seekable_stream.getPos();
+ const after_die_offset = try seekable.getPos();
switch (die_obj.tag_id) {
TAG_subprogram, TAG_inlined_subroutine, TAG_subroutine, TAG_entry_point => {
@@ -463,14 +462,14 @@ pub const DwarfInfo = struct {
// Follow the DIE it points to and repeat
const ref_offset = try this_die_obj.getAttrRef(AT_abstract_origin);
if (ref_offset > next_offset) return error.InvalidDebugInfo;
- try s.seekable_stream.seekTo(this_unit_offset + ref_offset);
- this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ try seekable.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try di.parseDie(in, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
} else if (this_die_obj.getAttr(AT_specification)) |ref| {
// Follow the DIE it points to and repeat
const ref_offset = try this_die_obj.getAttrRef(AT_specification);
if (ref_offset > next_offset) return error.InvalidDebugInfo;
- try s.seekable_stream.seekTo(this_unit_offset + ref_offset);
- this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ try seekable.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try di.parseDie(in, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
} else {
break :x null;
}
@@ -511,7 +510,7 @@ pub const DwarfInfo = struct {
else => {},
}
- try s.seekable_stream.seekTo(after_die_offset);
+ try seekable.seekTo(after_die_offset);
}
this_unit_offset += next_offset;
@@ -519,35 +518,37 @@ pub const DwarfInfo = struct {
}
fn scanAllCompileUnits(di: *DwarfInfo) !void {
- var s = io.SliceSeekableInStream.init(di.debug_info);
+ var stream = io.fixedBufferStream(di.debug_info);
+ const in = &stream.inStream();
+ const seekable = &stream.seekableStream();
var this_unit_offset: u64 = 0;
- while (this_unit_offset < try s.seekable_stream.getEndPos()) {
- s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) {
+ while (this_unit_offset < try seekable.getEndPos()) {
+ seekable.seekTo(this_unit_offset) catch |err| switch (err) {
error.EndOfStream => unreachable,
else => return err,
};
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
+ const unit_length = try readInitialLength(in, &is_64);
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try s.stream.readInt(u16, di.endian);
+ const version = try in.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
+ const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);
- const address_size = try s.stream.readByte();
+ const address_size = try in.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
- const compile_unit_pos = try s.seekable_stream.getPos();
+ const compile_unit_pos = try seekable.getPos();
const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset);
- try s.seekable_stream.seekTo(compile_unit_pos);
+ try seekable.seekTo(compile_unit_pos);
const compile_unit_die = try di.allocator().create(Die);
- compile_unit_die.* = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ compile_unit_die.* = (try di.parseDie(in, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
if (compile_unit_die.tag_id != TAG_compile_unit) return error.InvalidDebugInfo;
@@ -593,7 +594,9 @@ pub const DwarfInfo = struct {
}
if (di.debug_ranges) |debug_ranges| {
if (compile_unit.die.getAttrSecOffset(AT_ranges)) |ranges_offset| {
- var s = io.SliceSeekableInStream.init(debug_ranges);
+ var stream = io.fixedBufferStream(debug_ranges);
+ const in = &stream.inStream();
+ const seekable = &stream.seekableStream();
// All the addresses in the list are relative to the value
// specified by DW_AT_low_pc or to some other value encoded
@@ -604,11 +607,11 @@ pub const DwarfInfo = struct {
else => return err,
};
- try s.seekable_stream.seekTo(ranges_offset);
+ try seekable.seekTo(ranges_offset);
while (true) {
- const begin_addr = try s.stream.readIntLittle(usize);
- const end_addr = try s.stream.readIntLittle(usize);
+ const begin_addr = try in.readIntLittle(usize);
+ const end_addr = try in.readIntLittle(usize);
if (begin_addr == 0 and end_addr == 0) {
break;
}
@@ -646,25 +649,27 @@ pub const DwarfInfo = struct {
}
fn parseAbbrevTable(di: *DwarfInfo, offset: u64) !AbbrevTable {
- var s = io.SliceSeekableInStream.init(di.debug_abbrev);
+ var stream = io.fixedBufferStream(di.debug_abbrev);
+ const in = &stream.inStream();
+ const seekable = &stream.seekableStream();
- try s.seekable_stream.seekTo(offset);
+ try seekable.seekTo(offset);
var result = AbbrevTable.init(di.allocator());
errdefer result.deinit();
while (true) {
- const abbrev_code = try leb.readULEB128(u64, &s.stream);
+ const abbrev_code = try leb.readULEB128(u64, in);
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
.abbrev_code = abbrev_code,
- .tag_id = try leb.readULEB128(u64, &s.stream),
- .has_children = (try s.stream.readByte()) == CHILDREN_yes,
+ .tag_id = try leb.readULEB128(u64, in),
+ .has_children = (try in.readByte()) == CHILDREN_yes,
.attrs = ArrayList(AbbrevAttr).init(di.allocator()),
});
const attrs = &result.items[result.len - 1].attrs;
while (true) {
- const attr_id = try leb.readULEB128(u64, &s.stream);
- const form_id = try leb.readULEB128(u64, &s.stream);
+ const attr_id = try leb.readULEB128(u64, in);
+ const form_id = try leb.readULEB128(u64, in);
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
.attr_id = attr_id,
@@ -695,42 +700,44 @@ pub const DwarfInfo = struct {
}
fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !debug.LineInfo {
- var s = io.SliceSeekableInStream.init(di.debug_line);
+ var stream = io.fixedBufferStream(di.debug_line);
+ const in = &stream.inStream();
+ const seekable = &stream.seekableStream();
const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT_comp_dir);
const line_info_offset = try compile_unit.die.getAttrSecOffset(AT_stmt_list);
- try s.seekable_stream.seekTo(line_info_offset);
+ try seekable.seekTo(line_info_offset);
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
+ const unit_length = try readInitialLength(in, &is_64);
if (unit_length == 0) {
return error.MissingDebugInfo;
}
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try s.stream.readInt(u16, di.endian);
+ const version = try in.readInt(u16, di.endian);
// TODO support 3 and 5
if (version != 2 and version != 4) return error.InvalidDebugInfo;
- const prologue_length = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
- const prog_start_offset = (try s.seekable_stream.getPos()) + prologue_length;
+ const prologue_length = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);
+ const prog_start_offset = (try seekable.getPos()) + prologue_length;
- const minimum_instruction_length = try s.stream.readByte();
+ const minimum_instruction_length = try in.readByte();
if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
if (version >= 4) {
// maximum_operations_per_instruction
- _ = try s.stream.readByte();
+ _ = try in.readByte();
}
- const default_is_stmt = (try s.stream.readByte()) != 0;
- const line_base = try s.stream.readByteSigned();
+ const default_is_stmt = (try in.readByte()) != 0;
+ const line_base = try in.readByteSigned();
- const line_range = try s.stream.readByte();
+ const line_range = try in.readByte();
if (line_range == 0) return error.InvalidDebugInfo;
- const opcode_base = try s.stream.readByte();
+ const opcode_base = try in.readByte();
const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
defer di.allocator().free(standard_opcode_lengths);
@@ -738,14 +745,14 @@ pub const DwarfInfo = struct {
{
var i: usize = 0;
while (i < opcode_base - 1) : (i += 1) {
- standard_opcode_lengths[i] = try s.stream.readByte();
+ standard_opcode_lengths[i] = try in.readByte();
}
}
var include_directories = ArrayList([]const u8).init(di.allocator());
try include_directories.append(compile_unit_cwd);
while (true) {
- const dir = try s.stream.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
+ const dir = try in.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
if (dir.len == 0) break;
try include_directories.append(dir);
}
@@ -754,11 +761,11 @@ pub const DwarfInfo = struct {
var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
while (true) {
- const file_name = try s.stream.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
+ const file_name = try in.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
if (file_name.len == 0) break;
- const dir_index = try leb.readULEB128(usize, &s.stream);
- const mtime = try leb.readULEB128(usize, &s.stream);
- const len_bytes = try leb.readULEB128(usize, &s.stream);
+ const dir_index = try leb.readULEB128(usize, in);
+ const mtime = try leb.readULEB128(usize, in);
+ const len_bytes = try leb.readULEB128(usize, in);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -767,17 +774,17 @@ pub const DwarfInfo = struct {
});
}
- try s.seekable_stream.seekTo(prog_start_offset);
+ try seekable.seekTo(prog_start_offset);
const next_unit_pos = line_info_offset + next_offset;
- while ((try s.seekable_stream.getPos()) < next_unit_pos) {
- const opcode = try s.stream.readByte();
+ while ((try seekable.getPos()) < next_unit_pos) {
+ const opcode = try in.readByte();
if (opcode == LNS_extended_op) {
- const op_size = try leb.readULEB128(u64, &s.stream);
+ const op_size = try leb.readULEB128(u64, in);
if (op_size < 1) return error.InvalidDebugInfo;
- var sub_op = try s.stream.readByte();
+ var sub_op = try in.readByte();
switch (sub_op) {
LNE_end_sequence => {
prog.end_sequence = true;
@@ -785,14 +792,14 @@ pub const DwarfInfo = struct {
prog.reset();
},
LNE_set_address => {
- const addr = try s.stream.readInt(usize, di.endian);
+ const addr = try in.readInt(usize, di.endian);
prog.address = addr;
},
LNE_define_file => {
- const file_name = try s.stream.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
- const dir_index = try leb.readULEB128(usize, &s.stream);
- const mtime = try leb.readULEB128(usize, &s.stream);
- const len_bytes = try leb.readULEB128(usize, &s.stream);
+ const file_name = try in.readUntilDelimiterAlloc(di.allocator(), 0, math.maxInt(usize));
+ const dir_index = try leb.readULEB128(usize, in);
+ const mtime = try leb.readULEB128(usize, in);
+ const len_bytes = try leb.readULEB128(usize, in);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -802,7 +809,7 @@ pub const DwarfInfo = struct {
},
else => {
const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
- try s.seekable_stream.seekBy(fwd_amt);
+ try seekable.seekBy(fwd_amt);
},
}
} else if (opcode >= opcode_base) {
@@ -821,19 +828,19 @@ pub const DwarfInfo = struct {
prog.basic_block = false;
},
LNS_advance_pc => {
- const arg = try leb.readULEB128(usize, &s.stream);
+ const arg = try leb.readULEB128(usize, in);
prog.address += arg * minimum_instruction_length;
},
LNS_advance_line => {
- const arg = try leb.readILEB128(i64, &s.stream);
+ const arg = try leb.readILEB128(i64, in);
prog.line += arg;
},
LNS_set_file => {
- const arg = try leb.readULEB128(usize, &s.stream);
+ const arg = try leb.readULEB128(usize, in);
prog.file = arg;
},
LNS_set_column => {
- const arg = try leb.readULEB128(u64, &s.stream);
+ const arg = try leb.readULEB128(u64, in);
prog.column = arg;
},
LNS_negate_stmt => {
@@ -847,14 +854,14 @@ pub const DwarfInfo = struct {
prog.address += inc_addr;
},
LNS_fixed_advance_pc => {
- const arg = try s.stream.readInt(u16, di.endian);
+ const arg = try in.readInt(u16, di.endian);
prog.address += arg;
},
LNS_set_prologue_end => {},
else => {
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
const len_bytes = standard_opcode_lengths[opcode - 1];
- try s.seekable_stream.seekBy(len_bytes);
+ try seekable.seekBy(len_bytes);
},
}
}
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index fc57db7c9812aec7aef8dccc4425cc9aaacc5586..efaa4d6f062713e8d3490562f35a61ac9300032f 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -333,6 +333,54 @@ pub const ET = extern enum(u16) {
pub const SectionHeader = Elf64_Shdr;
pub const ProgramHeader = Elf64_Phdr;
+const Header = struct {
+ endian: builtin.Endian,
+ is_64: bool,
+ entry: u64,
+ phoff: u64,
+ shoff: u64,
+ phentsize: u16,
+ phnum: u16,
+ shentsize: u16,
+ shnum: u16,
+ shstrndx: u16,
+};
+
+pub fn readHeader(in_stream: var) !Header {
+ var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;
+ try in_stream.readAll(&hdr_buf);
+ const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
+ const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
+ if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
+ if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
+
+ const endian = switch (hdr32.e_ident[elf.EI_DATA]) {
+ ELFDATA2LSB => .Little,
+ ELFDATA2MSB => .Big,
+ else => return error.InvalidElfEndian,
+ };
+ const need_bswap = endian != std.builtin.endian;
+
+ const is_64 = switch (hdr32.e_ident[EI_CLASS]) {
+ ELFCLASS32 => false,
+ ELFCLASS64 => true,
+ else => return error.InvalidElfClass,
+ };
+
+ return @as(Header, .{
+ .endian = endian,
+ .is_64 = is_64,
+ .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),
+ .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),
+ .shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff),
+ .phentsize = int(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize),
+ .phnum = int(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum),
+ .shentsize = int(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize),
+ .shnum = int(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum),
+ .shstrndx = int(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx),
+ });
+}
+
pub const Elf = struct {
seekable_stream: *io.SeekableStream(anyerror, anyerror),
in_stream: *io.InStream(anyerror),
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 1f20a14f744c3e904224ddb59035ce479a7e0a0c..892b97729150e91a4b0cf5b09cc96f7057a8a01d 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1150,7 +1150,7 @@ pub const Dir = struct {
const buf = try allocator.alignedAlloc(u8, A, size);
errdefer allocator.free(buf);
- try file.inStream().stream.readNoEof(buf);
+ try file.inStream().readNoEof(buf);
return buf;
}
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 8f7a46ad3e97144ad2c30dd80a88bb9f108a83c9..845e4bc75ec25df6e91e138f89c782feb9c675b4 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -71,7 +71,7 @@ pub const File = struct {
if (need_async_thread and self.io_mode == .blocking and !self.async_block_allowed) {
std.event.Loop.instance.?.close(self.handle);
} else {
- return os.close(self.handle);
+ os.close(self.handle);
}
}
@@ -496,85 +496,29 @@ pub const File = struct {
}
}
- pub fn inStream(file: File) InStream {
- return InStream{
- .file = file,
- .stream = InStream.Stream{ .readFn = InStream.readFn },
- };
+ pub const InStream = io.InStream(File, ReadError, read);
+
+ pub fn inStream(file: File) io.InStream(File, ReadError, read) {
+ return .{ .context = file };
}
+ pub const OutStream = io.OutStream(File, WriteError, write);
+
pub fn outStream(file: File) OutStream {
- return OutStream{
- .file = file,
- .stream = OutStream.Stream{ .writeFn = OutStream.writeFn },
- };
+ return .{ .context = file };
}
+ pub const SeekableStream = io.SeekableStream(
+ File,
+ SeekError,
+ GetPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
pub fn seekableStream(file: File) SeekableStream {
- return SeekableStream{
- .file = file,
- .stream = SeekableStream.Stream{
- .seekToFn = SeekableStream.seekToFn,
- .seekByFn = SeekableStream.seekByFn,
- .getPosFn = SeekableStream.getPosFn,
- .getEndPosFn = SeekableStream.getEndPosFn,
- },
- };
+ return .{ .context = file };
}
-
- /// Implementation of io.InStream trait for File
- pub const InStream = struct {
- file: File,
- stream: Stream,
-
- pub const Error = ReadError;
- pub const Stream = io.InStream(Error);
-
- fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {
- const self = @fieldParentPtr(InStream, "stream", in_stream);
- return self.file.read(buffer);
- }
- };
-
- /// Implementation of io.OutStream trait for File
- pub const OutStream = struct {
- file: File,
- stream: Stream,
-
- pub const Error = WriteError;
- pub const Stream = io.OutStream(Error);
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- const self = @fieldParentPtr(OutStream, "stream", out_stream);
- return self.file.write(bytes);
- }
- };
-
- /// Implementation of io.SeekableStream trait for File
- pub const SeekableStream = struct {
- file: File,
- stream: Stream,
-
- pub const Stream = io.SeekableStream(SeekError, GetPosError);
-
- pub fn seekToFn(seekable_stream: *Stream, pos: u64) SeekError!void {
- const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
- return self.file.seekTo(pos);
- }
-
- pub fn seekByFn(seekable_stream: *Stream, amt: i64) SeekError!void {
- const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
- return self.file.seekBy(amt);
- }
-
- pub fn getEndPosFn(seekable_stream: *Stream) GetPosError!u64 {
- const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
- return self.file.getEndPos();
- }
-
- pub fn getPosFn(seekable_stream: *Stream) GetPosError!u64 {
- const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
- return self.file.getPos();
- }
- };
};
diff --git a/lib/std/io.zig b/lib/std/io.zig
index 99e9391f1d47e0c5ab6dd2d3940200f66542ad71..dcb0551dc9a7b8b416a20021d78a33decd775429 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -93,10 +93,46 @@ pub fn getStdIn() File {
}
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
-pub const SliceSeekableInStream = @import("io/seekable_stream.zig").SliceSeekableInStream;
-pub const COutStream = @import("io/c_out_stream.zig").COutStream;
pub const InStream = @import("io/in_stream.zig").InStream;
pub const OutStream = @import("io/out_stream.zig").OutStream;
+pub const FixedBufferInStream = @import("io/fixed_buffer_stream.zig").FixedBufferInStream;
+pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
+
+pub const BufferedOutStream = @import("io/buffered_out_stream.zig").BufferedOutStream;
+pub const BufferedOutStreamCustom = @import("io/buffered_out_stream.zig").BufferedOutStreamCustom;
+pub const bufferedOutStream = @import("io/buffered_out_stream.zig").bufferedOutStream;
+
+pub const CountingOutStream = @import("io/counting_out_stream.zig").CountingOutStream;
+
+pub fn fixedBufferStream(bytes: []const u8) FixedBufferInStream {
+ return (FixedBufferInStream{ .bytes = bytes, .pos = 0 });
+}
+
+pub fn cOutStream(c_file: *std.c.FILE) COutStream {
+ return .{ .context = c_file };
+}
+
+pub const COutStream = OutStream(*std.c.FILE, std.fs.File.WriteError, cOutStreamWrite);
+
+pub fn cOutStreamWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!usize {
+ const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, c_file);
+ if (amt_written >= 0) return amt_written;
+ switch (std.c._errno().*) {
+ 0 => unreachable,
+ os.EINVAL => unreachable,
+ os.EFAULT => unreachable,
+ os.EAGAIN => unreachable, // this is a blocking API
+ os.EBADF => unreachable, // always a race condition
+ os.EDESTADDRREQ => unreachable, // connect was never called
+ os.EDQUOT => return error.DiskQuota,
+ os.EFBIG => return error.FileTooBig,
+ os.EIO => return error.InputOutput,
+ os.ENOSPC => return error.NoSpaceLeft,
+ os.EPERM => return error.AccessDenied,
+ os.EPIPE => return error.BrokenPipe,
+ else => |err| return os.unexpectedErrno(@intCast(usize, err)),
+ }
+}
/// Deprecated; use `std.fs.Dir.writeFile`.
pub fn writeFile(path: []const u8, data: []const u8) !void {
@@ -495,139 +531,18 @@ test "io.SliceOutStream" {
testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten());
}
-var null_out_stream_state = NullOutStream.init();
-pub const null_out_stream = &null_out_stream_state.stream;
-
/// An OutStream that doesn't write to anything.
-pub const NullOutStream = struct {
- pub const Error = error{};
- pub const Stream = OutStream(Error);
+pub const null_out_stream = @as(NullOutStream, .{ .context = {} });
- stream: Stream,
-
- pub fn init() NullOutStream {
- return NullOutStream{
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- return bytes.len;
- }
-};
-
-test "io.NullOutStream" {
- var null_stream = NullOutStream.init();
- const stream = &null_stream.stream;
- stream.write("yay" ** 10000) catch unreachable;
-}
-
-/// An OutStream that counts how many bytes has been written to it.
-pub fn CountingOutStream(comptime OutStreamError: type) type {
- return struct {
- const Self = @This();
- pub const Stream = OutStream(Error);
- pub const Error = OutStreamError;
-
- stream: Stream,
- bytes_written: u64,
- child_stream: *Stream,
-
- pub fn init(child_stream: *Stream) Self {
- return Self{
- .stream = Stream{ .writeFn = writeFn },
- .bytes_written = 0,
- .child_stream = child_stream,
- };
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) OutStreamError!usize {
- const self = @fieldParentPtr(Self, "stream", out_stream);
- try self.child_stream.write(bytes);
- self.bytes_written += bytes.len;
- return bytes.len;
- }
- };
-}
-
-test "io.CountingOutStream" {
- var null_stream = NullOutStream.init();
- var counting_stream = CountingOutStream(NullOutStream.Error).init(&null_stream.stream);
- const stream = &counting_stream.stream;
-
- const bytes = "yay" ** 10000;
- stream.write(bytes) catch unreachable;
- testing.expect(counting_stream.bytes_written == bytes.len);
+const NullOutStream = OutStream(void, error{}, dummyWrite);
+fn dummyWrite(context: void, data: []const u8) error{}!usize {
+ return data.len;
}
-pub fn BufferedOutStream(comptime Error: type) type {
- return BufferedOutStreamCustom(mem.page_size, Error);
+test "null_out_stream" {
+ null_out_stream.writeAll("yay" ** 1000) catch |err| switch (err) {};
}
-pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamError: type) type {
- return struct {
- const Self = @This();
- pub const Stream = OutStream(Error);
- pub const Error = OutStreamError;
-
- stream: Stream,
-
- unbuffered_out_stream: *Stream,
-
- const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
- fifo: FifoType,
-
- pub fn init(unbuffered_out_stream: *Stream) Self {
- return Self{
- .unbuffered_out_stream = unbuffered_out_stream,
- .fifo = FifoType.init(),
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- pub fn flush(self: *Self) !void {
- while (true) {
- const slice = self.fifo.readableSlice(0);
- if (slice.len == 0) break;
- try self.unbuffered_out_stream.write(slice);
- self.fifo.discard(slice.len);
- }
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- const self = @fieldParentPtr(Self, "stream", out_stream);
- if (bytes.len >= self.fifo.writableLength()) {
- try self.flush();
- return self.unbuffered_out_stream.writeOnce(bytes);
- }
- self.fifo.writeAssumeCapacity(bytes);
- return bytes.len;
- }
- };
-}
-
-/// Implementation of OutStream trait for Buffer
-pub const BufferOutStream = struct {
- buffer: *Buffer,
- stream: Stream,
-
- pub const Error = error{OutOfMemory};
- pub const Stream = OutStream(Error);
-
- pub fn init(buffer: *Buffer) BufferOutStream {
- return BufferOutStream{
- .buffer = buffer,
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) !usize {
- const self = @fieldParentPtr(BufferOutStream, "stream", out_stream);
- try self.buffer.append(bytes);
- return bytes.len;
- }
-};
-
/// Creates a stream which allows for writing bit fields to another stream
pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
return struct {
@@ -752,52 +667,11 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
return buffer.len;
}
- return self.out_stream.writeOnce(buffer);
+ return self.out_stream.write(buffer);
}
};
}
-pub const BufferedAtomicFile = struct {
- atomic_file: fs.AtomicFile,
- file_stream: File.OutStream,
- buffered_stream: BufferedOutStream(File.WriteError),
- allocator: *mem.Allocator,
-
- pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
- // TODO with well defined copy elision we don't need this allocation
- var self = try allocator.create(BufferedAtomicFile);
- self.* = BufferedAtomicFile{
- .atomic_file = undefined,
- .file_stream = undefined,
- .buffered_stream = undefined,
- .allocator = allocator,
- };
- errdefer allocator.destroy(self);
-
- self.atomic_file = try fs.AtomicFile.init(dest_path, File.default_mode);
- errdefer self.atomic_file.deinit();
-
- self.file_stream = self.atomic_file.file.outStream();
- self.buffered_stream = BufferedOutStream(File.WriteError).init(&self.file_stream.stream);
- return self;
- }
-
- /// always call destroy, even after successful finish()
- pub fn destroy(self: *BufferedAtomicFile) void {
- self.atomic_file.deinit();
- self.allocator.destroy(self);
- }
-
- pub fn finish(self: *BufferedAtomicFile) !void {
- try self.buffered_stream.flush();
- try self.atomic_file.finish();
- }
-
- pub fn stream(self: *BufferedAtomicFile) *OutStream(File.WriteError) {
- return &self.buffered_stream.stream;
- }
-};
-
pub const Packing = enum {
/// Pack data to byte alignment
Byte,
@@ -1129,8 +1003,9 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
};
}
-test "import io tests" {
+test "" {
comptime {
_ = @import("io/test.zig");
}
+ std.meta.refAllDecls(@This());
}
diff --git a/lib/std/io/buffered_atomic_file.zig b/lib/std/io/buffered_atomic_file.zig
new file mode 100644
index 0000000000000000000000000000000000000000..48c550c90fa95f1c8899b53970711e572aab2ec3
--- /dev/null
+++ b/lib/std/io/buffered_atomic_file.zig
@@ -0,0 +1,50 @@
+const std = @import("../std.zig");
+const mem = std.mem;
+const fs = std.fs;
+const File = std.fs.File;
+
+pub const BufferedAtomicFile = struct {
+ atomic_file: fs.AtomicFile,
+ file_stream: File.OutStream,
+ buffered_stream: BufferedOutStream,
+ allocator: *mem.Allocator,
+
+ pub const buffer_size = 4096;
+ pub const BufferedOutStream = std.io.BufferedOutStreamCustom(buffer_size, File.OutStream);
+ pub const OutStream = std.io.OutStream(*BufferedOutStream, BufferedOutStream.Error, BufferedOutStream.write);
+
+ /// TODO when https://github.com/ziglang/zig/issues/2761 is solved
+ /// this API will not need an allocator
+ pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
+ var self = try allocator.create(BufferedAtomicFile);
+ self.* = BufferedAtomicFile{
+ .atomic_file = undefined,
+ .file_stream = undefined,
+ .buffered_stream = undefined,
+ .allocator = allocator,
+ };
+ errdefer allocator.destroy(self);
+
+ self.atomic_file = try fs.AtomicFile.init(dest_path, File.default_mode);
+ errdefer self.atomic_file.deinit();
+
+ self.file_stream = self.atomic_file.file.outStream();
+ self.buffered_stream = std.io.bufferedOutStream(buffer_size, self.file_stream);
+ return self;
+ }
+
+ /// always call destroy, even after successful finish()
+ pub fn destroy(self: *BufferedAtomicFile) void {
+ self.atomic_file.deinit();
+ self.allocator.destroy(self);
+ }
+
+ pub fn finish(self: *BufferedAtomicFile) !void {
+ try self.buffered_stream.flush();
+ try self.atomic_file.finish();
+ }
+
+ pub fn stream(self: *BufferedAtomicFile) OutStream {
+ return .{ .context = &self.buffered_stream };
+ }
+};
diff --git a/lib/std/io/buffered_out_stream.zig b/lib/std/io/buffered_out_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..3650022b29a607eea74bfaed4a1a5ba4785af702
--- /dev/null
+++ b/lib/std/io/buffered_out_stream.zig
@@ -0,0 +1,56 @@
+const std = @import("../std.zig");
+const io = std.io;
+
+pub fn BufferedOutStream(comptime OutStreamType: type) type {
+ return BufferedOutStreamCustom(4096, OutStreamType);
+}
+
+pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamType: type) type {
+ return struct {
+ unbuffered_out_stream: OutStreamType,
+ fifo: FifoType,
+
+ pub const Error = OutStreamType.Error;
+ pub const OutStream = io.OutStream(*Self, Error, write);
+
+ const Self = @This();
+ const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
+
+ pub fn init(unbuffered_out_stream: OutStreamType) Self {
+ return Self{
+ .unbuffered_out_stream = unbuffered_out_stream,
+ .fifo = FifoType.init(),
+ };
+ }
+
+ pub fn flush(self: *Self) !void {
+ while (true) {
+ const slice = self.fifo.readableSlice(0);
+ if (slice.len == 0) break;
+ try self.unbuffered_out_stream.writeAll(slice);
+ self.fifo.discard(slice.len);
+ }
+ }
+
+ pub fn outStream(self: *Self) OutStream {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ if (bytes.len >= self.fifo.writableLength()) {
+ try self.flush();
+ return self.unbuffered_out_stream.write(bytes);
+ }
+ self.fifo.writeAssumeCapacity(bytes);
+ return bytes.len;
+ }
+ };
+}
+
+pub fn bufferedOutStream(
+ comptime buffer_size: usize,
+ underlying_stream: var,
+) BufferedOutStreamCustom(buffer_size, @TypeOf(underlying_stream)) {
+ return BufferedOutStreamCustom(buffer_size, @TypeOf(underlying_stream)).init(underlying_stream);
+}
+
diff --git a/lib/std/io/c_out_stream.zig b/lib/std/io/c_out_stream.zig
deleted file mode 100644
index adaa3fcbafdcd23ae30fd7b9fd395037b05d6bd2..0000000000000000000000000000000000000000
--- a/lib/std/io/c_out_stream.zig
+++ /dev/null
@@ -1,43 +0,0 @@
-const std = @import("../std.zig");
-const os = std.os;
-const OutStream = std.io.OutStream;
-const builtin = @import("builtin");
-
-/// TODO make a proposal to make `std.fs.File` use *FILE when linking libc and this just becomes
-/// std.io.FileOutStream because std.fs.File.write would do this when linking
-/// libc.
-pub const COutStream = struct {
- pub const Error = std.fs.File.WriteError;
- pub const Stream = OutStream(Error);
-
- stream: Stream,
- c_file: *std.c.FILE,
-
- pub fn init(c_file: *std.c.FILE) COutStream {
- return COutStream{
- .c_file = c_file,
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- const self = @fieldParentPtr(COutStream, "stream", out_stream);
- const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
- if (amt_written >= 0) return amt_written;
- switch (std.c._errno().*) {
- 0 => unreachable,
- os.EINVAL => unreachable,
- os.EFAULT => unreachable,
- os.EAGAIN => unreachable, // this is a blocking API
- os.EBADF => unreachable, // always a race condition
- os.EDESTADDRREQ => unreachable, // connect was never called
- os.EDQUOT => return error.DiskQuota,
- os.EFBIG => return error.FileTooBig,
- os.EIO => return error.InputOutput,
- os.ENOSPC => return error.NoSpaceLeft,
- os.EPERM => return error.AccessDenied,
- os.EPIPE => return error.BrokenPipe,
- else => |err| return os.unexpectedErrno(@intCast(usize, err)),
- }
- }
-};
diff --git a/lib/std/io/counting_out_stream.zig b/lib/std/io/counting_out_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..2b0cba29fc6c2dce185a7e510a2555a5c3ae4658
--- /dev/null
+++ b/lib/std/io/counting_out_stream.zig
@@ -0,0 +1,42 @@
+const std = @import("../std.zig");
+const io = std.io;
+
+/// An OutStream that counts how many bytes has been written to it.
+pub fn CountingOutStream(comptime OutStreamType: type) type {
+ return struct {
+ bytes_written: u64,
+ child_stream: OutStreamType,
+
+ pub const Error = OutStreamType.Error;
+ pub const OutStream = io.OutStream(*Self, Error, write);
+
+ const Self = @This();
+
+ pub fn init(child_stream: OutStreamType) Self {
+ return Self{
+ .bytes_written = 0,
+ .child_stream = child_stream,
+ };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ const amt = try self.child_stream.write(bytes);
+ self.bytes_written += amt;
+ return amt;
+ }
+
+ pub fn outStream(self: *Self) OutStream {
+ return .{ .context = self };
+ }
+ };
+}
+
+test "io.CountingOutStream" {
+ var counting_stream = CountingOutStream(NullOutStream.Error).init(std.io.null_out_stream);
+ const stream = &counting_stream.stream;
+
+ const bytes = "yay" ** 10000;
+ stream.write(bytes) catch unreachable;
+ testing.expect(counting_stream.bytes_written == bytes.len);
+}
+
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..847feeae039fadeccd5083c9c3111aded04ed3d9
--- /dev/null
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -0,0 +1,66 @@
+const std = @import("../std.zig");
+const io = std.io;
+
+pub const FixedBufferInStream = struct {
+ bytes: []const u8,
+ pos: usize,
+
+ pub const SeekError = error{EndOfStream};
+ pub const GetSeekPosError = error{};
+
+ pub const InStream = io.InStream(*FixedBufferInStream, error{}, read);
+
+ pub fn inStream(self: *FixedBufferInStream) InStream {
+ return .{ .context = self };
+ }
+
+ pub const SeekableStream = io.SeekableStream(
+ *FixedBufferInStream,
+ SeekError,
+ GetSeekPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
+ pub fn seekableStream(self: *FixedBufferInStream) SeekableStream {
+ return .{ .context = self };
+ }
+
+ pub fn read(self: *FixedBufferInStream, dest: []u8) error{}!usize {
+ const size = std.math.min(dest.len, self.bytes.len - self.pos);
+ const end = self.pos + size;
+
+ std.mem.copy(u8, dest[0..size], self.bytes[self.pos..end]);
+ self.pos = end;
+
+ return size;
+ }
+
+ pub fn seekTo(self: *FixedBufferInStream, pos: u64) SeekError!void {
+ const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream;
+ if (usize_pos > self.bytes.len) return error.EndOfStream;
+ self.pos = usize_pos;
+ }
+
+ pub fn seekBy(self: *FixedBufferInStream, amt: i64) SeekError!void {
+ if (amt < 0) {
+ const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream;
+ if (abs_amt > self.pos) return error.EndOfStream;
+ self.pos -= abs_amt;
+ } else {
+ const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream;
+ if (self.pos + usize_amt > self.bytes.len) return error.EndOfStream;
+ self.pos += usize_amt;
+ }
+ }
+
+ pub fn getEndPos(self: *FixedBufferInStream) GetSeekPosError!u64 {
+ return self.bytes.len;
+ }
+
+ pub fn getPos(self: *FixedBufferInStream) GetSeekPosError!u64 {
+ return self.pos;
+ }
+};
diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig
index e2341827713266ae7ca4b296c113657e3539a7e7..d181f4df433d9a78fc638bf510b529ad478c91a6 100644
--- a/lib/std/io/in_stream.zig
+++ b/lib/std/io/in_stream.zig
@@ -1,44 +1,31 @@
const std = @import("../std.zig");
-const builtin = @import("builtin");
-const root = @import("root");
+const builtin = std.builtin;
const math = std.math;
const assert = std.debug.assert;
const mem = std.mem;
const Buffer = std.Buffer;
const testing = std.testing;
-pub const default_stack_size = 1 * 1024 * 1024;
-pub const stack_size: usize = if (@hasDecl(root, "stack_size_std_io_InStream"))
- root.stack_size_std_io_InStream
-else
- default_stack_size;
-
-pub fn InStream(comptime ReadError: type) type {
+pub fn InStream(
+ comptime Context: type,
+ comptime ReadError: type,
+ /// Returns the number of bytes read. It may be less than buffer.len.
+ /// If the number of bytes read is 0, it means end of stream.
+ /// End of stream is not an error condition.
+ comptime readFn: fn (context: Context, buffer: []u8) ReadError!usize,
+) type {
return struct {
- const Self = @This();
pub const Error = ReadError;
- pub const ReadFn = if (std.io.is_async)
- async fn (self: *Self, buffer: []u8) Error!usize
- else
- fn (self: *Self, buffer: []u8) Error!usize;
- /// Returns the number of bytes read. It may be less than buffer.len.
- /// If the number of bytes read is 0, it means end of stream.
- /// End of stream is not an error condition.
- readFn: ReadFn,
+ context: Context,
+
+ const Self = @This();
/// Returns the number of bytes read. It may be less than buffer.len.
/// If the number of bytes read is 0, it means end of stream.
/// End of stream is not an error condition.
- pub fn read(self: *Self, buffer: []u8) Error!usize {
- if (std.io.is_async) {
- // Let's not be writing 0xaa in safe modes for upwards of 4 MiB for every stream read.
- @setRuntimeSafety(false);
- var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
- return await @asyncCall(&stack_frame, {}, self.readFn, self, buffer);
- } else {
- return self.readFn(self, buffer);
- }
+ pub fn read(self: Self, buffer: []u8) Error!usize {
+ return readFn(self.context, buffer);
}
/// Deprecated: use `readAll`.
@@ -47,7 +34,7 @@ pub fn InStream(comptime ReadError: type) type {
/// Returns the number of bytes read. If the number read is smaller than buf.len, it
/// means the stream reached the end. Reaching the end of a stream is not an error
/// condition.
- pub fn readAll(self: *Self, buffer: []u8) Error!usize {
+ pub fn readAll(self: Self, buffer: []u8) Error!usize {
var index: usize = 0;
while (index != buffer.len) {
const amt = try self.read(buffer[index..]);
@@ -59,13 +46,13 @@ pub fn InStream(comptime ReadError: type) type {
/// Returns the number of bytes read. If the number read would be smaller than buf.len,
/// error.EndOfStream is returned instead.
- pub fn readNoEof(self: *Self, buf: []u8) !void {
+ pub fn readNoEof(self: Self, buf: []u8) !void {
const amt_read = try self.readAll(buf);
if (amt_read < buf.len) return error.EndOfStream;
}
/// Deprecated: use `readAllArrayList`.
- pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void {
+ pub fn readAllBuffer(self: Self, buffer: *Buffer, max_size: usize) !void {
buffer.list.shrink(0);
try self.readAllArrayList(&buffer.list, max_size);
errdefer buffer.shrink(0);
@@ -75,7 +62,7 @@ pub fn InStream(comptime ReadError: type) type {
/// Appends to the `std.ArrayList` contents by reading from the stream until end of stream is found.
/// If the number of bytes appended would exceed `max_append_size`, `error.StreamTooLong` is returned
/// and the `std.ArrayList` has exactly `max_append_size` bytes appended.
- pub fn readAllArrayList(self: *Self, array_list: *std.ArrayList(u8), max_append_size: usize) !void {
+ pub fn readAllArrayList(self: Self, array_list: *std.ArrayList(u8), max_append_size: usize) !void {
try array_list.ensureCapacity(math.min(max_append_size, 4096));
const original_len = array_list.len;
var start_index: usize = original_len;
@@ -104,7 +91,7 @@ pub fn InStream(comptime ReadError: type) type {
/// memory would be greater than `max_size`, returns `error.StreamTooLong`.
/// Caller owns returned memory.
/// If this function returns an error, the contents from the stream read so far are lost.
- pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 {
+ pub fn readAllAlloc(self: Self, allocator: *mem.Allocator, max_size: usize) ![]u8 {
var array_list = std.ArrayList(u8).init(allocator);
defer array_list.deinit();
try self.readAllArrayList(&array_list, max_size);
@@ -116,7 +103,7 @@ pub fn InStream(comptime ReadError: type) type {
/// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the
/// `std.ArrayList` is populated with `max_size` bytes from the stream.
pub fn readUntilDelimiterArrayList(
- self: *Self,
+ self: Self,
array_list: *std.ArrayList(u8),
delimiter: u8,
max_size: usize,
@@ -142,7 +129,7 @@ pub fn InStream(comptime ReadError: type) type {
/// Caller owns returned memory.
/// If this function returns an error, the contents from the stream read so far are lost.
pub fn readUntilDelimiterAlloc(
- self: *Self,
+ self: Self,
allocator: *mem.Allocator,
delimiter: u8,
max_size: usize,
@@ -159,7 +146,7 @@ pub fn InStream(comptime ReadError: type) type {
/// function is called again after that, returns null.
/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The
/// delimiter byte is not included in the returned slice.
- pub fn readUntilDelimiterOrEof(self: *Self, buf: []u8, delimiter: u8) !?[]u8 {
+ pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) !?[]u8 {
var index: usize = 0;
while (true) {
const byte = self.readByte() catch |err| switch (err) {
@@ -184,7 +171,7 @@ pub fn InStream(comptime ReadError: type) type {
/// Reads from the stream until specified byte is found, discarding all data,
/// including the delimiter.
/// If end-of-stream is found, this function succeeds.
- pub fn skipUntilDelimiterOrEof(self: *Self, delimiter: u8) !void {
+ pub fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) !void {
while (true) {
const byte = self.readByte() catch |err| switch (err) {
error.EndOfStream => return,
@@ -195,7 +182,7 @@ pub fn InStream(comptime ReadError: type) type {
}
/// Reads 1 byte from the stream or returns `error.EndOfStream`.
- pub fn readByte(self: *Self) !u8 {
+ pub fn readByte(self: Self) !u8 {
var result: [1]u8 = undefined;
const amt_read = try self.read(result[0..]);
if (amt_read < 1) return error.EndOfStream;
@@ -203,43 +190,43 @@ pub fn InStream(comptime ReadError: type) type {
}
/// Same as `readByte` except the returned byte is signed.
- pub fn readByteSigned(self: *Self) !i8 {
+ pub fn readByteSigned(self: Self) !i8 {
return @bitCast(i8, try self.readByte());
}
/// Reads a native-endian integer
- pub fn readIntNative(self: *Self, comptime T: type) !T {
+ pub fn readIntNative(self: Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntNative(T, &bytes);
}
/// Reads a foreign-endian integer
- pub fn readIntForeign(self: *Self, comptime T: type) !T {
+ pub fn readIntForeign(self: Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntForeign(T, &bytes);
}
- pub fn readIntLittle(self: *Self, comptime T: type) !T {
+ pub fn readIntLittle(self: Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntLittle(T, &bytes);
}
- pub fn readIntBig(self: *Self, comptime T: type) !T {
+ pub fn readIntBig(self: Self, comptime T: type) !T {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readIntBig(T, &bytes);
}
- pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
+ pub fn readInt(self: Self, comptime T: type, endian: builtin.Endian) !T {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
try self.readNoEof(bytes[0..]);
return mem.readInt(T, &bytes, endian);
}
- pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
+ pub fn readVarInt(self: Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
assert(size <= @sizeOf(ReturnType));
var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
const bytes = bytes_buf[0..size];
@@ -247,14 +234,14 @@ pub fn InStream(comptime ReadError: type) type {
return mem.readVarInt(ReturnType, bytes, endian);
}
- pub fn skipBytes(self: *Self, num_bytes: u64) !void {
+ pub fn skipBytes(self: Self, num_bytes: u64) !void {
var i: u64 = 0;
while (i < num_bytes) : (i += 1) {
_ = try self.readByte();
}
}
- pub fn readStruct(self: *Self, comptime T: type) !T {
+ pub fn readStruct(self: Self, comptime T: type) !T {
// Only extern and packed structs have defined in-memory layout.
comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
var res: [1]T = undefined;
@@ -265,7 +252,7 @@ pub fn InStream(comptime ReadError: type) type {
/// Reads an integer with the same size as the given enum's tag type. If the integer matches
/// an enum tag, casts the integer to the enum tag and returns it. Otherwise, returns an error.
/// TODO optimization taking advantage of most fields being in order
- pub fn readEnum(self: *Self, comptime Enum: type, endian: builtin.Endian) !Enum {
+ pub fn readEnum(self: Self, comptime Enum: type, endian: builtin.Endian) !Enum {
const E = error{
/// An integer was read, but it did not match any of the tags in the supplied enum.
InvalidValue,
diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig
index cb75b27bf11d1a20b0cd28c5328330cd0dc66a69..03901f6672be05e4a5556b52d39e5e6cec5ea63a 100644
--- a/lib/std/io/out_stream.zig
+++ b/lib/std/io/out_stream.zig
@@ -1,94 +1,85 @@
const std = @import("../std.zig");
-const builtin = @import("builtin");
-const root = @import("root");
+const builtin = std.builtin;
const mem = std.mem;
-pub const default_stack_size = 1 * 1024 * 1024;
-pub const stack_size: usize = if (@hasDecl(root, "stack_size_std_io_OutStream"))
- root.stack_size_std_io_OutStream
-else
- default_stack_size;
-
-pub fn OutStream(comptime WriteError: type) type {
+pub fn OutStream(
+ comptime Context: type,
+ comptime WriteError: type,
+ comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
+) type {
return struct {
+ context: Context,
+
const Self = @This();
pub const Error = WriteError;
- pub const WriteFn = if (std.io.is_async)
- async fn (self: *Self, bytes: []const u8) Error!usize
- else
- fn (self: *Self, bytes: []const u8) Error!usize;
- writeFn: WriteFn,
-
- pub fn writeOnce(self: *Self, bytes: []const u8) Error!usize {
- if (std.io.is_async) {
- // Let's not be writing 0xaa in safe modes for upwards of 4 MiB for every stream write.
- @setRuntimeSafety(false);
- var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
- return await @asyncCall(&stack_frame, {}, self.writeFn, self, bytes);
- } else {
- return self.writeFn(self, bytes);
- }
+ pub fn write(self: Self, bytes: []const u8) Error!usize {
+ return writeFn(self.context, bytes);
}
- pub fn write(self: *Self, bytes: []const u8) Error!void {
+ pub fn writeAll(self: Self, bytes: []const u8) Error!void {
var index: usize = 0;
while (index != bytes.len) {
- index += try self.writeOnce(bytes[index..]);
+ index += try self.write(bytes[index..]);
}
}
- pub fn print(self: *Self, comptime format: []const u8, args: var) Error!void {
- return std.fmt.format(self, Error, write, format, args);
+ pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
+ return std.fmt.format(self, Error, writeAll, format, args);
}
- pub fn writeByte(self: *Self, byte: u8) Error!void {
+ pub fn writeByte(self: Self, byte: u8) Error!void {
const array = [1]u8{byte};
- return self.write(&array);
+ return self.writeAll(&array);
}
- pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
+ pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
var bytes: [256]u8 = undefined;
mem.set(u8, bytes[0..], byte);
var remaining: usize = n;
while (remaining > 0) {
const to_write = std.math.min(remaining, bytes.len);
- try self.write(bytes[0..to_write]);
+ try self.writeAll(bytes[0..to_write]);
remaining -= to_write;
}
}
/// Write a native-endian integer.
- pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
+ /// TODO audit non-power-of-two int sizes
+ pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntNative(T, &bytes, value);
- return self.write(&bytes);
+ return self.writeAll(&bytes);
}
/// Write a foreign-endian integer.
- pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
+ /// TODO audit non-power-of-two int sizes
+ pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntForeign(T, &bytes, value);
- return self.write(&bytes);
+ return self.writeAll(&bytes);
}
- pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
+ /// TODO audit non-power-of-two int sizes
+ pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntLittle(T, &bytes, value);
- return self.write(&bytes);
+ return self.writeAll(&bytes);
}
- pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
+ /// TODO audit non-power-of-two int sizes
+ pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeIntBig(T, &bytes, value);
- return self.write(&bytes);
+ return self.writeAll(&bytes);
}
- pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
+ /// TODO audit non-power-of-two int sizes
+ pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
mem.writeInt(T, &bytes, value, endian);
- return self.write(&bytes);
+ return self.writeAll(&bytes);
}
};
}
diff --git a/lib/std/io/seekable_stream.zig b/lib/std/io/seekable_stream.zig
index 052abbc85640d15d61b7984b6f4a6a0a97fb6004..ed410b7aa748070199630cacf2475f9b104db172 100644
--- a/lib/std/io/seekable_stream.zig
+++ b/lib/std/io/seekable_stream.zig
@@ -1,103 +1,36 @@
const std = @import("../std.zig");
const InStream = std.io.InStream;
-pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType: type) type {
+pub fn SeekableStream(
+ comptime Context: type,
+ comptime SeekErrorType: type,
+ comptime GetSeekPosErrorType: type,
+ comptime seekToFn: fn (context: Context, pos: u64) SeekErrorType!void,
+ comptime seekByFn: fn (context: Context, pos: i64) SeekErrorType!void,
+ comptime getPosFn: fn (context: Context) GetSeekPosErrorType!u64,
+ comptime getEndPosFn: fn (context: Context) GetSeekPosErrorType!u64,
+) type {
return struct {
+ context: Context,
+
const Self = @This();
pub const SeekError = SeekErrorType;
pub const GetSeekPosError = GetSeekPosErrorType;
- seekToFn: fn (self: *Self, pos: u64) SeekError!void,
- seekByFn: fn (self: *Self, pos: i64) SeekError!void,
-
- getPosFn: fn (self: *Self) GetSeekPosError!u64,
- getEndPosFn: fn (self: *Self) GetSeekPosError!u64,
-
- pub fn seekTo(self: *Self, pos: u64) SeekError!void {
- return self.seekToFn(self, pos);
+ pub fn seekTo(self: Self, pos: u64) SeekError!void {
+ return seekToFn(self.context, pos);
}
- pub fn seekBy(self: *Self, amt: i64) SeekError!void {
- return self.seekByFn(self, amt);
+ pub fn seekBy(self: Self, amt: i64) SeekError!void {
+ return seekByFn(self.context, amt);
}
- pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
- return self.getEndPosFn(self);
+ pub fn getEndPos(self: Self) GetSeekPosError!u64 {
+ return getEndPosFn(self.context);
}
- pub fn getPos(self: *Self) GetSeekPosError!u64 {
- return self.getPosFn(self);
+ pub fn getPos(self: Self) GetSeekPosError!u64 {
+ return getPosFn(self.context);
}
};
}
-
-pub const SliceSeekableInStream = struct {
- const Self = @This();
- pub const Error = error{};
- pub const SeekError = error{EndOfStream};
- pub const GetSeekPosError = error{};
- pub const Stream = InStream(Error);
- pub const SeekableInStream = SeekableStream(SeekError, GetSeekPosError);
-
- stream: Stream,
- seekable_stream: SeekableInStream,
-
- pos: usize,
- slice: []const u8,
-
- pub fn init(slice: []const u8) Self {
- return Self{
- .slice = slice,
- .pos = 0,
- .stream = Stream{ .readFn = readFn },
- .seekable_stream = SeekableInStream{
- .seekToFn = seekToFn,
- .seekByFn = seekByFn,
- .getEndPosFn = getEndPosFn,
- .getPosFn = getPosFn,
- },
- };
- }
-
- fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
- const self = @fieldParentPtr(Self, "stream", in_stream);
- const size = std.math.min(dest.len, self.slice.len - self.pos);
- const end = self.pos + size;
-
- std.mem.copy(u8, dest[0..size], self.slice[self.pos..end]);
- self.pos = end;
-
- return size;
- }
-
- fn seekToFn(in_stream: *SeekableInStream, pos: u64) SeekError!void {
- const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
- const usize_pos = @intCast(usize, pos);
- if (usize_pos > self.slice.len) return error.EndOfStream;
- self.pos = usize_pos;
- }
-
- fn seekByFn(in_stream: *SeekableInStream, amt: i64) SeekError!void {
- const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
-
- if (amt < 0) {
- const abs_amt = @intCast(usize, -amt);
- if (abs_amt > self.pos) return error.EndOfStream;
- self.pos -= abs_amt;
- } else {
- const usize_amt = @intCast(usize, amt);
- if (self.pos + usize_amt > self.slice.len) return error.EndOfStream;
- self.pos += usize_amt;
- }
- }
-
- fn getEndPosFn(in_stream: *SeekableInStream) GetSeekPosError!u64 {
- const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
- return @intCast(u64, self.slice.len);
- }
-
- fn getPosFn(in_stream: *SeekableInStream) GetSeekPosError!u64 {
- const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
- return @intCast(u64, self.pos);
- }
-};
diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig
index 213b6768d48e4c7f735cfff98863c16f8696a069..6d88c8b6da6691335f5abe0943d9c5df2f487719 100644
--- a/lib/std/json/write_stream.zig
+++ b/lib/std/json/write_stream.zig
@@ -30,11 +30,11 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
/// The string used as spacing.
space: []const u8 = " ",
- stream: *OutStream,
+ stream: OutStream,
state_index: usize,
state: [max_depth]State,
- pub fn init(stream: *OutStream) Self {
+ pub fn init(stream: OutStream) Self {
var self = Self{
.stream = stream,
.state_index = 1,
@@ -90,8 +90,8 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
self.pushState(.Value);
try self.indent();
try self.writeEscapedString(name);
- try self.stream.write(":");
- try self.stream.write(self.space);
+ try self.stream.writeAll(":");
+ try self.stream.writeAll(self.space);
},
}
}
@@ -134,16 +134,16 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
pub fn emitNull(self: *Self) !void {
assert(self.state[self.state_index] == State.Value);
- try self.stream.write("null");
+ try self.stream.writeAll("null");
self.popState();
}
pub fn emitBool(self: *Self, value: bool) !void {
assert(self.state[self.state_index] == State.Value);
if (value) {
- try self.stream.write("true");
+ try self.stream.writeAll("true");
} else {
- try self.stream.write("false");
+ try self.stream.writeAll("false");
}
self.popState();
}
@@ -188,13 +188,13 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
try self.stream.writeByte('"');
for (string) |s| {
switch (s) {
- '"' => try self.stream.write("\\\""),
- '\t' => try self.stream.write("\\t"),
- '\r' => try self.stream.write("\\r"),
- '\n' => try self.stream.write("\\n"),
- 8 => try self.stream.write("\\b"),
- 12 => try self.stream.write("\\f"),
- '\\' => try self.stream.write("\\\\"),
+ '"' => try self.stream.writeAll("\\\""),
+ '\t' => try self.stream.writeAll("\\t"),
+ '\r' => try self.stream.writeAll("\\r"),
+ '\n' => try self.stream.writeAll("\\n"),
+ 8 => try self.stream.writeAll("\\b"),
+ 12 => try self.stream.writeAll("\\f"),
+ '\\' => try self.stream.writeAll("\\\\"),
else => try self.stream.writeByte(s),
}
}
@@ -231,10 +231,10 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
fn indent(self: *Self) !void {
assert(self.state_index >= 1);
- try self.stream.write(self.newline);
+ try self.stream.writeAll(self.newline);
var i: usize = 0;
while (i < self.state_index - 1) : (i += 1) {
- try self.stream.write(self.one_indent);
+ try self.stream.writeAll(self.one_indent);
}
}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 460f0bee022b97c384eec04f5cadf5271e068553..76a5dc2be55cf227ebe1240d9eb6448009f01389 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -176,7 +176,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
.io_mode = .blocking,
.async_block_allowed = std.fs.File.async_block_allowed_yes,
};
- const stream = &file.inStream().stream;
+ const stream = file.inStream();
stream.readNoEof(buf) catch return error.Unexpected;
}
diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig
index db60e60494ab06684475bf8485319214f2f32f2f..7c48cf7b7cdb9d8dc6e211df5eccead128e839db 100644
--- a/lib/std/pdb.zig
+++ b/lib/std/pdb.zig
@@ -632,11 +632,7 @@ const MsfStream = struct {
blocks: []u32 = undefined,
block_size: u32 = undefined,
- /// Implementation of InStream trait for Pdb.MsfStream
- stream: Stream = undefined,
-
pub const Error = @TypeOf(read).ReturnType.ErrorSet;
- pub const Stream = io.InStream(Error);
fn init(block_size: u32, file: File, blocks: []u32) MsfStream {
const stream = MsfStream{
@@ -644,7 +640,6 @@ const MsfStream = struct {
.pos = 0,
.blocks = blocks,
.block_size = block_size,
- .stream = Stream{ .readFn = readFn },
};
return stream;
@@ -715,8 +710,7 @@ const MsfStream = struct {
return block * self.block_size + offset;
}
- fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {
- const self = @fieldParentPtr(MsfStream, "stream", in_stream);
- return self.read(buffer);
+ fn inStream(self: *MsfStream) std.io.InStream(*MsfStream, Error, read) {
+ return .{ .context = self };
}
};
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 95a772376d75760ffbdbd5e9a606ef917fa1714b..8ae219a998ba18d4ce0142cbd1c2b59617456457 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -375,7 +375,7 @@ pub const Error = union(enum) {
token: TokenIndex,
pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
- return stream.write(msg);
+ return stream.writeAll(msg);
}
};
}
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index ce9049e35bebabc1552b815f7c216bb16f482f1e..9600de21df40f88e7b7933d7cba2fafd83ef94a6 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -12,64 +12,58 @@ pub const Error = error{
};
/// Returns whether anything changed
-pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Child.Error || Error)!bool {
- comptime assert(@typeInfo(@TypeOf(stream)) == .Pointer);
-
- var anything_changed: bool = false;
-
+pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Error || Error)!bool {
// make a passthrough stream that checks whether something changed
const MyStream = struct {
const MyStream = @This();
- const StreamError = @TypeOf(stream).Child.Error;
- const Stream = std.io.OutStream(StreamError);
+ const StreamError = @TypeOf(stream).Error;
- anything_changed_ptr: *bool,
child_stream: @TypeOf(stream),
- stream: Stream,
+ anything_changed: bool,
source_index: usize,
source: []const u8,
- fn write(iface_stream: *Stream, bytes: []const u8) StreamError!usize {
- const self = @fieldParentPtr(MyStream, "stream", iface_stream);
-
- if (!self.anything_changed_ptr.*) {
+ fn write(self: *MyStream, bytes: []const u8) StreamError!usize {
+ if (!self.anything_changed) {
const end = self.source_index + bytes.len;
if (end > self.source.len) {
- self.anything_changed_ptr.* = true;
+ self.anything_changed = true;
} else {
const src_slice = self.source[self.source_index..end];
self.source_index += bytes.len;
if (!mem.eql(u8, bytes, src_slice)) {
- self.anything_changed_ptr.* = true;
+ self.anything_changed = true;
}
}
}
- return self.child_stream.writeOnce(bytes);
+ return self.child_stream.write(bytes);
}
};
var my_stream = MyStream{
- .stream = MyStream.Stream{ .writeFn = MyStream.write },
.child_stream = stream,
- .anything_changed_ptr = &anything_changed,
+ .anything_changed = false,
.source_index = 0,
.source = tree.source,
};
+ const my_stream_stream: std.io.OutStream(*MyStream, MyStream.StreamError, MyStream.write) = .{
+ .context = &my_stream,
+ };
- try renderRoot(allocator, &my_stream.stream, tree);
+ try renderRoot(allocator, my_stream_stream, tree);
- if (!anything_changed and my_stream.source_index != my_stream.source.len) {
- anything_changed = true;
+ if (my_stream.source_index != my_stream.source.len) {
+ my_stream.anything_changed = true;
}
- return anything_changed;
+ return my_stream.anything_changed;
}
fn renderRoot(
allocator: *mem.Allocator,
stream: var,
tree: *ast.Tree,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
var tok_it = tree.tokens.iterator(0);
// render all the line comments at the beginning of the file
@@ -189,7 +183,7 @@ fn renderRoot(
}
}
-fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Child.Error!void {
+fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @TypeOf(stream).Error!void {
const first_token = node.firstToken();
var prev_token = first_token;
if (prev_token == 0) return;
@@ -204,11 +198,11 @@ fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *as
}
}
-fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node) (@TypeOf(stream).Child.Error || Error)!void {
+fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node) (@TypeOf(stream).Error || Error)!void {
try renderContainerDecl(allocator, stream, tree, indent, start_col, decl, .Newline);
}
-fn renderContainerDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node, space: Space) (@TypeOf(stream).Child.Error || Error)!void {
+fn renderContainerDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node, space: Space) (@TypeOf(stream).Error || Error)!void {
switch (decl.id) {
.FnProto => {
const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
@@ -343,7 +337,7 @@ fn renderExpression(
start_col: *usize,
base: *ast.Node,
space: Space,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
switch (base.id) {
.Identifier => {
const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
@@ -449,9 +443,9 @@ fn renderExpression(
switch (op_tok_id) {
.Asterisk, .AsteriskAsterisk => try stream.writeByte('*'),
.LBracket => if (tree.tokens.at(prefix_op_node.op_token + 2).id == .Identifier)
- try stream.write("[*c")
+ try stream.writeAll("[*c")
else
- try stream.write("[*"),
+ try stream.writeAll("[*"),
else => unreachable,
}
if (ptr_info.sentinel) |sentinel| {
@@ -757,7 +751,7 @@ fn renderExpression(
while (it.next()) |field_init| {
var find_stream = FindByteOutStream.init('\n');
var dummy_col: usize = 0;
- try renderExpression(allocator, &find_stream.stream, tree, 0, &dummy_col, field_init.*, Space.None);
+ try renderExpression(allocator, find_stream.outStream(), tree, 0, &dummy_col, field_init.*, Space.None);
if (find_stream.byte_found) break :blk false;
}
break :blk true;
@@ -909,8 +903,7 @@ fn renderExpression(
var column_widths = widths[widths.len - row_size ..];
// Null stream for counting the printed length of each expression
- var null_stream = std.io.NullOutStream.init();
- var counting_stream = std.io.CountingOutStream(std.io.NullOutStream.Error).init(&null_stream.stream);
+ var counting_stream = std.io.CountingOutStream(@TypeOf(std.io.null_out_stream)).init(std.io.null_out_stream);
var it = exprs.iterator(0);
var i: usize = 0;
@@ -918,7 +911,7 @@ fn renderExpression(
while (it.next()) |expr| : (i += 1) {
counting_stream.bytes_written = 0;
var dummy_col: usize = 0;
- try renderExpression(allocator, &counting_stream.stream, tree, indent, &dummy_col, expr.*, Space.None);
+ try renderExpression(allocator, counting_stream.outStream(), tree, indent, &dummy_col, expr.*, Space.None);
const width = @intCast(usize, counting_stream.bytes_written);
const col = i % row_size;
column_widths[col] = std.math.max(column_widths[col], width);
@@ -1336,7 +1329,7 @@ fn renderExpression(
// TODO: Remove condition after deprecating 'typeOf'. See https://github.com/ziglang/zig/issues/1348
if (mem.eql(u8, tree.tokenSlicePtr(tree.tokens.at(builtin_call.builtin_token)), "@typeOf")) {
- try stream.write("@TypeOf");
+ try stream.writeAll("@TypeOf");
} else {
try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name
}
@@ -1505,9 +1498,9 @@ fn renderExpression(
try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None);
try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // )
} else if (cc_rewrite_str) |str| {
- try stream.write("callconv(");
- try stream.write(mem.toSliceConst(u8, str));
- try stream.write(") ");
+ try stream.writeAll("callconv(");
+ try stream.writeAll(mem.toSliceConst(u8, str));
+ try stream.writeAll(") ");
}
switch (fn_proto.return_type) {
@@ -1997,11 +1990,11 @@ fn renderExpression(
.AsmInput => {
const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
- try stream.write("[");
+ try stream.writeAll("[");
try renderExpression(allocator, stream, tree, indent, start_col, asm_input.symbolic_name, Space.None);
- try stream.write("] ");
+ try stream.writeAll("] ");
try renderExpression(allocator, stream, tree, indent, start_col, asm_input.constraint, Space.None);
- try stream.write(" (");
+ try stream.writeAll(" (");
try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None);
return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // )
},
@@ -2009,18 +2002,18 @@ fn renderExpression(
.AsmOutput => {
const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
- try stream.write("[");
+ try stream.writeAll("[");
try renderExpression(allocator, stream, tree, indent, start_col, asm_output.symbolic_name, Space.None);
- try stream.write("] ");
+ try stream.writeAll("] ");
try renderExpression(allocator, stream, tree, indent, start_col, asm_output.constraint, Space.None);
- try stream.write(" (");
+ try stream.writeAll(" (");
switch (asm_output.kind) {
ast.Node.AsmOutput.Kind.Variable => |variable_name| {
try renderExpression(allocator, stream, tree, indent, start_col, &variable_name.base, Space.None);
},
ast.Node.AsmOutput.Kind.Return => |return_type| {
- try stream.write("-> ");
+ try stream.writeAll("-> ");
try renderExpression(allocator, stream, tree, indent, start_col, return_type, Space.None);
},
}
@@ -2052,7 +2045,7 @@ fn renderVarDecl(
indent: usize,
start_col: *usize,
var_decl: *ast.Node.VarDecl,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
if (var_decl.visib_token) |visib_token| {
try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
}
@@ -2125,7 +2118,7 @@ fn renderParamDecl(
start_col: *usize,
base: *ast.Node,
space: Space,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
try renderDocComments(tree, stream, param_decl, indent, start_col);
@@ -2154,7 +2147,7 @@ fn renderStatement(
indent: usize,
start_col: *usize,
base: *ast.Node,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
switch (base.id) {
.VarDecl => {
const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
@@ -2193,7 +2186,7 @@ fn renderTokenOffset(
start_col: *usize,
space: Space,
token_skip_bytes: usize,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
if (space == Space.BlockStart) {
if (start_col.* < indent + indent_delta)
return renderToken(tree, stream, token_index, indent, start_col, Space.Space);
@@ -2204,7 +2197,7 @@ fn renderTokenOffset(
}
var token = tree.tokens.at(token_index);
- try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token)[token_skip_bytes..], " "));
+ try stream.writeAll(mem.trimRight(u8, tree.tokenSlicePtr(token)[token_skip_bytes..], " "));
if (space == Space.NoComment)
return;
@@ -2214,15 +2207,15 @@ fn renderTokenOffset(
if (space == Space.Comma) switch (next_token.id) {
.Comma => return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline),
.LineComment => {
- try stream.write(", ");
+ try stream.writeAll(", ");
return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline);
},
else => {
if (token_index + 2 < tree.tokens.len and tree.tokens.at(token_index + 2).id == .MultilineStringLiteralLine) {
- try stream.write(",");
+ try stream.writeAll(",");
return;
} else {
- try stream.write(",\n");
+ try stream.writeAll(",\n");
start_col.* = 0;
return;
}
@@ -2246,7 +2239,7 @@ fn renderTokenOffset(
if (next_token.id == .MultilineStringLiteralLine) {
return;
} else {
- try stream.write("\n");
+ try stream.writeAll("\n");
start_col.* = 0;
return;
}
@@ -2309,7 +2302,7 @@ fn renderTokenOffset(
if (next_token.id == .MultilineStringLiteralLine) {
return;
} else {
- try stream.write("\n");
+ try stream.writeAll("\n");
start_col.* = 0;
return;
}
@@ -2327,7 +2320,7 @@ fn renderTokenOffset(
const newline_count = if (loc.line == 1) @as(u8, 1) else @as(u8, 2);
try stream.writeByteNTimes('\n', newline_count);
try stream.writeByteNTimes(' ', indent);
- try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
+ try stream.writeAll(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
offset += 1;
token = next_token;
@@ -2338,7 +2331,7 @@ fn renderTokenOffset(
if (next_token.id == .MultilineStringLiteralLine) {
return;
} else {
- try stream.write("\n");
+ try stream.writeAll("\n");
start_col.* = 0;
return;
}
@@ -2381,7 +2374,7 @@ fn renderToken(
indent: usize,
start_col: *usize,
space: Space,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
return renderTokenOffset(tree, stream, token_index, indent, start_col, space, 0);
}
@@ -2391,7 +2384,7 @@ fn renderDocComments(
node: var,
indent: usize,
start_col: *usize,
-) (@TypeOf(stream).Child.Error || Error)!void {
+) (@TypeOf(stream).Error || Error)!void {
const comment = node.doc_comments orelse return;
var it = comment.lines.iterator(0);
const first_token = node.firstToken();
@@ -2401,7 +2394,7 @@ fn renderDocComments(
try stream.writeByteNTimes(' ', indent);
} else {
try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.NoComment);
- try stream.write("\n");
+ try stream.writeAll("\n");
try stream.writeByteNTimes(' ', indent);
}
}
@@ -2427,27 +2420,23 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
};
}
-// An OutStream that returns whether the given character has been written to it.
-// The contents are not written to anything.
+/// A `std.io.OutStream` that returns whether the given character has been written to it.
+/// The contents are not written to anything.
const FindByteOutStream = struct {
- const Self = FindByteOutStream;
- pub const Error = error{};
- pub const Stream = std.io.OutStream(Error);
-
- stream: Stream,
byte_found: bool,
byte: u8,
- pub fn init(byte: u8) Self {
- return Self{
- .stream = Stream{ .writeFn = writeFn },
+ pub const Error = error{};
+ pub const OutStream = std.io.OutStream(*FindByteOutStream, Error, write);
+
+ pub fn init(byte: u8) FindByteOutStream {
+ return FindByteOutStream{
.byte = byte,
.byte_found = false,
};
}
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- const self = @fieldParentPtr(Self, "stream", out_stream);
+ pub fn write(self: *FindByteOutStream, bytes: []const u8) Error!usize {
if (self.byte_found) return bytes.len;
self.byte_found = blk: {
for (bytes) |b|
@@ -2456,11 +2445,15 @@ const FindByteOutStream = struct {
};
return bytes.len;
}
+
+ pub fn outStream(self: *FindByteOutStream) OutStream {
+ return .{ .context = self };
+ }
};
-fn copyFixingWhitespace(stream: var, slice: []const u8) @TypeOf(stream).Child.Error!void {
+fn copyFixingWhitespace(stream: var, slice: []const u8) @TypeOf(stream).Error!void {
for (slice) |byte| switch (byte) {
- '\t' => try stream.write(" "),
+ '\t' => try stream.writeAll(" "),
'\r' => {},
else => try stream.writeByte(byte),
};
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 41def3812670d3d1361dc906acf6b0604e06a72f..78aafeff289e79fc3b70c5eaabcabab55c3ca32e 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -38,7 +38,7 @@ pub const LibCInstallation = struct {
pub fn parse(
allocator: *Allocator,
libc_file: []const u8,
- stderr: *std.io.OutStream(fs.File.WriteError),
+ stderr: var,
) !LibCInstallation {
var self: LibCInstallation = .{};
@@ -123,7 +123,7 @@ pub const LibCInstallation = struct {
return self;
}
- pub fn render(self: LibCInstallation, out: *std.io.OutStream(fs.File.WriteError)) !void {
+ pub fn render(self: LibCInstallation, out: var) !void {
@setEvalBranchQuota(4000);
const include_dir = self.include_dir orelse "";
const sys_include_dir = self.sys_include_dir orelse "";
diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig
index bb3841ba24988315301f01a1d02c050a1b480fe2..473e3dfa51f3c8059d0b09669d1a56008cdb4fb6 100644
--- a/src-self-hosted/print_targets.zig
+++ b/src-self-hosted/print_targets.zig
@@ -52,7 +52,7 @@ const available_libcs = [_][]const u8{
"sparc-linux-gnu",
"sparcv9-linux-gnu",
"wasm32-freestanding-musl",
- "x86_64-linux-gnu (native)",
+ "x86_64-linux-gnu",
"x86_64-linux-gnux32",
"x86_64-linux-musl",
"x86_64-windows-gnu",
@@ -61,7 +61,8 @@ const available_libcs = [_][]const u8{
pub fn cmdTargets(
allocator: *Allocator,
args: []const []const u8,
- stdout: *io.OutStream(fs.File.WriteError),
+ /// Output stream
+ stdout: var,
native_target: Target,
) !void {
const available_glibcs = blk: {
@@ -92,9 +93,9 @@ pub fn cmdTargets(
};
defer allocator.free(available_glibcs);
- const BOS = io.BufferedOutStream(fs.File.WriteError);
- var bos = BOS.init(stdout);
- var jws = std.json.WriteStream(BOS.Stream, 6).init(&bos.stream);
+ var bos = io.bufferedOutStream(4096, stdout);
+ const bos_stream = bos.outStream();
+ var jws = std.json.WriteStream(@TypeOf(bos_stream), 6).init(bos_stream);
try jws.beginObject();
@@ -219,6 +220,6 @@ pub fn cmdTargets(
try jws.endObject();
- try bos.stream.writeByte('\n');
+ try bos_stream.writeByte('\n');
return bos.flush();
}
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
index ee6789ab86fa91460bb899ba6e6bc065f1c8c9aa..8f2656de44385e7006553e2ef4400a03c8262fdf 100644
--- a/src-self-hosted/stage2.zig
+++ b/src-self-hosted/stage2.zig
@@ -18,8 +18,8 @@ const assert = std.debug.assert;
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
var stderr_file: fs.File = undefined;
-var stderr: *io.OutStream(fs.File.WriteError) = undefined;
-var stdout: *io.OutStream(fs.File.WriteError) = undefined;
+var stderr: fs.File.OutStream = undefined;
+var stdout: fs.File.OutStream = undefined;
comptime {
_ = @import("dep_tokenizer.zig");
@@ -146,7 +146,7 @@ export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, error
}
export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
- const c_out_stream = &std.io.COutStream.init(output_file).stream;
+ const c_out_stream = std.io.cOutStream(output_file);
_ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
error.SystemResources => return .SystemResources,
@@ -186,9 +186,9 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
}
- stdout = &std.io.getStdOut().outStream().stream;
+ stdout = std.io.getStdOut().outStream();
stderr_file = std.io.getStdErr();
- stderr = &stderr_file.outStream().stream;
+ stderr = stderr_file.outStream();
const args = args_list.toSliceConst()[2..];
@@ -203,11 +203,11 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
const arg = args[i];
if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "--help")) {
- try stdout.write(self_hosted_main.usage_fmt);
+ try stdout.writeAll(self_hosted_main.usage_fmt);
process.exit(0);
} else if (mem.eql(u8, arg, "--color")) {
if (i + 1 >= args.len) {
- try stderr.write("expected [auto|on|off] after --color\n");
+ try stderr.writeAll("expected [auto|on|off] after --color\n");
process.exit(1);
}
i += 1;
@@ -238,14 +238,14 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
if (stdin_flag) {
if (input_files.len != 0) {
- try stderr.write("cannot use --stdin with positional arguments\n");
+ try stderr.writeAll("cannot use --stdin with positional arguments\n");
process.exit(1);
}
const stdin_file = io.getStdIn();
var stdin = stdin_file.inStream();
- const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
+ const source_code = try stdin.readAllAlloc(allocator, self_hosted_main.max_src_size);
defer allocator.free(source_code);
const tree = std.zig.parse(allocator, source_code) catch |err| {
@@ -272,7 +272,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
}
if (input_files.len == 0) {
- try stderr.write("expected at least one source file argument\n");
+ try stderr.writeAll("expected at least one source file argument\n");
process.exit(1);
}
@@ -409,11 +409,11 @@ fn printErrMsgToFile(
const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
var text_buf = try std.Buffer.initSize(allocator, 0);
- var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
+ const out_stream = &text_buf.outStream();
try parse_error.render(&tree.tokens, out_stream);
const text = text_buf.toOwnedSlice();
- const stream = &file.outStream().stream;
+ const stream = &file.outStream();
try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text });
if (!color_on) return;
@@ -641,7 +641,7 @@ fn cmdTargets(zig_triple: [*:0]const u8) !void {
return @import("print_targets.zig").cmdTargets(
std.heap.c_allocator,
&[0][]u8{},
- &std.io.getStdOut().outStream().stream,
+ std.io.getStdOut().outStream(),
target,
);
}
@@ -808,7 +808,7 @@ const Stage2LibCInstallation = extern struct {
// ABI warning
export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error {
stderr_file = std.io.getStdErr();
- stderr = &stderr_file.outStream().stream;
+ stderr = stderr_file.outStream();
const libc_file = mem.toSliceConst(u8, libc_file_z);
var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) {
error.ParseError => return .SemanticAnalyzeFail,
@@ -870,7 +870,7 @@ export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
// ABI warning
export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error {
var libc = stage1_libc.toStage2();
- const c_out_stream = &std.io.COutStream.init(output_file).stream;
+ const c_out_stream = std.io.cOutStream(output_file);
libc.render(c_out_stream) catch |err| switch (err) {
error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
error.SystemResources => return .SystemResources,
--
2.54.0
From 300fceac6eca99fd858678b03a47357e72856e10 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 10 Mar 2020 20:54:05 +0100
Subject: [PATCH 037/111] ir: Implement more safety checks for shl/shr
The checks are now valid on types whose size is not a power of two.
Closes #2096
---
src/all_types.hpp | 1 +
src/codegen.cpp | 32 ++++++++++++++++++++++++++++++++
src/ir.cpp | 38 ++++++++++++++++++--------------------
test/compile_errors.zig | 35 +++++++++++++++++++++++++++++++++--
test/runtime_safety.zig | 31 +++++++++++++++++++++++++++++++
5 files changed, 115 insertions(+), 22 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 14b99228ca1c3fe8ef1f2f15155f39840055267e..53aae9e236471205e23cca522ef4b0bd909ad07f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1834,6 +1834,7 @@ enum PanicMsgId {
PanicMsgIdBadNoAsyncCall,
PanicMsgIdResumeNotSuspendedFn,
PanicMsgIdBadSentinel,
+ PanicMsgIdShxTooBigRhs,
PanicMsgIdCount,
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 22cb97520565ef44d0986e10e1f6b9e44648b38f..d659e27d86761082e4b79d160a0c4c3d65418131 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -974,6 +974,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
return buf_create_from_str("resumed a non-suspended function");
case PanicMsgIdBadSentinel:
return buf_create_from_str("sentinel mismatch");
+ case PanicMsgIdShxTooBigRhs:
+ return buf_create_from_str("shift amount is greater than the type size");
}
zig_unreachable();
}
@@ -2841,6 +2843,26 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast
}
+static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type, LLVMValueRef value) {
+ // We only check if the rhs value of the shift expression is greater or
+ // equal to the number of bits of the lhs if it's not a power of two,
+ // otherwise the check is useful as the allowed values are limited by the
+ // operand type itself
+ if (!is_power_of_2(lhs_type->data.integral.bit_count)) {
+ LLVMValueRef bit_count_value = LLVMConstInt(get_llvm_type(g, rhs_type),
+ lhs_type->data.integral.bit_count, false);
+ LLVMValueRef less_than_bit = LLVMBuildICmp(g->builder, LLVMIntULT, value, bit_count_value, "");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CheckFail");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CheckOk");
+ LLVMBuildCondBr(g->builder, less_than_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdShxTooBigRhs);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ }
+}
+
static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable,
IrInstGenBinOp *bin_op_instruction)
{
@@ -2949,6 +2971,11 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable,
{
assert(scalar_type->id == ZigTypeIdInt);
LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value->type, scalar_type, op2_value);
+
+ if (want_runtime_safety) {
+ gen_shift_rhs_check(g, scalar_type, op2->value->type, op2_value);
+ }
+
bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
if (is_sloppy) {
return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
@@ -2965,6 +2992,11 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable,
{
assert(scalar_type->id == ZigTypeIdInt);
LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value->type, scalar_type, op2_value);
+
+ if (want_runtime_safety) {
+ gen_shift_rhs_check(g, scalar_type, op2->value->type, op2_value);
+ }
+
bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
if (is_sloppy) {
if (scalar_type->data.integral.is_signed) {
diff --git a/src/ir.cpp b/src/ir.cpp
index e5b28f84c2fcc79c5ce1719369b85daf0b2ab4ad..b9b42141bce8ad79da017b170c5556795121e1f0 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -16648,36 +16648,34 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
return ira->codegen->invalid_inst_gen;
}
} else {
+ assert(op1->value->type->data.integral.bit_count > 0);
ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
- op1->value->type->data.integral.bit_count - 1);
- if (bin_op_instruction->op_id == IrBinOpBitShiftLeftLossy &&
- op2->value->type->id == ZigTypeIdComptimeInt) {
+ op1->value->type->data.integral.bit_count - 1);
- ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
+ casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
+ if (type_is_invalid(casted_op2->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (instr_is_comptime(casted_op2)) {
+ ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
return ira->codegen->invalid_inst_gen;
- if (!bigint_fits_in_bits(&op2_val->data.x_bigint,
- shift_amt_type->data.integral.bit_count,
- op2_val->data.x_bigint.is_negative)) {
- Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
+
+ BigInt bit_count_value = {0};
+ bigint_init_unsigned(&bit_count_value, op1->value->type->data.integral.bit_count);
+
+ if (bigint_cmp(&op2_val->data.x_bigint, &bit_count_value) != CmpLT) {
ErrorMsg* msg = ir_add_error(ira,
&bin_op_instruction->base.base,
buf_sprintf("RHS of shift is too large for LHS type"));
- add_error_note(
- ira->codegen,
- msg,
- op2->base.source_node,
- buf_sprintf("value %s cannot fit into type %s",
- buf_ptr(val_buf),
- buf_ptr(&shift_amt_type->name)));
+ add_error_note(ira->codegen, msg, op1->base.source_node,
+ buf_sprintf("type %s has only %u bits",
+ buf_ptr(&op1->value->type->name),
+ op1->value->type->data.integral.bit_count));
+
return ira->codegen->invalid_inst_gen;
}
}
-
- casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
- if (type_is_invalid(casted_op2->value->type))
- return ira->codegen->invalid_inst_gen;
}
if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index a2d4e8ac23df0e39c0e78918cc9bc2c590f23c80..5078453332618de9d237e5404f430625f8934b09 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,38 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest("shift on type with non-power-of-two size",
+ \\export fn entry() void {
+ \\ const S = struct {
+ \\ fn a() void {
+ \\ var x: u24 = 42;
+ \\ _ = x >> 24;
+ \\ }
+ \\ fn b() void {
+ \\ var x: u24 = 42;
+ \\ _ = x << 24;
+ \\ }
+ \\ fn c() void {
+ \\ var x: u24 = 42;
+ \\ _ = @shlExact(x, 24);
+ \\ }
+ \\ fn d() void {
+ \\ var x: u24 = 42;
+ \\ _ = @shrExact(x, 24);
+ \\ }
+ \\ };
+ \\ S.a();
+ \\ S.b();
+ \\ S.c();
+ \\ S.d();
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:5:19: error: RHS of shift is too large for LHS type",
+ "tmp.zig:9:19: error: RHS of shift is too large for LHS type",
+ "tmp.zig:13:17: error: RHS of shift is too large for LHS type",
+ "tmp.zig:17:17: error: RHS of shift is too large for LHS type",
+ });
+
cases.addTest("combination of noasync and async",
\\export fn entry() void {
\\ noasync {
@@ -4029,8 +4061,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
\\export fn entry() u16 { return f(); }
, &[_][]const u8{
- "tmp.zig:3:14: error: RHS of shift is too large for LHS type",
- "tmp.zig:3:17: note: value 8 cannot fit into type u3",
+ "tmp.zig:3:17: error: integer value 8 cannot be coerced to type 'u3'",
});
cases.add("missing function call param",
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
index e183c6979f14096c538ab9c54646e8ef3006acfe..9855aae16bbfe2049eedc45fca58ef0aaf90e3aa 100644
--- a/test/runtime_safety.zig
+++ b/test/runtime_safety.zig
@@ -1,6 +1,37 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompareOutputContext) void {
+ cases.addRuntimeSafety("shift left by huge amount",
+ \\const std = @import("std");
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ std.debug.warn("{}\n", .{message});
+ \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+ \\ std.process.exit(126); // good
+ \\ }
+ \\ std.process.exit(0); // test failed
+ \\}
+ \\pub fn main() void {
+ \\ var x: u24 = 42;
+ \\ var y: u5 = 24;
+ \\ var z = x >> y;
+ \\}
+ );
+
+ cases.addRuntimeSafety("shift right by huge amount",
+ \\const std = @import("std");
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+ \\ std.process.exit(126); // good
+ \\ }
+ \\ std.process.exit(0); // test failed
+ \\}
+ \\pub fn main() void {
+ \\ var x: u24 = 42;
+ \\ var y: u5 = 24;
+ \\ var z = x << y;
+ \\}
+ );
+
cases.addRuntimeSafety("slice sentinel mismatch - optional pointers",
\\const std = @import("std");
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
--
2.54.0
From b6fbd524f122449e6e2bb4d73ce3f59b01286f50 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 16:31:04 -0400
Subject: [PATCH 038/111] (breaking) improve and simplify fixed buffer streams
API
---
lib/std/io.zig | 156 +-----------------------
lib/std/io/buffered_atomic_file.zig | 4 +-
lib/std/io/buffered_in_stream.zig | 84 +++++++++++++
lib/std/io/buffered_out_stream.zig | 23 +---
lib/std/io/fixed_buffer_stream.zig | 183 +++++++++++++++++++---------
lib/std/json.zig | 4 +-
lib/std/progress.zig | 2 +-
lib/std/std.zig | 1 -
src-self-hosted/print_targets.zig | 2 +-
9 files changed, 223 insertions(+), 236 deletions(-)
create mode 100644 lib/std/io/buffered_in_stream.zig
diff --git a/lib/std/io.zig b/lib/std/io.zig
index dcb0551dc9a7b8b416a20021d78a33decd775429..1283461271d238b5bcca6d0fd9e1387c5b0dc84b 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -95,19 +95,19 @@ pub fn getStdIn() File {
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
pub const InStream = @import("io/in_stream.zig").InStream;
pub const OutStream = @import("io/out_stream.zig").OutStream;
-pub const FixedBufferInStream = @import("io/fixed_buffer_stream.zig").FixedBufferInStream;
pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
pub const BufferedOutStream = @import("io/buffered_out_stream.zig").BufferedOutStream;
-pub const BufferedOutStreamCustom = @import("io/buffered_out_stream.zig").BufferedOutStreamCustom;
pub const bufferedOutStream = @import("io/buffered_out_stream.zig").bufferedOutStream;
+pub const BufferedInStream = @import("io/buffered_in_stream.zig").BufferedInStream;
+pub const bufferedInStream = @import("io/buffered_in_stream.zig").bufferedInStream;
+
+pub const FixedBufferStream = @import("io/fixed_buffer_stream.zig").FixedBufferStream;
+pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferStream;
+
pub const CountingOutStream = @import("io/counting_out_stream.zig").CountingOutStream;
-pub fn fixedBufferStream(bytes: []const u8) FixedBufferInStream {
- return (FixedBufferInStream{ .bytes = bytes, .pos = 0 });
-}
-
pub fn cOutStream(c_file: *std.c.FILE) COutStream {
return .{ .context = c_file };
}
@@ -144,92 +144,6 @@ pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
return fs.cwd().readFileAlloc(allocator, path, math.maxInt(usize));
}
-pub fn BufferedInStream(comptime Error: type) type {
- return BufferedInStreamCustom(mem.page_size, Error);
-}
-
-pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type {
- return struct {
- const Self = @This();
- const Stream = InStream(Error);
-
- stream: Stream,
-
- unbuffered_in_stream: *Stream,
-
- const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
- fifo: FifoType,
-
- pub fn init(unbuffered_in_stream: *Stream) Self {
- return Self{
- .unbuffered_in_stream = unbuffered_in_stream,
- .fifo = FifoType.init(),
- .stream = Stream{ .readFn = readFn },
- };
- }
-
- fn readFn(in_stream: *Stream, dest: []u8) !usize {
- const self = @fieldParentPtr(Self, "stream", in_stream);
- var dest_index: usize = 0;
- while (dest_index < dest.len) {
- const written = self.fifo.read(dest[dest_index..]);
- if (written == 0) {
- // fifo empty, fill it
- const writable = self.fifo.writableSlice(0);
- assert(writable.len > 0);
- const n = try self.unbuffered_in_stream.read(writable);
- if (n == 0) {
- // reading from the unbuffered stream returned nothing
- // so we have nothing left to read.
- return dest_index;
- }
- self.fifo.update(n);
- }
- dest_index += written;
- }
- return dest.len;
- }
- };
-}
-
-test "io.BufferedInStream" {
- const OneByteReadInStream = struct {
- const Error = error{NoError};
- const Stream = InStream(Error);
-
- stream: Stream,
- str: []const u8,
- curr: usize,
-
- fn init(str: []const u8) @This() {
- return @This(){
- .stream = Stream{ .readFn = readFn },
- .str = str,
- .curr = 0,
- };
- }
-
- fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
- const self = @fieldParentPtr(@This(), "stream", in_stream);
- if (self.str.len <= self.curr or dest.len == 0)
- return 0;
-
- dest[0] = self.str[self.curr];
- self.curr += 1;
- return 1;
- }
- };
-
- const str = "This is a test";
- var one_byte_stream = OneByteReadInStream.init(str);
- var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream);
- const stream = &buf_in_stream.stream;
-
- const res = try stream.readAllAlloc(testing.allocator, str.len + 1);
- defer testing.allocator.free(res);
- testing.expectEqualSlices(u8, str, res);
-}
-
/// Creates a stream which supports 'un-reading' data, so that it can be read again.
/// This makes look-ahead style parsing much easier.
pub fn PeekStream(comptime buffer_type: std.fifo.LinearFifoBufferType, comptime InStreamError: type) type {
@@ -473,64 +387,6 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
};
}
-/// This is a simple OutStream that writes to a fixed buffer. If the returned number
-/// of bytes written is less than requested, the buffer is full.
-/// Returns error.OutOfMemory when no bytes would be written.
-pub const SliceOutStream = struct {
- pub const Error = error{OutOfMemory};
- pub const Stream = OutStream(Error);
-
- stream: Stream,
-
- pos: usize,
- slice: []u8,
-
- pub fn init(slice: []u8) SliceOutStream {
- return SliceOutStream{
- .slice = slice,
- .pos = 0,
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- pub fn getWritten(self: *const SliceOutStream) []const u8 {
- return self.slice[0..self.pos];
- }
-
- pub fn reset(self: *SliceOutStream) void {
- self.pos = 0;
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) Error!usize {
- const self = @fieldParentPtr(SliceOutStream, "stream", out_stream);
-
- if (bytes.len == 0) return 0;
-
- assert(self.pos <= self.slice.len);
-
- const n = if (self.pos + bytes.len <= self.slice.len)
- bytes.len
- else
- self.slice.len - self.pos;
-
- std.mem.copy(u8, self.slice[self.pos .. self.pos + n], bytes[0..n]);
- self.pos += n;
-
- if (n == 0) return error.OutOfMemory;
-
- return n;
- }
-};
-
-test "io.SliceOutStream" {
- var buf: [255]u8 = undefined;
- var slice_stream = SliceOutStream.init(buf[0..]);
- const stream = &slice_stream.stream;
-
- try stream.print("{}{}!", .{ "Hello", "World" });
- testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten());
-}
-
/// An OutStream that doesn't write to anything.
pub const null_out_stream = @as(NullOutStream, .{ .context = {} });
diff --git a/lib/std/io/buffered_atomic_file.zig b/lib/std/io/buffered_atomic_file.zig
index 48c550c90fa95f1c8899b53970711e572aab2ec3..e2f8c75af0883b3b26ea2bbdc1c6a796adffea25 100644
--- a/lib/std/io/buffered_atomic_file.zig
+++ b/lib/std/io/buffered_atomic_file.zig
@@ -10,7 +10,7 @@ pub const BufferedAtomicFile = struct {
allocator: *mem.Allocator,
pub const buffer_size = 4096;
- pub const BufferedOutStream = std.io.BufferedOutStreamCustom(buffer_size, File.OutStream);
+ pub const BufferedOutStream = std.io.BufferedOutStream(buffer_size, File.OutStream);
pub const OutStream = std.io.OutStream(*BufferedOutStream, BufferedOutStream.Error, BufferedOutStream.write);
/// TODO when https://github.com/ziglang/zig/issues/2761 is solved
@@ -29,7 +29,7 @@ pub const BufferedAtomicFile = struct {
errdefer self.atomic_file.deinit();
self.file_stream = self.atomic_file.file.outStream();
- self.buffered_stream = std.io.bufferedOutStream(buffer_size, self.file_stream);
+ self.buffered_stream = .{ .unbuffered_out_stream = self.file_stream };
return self;
}
diff --git a/lib/std/io/buffered_in_stream.zig b/lib/std/io/buffered_in_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..72f1b30b76a2fb80dcdc1b31afed73627403d820
--- /dev/null
+++ b/lib/std/io/buffered_in_stream.zig
@@ -0,0 +1,84 @@
+const std = @import("../std.zig");
+const io = std.io;
+
+pub fn BufferedInStream(comptime buffer_size: usize, comptime InStreamType) type {
+ return struct {
+ unbuffered_in_stream: InStreamType,
+ fifo: FifoType = FifoType.init(),
+
+ pub const Error = InStreamType.Error;
+ pub const InStream = io.InStream(*Self, Error, read);
+
+ const Self = @This();
+ const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
+
+ pub fn read(self: *Self, dest: []u8) Error!usize {
+ var dest_index: usize = 0;
+ while (dest_index < dest.len) {
+ const written = self.fifo.read(dest[dest_index..]);
+ if (written == 0) {
+ // fifo empty, fill it
+ const writable = self.fifo.writableSlice(0);
+ assert(writable.len > 0);
+ const n = try self.unbuffered_in_stream.read(writable);
+ if (n == 0) {
+ // reading from the unbuffered stream returned nothing
+ // so we have nothing left to read.
+ return dest_index;
+ }
+ self.fifo.update(n);
+ }
+ dest_index += written;
+ }
+ return dest.len;
+ }
+
+ pub fn inStream(self: *Self) InStream {
+ return .{ .context = self };
+ }
+ };
+}
+
+pub fn bufferedInStream(underlying_stream: var) BufferedInStream(4096, @TypeOf(underlying_stream)) {
+ return .{ .unbuffered_in_stream = underlying_stream };
+}
+
+test "io.BufferedInStream" {
+ const OneByteReadInStream = struct {
+ str: []const u8,
+ curr: usize,
+
+ const Error = error{NoError};
+ const Self = @This();
+ const InStream = io.InStream(*Self, Error, read);
+
+ fn init(str: []const u8) Self {
+ return Self{
+ .str = str,
+ .curr = 0,
+ };
+ }
+
+ fn read(self: *Self, dest: []u8) Error!usize {
+ if (self.str.len <= self.curr or dest.len == 0)
+ return 0;
+
+ dest[0] = self.str[self.curr];
+ self.curr += 1;
+ return 1;
+ }
+
+ fn inStream(self: *Self) InStream {
+ return .{ .context = self };
+ }
+ };
+
+ const str = "This is a test";
+ var one_byte_stream = OneByteReadInStream.init(str);
+ var buf_in_stream = bufferedInStream(one_byte_stream.inStream());
+ const stream = buf_in_stream.inStream();
+
+ const res = try stream.readAllAlloc(testing.allocator, str.len + 1);
+ defer testing.allocator.free(res);
+ testing.expectEqualSlices(u8, str, res);
+}
diff --git a/lib/std/io/buffered_out_stream.zig b/lib/std/io/buffered_out_stream.zig
index 3650022b29a607eea74bfaed4a1a5ba4785af702..43af83c537faa14d9170410611ad1f22697ab814 100644
--- a/lib/std/io/buffered_out_stream.zig
+++ b/lib/std/io/buffered_out_stream.zig
@@ -1,14 +1,10 @@
const std = @import("../std.zig");
const io = std.io;
-pub fn BufferedOutStream(comptime OutStreamType: type) type {
- return BufferedOutStreamCustom(4096, OutStreamType);
-}
-
-pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamType: type) type {
+pub fn BufferedOutStream(comptime buffer_size: usize, comptime OutStreamType: type) type {
return struct {
unbuffered_out_stream: OutStreamType,
- fifo: FifoType,
+ fifo: FifoType = FifoType.init(),
pub const Error = OutStreamType.Error;
pub const OutStream = io.OutStream(*Self, Error, write);
@@ -16,13 +12,6 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamTy
const Self = @This();
const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
- pub fn init(unbuffered_out_stream: OutStreamType) Self {
- return Self{
- .unbuffered_out_stream = unbuffered_out_stream,
- .fifo = FifoType.init(),
- };
- }
-
pub fn flush(self: *Self) !void {
while (true) {
const slice = self.fifo.readableSlice(0);
@@ -47,10 +36,6 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamTy
};
}
-pub fn bufferedOutStream(
- comptime buffer_size: usize,
- underlying_stream: var,
-) BufferedOutStreamCustom(buffer_size, @TypeOf(underlying_stream)) {
- return BufferedOutStreamCustom(buffer_size, @TypeOf(underlying_stream)).init(underlying_stream);
+pub fn bufferedOutStream(underlying_stream: var) BufferedOutStream(4096, @TypeOf(underlying_stream)) {
+ return .{ .unbuffered_out_stream = underlying_stream };
}
-
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index 847feeae039fadeccd5083c9c3111aded04ed3d9..75a337d3de4b111544fe94facac2cda786541a07 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -1,66 +1,129 @@
const std = @import("../std.zig");
const io = std.io;
+const testing = std.testing;
-pub const FixedBufferInStream = struct {
- bytes: []const u8,
- pos: usize,
-
- pub const SeekError = error{EndOfStream};
- pub const GetSeekPosError = error{};
-
- pub const InStream = io.InStream(*FixedBufferInStream, error{}, read);
-
- pub fn inStream(self: *FixedBufferInStream) InStream {
- return .{ .context = self };
- }
-
- pub const SeekableStream = io.SeekableStream(
- *FixedBufferInStream,
- SeekError,
- GetSeekPosError,
- seekTo,
- seekBy,
- getPos,
- getEndPos,
- );
-
- pub fn seekableStream(self: *FixedBufferInStream) SeekableStream {
- return .{ .context = self };
- }
-
- pub fn read(self: *FixedBufferInStream, dest: []u8) error{}!usize {
- const size = std.math.min(dest.len, self.bytes.len - self.pos);
- const end = self.pos + size;
-
- std.mem.copy(u8, dest[0..size], self.bytes[self.pos..end]);
- self.pos = end;
-
- return size;
- }
-
- pub fn seekTo(self: *FixedBufferInStream, pos: u64) SeekError!void {
- const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream;
- if (usize_pos > self.bytes.len) return error.EndOfStream;
- self.pos = usize_pos;
- }
-
- pub fn seekBy(self: *FixedBufferInStream, amt: i64) SeekError!void {
- if (amt < 0) {
- const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream;
- if (abs_amt > self.pos) return error.EndOfStream;
- self.pos -= abs_amt;
- } else {
- const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream;
- if (self.pos + usize_amt > self.bytes.len) return error.EndOfStream;
- self.pos += usize_amt;
+/// This turns a slice into an `io.OutStream`, `io.InStream`, or `io.SeekableStream`.
+/// If the supplied slice is const, then `io.OutStream` is not available.
+pub fn FixedBufferStream(comptime Buffer: type) type {
+ return struct {
+ /// `Buffer` is either a `[]u8` or `[]const u8`.
+ buffer: Buffer,
+ pos: usize,
+
+ pub const ReadError = error{EndOfStream};
+ pub const WriteError = error{OutOfMemory};
+ pub const SeekError = error{EndOfStream};
+ pub const GetSeekPosError = error{};
+
+ pub const InStream = io.InStream(*Self, ReadError, read);
+ pub const OutStream = io.OutStream(*Self, WriteError, write);
+
+ pub const SeekableStream = io.SeekableStream(
+ *Self,
+ SeekError,
+ GetSeekPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
+ const Self = @This();
+
+ pub fn inStream(self: *Self) InStream {
+ return .{ .context = self };
+ }
+
+ pub fn outStream(self: *Self) OutStream {
+ return .{ .context = self };
+ }
+
+ pub fn seekableStream(self: *Self) SeekableStream {
+ return .{ .context = self };
+ }
+
+ pub fn read(self: *Self, dest: []u8) ReadError!usize {
+ const size = std.math.min(dest.len, self.buffer.len - self.pos);
+ const end = self.pos + size;
+
+ std.mem.copy(u8, dest[0..size], self.buffer[self.pos..end]);
+ self.pos = end;
+
+ if (size == 0) return error.EndOfStream;
+ return size;
+ }
+
+ /// If the returned number of bytes written is less than requested, the
+ /// buffer is full. Returns `error.OutOfMemory` when no bytes would be written.
+ pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
+ if (bytes.len == 0) return 0;
+
+ assert(self.pos <= self.buffer.len);
+
+ const n = if (self.pos + bytes.len <= self.buffer.len)
+ bytes.len
+ else
+ self.buffer.len - self.pos;
+
+ std.mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]);
+ self.pos += n;
+
+ if (n == 0) return error.OutOfMemory;
+
+ return n;
+ }
+
+ pub fn seekTo(self: *Self, pos: u64) SeekError!void {
+ const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream;
+ if (usize_pos > self.buffer.len) return error.EndOfStream;
+ self.pos = usize_pos;
+ }
+
+ pub fn seekBy(self: *Self, amt: i64) SeekError!void {
+ if (amt < 0) {
+ const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream;
+ if (abs_amt > self.pos) return error.EndOfStream;
+ self.pos -= abs_amt;
+ } else {
+ const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream;
+ if (self.pos + usize_amt > self.buffer.len) return error.EndOfStream;
+ self.pos += usize_amt;
+ }
+ }
+
+ pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
+ return self.buffer.len;
}
- }
- pub fn getEndPos(self: *FixedBufferInStream) GetSeekPosError!u64 {
- return self.bytes.len;
- }
+ pub fn getPos(self: *Self) GetSeekPosError!u64 {
+ return self.pos;
+ }
+
+ pub fn getWritten(self: Self) []const u8 {
+ return self.slice[0..self.pos];
+ }
+
+ pub fn reset(self: *Self) void {
+ self.pos = 0;
+ }
+ };
+}
+
+pub fn fixedBufferStream(buffer: var) FixedBufferStream(NonSentinelSpan(@TypeOf(buffer))) {
+ return .{ .buffer = std.mem.span(buffer), .pos = 0 };
+}
+
+fn NonSentinelSpan(comptime T: type) type {
+ var ptr_info = @typeInfo(std.mem.Span(T)).Pointer;
+ ptr_info.sentinel = null;
+ return @Type(std.builtin.TypeInfo{ .Pointer = ptr_info });
+}
+
+test "FixedBufferStream" {
+ var buf: [255]u8 = undefined;
+ var fbs = fixedBufferStream(&buf);
+ const stream = fbs.outStream();
- pub fn getPos(self: *FixedBufferInStream) GetSeekPosError!u64 {
- return self.pos;
- }
-};
+ try stream.print("{}{}!", .{ "Hello", "World" });
+ testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
+}
diff --git a/lib/std/json.zig b/lib/std/json.zig
index bb59b4e0f3be5c11464a69bd8f6c381b10bb26d0..f2cf68d7eb2079cf17b117aea87866dea590606e 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -2107,8 +2107,8 @@ test "import more json tests" {
test "write json then parse it" {
var out_buffer: [1000]u8 = undefined;
- var slice_out_stream = std.io.SliceOutStream.init(&out_buffer);
- const out_stream = &slice_out_stream.stream;
+ var fixed_buffer_stream = std.io.fixedBufferStream(&out_buffer);
+ const out_stream = fixed_buffer_stream.outStream();
var jw = WriteStream(@TypeOf(out_stream).Child, 4).init(out_stream);
try jw.beginObject();
diff --git a/lib/std/progress.zig b/lib/std/progress.zig
index 1c5ecd261ae71045e09c360fc8a91a7cc6a2c5c3..0264d99c91a8fe02ce5a689b2c34c713874a4ede 100644
--- a/lib/std/progress.zig
+++ b/lib/std/progress.zig
@@ -177,7 +177,7 @@ pub const Progress = struct {
pub fn log(self: *Progress, comptime format: []const u8, args: var) void {
const file = self.terminal orelse return;
self.refresh();
- file.outStream().stream.print(format, args) catch {
+ file.outStream().print(format, args) catch {
self.terminal = null;
return;
};
diff --git a/lib/std/std.zig b/lib/std/std.zig
index dd4d968efbc9fa8fa81ffaf07245dc77d56a2896..9277370ca6abf6c020ce48ec059eca6161c63594 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -5,7 +5,6 @@ pub const BloomFilter = @import("bloom_filter.zig").BloomFilter;
pub const BufMap = @import("buf_map.zig").BufMap;
pub const BufSet = @import("buf_set.zig").BufSet;
pub const Buffer = @import("buffer.zig").Buffer;
-pub const BufferOutStream = @import("io.zig").BufferOutStream;
pub const ChildProcess = @import("child_process.zig").ChildProcess;
pub const DynLib = @import("dynamic_library.zig").DynLib;
pub const HashMap = @import("hash_map.zig").HashMap;
diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig
index 473e3dfa51f3c8059d0b09669d1a56008cdb4fb6..ad506425d2af144e4b906e8781510a58c769d4b2 100644
--- a/src-self-hosted/print_targets.zig
+++ b/src-self-hosted/print_targets.zig
@@ -93,7 +93,7 @@ pub fn cmdTargets(
};
defer allocator.free(available_glibcs);
- var bos = io.bufferedOutStream(4096, stdout);
+ var bos = io.bufferedOutStream(stdout);
const bos_stream = bos.outStream();
var jws = std.json.WriteStream(@TypeOf(bos_stream), 6).init(bos_stream);
--
2.54.0
From 8dc188ebe06b5b78dcead521561858fc27e25204 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 22:33:32 +0200
Subject: [PATCH 039/111] support atomic operations with bools
---
src/codegen.cpp | 43 ++++++++++++++++++++++++++++++++
src/ir.cpp | 6 +++++
test/stage1/behavior/atomics.zig | 10 ++++++++
3 files changed, 59 insertions(+)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 22cb97520565ef44d0986e10e1f6b9e44648b38f..7238d5041b4693262facad6be138667e0c1b9c27 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5224,6 +5224,15 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
+ ZigType *operand_type = instruction->new_value->value->type;
+ if (operand_type->id == ZigTypeIdBool) {
+ // treat bool as u8
+ ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
+ LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
+ cmp_val = LLVMConstZExt(cmp_val, g->builtin_types.entry_u8->llvm_type);
+ new_val = LLVMConstZExt(new_val, g->builtin_types.entry_u8->llvm_type);
+ }
+
LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering(instruction->failure_order);
@@ -5236,6 +5245,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
if (!handle_is_ptr(g, optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
+ if (operand_type->id == ZigTypeIdBool) {
+ payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
+ }
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
}
@@ -5250,6 +5262,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
ir_assert(type_has_bits(g, child_type), &instruction->base);
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
+ if (operand_type->id == ZigTypeIdBool) {
+ payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
+ }
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
@@ -5827,6 +5842,16 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
+ if (operand_type->id == ZigTypeIdBool) {
+ // treat bool as u8
+ LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
+ LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
+ LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_u8->llvm_type, "");
+ LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
+ g->is_single_threaded);
+ return LLVMBuildTrunc(g->builder, uncasted_result, g->builtin_types.entry_bool->llvm_type, "");
+ }
+
if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {
return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);
}
@@ -5845,6 +5870,16 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl
{
LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
+
+ ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type;
+ if (operand_type->id == ZigTypeIdBool) {
+ // treat bool as u8
+ ptr = LLVMBuildBitCast(g->builder, ptr,
+ LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
+ LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
+ LLVMSetOrdering(load_inst, ordering);
+ return LLVMBuildTrunc(g->builder, load_inst, g->builtin_types.entry_bool->llvm_type, "");
+ }
LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
LLVMSetOrdering(load_inst, ordering);
return load_inst;
@@ -5856,6 +5891,14 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef value = ir_llvm_value(g, instruction->value);
+
+ ZigType *operand_type = instruction->value->value->type;
+ if (operand_type->id == ZigTypeIdBool) {
+ // treat bool as u8
+ ptr = LLVMBuildBitCast(g->builder, ptr,
+ LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
+ value = LLVMConstZExt(value, g->builtin_types.entry_u8->llvm_type);
+ }
LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
LLVMSetOrdering(store_inst, ordering);
return nullptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index e5b28f84c2fcc79c5ce1719369b85daf0b2ab4ad..c6978ca0a961b1bab06ff93f8bd2069e08f2eae1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -28357,6 +28357,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count));
return ira->codegen->builtin_types.entry_invalid;
}
+ } else if (operand_type->id == ZigTypeIdBool) {
+ // will be treated as u8
} else {
Error err;
ZigType *operand_ptr_type;
@@ -28397,6 +28399,10 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
ir_add_error(ira, &instruction->op->base,
buf_sprintf("@atomicRmw on enum only works with .Xchg"));
return ira->codegen->invalid_inst_gen;
+ } else if (operand_type->id == ZigTypeIdBool && op != AtomicRmwOp_xchg) {
+ ir_add_error(ira, &instruction->op->base,
+ buf_sprintf("@atomicRmw on bool only works with .Xchg"));
+ return ira->codegen->invalid_inst_gen;
} else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) {
ir_add_error(ira, &instruction->op->base,
buf_sprintf("@atomicRmw with float only works with .Xchg, .Add and .Sub"));
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index 0347f6f94a2886927859507b72357aad60d61176..bda0a8469ce091d9b7e8df871e8f63d4fd2273c3 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -161,3 +161,13 @@ fn testAtomicRmwFloat() void {
_ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
expect(x == 4);
}
+
+test "atomics with bool" {
+ var x = false;
+ @atomicStore(bool, &x, true, .SeqCst);
+ expect(x == true);
+ expect(@atomicLoad(bool, &x, .SeqCst) == true);
+ expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
+ expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
+ expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
+}
--
2.54.0
From ee5b00a8b90ef375d0cd4432d31e3a4ed0b6f632 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Tue, 10 Mar 2020 22:46:19 +0200
Subject: [PATCH 040/111] use atomic bools in std lib
---
lib/std/atomic/queue.zig | 20 +++++++++-----------
lib/std/atomic/stack.zig | 31 +++++++++++++++----------------
lib/std/event/channel.zig | 24 ++++++++++++------------
lib/std/event/lock.zig | 36 +++++++++++++++++-------------------
lib/std/event/rwlock.zig | 32 ++++++++++++++++----------------
src/ir.cpp | 6 +++---
test/compile_errors.zig | 13 +++++++++++--
7 files changed, 83 insertions(+), 79 deletions(-)
diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig
index 1969587f30a61bf6c211bcc0578021b3d5bfd59a..5c40acc3cb7216bfab232c342c8fe6b17259ac41 100644
--- a/lib/std/atomic/queue.zig
+++ b/lib/std/atomic/queue.zig
@@ -1,7 +1,5 @@
const std = @import("../std.zig");
const builtin = @import("builtin");
-const AtomicOrder = builtin.AtomicOrder;
-const AtomicRmwOp = builtin.AtomicRmwOp;
const assert = std.debug.assert;
const expect = std.testing.expect;
@@ -149,7 +147,7 @@ const Context = struct {
put_sum: isize,
get_sum: isize,
get_count: usize,
- puts_done: u8, // TODO make this a bool
+ puts_done: bool,
};
// TODO add lazy evaluated build options and then put puts_per_thread behind
@@ -173,7 +171,7 @@ test "std.atomic.Queue" {
.queue = &queue,
.put_sum = 0,
.get_sum = 0,
- .puts_done = 0,
+ .puts_done = false,
.get_count = 0,
};
@@ -186,7 +184,7 @@ test "std.atomic.Queue" {
}
}
expect(!context.queue.isEmpty());
- context.puts_done = 1;
+ context.puts_done = true;
{
var i: usize = 0;
while (i < put_thread_count) : (i += 1) {
@@ -208,7 +206,7 @@ test "std.atomic.Queue" {
for (putters) |t|
t.wait();
- @atomicStore(u8, &context.puts_done, 1, AtomicOrder.SeqCst);
+ @atomicStore(bool, &context.puts_done, true, .SeqCst);
for (getters) |t|
t.wait();
@@ -235,25 +233,25 @@ fn startPuts(ctx: *Context) u8 {
std.time.sleep(1); // let the os scheduler be our fuzz
const x = @bitCast(i32, r.random.scalar(u32));
const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
- node.* = Queue(i32).Node{
+ node.* = .{
.prev = undefined,
.next = undefined,
.data = x,
};
ctx.queue.put(node);
- _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
+ _ = @atomicRmw(isize, &ctx.put_sum, .Add, x, .SeqCst);
}
return 0;
}
fn startGets(ctx: *Context) u8 {
while (true) {
- const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
+ const last = @atomicLoad(bool, &ctx.puts_done, .SeqCst);
while (ctx.queue.get()) |node| {
std.time.sleep(1); // let the os scheduler be our fuzz
- _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
- _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
+ _ = @atomicRmw(isize, &ctx.get_sum, .Add, node.data, .SeqCst);
+ _ = @atomicRmw(usize, &ctx.get_count, .Add, 1, .SeqCst);
}
if (last) return 0;
diff --git a/lib/std/atomic/stack.zig b/lib/std/atomic/stack.zig
index 0f67a257cc71526fe1dca238ad42bc2cd6bb3fb3..07cb16e450132668e8726d6ad795a1e58f6affea 100644
--- a/lib/std/atomic/stack.zig
+++ b/lib/std/atomic/stack.zig
@@ -1,6 +1,5 @@
const assert = std.debug.assert;
const builtin = @import("builtin");
-const AtomicOrder = builtin.AtomicOrder;
const expect = std.testing.expect;
/// Many reader, many writer, non-allocating, thread-safe
@@ -11,7 +10,7 @@ pub fn Stack(comptime T: type) type {
root: ?*Node,
lock: @TypeOf(lock_init),
- const lock_init = if (builtin.single_threaded) {} else @as(u8, 0);
+ const lock_init = if (builtin.single_threaded) {} else false;
pub const Self = @This();
@@ -31,7 +30,7 @@ pub fn Stack(comptime T: type) type {
/// being the first item in the stack, returns the other item that was there.
pub fn pushFirst(self: *Self, node: *Node) ?*Node {
node.next = null;
- return @cmpxchgStrong(?*Node, &self.root, null, node, AtomicOrder.SeqCst, AtomicOrder.SeqCst);
+ return @cmpxchgStrong(?*Node, &self.root, null, node, .SeqCst, .SeqCst);
}
pub fn push(self: *Self, node: *Node) void {
@@ -39,8 +38,8 @@ pub fn Stack(comptime T: type) type {
node.next = self.root;
self.root = node;
} else {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst) != false) {}
+ defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst) == true);
node.next = self.root;
self.root = node;
@@ -53,8 +52,8 @@ pub fn Stack(comptime T: type) type {
self.root = root.next;
return root;
} else {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst) != false) {}
+ defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst) == true);
const root = self.root orelse return null;
self.root = root.next;
@@ -63,7 +62,7 @@ pub fn Stack(comptime T: type) type {
}
pub fn isEmpty(self: *Self) bool {
- return @atomicLoad(?*Node, &self.root, AtomicOrder.SeqCst) == null;
+ return @atomicLoad(?*Node, &self.root, .SeqCst) == null;
}
};
}
@@ -75,7 +74,7 @@ const Context = struct {
put_sum: isize,
get_sum: isize,
get_count: usize,
- puts_done: u8, // TODO make this a bool
+ puts_done: bool,
};
// TODO add lazy evaluated build options and then put puts_per_thread behind
// some option such as: "AggressiveMultithreadedFuzzTest". In the AppVeyor
@@ -98,7 +97,7 @@ test "std.atomic.stack" {
.stack = &stack,
.put_sum = 0,
.get_sum = 0,
- .puts_done = 0,
+ .puts_done = false,
.get_count = 0,
};
@@ -109,7 +108,7 @@ test "std.atomic.stack" {
expect(startPuts(&context) == 0);
}
}
- context.puts_done = 1;
+ context.puts_done = true;
{
var i: usize = 0;
while (i < put_thread_count) : (i += 1) {
@@ -128,7 +127,7 @@ test "std.atomic.stack" {
for (putters) |t|
t.wait();
- @atomicStore(u8, &context.puts_done, 1, AtomicOrder.SeqCst);
+ @atomicStore(bool, &context.puts_done, true, .SeqCst);
for (getters) |t|
t.wait();
}
@@ -158,19 +157,19 @@ fn startPuts(ctx: *Context) u8 {
.data = x,
};
ctx.stack.push(node);
- _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
+ _ = @atomicRmw(isize, &ctx.put_sum, .Add, x, .SeqCst);
}
return 0;
}
fn startGets(ctx: *Context) u8 {
while (true) {
- const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
+ const last = @atomicLoad(bool, &ctx.puts_done, .SeqCst) == true;
while (ctx.stack.pop()) |node| {
std.time.sleep(1); // let the os scheduler be our fuzz
- _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
- _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
+ _ = @atomicRmw(isize, &ctx.get_sum, .Add, node.data, .SeqCst);
+ _ = @atomicRmw(usize, &ctx.get_count, .Add, 1, .SeqCst);
}
if (last) return 0;
diff --git a/lib/std/event/channel.zig b/lib/std/event/channel.zig
index 3c5b48d047419b67787fdfa0788dd5d7d48bf012..355bd782922582dc3e8ec3bc4273de439d63895b 100644
--- a/lib/std/event/channel.zig
+++ b/lib/std/event/channel.zig
@@ -14,8 +14,8 @@ pub fn Channel(comptime T: type) type {
putters: std.atomic.Queue(PutNode),
get_count: usize,
put_count: usize,
- dispatch_lock: u8, // TODO make this a bool
- need_dispatch: u8, // TODO make this a bool
+ dispatch_lock: bool,
+ need_dispatch: bool,
// simple fixed size ring buffer
buffer_nodes: []T,
@@ -62,8 +62,8 @@ pub fn Channel(comptime T: type) type {
.buffer_len = 0,
.buffer_nodes = buffer,
.buffer_index = 0,
- .dispatch_lock = 0,
- .need_dispatch = 0,
+ .dispatch_lock = false,
+ .need_dispatch = false,
.getters = std.atomic.Queue(GetNode).init(),
.putters = std.atomic.Queue(PutNode).init(),
.or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
@@ -165,15 +165,15 @@ pub fn Channel(comptime T: type) type {
fn dispatch(self: *SelfChannel) void {
// set the "need dispatch" flag
- @atomicStore(u8, &self.need_dispatch, 1, .SeqCst);
+ @atomicStore(bool, &self.need_dispatch, true, .SeqCst);
lock: while (true) {
// set the lock flag
- const prev_lock = @atomicRmw(u8, &self.dispatch_lock, .Xchg, 1, .SeqCst);
+ const prev_lock = @atomicRmw(bool, &self.dispatch_lock, .Xchg, true, .SeqCst);
if (prev_lock != 0) return;
// clear the need_dispatch flag since we're about to do it
- @atomicStore(u8, &self.need_dispatch, 0, .SeqCst);
+ @atomicStore(bool, &self.need_dispatch, false, .SeqCst);
while (true) {
one_dispatch: {
@@ -250,14 +250,14 @@ pub fn Channel(comptime T: type) type {
}
// clear need-dispatch flag
- const need_dispatch = @atomicRmw(u8, &self.need_dispatch, .Xchg, 0, .SeqCst);
- if (need_dispatch != 0) continue;
+ const need_dispatch = @atomicRmw(bool, &self.need_dispatch, .Xchg, false, .SeqCst);
+ if (need_dispatch) continue;
- const my_lock = @atomicRmw(u8, &self.dispatch_lock, .Xchg, 0, .SeqCst);
- assert(my_lock != 0);
+ const my_lock = @atomicRmw(bool, &self.dispatch_lock, .Xchg, false, .SeqCst);
+ assert(my_lock);
// we have to check again now that we unlocked
- if (@atomicLoad(u8, &self.need_dispatch, .SeqCst) != 0) continue :lock;
+ if (@atomicLoad(bool, &self.need_dispatch, .SeqCst)) continue :lock;
return;
}
diff --git a/lib/std/event/lock.zig b/lib/std/event/lock.zig
index b9cbb5d95fd02969aa0474b6aa71689d61df4594..6b27bbd8c459e75eba2b7ee42fc3bef45747ed8d 100644
--- a/lib/std/event/lock.zig
+++ b/lib/std/event/lock.zig
@@ -11,9 +11,9 @@ const Loop = std.event.Loop;
/// Allows only one actor to hold the lock.
/// TODO: make this API also work in blocking I/O mode.
pub const Lock = struct {
- shared_bit: u8, // TODO make this a bool
+ shared: bool,
queue: Queue,
- queue_empty_bit: u8, // TODO make this a bool
+ queue_empty: bool,
const Queue = std.atomic.Queue(anyframe);
@@ -31,20 +31,19 @@ pub const Lock = struct {
}
// We need to release the lock.
- @atomicStore(u8, &self.lock.queue_empty_bit, 1, .SeqCst);
- @atomicStore(u8, &self.lock.shared_bit, 0, .SeqCst);
+ @atomicStore(bool, &self.lock.queue_empty, true, .SeqCst);
+ @atomicStore(bool, &self.lock.shared, false, .SeqCst);
// There might be a queue item. If we know the queue is empty, we can be done,
// because the other actor will try to obtain the lock.
// But if there's a queue item, we are the actor which must loop and attempt
// to grab the lock again.
- if (@atomicLoad(u8, &self.lock.queue_empty_bit, .SeqCst) == 1) {
+ if (@atomicLoad(bool, &self.lock.queue_empty, .SeqCst)) {
return;
}
while (true) {
- const old_bit = @atomicRmw(u8, &self.lock.shared_bit, .Xchg, 1, .SeqCst);
- if (old_bit != 0) {
+ if (@atomicRmw(bool, &self.lock.shared, .Xchg, true, .SeqCst)) {
// We did not obtain the lock. Great, the queue is someone else's problem.
return;
}
@@ -56,11 +55,11 @@ pub const Lock = struct {
}
// Release the lock again.
- @atomicStore(u8, &self.lock.queue_empty_bit, 1, .SeqCst);
- @atomicStore(u8, &self.lock.shared_bit, 0, .SeqCst);
+ @atomicStore(bool, &self.lock.queue_empty, true, .SeqCst);
+ @atomicStore(bool, &self.lock.shared, false, .SeqCst);
// Find out if we can be done.
- if (@atomicLoad(u8, &self.lock.queue_empty_bit, .SeqCst) == 1) {
+ if (@atomicLoad(bool, &self.lock.queue_empty, .SeqCst)) {
return;
}
}
@@ -69,24 +68,24 @@ pub const Lock = struct {
pub fn init() Lock {
return Lock{
- .shared_bit = 0,
+ .shared = false,
.queue = Queue.init(),
- .queue_empty_bit = 1,
+ .queue_empty = true,
};
}
pub fn initLocked() Lock {
return Lock{
- .shared_bit = 1,
+ .shared = true,
.queue = Queue.init(),
- .queue_empty_bit = 1,
+ .queue_empty = true,
};
}
/// Must be called when not locked. Not thread safe.
/// All calls to acquire() and release() must complete before calling deinit().
pub fn deinit(self: *Lock) void {
- assert(self.shared_bit == 0);
+ assert(!self.shared);
while (self.queue.get()) |node| resume node.data;
}
@@ -99,12 +98,11 @@ pub const Lock = struct {
// At this point, we are in the queue, so we might have already been resumed.
- // We set this bit so that later we can rely on the fact, that if queue_empty_bit is 1, some actor
+ // We set this bit so that later we can rely on the fact, that if queue_empty == true, some actor
// will attempt to grab the lock.
- @atomicStore(u8, &self.queue_empty_bit, 0, .SeqCst);
+ @atomicStore(bool, &self.queue_empty, false, .SeqCst);
- const old_bit = @atomicRmw(u8, &self.shared_bit, .Xchg, 1, .SeqCst);
- if (old_bit == 0) {
+ if (!@atomicRmw(bool, &self.shared, .Xchg, true, .SeqCst)) {
if (self.queue.get()) |node| {
// Whether this node is us or someone else, we tail resume it.
resume node.data;
diff --git a/lib/std/event/rwlock.zig b/lib/std/event/rwlock.zig
index f4b13d008b5f45e88e77905855b1f5749141cd57..425088063f71e4828272be19767b761f60799370 100644
--- a/lib/std/event/rwlock.zig
+++ b/lib/std/event/rwlock.zig
@@ -16,8 +16,8 @@ pub const RwLock = struct {
shared_state: State,
writer_queue: Queue,
reader_queue: Queue,
- writer_queue_empty_bit: u8, // TODO make this a bool
- reader_queue_empty_bit: u8, // TODO make this a bool
+ writer_queue_empty: bool,
+ reader_queue_empty: bool,
reader_lock_count: usize,
const State = enum(u8) {
@@ -40,7 +40,7 @@ pub const RwLock = struct {
return;
}
- @atomicStore(u8, &self.lock.reader_queue_empty_bit, 1, .SeqCst);
+ @atomicStore(bool, &self.lock.reader_queue_empty, true, .SeqCst);
if (@cmpxchgStrong(State, &self.lock.shared_state, .ReadLock, .Unlocked, .SeqCst, .SeqCst) != null) {
// Didn't unlock. Someone else's problem.
return;
@@ -62,7 +62,7 @@ pub const RwLock = struct {
}
// We need to release the write lock. Check if any readers are waiting to grab the lock.
- if (@atomicLoad(u8, &self.lock.reader_queue_empty_bit, .SeqCst) == 0) {
+ if (!@atomicLoad(bool, &self.lock.reader_queue_empty, .SeqCst)) {
// Switch to a read lock.
@atomicStore(State, &self.lock.shared_state, .ReadLock, .SeqCst);
while (self.lock.reader_queue.get()) |node| {
@@ -71,7 +71,7 @@ pub const RwLock = struct {
return;
}
- @atomicStore(u8, &self.lock.writer_queue_empty_bit, 1, .SeqCst);
+ @atomicStore(bool, &self.lock.writer_queue_empty, true, .SeqCst);
@atomicStore(State, &self.lock.shared_state, .Unlocked, .SeqCst);
self.lock.commonPostUnlock();
@@ -79,12 +79,12 @@ pub const RwLock = struct {
};
pub fn init() RwLock {
- return RwLock{
+ return .{
.shared_state = .Unlocked,
.writer_queue = Queue.init(),
- .writer_queue_empty_bit = 1,
+ .writer_queue_empty = true,
.reader_queue = Queue.init(),
- .reader_queue_empty_bit = 1,
+ .reader_queue_empty = true,
.reader_lock_count = 0,
};
}
@@ -111,9 +111,9 @@ pub const RwLock = struct {
// At this point, we are in the reader_queue, so we might have already been resumed.
- // We set this bit so that later we can rely on the fact, that if reader_queue_empty_bit is 1,
+ // We set this bit so that later we can rely on the fact, that if reader_queue_empty == true,
// some actor will attempt to grab the lock.
- @atomicStore(u8, &self.reader_queue_empty_bit, 0, .SeqCst);
+ @atomicStore(bool, &self.reader_queue_empty, false, .SeqCst);
// Here we don't care if we are the one to do the locking or if it was already locked for reading.
const have_read_lock = if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .ReadLock, .SeqCst, .SeqCst)) |old_state| old_state == .ReadLock else true;
@@ -142,9 +142,9 @@ pub const RwLock = struct {
// At this point, we are in the writer_queue, so we might have already been resumed.
- // We set this bit so that later we can rely on the fact, that if writer_queue_empty_bit is 1,
+ // We set this bit so that later we can rely on the fact, that if writer_queue_empty == true,
// some actor will attempt to grab the lock.
- @atomicStore(u8, &self.writer_queue_empty_bit, 0, .SeqCst);
+ @atomicStore(bool, &self.writer_queue_empty, false, .SeqCst);
// Here we must be the one to acquire the write lock. It cannot already be locked.
if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .WriteLock, .SeqCst, .SeqCst) == null) {
@@ -165,7 +165,7 @@ pub const RwLock = struct {
// obtain the lock.
// But if there's a writer_queue item or a reader_queue item,
// we are the actor which must loop and attempt to grab the lock again.
- if (@atomicLoad(u8, &self.writer_queue_empty_bit, .SeqCst) == 0) {
+ if (!@atomicLoad(bool, &self.writer_queue_empty, .SeqCst)) {
if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .WriteLock, .SeqCst, .SeqCst) != null) {
// We did not obtain the lock. Great, the queues are someone else's problem.
return;
@@ -176,12 +176,12 @@ pub const RwLock = struct {
return;
}
// Release the lock again.
- @atomicStore(u8, &self.writer_queue_empty_bit, 1, .SeqCst);
+ @atomicStore(bool, &self.writer_queue_empty, true, .SeqCst);
@atomicStore(State, &self.shared_state, .Unlocked, .SeqCst);
continue;
}
- if (@atomicLoad(u8, &self.reader_queue_empty_bit, .SeqCst) == 0) {
+ if (!@atomicLoad(bool, &self.reader_queue_empty, .SeqCst)) {
if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .ReadLock, .SeqCst, .SeqCst) != null) {
// We did not obtain the lock. Great, the queues are someone else's problem.
return;
@@ -195,7 +195,7 @@ pub const RwLock = struct {
return;
}
// Release the lock again.
- @atomicStore(u8, &self.reader_queue_empty_bit, 1, .SeqCst);
+ @atomicStore(bool, &self.reader_queue_empty, true, .SeqCst);
if (@cmpxchgStrong(State, &self.shared_state, .ReadLock, .Unlocked, .SeqCst, .SeqCst) != null) {
// Didn't unlock. Someone else's problem.
return;
diff --git a/src/ir.cpp b/src/ir.cpp
index c6978ca0a961b1bab06ff93f8bd2069e08f2eae1..cad1d382e16ecac6b5ba1a9c99f825909d420d85 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -28397,15 +28397,15 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
if (operand_type->id == ZigTypeIdEnum && op != AtomicRmwOp_xchg) {
ir_add_error(ira, &instruction->op->base,
- buf_sprintf("@atomicRmw on enum only works with .Xchg"));
+ buf_sprintf("@atomicRmw with enum only allowed with .Xchg"));
return ira->codegen->invalid_inst_gen;
} else if (operand_type->id == ZigTypeIdBool && op != AtomicRmwOp_xchg) {
ir_add_error(ira, &instruction->op->base,
- buf_sprintf("@atomicRmw on bool only works with .Xchg"));
+ buf_sprintf("@atomicRmw with bool only allowed with .Xchg"));
return ira->codegen->invalid_inst_gen;
} else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) {
ir_add_error(ira, &instruction->op->base,
- buf_sprintf("@atomicRmw with float only works with .Xchg, .Add and .Sub"));
+ buf_sprintf("@atomicRmw with float only allowed with .Xchg, .Add and .Sub"));
return ira->codegen->invalid_inst_gen;
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index a2d4e8ac23df0e39c0e78918cc9bc2c590f23c80..28529b3f579c477c0bcc2eb27b5c9350afff5589 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add("atomicrmw with bool op not .Xchg",
+ \\export fn entry() void {
+ \\ var x = false;
+ \\ _ = @atomicRmw(bool, &x, .Add, true, .SeqCst);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:3:30: error: @atomicRmw with bool only allowed with .Xchg",
+ });
+
cases.addTest("combination of noasync and async",
\\export fn entry() void {
\\ noasync {
@@ -325,7 +334,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst);
\\}
, &[_][]const u8{
- "tmp.zig:3:29: error: @atomicRmw with float only works with .Xchg, .Add and .Sub",
+ "tmp.zig:3:29: error: @atomicRmw with float only allowed with .Xchg, .Add and .Sub",
});
cases.add("intToPtr with misaligned address",
@@ -542,7 +551,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = @atomicRmw(E, &x, .Add, .b, .SeqCst);
\\}
, &[_][]const u8{
- "tmp.zig:9:27: error: @atomicRmw on enum only works with .Xchg",
+ "tmp.zig:9:27: error: @atomicRmw with enum only allowed with .Xchg",
});
cases.add("disallow coercion from non-null-terminated pointer to null-terminated pointer",
--
2.54.0
From 4ab13a359dfb14c93869e7f88320ec2aa438da9c Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 10 Mar 2020 23:04:49 +0100
Subject: [PATCH 041/111] ir: Fix shift code for u0 operands
---
src/ir.cpp | 46 +++++++++++++++++++++++------------
test/stage1/behavior/math.zig | 19 +++++++++++++++
2 files changed, 50 insertions(+), 15 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index b9b42141bce8ad79da017b170c5556795121e1f0..bb2dc75c6467fd18712e176d6277c6ae0578efbd 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -16635,34 +16635,47 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
IrInstGen *casted_op2;
IrBinOp op_id = bin_op_instruction->op_id;
if (op1->value->type->id == ZigTypeIdComptimeInt) {
+ // comptime_int has no finite bit width
casted_op2 = op2;
if (op_id == IrBinOpBitShiftLeftLossy) {
op_id = IrBinOpBitShiftLeftExact;
}
- if (casted_op2->value->data.x_bigint.is_negative) {
+ if (!instr_is_comptime(op2)) {
+ ir_add_error(ira, &bin_op_instruction->base.base,
+ buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
+ if (op2_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ if (op2_val->data.x_bigint.is_negative) {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &casted_op2->value->data.x_bigint, 10);
- ir_add_error(ira, &casted_op2->base, buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
+ bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
+ ir_add_error(ira, &casted_op2->base,
+ buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
return ira->codegen->invalid_inst_gen;
}
} else {
- assert(op1->value->type->data.integral.bit_count > 0);
+ const unsigned bit_count = op1->value->type->data.integral.bit_count;
ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
- op1->value->type->data.integral.bit_count - 1);
+ bit_count > 0 ? bit_count - 1 : 0);
casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
if (type_is_invalid(casted_op2->value->type))
return ira->codegen->invalid_inst_gen;
- if (instr_is_comptime(casted_op2)) {
+ // This check is only valid iff op1 has at least one bit
+ if (bit_count > 0 && instr_is_comptime(casted_op2)) {
ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
return ira->codegen->invalid_inst_gen;
BigInt bit_count_value = {0};
- bigint_init_unsigned(&bit_count_value, op1->value->type->data.integral.bit_count);
+ bigint_init_unsigned(&bit_count_value, bit_count);
if (bigint_cmp(&op2_val->data.x_bigint, &bit_count_value) != CmpLT) {
ErrorMsg* msg = ir_add_error(ira,
@@ -16670,14 +16683,23 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
buf_sprintf("RHS of shift is too large for LHS type"));
add_error_note(ira->codegen, msg, op1->base.source_node,
buf_sprintf("type %s has only %u bits",
- buf_ptr(&op1->value->type->name),
- op1->value->type->data.integral.bit_count));
+ buf_ptr(&op1->value->type->name), bit_count));
return ira->codegen->invalid_inst_gen;
}
}
}
+ // Fast path for zero RHS
+ if (instr_is_comptime(casted_op2)) {
+ ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
+ if (op2_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ if (bigint_cmp_zero(&op2_val->data.x_bigint) == CmpEQ)
+ return ir_analyze_cast(ira, &bin_op_instruction->base.base, op1->value->type, op1);
+ }
+
if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (op1_val == nullptr)
@@ -16688,12 +16710,6 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
return ira->codegen->invalid_inst_gen;
return ir_analyze_math_op(ira, &bin_op_instruction->base.base, op1->value->type, op1_val, op_id, op2_val);
- } else if (op1->value->type->id == ZigTypeIdComptimeInt) {
- ir_add_error(ira, &bin_op_instruction->base.base,
- buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
- return ira->codegen->invalid_inst_gen;
- } else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value->data.x_bigint) == CmpEQ) {
- return ir_build_cast(ira, &bin_op_instruction->base.base, op1->value->type, op1, CastOpNoop);
}
return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, op1->value->type,
diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig
index e657b5472b0f6f0e48b54bc85f2228d2188c6871..fb70fb7e4420e6c1eae4ca786ea323cc7d73b312 100644
--- a/test/stage1/behavior/math.zig
+++ b/test/stage1/behavior/math.zig
@@ -453,6 +453,25 @@ fn testShrExact(x: u8) void {
expect(shifted == 0b00101101);
}
+test "shift left/right on u0 operand" {
+ const S = struct {
+ fn doTheTest() void {
+ var x: u0 = 0;
+ var y: u0 = 0;
+ expectEqual(@as(u0, 0), x << 0);
+ expectEqual(@as(u0, 0), x >> 0);
+ expectEqual(@as(u0, 0), x << y);
+ expectEqual(@as(u0, 0), x >> y);
+ expectEqual(@as(u0, 0), @shlExact(x, 0));
+ expectEqual(@as(u0, 0), @shrExact(x, 0));
+ expectEqual(@as(u0, 0), @shlExact(x, y));
+ expectEqual(@as(u0, 0), @shrExact(x, y));
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
test "comptime_int addition" {
comptime {
expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
--
2.54.0
From 83f6f730cdd5bb9c2a12b30c0aac33d858a1eaa8 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Tue, 10 Mar 2020 15:22:29 -0400
Subject: [PATCH 042/111] std: simplify format enum-literals
---
lib/std/fmt.zig | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index deae0a717bb7591dcd2a3121657a908962bbabc5..a7525ba79545fc601ee17b6d2afee55d714efa49 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -492,10 +492,7 @@ pub fn formatType(
},
.Type => return output(context, @typeName(T)),
.EnumLiteral => {
- const name = @tagName(value);
- var buffer: [name.len + 1]u8 = undefined;
- buffer[0] = '.';
- std.mem.copy(u8, buffer[1..], name);
+ const buffer = [_]u8{'.'} ++ @tagName(value);
return formatType(buffer, fmt, options, context, Errors, output, max_depth);
},
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
--
2.54.0
From 18f1fef1426cb0405c733890b2e1d8d48627e4fe Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 18:44:30 -0400
Subject: [PATCH 043/111] update standard library to new I/O streams API
---
lib/std/atomic/queue.zig | 33 +-
lib/std/buffer.zig | 12 +
lib/std/debug/leb128.zig | 24 +-
lib/std/heap.zig | 1 +
lib/std/heap/logging_allocator.zig | 106 ++--
lib/std/io.zig | 762 +----------------------------
lib/std/io/bit_in_stream.zig | 237 +++++++++
lib/std/io/bit_out_stream.zig | 197 ++++++++
lib/std/io/buffered_in_stream.zig | 4 +-
lib/std/io/c_out_stream.zig | 44 ++
lib/std/io/counting_out_stream.zig | 21 +-
lib/std/io/fixed_buffer_stream.zig | 56 ++-
lib/std/io/in_stream.zig | 3 +-
lib/std/io/peek_stream.zig | 112 +++++
lib/std/io/serialization.zig | 606 +++++++++++++++++++++++
lib/std/io/test.zig | 534 +-------------------
lib/std/json.zig | 5 +-
lib/std/json/write_stream.zig | 13 +-
lib/std/net.zig | 4 +-
lib/std/os/test.zig | 11 +-
lib/std/zig/parser_test.zig | 11 +-
lib/std/zig/render.zig | 2 +-
22 files changed, 1415 insertions(+), 1383 deletions(-)
create mode 100644 lib/std/io/bit_in_stream.zig
create mode 100644 lib/std/io/bit_out_stream.zig
create mode 100644 lib/std/io/c_out_stream.zig
create mode 100644 lib/std/io/peek_stream.zig
create mode 100644 lib/std/io/serialization.zig
diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig
index 1969587f30a61bf6c211bcc0578021b3d5bfd59a..1a0f39587e96212b6c75a927d7ce4b9653ceaedb 100644
--- a/lib/std/atomic/queue.zig
+++ b/lib/std/atomic/queue.zig
@@ -104,21 +104,17 @@ pub fn Queue(comptime T: type) type {
}
pub fn dump(self: *Self) void {
- var stderr_file = std.io.getStdErr() catch return;
- const stderr = &stderr_file.outStream().stream;
- const Error = @typeInfo(@TypeOf(stderr)).Pointer.child.Error;
-
- self.dumpToStream(Error, stderr) catch return;
+ self.dumpToStream(std.io.getStdErr().outStream()) catch return;
}
- pub fn dumpToStream(self: *Self, comptime Error: type, stream: *std.io.OutStream(Error)) Error!void {
+ pub fn dumpToStream(self: *Self, stream: var) !void {
const S = struct {
fn dumpRecursive(
- s: *std.io.OutStream(Error),
+ s: var,
optional_node: ?*Node,
indent: usize,
comptime depth: comptime_int,
- ) Error!void {
+ ) !void {
try s.writeByteNTimes(' ', indent);
if (optional_node) |node| {
try s.print("0x{x}={}\n", .{ @ptrToInt(node), node.data });
@@ -326,17 +322,16 @@ test "std.atomic.Queue single-threaded" {
test "std.atomic.Queue dump" {
const mem = std.mem;
- const SliceOutStream = std.io.SliceOutStream;
var buffer: [1024]u8 = undefined;
var expected_buffer: [1024]u8 = undefined;
- var sos = SliceOutStream.init(buffer[0..]);
+ var fbs = std.io.fixedBufferStream(&buffer);
var queue = Queue(i32).init();
// Test empty stream
- sos.reset();
- try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
- expect(mem.eql(u8, buffer[0..sos.pos],
+ fbs.reset();
+ try queue.dumpToStream(fbs.outStream());
+ expect(mem.eql(u8, buffer[0..fbs.pos],
\\head: (null)
\\tail: (null)
\\
@@ -350,8 +345,8 @@ test "std.atomic.Queue dump" {
};
queue.put(&node_0);
- sos.reset();
- try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
+ fbs.reset();
+ try queue.dumpToStream(fbs.outStream());
var expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
@@ -360,7 +355,7 @@ test "std.atomic.Queue dump" {
\\ (null)
\\
, .{ @ptrToInt(queue.head), @ptrToInt(queue.tail) });
- expect(mem.eql(u8, buffer[0..sos.pos], expected));
+ expect(mem.eql(u8, buffer[0..fbs.pos], expected));
// Test a stream with two elements
var node_1 = Queue(i32).Node{
@@ -370,8 +365,8 @@ test "std.atomic.Queue dump" {
};
queue.put(&node_1);
- sos.reset();
- try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
+ fbs.reset();
+ try queue.dumpToStream(fbs.outStream());
expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
@@ -381,5 +376,5 @@ test "std.atomic.Queue dump" {
\\ (null)
\\
, .{ @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail) });
- expect(mem.eql(u8, buffer[0..sos.pos], expected));
+ expect(mem.eql(u8, buffer[0..fbs.pos], expected));
}
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index a33670b6d3fc8c4b1ebf6d5d0aaecde5df4599fc..28ce2a561062f0a84f55c58c10c1c3b9d359a293 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -219,3 +219,15 @@ test "Buffer.print" {
try buf.print("Hello {} the {}", .{ 2, "world" });
testing.expect(buf.eql("Hello 2 the world"));
}
+
+test "Buffer.outStream" {
+ var buffer = try Buffer.initSize(testing.allocator, 0);
+ defer buffer.deinit();
+ const buf_stream = buffer.outStream();
+
+ const x: i32 = 42;
+ const y: i32 = 1234;
+ try buf_stream.print("x: {}\ny: {}\n", .{ x, y });
+
+ testing.expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
+}
diff --git a/lib/std/debug/leb128.zig b/lib/std/debug/leb128.zig
index 1d81b9390a8ade29b78c7383c787623abe822dab..e2157335b5a83bff1c477ca757eafd7fea2e9c9e 100644
--- a/lib/std/debug/leb128.zig
+++ b/lib/std/debug/leb128.zig
@@ -121,18 +121,18 @@ pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
}
fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
- var in_stream = std.io.SliceInStream.init(encoded);
- return try readILEB128(T, &in_stream.stream);
+ var in_stream = std.io.fixedBufferStream(encoded);
+ return try readILEB128(T, in_stream.inStream());
}
fn test_read_stream_uleb128(comptime T: type, encoded: []const u8) !T {
- var in_stream = std.io.SliceInStream.init(encoded);
- return try readULEB128(T, &in_stream.stream);
+ var in_stream = std.io.fixedBufferStream(encoded);
+ return try readULEB128(T, in_stream.inStream());
}
fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
- var in_stream = std.io.SliceInStream.init(encoded);
- const v1 = readILEB128(T, &in_stream.stream);
+ var in_stream = std.io.fixedBufferStream(encoded);
+ const v1 = readILEB128(T, in_stream.inStream());
var in_ptr = encoded.ptr;
const v2 = readILEB128Mem(T, &in_ptr);
testing.expectEqual(v1, v2);
@@ -140,8 +140,8 @@ fn test_read_ileb128(comptime T: type, encoded: []const u8) !T {
}
fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
- var in_stream = std.io.SliceInStream.init(encoded);
- const v1 = readULEB128(T, &in_stream.stream);
+ var in_stream = std.io.fixedBufferStream(encoded);
+ const v1 = readULEB128(T, in_stream.inStream());
var in_ptr = encoded.ptr;
const v2 = readULEB128Mem(T, &in_ptr);
testing.expectEqual(v1, v2);
@@ -149,22 +149,22 @@ fn test_read_uleb128(comptime T: type, encoded: []const u8) !T {
}
fn test_read_ileb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) void {
- var in_stream = std.io.SliceInStream.init(encoded);
+ var in_stream = std.io.fixedBufferStream(encoded);
var in_ptr = encoded.ptr;
var i: usize = 0;
while (i < N) : (i += 1) {
- const v1 = readILEB128(T, &in_stream.stream);
+ const v1 = readILEB128(T, in_stream.inStream());
const v2 = readILEB128Mem(T, &in_ptr);
testing.expectEqual(v1, v2);
}
}
fn test_read_uleb128_seq(comptime T: type, comptime N: usize, encoded: []const u8) void {
- var in_stream = std.io.SliceInStream.init(encoded);
+ var in_stream = std.io.fixedBufferStream(encoded);
var in_ptr = encoded.ptr;
var i: usize = 0;
while (i < N) : (i += 1) {
- const v1 = readULEB128(T, &in_stream.stream);
+ const v1 = readULEB128(T, in_stream.inStream());
const v2 = readULEB128Mem(T, &in_ptr);
testing.expectEqual(v1, v2);
}
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
index 65809e97b4e70588cad01b53f0e390db50c08856..8c79249d4baaf2ad6f46933d757db306ecc55de9 100644
--- a/lib/std/heap.zig
+++ b/lib/std/heap.zig
@@ -10,6 +10,7 @@ const c = std.c;
const maxInt = std.math.maxInt;
pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator;
+pub const loggingAllocator = @import("heap/logging_allocator.zig").loggingAllocator;
const Allocator = mem.Allocator;
diff --git a/lib/std/heap/logging_allocator.zig b/lib/std/heap/logging_allocator.zig
index 7dce7bc20a5a1b5d98edd044285314322466bc79..0d15986a76a94ed881caad2b53cfa27c039045ea 100644
--- a/lib/std/heap/logging_allocator.zig
+++ b/lib/std/heap/logging_allocator.zig
@@ -1,63 +1,69 @@
const std = @import("../std.zig");
const Allocator = std.mem.Allocator;
-const AnyErrorOutStream = std.io.OutStream(anyerror);
-
/// This allocator is used in front of another allocator and logs to the provided stream
/// on every call to the allocator. Stream errors are ignored.
/// If https://github.com/ziglang/zig/issues/2586 is implemented, this API can be improved.
-pub const LoggingAllocator = struct {
- allocator: Allocator,
+pub fn LoggingAllocator(comptime OutStreamType: type) type {
+ return struct {
+ allocator: Allocator,
+ parent_allocator: *Allocator,
+ out_stream: OutStreamType,
+
+ const Self = @This();
+
+ pub fn init(parent_allocator: *Allocator, out_stream: OutStreamType) Self {
+ return Self{
+ .allocator = Allocator{
+ .reallocFn = realloc,
+ .shrinkFn = shrink,
+ },
+ .parent_allocator = parent_allocator,
+ .out_stream = out_stream,
+ };
+ }
+
+ fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
+ const self = @fieldParentPtr(Self, "allocator", allocator);
+ if (old_mem.len == 0) {
+ self.out_stream.print("allocation of {} ", .{new_size}) catch {};
+ } else {
+ self.out_stream.print("resize from {} to {} ", .{ old_mem.len, new_size }) catch {};
+ }
+ const result = self.parent_allocator.reallocFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
+ if (result) |buff| {
+ self.out_stream.print("success!\n", .{}) catch {};
+ } else |err| {
+ self.out_stream.print("failure!\n", .{}) catch {};
+ }
+ return result;
+ }
+
+ fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
+ const self = @fieldParentPtr(Self, "allocator", allocator);
+ const result = self.parent_allocator.shrinkFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
+ if (new_size == 0) {
+ self.out_stream.print("free of {} bytes success!\n", .{old_mem.len}) catch {};
+ } else {
+ self.out_stream.print("shrink from {} bytes to {} bytes success!\n", .{ old_mem.len, new_size }) catch {};
+ }
+ return result;
+ }
+ };
+}
+
+pub fn loggingAllocator(
parent_allocator: *Allocator,
- out_stream: *AnyErrorOutStream,
-
- const Self = @This();
-
- pub fn init(parent_allocator: *Allocator, out_stream: *AnyErrorOutStream) Self {
- return Self{
- .allocator = Allocator{
- .reallocFn = realloc,
- .shrinkFn = shrink,
- },
- .parent_allocator = parent_allocator,
- .out_stream = out_stream,
- };
- }
-
- fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
- const self = @fieldParentPtr(Self, "allocator", allocator);
- if (old_mem.len == 0) {
- self.out_stream.print("allocation of {} ", .{new_size}) catch {};
- } else {
- self.out_stream.print("resize from {} to {} ", .{ old_mem.len, new_size }) catch {};
- }
- const result = self.parent_allocator.reallocFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
- if (result) |buff| {
- self.out_stream.print("success!\n", .{}) catch {};
- } else |err| {
- self.out_stream.print("failure!\n", .{}) catch {};
- }
- return result;
- }
-
- fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
- const self = @fieldParentPtr(Self, "allocator", allocator);
- const result = self.parent_allocator.shrinkFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
- if (new_size == 0) {
- self.out_stream.print("free of {} bytes success!\n", .{old_mem.len}) catch {};
- } else {
- self.out_stream.print("shrink from {} bytes to {} bytes success!\n", .{ old_mem.len, new_size }) catch {};
- }
- return result;
- }
-};
+ out_stream: var,
+) LoggingAllocator(@TypeOf(out_stream)) {
+ return LoggingAllocator(@TypeOf(out_stream)).init(parent_allocator, out_stream);
+}
test "LoggingAllocator" {
var buf: [255]u8 = undefined;
- var slice_stream = std.io.SliceOutStream.init(buf[0..]);
- const stream = &slice_stream.stream;
+ var fbs = std.io.fixedBufferStream(&buf);
- const allocator = &LoggingAllocator.init(std.testing.allocator, @ptrCast(*AnyErrorOutStream, stream)).allocator;
+ const allocator = &loggingAllocator(std.testing.allocator, fbs.outStream()).allocator;
const ptr = try allocator.alloc(u8, 10);
allocator.free(ptr);
@@ -66,5 +72,5 @@ test "LoggingAllocator" {
\\allocation of 10 success!
\\free of 10 bytes success!
\\
- , slice_stream.getWritten());
+ , fbs.getWritten());
}
diff --git a/lib/std/io.zig b/lib/std/io.zig
index 1283461271d238b5bcca6d0fd9e1387c5b0dc84b..22af5c06b11e6e309ae5877614b466f9069af09f 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -4,17 +4,13 @@ const root = @import("root");
const c = std.c;
const math = std.math;
-const debug = std.debug;
-const assert = debug.assert;
+const assert = std.debug.assert;
const os = std.os;
const fs = std.fs;
const mem = std.mem;
const meta = std.meta;
const trait = meta.trait;
-const Buffer = std.Buffer;
-const fmt = std.fmt;
const File = std.fs.File;
-const testing = std.testing;
pub const Mode = enum {
/// I/O operates normally, waiting for the operating system syscalls to complete.
@@ -92,10 +88,9 @@ pub fn getStdIn() File {
};
}
-pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
pub const InStream = @import("io/in_stream.zig").InStream;
pub const OutStream = @import("io/out_stream.zig").OutStream;
-pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
+pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
pub const BufferedOutStream = @import("io/buffered_out_stream.zig").BufferedOutStream;
pub const bufferedOutStream = @import("io/buffered_out_stream.zig").bufferedOutStream;
@@ -103,36 +98,33 @@ pub const bufferedOutStream = @import("io/buffered_out_stream.zig").bufferedOutS
pub const BufferedInStream = @import("io/buffered_in_stream.zig").BufferedInStream;
pub const bufferedInStream = @import("io/buffered_in_stream.zig").bufferedInStream;
+pub const PeekStream = @import("io/peek_stream.zig").PeekStream;
+pub const peekStream = @import("io/peek_stream.zig").peekStream;
+
pub const FixedBufferStream = @import("io/fixed_buffer_stream.zig").FixedBufferStream;
pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferStream;
+pub const COutStream = @import("io/c_out_stream.zig").COutStream;
+pub const cOutStream = @import("io/c_out_stream.zig").cOutStream;
+
pub const CountingOutStream = @import("io/counting_out_stream.zig").CountingOutStream;
+pub const countingOutStream = @import("io/counting_out_stream.zig").countingOutStream;
-pub fn cOutStream(c_file: *std.c.FILE) COutStream {
- return .{ .context = c_file };
-}
+pub const BitInStream = @import("io/bit_in_stream.zig").BitInStream;
+pub const bitInStream = @import("io/bit_in_stream.zig").bitInStream;
-pub const COutStream = OutStream(*std.c.FILE, std.fs.File.WriteError, cOutStreamWrite);
+pub const BitOutStream = @import("io/bit_out_stream.zig").BitOutStream;
+pub const bitOutStream = @import("io/bit_out_stream.zig").bitOutStream;
-pub fn cOutStreamWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!usize {
- const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, c_file);
- if (amt_written >= 0) return amt_written;
- switch (std.c._errno().*) {
- 0 => unreachable,
- os.EINVAL => unreachable,
- os.EFAULT => unreachable,
- os.EAGAIN => unreachable, // this is a blocking API
- os.EBADF => unreachable, // always a race condition
- os.EDESTADDRREQ => unreachable, // connect was never called
- os.EDQUOT => return error.DiskQuota,
- os.EFBIG => return error.FileTooBig,
- os.EIO => return error.InputOutput,
- os.ENOSPC => return error.NoSpaceLeft,
- os.EPERM => return error.AccessDenied,
- os.EPIPE => return error.BrokenPipe,
- else => |err| return os.unexpectedErrno(@intCast(usize, err)),
- }
-}
+pub const Packing = @import("io/serialization.zig").Packing;
+
+pub const Serializer = @import("io/serialization.zig").Serializer;
+pub const serializer = @import("io/serialization.zig").serializer;
+
+pub const Deserializer = @import("io/serialization.zig").Deserializer;
+pub const deserializer = @import("io/serialization.zig").deserializer;
+
+pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
/// Deprecated; use `std.fs.Dir.writeFile`.
pub fn writeFile(path: []const u8, data: []const u8) !void {
@@ -144,249 +136,6 @@ pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
return fs.cwd().readFileAlloc(allocator, path, math.maxInt(usize));
}
-/// Creates a stream which supports 'un-reading' data, so that it can be read again.
-/// This makes look-ahead style parsing much easier.
-pub fn PeekStream(comptime buffer_type: std.fifo.LinearFifoBufferType, comptime InStreamError: type) type {
- return struct {
- const Self = @This();
- pub const Error = InStreamError;
- pub const Stream = InStream(Error);
-
- stream: Stream,
- base: *Stream,
-
- const FifoType = std.fifo.LinearFifo(u8, buffer_type);
- fifo: FifoType,
-
- pub usingnamespace switch (buffer_type) {
- .Static => struct {
- pub fn init(base: *Stream) Self {
- return .{
- .base = base,
- .fifo = FifoType.init(),
- .stream = Stream{ .readFn = readFn },
- };
- }
- },
- .Slice => struct {
- pub fn init(base: *Stream, buf: []u8) Self {
- return .{
- .base = base,
- .fifo = FifoType.init(buf),
- .stream = Stream{ .readFn = readFn },
- };
- }
- },
- .Dynamic => struct {
- pub fn init(base: *Stream, allocator: *mem.Allocator) Self {
- return .{
- .base = base,
- .fifo = FifoType.init(allocator),
- .stream = Stream{ .readFn = readFn },
- };
- }
- },
- };
-
- pub fn putBackByte(self: *Self, byte: u8) !void {
- try self.putBack(&[_]u8{byte});
- }
-
- pub fn putBack(self: *Self, bytes: []const u8) !void {
- try self.fifo.unget(bytes);
- }
-
- fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
- const self = @fieldParentPtr(Self, "stream", in_stream);
-
- // copy over anything putBack()'d
- var dest_index = self.fifo.read(dest);
- if (dest_index == dest.len) return dest_index;
-
- // ask the backing stream for more
- dest_index += try self.base.read(dest[dest_index..]);
- return dest_index;
- }
- };
-}
-
-pub const SliceInStream = struct {
- const Self = @This();
- pub const Error = error{};
- pub const Stream = InStream(Error);
-
- stream: Stream,
-
- pos: usize,
- slice: []const u8,
-
- pub fn init(slice: []const u8) Self {
- return Self{
- .slice = slice,
- .pos = 0,
- .stream = Stream{ .readFn = readFn },
- };
- }
-
- fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
- const self = @fieldParentPtr(Self, "stream", in_stream);
- const size = math.min(dest.len, self.slice.len - self.pos);
- const end = self.pos + size;
-
- mem.copy(u8, dest[0..size], self.slice[self.pos..end]);
- self.pos = end;
-
- return size;
- }
-};
-
-/// Creates a stream which allows for reading bit fields from another stream
-pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
- return struct {
- const Self = @This();
-
- in_stream: *Stream,
- bit_buffer: u7,
- bit_count: u3,
- stream: Stream,
-
- pub const Stream = InStream(Error);
- const u8_bit_count = comptime meta.bitCount(u8);
- const u7_bit_count = comptime meta.bitCount(u7);
- const u4_bit_count = comptime meta.bitCount(u4);
-
- pub fn init(in_stream: *Stream) Self {
- return Self{
- .in_stream = in_stream,
- .bit_buffer = 0,
- .bit_count = 0,
- .stream = Stream{ .readFn = read },
- };
- }
-
- /// Reads `bits` bits from the stream and returns a specified unsigned int type
- /// containing them in the least significant end, returning an error if the
- /// specified number of bits could not be read.
- pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U {
- var n: usize = undefined;
- const result = try self.readBits(U, bits, &n);
- if (n < bits) return error.EndOfStream;
- return result;
- }
-
- /// Reads `bits` bits from the stream and returns a specified unsigned int type
- /// containing them in the least significant end. The number of bits successfully
- /// read is placed in `out_bits`, as reaching the end of the stream is not an error.
- pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U {
- comptime assert(trait.isUnsignedInt(U));
-
- //by extending the buffer to a minimum of u8 we can cover a number of edge cases
- // related to shifting and casting.
- const u_bit_count = comptime meta.bitCount(U);
- const buf_bit_count = bc: {
- assert(u_bit_count >= bits);
- break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
- };
- const Buf = std.meta.IntType(false, buf_bit_count);
- const BufShift = math.Log2Int(Buf);
-
- out_bits.* = @as(usize, 0);
- if (U == u0 or bits == 0) return 0;
- var out_buffer = @as(Buf, 0);
-
- if (self.bit_count > 0) {
- const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count;
- const shift = u7_bit_count - n;
- switch (endian) {
- .Big => {
- out_buffer = @as(Buf, self.bit_buffer >> shift);
- self.bit_buffer <<= n;
- },
- .Little => {
- const value = (self.bit_buffer << shift) >> shift;
- out_buffer = @as(Buf, value);
- self.bit_buffer >>= n;
- },
- }
- self.bit_count -= n;
- out_bits.* = n;
- }
- //at this point we know bit_buffer is empty
-
- //copy bytes until we have enough bits, then leave the rest in bit_buffer
- while (out_bits.* < bits) {
- const n = bits - out_bits.*;
- const next_byte = self.in_stream.readByte() catch |err| {
- if (err == error.EndOfStream) {
- return @intCast(U, out_buffer);
- }
- //@BUG: See #1810. Not sure if the bug is that I have to do this for some
- // streams, or that I don't for streams with emtpy errorsets.
- return @errSetCast(Error, err);
- };
-
- switch (endian) {
- .Big => {
- if (n >= u8_bit_count) {
- out_buffer <<= @intCast(u3, u8_bit_count - 1);
- out_buffer <<= 1;
- out_buffer |= @as(Buf, next_byte);
- out_bits.* += u8_bit_count;
- continue;
- }
-
- const shift = @intCast(u3, u8_bit_count - n);
- out_buffer <<= @intCast(BufShift, n);
- out_buffer |= @as(Buf, next_byte >> shift);
- out_bits.* += n;
- self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1));
- self.bit_count = shift;
- },
- .Little => {
- if (n >= u8_bit_count) {
- out_buffer |= @as(Buf, next_byte) << @intCast(BufShift, out_bits.*);
- out_bits.* += u8_bit_count;
- continue;
- }
-
- const shift = @intCast(u3, u8_bit_count - n);
- const value = (next_byte << shift) >> shift;
- out_buffer |= @as(Buf, value) << @intCast(BufShift, out_bits.*);
- out_bits.* += n;
- self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n));
- self.bit_count = shift;
- },
- }
- }
-
- return @intCast(U, out_buffer);
- }
-
- pub fn alignToByte(self: *Self) void {
- self.bit_buffer = 0;
- self.bit_count = 0;
- }
-
- pub fn read(self_stream: *Stream, buffer: []u8) Error!usize {
- var self = @fieldParentPtr(Self, "stream", self_stream);
-
- var out_bits: usize = undefined;
- var out_bits_total = @as(usize, 0);
- //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced
- if (self.bit_count > 0) {
- for (buffer) |*b, i| {
- b.* = try self.readBits(u8, u8_bit_count, &out_bits);
- out_bits_total += out_bits;
- }
- const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0);
- return (out_bits_total / u8_bit_count) + incomplete_byte;
- }
-
- return self.in_stream.read(buffer);
- }
- };
-}
-
/// An OutStream that doesn't write to anything.
pub const null_out_stream = @as(NullOutStream, .{ .context = {} });
@@ -396,472 +145,9 @@ fn dummyWrite(context: void, data: []const u8) error{}!usize {
}
test "null_out_stream" {
- null_out_stream.writeAll("yay" ** 1000) catch |err| switch (err) {};
-}
-
-/// Creates a stream which allows for writing bit fields to another stream
-pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
- return struct {
- const Self = @This();
-
- out_stream: *Stream,
- bit_buffer: u8,
- bit_count: u4,
- stream: Stream,
-
- pub const Stream = OutStream(Error);
- const u8_bit_count = comptime meta.bitCount(u8);
- const u4_bit_count = comptime meta.bitCount(u4);
-
- pub fn init(out_stream: *Stream) Self {
- return Self{
- .out_stream = out_stream,
- .bit_buffer = 0,
- .bit_count = 0,
- .stream = Stream{ .writeFn = write },
- };
- }
-
- /// Write the specified number of bits to the stream from the least significant bits of
- /// the specified unsigned int value. Bits will only be written to the stream when there
- /// are enough to fill a byte.
- pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
- if (bits == 0) return;
-
- const U = @TypeOf(value);
- comptime assert(trait.isUnsignedInt(U));
-
- //by extending the buffer to a minimum of u8 we can cover a number of edge cases
- // related to shifting and casting.
- const u_bit_count = comptime meta.bitCount(U);
- const buf_bit_count = bc: {
- assert(u_bit_count >= bits);
- break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
- };
- const Buf = std.meta.IntType(false, buf_bit_count);
- const BufShift = math.Log2Int(Buf);
-
- const buf_value = @intCast(Buf, value);
-
- const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
- var in_buffer = switch (endian) {
- .Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
- .Little => buf_value,
- };
- var in_bits = bits;
-
- if (self.bit_count > 0) {
- const bits_remaining = u8_bit_count - self.bit_count;
- const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
- switch (endian) {
- .Big => {
- const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
- const v = @intCast(u8, in_buffer >> shift);
- self.bit_buffer |= v;
- in_buffer <<= n;
- },
- .Little => {
- const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
- self.bit_buffer |= v;
- in_buffer >>= n;
- },
- }
- self.bit_count += n;
- in_bits -= n;
-
- //if we didn't fill the buffer, it's because bits < bits_remaining;
- if (self.bit_count != u8_bit_count) return;
- try self.out_stream.writeByte(self.bit_buffer);
- self.bit_buffer = 0;
- self.bit_count = 0;
- }
- //at this point we know bit_buffer is empty
-
- //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
- while (in_bits >= u8_bit_count) {
- switch (endian) {
- .Big => {
- const v = @intCast(u8, in_buffer >> high_byte_shift);
- try self.out_stream.writeByte(v);
- in_buffer <<= @intCast(u3, u8_bit_count - 1);
- in_buffer <<= 1;
- },
- .Little => {
- const v = @truncate(u8, in_buffer);
- try self.out_stream.writeByte(v);
- in_buffer >>= @intCast(u3, u8_bit_count - 1);
- in_buffer >>= 1;
- },
- }
- in_bits -= u8_bit_count;
- }
-
- if (in_bits > 0) {
- self.bit_count = @intCast(u4, in_bits);
- self.bit_buffer = switch (endian) {
- .Big => @truncate(u8, in_buffer >> high_byte_shift),
- .Little => @truncate(u8, in_buffer),
- };
- }
- }
-
- /// Flush any remaining bits to the stream.
- pub fn flushBits(self: *Self) Error!void {
- if (self.bit_count == 0) return;
- try self.out_stream.writeByte(self.bit_buffer);
- self.bit_buffer = 0;
- self.bit_count = 0;
- }
-
- pub fn write(self_stream: *Stream, buffer: []const u8) Error!usize {
- var self = @fieldParentPtr(Self, "stream", self_stream);
-
- // TODO: I'm not sure this is a good idea, maybe flushBits should be forced
- if (self.bit_count > 0) {
- for (buffer) |b, i|
- try self.writeBits(b, u8_bit_count);
- return buffer.len;
- }
-
- return self.out_stream.write(buffer);
- }
- };
-}
-
-pub const Packing = enum {
- /// Pack data to byte alignment
- Byte,
-
- /// Pack data to bit alignment
- Bit,
-};
-
-/// Creates a deserializer that deserializes types from any stream.
-/// If `is_packed` is true, the data stream is treated as bit-packed,
-/// otherwise data is expected to be packed to the smallest byte.
-/// Types may implement a custom deserialization routine with a
-/// function named `deserialize` in the form of:
-/// pub fn deserialize(self: *Self, deserializer: var) !void
-/// which will be called when the deserializer is used to deserialize
-/// that type. It will pass a pointer to the type instance to deserialize
-/// into and a pointer to the deserializer struct.
-pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime Error: type) type {
- return struct {
- const Self = @This();
-
- in_stream: if (packing == .Bit) BitInStream(endian, Stream.Error) else *Stream,
-
- pub const Stream = InStream(Error);
-
- pub fn init(in_stream: *Stream) Self {
- return Self{
- .in_stream = switch (packing) {
- .Bit => BitInStream(endian, Stream.Error).init(in_stream),
- .Byte => in_stream,
- },
- };
- }
-
- pub fn alignToByte(self: *Self) void {
- if (packing == .Byte) return;
- self.in_stream.alignToByte();
- }
-
- //@BUG: inferred error issue. See: #1386
- fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
- comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
-
- const u8_bit_count = 8;
- const t_bit_count = comptime meta.bitCount(T);
-
- const U = std.meta.IntType(false, t_bit_count);
- const Log2U = math.Log2Int(U);
- const int_size = (U.bit_count + 7) / 8;
-
- if (packing == .Bit) {
- const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
- return @bitCast(T, result);
- }
-
- var buffer: [int_size]u8 = undefined;
- const read_size = try self.in_stream.read(buffer[0..]);
- if (read_size < int_size) return error.EndOfStream;
-
- if (int_size == 1) {
- if (t_bit_count == 8) return @bitCast(T, buffer[0]);
- const PossiblySignedByte = std.meta.IntType(T.is_signed, 8);
- return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
- }
-
- var result = @as(U, 0);
- for (buffer) |byte, i| {
- switch (endian) {
- .Big => {
- result = (result << u8_bit_count) | byte;
- },
- .Little => {
- result |= @as(U, byte) << @intCast(Log2U, u8_bit_count * i);
- },
- }
- }
-
- return @bitCast(T, result);
- }
-
- /// Deserializes and returns data of the specified type from the stream
- pub fn deserialize(self: *Self, comptime T: type) !T {
- var value: T = undefined;
- try self.deserializeInto(&value);
- return value;
- }
-
- /// Deserializes data into the type pointed to by `ptr`
- pub fn deserializeInto(self: *Self, ptr: var) !void {
- const T = @TypeOf(ptr);
- comptime assert(trait.is(.Pointer)(T));
-
- if (comptime trait.isSlice(T) or comptime trait.isPtrTo(.Array)(T)) {
- for (ptr) |*v|
- try self.deserializeInto(v);
- return;
- }
-
- comptime assert(trait.isSingleItemPtr(T));
-
- const C = comptime meta.Child(T);
- const child_type_id = @typeInfo(C);
-
- //custom deserializer: fn(self: *Self, deserializer: var) !void
- if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
-
- if (comptime trait.isPacked(C) and packing != .Bit) {
- var packed_deserializer = Deserializer(endian, .Bit, Error).init(self.in_stream);
- return packed_deserializer.deserializeInto(ptr);
- }
-
- switch (child_type_id) {
- .Void => return,
- .Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
- .Float, .Int => ptr.* = try self.deserializeInt(C),
- .Struct => {
- const info = @typeInfo(C).Struct;
-
- inline for (info.fields) |*field_info| {
- const name = field_info.name;
- const FieldType = field_info.field_type;
-
- if (FieldType == void or FieldType == u0) continue;
-
- //it doesn't make any sense to read pointers
- if (comptime trait.is(.Pointer)(FieldType)) {
- @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
- @typeName(C) ++ " because it " ++ "is of pointer-type " ++
- @typeName(FieldType) ++ ".");
- }
-
- try self.deserializeInto(&@field(ptr, name));
- }
- },
- .Union => {
- const info = @typeInfo(C).Union;
- if (info.tag_type) |TagType| {
- //we avoid duplicate iteration over the enum tags
- // by getting the int directly and casting it without
- // safety. If it is bad, it will be caught anyway.
- const TagInt = @TagType(TagType);
- const tag = try self.deserializeInt(TagInt);
-
- inline for (info.fields) |field_info| {
- if (field_info.enum_field.?.value == tag) {
- const name = field_info.name;
- const FieldType = field_info.field_type;
- ptr.* = @unionInit(C, name, undefined);
- try self.deserializeInto(&@field(ptr, name));
- return;
- }
- }
- //This is reachable if the enum data is bad
- return error.InvalidEnumTag;
- }
- @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
- " because it is an untagged union. Use a custom deserialize().");
- },
- .Optional => {
- const OC = comptime meta.Child(C);
- const exists = (try self.deserializeInt(u1)) > 0;
- if (!exists) {
- ptr.* = null;
- return;
- }
-
- ptr.* = @as(OC, undefined); //make it non-null so the following .? is guaranteed safe
- const val_ptr = &ptr.*.?;
- try self.deserializeInto(val_ptr);
- },
- .Enum => {
- var value = try self.deserializeInt(@TagType(C));
- ptr.* = try meta.intToEnum(C, value);
- },
- else => {
- @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented).");
- },
- }
- }
- };
-}
-
-/// Creates a serializer that serializes types to any stream.
-/// If `is_packed` is true, the data will be bit-packed into the stream.
-/// Note that the you must call `serializer.flush()` when you are done
-/// writing bit-packed data in order ensure any unwritten bits are committed.
-/// If `is_packed` is false, data is packed to the smallest byte. In the case
-/// of packed structs, the struct will written bit-packed and with the specified
-/// endianess, after which data will resume being written at the next byte boundary.
-/// Types may implement a custom serialization routine with a
-/// function named `serialize` in the form of:
-/// pub fn serialize(self: Self, serializer: var) !void
-/// which will be called when the serializer is used to serialize that type. It will
-/// pass a const pointer to the type instance to be serialized and a pointer
-/// to the serializer struct.
-pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime Error: type) type {
- return struct {
- const Self = @This();
-
- out_stream: if (packing == .Bit) BitOutStream(endian, Stream.Error) else *Stream,
-
- pub const Stream = OutStream(Error);
-
- pub fn init(out_stream: *Stream) Self {
- return Self{
- .out_stream = switch (packing) {
- .Bit => BitOutStream(endian, Stream.Error).init(out_stream),
- .Byte => out_stream,
- },
- };
- }
-
- /// Flushes any unwritten bits to the stream
- pub fn flush(self: *Self) Error!void {
- if (packing == .Bit) return self.out_stream.flushBits();
- }
-
- fn serializeInt(self: *Self, value: var) Error!void {
- const T = @TypeOf(value);
- comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
-
- const t_bit_count = comptime meta.bitCount(T);
- const u8_bit_count = comptime meta.bitCount(u8);
-
- const U = std.meta.IntType(false, t_bit_count);
- const Log2U = math.Log2Int(U);
- const int_size = (U.bit_count + 7) / 8;
-
- const u_value = @bitCast(U, value);
-
- if (packing == .Bit) return self.out_stream.writeBits(u_value, t_bit_count);
-
- var buffer: [int_size]u8 = undefined;
- if (int_size == 1) buffer[0] = u_value;
-
- for (buffer) |*byte, i| {
- const idx = switch (endian) {
- .Big => int_size - i - 1,
- .Little => i,
- };
- const shift = @intCast(Log2U, idx * u8_bit_count);
- const v = u_value >> shift;
- byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
- }
-
- try self.out_stream.write(&buffer);
- }
-
- /// Serializes the passed value into the stream
- pub fn serialize(self: *Self, value: var) Error!void {
- const T = comptime @TypeOf(value);
-
- if (comptime trait.isIndexable(T)) {
- for (value) |v|
- try self.serialize(v);
- return;
- }
-
- //custom serializer: fn(self: Self, serializer: var) !void
- if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
-
- if (comptime trait.isPacked(T) and packing != .Bit) {
- var packed_serializer = Serializer(endian, .Bit, Error).init(self.out_stream);
- try packed_serializer.serialize(value);
- try packed_serializer.flush();
- return;
- }
-
- switch (@typeInfo(T)) {
- .Void => return,
- .Bool => try self.serializeInt(@as(u1, @boolToInt(value))),
- .Float, .Int => try self.serializeInt(value),
- .Struct => {
- const info = @typeInfo(T);
-
- inline for (info.Struct.fields) |*field_info| {
- const name = field_info.name;
- const FieldType = field_info.field_type;
-
- if (FieldType == void or FieldType == u0) continue;
-
- //It doesn't make sense to write pointers
- if (comptime trait.is(.Pointer)(FieldType)) {
- @compileError("Will not " ++ "serialize field " ++ name ++
- " of struct " ++ @typeName(T) ++ " because it " ++
- "is of pointer-type " ++ @typeName(FieldType) ++ ".");
- }
- try self.serialize(@field(value, name));
- }
- },
- .Union => {
- const info = @typeInfo(T).Union;
- if (info.tag_type) |TagType| {
- const active_tag = meta.activeTag(value);
- try self.serialize(active_tag);
- //This inline loop is necessary because active_tag is a runtime
- // value, but @field requires a comptime value. Our alternative
- // is to check each field for a match
- inline for (info.fields) |field_info| {
- if (field_info.enum_field.?.value == @enumToInt(active_tag)) {
- const name = field_info.name;
- const FieldType = field_info.field_type;
- try self.serialize(@field(value, name));
- return;
- }
- }
- unreachable;
- }
- @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
- " because it is an untagged union. Use a custom serialize().");
- },
- .Optional => {
- if (value == null) {
- try self.serializeInt(@as(u1, @boolToInt(false)));
- return;
- }
- try self.serializeInt(@as(u1, @boolToInt(true)));
-
- const OC = comptime meta.Child(T);
- const val_ptr = &value.?;
- try self.serialize(val_ptr.*);
- },
- .Enum => {
- try self.serializeInt(@enumToInt(value));
- },
- else => @compileError("Cannot serialize " ++ @tagName(@typeInfo(T)) ++ " types (unimplemented)."),
- }
- }
- };
+ null_out_stream.writeAll("yay" ** 10) catch |err| switch (err) {};
}
test "" {
- comptime {
- _ = @import("io/test.zig");
- }
- std.meta.refAllDecls(@This());
+ _ = @import("io/test.zig");
}
diff --git a/lib/std/io/bit_in_stream.zig b/lib/std/io/bit_in_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..876621343365eca35eb94492b37fc7cee6d5d126
--- /dev/null
+++ b/lib/std/io/bit_in_stream.zig
@@ -0,0 +1,237 @@
+const std = @import("../std.zig");
+const builtin = std.builtin;
+const io = std.io;
+const assert = std.debug.assert;
+const testing = std.testing;
+const trait = std.meta.trait;
+const meta = std.meta;
+const math = std.math;
+
+/// Creates a stream which allows for reading bit fields from another stream
+pub fn BitInStream(endian: builtin.Endian, comptime InStreamType: type) type {
+ return struct {
+ in_stream: InStreamType,
+ bit_buffer: u7,
+ bit_count: u3,
+
+ pub const Error = InStreamType.Error;
+ pub const InStream = io.InStream(*Self, Error, read);
+
+ const Self = @This();
+ const u8_bit_count = comptime meta.bitCount(u8);
+ const u7_bit_count = comptime meta.bitCount(u7);
+ const u4_bit_count = comptime meta.bitCount(u4);
+
+ pub fn init(in_stream: InStreamType) Self {
+ return Self{
+ .in_stream = in_stream,
+ .bit_buffer = 0,
+ .bit_count = 0,
+ };
+ }
+
+ /// Reads `bits` bits from the stream and returns a specified unsigned int type
+ /// containing them in the least significant end, returning an error if the
+ /// specified number of bits could not be read.
+ pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U {
+ var n: usize = undefined;
+ const result = try self.readBits(U, bits, &n);
+ if (n < bits) return error.EndOfStream;
+ return result;
+ }
+
+ /// Reads `bits` bits from the stream and returns a specified unsigned int type
+ /// containing them in the least significant end. The number of bits successfully
+ /// read is placed in `out_bits`, as reaching the end of the stream is not an error.
+ pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U {
+ comptime assert(trait.isUnsignedInt(U));
+
+ //by extending the buffer to a minimum of u8 we can cover a number of edge cases
+ // related to shifting and casting.
+ const u_bit_count = comptime meta.bitCount(U);
+ const buf_bit_count = bc: {
+ assert(u_bit_count >= bits);
+ break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
+ };
+ const Buf = std.meta.IntType(false, buf_bit_count);
+ const BufShift = math.Log2Int(Buf);
+
+ out_bits.* = @as(usize, 0);
+ if (U == u0 or bits == 0) return 0;
+ var out_buffer = @as(Buf, 0);
+
+ if (self.bit_count > 0) {
+ const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count;
+ const shift = u7_bit_count - n;
+ switch (endian) {
+ .Big => {
+ out_buffer = @as(Buf, self.bit_buffer >> shift);
+ self.bit_buffer <<= n;
+ },
+ .Little => {
+ const value = (self.bit_buffer << shift) >> shift;
+ out_buffer = @as(Buf, value);
+ self.bit_buffer >>= n;
+ },
+ }
+ self.bit_count -= n;
+ out_bits.* = n;
+ }
+ //at this point we know bit_buffer is empty
+
+ //copy bytes until we have enough bits, then leave the rest in bit_buffer
+ while (out_bits.* < bits) {
+ const n = bits - out_bits.*;
+ const next_byte = self.in_stream.readByte() catch |err| {
+ if (err == error.EndOfStream) {
+ return @intCast(U, out_buffer);
+ }
+ //@BUG: See #1810. Not sure if the bug is that I have to do this for some
+ // streams, or that I don't for streams with emtpy errorsets.
+ return @errSetCast(Error, err);
+ };
+
+ switch (endian) {
+ .Big => {
+ if (n >= u8_bit_count) {
+ out_buffer <<= @intCast(u3, u8_bit_count - 1);
+ out_buffer <<= 1;
+ out_buffer |= @as(Buf, next_byte);
+ out_bits.* += u8_bit_count;
+ continue;
+ }
+
+ const shift = @intCast(u3, u8_bit_count - n);
+ out_buffer <<= @intCast(BufShift, n);
+ out_buffer |= @as(Buf, next_byte >> shift);
+ out_bits.* += n;
+ self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1));
+ self.bit_count = shift;
+ },
+ .Little => {
+ if (n >= u8_bit_count) {
+ out_buffer |= @as(Buf, next_byte) << @intCast(BufShift, out_bits.*);
+ out_bits.* += u8_bit_count;
+ continue;
+ }
+
+ const shift = @intCast(u3, u8_bit_count - n);
+ const value = (next_byte << shift) >> shift;
+ out_buffer |= @as(Buf, value) << @intCast(BufShift, out_bits.*);
+ out_bits.* += n;
+ self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n));
+ self.bit_count = shift;
+ },
+ }
+ }
+
+ return @intCast(U, out_buffer);
+ }
+
+ pub fn alignToByte(self: *Self) void {
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+
+ pub fn read(self: *Self, buffer: []u8) Error!usize {
+ var out_bits: usize = undefined;
+ var out_bits_total = @as(usize, 0);
+ //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced
+ if (self.bit_count > 0) {
+ for (buffer) |*b, i| {
+ b.* = try self.readBits(u8, u8_bit_count, &out_bits);
+ out_bits_total += out_bits;
+ }
+ const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0);
+ return (out_bits_total / u8_bit_count) + incomplete_byte;
+ }
+
+ return self.in_stream.read(buffer);
+ }
+
+ pub fn inStream(self: *Self) InStream {
+ return .{ .context = self };
+ }
+ };
+}
+
+pub fn bitInStream(
+ comptime endian: builtin.Endian,
+ underlying_stream: var,
+) BitInStream(endian, @TypeOf(underlying_stream)) {
+ return BitInStream(endian, @TypeOf(underlying_stream)).init(underlying_stream);
+}
+
+test "api coverage" {
+ const mem_be = [_]u8{ 0b11001101, 0b00001011 };
+ const mem_le = [_]u8{ 0b00011101, 0b10010101 };
+
+ var mem_in_be = io.fixedBufferStream(&mem_be);
+ var bit_stream_be = bitInStream(.Big, mem_in_be.inStream());
+
+ var out_bits: usize = undefined;
+
+ const expect = testing.expect;
+ const expectError = testing.expectError;
+
+ expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
+ expect(out_bits == 1);
+ expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
+ expect(out_bits == 2);
+ expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
+ expect(out_bits == 3);
+ expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
+ expect(out_bits == 4);
+ expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
+ expect(out_bits == 5);
+ expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
+ expect(out_bits == 1);
+
+ mem_in_be.pos = 0;
+ bit_stream_be.bit_count = 0;
+ expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
+ expect(out_bits == 15);
+
+ mem_in_be.pos = 0;
+ bit_stream_be.bit_count = 0;
+ expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
+ expect(out_bits == 16);
+
+ _ = try bit_stream_be.readBits(u0, 0, &out_bits);
+
+ expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
+ expect(out_bits == 0);
+ expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
+
+ var mem_in_le = io.fixedBufferStream(&mem_le);
+ var bit_stream_le = bitInStream(.Little, mem_in_le.inStream());
+
+ expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
+ expect(out_bits == 1);
+ expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
+ expect(out_bits == 2);
+ expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
+ expect(out_bits == 3);
+ expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
+ expect(out_bits == 4);
+ expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
+ expect(out_bits == 5);
+ expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
+ expect(out_bits == 1);
+
+ mem_in_le.pos = 0;
+ bit_stream_le.bit_count = 0;
+ expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
+ expect(out_bits == 15);
+
+ mem_in_le.pos = 0;
+ bit_stream_le.bit_count = 0;
+ expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
+ expect(out_bits == 16);
+
+ _ = try bit_stream_le.readBits(u0, 0, &out_bits);
+
+ expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
+ expect(out_bits == 0);
+ expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
+}
diff --git a/lib/std/io/bit_out_stream.zig b/lib/std/io/bit_out_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..1a2bb62e7cd86e78784eb9026558e88a189975c9
--- /dev/null
+++ b/lib/std/io/bit_out_stream.zig
@@ -0,0 +1,197 @@
+const std = @import("../std.zig");
+const builtin = std.builtin;
+const io = std.io;
+const testing = std.testing;
+const assert = std.debug.assert;
+const trait = std.meta.trait;
+const meta = std.meta;
+const math = std.math;
+
+/// Creates a stream which allows for writing bit fields to another stream
+pub fn BitOutStream(endian: builtin.Endian, comptime OutStreamType: type) type {
+ return struct {
+ out_stream: OutStreamType,
+ bit_buffer: u8,
+ bit_count: u4,
+
+ pub const Error = OutStreamType.Error;
+ pub const OutStream = io.OutStream(*Self, Error, write);
+
+ const Self = @This();
+ const u8_bit_count = comptime meta.bitCount(u8);
+ const u4_bit_count = comptime meta.bitCount(u4);
+
+ pub fn init(out_stream: OutStreamType) Self {
+ return Self{
+ .out_stream = out_stream,
+ .bit_buffer = 0,
+ .bit_count = 0,
+ };
+ }
+
+ /// Write the specified number of bits to the stream from the least significant bits of
+ /// the specified unsigned int value. Bits will only be written to the stream when there
+ /// are enough to fill a byte.
+ pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
+ if (bits == 0) return;
+
+ const U = @TypeOf(value);
+ comptime assert(trait.isUnsignedInt(U));
+
+ //by extending the buffer to a minimum of u8 we can cover a number of edge cases
+ // related to shifting and casting.
+ const u_bit_count = comptime meta.bitCount(U);
+ const buf_bit_count = bc: {
+ assert(u_bit_count >= bits);
+ break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
+ };
+ const Buf = std.meta.IntType(false, buf_bit_count);
+ const BufShift = math.Log2Int(Buf);
+
+ const buf_value = @intCast(Buf, value);
+
+ const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
+ var in_buffer = switch (endian) {
+ .Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
+ .Little => buf_value,
+ };
+ var in_bits = bits;
+
+ if (self.bit_count > 0) {
+ const bits_remaining = u8_bit_count - self.bit_count;
+ const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
+ switch (endian) {
+ .Big => {
+ const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
+ const v = @intCast(u8, in_buffer >> shift);
+ self.bit_buffer |= v;
+ in_buffer <<= n;
+ },
+ .Little => {
+ const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
+ self.bit_buffer |= v;
+ in_buffer >>= n;
+ },
+ }
+ self.bit_count += n;
+ in_bits -= n;
+
+ //if we didn't fill the buffer, it's because bits < bits_remaining;
+ if (self.bit_count != u8_bit_count) return;
+ try self.out_stream.writeByte(self.bit_buffer);
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+ //at this point we know bit_buffer is empty
+
+ //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
+ while (in_bits >= u8_bit_count) {
+ switch (endian) {
+ .Big => {
+ const v = @intCast(u8, in_buffer >> high_byte_shift);
+ try self.out_stream.writeByte(v);
+ in_buffer <<= @intCast(u3, u8_bit_count - 1);
+ in_buffer <<= 1;
+ },
+ .Little => {
+ const v = @truncate(u8, in_buffer);
+ try self.out_stream.writeByte(v);
+ in_buffer >>= @intCast(u3, u8_bit_count - 1);
+ in_buffer >>= 1;
+ },
+ }
+ in_bits -= u8_bit_count;
+ }
+
+ if (in_bits > 0) {
+ self.bit_count = @intCast(u4, in_bits);
+ self.bit_buffer = switch (endian) {
+ .Big => @truncate(u8, in_buffer >> high_byte_shift),
+ .Little => @truncate(u8, in_buffer),
+ };
+ }
+ }
+
+ /// Flush any remaining bits to the stream.
+ pub fn flushBits(self: *Self) Error!void {
+ if (self.bit_count == 0) return;
+ try self.out_stream.writeByte(self.bit_buffer);
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+
+ pub fn write(self: *Self, buffer: []const u8) Error!usize {
+ // TODO: I'm not sure this is a good idea, maybe flushBits should be forced
+ if (self.bit_count > 0) {
+ for (buffer) |b, i|
+ try self.writeBits(b, u8_bit_count);
+ return buffer.len;
+ }
+
+ return self.out_stream.write(buffer);
+ }
+
+ pub fn outStream(self: *Self) OutStream {
+ return .{ .context = self };
+ }
+ };
+}
+
+pub fn bitOutStream(
+ comptime endian: builtin.Endian,
+ underlying_stream: var,
+) BitOutStream(endian, @TypeOf(underlying_stream)) {
+ return BitOutStream(endian, @TypeOf(underlying_stream)).init(underlying_stream);
+}
+
+test "api coverage" {
+ var mem_be = [_]u8{0} ** 2;
+ var mem_le = [_]u8{0} ** 2;
+
+ var mem_out_be = io.fixedBufferStream(&mem_be);
+ var bit_stream_be = bitOutStream(.Big, mem_out_be.outStream());
+
+ try bit_stream_be.writeBits(@as(u2, 1), 1);
+ try bit_stream_be.writeBits(@as(u5, 2), 2);
+ try bit_stream_be.writeBits(@as(u128, 3), 3);
+ try bit_stream_be.writeBits(@as(u8, 4), 4);
+ try bit_stream_be.writeBits(@as(u9, 5), 5);
+ try bit_stream_be.writeBits(@as(u1, 1), 1);
+
+ testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
+
+ mem_out_be.pos = 0;
+
+ try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15);
+ try bit_stream_be.flushBits();
+ testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
+
+ mem_out_be.pos = 0;
+ try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16);
+ testing.expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
+
+ try bit_stream_be.writeBits(@as(u0, 0), 0);
+
+ var mem_out_le = io.fixedBufferStream(&mem_le);
+ var bit_stream_le = bitOutStream(.Little, mem_out_le.outStream());
+
+ try bit_stream_le.writeBits(@as(u2, 1), 1);
+ try bit_stream_le.writeBits(@as(u5, 2), 2);
+ try bit_stream_le.writeBits(@as(u128, 3), 3);
+ try bit_stream_le.writeBits(@as(u8, 4), 4);
+ try bit_stream_le.writeBits(@as(u9, 5), 5);
+ try bit_stream_le.writeBits(@as(u1, 1), 1);
+
+ testing.expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
+
+ mem_out_le.pos = 0;
+ try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15);
+ try bit_stream_le.flushBits();
+ testing.expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
+
+ mem_out_le.pos = 0;
+ try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16);
+ testing.expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
+
+ try bit_stream_le.writeBits(@as(u0, 0), 0);
+}
diff --git a/lib/std/io/buffered_in_stream.zig b/lib/std/io/buffered_in_stream.zig
index 72f1b30b76a2fb80dcdc1b31afed73627403d820..7f76c8c576ee4acc1813eabd325811896fdf6a6c 100644
--- a/lib/std/io/buffered_in_stream.zig
+++ b/lib/std/io/buffered_in_stream.zig
@@ -1,7 +1,9 @@
const std = @import("../std.zig");
const io = std.io;
+const assert = std.debug.assert;
+const testing = std.testing;
-pub fn BufferedInStream(comptime buffer_size: usize, comptime InStreamType) type {
+pub fn BufferedInStream(comptime buffer_size: usize, comptime InStreamType: type) type {
return struct {
unbuffered_in_stream: InStreamType,
fifo: FifoType = FifoType.init(),
diff --git a/lib/std/io/c_out_stream.zig b/lib/std/io/c_out_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..106fc601a2c3b439a9f9db05b1809b6f4f097057
--- /dev/null
+++ b/lib/std/io/c_out_stream.zig
@@ -0,0 +1,44 @@
+const std = @import("../std.zig");
+const builtin = std.builtin;
+const io = std.io;
+const testing = std.testing;
+
+pub const COutStream = io.OutStream(*std.c.FILE, std.fs.File.WriteError, cOutStreamWrite);
+
+pub fn cOutStream(c_file: *std.c.FILE) COutStream {
+ return .{ .context = c_file };
+}
+
+fn cOutStreamWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!usize {
+ const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, c_file);
+ if (amt_written >= 0) return amt_written;
+ switch (std.c._errno().*) {
+ 0 => unreachable,
+ os.EINVAL => unreachable,
+ os.EFAULT => unreachable,
+ os.EAGAIN => unreachable, // this is a blocking API
+ os.EBADF => unreachable, // always a race condition
+ os.EDESTADDRREQ => unreachable, // connect was never called
+ os.EDQUOT => return error.DiskQuota,
+ os.EFBIG => return error.FileTooBig,
+ os.EIO => return error.InputOutput,
+ os.ENOSPC => return error.NoSpaceLeft,
+ os.EPERM => return error.AccessDenied,
+ os.EPIPE => return error.BrokenPipe,
+ else => |err| return os.unexpectedErrno(@intCast(usize, err)),
+ }
+}
+
+test "" {
+ if (!builtin.link_libc) return error.SkipZigTest;
+
+ const filename = "tmp_io_test_file.txt";
+ const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
+ defer {
+ _ = std.c.fclose(out_file);
+ fs.cwd().deleteFileC(filename) catch {};
+ }
+
+ const out_stream = &io.COutStream.init(out_file).stream;
+ try out_stream.print("hi: {}\n", .{@as(i32, 123)});
+}
diff --git a/lib/std/io/counting_out_stream.zig b/lib/std/io/counting_out_stream.zig
index 2b0cba29fc6c2dce185a7e510a2555a5c3ae4658..f5bd6634f3e05c41e4ac721764200ed2836c02fd 100644
--- a/lib/std/io/counting_out_stream.zig
+++ b/lib/std/io/counting_out_stream.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
const io = std.io;
+const testing = std.testing;
/// An OutStream that counts how many bytes has been written to it.
pub fn CountingOutStream(comptime OutStreamType: type) type {
@@ -12,13 +13,6 @@ pub fn CountingOutStream(comptime OutStreamType: type) type {
const Self = @This();
- pub fn init(child_stream: OutStreamType) Self {
- return Self{
- .bytes_written = 0,
- .child_stream = child_stream,
- };
- }
-
pub fn write(self: *Self, bytes: []const u8) Error!usize {
const amt = try self.child_stream.write(bytes);
self.bytes_written += amt;
@@ -31,12 +25,15 @@ pub fn CountingOutStream(comptime OutStreamType: type) type {
};
}
+pub fn countingOutStream(child_stream: var) CountingOutStream(@TypeOf(child_stream)) {
+ return .{ .bytes_written = 0, .child_stream = child_stream };
+}
+
test "io.CountingOutStream" {
- var counting_stream = CountingOutStream(NullOutStream.Error).init(std.io.null_out_stream);
- const stream = &counting_stream.stream;
+ var counting_stream = countingOutStream(std.io.null_out_stream);
+ const stream = counting_stream.outStream();
- const bytes = "yay" ** 10000;
- stream.write(bytes) catch unreachable;
+ const bytes = "yay" ** 100;
+ stream.writeAll(bytes) catch unreachable;
testing.expect(counting_stream.bytes_written == bytes.len);
}
-
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index 75a337d3de4b111544fe94facac2cda786541a07..9cdad7dc577e3fefec2141258dccf449415aa05d 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -1,9 +1,11 @@
const std = @import("../std.zig");
const io = std.io;
const testing = std.testing;
+const mem = std.mem;
+const assert = std.debug.assert;
-/// This turns a slice into an `io.OutStream`, `io.InStream`, or `io.SeekableStream`.
-/// If the supplied slice is const, then `io.OutStream` is not available.
+/// This turns a byte buffer into an `io.OutStream`, `io.InStream`, or `io.SeekableStream`.
+/// If the supplied byte buffer is const, then `io.OutStream` is not available.
pub fn FixedBufferStream(comptime Buffer: type) type {
return struct {
/// `Buffer` is either a `[]u8` or `[]const u8`.
@@ -46,7 +48,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
const size = std.math.min(dest.len, self.buffer.len - self.pos);
const end = self.pos + size;
- std.mem.copy(u8, dest[0..size], self.buffer[self.pos..end]);
+ mem.copy(u8, dest[0..size], self.buffer[self.pos..end]);
self.pos = end;
if (size == 0) return error.EndOfStream;
@@ -65,7 +67,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
else
self.buffer.len - self.pos;
- std.mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]);
+ mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]);
self.pos += n;
if (n == 0) return error.OutOfMemory;
@@ -100,7 +102,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
}
pub fn getWritten(self: Self) []const u8 {
- return self.slice[0..self.pos];
+ return self.buffer[0..self.pos];
}
pub fn reset(self: *Self) void {
@@ -110,16 +112,16 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
}
pub fn fixedBufferStream(buffer: var) FixedBufferStream(NonSentinelSpan(@TypeOf(buffer))) {
- return .{ .buffer = std.mem.span(buffer), .pos = 0 };
+ return .{ .buffer = mem.span(buffer), .pos = 0 };
}
fn NonSentinelSpan(comptime T: type) type {
- var ptr_info = @typeInfo(std.mem.Span(T)).Pointer;
+ var ptr_info = @typeInfo(mem.Span(T)).Pointer;
ptr_info.sentinel = null;
return @Type(std.builtin.TypeInfo{ .Pointer = ptr_info });
}
-test "FixedBufferStream" {
+test "FixedBufferStream output" {
var buf: [255]u8 = undefined;
var fbs = fixedBufferStream(&buf);
const stream = fbs.outStream();
@@ -127,3 +129,41 @@ test "FixedBufferStream" {
try stream.print("{}{}!", .{ "Hello", "World" });
testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
}
+
+test "FixedBufferStream output 2" {
+ var buffer: [10]u8 = undefined;
+ var fbs = fixedBufferStream(&buffer);
+
+ try fbs.outStream().writeAll("Hello");
+ testing.expect(mem.eql(u8, fbs.getWritten(), "Hello"));
+
+ try fbs.outStream().writeAll("world");
+ testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
+
+ testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("!"));
+ testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
+
+ fbs.reset();
+ testing.expect(fbs.getWritten().len == 0);
+
+ testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("Hello world!"));
+ testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl"));
+}
+
+test "FixedBufferStream input" {
+ const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7 };
+ var fbs = fixedBufferStream(&bytes);
+
+ var dest: [4]u8 = undefined;
+
+ var read = try fbs.inStream().read(dest[0..4]);
+ testing.expect(read == 4);
+ testing.expect(mem.eql(u8, dest[0..4], bytes[0..4]));
+
+ read = try fbs.inStream().read(dest[0..4]);
+ testing.expect(read == 3);
+ testing.expect(mem.eql(u8, dest[0..3], bytes[4..7]));
+
+ read = try fbs.inStream().read(dest[0..4]);
+ testing.expect(read == 0);
+}
diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig
index d181f4df433d9a78fc638bf510b529ad478c91a6..2830582482809bee439b560ef56b747b0504edee 100644
--- a/lib/std/io/in_stream.zig
+++ b/lib/std/io/in_stream.zig
@@ -273,8 +273,7 @@ pub fn InStream(
test "InStream" {
var buf = "a\x02".*;
- var slice_stream = std.io.SliceInStream.init(&buf);
- const in_stream = &slice_stream.stream;
+ const in_stream = std.io.fixedBufferStream(&buf).inStream();
testing.expect((try in_stream.readByte()) == 'a');
testing.expect((try in_stream.readEnum(enum(u8) {
a = 0,
diff --git a/lib/std/io/peek_stream.zig b/lib/std/io/peek_stream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..5ee30ce273e1413d46ef0242a5ac71e177aec6b6
--- /dev/null
+++ b/lib/std/io/peek_stream.zig
@@ -0,0 +1,112 @@
+const std = @import("../std.zig");
+const io = std.io;
+const mem = std.mem;
+const testing = std.testing;
+
+/// Creates a stream which supports 'un-reading' data, so that it can be read again.
+/// This makes look-ahead style parsing much easier.
+/// TODO merge this with `std.io.BufferedInStream`: https://github.com/ziglang/zig/issues/4501
+pub fn PeekStream(
+ comptime buffer_type: std.fifo.LinearFifoBufferType,
+ comptime InStreamType: type,
+) type {
+ return struct {
+ unbuffered_in_stream: InStreamType,
+ fifo: FifoType,
+
+ pub const Error = InStreamType.Error;
+ pub const InStream = io.InStream(*Self, Error, read);
+
+ const Self = @This();
+ const FifoType = std.fifo.LinearFifo(u8, buffer_type);
+
+ pub usingnamespace switch (buffer_type) {
+ .Static => struct {
+ pub fn init(base: InStreamType) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(),
+ };
+ }
+ },
+ .Slice => struct {
+ pub fn init(base: InStreamType, buf: []u8) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(buf),
+ };
+ }
+ },
+ .Dynamic => struct {
+ pub fn init(base: InStreamType, allocator: *mem.Allocator) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(allocator),
+ };
+ }
+ },
+ };
+
+ pub fn putBackByte(self: *Self, byte: u8) !void {
+ try self.putBack(&[_]u8{byte});
+ }
+
+ pub fn putBack(self: *Self, bytes: []const u8) !void {
+ try self.fifo.unget(bytes);
+ }
+
+ pub fn read(self: *Self, dest: []u8) Error!usize {
+ // copy over anything putBack()'d
+ var dest_index = self.fifo.read(dest);
+ if (dest_index == dest.len) return dest_index;
+
+ // ask the backing stream for more
+ dest_index += try self.base.read(dest[dest_index..]);
+ return dest_index;
+ }
+
+ pub fn inStream(self: *Self) InStream {
+ return .{ .context = self };
+ }
+ };
+}
+
+pub fn peekStream(
+ comptime lookahead: comptime_int,
+ underlying_stream: var,
+) PeekStream(.{ .Static = lookahead }, @TypeOf(underlying_stream)) {
+ return PeekStream(.{ .Static = lookahead }, @TypeOf(underlying_stream)).init(underlying_stream);
+}
+
+test "PeekStream" {
+ const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
+ var fbs = io.fixedBufferStream(&bytes);
+ var ps = peekStream(2, fbs.inStream());
+
+ var dest: [4]u8 = undefined;
+
+ try ps.putBackByte(9);
+ try ps.putBackByte(10);
+
+ var read = try ps.inStream().read(dest[0..4]);
+ testing.expect(read == 4);
+ testing.expect(dest[0] == 10);
+ testing.expect(dest[1] == 9);
+ testing.expect(mem.eql(u8, dest[2..4], bytes[0..2]));
+
+ read = try ps.inStream().read(dest[0..4]);
+ testing.expect(read == 4);
+ testing.expect(mem.eql(u8, dest[0..4], bytes[2..6]));
+
+ read = try ps.inStream().read(dest[0..4]);
+ testing.expect(read == 2);
+ testing.expect(mem.eql(u8, dest[0..2], bytes[6..8]));
+
+ try ps.putBackByte(11);
+ try ps.putBackByte(12);
+
+ read = try ps.inStream().read(dest[0..4]);
+ testing.expect(read == 2);
+ testing.expect(dest[0] == 12);
+ testing.expect(dest[1] == 11);
+}
diff --git a/lib/std/io/serialization.zig b/lib/std/io/serialization.zig
new file mode 100644
index 0000000000000000000000000000000000000000..4aa462aab89b09f2dd0da6382a907298b6f17617
--- /dev/null
+++ b/lib/std/io/serialization.zig
@@ -0,0 +1,606 @@
+const std = @import("../std.zig");
+const builtin = std.builtin;
+const io = std.io;
+
+pub const Packing = enum {
+ /// Pack data to byte alignment
+ Byte,
+
+ /// Pack data to bit alignment
+ Bit,
+};
+
+/// Creates a deserializer that deserializes types from any stream.
+/// If `is_packed` is true, the data stream is treated as bit-packed,
+/// otherwise data is expected to be packed to the smallest byte.
+/// Types may implement a custom deserialization routine with a
+/// function named `deserialize` in the form of:
+/// pub fn deserialize(self: *Self, deserializer: var) !void
+/// which will be called when the deserializer is used to deserialize
+/// that type. It will pass a pointer to the type instance to deserialize
+/// into and a pointer to the deserializer struct.
+pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime InStreamType: type) type {
+ return struct {
+ in_stream: if (packing == .Bit) io.BitInStream(endian, InStreamType) else InStreamType,
+
+ const Self = @This();
+
+ pub fn init(in_stream: InStreamType) Self {
+ return Self{
+ .in_stream = switch (packing) {
+ .Bit => io.bitInStream(endian, in_stream),
+ .Byte => in_stream,
+ },
+ };
+ }
+
+ pub fn alignToByte(self: *Self) void {
+ if (packing == .Byte) return;
+ self.in_stream.alignToByte();
+ }
+
+ //@BUG: inferred error issue. See: #1386
+ fn deserializeInt(self: *Self, comptime T: type) (InStreamType.Error || error{EndOfStream})!T {
+ comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
+
+ const u8_bit_count = 8;
+ const t_bit_count = comptime meta.bitCount(T);
+
+ const U = std.meta.IntType(false, t_bit_count);
+ const Log2U = math.Log2Int(U);
+ const int_size = (U.bit_count + 7) / 8;
+
+ if (packing == .Bit) {
+ const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
+ return @bitCast(T, result);
+ }
+
+ var buffer: [int_size]u8 = undefined;
+ const read_size = try self.in_stream.read(buffer[0..]);
+ if (read_size < int_size) return error.EndOfStream;
+
+ if (int_size == 1) {
+ if (t_bit_count == 8) return @bitCast(T, buffer[0]);
+ const PossiblySignedByte = std.meta.IntType(T.is_signed, 8);
+ return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
+ }
+
+ var result = @as(U, 0);
+ for (buffer) |byte, i| {
+ switch (endian) {
+ .Big => {
+ result = (result << u8_bit_count) | byte;
+ },
+ .Little => {
+ result |= @as(U, byte) << @intCast(Log2U, u8_bit_count * i);
+ },
+ }
+ }
+
+ return @bitCast(T, result);
+ }
+
+ /// Deserializes and returns data of the specified type from the stream
+ pub fn deserialize(self: *Self, comptime T: type) !T {
+ var value: T = undefined;
+ try self.deserializeInto(&value);
+ return value;
+ }
+
+ /// Deserializes data into the type pointed to by `ptr`
+ pub fn deserializeInto(self: *Self, ptr: var) !void {
+ const T = @TypeOf(ptr);
+ comptime assert(trait.is(.Pointer)(T));
+
+ if (comptime trait.isSlice(T) or comptime trait.isPtrTo(.Array)(T)) {
+ for (ptr) |*v|
+ try self.deserializeInto(v);
+ return;
+ }
+
+ comptime assert(trait.isSingleItemPtr(T));
+
+ const C = comptime meta.Child(T);
+ const child_type_id = @typeInfo(C);
+
+ //custom deserializer: fn(self: *Self, deserializer: var) !void
+ if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
+
+ if (comptime trait.isPacked(C) and packing != .Bit) {
+ var packed_deserializer = deserializer(endian, .Bit, self.in_stream);
+ return packed_deserializer.deserializeInto(ptr);
+ }
+
+ switch (child_type_id) {
+ .Void => return,
+ .Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
+ .Float, .Int => ptr.* = try self.deserializeInt(C),
+ .Struct => {
+ const info = @typeInfo(C).Struct;
+
+ inline for (info.fields) |*field_info| {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+
+ if (FieldType == void or FieldType == u0) continue;
+
+ //it doesn't make any sense to read pointers
+ if (comptime trait.is(.Pointer)(FieldType)) {
+ @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
+ @typeName(C) ++ " because it " ++ "is of pointer-type " ++
+ @typeName(FieldType) ++ ".");
+ }
+
+ try self.deserializeInto(&@field(ptr, name));
+ }
+ },
+ .Union => {
+ const info = @typeInfo(C).Union;
+ if (info.tag_type) |TagType| {
+ //we avoid duplicate iteration over the enum tags
+ // by getting the int directly and casting it without
+ // safety. If it is bad, it will be caught anyway.
+ const TagInt = @TagType(TagType);
+ const tag = try self.deserializeInt(TagInt);
+
+ inline for (info.fields) |field_info| {
+ if (field_info.enum_field.?.value == tag) {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+ ptr.* = @unionInit(C, name, undefined);
+ try self.deserializeInto(&@field(ptr, name));
+ return;
+ }
+ }
+ //This is reachable if the enum data is bad
+ return error.InvalidEnumTag;
+ }
+ @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
+ " because it is an untagged union. Use a custom deserialize().");
+ },
+ .Optional => {
+ const OC = comptime meta.Child(C);
+ const exists = (try self.deserializeInt(u1)) > 0;
+ if (!exists) {
+ ptr.* = null;
+ return;
+ }
+
+ ptr.* = @as(OC, undefined); //make it non-null so the following .? is guaranteed safe
+ const val_ptr = &ptr.*.?;
+ try self.deserializeInto(val_ptr);
+ },
+ .Enum => {
+ var value = try self.deserializeInt(@TagType(C));
+ ptr.* = try meta.intToEnum(C, value);
+ },
+ else => {
+ @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented).");
+ },
+ }
+ }
+ };
+}
+
+pub fn deserializer(
+ comptime endian: builtin.Endian,
+ comptime packing: Packing,
+ in_stream: var,
+) Deserializer(endian, packing, @TypeOf(in_stream)) {
+ return Deserializer(endian, packing, @TypeOf(in_stream)).init(in_stream);
+}
+
+/// Creates a serializer that serializes types to any stream.
+/// If `is_packed` is true, the data will be bit-packed into the stream.
+/// Note that the you must call `serializer.flush()` when you are done
+/// writing bit-packed data in order ensure any unwritten bits are committed.
+/// If `is_packed` is false, data is packed to the smallest byte. In the case
+/// of packed structs, the struct will written bit-packed and with the specified
+/// endianess, after which data will resume being written at the next byte boundary.
+/// Types may implement a custom serialization routine with a
+/// function named `serialize` in the form of:
+/// pub fn serialize(self: Self, serializer: var) !void
+/// which will be called when the serializer is used to serialize that type. It will
+/// pass a const pointer to the type instance to be serialized and a pointer
+/// to the serializer struct.
+pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime OutStreamType: type) type {
+ return struct {
+ out_stream: if (packing == .Bit) BitOutStream(endian, OutStreamType) else OutStreamType,
+
+ const Self = @This();
+ pub const Error = OutStreamType.Error;
+
+ pub fn init(out_stream: OutStreamType) Self {
+ return Self{
+ .out_stream = switch (packing) {
+ .Bit => io.bitOutStream(endian, out_stream),
+ .Byte => out_stream,
+ },
+ };
+ }
+
+ /// Flushes any unwritten bits to the stream
+ pub fn flush(self: *Self) Error!void {
+ if (packing == .Bit) return self.out_stream.flushBits();
+ }
+
+ fn serializeInt(self: *Self, value: var) Error!void {
+ const T = @TypeOf(value);
+ comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
+
+ const t_bit_count = comptime meta.bitCount(T);
+ const u8_bit_count = comptime meta.bitCount(u8);
+
+ const U = std.meta.IntType(false, t_bit_count);
+ const Log2U = math.Log2Int(U);
+ const int_size = (U.bit_count + 7) / 8;
+
+ const u_value = @bitCast(U, value);
+
+ if (packing == .Bit) return self.out_stream.writeBits(u_value, t_bit_count);
+
+ var buffer: [int_size]u8 = undefined;
+ if (int_size == 1) buffer[0] = u_value;
+
+ for (buffer) |*byte, i| {
+ const idx = switch (endian) {
+ .Big => int_size - i - 1,
+ .Little => i,
+ };
+ const shift = @intCast(Log2U, idx * u8_bit_count);
+ const v = u_value >> shift;
+ byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
+ }
+
+ try self.out_stream.write(&buffer);
+ }
+
+ /// Serializes the passed value into the stream
+ pub fn serialize(self: *Self, value: var) Error!void {
+ const T = comptime @TypeOf(value);
+
+ if (comptime trait.isIndexable(T)) {
+ for (value) |v|
+ try self.serialize(v);
+ return;
+ }
+
+ //custom serializer: fn(self: Self, serializer: var) !void
+ if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
+
+ if (comptime trait.isPacked(T) and packing != .Bit) {
+ var packed_serializer = Serializer(endian, .Bit, Error).init(self.out_stream);
+ try packed_serializer.serialize(value);
+ try packed_serializer.flush();
+ return;
+ }
+
+ switch (@typeInfo(T)) {
+ .Void => return,
+ .Bool => try self.serializeInt(@as(u1, @boolToInt(value))),
+ .Float, .Int => try self.serializeInt(value),
+ .Struct => {
+ const info = @typeInfo(T);
+
+ inline for (info.Struct.fields) |*field_info| {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+
+ if (FieldType == void or FieldType == u0) continue;
+
+ //It doesn't make sense to write pointers
+ if (comptime trait.is(.Pointer)(FieldType)) {
+ @compileError("Will not " ++ "serialize field " ++ name ++
+ " of struct " ++ @typeName(T) ++ " because it " ++
+ "is of pointer-type " ++ @typeName(FieldType) ++ ".");
+ }
+ try self.serialize(@field(value, name));
+ }
+ },
+ .Union => {
+ const info = @typeInfo(T).Union;
+ if (info.tag_type) |TagType| {
+ const active_tag = meta.activeTag(value);
+ try self.serialize(active_tag);
+ //This inline loop is necessary because active_tag is a runtime
+ // value, but @field requires a comptime value. Our alternative
+ // is to check each field for a match
+ inline for (info.fields) |field_info| {
+ if (field_info.enum_field.?.value == @enumToInt(active_tag)) {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+ try self.serialize(@field(value, name));
+ return;
+ }
+ }
+ unreachable;
+ }
+ @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
+ " because it is an untagged union. Use a custom serialize().");
+ },
+ .Optional => {
+ if (value == null) {
+ try self.serializeInt(@as(u1, @boolToInt(false)));
+ return;
+ }
+ try self.serializeInt(@as(u1, @boolToInt(true)));
+
+ const OC = comptime meta.Child(T);
+ const val_ptr = &value.?;
+ try self.serialize(val_ptr.*);
+ },
+ .Enum => {
+ try self.serializeInt(@enumToInt(value));
+ },
+ else => @compileError("Cannot serialize " ++ @tagName(@typeInfo(T)) ++ " types (unimplemented)."),
+ }
+ }
+ };
+}
+
+pub fn serializer(
+ comptime endian: builtin.Endian,
+ comptime packing: Packing,
+ out_stream: var,
+) Serializer(endian, packing, @TypeOf(out_stream)) {
+ return Serializer(endian, packing, @TypeOf(out_stream)).init(out_stream);
+}
+
+fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
+ @setEvalBranchQuota(1500);
+ //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
+ const max_test_bitsize = 128;
+
+ const total_bytes = comptime blk: {
+ var bytes = 0;
+ comptime var i = 0;
+ while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
+ break :blk bytes * 2;
+ };
+
+ var data_mem: [total_bytes]u8 = undefined;
+ var out = io.fixedBufferStream(&data_mem);
+ var serializer = serializer(endian, packing, out.outStream());
+
+ var in = io.fixedBufferStream(&data_mem);
+ var deserializer = Deserializer(endian, packing, in.inStream());
+
+ comptime var i = 0;
+ inline while (i <= max_test_bitsize) : (i += 1) {
+ const U = std.meta.IntType(false, i);
+ const S = std.meta.IntType(true, i);
+ try serializer.serializeInt(@as(U, i));
+ if (i != 0) try serializer.serializeInt(@as(S, -1)) else try serializer.serialize(@as(S, 0));
+ }
+ try serializer.flush();
+
+ i = 0;
+ inline while (i <= max_test_bitsize) : (i += 1) {
+ const U = std.meta.IntType(false, i);
+ const S = std.meta.IntType(true, i);
+ const x = try deserializer.deserializeInt(U);
+ const y = try deserializer.deserializeInt(S);
+ expect(x == @as(U, i));
+ if (i != 0) expect(y == @as(S, -1)) else expect(y == 0);
+ }
+
+ const u8_bit_count = comptime meta.bitCount(u8);
+ //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
+ //and we have each for unsigned and signed, so * 2
+ const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
+ const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
+ const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
+
+ expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
+
+ //Verify that empty error set works with serializer.
+ //deserializer is covered by FixedBufferStream
+ var null_serializer = io.serializer(endian, packing, std.io.null_out_stream);
+ try null_serializer.serialize(data_mem[0..]);
+ try null_serializer.flush();
+}
+
+test "Serializer/Deserializer Int" {
+ try testIntSerializerDeserializer(.Big, .Byte);
+ try testIntSerializerDeserializer(.Little, .Byte);
+ // TODO these tests are disabled due to tripping an LLVM assertion
+ // https://github.com/ziglang/zig/issues/2019
+ //try testIntSerializerDeserializer(builtin.Endian.Big, true);
+ //try testIntSerializerDeserializer(builtin.Endian.Little, true);
+}
+
+fn testIntSerializerDeserializerInfNaN(
+ comptime endian: builtin.Endian,
+ comptime packing: io.Packing,
+) !void {
+ const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
+ var data_mem: [mem_size]u8 = undefined;
+
+ var out = io.fixedBufferStream(&data_mem);
+ var serializer = serializer(endian, packing, out.outStream());
+
+ var in = io.fixedBufferStream(&data_mem);
+ var deserializer = deserializer(endian, packing, in.inStream());
+
+ //@TODO: isInf/isNan not currently implemented for f128.
+ try serializer.serialize(std.math.nan(f16));
+ try serializer.serialize(std.math.inf(f16));
+ try serializer.serialize(std.math.nan(f32));
+ try serializer.serialize(std.math.inf(f32));
+ try serializer.serialize(std.math.nan(f64));
+ try serializer.serialize(std.math.inf(f64));
+ //try serializer.serialize(std.math.nan(f128));
+ //try serializer.serialize(std.math.inf(f128));
+ const nan_check_f16 = try deserializer.deserialize(f16);
+ const inf_check_f16 = try deserializer.deserialize(f16);
+ const nan_check_f32 = try deserializer.deserialize(f32);
+ deserializer.alignToByte();
+ const inf_check_f32 = try deserializer.deserialize(f32);
+ const nan_check_f64 = try deserializer.deserialize(f64);
+ const inf_check_f64 = try deserializer.deserialize(f64);
+ //const nan_check_f128 = try deserializer.deserialize(f128);
+ //const inf_check_f128 = try deserializer.deserialize(f128);
+ expect(std.math.isNan(nan_check_f16));
+ expect(std.math.isInf(inf_check_f16));
+ expect(std.math.isNan(nan_check_f32));
+ expect(std.math.isInf(inf_check_f32));
+ expect(std.math.isNan(nan_check_f64));
+ expect(std.math.isInf(inf_check_f64));
+ //expect(std.math.isNan(nan_check_f128));
+ //expect(std.math.isInf(inf_check_f128));
+}
+
+test "Serializer/Deserializer Int: Inf/NaN" {
+ try testIntSerializerDeserializerInfNaN(.Big, .Byte);
+ try testIntSerializerDeserializerInfNaN(.Little, .Byte);
+ try testIntSerializerDeserializerInfNaN(.Big, .Bit);
+ try testIntSerializerDeserializerInfNaN(.Little, .Bit);
+}
+
+fn testAlternateSerializer(self: var, serializer: var) !void {
+ try serializer.serialize(self.f_f16);
+}
+
+fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
+ const ColorType = enum(u4) {
+ RGB8 = 1,
+ RA16 = 2,
+ R32 = 3,
+ };
+
+ const TagAlign = union(enum(u32)) {
+ A: u8,
+ B: u8,
+ C: u8,
+ };
+
+ const Color = union(ColorType) {
+ RGB8: struct {
+ r: u8,
+ g: u8,
+ b: u8,
+ a: u8,
+ },
+ RA16: struct {
+ r: u16,
+ a: u16,
+ },
+ R32: u32,
+ };
+
+ const PackedStruct = packed struct {
+ f_i3: i3,
+ f_u2: u2,
+ };
+
+ //to test custom serialization
+ const Custom = struct {
+ f_f16: f16,
+ f_unused_u32: u32,
+
+ pub fn deserialize(self: *@This(), deserializer: var) !void {
+ try deserializer.deserializeInto(&self.f_f16);
+ self.f_unused_u32 = 47;
+ }
+
+ pub const serialize = testAlternateSerializer;
+ };
+
+ const MyStruct = struct {
+ f_i3: i3,
+ f_u8: u8,
+ f_tag_align: TagAlign,
+ f_u24: u24,
+ f_i19: i19,
+ f_void: void,
+ f_f32: f32,
+ f_f128: f128,
+ f_packed_0: PackedStruct,
+ f_i7arr: [10]i7,
+ f_of64n: ?f64,
+ f_of64v: ?f64,
+ f_color_type: ColorType,
+ f_packed_1: PackedStruct,
+ f_custom: Custom,
+ f_color: Color,
+ };
+
+ const my_inst = MyStruct{
+ .f_i3 = -1,
+ .f_u8 = 8,
+ .f_tag_align = TagAlign{ .B = 148 },
+ .f_u24 = 24,
+ .f_i19 = 19,
+ .f_void = {},
+ .f_f32 = 32.32,
+ .f_f128 = 128.128,
+ .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
+ .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ .f_of64n = null,
+ .f_of64v = 64.64,
+ .f_color_type = ColorType.R32,
+ .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
+ .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
+ .f_color = Color{ .R32 = 123822 },
+ };
+
+ var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
+ var out = io.fixedBufferStream(&data_mem);
+ var serializer = serializer(endian, packing, out.outStream());
+
+ var in = io.fixedBufferStream(&data_mem);
+ var deserializer = deserializer(endian, packing, in.inStream());
+
+ try serializer.serialize(my_inst);
+
+ const my_copy = try deserializer.deserialize(MyStruct);
+ expect(meta.eql(my_copy, my_inst));
+}
+
+test "Serializer/Deserializer generic" {
+ if (std.Target.current.os.tag == .windows) {
+ // TODO https://github.com/ziglang/zig/issues/508
+ return error.SkipZigTest;
+ }
+ try testSerializerDeserializer(builtin.Endian.Big, .Byte);
+ try testSerializerDeserializer(builtin.Endian.Little, .Byte);
+ try testSerializerDeserializer(builtin.Endian.Big, .Bit);
+ try testSerializerDeserializer(builtin.Endian.Little, .Bit);
+}
+
+fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
+ const E = enum(u14) {
+ One = 1,
+ Two = 2,
+ };
+
+ const A = struct {
+ e: E,
+ };
+
+ const C = union(E) {
+ One: u14,
+ Two: f16,
+ };
+
+ var data_mem: [4]u8 = undefined;
+ var out = io.fixedBufferStream.init(&data_mem);
+ var serializer = serializer(endian, packing, out.outStream());
+
+ var in = io.fixedBufferStream(&data_mem);
+ var deserializer = deserializer(endian, packing, in.inStream());
+
+ try serializer.serialize(@as(u14, 3));
+ expectError(error.InvalidEnumTag, deserializer.deserialize(A));
+ out.pos = 0;
+ try serializer.serialize(@as(u14, 3));
+ try serializer.serialize(@as(u14, 88));
+ expectError(error.InvalidEnumTag, deserializer.deserialize(C));
+}
+
+test "Deserializer bad data" {
+ try testBadData(.Big, .Byte);
+ try testBadData(.Little, .Byte);
+ try testBadData(.Big, .Bit);
+ try testBadData(.Little, .Bit);
+}
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
index 1ab0f82313b9c90eed943d73d4b3227396efafc0..38dd2bb67a82adb019beea50f122c169dc173e26 100644
--- a/lib/std/io/test.zig
+++ b/lib/std/io/test.zig
@@ -22,11 +22,10 @@ test "write a file, read it, then delete it" {
var file = try cwd.createFile(tmp_file_name, .{});
defer file.close();
- var file_out_stream = file.outStream();
- var buf_stream = io.BufferedOutStream(File.WriteError).init(&file_out_stream.stream);
- const st = &buf_stream.stream;
+ var buf_stream = io.bufferedOutStream(file.outStream());
+ const st = buf_stream.outStream();
try st.print("begin", .{});
- try st.write(data[0..]);
+ try st.writeAll(data[0..]);
try st.print("end", .{});
try buf_stream.flush();
}
@@ -48,9 +47,8 @@ test "write a file, read it, then delete it" {
const expected_file_size: u64 = "begin".len + data.len + "end".len;
expectEqual(expected_file_size, file_size);
- var file_in_stream = file.inStream();
- var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream);
- const st = &buf_stream.stream;
+ var buf_stream = io.bufferedInStream(file.inStream());
+ const st = buf_stream.inStream();
const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);
defer std.testing.allocator.free(contents);
@@ -61,224 +59,13 @@ test "write a file, read it, then delete it" {
try cwd.deleteFile(tmp_file_name);
}
-test "BufferOutStream" {
- var buffer = try std.Buffer.initSize(std.testing.allocator, 0);
- defer buffer.deinit();
- var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
-
- const x: i32 = 42;
- const y: i32 = 1234;
- try buf_stream.print("x: {}\ny: {}\n", .{ x, y });
-
- expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
-}
-
-test "SliceInStream" {
- const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7 };
- var ss = io.SliceInStream.init(&bytes);
-
- var dest: [4]u8 = undefined;
-
- var read = try ss.stream.read(dest[0..4]);
- expect(read == 4);
- expect(mem.eql(u8, dest[0..4], bytes[0..4]));
-
- read = try ss.stream.read(dest[0..4]);
- expect(read == 3);
- expect(mem.eql(u8, dest[0..3], bytes[4..7]));
-
- read = try ss.stream.read(dest[0..4]);
- expect(read == 0);
-}
-
-test "PeekStream" {
- const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
- var ss = io.SliceInStream.init(&bytes);
- var ps = io.PeekStream(.{ .Static = 2 }, io.SliceInStream.Error).init(&ss.stream);
-
- var dest: [4]u8 = undefined;
-
- try ps.putBackByte(9);
- try ps.putBackByte(10);
-
- var read = try ps.stream.read(dest[0..4]);
- expect(read == 4);
- expect(dest[0] == 10);
- expect(dest[1] == 9);
- expect(mem.eql(u8, dest[2..4], bytes[0..2]));
-
- read = try ps.stream.read(dest[0..4]);
- expect(read == 4);
- expect(mem.eql(u8, dest[0..4], bytes[2..6]));
-
- read = try ps.stream.read(dest[0..4]);
- expect(read == 2);
- expect(mem.eql(u8, dest[0..2], bytes[6..8]));
-
- try ps.putBackByte(11);
- try ps.putBackByte(12);
-
- read = try ps.stream.read(dest[0..4]);
- expect(read == 2);
- expect(dest[0] == 12);
- expect(dest[1] == 11);
-}
-
-test "SliceOutStream" {
- var buffer: [10]u8 = undefined;
- var ss = io.SliceOutStream.init(buffer[0..]);
-
- try ss.stream.write("Hello");
- expect(mem.eql(u8, ss.getWritten(), "Hello"));
-
- try ss.stream.write("world");
- expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
-
- expectError(error.OutOfMemory, ss.stream.write("!"));
- expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
-
- ss.reset();
- expect(ss.getWritten().len == 0);
-
- expectError(error.OutOfMemory, ss.stream.write("Hello world!"));
- expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
-}
-
-test "BitInStream" {
- const mem_be = [_]u8{ 0b11001101, 0b00001011 };
- const mem_le = [_]u8{ 0b00011101, 0b10010101 };
-
- var mem_in_be = io.SliceInStream.init(mem_be[0..]);
- const InError = io.SliceInStream.Error;
- var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
-
- var out_bits: usize = undefined;
-
- expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
- expect(out_bits == 1);
- expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
- expect(out_bits == 2);
- expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
- expect(out_bits == 3);
- expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
- expect(out_bits == 4);
- expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
- expect(out_bits == 5);
- expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
- expect(out_bits == 1);
-
- mem_in_be.pos = 0;
- bit_stream_be.bit_count = 0;
- expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
- expect(out_bits == 15);
-
- mem_in_be.pos = 0;
- bit_stream_be.bit_count = 0;
- expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
- expect(out_bits == 16);
-
- _ = try bit_stream_be.readBits(u0, 0, &out_bits);
-
- expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
- expect(out_bits == 0);
- expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
-
- var mem_in_le = io.SliceInStream.init(mem_le[0..]);
- var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
-
- expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
- expect(out_bits == 1);
- expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
- expect(out_bits == 2);
- expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
- expect(out_bits == 3);
- expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
- expect(out_bits == 4);
- expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
- expect(out_bits == 5);
- expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
- expect(out_bits == 1);
-
- mem_in_le.pos = 0;
- bit_stream_le.bit_count = 0;
- expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
- expect(out_bits == 15);
-
- mem_in_le.pos = 0;
- bit_stream_le.bit_count = 0;
- expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
- expect(out_bits == 16);
-
- _ = try bit_stream_le.readBits(u0, 0, &out_bits);
-
- expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
- expect(out_bits == 0);
- expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
-}
-
-test "BitOutStream" {
- var mem_be = [_]u8{0} ** 2;
- var mem_le = [_]u8{0} ** 2;
-
- var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
- const OutError = io.SliceOutStream.Error;
- var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
-
- try bit_stream_be.writeBits(@as(u2, 1), 1);
- try bit_stream_be.writeBits(@as(u5, 2), 2);
- try bit_stream_be.writeBits(@as(u128, 3), 3);
- try bit_stream_be.writeBits(@as(u8, 4), 4);
- try bit_stream_be.writeBits(@as(u9, 5), 5);
- try bit_stream_be.writeBits(@as(u1, 1), 1);
-
- expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
-
- mem_out_be.pos = 0;
-
- try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15);
- try bit_stream_be.flushBits();
- expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
-
- mem_out_be.pos = 0;
- try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16);
- expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
-
- try bit_stream_be.writeBits(@as(u0, 0), 0);
-
- var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
- var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
-
- try bit_stream_le.writeBits(@as(u2, 1), 1);
- try bit_stream_le.writeBits(@as(u5, 2), 2);
- try bit_stream_le.writeBits(@as(u128, 3), 3);
- try bit_stream_le.writeBits(@as(u8, 4), 4);
- try bit_stream_le.writeBits(@as(u9, 5), 5);
- try bit_stream_le.writeBits(@as(u1, 1), 1);
-
- expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
-
- mem_out_le.pos = 0;
- try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15);
- try bit_stream_le.flushBits();
- expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
-
- mem_out_le.pos = 0;
- try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16);
- expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
-
- try bit_stream_le.writeBits(@as(u0, 0), 0);
-}
-
test "BitStreams with File Stream" {
const tmp_file_name = "temp_test_file.txt";
{
var file = try fs.cwd().createFile(tmp_file_name, .{});
defer file.close();
- var file_out = file.outStream();
- var file_out_stream = &file_out.stream;
- const OutError = File.WriteError;
- var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
+ var bit_stream = io.bitOutStream(builtin.endian, file.outStream());
try bit_stream.writeBits(@as(u2, 1), 1);
try bit_stream.writeBits(@as(u5, 2), 2);
@@ -292,10 +79,7 @@ test "BitStreams with File Stream" {
var file = try fs.cwd().openFile(tmp_file_name, .{});
defer file.close();
- var file_in = file.inStream();
- var file_in_stream = &file_in.stream;
- const InError = File.ReadError;
- var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
+ var bit_stream = io.bitInStream(builtin.endian, file.inStream());
var out_bits: usize = undefined;
@@ -317,298 +101,6 @@ test "BitStreams with File Stream" {
try fs.cwd().deleteFile(tmp_file_name);
}
-fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
- @setEvalBranchQuota(1500);
- //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
- const max_test_bitsize = 128;
-
- const total_bytes = comptime blk: {
- var bytes = 0;
- comptime var i = 0;
- while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
- break :blk bytes * 2;
- };
-
- var data_mem: [total_bytes]u8 = undefined;
- var out = io.SliceOutStream.init(data_mem[0..]);
- const OutError = io.SliceOutStream.Error;
- var out_stream = &out.stream;
- var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
-
- var in = io.SliceInStream.init(data_mem[0..]);
- const InError = io.SliceInStream.Error;
- var in_stream = &in.stream;
- var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
-
- comptime var i = 0;
- inline while (i <= max_test_bitsize) : (i += 1) {
- const U = std.meta.IntType(false, i);
- const S = std.meta.IntType(true, i);
- try serializer.serializeInt(@as(U, i));
- if (i != 0) try serializer.serializeInt(@as(S, -1)) else try serializer.serialize(@as(S, 0));
- }
- try serializer.flush();
-
- i = 0;
- inline while (i <= max_test_bitsize) : (i += 1) {
- const U = std.meta.IntType(false, i);
- const S = std.meta.IntType(true, i);
- const x = try deserializer.deserializeInt(U);
- const y = try deserializer.deserializeInt(S);
- expect(x == @as(U, i));
- if (i != 0) expect(y == @as(S, -1)) else expect(y == 0);
- }
-
- const u8_bit_count = comptime meta.bitCount(u8);
- //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
- //and we have each for unsigned and signed, so * 2
- const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
- const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
- const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
-
- expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
-
- //Verify that empty error set works with serializer.
- //deserializer is covered by SliceInStream
- const NullError = io.NullOutStream.Error;
- var null_out = io.NullOutStream.init();
- var null_out_stream = &null_out.stream;
- var null_serializer = io.Serializer(endian, packing, NullError).init(null_out_stream);
- try null_serializer.serialize(data_mem[0..]);
- try null_serializer.flush();
-}
-
-test "Serializer/Deserializer Int" {
- try testIntSerializerDeserializer(.Big, .Byte);
- try testIntSerializerDeserializer(.Little, .Byte);
- // TODO these tests are disabled due to tripping an LLVM assertion
- // https://github.com/ziglang/zig/issues/2019
- //try testIntSerializerDeserializer(builtin.Endian.Big, true);
- //try testIntSerializerDeserializer(builtin.Endian.Little, true);
-}
-
-fn testIntSerializerDeserializerInfNaN(
- comptime endian: builtin.Endian,
- comptime packing: io.Packing,
-) !void {
- const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
- var data_mem: [mem_size]u8 = undefined;
-
- var out = io.SliceOutStream.init(data_mem[0..]);
- const OutError = io.SliceOutStream.Error;
- var out_stream = &out.stream;
- var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
-
- var in = io.SliceInStream.init(data_mem[0..]);
- const InError = io.SliceInStream.Error;
- var in_stream = &in.stream;
- var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
-
- //@TODO: isInf/isNan not currently implemented for f128.
- try serializer.serialize(std.math.nan(f16));
- try serializer.serialize(std.math.inf(f16));
- try serializer.serialize(std.math.nan(f32));
- try serializer.serialize(std.math.inf(f32));
- try serializer.serialize(std.math.nan(f64));
- try serializer.serialize(std.math.inf(f64));
- //try serializer.serialize(std.math.nan(f128));
- //try serializer.serialize(std.math.inf(f128));
- const nan_check_f16 = try deserializer.deserialize(f16);
- const inf_check_f16 = try deserializer.deserialize(f16);
- const nan_check_f32 = try deserializer.deserialize(f32);
- deserializer.alignToByte();
- const inf_check_f32 = try deserializer.deserialize(f32);
- const nan_check_f64 = try deserializer.deserialize(f64);
- const inf_check_f64 = try deserializer.deserialize(f64);
- //const nan_check_f128 = try deserializer.deserialize(f128);
- //const inf_check_f128 = try deserializer.deserialize(f128);
- expect(std.math.isNan(nan_check_f16));
- expect(std.math.isInf(inf_check_f16));
- expect(std.math.isNan(nan_check_f32));
- expect(std.math.isInf(inf_check_f32));
- expect(std.math.isNan(nan_check_f64));
- expect(std.math.isInf(inf_check_f64));
- //expect(std.math.isNan(nan_check_f128));
- //expect(std.math.isInf(inf_check_f128));
-}
-
-test "Serializer/Deserializer Int: Inf/NaN" {
- try testIntSerializerDeserializerInfNaN(.Big, .Byte);
- try testIntSerializerDeserializerInfNaN(.Little, .Byte);
- try testIntSerializerDeserializerInfNaN(.Big, .Bit);
- try testIntSerializerDeserializerInfNaN(.Little, .Bit);
-}
-
-fn testAlternateSerializer(self: var, serializer: var) !void {
- try serializer.serialize(self.f_f16);
-}
-
-fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
- const ColorType = enum(u4) {
- RGB8 = 1,
- RA16 = 2,
- R32 = 3,
- };
-
- const TagAlign = union(enum(u32)) {
- A: u8,
- B: u8,
- C: u8,
- };
-
- const Color = union(ColorType) {
- RGB8: struct {
- r: u8,
- g: u8,
- b: u8,
- a: u8,
- },
- RA16: struct {
- r: u16,
- a: u16,
- },
- R32: u32,
- };
-
- const PackedStruct = packed struct {
- f_i3: i3,
- f_u2: u2,
- };
-
- //to test custom serialization
- const Custom = struct {
- f_f16: f16,
- f_unused_u32: u32,
-
- pub fn deserialize(self: *@This(), deserializer: var) !void {
- try deserializer.deserializeInto(&self.f_f16);
- self.f_unused_u32 = 47;
- }
-
- pub const serialize = testAlternateSerializer;
- };
-
- const MyStruct = struct {
- f_i3: i3,
- f_u8: u8,
- f_tag_align: TagAlign,
- f_u24: u24,
- f_i19: i19,
- f_void: void,
- f_f32: f32,
- f_f128: f128,
- f_packed_0: PackedStruct,
- f_i7arr: [10]i7,
- f_of64n: ?f64,
- f_of64v: ?f64,
- f_color_type: ColorType,
- f_packed_1: PackedStruct,
- f_custom: Custom,
- f_color: Color,
- };
-
- const my_inst = MyStruct{
- .f_i3 = -1,
- .f_u8 = 8,
- .f_tag_align = TagAlign{ .B = 148 },
- .f_u24 = 24,
- .f_i19 = 19,
- .f_void = {},
- .f_f32 = 32.32,
- .f_f128 = 128.128,
- .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
- .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
- .f_of64n = null,
- .f_of64v = 64.64,
- .f_color_type = ColorType.R32,
- .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
- .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
- .f_color = Color{ .R32 = 123822 },
- };
-
- var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
- var out = io.SliceOutStream.init(data_mem[0..]);
- const OutError = io.SliceOutStream.Error;
- var out_stream = &out.stream;
- var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
-
- var in = io.SliceInStream.init(data_mem[0..]);
- const InError = io.SliceInStream.Error;
- var in_stream = &in.stream;
- var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
-
- try serializer.serialize(my_inst);
-
- const my_copy = try deserializer.deserialize(MyStruct);
- expect(meta.eql(my_copy, my_inst));
-}
-
-test "Serializer/Deserializer generic" {
- if (std.Target.current.os.tag == .windows) {
- // TODO https://github.com/ziglang/zig/issues/508
- return error.SkipZigTest;
- }
- try testSerializerDeserializer(builtin.Endian.Big, .Byte);
- try testSerializerDeserializer(builtin.Endian.Little, .Byte);
- try testSerializerDeserializer(builtin.Endian.Big, .Bit);
- try testSerializerDeserializer(builtin.Endian.Little, .Bit);
-}
-
-fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
- const E = enum(u14) {
- One = 1,
- Two = 2,
- };
-
- const A = struct {
- e: E,
- };
-
- const C = union(E) {
- One: u14,
- Two: f16,
- };
-
- var data_mem: [4]u8 = undefined;
- var out = io.SliceOutStream.init(data_mem[0..]);
- const OutError = io.SliceOutStream.Error;
- var out_stream = &out.stream;
- var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
-
- var in = io.SliceInStream.init(data_mem[0..]);
- const InError = io.SliceInStream.Error;
- var in_stream = &in.stream;
- var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
-
- try serializer.serialize(@as(u14, 3));
- expectError(error.InvalidEnumTag, deserializer.deserialize(A));
- out.pos = 0;
- try serializer.serialize(@as(u14, 3));
- try serializer.serialize(@as(u14, 88));
- expectError(error.InvalidEnumTag, deserializer.deserialize(C));
-}
-
-test "Deserializer bad data" {
- try testBadData(.Big, .Byte);
- try testBadData(.Little, .Byte);
- try testBadData(.Big, .Bit);
- try testBadData(.Little, .Bit);
-}
-
-test "c out stream" {
- if (!builtin.link_libc) return error.SkipZigTest;
-
- const filename = "tmp_io_test_file.txt";
- const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
- defer {
- _ = std.c.fclose(out_file);
- fs.cwd().deleteFileC(filename) catch {};
- }
-
- const out_stream = &io.COutStream.init(out_file).stream;
- try out_stream.print("hi: {}\n", .{@as(i32, 123)});
-}
-
test "File seek ops" {
const tmp_file_name = "temp_test_file.txt";
var file = try fs.cwd().createFile(tmp_file_name, .{});
@@ -621,16 +113,16 @@ test "File seek ops" {
// Seek to the end
try file.seekFromEnd(0);
- std.testing.expect((try file.getPos()) == try file.getEndPos());
+ expect((try file.getPos()) == try file.getEndPos());
// Negative delta
try file.seekBy(-4096);
- std.testing.expect((try file.getPos()) == 4096);
+ expect((try file.getPos()) == 4096);
// Positive delta
try file.seekBy(10);
- std.testing.expect((try file.getPos()) == 4106);
+ expect((try file.getPos()) == 4106);
// Absolute position
try file.seekTo(1234);
- std.testing.expect((try file.getPos()) == 1234);
+ expect((try file.getPos()) == 1234);
}
test "updateTimes" {
@@ -647,6 +139,6 @@ test "updateTimes" {
stat_old.mtime - 5 * std.time.ns_per_s,
);
var stat_new = try file.stat();
- std.testing.expect(stat_new.atime < stat_old.atime);
- std.testing.expect(stat_new.mtime < stat_old.mtime);
+ expect(stat_new.atime < stat_old.atime);
+ expect(stat_new.mtime < stat_old.mtime);
}
diff --git a/lib/std/json.zig b/lib/std/json.zig
index f2cf68d7eb2079cf17b117aea87866dea590606e..4e2440d4e9b50212a2c5539f3148b65de2db12ed 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -10,6 +10,7 @@ const mem = std.mem;
const maxInt = std.math.maxInt;
pub const WriteStream = @import("json/write_stream.zig").WriteStream;
+pub const writeStream = @import("json/write_stream.zig").writeStream;
const StringEscapes = union(enum) {
None,
@@ -2109,7 +2110,7 @@ test "write json then parse it" {
var fixed_buffer_stream = std.io.fixedBufferStream(&out_buffer);
const out_stream = fixed_buffer_stream.outStream();
- var jw = WriteStream(@TypeOf(out_stream).Child, 4).init(out_stream);
+ var jw = writeStream(out_stream, 4);
try jw.beginObject();
@@ -2140,7 +2141,7 @@ test "write json then parse it" {
var parser = Parser.init(testing.allocator, false);
defer parser.deinit();
- var tree = try parser.parse(slice_out_stream.getWritten());
+ var tree = try parser.parse(fixed_buffer_stream.getWritten());
defer tree.deinit();
testing.expect(tree.root.Object.get("f").?.value.Bool == false);
diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig
index 6d88c8b6da6691335f5abe0943d9c5df2f487719..f4d171011c5c88590eaccbec63f5722137f0b404 100644
--- a/lib/std/json/write_stream.zig
+++ b/lib/std/json/write_stream.zig
@@ -249,15 +249,22 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
};
}
+pub fn writeStream(
+ out_stream: var,
+ comptime max_depth: usize,
+) WriteStream(@TypeOf(out_stream), max_depth) {
+ return WriteStream(@TypeOf(out_stream), max_depth).init(out_stream);
+}
+
test "json write stream" {
var out_buf: [1024]u8 = undefined;
- var slice_stream = std.io.SliceOutStream.init(&out_buf);
- const out = &slice_stream.stream;
+ var slice_stream = std.io.fixedBufferStream(&out_buf);
+ const out = slice_stream.outStream();
var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena_allocator.deinit();
- var w = std.json.WriteStream(@TypeOf(out).Child, 10).init(out);
+ var w = std.json.writeStream(out, 10);
try w.emitJson(try getJson(&arena_allocator.allocator));
const result = slice_stream.getWritten();
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 6d0daefdc0b67e90571dfe363b1203ae2c461c9c..de10a17640c23841d501e2b83db09a13f6d2bd58 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -816,7 +816,7 @@ fn linuxLookupNameFromHosts(
};
defer file.close();
- const stream = &std.io.BufferedInStream(fs.File.ReadError).init(&file.inStream().stream).stream;
+ const stream = std.io.bufferedInStream(file.inStream()).inStream();
var line_buf: [512]u8 = undefined;
while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
error.StreamTooLong => blk: {
@@ -1010,7 +1010,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
};
defer file.close();
- const stream = &std.io.BufferedInStream(fs.File.ReadError).init(&file.inStream().stream).stream;
+ const stream = std.io.bufferedInStream(file.inStream()).inStream();
var line_buf: [512]u8 = undefined;
while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
error.StreamTooLong => blk: {
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index 5f97597537963210d75a16879d1d2ddb880b8b92..75a6d5db919a19bf2b3d79e90bd6ff03b11810f9 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -354,8 +354,7 @@ test "mmap" {
const file = try fs.cwd().createFile(test_out_file, .{});
defer file.close();
- var out_stream = file.outStream();
- const stream = &out_stream.stream;
+ const stream = file.outStream();
var i: u32 = 0;
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
@@ -378,8 +377,8 @@ test "mmap" {
);
defer os.munmap(data);
- var mem_stream = io.SliceInStream.init(data);
- const stream = &mem_stream.stream;
+ var mem_stream = io.fixedBufferStream(data);
+ const stream = mem_stream.inStream();
var i: u32 = 0;
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
@@ -402,8 +401,8 @@ test "mmap" {
);
defer os.munmap(data);
- var mem_stream = io.SliceInStream.init(data);
- const stream = &mem_stream.stream;
+ var mem_stream = io.fixedBufferStream(data);
+ const stream = mem_stream.inStream();
var i: u32 = alloc_size / 2 / @sizeOf(u32);
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index ddea0fc57c55adff55785e0add4ccff4db2bad10..d00568e49f92a9139d923eeb2c2b377606252566 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -2809,7 +2809,7 @@ const maxInt = std.math.maxInt;
var fixed_buffer_mem: [100 * 1024]u8 = undefined;
fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *bool) ![]u8 {
- const stderr = &io.getStdErr().outStream().stream;
+ const stderr = io.getStdErr().outStream();
const tree = try std.zig.parse(allocator, source);
defer tree.deinit();
@@ -2824,17 +2824,17 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
{
var i: usize = 0;
while (i < loc.column) : (i += 1) {
- try stderr.write(" ");
+ try stderr.writeAll(" ");
}
}
{
const caret_count = token.end - token.start;
var i: usize = 0;
while (i < caret_count) : (i += 1) {
- try stderr.write("~");
+ try stderr.writeAll("~");
}
}
- try stderr.write("\n");
+ try stderr.writeAll("\n");
}
if (tree.errors.len != 0) {
return error.ParseError;
@@ -2843,8 +2843,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
var buffer = try std.Buffer.initSize(allocator, 0);
errdefer buffer.deinit();
- var buffer_out_stream = io.BufferOutStream.init(&buffer);
- anything_changed.* = try std.zig.render(allocator, &buffer_out_stream.stream, tree);
+ anything_changed.* = try std.zig.render(allocator, buffer.outStream(), tree);
return buffer.toOwnedSlice();
}
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index 9600de21df40f88e7b7933d7cba2fafd83ef94a6..1a221bd5b3619fd182bcd7f501e1e25ce051d2a9 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -903,7 +903,7 @@ fn renderExpression(
var column_widths = widths[widths.len - row_size ..];
// Null stream for counting the printed length of each expression
- var counting_stream = std.io.CountingOutStream(@TypeOf(std.io.null_out_stream)).init(std.io.null_out_stream);
+ var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
var it = exprs.iterator(0);
var i: usize = 0;
--
2.54.0
From 2f1052a313cb09f87f04cef56805c33be62eb169 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 10 Mar 2020 23:50:04 +0100
Subject: [PATCH 044/111] std: Fix broken tests
---
lib/std/io.zig | 10 ++++++++--
lib/std/mem.zig | 8 +++++++-
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/lib/std/io.zig b/lib/std/io.zig
index 99e9391f1d47e0c5ab6dd2d3940200f66542ad71..f823eb8115e5344efb3d3eb8a1cc3623831f2d51 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -350,12 +350,18 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
switch (endian) {
.Big => {
out_buffer = @as(Buf, self.bit_buffer >> shift);
- self.bit_buffer <<= n;
+ if (n >= u7_bit_count)
+ self.bit_buffer = 0
+ else
+ self.bit_buffer <<= n;
},
.Little => {
const value = (self.bit_buffer << shift) >> shift;
out_buffer = @as(Buf, value);
- self.bit_buffer >>= n;
+ if (n >= u7_bit_count)
+ self.bit_buffer = 0
+ else
+ self.bit_buffer >>= n;
},
}
self.bit_count -= n;
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 4da78295702d4adf673a794b2265d838259bb76f..bee38a30f6a09dbbcd2e3bfa4bfb5c8059997af6 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -921,6 +921,9 @@ pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value:
pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
assert(buffer.len >= @divExact(T.bit_count, 8));
+ if (T.bit_count == 0)
+ return set(u8, buffer, 0);
+
// TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
const uint = std.meta.IntType(false, T.bit_count);
var bits = @truncate(uint, value);
@@ -938,6 +941,9 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
assert(buffer.len >= @divExact(T.bit_count, 8));
+ if (T.bit_count == 0)
+ return set(u8, buffer, 0);
+
// TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
const uint = std.meta.IntType(false, T.bit_count);
var bits = @truncate(uint, value);
@@ -1807,7 +1813,7 @@ test "sliceAsBytes" {
}
test "sliceAsBytes with sentinel slice" {
- const empty_string:[:0]const u8 = "";
+ const empty_string: [:0]const u8 = "";
const bytes = sliceAsBytes(empty_string);
testing.expect(bytes.len == 0);
}
--
2.54.0
From cd26d3b0bb2b32f1daf1d3d46bb53731dd54afec Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 18:54:24 -0400
Subject: [PATCH 045/111] fix regressions caused earlier in this branch
---
lib/std/debug.zig | 11 +++++++++--
lib/std/io/fixed_buffer_stream.zig | 3 +--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 5c564905193e42569a01e1b5c741c20a4e83299a..b27b1caa68d62f9168db6f76aa1445901ab5b8ba 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -825,8 +825,15 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !M
const shoff = hdr.e_shoff;
const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx);
- const header_strings = mapped_mem[str_section_off..str_section_off + hdr.e_shentsize];
- const shdrs = @ptrCast([*]const elf.Shdr, @alignCast(@alignOf(elf.Shdr), &mapped_mem[shoff]))[0..hdr.e_shnum];
+ const str_shdr = @ptrCast(
+ *const elf.Shdr,
+ @alignCast(@alignOf(elf.Shdr), &mapped_mem[str_section_off]),
+ );
+ const header_strings = mapped_mem[str_shdr.sh_offset .. str_shdr.sh_offset + str_shdr.sh_size];
+ const shdrs = @ptrCast(
+ [*]const elf.Shdr,
+ @alignCast(@alignOf(elf.Shdr), &mapped_mem[shoff]),
+ )[0..hdr.e_shnum];
var opt_debug_info: ?[]const u8 = null;
var opt_debug_abbrev: ?[]const u8 = null;
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index 9cdad7dc577e3fefec2141258dccf449415aa05d..0f2b54220117a0ee74a9fb12d29c875a7bcf3fb0 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -164,6 +164,5 @@ test "FixedBufferStream input" {
testing.expect(read == 3);
testing.expect(mem.eql(u8, dest[0..3], bytes[4..7]));
- read = try fbs.inStream().read(dest[0..4]);
- testing.expect(read == 0);
+ testing.expectError(error.EndOfStream, fbs.inStream().read(dest[0..4]));
}
--
2.54.0
From 9abee660dce3b43b9ac3b8260fbf269532d6c7f5 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 19:28:05 -0400
Subject: [PATCH 046/111] fix stack trace code not opening files in forced
blocking mode
---
lib/std/debug.zig | 4 +++-
lib/std/event/group.zig | 4 +++-
lib/std/event/lock.zig | 3 +++
lib/std/net/test.zig | 2 +-
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index b27b1caa68d62f9168db6f76aa1445901ab5b8ba..e849d72bcf21e4622df1aa8d77021b81a62c2c84 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -964,7 +964,9 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !M
}
fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
- var f = try fs.cwd().openFile(line_info.file_name, .{});
+ // Need this to always block even in async I/O mode, because this could potentially
+ // be called from e.g. the event loop code crashing.
+ var f = try fs.cwd().openFile(line_info.file_name, .{ .always_blocking = true });
defer f.close();
// TODO fstat and make sure that the file has the correct size
diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig
index ac1bf68245071cf2382f07473324c519701f76c3..5eebb7ffbcf4816d315a27c7d72a9711bad334e6 100644
--- a/lib/std/event/group.zig
+++ b/lib/std/event/group.zig
@@ -120,9 +120,11 @@ test "std.event.Group" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
- // TODO provide a way to run tests in evented I/O mode
if (!std.io.is_async) return error.SkipZigTest;
+ // TODO this file has bit-rotted. repair it
+ if (true) return error.SkipZigTest;
+
const handle = async testGroup(std.heap.page_allocator);
}
diff --git a/lib/std/event/lock.zig b/lib/std/event/lock.zig
index b9cbb5d95fd02969aa0474b6aa71689d61df4594..1bb51261d79f7e55e1ef9236f8b8de9e84adc9f4 100644
--- a/lib/std/event/lock.zig
+++ b/lib/std/event/lock.zig
@@ -125,6 +125,9 @@ test "std.event.Lock" {
// TODO https://github.com/ziglang/zig/issues/3251
if (builtin.os.tag == .freebsd) return error.SkipZigTest;
+ // TODO this file has bit-rotted. repair it
+ if (true) return error.SkipZigTest;
+
var lock = Lock.init();
defer lock.deinit();
diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig
index 4f3d955f30efbbdfb760ca6254988e11a9785979..087f965c4ee3de39ff83ed48c09ad40f2653f46f 100644
--- a/lib/std/net/test.zig
+++ b/lib/std/net/test.zig
@@ -113,6 +113,6 @@ fn testClient(addr: net.Address) anyerror!void {
fn testServer(server: *net.StreamServer) anyerror!void {
var client = try server.accept();
- const stream = &client.file.outStream().stream;
+ const stream = client.file.outStream();
try stream.print("hello from server\n", .{});
}
--
2.54.0
From 2bff0dda795cd84e4da59652736b7cfa7e1c964c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 20:22:30 -0400
Subject: [PATCH 047/111] fix regressions found by test suite
---
doc/docgen.zig | 95 +++++++++++++--------------
doc/langref.html.in | 2 +-
lib/std/build.zig | 3 +-
lib/std/build/run.zig | 6 +-
lib/std/coff.zig | 15 ++---
lib/std/debug.zig | 38 +++++------
lib/std/pdb.zig | 14 ++--
lib/std/special/build_runner.zig | 8 +--
test/compare_output.zig | 34 +++++-----
test/standalone/guess_number/main.zig | 2 +-
test/tests.zig | 14 ++--
11 files changed, 103 insertions(+), 128 deletions(-)
diff --git a/doc/docgen.zig b/doc/docgen.zig
index 319d9e0035b25210d175fa2bc9b32526d2ac9cfa..4d2625f54f7415a3fdb11154ce05c294d4c660a9 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -40,12 +40,9 @@ pub fn main() !void {
var out_file = try fs.cwd().createFile(out_file_name, .{});
defer out_file.close();
- var file_in_stream = in_file.inStream();
+ const input_file_bytes = try in_file.inStream().readAllAlloc(allocator, max_doc_file_size);
- const input_file_bytes = try file_in_stream.stream.readAllAlloc(allocator, max_doc_file_size);
-
- var file_out_stream = out_file.outStream();
- var buffered_out_stream = io.BufferedOutStream(fs.File.WriteError).init(&file_out_stream.stream);
+ var buffered_out_stream = io.bufferedOutStream(out_file.outStream());
var tokenizer = Tokenizer.init(in_file_name, input_file_bytes);
var toc = try genToc(allocator, &tokenizer);
@@ -53,7 +50,7 @@ pub fn main() !void {
try fs.cwd().makePath(tmp_dir_name);
defer fs.deleteTree(tmp_dir_name) catch {};
- try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe);
+ try genHtml(allocator, &tokenizer, &toc, buffered_out_stream.outStream(), zig_exe);
try buffered_out_stream.flush();
}
@@ -327,8 +324,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
var toc_buf = try std.Buffer.initSize(allocator, 0);
defer toc_buf.deinit();
- var toc_buf_adapter = io.BufferOutStream.init(&toc_buf);
- var toc = &toc_buf_adapter.stream;
+ var toc = toc_buf.outStream();
var nodes = std.ArrayList(Node).init(allocator);
defer nodes.deinit();
@@ -342,7 +338,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
if (header_stack_size != 0) {
return parseError(tokenizer, token, "unbalanced headers", .{});
}
- try toc.write(" \n");
+ try toc.writeAll(" \n");
break;
},
Token.Id.Content => {
@@ -407,7 +403,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
if (last_columns) |n| {
try toc.print("\n", .{n});
} else {
- try toc.write("\n");
+ try toc.writeAll("\n");
}
} else {
last_action = Action.Open;
@@ -424,9 +420,9 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
if (last_action == Action.Close) {
try toc.writeByteNTimes(' ', 8 + header_stack_size * 4);
- try toc.write("
\n");
+ try toc.writeAll("
\n");
} else {
- try toc.write("\n");
+ try toc.writeAll("\n");
last_action = Action.Close;
}
} else if (mem.eql(u8, tag_name, "see_also")) {
@@ -614,8 +610,7 @@ fn urlize(allocator: *mem.Allocator, input: []const u8) ![]u8 {
var buf = try std.Buffer.initSize(allocator, 0);
defer buf.deinit();
- var buf_adapter = io.BufferOutStream.init(&buf);
- var out = &buf_adapter.stream;
+ const out = buf.outStream();
for (input) |c| {
switch (c) {
'a'...'z', 'A'...'Z', '_', '-', '0'...'9' => {
@@ -634,8 +629,7 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
var buf = try std.Buffer.initSize(allocator, 0);
defer buf.deinit();
- var buf_adapter = io.BufferOutStream.init(&buf);
- var out = &buf_adapter.stream;
+ const out = buf.outStream();
try writeEscaped(out, input);
return buf.toOwnedSlice();
}
@@ -643,10 +637,10 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
fn writeEscaped(out: var, input: []const u8) !void {
for (input) |c| {
try switch (c) {
- '&' => out.write("&"),
- '<' => out.write("<"),
- '>' => out.write(">"),
- '"' => out.write("""),
+ '&' => out.writeAll("&"),
+ '<' => out.writeAll("<"),
+ '>' => out.writeAll(">"),
+ '"' => out.writeAll("""),
else => out.writeByte(c),
};
}
@@ -681,8 +675,7 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
var buf = try std.Buffer.initSize(allocator, 0);
defer buf.deinit();
- var buf_adapter = io.BufferOutStream.init(&buf);
- var out = &buf_adapter.stream;
+ var out = buf.outStream();
var number_start_index: usize = undefined;
var first_number: usize = undefined;
var second_number: usize = undefined;
@@ -743,7 +736,7 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
'm' => {
state = TermState.Start;
while (open_span_count != 0) : (open_span_count -= 1) {
- try out.write("");
+ try out.writeAll("");
}
if (first_number != 0 or second_number != 0) {
try out.print("", .{ first_number, second_number });
@@ -774,7 +767,7 @@ fn isType(name: []const u8) bool {
fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Token, raw_src: []const u8) !void {
const src = mem.trim(u8, raw_src, " \n");
- try out.write("");
+ try out.writeAll("");
var tokenizer = std.zig.Tokenizer.init(src);
var index: usize = 0;
var next_tok_is_fn = false;
@@ -835,15 +828,15 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_allowzero,
.Keyword_while,
=> {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
},
.Keyword_fn => {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
next_tok_is_fn = true;
},
@@ -852,24 +845,24 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_true,
.Keyword_false,
=> {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
},
.StringLiteral,
.MultilineStringLiteralLine,
.CharLiteral,
=> {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
},
.Builtin => {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
},
.LineComment,
@@ -877,16 +870,16 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.ContainerDocComment,
.ShebangLine,
=> {
- try out.write("");
},
.Identifier => {
if (prev_tok_was_fn) {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
} else {
const is_int = blk: {
if (src[token.start] != 'i' and src[token.start] != 'u')
@@ -901,9 +894,9 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
break :blk true;
};
if (is_int or isType(src[token.start..token.end])) {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
} else {
try writeEscaped(out, src[token.start..token.end]);
}
@@ -913,9 +906,9 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.IntegerLiteral,
.FloatLiteral,
=> {
- try out.write("");
+ try out.writeAll("");
try writeEscaped(out, src[token.start..token.end]);
- try out.write("");
+ try out.writeAll("");
},
.Bang,
@@ -983,7 +976,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
}
index = token.end;
}
- try out.write("");
+ try out.writeAll("");
}
fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
@@ -1002,7 +995,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
for (toc.nodes) |node| {
switch (node) {
.Content => |data| {
- try out.write(data);
+ try out.writeAll(data);
},
.Link => |info| {
if (!toc.urls.contains(info.url)) {
@@ -1011,12 +1004,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.print("{}", .{ info.url, info.name });
},
.Nav => {
- try out.write(toc.toc);
+ try out.writeAll(toc.toc);
},
.Builtin => |tok| {
- try out.write("");
+ try out.writeAll("");
try tokenizeAndPrintRaw(tokenizer, out, tok, builtin_code);
- try out.write("");
+ try out.writeAll("");
},
.HeaderOpen => |info| {
try out.print(
@@ -1025,7 +1018,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
);
},
.SeeAlso => |items| {
- try out.write("See also:
\n");
+ try out.writeAll("See also:
\n");
for (items) |item| {
const url = try urlize(allocator, item.name);
if (!toc.urls.contains(url)) {
@@ -1033,7 +1026,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
try out.print("- {}
\n", .{ url, item.name });
}
- try out.write("
\n");
+ try out.writeAll("
\n");
},
.Syntax => |content_tok| {
try tokenizeAndPrint(tokenizer, out, content_tok);
@@ -1047,9 +1040,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
if (!code.is_inline) {
try out.print("{}.zig
", .{code.name});
}
- try out.write("");
+ try out.writeAll("");
try tokenizeAndPrint(tokenizer, out, code.source_token);
- try out.write("");
+ try out.writeAll("");
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", .{code.name});
const tmp_source_file_name = try fs.path.join(
allocator,
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 447d545975f814fcfe9928f9bed7d85d2e6a86f0..baba472e881588589e5da30f577799de977a9fe2 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -230,7 +230,7 @@
const std = @import("std");
pub fn main() !void {
- const stdout = &std.io.getStdOut().outStream().stream;
+ const stdout = std.io.getStdOut().outStream();
try stdout.print("Hello, {}!\n", .{"world"});
}
{#code_end#}
diff --git a/lib/std/build.zig b/lib/std/build.zig
index bc8b8acba089b109beb3c431e6fb4aa8962b2cda..e8484e9d1c0ad9a5c89b35bb901555e42af65ee1 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -926,8 +926,7 @@ pub const Builder = struct {
try child.spawn();
- var stdout_file_in_stream = child.stdout.?.inStream();
- const stdout = try stdout_file_in_stream.stream.readAllAlloc(self.allocator, max_output_size);
+ const stdout = try child.stdout.?.inStream().readAllAlloc(self.allocator, max_output_size);
errdefer self.allocator.free(stdout);
const term = try child.wait();
diff --git a/lib/std/build/run.zig b/lib/std/build/run.zig
index 41417572ca4b70adda4be7ecd9448afc23192f95..91ecd56c3a520e5e1c4a3643aebe318fd464dca1 100644
--- a/lib/std/build/run.zig
+++ b/lib/std/build/run.zig
@@ -175,8 +175,7 @@ pub const RunStep = struct {
switch (self.stdout_action) {
.expect_exact, .expect_matches => {
- var stdout_file_in_stream = child.stdout.?.inStream();
- stdout = stdout_file_in_stream.stream.readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable;
+ stdout = child.stdout.?.inStream().readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable;
},
.inherit, .ignore => {},
}
@@ -186,8 +185,7 @@ pub const RunStep = struct {
switch (self.stderr_action) {
.expect_exact, .expect_matches => {
- var stderr_file_in_stream = child.stderr.?.inStream();
- stderr = stderr_file_in_stream.stream.readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable;
+ stderr = child.stderr.?.inStream().readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable;
},
.inherit, .ignore => {},
}
diff --git a/lib/std/coff.zig b/lib/std/coff.zig
index b1be21c4d370604b6a1f72988fffd6a3f3fc095c..2e17f46454d3eabcd2f1ee2b2044936ab4cbbc14 100644
--- a/lib/std/coff.zig
+++ b/lib/std/coff.zig
@@ -56,8 +56,7 @@ pub const Coff = struct {
pub fn loadHeader(self: *Coff) !void {
const pe_pointer_offset = 0x3C;
- var file_stream = self.in_file.inStream();
- const in = &file_stream.stream;
+ const in = self.in_file.inStream();
var magic: [2]u8 = undefined;
try in.readNoEof(magic[0..]);
@@ -89,11 +88,11 @@ pub const Coff = struct {
else => return error.InvalidMachine,
}
- try self.loadOptionalHeader(&file_stream);
+ try self.loadOptionalHeader();
}
- fn loadOptionalHeader(self: *Coff, file_stream: *File.InStream) !void {
- const in = &file_stream.stream;
+ fn loadOptionalHeader(self: *Coff) !void {
+ const in = self.in_file.inStream();
self.pe_header.magic = try in.readIntLittle(u16);
// For now we're only interested in finding the reference to the .pdb,
// so we'll skip most of this header, which size is different in 32
@@ -136,8 +135,7 @@ pub const Coff = struct {
const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];
const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
- var file_stream = self.in_file.inStream();
- const in = &file_stream.stream;
+ const in = self.in_file.inStream();
try self.in_file.seekTo(file_offset);
// Find the correct DebugDirectoryEntry, and where its data is stored.
@@ -188,8 +186,7 @@ pub const Coff = struct {
try self.sections.ensureCapacity(self.coff_header.number_of_sections);
- var file_stream = self.in_file.inStream();
- const in = &file_stream.stream;
+ const in = self.in_file.inStream();
var name: [8]u8 = undefined;
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index e849d72bcf21e4622df1aa8d77021b81a62c2c84..0a7a0dee7ec57eabb9ce565dcf74dd4ee743d7b8 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -475,15 +475,15 @@ fn populateModule(di: *ModuleDebugInfo, mod: *Module) !void {
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
- const signature = try modi.stream.readIntLittle(u32);
+ const signature = try modi.inStream().readIntLittle(u32);
if (signature != 4)
return error.InvalidDebugInfo;
mod.symbols = try allocator.alloc(u8, mod.mod_info.SymByteSize - 4);
- try modi.stream.readNoEof(mod.symbols);
+ try modi.inStream().readNoEof(mod.symbols);
mod.subsect_info = try allocator.alloc(u8, mod.mod_info.C13ByteSize);
- try modi.stream.readNoEof(mod.subsect_info);
+ try modi.inStream().readNoEof(mod.subsect_info);
var sect_offset: usize = 0;
var skip_len: usize = undefined;
@@ -656,11 +656,11 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
try di.pdb.openFile(di.coff, path);
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
- const version = try pdb_stream.stream.readIntLittle(u32);
- const signature = try pdb_stream.stream.readIntLittle(u32);
- const age = try pdb_stream.stream.readIntLittle(u32);
+ const version = try pdb_stream.inStream().readIntLittle(u32);
+ const signature = try pdb_stream.inStream().readIntLittle(u32);
+ const age = try pdb_stream.inStream().readIntLittle(u32);
var guid: [16]u8 = undefined;
- try pdb_stream.stream.readNoEof(&guid);
+ try pdb_stream.inStream().readNoEof(&guid);
if (version != 20000404) // VC70, only value observed by LLVM team
return error.UnknownPDBVersion;
if (!mem.eql(u8, &di.coff.guid, &guid) or di.coff.age != age)
@@ -668,9 +668,9 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
// We validated the executable and pdb match.
const string_table_index = str_tab_index: {
- const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
+ const name_bytes_len = try pdb_stream.inStream().readIntLittle(u32);
const name_bytes = try allocator.alloc(u8, name_bytes_len);
- try pdb_stream.stream.readNoEof(name_bytes);
+ try pdb_stream.inStream().readNoEof(name_bytes);
const HashTableHeader = packed struct {
Size: u32,
@@ -680,17 +680,17 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
return cap * 2 / 3 + 1;
}
};
- const hash_tbl_hdr = try pdb_stream.stream.readStruct(HashTableHeader);
+ const hash_tbl_hdr = try pdb_stream.inStream().readStruct(HashTableHeader);
if (hash_tbl_hdr.Capacity == 0)
return error.InvalidDebugInfo;
if (hash_tbl_hdr.Size > HashTableHeader.maxLoad(hash_tbl_hdr.Capacity))
return error.InvalidDebugInfo;
- const present = try readSparseBitVector(&pdb_stream.stream, allocator);
+ const present = try readSparseBitVector(&pdb_stream.inStream(), allocator);
if (present.len != hash_tbl_hdr.Size)
return error.InvalidDebugInfo;
- const deleted = try readSparseBitVector(&pdb_stream.stream, allocator);
+ const deleted = try readSparseBitVector(&pdb_stream.inStream(), allocator);
const Bucket = struct {
first: u32,
@@ -698,8 +698,8 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
};
const bucket_list = try allocator.alloc(Bucket, present.len);
for (present) |_| {
- const name_offset = try pdb_stream.stream.readIntLittle(u32);
- const name_index = try pdb_stream.stream.readIntLittle(u32);
+ const name_offset = try pdb_stream.inStream().readIntLittle(u32);
+ const name_index = try pdb_stream.inStream().readIntLittle(u32);
const name = mem.toSlice(u8, @ptrCast([*:0]u8, name_bytes.ptr + name_offset));
if (mem.eql(u8, name, "/names")) {
break :str_tab_index name_index;
@@ -714,7 +714,7 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
const dbi = di.pdb.dbi;
// Dbi Header
- const dbi_stream_header = try dbi.stream.readStruct(pdb.DbiStreamHeader);
+ const dbi_stream_header = try dbi.inStream().readStruct(pdb.DbiStreamHeader);
if (dbi_stream_header.VersionHeader != 19990903) // V70, only value observed by LLVM team
return error.UnknownPDBVersion;
if (dbi_stream_header.Age != age)
@@ -728,7 +728,7 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
// Module Info Substream
var mod_info_offset: usize = 0;
while (mod_info_offset != mod_info_size) {
- const mod_info = try dbi.stream.readStruct(pdb.ModInfo);
+ const mod_info = try dbi.inStream().readStruct(pdb.ModInfo);
var this_record_len: usize = @sizeOf(pdb.ModInfo);
const module_name = try dbi.readNullTermString(allocator);
@@ -766,14 +766,14 @@ fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
var sect_cont_offset: usize = 0;
if (section_contrib_size != 0) {
- const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
+ const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.inStream().readIntLittle(u32));
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
return error.InvalidDebugInfo;
sect_cont_offset += @sizeOf(u32);
}
while (sect_cont_offset != section_contrib_size) {
const entry = try sect_contribs.addOne();
- entry.* = try dbi.stream.readStruct(pdb.SectionContribEntry);
+ entry.* = try dbi.inStream().readStruct(pdb.SectionContribEntry);
sect_cont_offset += @sizeOf(pdb.SectionContribEntry);
if (sect_cont_offset > section_contrib_size)
@@ -827,7 +827,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !M
const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx);
const str_shdr = @ptrCast(
*const elf.Shdr,
- @alignCast(@alignOf(elf.Shdr), &mapped_mem[str_section_off]),
+ @alignCast(@alignOf(elf.Shdr), &mapped_mem[try math.cast(usize, str_section_off)]),
);
const header_strings = mapped_mem[str_shdr.sh_offset .. str_shdr.sh_offset + str_shdr.sh_size];
const shdrs = @ptrCast(
diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig
index 7c48cf7b7cdb9d8dc6e211df5eccead128e839db..93fef0b16d1b5bb52d4cd31d91a8d6769388846a 100644
--- a/lib/std/pdb.zig
+++ b/lib/std/pdb.zig
@@ -495,8 +495,7 @@ const Msf = struct {
streams: []MsfStream,
fn openFile(self: *Msf, allocator: *mem.Allocator, file: File) !void {
- var file_stream = file.inStream();
- const in = &file_stream.stream;
+ const in = file.inStream();
const superblock = try in.readStruct(SuperBlock);
@@ -529,7 +528,7 @@ const Msf = struct {
);
const begin = self.directory.pos;
- const stream_count = try self.directory.stream.readIntLittle(u32);
+ const stream_count = try self.directory.inStream().readIntLittle(u32);
const stream_sizes = try allocator.alloc(u32, stream_count);
defer allocator.free(stream_sizes);
@@ -538,7 +537,7 @@ const Msf = struct {
// and must be taken into account when resolving stream indices.
const Nil = 0xFFFFFFFF;
for (stream_sizes) |*s, i| {
- const size = try self.directory.stream.readIntLittle(u32);
+ const size = try self.directory.inStream().readIntLittle(u32);
s.* = if (size == Nil) 0 else blockCountFromSize(size, superblock.BlockSize);
}
@@ -553,7 +552,7 @@ const Msf = struct {
var blocks = try allocator.alloc(u32, size);
var j: u32 = 0;
while (j < size) : (j += 1) {
- const block_id = try self.directory.stream.readIntLittle(u32);
+ const block_id = try self.directory.inStream().readIntLittle(u32);
const n = (block_id % superblock.BlockSize);
// 0 is for SuperBlock, 1 and 2 for FPMs.
if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > try file.getEndPos())
@@ -648,7 +647,7 @@ const MsfStream = struct {
fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 {
var list = ArrayList(u8).init(allocator);
while (true) {
- const byte = try self.stream.readByte();
+ const byte = try self.inStream().readByte();
if (byte == 0) {
return list.toSlice();
}
@@ -662,8 +661,7 @@ const MsfStream = struct {
var offset = self.pos % self.block_size;
try self.in_file.seekTo(block * self.block_size + offset);
- var file_stream = self.in_file.inStream();
- const in = &file_stream.stream;
+ const in = self.in_file.inStream();
var size: usize = 0;
var rem_buffer = buffer;
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
index baf21570ecc5d65bb3fccccd076acc069fdb46e2..974247e2a1b708bbbc270b70e4da5c7461205d80 100644
--- a/lib/std/special/build_runner.zig
+++ b/lib/std/special/build_runner.zig
@@ -42,8 +42,8 @@ pub fn main() !void {
var targets = ArrayList([]const u8).init(allocator);
- const stderr_stream = &io.getStdErr().outStream().stream;
- const stdout_stream = &io.getStdOut().outStream().stream;
+ const stderr_stream = io.getStdErr().outStream();
+ const stdout_stream = io.getStdOut().outStream();
while (nextArg(args, &arg_idx)) |arg| {
if (mem.startsWith(u8, arg, "-D")) {
@@ -159,7 +159,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description });
}
- try out_stream.write(
+ try out_stream.writeAll(
\\
\\General Options:
\\ --help Print this help and exit
@@ -184,7 +184,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
}
}
- try out_stream.write(
+ try out_stream.writeAll(
\\
\\Advanced Options:
\\ --build-file [file] Override path to build.zig
diff --git a/test/compare_output.zig b/test/compare_output.zig
index ec89af35f855b3150901f6c2e9828f250b873564..1a0179c4c22d9ff7569bfcd190b8e6e7d769774b 100644
--- a/test/compare_output.zig
+++ b/test/compare_output.zig
@@ -22,7 +22,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn main() void {
\\ privateFunction();
- \\ const stdout = &getStdOut().outStream().stream;
+ \\ const stdout = getStdOut().outStream();
\\ stdout.print("OK 2\n", .{}) catch unreachable;
\\}
\\
@@ -37,7 +37,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\// purposefully conflicting function with main.zig
\\// but it's private so it should be OK
\\fn privateFunction() void {
- \\ const stdout = &getStdOut().outStream().stream;
+ \\ const stdout = getStdOut().outStream();
\\ stdout.print("OK 1\n", .{}) catch unreachable;
\\}
\\
@@ -63,7 +63,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
tc.addSourceFile("foo.zig",
\\usingnamespace @import("std").io;
\\pub fn foo_function() void {
- \\ const stdout = &getStdOut().outStream().stream;
+ \\ const stdout = getStdOut().outStream();
\\ stdout.print("OK\n", .{}) catch unreachable;
\\}
);
@@ -74,7 +74,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn bar_function() void {
\\ if (foo_function()) {
- \\ const stdout = &getStdOut().outStream().stream;
+ \\ const stdout = getStdOut().outStream();
\\ stdout.print("OK\n", .{}) catch unreachable;
\\ }
\\}
@@ -106,7 +106,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub const a_text = "OK\n";
\\
\\pub fn ok() void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print(b_text, .{}) catch unreachable;
\\}
);
@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\
\\pub fn main() void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", .{@as(u32, 12), @as(u16, 0x12), @as(u8, 'a')}) catch unreachable;
\\}
, "Hello, world!\n 12 12 a\n");
@@ -267,7 +267,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ var x_local : i32 = print_ok(x);
\\}
\\fn print_ok(val: @TypeOf(x)) @TypeOf(foo) {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("OK\n", .{}) catch unreachable;
\\ return 0;
\\}
@@ -349,7 +349,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub fn main() void {
\\ const bar = Bar {.field2 = 13,};
\\ const foo = Foo {.field1 = bar,};
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ if (!foo.method()) {
\\ stdout.print("BAD\n", .{}) catch unreachable;
\\ }
@@ -363,7 +363,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
cases.add("defer with only fallthrough",
\\const io = @import("std").io;
\\pub fn main() void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("before\n", .{}) catch unreachable;
\\ defer stdout.print("defer1\n", .{}) catch unreachable;
\\ defer stdout.print("defer2\n", .{}) catch unreachable;
@@ -376,7 +376,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\const os = @import("std").os;
\\pub fn main() void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("before\n", .{}) catch unreachable;
\\ defer stdout.print("defer1\n", .{}) catch unreachable;
\\ defer stdout.print("defer2\n", .{}) catch unreachable;
@@ -393,7 +393,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ do_test() catch return;
\\}
\\fn do_test() !void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("before\n", .{}) catch unreachable;
\\ defer stdout.print("defer1\n", .{}) catch unreachable;
\\ errdefer stdout.print("deferErr\n", .{}) catch unreachable;
@@ -412,7 +412,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ do_test() catch return;
\\}
\\fn do_test() !void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print("before\n", .{}) catch unreachable;
\\ defer stdout.print("defer1\n", .{}) catch unreachable;
\\ errdefer stdout.print("deferErr\n", .{}) catch unreachable;
@@ -429,7 +429,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\
\\pub fn main() void {
- \\ const stdout = &io.getStdOut().outStream().stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ stdout.print(foo_txt, .{}) catch unreachable;
\\}
, "1234\nabcd\n");
@@ -448,9 +448,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn main() !void {
\\ var args_it = std.process.args();
- \\ var stdout_file = io.getStdOut();
- \\ var stdout_adapter = stdout_file.outStream();
- \\ const stdout = &stdout_adapter.stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ var index: usize = 0;
\\ _ = args_it.skip();
\\ while (args_it.next(allocator)) |arg_or_err| : (index += 1) {
@@ -489,9 +487,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn main() !void {
\\ var args_it = std.process.args();
- \\ var stdout_file = io.getStdOut();
- \\ var stdout_adapter = stdout_file.outStream();
- \\ const stdout = &stdout_adapter.stream;
+ \\ const stdout = io.getStdOut().outStream();
\\ var index: usize = 0;
\\ _ = args_it.skip();
\\ while (args_it.next(allocator)) |arg_or_err| : (index += 1) {
diff --git a/test/standalone/guess_number/main.zig b/test/standalone/guess_number/main.zig
index f5b3b3699366673a37087b083b5c59642bb65e76..14babcd145d10cc0921fa3c473a13df99dce4a48 100644
--- a/test/standalone/guess_number/main.zig
+++ b/test/standalone/guess_number/main.zig
@@ -4,7 +4,7 @@ const io = std.io;
const fmt = std.fmt;
pub fn main() !void {
- const stdout = &io.getStdOut().outStream().stream;
+ const stdout = io.getStdOut().outStream();
const stdin = io.getStdIn();
try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
diff --git a/test/tests.zig b/test/tests.zig
index e3249025792caa0da4406a77e2f9470ddc089a19..22dad10e3e46c6edccd7c001fbe0705392b264bb 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -566,12 +566,9 @@ pub const StackTracesContext = struct {
}
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) });
- var stdout_file_in_stream = child.stdout.?.inStream();
- var stderr_file_in_stream = child.stderr.?.inStream();
-
- const stdout = stdout_file_in_stream.stream.readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
+ const stdout = child.stdout.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
defer b.allocator.free(stdout);
- const stderr = stderr_file_in_stream.stream.readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
+ const stderr = child.stderr.?.inStream().readAllAlloc(b.allocator, max_stdout_size) catch unreachable;
defer b.allocator.free(stderr);
const term = child.wait() catch |err| {
@@ -798,11 +795,8 @@ pub const CompileErrorContext = struct {
var stdout_buf = Buffer.initNull(b.allocator);
var stderr_buf = Buffer.initNull(b.allocator);
- var stdout_file_in_stream = child.stdout.?.inStream();
- var stderr_file_in_stream = child.stderr.?.inStream();
-
- stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
- stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
+ child.stdout.?.inStream().readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
+ child.stderr.?.inStream().readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
const term = child.wait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", .{ zig_args.items[0], @errorName(err) });
--
2.54.0
From d882a305875d5e0ab5d7877c3763b5aaf0ff61ce Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 20:51:30 -0400
Subject: [PATCH 048/111] fix stage2 lib on windows
---
src-self-hosted/libc_installation.zig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 78aafeff289e79fc3b70c5eaabcabab55c3ca32e..0f9736456a0ef408041a8bf86a174d3eeec0dba7 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -348,7 +348,7 @@ pub const LibCInstallation = struct {
for (searches) |search| {
result_buf.shrink(0);
- const stream = &std.io.BufferOutStream.init(&result_buf).stream;
+ const stream = result_buf.outStream();
try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });
var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
@@ -395,7 +395,7 @@ pub const LibCInstallation = struct {
for (searches) |search| {
result_buf.shrink(0);
- const stream = &std.io.BufferOutStream.init(&result_buf).stream;
+ const stream = result_buf.outStream();
try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });
var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
@@ -459,7 +459,7 @@ pub const LibCInstallation = struct {
for (searches) |search| {
result_buf.shrink(0);
- const stream = &std.io.BufferOutStream.init(&result_buf).stream;
+ const stream = result_buf.outStream();
try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });
var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
--
2.54.0
From bd14a81e301401b5b2a8b849d17d6ae0750272b8 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 21:09:49 -0400
Subject: [PATCH 049/111] fix std.ChildProcess on Windows
---
lib/std/child_process.zig | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
index 95619384b18a5574db9db01e45f15964d4d7cced..008fc34ff6e47544376351308d6e90cc0f59b15c 100644
--- a/lib/std/child_process.zig
+++ b/lib/std/child_process.zig
@@ -217,13 +217,13 @@ pub const ChildProcess = struct {
try child.spawn();
- var stdout_file_in_stream = child.stdout.?.inStream();
- var stderr_file_in_stream = child.stderr.?.inStream();
+ const stdout_in = child.stdout.?.inStream();
+ const stderr_in = child.stderr.?.inStream();
// TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O).
- const stdout = try stdout_file_in_stream.readAllAlloc(args.allocator, args.max_output_bytes);
+ const stdout = try stdout_in.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stdout);
- const stderr = try stderr_file_in_stream.readAllAlloc(args.allocator, args.max_output_bytes);
+ const stderr = try stderr_in.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stderr);
return ExecResult{
@@ -780,7 +780,7 @@ fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8)
var buf = try Buffer.initSize(allocator, 0);
defer buf.deinit();
- var buf_stream = &io.BufferOutStream.init(&buf).stream;
+ var buf_stream = buf.outStream();
for (argv) |arg, arg_i| {
if (arg_i != 0) try buf.appendByte(' ');
--
2.54.0
From ed13cffca4c42718cc7239faf7aab642ac67ef77 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 10 Mar 2020 22:01:58 -0400
Subject: [PATCH 050/111] rework some old ELF parsing code and start to fix
emitRaw
---
lib/std/build/emit_raw.zig | 112 +++++---------
lib/std/elf.zig | 292 ++++++++++---------------------------
lib/std/zig/system.zig | 35 ++---
3 files changed, 128 insertions(+), 311 deletions(-)
diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig
index 44e0227b6ecc23101ded80abfba4500cf9d2b975..63c232994753d54e4bdbc58741bd4da9413ea676 100644
--- a/lib/std/build/emit_raw.zig
+++ b/lib/std/build/emit_raw.zig
@@ -14,11 +14,6 @@ const io = std.io;
const sort = std.sort;
const warn = std.debug.warn;
-const BinOutStream = io.OutStream(anyerror);
-const BinSeekStream = io.SeekableStream(anyerror, anyerror);
-const ElfSeekStream = io.SeekableStream(anyerror, anyerror);
-const ElfInStream = io.InStream(anyerror);
-
const BinaryElfSection = struct {
elfOffset: u64,
binaryOffset: u64,
@@ -41,22 +36,21 @@ const BinaryElfOutput = struct {
const Self = @This();
- pub fn init(allocator: *Allocator) Self {
- return Self{
- .segments = ArrayList(*BinaryElfSegment).init(allocator),
- .sections = ArrayList(*BinaryElfSection).init(allocator),
- };
- }
-
pub fn deinit(self: *Self) void {
self.sections.deinit();
self.segments.deinit();
}
- pub fn parseElf(self: *Self, elfFile: elf.Elf) !void {
- const allocator = self.segments.allocator;
+ pub fn parse(allocator: *Allocator, elf_file: File) !Self {
+ var self: Self = .{
+ .segments = ArrayList(*BinaryElfSegment).init(allocator),
+ .sections = ArrayList(*BinaryElfSection).init(allocator),
+ };
+ const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file);
- for (elfFile.section_headers) |section, i| {
+ var binaryElfOutput = BinaryElfOutput.init(arena_allocator);
+
+ for (elf_hdrs.section_headers) |section, i| {
if (sectionValidForOutput(section)) {
const newSection = try allocator.create(BinaryElfSection);
@@ -69,19 +63,19 @@ const BinaryElfOutput = struct {
}
}
- for (elfFile.program_headers) |programHeader, i| {
- if (programHeader.p_type == elf.PT_LOAD) {
+ for (elf_hdrs.program_headers) |phdr, i| {
+ if (phdr.p_type == elf.PT_LOAD) {
const newSegment = try allocator.create(BinaryElfSegment);
- newSegment.physicalAddress = if (programHeader.p_paddr != 0) programHeader.p_paddr else programHeader.p_vaddr;
- newSegment.virtualAddress = programHeader.p_vaddr;
- newSegment.fileSize = @intCast(usize, programHeader.p_filesz);
- newSegment.elfOffset = programHeader.p_offset;
+ newSegment.physicalAddress = if (phdr.p_paddr != 0) phdr.p_paddr else phdr.p_vaddr;
+ newSegment.virtualAddress = phdr.p_vaddr;
+ newSegment.fileSize = @intCast(usize, phdr.p_filesz);
+ newSegment.elfOffset = phdr.p_offset;
newSegment.binaryOffset = 0;
newSegment.firstSection = null;
for (self.sections.toSlice()) |section| {
- if (sectionWithinSegment(section, programHeader)) {
+ if (sectionWithinSegment(section, phdr)) {
if (section.segment) |sectionSegment| {
if (sectionSegment.elfOffset > newSegment.elfOffset) {
section.segment = newSegment;
@@ -126,14 +120,17 @@ const BinaryElfOutput = struct {
}
sort.sort(*BinaryElfSection, self.sections.toSlice(), sectionSortCompare);
+
+ return self;
}
- fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.ProgramHeader) bool {
+ fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64_Phdr) bool {
return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize);
}
- fn sectionValidForOutput(section: elf.SectionHeader) bool {
- return section.sh_size > 0 and section.sh_type != elf.SHT_NOBITS and ((section.sh_flags & elf.SHF_ALLOC) == elf.SHF_ALLOC);
+ fn sectionValidForOutput(shdr: var) bool {
+ return shdr.sh_size > 0 and shdr.sh_type != elf.SHT_NOBITS and
+ ((shdr.sh_flags & elf.SHF_ALLOC) == elf.SHF_ALLOC);
}
fn segmentSortCompare(left: *BinaryElfSegment, right: *BinaryElfSegment) bool {
@@ -151,60 +148,27 @@ const BinaryElfOutput = struct {
}
};
-const WriteContext = struct {
- inStream: *ElfInStream,
- inSeekStream: *ElfSeekStream,
- outStream: *BinOutStream,
- outSeekStream: *BinSeekStream,
-};
+fn writeBinaryElfSection(elf_file: File, out_file: File, section: *BinaryElfSection) !void {
+ try out_file.seekTo(section.binaryOffset);
-fn writeBinaryElfSection(allocator: *Allocator, context: WriteContext, section: *BinaryElfSection) !void {
- var readBuffer = try allocator.alloc(u8, section.fileSize);
- defer allocator.free(readBuffer);
-
- try context.inSeekStream.seekTo(section.elfOffset);
- _ = try context.inStream.read(readBuffer);
-
- try context.outSeekStream.seekTo(section.binaryOffset);
- try context.outStream.write(readBuffer);
+ try out_file.writeFileAll(elf_file, .{
+ .in_offset = section.elfOffset,
+ .in_len = section.fileSize,
+ });
}
-fn emit_raw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !void {
- var arenaAlloc = ArenaAllocator.init(allocator);
- errdefer arenaAlloc.deinit();
- var arena_allocator = &arenaAlloc.allocator;
+fn emitRaw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !void {
+ var elf_file = try fs.cwd().openFile(elf_path, .{});
+ defer elf_file.close();
- const currentDir = fs.cwd();
+ var out_file = try fs.cwd().createFile(raw_path, .{});
+ defer out_file.close();
- var file = try currentDir.openFile(elf_path, File.OpenFlags{});
- defer file.close();
+ const binary_elf_output = BinaryElfOutput.parse(allocator, elf_file);
+ defer binary_elf_output.deinit();
- var fileInStream = file.inStream();
- var fileSeekStream = file.seekableStream();
-
- var elfFile = try elf.Elf.openStream(allocator, @ptrCast(*ElfSeekStream, &fileSeekStream.stream), @ptrCast(*ElfInStream, &fileInStream.stream));
- defer elfFile.close();
-
- var outFile = try currentDir.createFile(raw_path, File.CreateFlags{});
- defer outFile.close();
-
- var outFileOutStream = outFile.outStream();
- var outFileSeekStream = outFile.seekableStream();
-
- const writeContext = WriteContext{
- .inStream = @ptrCast(*ElfInStream, &fileInStream.stream),
- .inSeekStream = @ptrCast(*ElfSeekStream, &fileSeekStream.stream),
- .outStream = @ptrCast(*BinOutStream, &outFileOutStream.stream),
- .outSeekStream = @ptrCast(*BinSeekStream, &outFileSeekStream.stream),
- };
-
- var binaryElfOutput = BinaryElfOutput.init(arena_allocator);
- defer binaryElfOutput.deinit();
-
- try binaryElfOutput.parseElf(elfFile);
-
- for (binaryElfOutput.sections.toSlice()) |section| {
- try writeBinaryElfSection(allocator, writeContext, section);
+ for (binary_elf_output.sections.toSlice()) |section| {
+ try writeBinaryElfSection(elf_file, out_file, section);
}
}
@@ -250,6 +214,6 @@ pub const InstallRawStep = struct {
const full_dest_path = builder.getInstallPath(self.dest_dir, self.dest_filename);
fs.cwd().makePath(builder.getInstallPath(self.dest_dir, "")) catch unreachable;
- try emit_raw(builder.allocator, full_src_path, full_dest_path);
+ try emitRaw(builder.allocator, full_src_path, full_dest_path);
}
};
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index efaa4d6f062713e8d3490562f35a61ac9300032f..3aefd87f09e71d64a71b7d056bfbb0479cf470dc 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -330,9 +330,7 @@ pub const ET = extern enum(u16) {
pub const HIPROC = 0xffff;
};
-pub const SectionHeader = Elf64_Shdr;
-pub const ProgramHeader = Elf64_Phdr;
-
+/// All integers are native endian.
const Header = struct {
endian: builtin.Endian,
is_64: bool,
@@ -346,9 +344,9 @@ const Header = struct {
shstrndx: u16,
};
-pub fn readHeader(in_stream: var) !Header {
+pub fn readHeader(file: File) !Header {
var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;
- try in_stream.readAll(&hdr_buf);
+ try in_stream.preadAll(&hdr_buf, 0);
const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
@@ -381,216 +379,86 @@ pub fn readHeader(in_stream: var) !Header {
});
}
-pub const Elf = struct {
- seekable_stream: *io.SeekableStream(anyerror, anyerror),
- in_stream: *io.InStream(anyerror),
- is_64: bool,
- endian: builtin.Endian,
- file_type: ET,
- arch: EM,
- entry_addr: u64,
- program_header_offset: u64,
- section_header_offset: u64,
- string_section_index: usize,
- string_section: *SectionHeader,
- section_headers: []SectionHeader,
- program_headers: []ProgramHeader,
+/// All integers are native endian.
+pub const AllHeaders = struct {
+ header: Header,
+ section_headers: []Elf64_Shdr,
+ program_headers: []Elf64_Phdr,
allocator: *mem.Allocator,
-
- pub fn openStream(
- allocator: *mem.Allocator,
- seekable_stream: *io.SeekableStream(anyerror, anyerror),
- in: *io.InStream(anyerror),
- ) !Elf {
- var elf: Elf = undefined;
- elf.allocator = allocator;
- elf.seekable_stream = seekable_stream;
- elf.in_stream = in;
-
- var magic: [4]u8 = undefined;
- try in.readNoEof(magic[0..]);
- if (!mem.eql(u8, &magic, "\x7fELF")) return error.InvalidFormat;
-
- elf.is_64 = switch (try in.readByte()) {
- 1 => false,
- 2 => true,
- else => return error.InvalidFormat,
- };
-
- elf.endian = switch (try in.readByte()) {
- 1 => .Little,
- 2 => .Big,
- else => return error.InvalidFormat,
- };
-
- const version_byte = try in.readByte();
- if (version_byte != 1) return error.InvalidFormat;
-
- // skip over padding
- try seekable_stream.seekBy(9);
-
- elf.file_type = try in.readEnum(ET, elf.endian);
- elf.arch = try in.readEnum(EM, elf.endian);
-
- const elf_version = try in.readInt(u32, elf.endian);
- if (elf_version != 1) return error.InvalidFormat;
-
- if (elf.is_64) {
- elf.entry_addr = try in.readInt(u64, elf.endian);
- elf.program_header_offset = try in.readInt(u64, elf.endian);
- elf.section_header_offset = try in.readInt(u64, elf.endian);
- } else {
- elf.entry_addr = @as(u64, try in.readInt(u32, elf.endian));
- elf.program_header_offset = @as(u64, try in.readInt(u32, elf.endian));
- elf.section_header_offset = @as(u64, try in.readInt(u32, elf.endian));
- }
-
- // skip over flags
- try seekable_stream.seekBy(4);
-
- const header_size = try in.readInt(u16, elf.endian);
- if ((elf.is_64 and header_size != @sizeOf(Elf64_Ehdr)) or (!elf.is_64 and header_size != @sizeOf(Elf32_Ehdr))) {
- return error.InvalidFormat;
- }
-
- const ph_entry_size = try in.readInt(u16, elf.endian);
- const ph_entry_count = try in.readInt(u16, elf.endian);
-
- if ((elf.is_64 and ph_entry_size != @sizeOf(Elf64_Phdr)) or (!elf.is_64 and ph_entry_size != @sizeOf(Elf32_Phdr))) {
- return error.InvalidFormat;
- }
-
- const sh_entry_size = try in.readInt(u16, elf.endian);
- const sh_entry_count = try in.readInt(u16, elf.endian);
-
- if ((elf.is_64 and sh_entry_size != @sizeOf(Elf64_Shdr)) or (!elf.is_64 and sh_entry_size != @sizeOf(Elf32_Shdr))) {
- return error.InvalidFormat;
- }
-
- elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian));
-
- if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
-
- const sh_byte_count = @as(u64, sh_entry_size) * @as(u64, sh_entry_count);
- const end_sh = try math.add(u64, elf.section_header_offset, sh_byte_count);
- const ph_byte_count = @as(u64, ph_entry_size) * @as(u64, ph_entry_count);
- const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);
-
- const stream_end = try seekable_stream.getEndPos();
- if (stream_end < end_sh or stream_end < end_ph) {
- return error.InvalidFormat;
- }
-
- try seekable_stream.seekTo(elf.program_header_offset);
-
- elf.program_headers = try elf.allocator.alloc(ProgramHeader, ph_entry_count);
- errdefer elf.allocator.free(elf.program_headers);
-
- if (elf.is_64) {
- for (elf.program_headers) |*elf_program| {
- elf_program.p_type = try in.readInt(Elf64_Word, elf.endian);
- elf_program.p_flags = try in.readInt(Elf64_Word, elf.endian);
- elf_program.p_offset = try in.readInt(Elf64_Off, elf.endian);
- elf_program.p_vaddr = try in.readInt(Elf64_Addr, elf.endian);
- elf_program.p_paddr = try in.readInt(Elf64_Addr, elf.endian);
- elf_program.p_filesz = try in.readInt(Elf64_Xword, elf.endian);
- elf_program.p_memsz = try in.readInt(Elf64_Xword, elf.endian);
- elf_program.p_align = try in.readInt(Elf64_Xword, elf.endian);
- }
- } else {
- for (elf.program_headers) |*elf_program| {
- elf_program.p_type = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian));
- elf_program.p_offset = @as(Elf64_Off, try in.readInt(Elf32_Off, elf.endian));
- elf_program.p_vaddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian));
- elf_program.p_paddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian));
- elf_program.p_filesz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian));
- elf_program.p_memsz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian));
- elf_program.p_flags = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian));
- elf_program.p_align = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian));
- }
- }
-
- try seekable_stream.seekTo(elf.section_header_offset);
-
- elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
- errdefer elf.allocator.free(elf.section_headers);
-
- if (elf.is_64) {
- for (elf.section_headers) |*elf_section| {
- elf_section.sh_name = try in.readInt(u32, elf.endian);
- elf_section.sh_type = try in.readInt(u32, elf.endian);
- elf_section.sh_flags = try in.readInt(u64, elf.endian);
- elf_section.sh_addr = try in.readInt(u64, elf.endian);
- elf_section.sh_offset = try in.readInt(u64, elf.endian);
- elf_section.sh_size = try in.readInt(u64, elf.endian);
- elf_section.sh_link = try in.readInt(u32, elf.endian);
- elf_section.sh_info = try in.readInt(u32, elf.endian);
- elf_section.sh_addralign = try in.readInt(u64, elf.endian);
- elf_section.sh_entsize = try in.readInt(u64, elf.endian);
- }
- } else {
- for (elf.section_headers) |*elf_section| {
- // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
- elf_section.sh_name = try in.readInt(u32, elf.endian);
- elf_section.sh_type = try in.readInt(u32, elf.endian);
- elf_section.sh_flags = @as(u64, try in.readInt(u32, elf.endian));
- elf_section.sh_addr = @as(u64, try in.readInt(u32, elf.endian));
- elf_section.sh_offset = @as(u64, try in.readInt(u32, elf.endian));
- elf_section.sh_size = @as(u64, try in.readInt(u32, elf.endian));
- elf_section.sh_link = try in.readInt(u32, elf.endian);
- elf_section.sh_info = try in.readInt(u32, elf.endian);
- elf_section.sh_addralign = @as(u64, try in.readInt(u32, elf.endian));
- elf_section.sh_entsize = @as(u64, try in.readInt(u32, elf.endian));
- }
- }
-
- for (elf.section_headers) |*elf_section| {
- if (elf_section.sh_type != SHT_NOBITS) {
- const file_end_offset = try math.add(u64, elf_section.sh_offset, elf_section.sh_size);
- if (stream_end < file_end_offset) return error.InvalidFormat;
- }
- }
-
- elf.string_section = &elf.section_headers[elf.string_section_index];
- if (elf.string_section.sh_type != SHT_STRTAB) {
- // not a string table
- return error.InvalidFormat;
- }
-
- return elf;
- }
-
- pub fn close(elf: *Elf) void {
- elf.allocator.free(elf.section_headers);
- elf.allocator.free(elf.program_headers);
- }
-
- pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
- section_loop: for (elf.section_headers) |*elf_section| {
- if (elf_section.sh_type == SHT_NULL) continue;
-
- const name_offset = elf.string_section.sh_offset + elf_section.sh_name;
- try elf.seekable_stream.seekTo(name_offset);
-
- for (name) |expected_c| {
- const target_c = try elf.in_stream.readByte();
- if (target_c == 0 or expected_c != target_c) continue :section_loop;
- }
-
- {
- const null_byte = try elf.in_stream.readByte();
- if (null_byte == 0) return elf_section;
- }
- }
-
- return null;
- }
-
- pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {
- try elf.seekable_stream.seekTo(elf_section.sh_offset);
- }
};
+pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
+ var hdrs: AllHeaders = .{
+ .allocator = allocator,
+ .header = try readHeader(file),
+ .section_headers = undefined,
+ .program_headers = undefined,
+ };
+ const is_64 = hdrs.header.is_64;
+ const need_bswap = hdrs.header.endian != std.builtin.endian;
+
+ hdrs.section_headers = try allocator.alloc(Elf64_Shdr, hdrs.header.shnum);
+ errdefer hdrs.allocator.free(hdrs.section_headers);
+
+ hdrs.program_headers = try allocator.alloc(Elf64_Phdr, hdrs.header.phnum);
+ errdefer hdrs.allocator.free(hdrs.program_headers);
+
+ // Treat section headers and program headers as byte buffers. For 32-bit ELF and
+ // non-matching endian files, we post-process to correct integer endianness and offsets.
+
+ const shdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];
+ const phdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
+
+ try file.preadAll(phdr_buf, hdrs.header.phoff);
+ try file.preadAll(shdr_buf, hdrs.header.shoff);
+
+ const shdrs32 = @ptrCast([*]Elf32_Shdr, @alignCast(@alignOf(Elf32_Shdr), shdr_buf.ptr))[0..hdrs.header.shnum];
+ const phdrs32 = @ptrCast([*]Elf32_Phdr, @alignCast(@alignOf(Elf32_Phdr), phdr_buf.ptr))[0..hdrs.header.phnum];
+ for (hdrs.section_headers) |*shdr, i| {
+ shdr.* = .{
+ .sh_name = int(is_64, need_bswap, shdrs32[i].sh_name, shdr.sh_name),
+ .sh_type = int(is_64, need_bswap, shdrs32[i].sh_type, shdr.sh_type),
+ .sh_flags = int(is_64, need_bswap, shdrs32[i].sh_flags, shdr.sh_flags),
+ .sh_addr = int(is_64, need_bswap, shdrs32[i].sh_addr, shdr.sh_addr),
+ .sh_offset = int(is_64, need_bswap, shdrs32[i].sh_offset, shdr.sh_offset),
+ .sh_size = int(is_64, need_bswap, shdrs32[i].sh_size, shdr.sh_size),
+ .sh_link = int(is_64, need_bswap, shdrs32[i].sh_link, shdr.sh_link),
+ .sh_info = int(is_64, need_bswap, shdrs32[i].sh_info, shdr.sh_info),
+ .sh_addralign = int(is_64, need_bswap, shdrs32[i].sh_addralign, shdr.sh_addralign),
+ .sh_entsize = int(is_64, need_bswap, shdrs32[i].sh_entsize, shdr.sh_entsize),
+ };
+ }
+ for (hdrs.program_headers) |*phdr, i| {
+ phdr.* = .{
+ .p_type = int(is_64, need_bswap, phdrs32[i].p_type, shdr.p_type),
+ .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, shdr.p_offset),
+ .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, shdr.p_vaddr),
+ .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, shdr.p_paddr),
+ .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, shdr.p_filesz),
+ .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, shdr.p_memsz),
+ .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, shdr.p_flags),
+ .p_align = int(is_64, need_bswap, phdrs32[i].p_align, shdr.p_align),
+ };
+ }
+ return hdrs;
+}
+
+pub fn int(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
+ if (is_64) {
+ if (need_bswap) {
+ return @byteSwap(@TypeOf(int_64), int_64);
+ } else {
+ return int_64;
+ }
+ } else {
+ if (need_bswap) {
+ return @byteSwap(@TypeOf(int_32), int_32);
+ } else {
+ return int_32;
+ }
+ }
+}
+
pub const EI_NIDENT = 16;
pub const EI_CLASS = 4;
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 336dd0d3149652d5f0dcd3af10b4899edfe3fcec..e7953a1a9127d7e492dba4b02c24b5548f8f77bd 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -570,7 +570,7 @@ pub const NativeTargetInfo = struct {
cross_target: CrossTarget,
) AbiAndDynamicLinkerFromFileError!NativeTargetInfo {
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
- _ = try preadFull(file, &hdr_buf, 0, hdr_buf.len);
+ _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
@@ -587,6 +587,7 @@ pub const NativeTargetInfo = struct {
elf.ELFCLASS64 => true,
else => return error.InvalidElfClass,
};
+ const elfInt = elf.int;
var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);
const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);
const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
@@ -610,7 +611,7 @@ pub const NativeTargetInfo = struct {
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
- const ph_read_byte_len = try preadFull(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
+ const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
var ph_buf_i: usize = 0;
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
ph_i += 1;
@@ -625,7 +626,7 @@ pub const NativeTargetInfo = struct {
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
- _ = try preadFull(file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
+ _ = try preadMin(file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
// PT_INTERP includes a null byte in p_filesz.
const len = p_filesz - 1;
// dynamic_linker.max_byte is "max", not "len".
@@ -656,7 +657,7 @@ pub const NativeTargetInfo = struct {
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
- const dyn_read_byte_len = try preadFull(
+ const dyn_read_byte_len = try preadMin(
file,
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
dyn_off,
@@ -701,14 +702,14 @@ pub const NativeTargetInfo = struct {
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
if (sh_buf.len < shentsize) return error.InvalidElfFile;
- _ = try preadFull(file, &sh_buf, str_section_off, shentsize);
+ _ = try preadMin(file, &sh_buf, str_section_off, shentsize);
const shstr32 = @ptrCast(*elf.Elf32_Shdr, @alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf));
const shstr64 = @ptrCast(*elf.Elf64_Shdr, @alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf));
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
var strtab_buf: [4096:0]u8 = undefined;
const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
- const shstrtab_read_len = try preadFull(file, &strtab_buf, shstrtab_off, shstrtab_len);
+ const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
const shstrtab = strtab_buf[0..shstrtab_read_len];
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
@@ -717,7 +718,7 @@ pub const NativeTargetInfo = struct {
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
- const sh_read_byte_len = try preadFull(
+ const sh_read_byte_len = try preadMin(
file,
sh_buf[0 .. sh_buf.len - sh_reserve],
shoff,
@@ -751,7 +752,7 @@ pub const NativeTargetInfo = struct {
if (dynstr) |ds| {
const strtab_len = std.math.min(ds.size, strtab_buf.len);
- const strtab_read_len = try preadFull(file, &strtab_buf, ds.offset, shstrtab_len);
+ const strtab_read_len = try preadMin(file, &strtab_buf, ds.offset, shstrtab_len);
const strtab = strtab_buf[0..strtab_read_len];
// TODO this pointer cast should not be necessary
const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
@@ -813,7 +814,7 @@ pub const NativeTargetInfo = struct {
return result;
}
- fn preadFull(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
+ fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
var i: u64 = 0;
while (i < min_read_len) {
const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) {
@@ -853,22 +854,6 @@ pub const NativeTargetInfo = struct {
abi: Target.Abi,
};
- fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
- if (is_64) {
- if (need_bswap) {
- return @byteSwap(@TypeOf(int_64), int_64);
- } else {
- return int_64;
- }
- } else {
- if (need_bswap) {
- return @byteSwap(@TypeOf(int_32), int_32);
- } else {
- return int_32;
- }
- }
- }
-
fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu {
// Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,
// although it is a runtime value, is guaranteed to be one of the architectures in the set
--
2.54.0
From 21809c33001cc53c8fb3b56b25264e8d9076bed9 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Wed, 11 Mar 2020 09:24:53 +0200
Subject: [PATCH 051/111] support non power of two integers in atomic ops
---
src/all_types.hpp | 8 +++++
src/codegen.cpp | 45 ++++++++++++------------
src/ir.cpp | 87 +++++++++++++++++++++++------------------------
3 files changed, 73 insertions(+), 67 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 14b99228ca1c3fe8ef1f2f15155f39840055267e..149b7f46470603f0e2182fee4dd6feb2d2721678 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3567,6 +3567,8 @@ struct IrInstGenCmpxchg {
IrInstGen *cmp_value;
IrInstGen *new_value;
IrInstGen *result_loc;
+ // non null if operand needs widening and truncating
+ ZigType *actual_type;
bool is_weak;
};
@@ -4199,6 +4201,8 @@ struct IrInstGenAtomicRmw {
IrInstGen *ptr;
IrInstGen *operand;
+ // non null if operand needs widening and truncating
+ ZigType *actual_type;
AtomicRmwOp op;
AtomicOrder ordering;
};
@@ -4215,6 +4219,8 @@ struct IrInstGenAtomicLoad {
IrInstGen base;
IrInstGen *ptr;
+ // non null if operand needs widening and truncating
+ ZigType *actual_type;
AtomicOrder ordering;
};
@@ -4232,6 +4238,8 @@ struct IrInstGenAtomicStore {
IrInstGen *ptr;
IrInstGen *value;
+ // non null if operand needs widening and truncating
+ ZigType *actual_type;
AtomicOrder ordering;
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7238d5041b4693262facad6be138667e0c1b9c27..cfb3de292aa15d9d57c1fbdd57ad086bcc2d1f12 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5225,12 +5225,12 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
ZigType *operand_type = instruction->new_value->value->type;
- if (operand_type->id == ZigTypeIdBool) {
- // treat bool as u8
+ if (instruction->actual_type != nullptr) {
+ // operand needs widening and truncating
ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
- LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
- cmp_val = LLVMConstZExt(cmp_val, g->builtin_types.entry_u8->llvm_type);
- new_val = LLVMConstZExt(new_val, g->builtin_types.entry_u8->llvm_type);
+ LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
+ cmp_val = LLVMConstZExt(cmp_val, get_llvm_type(g, instruction->actual_type));
+ new_val = LLVMConstZExt(new_val, get_llvm_type(g, instruction->actual_type));
}
LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
@@ -5245,8 +5245,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
if (!handle_is_ptr(g, optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- if (operand_type->id == ZigTypeIdBool) {
- payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
+ if (instruction->actual_type != nullptr) {
+ payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
}
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
@@ -5262,8 +5262,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
ir_assert(type_has_bits(g, child_type), &instruction->base);
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- if (operand_type->id == ZigTypeIdBool) {
- payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
+ if (instruction->actual_type != nullptr) {
+ payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
}
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
@@ -5842,14 +5842,14 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
- if (operand_type->id == ZigTypeIdBool) {
- // treat bool as u8
+ if (instruction->actual_type != nullptr) {
+ // operand needs widening and truncating
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
- LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_u8->llvm_type, "");
+ LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
+ LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, get_llvm_type(g, instruction->actual_type), "");
LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
g->is_single_threaded);
- return LLVMBuildTrunc(g->builder, uncasted_result, g->builtin_types.entry_bool->llvm_type, "");
+ return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
}
if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {
@@ -5872,13 +5872,13 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type;
- if (operand_type->id == ZigTypeIdBool) {
- // treat bool as u8
+ if (instruction->actual_type != nullptr) {
+ // operand needs widening and truncating
ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
+ LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
LLVMSetOrdering(load_inst, ordering);
- return LLVMBuildTrunc(g->builder, load_inst, g->builtin_types.entry_bool->llvm_type, "");
+ return LLVMBuildTrunc(g->builder, load_inst, get_llvm_type(g, operand_type), "");
}
LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
LLVMSetOrdering(load_inst, ordering);
@@ -5892,12 +5892,11 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef value = ir_llvm_value(g, instruction->value);
- ZigType *operand_type = instruction->value->value->type;
- if (operand_type->id == ZigTypeIdBool) {
- // treat bool as u8
+ if (instruction->actual_type != nullptr) {
+ // operand needs widening and truncating
ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
- value = LLVMConstZExt(value, g->builtin_types.entry_u8->llvm_type);
+ LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
+ value = LLVMConstZExt(value, get_llvm_type(g, instruction->actual_type));
}
LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
LLVMSetOrdering(store_inst, ordering);
diff --git a/src/ir.cpp b/src/ir.cpp
index cad1d382e16ecac6b5ba1a9c99f825909d420d85..9465be8b0b2466918250d0427be90d12ccf1a87d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -227,7 +227,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
static void ir_assert(bool ok, IrInst* source_instruction);
static void ir_assert_gen(bool ok, IrInstGen *source_instruction);
static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var);
-static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
+static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, ZigType **actual_type);
static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
@@ -3406,7 +3406,7 @@ static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode
static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type,
IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value,
- AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc)
+ AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc, ZigType *actual_type)
{
IrInstGenCmpxchg *instruction = ir_build_inst_gen(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
@@ -3418,6 +3418,7 @@ static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instructio
instruction->failure_order = failure_order;
instruction->is_weak = is_weak;
instruction->result_loc = result_loc;
+ instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(cmp_value, ira->new_irb.current_basic_block);
@@ -4554,7 +4555,7 @@ static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNo
}
static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type)
+ IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type, ZigType *actual_type)
{
IrInstGenAtomicRmw *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node);
instruction->base.value->type = operand_type;
@@ -4562,6 +4563,7 @@ static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr,
instruction->op = op;
instruction->operand = operand;
instruction->ordering = ordering;
+ instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(operand, ira->new_irb.current_basic_block);
@@ -4585,13 +4587,14 @@ static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstN
}
static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type)
+ IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type, ZigType *actual_type)
{
IrInstGenAtomicLoad *instruction = ir_build_inst_gen(&ira->new_irb,
source_instr->scope, source_instr->source_node);
instruction->base.value->type = operand_type;
instruction->ptr = ptr;
instruction->ordering = ordering;
+ instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
@@ -4616,13 +4619,14 @@ static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, Ast
}
static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering)
+ IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering, ZigType *actual_type)
{
IrInstGenAtomicStore *instruction = ir_build_inst_void(&ira->new_irb,
source_instr->scope, source_instr->source_node);
instruction->ptr = ptr;
instruction->value = value;
instruction->ordering = ordering;
+ instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(value, ira->new_irb.current_basic_block);
@@ -25121,7 +25125,8 @@ static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmb
}
static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxchg *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
+ ZigType *actual_type;
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child, &actual_type);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -25213,7 +25218,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
return ir_build_cmpxchg_gen(ira, &instruction->base.base, result_type,
casted_ptr, casted_cmp_value, casted_new_value,
- success_order, failure_order, instruction->is_weak, result_loc);
+ success_order, failure_order, instruction->is_weak, result_loc, actual_type);
}
static IrInstGen *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstSrcFence *instruction) {
@@ -28305,17 +28310,15 @@ static IrInstGen *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstSrcTagTy
}
}
-static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
+static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, ZigType **actual_type) {
ZigType *operand_type = ir_resolve_type(ira, op);
if (type_is_invalid(operand_type))
return ira->codegen->builtin_types.entry_invalid;
- if (operand_type->id == ZigTypeIdInt) {
- if (operand_type->data.integral.bit_count < 8) {
- ir_add_error(ira, &op->base,
- buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type",
- operand_type->data.integral.bit_count));
- return ira->codegen->builtin_types.entry_invalid;
+ *actual_type = nullptr;
+ if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
+ if (operand_type->id == ZigTypeIdEnum) {
+ operand_type = operand_type->data.enumeration.tag_int_type;
}
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
if (operand_type->data.integral.bit_count > max_atomic_bits) {
@@ -28324,30 +28327,22 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
max_atomic_bits, operand_type->data.integral.bit_count));
return ira->codegen->builtin_types.entry_invalid;
}
- if (!is_power_of_2(operand_type->data.integral.bit_count)) {
- ir_add_error(ira, &op->base,
- buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count));
- return ira->codegen->builtin_types.entry_invalid;
- }
- } else if (operand_type->id == ZigTypeIdEnum) {
- ZigType *int_type = operand_type->data.enumeration.tag_int_type;
- if (int_type->data.integral.bit_count < 8) {
- ir_add_error(ira, &op->base,
- buf_sprintf("expected enum tag type 8 bits or larger, found %" PRIu32 "-bit tag type",
- int_type->data.integral.bit_count));
- return ira->codegen->builtin_types.entry_invalid;
- }
- uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
- if (int_type->data.integral.bit_count > max_atomic_bits) {
- ir_add_error(ira, &op->base,
- buf_sprintf("expected %" PRIu32 "-bit enum tag type or smaller, found %" PRIu32 "-bit tag type",
- max_atomic_bits, int_type->data.integral.bit_count));
- return ira->codegen->builtin_types.entry_invalid;
- }
- if (!is_power_of_2(int_type->data.integral.bit_count)) {
- ir_add_error(ira, &op->base,
- buf_sprintf("%" PRIu32 "-bit enum tag type is not a power of 2", int_type->data.integral.bit_count));
- return ira->codegen->builtin_types.entry_invalid;
+ auto bit_count = operand_type->data.integral.bit_count;
+ bool is_signed = operand_type->data.integral.is_signed;
+ if (bit_count < 2 || !is_power_of_2(bit_count)) {
+ if (bit_count < 8) {
+ *actual_type = get_int_type(ira->codegen, is_signed, 8);
+ } else if (bit_count < 16) {
+ *actual_type = get_int_type(ira->codegen, is_signed, 16);
+ } else if (bit_count < 32) {
+ *actual_type = get_int_type(ira->codegen, is_signed, 32);
+ } else if (bit_count < 64) {
+ *actual_type = get_int_type(ira->codegen, is_signed, 64);
+ } else if (bit_count < 128) {
+ *actual_type = get_int_type(ira->codegen, is_signed, 128);
+ } else {
+ zig_unreachable();
+ }
}
} else if (operand_type->id == ZigTypeIdFloat) {
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
@@ -28359,6 +28354,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
}
} else if (operand_type->id == ZigTypeIdBool) {
// will be treated as u8
+ *actual_type = ira->codegen->builtin_types.entry_u8;
} else {
Error err;
ZigType *operand_ptr_type;
@@ -28376,7 +28372,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
}
static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAtomicRmw *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
+ ZigType *actual_type;
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28434,11 +28431,12 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
}
return ir_build_atomic_rmw_gen(ira, &instruction->base.base, casted_ptr, casted_operand, op,
- ordering, operand_type);
+ ordering, operand_type, actual_type);
}
static IrInstGen *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstSrcAtomicLoad *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
+ ZigType *actual_type;
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28468,11 +28466,12 @@ static IrInstGen *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstSrcAt
return result;
}
- return ir_build_atomic_load_gen(ira, &instruction->base.base, casted_ptr, ordering, operand_type);
+ return ir_build_atomic_load_gen(ira, &instruction->base.base, casted_ptr, ordering, operand_type, actual_type);
}
static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcAtomicStore *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
+ ZigType *actual_type;
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28511,7 +28510,7 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
return result;
}
- return ir_build_atomic_store_gen(ira, &instruction->base.base, casted_ptr, casted_value, ordering);
+ return ir_build_atomic_store_gen(ira, &instruction->base.base, casted_ptr, casted_value, ordering, actual_type);
}
static IrInstGen *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstSrcSaveErrRetAddr *instruction) {
--
2.54.0
From 64e60d8ae2c06689a2e0533eb43a1c6a8ff01259 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Wed, 11 Mar 2020 10:29:15 +0200
Subject: [PATCH 052/111] special case atomic operations on zero bit types
---
src/ir.cpp | 37 ++++++++++++++++++++++++++------
test/stage1/behavior/atomics.zig | 27 ++++++++++++++++-------
2 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 9465be8b0b2466918250d0427be90d12ccf1a87d..2e87bd2687ecaeb538d6fc904fdf623251d783ef 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25199,12 +25199,22 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
return ira->codegen->invalid_inst_gen;
}
+ ZigType *result_type = get_optional_type(ira->codegen, operand_type);
+
+ // special case zero bit types
+ if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
+ ZigValue *val = ira->codegen->pass1_arena->allocate(1);
+ val->special = ConstValSpecialStatic;
+ val->type = result_type;
+ set_optional_value_to_null(val);
+ return ir_const_move(ira, &instruction->base.base, val);
+ }
+
if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
zig_panic("TODO compile-time execution of cmpxchg");
}
- ZigType *result_type = get_optional_type(ira->codegen, operand_type);
IrInstGen *result_loc;
if (handle_is_ptr(ira->codegen, result_type)) {
result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
@@ -28317,18 +28327,23 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
*actual_type = nullptr;
if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
+ ZigType *int_type;
if (operand_type->id == ZigTypeIdEnum) {
- operand_type = operand_type->data.enumeration.tag_int_type;
+ int_type = operand_type->data.enumeration.tag_int_type;
+ } else {
+ int_type = operand_type;
}
+ auto bit_count = int_type->data.integral.bit_count;
+ bool is_signed = int_type->data.integral.is_signed;
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
- if (operand_type->data.integral.bit_count > max_atomic_bits) {
+
+ if (bit_count > max_atomic_bits) {
ir_add_error(ira, &op->base,
buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
- max_atomic_bits, operand_type->data.integral.bit_count));
+ max_atomic_bits, bit_count));
return ira->codegen->builtin_types.entry_invalid;
}
- auto bit_count = operand_type->data.integral.bit_count;
- bool is_signed = operand_type->data.integral.is_signed;
+
if (bit_count < 2 || !is_power_of_2(bit_count)) {
if (bit_count < 8) {
*actual_type = get_int_type(ira->codegen, is_signed, 8);
@@ -28423,6 +28438,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
return ira->codegen->invalid_inst_gen;
}
+ // special case zero bit types
+ if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
+ return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
+ }
+
if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar)
{
ir_add_error(ira, &instruction->base.base,
@@ -28504,6 +28524,11 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
return ira->codegen->invalid_inst_gen;
}
+ // special case zero bit types
+ if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
+ return ir_const_void(ira, &instruction->base.base);
+ }
+
if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false);
result->value->type = ira->codegen->builtin_types.entry_void;
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index bda0a8469ce091d9b7e8df871e8f63d4fd2273c3..edc712d85b884249c6b4fbc881d724f64f5d53d6 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -162,12 +162,23 @@ fn testAtomicRmwFloat() void {
expect(x == 4);
}
-test "atomics with bool" {
- var x = false;
- @atomicStore(bool, &x, true, .SeqCst);
- expect(x == true);
- expect(@atomicLoad(bool, &x, .SeqCst) == true);
- expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
- expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
- expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
+test "atomics with different types" {
+ // testAtomicsWithType(bool, true, false);
+ // inline for (.{ u1, i5, u33 }) |T| {
+ // var x: T = 0;
+ // testAtomicsWithType(T, 0, 1);
+ // }
+ testAtomicsWithType(u0, 0, 0);
+ testAtomicsWithType(i0, 0, 0);
+}
+
+fn testAtomicsWithType(comptime T: type, a: T, b: T) void {
+ var x: T = b;
+ @atomicStore(T, &x, a, .SeqCst);
+ expect(x == a);
+ expect(@atomicLoad(T, &x, .SeqCst) == a);
+ expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
+ expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
+ if (@sizeOf(T) != 0)
+ expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
}
--
2.54.0
From 1f66435a6b0c5ccf6e4e96df0ed96732480ab4db Mon Sep 17 00:00:00 2001
From: Vexu
Date: Wed, 11 Mar 2020 12:02:05 +0200
Subject: [PATCH 053/111] support cmpxchg at comptime
---
src/ir.cpp | 32 ++++++++++++------------
test/stage1/behavior/atomics.zig | 42 +++++++++++++++++---------------
2 files changed, 39 insertions(+), 35 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 2e87bd2687ecaeb538d6fc904fdf623251d783ef..338f803bbe874999a0918deaf1f34d9eb9214368 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25212,7 +25212,20 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
- zig_panic("TODO compile-time execution of cmpxchg");
+ IrInstGen *result = ir_get_deref(ira, &instruction->base.base, casted_ptr, nullptr);
+ ZigValue *op1_val = ir_resolve_const(ira, result, UndefBad);
+ ZigValue *op2_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
+ bool eql = const_values_equal(ira->codegen, op1_val, op2_val);
+ ZigValue *val = ira->codegen->pass1_arena->allocate(1);
+ val->special = ConstValSpecialStatic;
+ val->type = result_type;
+ if (eql) {
+ ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, casted_new_value, false);
+ set_optional_value_to_null(val);
+ } else {
+ set_optional_payload(val, op1_val);
+ }
+ return ir_const_move(ira, &instruction->base.base, val);
}
IrInstGen *result_loc;
@@ -28334,7 +28347,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
int_type = operand_type;
}
auto bit_count = int_type->data.integral.bit_count;
- bool is_signed = int_type->data.integral.is_signed;
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
if (bit_count > max_atomic_bits) {
@@ -28344,20 +28356,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
return ira->codegen->builtin_types.entry_invalid;
}
- if (bit_count < 2 || !is_power_of_2(bit_count)) {
- if (bit_count < 8) {
- *actual_type = get_int_type(ira->codegen, is_signed, 8);
- } else if (bit_count < 16) {
- *actual_type = get_int_type(ira->codegen, is_signed, 16);
- } else if (bit_count < 32) {
- *actual_type = get_int_type(ira->codegen, is_signed, 32);
- } else if (bit_count < 64) {
- *actual_type = get_int_type(ira->codegen, is_signed, 64);
- } else if (bit_count < 128) {
- *actual_type = get_int_type(ira->codegen, is_signed, 128);
- } else {
- zig_unreachable();
- }
+ if (bit_count == 1 || !is_power_of_2(bit_count)) {
+ *actual_type = get_int_type(ira->codegen, int_type->data.integral.is_signed, int_type->abi_size * 8);
}
} else if (operand_type->id == ZigTypeIdFloat) {
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index edc712d85b884249c6b4fbc881d724f64f5d53d6..9c75afc36947e8cf3c8733f1b0c59fd167ebdc29 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -2,29 +2,32 @@ const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const builtin = @import("builtin");
-const AtomicRmwOp = builtin.AtomicRmwOp;
-const AtomicOrder = builtin.AtomicOrder;
test "cmpxchg" {
+ testCmpxchg();
+ comptime testCmpxchg();
+}
+
+fn testCmpxchg() void {
var x: i32 = 1234;
- if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
expect(x1 == 1234);
} else {
@panic("cmpxchg should have failed");
}
- while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
expect(x1 == 1234);
}
expect(x == 5678);
- expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
expect(x == 42);
}
test "fence" {
var x: i32 = 1234;
- @fence(AtomicOrder.SeqCst);
+ @fence(.SeqCst);
x = 5678;
}
@@ -36,18 +39,18 @@ test "atomicrmw and atomicload" {
}
fn testAtomicRmw(ptr: *u8) void {
- const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
+ const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
expect(prev_value == 200);
comptime {
var x: i32 = 1234;
const y: i32 = 12345;
- expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
- expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
+ expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
+ expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
}
}
fn testAtomicLoad(ptr: *u8) void {
- const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
+ const x = @atomicLoad(u8, ptr, .SeqCst);
expect(x == 42);
}
@@ -56,18 +59,18 @@ test "cmpxchg with ptr" {
var data2: i32 = 5678;
var data3: i32 = 9101;
var x: *i32 = &data1;
- if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
expect(x1 == &data1);
} else {
@panic("cmpxchg should have failed");
}
- while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
expect(x1 == &data1);
}
expect(x == &data3);
- expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
expect(x == &data2);
}
@@ -163,16 +166,17 @@ fn testAtomicRmwFloat() void {
}
test "atomics with different types" {
- // testAtomicsWithType(bool, true, false);
- // inline for (.{ u1, i5, u33 }) |T| {
- // var x: T = 0;
- // testAtomicsWithType(T, 0, 1);
- // }
+ testAtomicsWithType(bool, true, false);
+ inline for (.{ u1, i5, u33 }) |T| {
+ var x: T = 0;
+ testAtomicsWithType(T, 0, 1);
+ }
testAtomicsWithType(u0, 0, 0);
testAtomicsWithType(i0, 0, 0);
}
-fn testAtomicsWithType(comptime T: type, a: T, b: T) void {
+// a and b souldn't need to be comptime
+fn testAtomicsWithType(comptime T: type, comptime a: T, comptime b: T) void {
var x: T = b;
@atomicStore(T, &x, a, .SeqCst);
expect(x == a);
--
2.54.0
From ec906a97712b329694e8f2e1a35b50b75d052642 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Wed, 11 Mar 2020 13:29:17 +0200
Subject: [PATCH 054/111] fix codegen, update docs
---
doc/langref.html.in | 45 +++++++-------------------------
src/codegen.cpp | 10 +++----
test/stage1/behavior/atomics.zig | 5 ++--
3 files changed, 17 insertions(+), 43 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 447d545975f814fcfe9928f9bed7d85d2e6a86f0..0dedb48b1c674d29cc6b469ee1e4007f648889bf 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6728,17 +6728,8 @@ async fn func(y: *i32) void {
This builtin function atomically dereferences a pointer and returns the value.
- {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float,
- an integer whose bit count meets these requirements:
-
-
- - At least 8
- - At most the same as usize
- - Power of 2
-
or an enum with a valid integer tag type.
-
- TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
- we can remove this restriction
+ {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,
+ an integer or an enum.
{#header_close#}
{#header_open|@atomicRmw#}
@@ -6747,17 +6738,8 @@ async fn func(y: *i32) void {
This builtin function atomically modifies memory and then returns the previous value.
- {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#},
- or an integer whose bit count meets these requirements:
-
-
- - At least 8
- - At most the same as usize
- - Power of 2
-
-
- TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
- we can remove this restriction
+ {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,
+ an integer or an enum.
Supported operations:
@@ -6782,17 +6764,8 @@ async fn func(y: *i32) void {
This builtin function atomically stores a value.
- {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float,
- an integer whose bit count meets these requirements:
-
-
- - At least 8
- - At most the same as usize
- - Power of 2
-
or an enum with a valid integer tag type.
-
- TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
- we can remove this restriction
+ {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,
+ an integer or an enum.
{#header_close#}
{#header_open|@bitCast#}
@@ -7108,7 +7081,8 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
more efficiently in machine instructions.
- {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
+ {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,
+ an integer or an enum.
{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}
{#see_also|Compile Variables|cmpxchgWeak#}
@@ -7136,7 +7110,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
- {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
+ {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,
+ an integer or an enum.
{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}
{#see_also|Compile Variables|cmpxchgStrong#}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index cfb3de292aa15d9d57c1fbdd57ad086bcc2d1f12..66cf919d883b12a1ff91a284e0e476fe293130ec 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5229,8 +5229,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
// operand needs widening and truncating
ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- cmp_val = LLVMConstZExt(cmp_val, get_llvm_type(g, instruction->actual_type));
- new_val = LLVMConstZExt(new_val, get_llvm_type(g, instruction->actual_type));
+ cmp_val = LLVMBuildZExt(g->builder, cmp_val, get_llvm_type(g, instruction->actual_type), "");
+ new_val = LLVMBuildZExt(g->builder, new_val, get_llvm_type(g, instruction->actual_type), "");
}
LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
@@ -5846,7 +5846,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
// operand needs widening and truncating
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, get_llvm_type(g, instruction->actual_type), "");
+ LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, get_llvm_type(g, instruction->actual_type), "");
LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
g->is_single_threaded);
return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
@@ -5893,10 +5893,10 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
LLVMValueRef value = ir_llvm_value(g, instruction->value);
if (instruction->actual_type != nullptr) {
- // operand needs widening and truncating
+ // operand needs widening
ptr = LLVMBuildBitCast(g->builder, ptr,
LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- value = LLVMConstZExt(value, get_llvm_type(g, instruction->actual_type));
+ value = LLVMBuildZExt(g->builder, value, get_llvm_type(g, instruction->actual_type), "");
}
LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
LLVMSetOrdering(store_inst, ordering);
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index 9c75afc36947e8cf3c8733f1b0c59fd167ebdc29..c655bfe7a4046fe8edd9d273ed172eadf2697346 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -167,7 +167,7 @@ fn testAtomicRmwFloat() void {
test "atomics with different types" {
testAtomicsWithType(bool, true, false);
- inline for (.{ u1, i5, u33 }) |T| {
+ inline for (.{ u1, i5, u15 }) |T| {
var x: T = 0;
testAtomicsWithType(T, 0, 1);
}
@@ -175,8 +175,7 @@ test "atomics with different types" {
testAtomicsWithType(i0, 0, 0);
}
-// a and b souldn't need to be comptime
-fn testAtomicsWithType(comptime T: type, comptime a: T, comptime b: T) void {
+fn testAtomicsWithType(comptime T: type, a: T, b: T) void {
var x: T = b;
@atomicStore(T, &x, a, .SeqCst);
expect(x == a);
--
2.54.0
From 9262f065f50db3ea72454b6c1b9b66fd911aa6ba Mon Sep 17 00:00:00 2001
From: Vexu
Date: Wed, 11 Mar 2020 16:46:12 +0200
Subject: [PATCH 055/111] Move abi size checking to codegen
---
lib/std/atomic/int.zig | 13 +++-----
src/all_types.hpp | 8 -----
src/codegen.cpp | 61 +++++++++++++++++++++++++++--------
src/ir.cpp | 73 ++++++++++++++++++------------------------
4 files changed, 84 insertions(+), 71 deletions(-)
diff --git a/lib/std/atomic/int.zig b/lib/std/atomic/int.zig
index 94985b914faea8831bf12bcbbd2282656ab796f6..446059e7ef66723b4d765b7fa213ca752189d756 100644
--- a/lib/std/atomic/int.zig
+++ b/lib/std/atomic/int.zig
@@ -1,6 +1,3 @@
-const builtin = @import("builtin");
-const AtomicOrder = builtin.AtomicOrder;
-
/// Thread-safe, lock-free integer
pub fn Int(comptime T: type) type {
return struct {
@@ -14,16 +11,16 @@ pub fn Int(comptime T: type) type {
/// Returns previous value
pub fn incr(self: *Self) T {
- return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
+ return @atomicRmw(T, &self.unprotected_value, .Add, 1, .SeqCst);
}
/// Returns previous value
pub fn decr(self: *Self) T {
- return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);
+ return @atomicRmw(T, &self.unprotected_value, .Sub, 1, .SeqCst);
}
pub fn get(self: *Self) T {
- return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);
+ return @atomicLoad(T, &self.unprotected_value, .SeqCst);
}
pub fn set(self: *Self, new_value: T) void {
@@ -31,11 +28,11 @@ pub fn Int(comptime T: type) type {
}
pub fn xchg(self: *Self, new_value: T) T {
- return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
+ return @atomicRmw(T, &self.unprotected_value, .Xchg, new_value, .SeqCst);
}
pub fn fetchAdd(self: *Self, op: T) T {
- return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Add, op, AtomicOrder.SeqCst);
+ return @atomicRmw(T, &self.unprotected_value, .Add, op, .SeqCst);
}
};
}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 149b7f46470603f0e2182fee4dd6feb2d2721678..14b99228ca1c3fe8ef1f2f15155f39840055267e 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3567,8 +3567,6 @@ struct IrInstGenCmpxchg {
IrInstGen *cmp_value;
IrInstGen *new_value;
IrInstGen *result_loc;
- // non null if operand needs widening and truncating
- ZigType *actual_type;
bool is_weak;
};
@@ -4201,8 +4199,6 @@ struct IrInstGenAtomicRmw {
IrInstGen *ptr;
IrInstGen *operand;
- // non null if operand needs widening and truncating
- ZigType *actual_type;
AtomicRmwOp op;
AtomicOrder ordering;
};
@@ -4219,8 +4215,6 @@ struct IrInstGenAtomicLoad {
IrInstGen base;
IrInstGen *ptr;
- // non null if operand needs widening and truncating
- ZigType *actual_type;
AtomicOrder ordering;
};
@@ -4238,8 +4232,6 @@ struct IrInstGenAtomicStore {
IrInstGen *ptr;
IrInstGen *value;
- // non null if operand needs widening and truncating
- ZigType *actual_type;
AtomicOrder ordering;
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 66cf919d883b12a1ff91a284e0e476fe293130ec..55713c1b88c8fc7de08c1983b5143c1dd33cc87e 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5219,18 +5219,48 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool
zig_unreachable();
}
+static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) {
+ // If the operand type of an atomic operation is not a power of two sized
+ // we need to widen it before using it and then truncate the result.
+
+ ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction);
+ ZigType *operand_type = instruction->value->type->data.pointer.child_type;
+ if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
+ if (operand_type->id == ZigTypeIdEnum) {
+ operand_type = operand_type->data.enumeration.tag_int_type;
+ }
+ auto bit_count = operand_type->data.integral.bit_count;
+ bool is_signed = operand_type->data.integral.is_signed;
+
+ ir_assert(bit_count != 0, instruction);
+ if (bit_count == 1 || !is_power_of_2(bit_count)) {
+ return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8));
+ } else {
+ return nullptr;
+ }
+ } else if (operand_type->id == ZigTypeIdFloat) {
+ return nullptr;
+ } else if (operand_type->id == ZigTypeIdBool) {
+ return g->builtin_types.entry_u8->llvm_type;
+ } else {
+ ir_assert(get_codegen_ptr_type_bail(g, operand_type) != nullptr, instruction);
+ return nullptr;
+ }
+}
+
static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, IrInstGenCmpxchg *instruction) {
LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
ZigType *operand_type = instruction->new_value->value->type;
- if (instruction->actual_type != nullptr) {
+ LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr);
+ if (actual_abi_type != nullptr) {
// operand needs widening and truncating
ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
- LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- cmp_val = LLVMBuildZExt(g->builder, cmp_val, get_llvm_type(g, instruction->actual_type), "");
- new_val = LLVMBuildZExt(g->builder, new_val, get_llvm_type(g, instruction->actual_type), "");
+ LLVMPointerType(actual_abi_type, 0), "");
+ cmp_val = LLVMBuildZExt(g->builder, cmp_val, actual_abi_type, "");
+ new_val = LLVMBuildZExt(g->builder, new_val, actual_abi_type, "");
}
LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
@@ -5245,7 +5275,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
if (!handle_is_ptr(g, optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- if (instruction->actual_type != nullptr) {
+ if (actual_abi_type != nullptr) {
payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
}
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
@@ -5262,7 +5292,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
ir_assert(type_has_bits(g, child_type), &instruction->base);
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- if (instruction->actual_type != nullptr) {
+ if (actual_abi_type != nullptr) {
payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), "");
}
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
@@ -5842,11 +5872,12 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
- if (instruction->actual_type != nullptr) {
+ LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr);
+ if (actual_abi_type != nullptr) {
// operand needs widening and truncating
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, get_llvm_type(g, instruction->actual_type), "");
+ LLVMPointerType(actual_abi_type, 0), "");
+ LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, actual_abi_type, "");
LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
g->is_single_threaded);
return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
@@ -5872,10 +5903,11 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type;
- if (instruction->actual_type != nullptr) {
+ LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr);
+ if (actual_abi_type != nullptr) {
// operand needs widening and truncating
ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
+ LLVMPointerType(actual_abi_type, 0), "");
LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
LLVMSetOrdering(load_inst, ordering);
return LLVMBuildTrunc(g->builder, load_inst, get_llvm_type(g, operand_type), "");
@@ -5892,11 +5924,12 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef value = ir_llvm_value(g, instruction->value);
- if (instruction->actual_type != nullptr) {
+ LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr);
+ if (actual_abi_type != nullptr) {
// operand needs widening
ptr = LLVMBuildBitCast(g->builder, ptr,
- LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), "");
- value = LLVMBuildZExt(g->builder, value, get_llvm_type(g, instruction->actual_type), "");
+ LLVMPointerType(actual_abi_type, 0), "");
+ value = LLVMBuildZExt(g->builder, value, actual_abi_type, "");
}
LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
LLVMSetOrdering(store_inst, ordering);
diff --git a/src/ir.cpp b/src/ir.cpp
index 338f803bbe874999a0918deaf1f34d9eb9214368..dc3e7941d6203f8f02e5251efb5ccc616866cba8 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -227,7 +227,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
static void ir_assert(bool ok, IrInst* source_instruction);
static void ir_assert_gen(bool ok, IrInstGen *source_instruction);
static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var);
-static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, ZigType **actual_type);
+static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
@@ -3406,7 +3406,7 @@ static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode
static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type,
IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value,
- AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc, ZigType *actual_type)
+ AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc)
{
IrInstGenCmpxchg *instruction = ir_build_inst_gen(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
@@ -3418,7 +3418,6 @@ static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instructio
instruction->failure_order = failure_order;
instruction->is_weak = is_weak;
instruction->result_loc = result_loc;
- instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(cmp_value, ira->new_irb.current_basic_block);
@@ -4555,7 +4554,7 @@ static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNo
}
static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type, ZigType *actual_type)
+ IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type)
{
IrInstGenAtomicRmw *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node);
instruction->base.value->type = operand_type;
@@ -4563,7 +4562,6 @@ static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr,
instruction->op = op;
instruction->operand = operand;
instruction->ordering = ordering;
- instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(operand, ira->new_irb.current_basic_block);
@@ -4587,14 +4585,13 @@ static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstN
}
static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type, ZigType *actual_type)
+ IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type)
{
IrInstGenAtomicLoad *instruction = ir_build_inst_gen(&ira->new_irb,
source_instr->scope, source_instr->source_node);
instruction->base.value->type = operand_type;
instruction->ptr = ptr;
instruction->ordering = ordering;
- instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
@@ -4619,14 +4616,13 @@ static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, Ast
}
static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr,
- IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering, ZigType *actual_type)
+ IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering)
{
IrInstGenAtomicStore *instruction = ir_build_inst_void(&ira->new_irb,
source_instr->scope, source_instr->source_node);
instruction->ptr = ptr;
instruction->value = value;
instruction->ordering = ordering;
- instruction->actual_type = actual_type;
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(value, ira->new_irb.current_basic_block);
@@ -25125,8 +25121,7 @@ static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmb
}
static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxchg *instruction) {
- ZigType *actual_type;
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child, &actual_type);
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -25203,29 +25198,34 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
// special case zero bit types
if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
- ZigValue *val = ira->codegen->pass1_arena->allocate(1);
- val->special = ConstValSpecialStatic;
- val->type = result_type;
- set_optional_value_to_null(val);
- return ir_const_move(ira, &instruction->base.base, val);
+ IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
+ set_optional_value_to_null(result->value);
+ return result;
}
if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
- IrInstGen *result = ir_get_deref(ira, &instruction->base.base, casted_ptr, nullptr);
- ZigValue *op1_val = ir_resolve_const(ira, result, UndefBad);
+ ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
+ if (ptr_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ ZigValue *op1_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.base.source_node);
+ if (op1_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
ZigValue *op2_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
+ if (op2_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
bool eql = const_values_equal(ira->codegen, op1_val, op2_val);
- ZigValue *val = ira->codegen->pass1_arena->allocate(1);
- val->special = ConstValSpecialStatic;
- val->type = result_type;
+ IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
if (eql) {
ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, casted_new_value, false);
- set_optional_value_to_null(val);
+ set_optional_value_to_null(result->value);
} else {
- set_optional_payload(val, op1_val);
+ set_optional_payload(result->value, op1_val);
}
- return ir_const_move(ira, &instruction->base.base, val);
+ return result;
}
IrInstGen *result_loc;
@@ -25241,7 +25241,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
return ir_build_cmpxchg_gen(ira, &instruction->base.base, result_type,
casted_ptr, casted_cmp_value, casted_new_value,
- success_order, failure_order, instruction->is_weak, result_loc, actual_type);
+ success_order, failure_order, instruction->is_weak, result_loc);
}
static IrInstGen *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstSrcFence *instruction) {
@@ -28333,12 +28333,11 @@ static IrInstGen *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstSrcTagTy
}
}
-static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, ZigType **actual_type) {
+static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
ZigType *operand_type = ir_resolve_type(ira, op);
if (type_is_invalid(operand_type))
return ira->codegen->builtin_types.entry_invalid;
- *actual_type = nullptr;
if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
ZigType *int_type;
if (operand_type->id == ZigTypeIdEnum) {
@@ -28355,10 +28354,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
max_atomic_bits, bit_count));
return ira->codegen->builtin_types.entry_invalid;
}
-
- if (bit_count == 1 || !is_power_of_2(bit_count)) {
- *actual_type = get_int_type(ira->codegen, int_type->data.integral.is_signed, int_type->abi_size * 8);
- }
} else if (operand_type->id == ZigTypeIdFloat) {
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
if (operand_type->data.floating.bit_count > max_atomic_bits) {
@@ -28369,7 +28364,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
}
} else if (operand_type->id == ZigTypeIdBool) {
// will be treated as u8
- *actual_type = ira->codegen->builtin_types.entry_u8;
} else {
Error err;
ZigType *operand_ptr_type;
@@ -28387,8 +28381,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
}
static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAtomicRmw *instruction) {
- ZigType *actual_type;
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28451,12 +28444,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
}
return ir_build_atomic_rmw_gen(ira, &instruction->base.base, casted_ptr, casted_operand, op,
- ordering, operand_type, actual_type);
+ ordering, operand_type);
}
static IrInstGen *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstSrcAtomicLoad *instruction) {
- ZigType *actual_type;
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28486,12 +28478,11 @@ static IrInstGen *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstSrcAt
return result;
}
- return ir_build_atomic_load_gen(ira, &instruction->base.base, casted_ptr, ordering, operand_type, actual_type);
+ return ir_build_atomic_load_gen(ira, &instruction->base.base, casted_ptr, ordering, operand_type);
}
static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcAtomicStore *instruction) {
- ZigType *actual_type;
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child, &actual_type);
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_inst_gen;
@@ -28535,7 +28526,7 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
return result;
}
- return ir_build_atomic_store_gen(ira, &instruction->base.base, casted_ptr, casted_value, ordering, actual_type);
+ return ir_build_atomic_store_gen(ira, &instruction->base.base, casted_ptr, casted_value, ordering);
}
static IrInstGen *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstSrcSaveErrRetAddr *instruction) {
--
2.54.0
From 02ba1d8fe14a034e5873a56b4aef9c2801dc52e9 Mon Sep 17 00:00:00 2001
From: Heppokoyuki
Date: Thu, 12 Mar 2020 00:15:22 +0900
Subject: [PATCH 056/111] add file protocols
---
lib/std/os/uefi/protocols.zig | 4 +
lib/std/os/uefi/protocols/file_protocol.zig | 87 +++++++++++++++++++
.../protocols/simple_file_system_protocol.zig | 21 +++++
3 files changed, 112 insertions(+)
create mode 100644 lib/std/os/uefi/protocols/file_protocol.zig
create mode 100644 lib/std/os/uefi/protocols/simple_file_system_protocol.zig
diff --git a/lib/std/os/uefi/protocols.zig b/lib/std/os/uefi/protocols.zig
index 58f342ac22ca514c036bffaf4fe06098ea39c41a..500a246e2670020102ff408863604f9d035dfbdb 100644
--- a/lib/std/os/uefi/protocols.zig
+++ b/lib/std/os/uefi/protocols.zig
@@ -2,6 +2,10 @@ pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").L
pub const DevicePathProtocol = @import("protocols/device_path_protocol.zig").DevicePathProtocol;
+pub const SimpleFileSystemProtocol = @import("protocols/simple_file_system_protocol.zig").SimpleFileSystemProtocol;
+pub const FileProtocol = @import("protocols/file_protocol.zig").FileProtocol;
+pub const FileInfo = @import("protocols/file_protocol.zig").FileInfo;
+
pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey;
pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData;
pub const KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState;
diff --git a/lib/std/os/uefi/protocols/file_protocol.zig b/lib/std/os/uefi/protocols/file_protocol.zig
new file mode 100644
index 0000000000000000000000000000000000000000..cc6785caf7c4795d62988e753f7c5ed836456ceb
--- /dev/null
+++ b/lib/std/os/uefi/protocols/file_protocol.zig
@@ -0,0 +1,87 @@
+const uefi = @import("std").os.uefi;
+const Guid = uefi.Guid;
+const Time = uefi.Time;
+
+const FileProtocol = extern struct {
+ revision: u64,
+ _open: extern fn (*const FileProtocol, **const FileProtocol, *u16, u64, u64) usize,
+ _close: extern fn (*const FileProtocol) usize,
+ _delete: extern fn (*const FileProtocol) usize,
+ _read: extern fn (*const FileProtocol, *usize, *c_void) usize,
+ _write: extern fn (*const FileProtocol, *usize, *c_void) usize,
+ _get_info: extern fn (*const FileProtocol, *Guid, *usize, *c_void) usize,
+ _set_info: extern fn (*const FileProtocol, *Guid, usize, *c_void) usize,
+ _flush: extern fn (*const FileProtocol) usize,
+
+ pub fn open(self: *const FileProtocol, new_handle: **const FileProtocol, file_name: *u16, open_mode: u64, attributes: u64) usize {
+ return self._open(self, new_handle, file_name, open_mode, attributes);
+ }
+
+ pub fn close(self: *const FileProtocol) usize {
+ return self._close(self);
+ }
+
+ pub fn delete(self: *const FileProtocol) usize {
+ return self._delete(self);
+ }
+
+ pub fn read(self: *const FileProtocol, buffer_size: *usize, buffer: *c_void) usize {
+ return self._read(self, buffer_size, buffer);
+ }
+
+ pub fn write(self: *const FileProtocol, buffer_size: *usize, buffer: *c_void) usize {
+ return self._write(self, buffer_size, buffer);
+ }
+
+ pub fn get_info(self: *const FileProtocol, information_type: *Guid, buffer_size: *usize, buffer: *c_void) usize {
+ return self._get_info(self, information_type, buffer_size, buffer);
+ }
+
+ pub fn set_info(self: *const FileProtocol, information_type: *Guid, buffer_size: usize, buffer: *c_void) usize {
+ return self._set_info(self, information_type, buffer_size, buffer);
+ }
+
+ pub fn flush(self: *const FileProtocol) usize {
+ return self._flush(self);
+ }
+
+ pub const guid align(8) = Guid{
+ .time_low = 0x09576e92,
+ .time_mid = 0x6d3f,
+ .time_high_and_version = 0x11d2,
+ .clock_seq_high_and_reserved = 0x8e,
+ .clock_seq_low = 0x39,
+ .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
+ };
+
+ pub const efi_file_mode_read: u64 = 0x0000000000000001;
+ pub const efi_file_mode_write: u64 = 0x0000000000000002;
+ pub const efi_file_mode_create: u64 = 0x8000000000000000;
+
+ pub const efi_file_read_only: u64 = 0x0000000000000001;
+ pub const efi_file_hidden: u64 = 0x0000000000000002;
+ pub const efi_file_system: u64 = 0x0000000000000004;
+ pub const efi_file_reserved: u64 = 0x0000000000000008;
+ pub const efi_file_directory: u64 = 0x0000000000000010;
+ pub const efi_file_archive: u64 = 0x0000000000000020;
+ pub const efi_file_valid_attr: u64 = 0x0000000000000037;
+};
+
+const FileInfo = extern struct {
+ size: u64,
+ file_size: u64,
+ physical_size: u64,
+ create_time: Time,
+ last_access_time: Time,
+ modification_time: Time,
+ attribute: u64,
+ file_name: [100:0]u16,
+
+ pub const efi_file_read_only: u64 = 0x0000000000000001;
+ pub const efi_file_hidden: u64 = 0x0000000000000002;
+ pub const efi_file_system: u64 = 0x0000000000000004;
+ pub const efi_file_reserved: u64 = 0x0000000000000008;
+ pub const efi_file_directory: u64 = 0x0000000000000010;
+ pub const efi_file_archive: u64 = 0x0000000000000020;
+ pub const efi_file_valid_attr: u64 = 0x0000000000000037;
+};
diff --git a/lib/std/os/uefi/protocols/simple_file_system_protocol.zig b/lib/std/os/uefi/protocols/simple_file_system_protocol.zig
new file mode 100644
index 0000000000000000000000000000000000000000..41bfaa18a58d8530fc826863e707103039323031
--- /dev/null
+++ b/lib/std/os/uefi/protocols/simple_file_system_protocol.zig
@@ -0,0 +1,21 @@
+const uefi = @import("std").os.uefi;
+const Guid = uefi.Guid;
+const FileProtocol = uefi.protocols.FileProtocol;
+
+const SimpleFileSystemProtocol = extern struct {
+ revision: u64,
+ _open_volume: extern fn (*const SimpleFileSystemProtocol, **const FileProtocol) usize,
+
+ pub fn openVolume(self: *const SimpleFileSystemProtocol, root: **const FileProtocol) usize {
+ return self._open_volume(self, root);
+ }
+
+ pub const guid align(8) = Guid{
+ .time_low = 0x0964e5b22,
+ .time_mid = 0x6459,
+ .time_high_and_version = 0x11d2,
+ .clock_seq_high_and_reserved = 0x8e,
+ .clock_seq_low = 0x39,
+ .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
+ };
+};
--
2.54.0
From 58941927c426f61a6680348e4380f9f4eed3e8a8 Mon Sep 17 00:00:00 2001
From: Heppokoyuki
Date: Thu, 12 Mar 2020 00:16:45 +0900
Subject: [PATCH 057/111] refactor
---
lib/std/os/uefi/protocols/simple_text_input_protocol.zig | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/std/os/uefi/protocols/simple_text_input_protocol.zig b/lib/std/os/uefi/protocols/simple_text_input_protocol.zig
index b56ff728ef1239031b6caa526dd3c1535f3ae12c..a6d5f837a588126d956a1097c2c17cf692e006e2 100644
--- a/lib/std/os/uefi/protocols/simple_text_input_protocol.zig
+++ b/lib/std/os/uefi/protocols/simple_text_input_protocol.zig
@@ -1,11 +1,12 @@
const uefi = @import("std").os.uefi;
const Event = uefi.Event;
const Guid = uefi.Guid;
+const InputKey = uefi.protocols.InputKey;
/// Character input devices, e.g. Keyboard
pub const SimpleTextInputProtocol = extern struct {
_reset: extern fn (*const SimpleTextInputProtocol, bool) usize,
- _read_key_stroke: extern fn (*const SimpleTextInputProtocol, *uefi.protocols.InputKey) usize,
+ _read_key_stroke: extern fn (*const SimpleTextInputProtocol, *InputKey) usize,
wait_for_key: Event,
/// Resets the input device hardware.
@@ -14,7 +15,7 @@ pub const SimpleTextInputProtocol = extern struct {
}
/// Reads the next keystroke from the input device.
- pub fn readKeyStroke(self: *const SimpleTextInputProtocol, input_key: *uefi.protocols.InputKey) usize {
+ pub fn readKeyStroke(self: *const SimpleTextInputProtocol, input_key: *InputKey) usize {
return self._read_key_stroke(self, input_key);
}
--
2.54.0
From d96b6c0d9f7a4fc6e7e28dd92d18e548f00885de Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 13:06:30 -0400
Subject: [PATCH 058/111] fix footguns in File readAll functions
---
lib/std/fs.zig | 33 ++++++++++++-------------------
lib/std/fs/file.zig | 42 +++++++++++++++++++++++++++++++---------
lib/std/io/in_stream.zig | 5 +----
lib/std/os/test.zig | 32 +++++++++++++++++++++++++++---
4 files changed, 75 insertions(+), 37 deletions(-)
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 892b97729150e91a4b0cf5b09cc96f7057a8a01d..de6be91f71a0668ff5a705333c14df634f16b28a 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -96,6 +96,7 @@ pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus {
/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
/// Returns the previous status of the file before updating.
/// If any of the directories do not exist for dest_path, they are created.
+/// TODO rework this to integrate with Dir
pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus {
const my_cwd = cwd();
@@ -141,29 +142,25 @@ pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?Fil
/// there is a possibility of power loss or application termination leaving temporary files present
/// in the same directory as dest_path.
/// Destination file will have the same mode as the source file.
+/// TODO rework this to integrate with Dir
pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
var in_file = try cwd().openFile(source_path, .{});
defer in_file.close();
- const mode = try in_file.mode();
- const in_stream = &in_file.inStream().stream;
+ const stat = try in_file.stat();
- var atomic_file = try AtomicFile.init(dest_path, mode);
+ var atomic_file = try AtomicFile.init(dest_path, stat.mode);
defer atomic_file.deinit();
- var buf: [mem.page_size]u8 = undefined;
- while (true) {
- const amt = try in_stream.readFull(buf[0..]);
- try atomic_file.file.write(buf[0..amt]);
- if (amt != buf.len) {
- return atomic_file.finish();
- }
- }
+ try atomic_file.file.writeFileAll(in_file, .{ .in_len = stat.size });
+ return atomic_file.finish();
}
-/// Guaranteed to be atomic. However until https://patchwork.kernel.org/patch/9636735/ is
-/// merged and readily available,
+/// Guaranteed to be atomic.
+/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
/// there is a possibility of power loss or application termination leaving temporary files present
+/// in the same directory as dest_path.
+/// TODO rework this to integrate with Dir
pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
var in_file = try cwd().openFile(source_path, .{});
defer in_file.close();
@@ -171,14 +168,8 @@ pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.M
var atomic_file = try AtomicFile.init(dest_path, mode);
defer atomic_file.deinit();
- var buf: [mem.page_size * 6]u8 = undefined;
- while (true) {
- const amt = try in_file.read(buf[0..]);
- try atomic_file.file.write(buf[0..amt]);
- if (amt != buf.len) {
- return atomic_file.finish();
- }
- }
+ try atomic_file.file.writeFileAll(in_file, .{});
+ return atomic_file.finish();
}
/// TODO update this API to avoid a getrandom syscall for every operation. It
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 845e4bc75ec25df6e91e138f89c782feb9c675b4..8362f94ca57fe1300c169b3da4fdd825fcb1839b 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -250,11 +250,16 @@ pub const File = struct {
}
}
- pub fn readAll(self: File, buffer: []u8) ReadError!void {
+ /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
+ /// means the file reached the end. Reaching the end of a file is not an error condition.
+ pub fn readAll(self: File, buffer: []u8) ReadError!usize {
var index: usize = 0;
- while (index < buffer.len) {
- index += try self.read(buffer[index..]);
+ while (index != buffer.len) {
+ const amt = try self.read(buffer[index..]);
+ if (amt == 0) break;
+ index += amt;
}
+ return index;
}
pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
@@ -265,11 +270,16 @@ pub const File = struct {
}
}
- pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!void {
+ /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
+ /// means the file reached the end. Reaching the end of a file is not an error condition.
+ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
var index: usize = 0;
- while (index < buffer.len) {
- index += try self.pread(buffer[index..], offset + index);
+ while (index != buffer.len) {
+ const amt = try self.pread(buffer[index..], offset + index);
+ if (amt == 0) break;
+ index += amt;
}
+ return index;
}
pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize {
@@ -280,19 +290,27 @@ pub const File = struct {
}
}
+ /// Returns the number of bytes read. If the number read is smaller than the total bytes
+ /// from all the buffers, it means the file reached the end. Reaching the end of a file
+ /// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
- pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!void {
+ pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
if (iovecs.len == 0) return;
var i: usize = 0;
+ var off: usize = 0;
while (true) {
var amt = try self.readv(iovecs[i..]);
+ var eof = amt == 0;
+ off += amt;
while (amt >= iovecs[i].iov_len) {
amt -= iovecs[i].iov_len;
i += 1;
- if (i >= iovecs.len) return;
+ if (i >= iovecs.len) return off;
+ eof = false;
}
+ if (eof) return off;
iovecs[i].iov_base += amt;
iovecs[i].iov_len -= amt;
}
@@ -306,6 +324,9 @@ pub const File = struct {
}
}
+ /// Returns the number of bytes read. If the number read is smaller than the total bytes
+ /// from all the buffers, it means the file reached the end. Reaching the end of a file
+ /// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void {
@@ -315,12 +336,15 @@ pub const File = struct {
var off: usize = 0;
while (true) {
var amt = try self.preadv(iovecs[i..], offset + off);
+ var eof = amt == 0;
off += amt;
while (amt >= iovecs[i].iov_len) {
amt -= iovecs[i].iov_len;
i += 1;
- if (i >= iovecs.len) return;
+ if (i >= iovecs.len) return off;
+ eof = false;
}
+ if (eof) return off;
iovecs[i].iov_base += amt;
iovecs[i].iov_len -= amt;
}
diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig
index 2830582482809bee439b560ef56b747b0504edee..d1d24ab42797ae0f133a80d8b2a80698ff59fbec 100644
--- a/lib/std/io/in_stream.zig
+++ b/lib/std/io/in_stream.zig
@@ -28,10 +28,7 @@ pub fn InStream(
return readFn(self.context, buffer);
}
- /// Deprecated: use `readAll`.
- pub const readFull = readAll;
-
- /// Returns the number of bytes read. If the number read is smaller than buf.len, it
+ /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
/// means the stream reached the end. Reaching the end of a stream is not an error
/// condition.
pub fn readAll(self: Self, buffer: []u8) Error!usize {
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index 75a6d5db919a19bf2b3d79e90bd6ff03b11810f9..1ef6798b50f97f2d21911b6d9064e0608a895af9 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -95,15 +95,41 @@ test "sendfile" {
},
};
- var written_buf: [header1.len + header2.len + 10 + trailer1.len + trailer2.len]u8 = undefined;
+ var written_buf: [100]u8 = undefined;
try dest_file.writeFileAll(src_file, .{
.in_offset = 1,
.in_len = 10,
.headers_and_trailers = &hdtr,
.header_count = 2,
});
- try dest_file.preadAll(&written_buf, 0);
- expect(mem.eql(u8, &written_buf, "header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n"));
+ const amt = try dest_file.preadAll(&written_buf, 0);
+ expect(mem.eql(u8, written_buf[0..amt], "header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n"));
+}
+
+test "fs.copyFile" {
+ const data = "u6wj+JmdF3qHsFPE BUlH2g4gJCmEz0PP";
+ const src_file = "tmp_test_copy_file.txt";
+ const dest_file = "tmp_test_copy_file2.txt";
+ const dest_file2 = "tmp_test_copy_file3.txt";
+
+ try fs.cwd().writeFile(src_file, data);
+ defer fs.cwd().deleteFile(src_file) catch {};
+
+ try fs.copyFile(src_file, dest_file);
+ defer fs.cwd().deleteFile(dest_file) catch {};
+
+ try fs.copyFileMode(src_file, dest_file2, File.default_mode);
+ defer fs.cwd().deleteFile(dest_file2) catch {};
+
+ try expectFileContents(dest_file, data);
+ try expectFileContents(dest_file2, data);
+}
+
+fn expectFileContents(file_path: []const u8, data: []const u8) !void {
+ const contents = try fs.cwd().readFileAlloc(testing.allocator, file_path, 1000);
+ defer testing.allocator.free(contents);
+
+ testing.expectEqualSlices(u8, data, contents);
}
test "std.Thread.getCurrentId" {
--
2.54.0
From c71991c869fc8c997c2714fe1b53caef23449c9c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 14:34:13 -0400
Subject: [PATCH 059/111] fix compilation errors for emitRaw
---
lib/std/build/emit_raw.zig | 2 +-
lib/std/elf.zig | 33 ++++++++++++++++++++++++++-------
2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig
index 63c232994753d54e4bdbc58741bd4da9413ea676..b56305403c09da5d9235b2232b07724f5cf3fe1d 100644
--- a/lib/std/build/emit_raw.zig
+++ b/lib/std/build/emit_raw.zig
@@ -164,7 +164,7 @@ fn emitRaw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !v
var out_file = try fs.cwd().createFile(raw_path, .{});
defer out_file.close();
- const binary_elf_output = BinaryElfOutput.parse(allocator, elf_file);
+ const binary_elf_output = try BinaryElfOutput.parse(allocator, elf_file);
defer binary_elf_output.deinit();
for (binary_elf_output.sections.toSlice()) |section| {
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index 3aefd87f09e71d64a71b7d056bfbb0479cf470dc..5cb3c566af0cd141b8a3fe762196bb09edd9b64e 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -346,13 +346,13 @@ const Header = struct {
pub fn readHeader(file: File) !Header {
var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined;
- try in_stream.preadAll(&hdr_buf, 0);
- const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
- const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
+ try preadNoEof(file, &hdr_buf, 0);
+ const hdr32 = @ptrCast(*Elf32_Ehdr, &hdr_buf);
+ const hdr64 = @ptrCast(*Elf64_Ehdr, &hdr_buf);
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
- const endian = switch (hdr32.e_ident[elf.EI_DATA]) {
+ const endian = switch (hdr32.e_ident[EI_DATA]) {
ELFDATA2LSB => .Little,
ELFDATA2MSB => .Big,
else => return error.InvalidElfEndian,
@@ -407,10 +407,10 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
// non-matching endian files, we post-process to correct integer endianness and offsets.
const shdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];
- const phdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
+ const phdr_buf = std.mem.sliceToBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
- try file.preadAll(phdr_buf, hdrs.header.phoff);
- try file.preadAll(shdr_buf, hdrs.header.shoff);
+ try preadNoEof(file, shdr_buf, hdrs.header.shoff);
+ try preadNoEof(file, phdr_buf, hdrs.header.phoff);
const shdrs32 = @ptrCast([*]Elf32_Shdr, @alignCast(@alignOf(Elf32_Shdr), shdr_buf.ptr))[0..hdrs.header.shnum];
const phdrs32 = @ptrCast([*]Elf32_Phdr, @alignCast(@alignOf(Elf32_Phdr), phdr_buf.ptr))[0..hdrs.header.phnum];
@@ -459,6 +459,25 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_
}
}
+fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void {
+ var i: u64 = 0;
+ while (i < buf.len) {
+ const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) {
+ error.SystemResources => return error.SystemResources,
+ error.IsDir => return error.UnableToReadElfFile,
+ error.OperationAborted => return error.UnableToReadElfFile,
+ error.BrokenPipe => return error.UnableToReadElfFile,
+ error.Unseekable => return error.UnableToReadElfFile,
+ error.ConnectionResetByPeer => return error.UnableToReadElfFile,
+ error.InputOutput => return error.FileSystem,
+ error.Unexpected => return error.Unexpected,
+ error.WouldBlock => return error.Unexpected,
+ };
+ if (len == 0) return error.UnexpectedEndOfFile;
+ i += len;
+ }
+}
+
pub const EI_NIDENT = 16;
pub const EI_CLASS = 4;
--
2.54.0
From 431d76c0233271de6a30aa626ccb1553dc241722 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 15:40:34 -0400
Subject: [PATCH 060/111] add std.io.StreamSource and fixes to emitRaw
---
lib/std/build/emit_raw.zig | 4 +-
lib/std/elf.zig | 24 ++++----
lib/std/io.zig | 2 +
lib/std/io/fixed_buffer_stream.zig | 41 +++++++-------
lib/std/io/stream_source.zig | 90 ++++++++++++++++++++++++++++++
5 files changed, 127 insertions(+), 34 deletions(-)
create mode 100644 lib/std/io/stream_source.zig
diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig
index b56305403c09da5d9235b2232b07724f5cf3fe1d..8b4747e8a7125df39bb19022063d29ce0d15766c 100644
--- a/lib/std/build/emit_raw.zig
+++ b/lib/std/build/emit_raw.zig
@@ -48,8 +48,6 @@ const BinaryElfOutput = struct {
};
const elf_hdrs = try std.elf.readAllHeaders(allocator, elf_file);
- var binaryElfOutput = BinaryElfOutput.init(arena_allocator);
-
for (elf_hdrs.section_headers) |section, i| {
if (sectionValidForOutput(section)) {
const newSection = try allocator.create(BinaryElfSection);
@@ -164,7 +162,7 @@ fn emitRaw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !v
var out_file = try fs.cwd().createFile(raw_path, .{});
defer out_file.close();
- const binary_elf_output = try BinaryElfOutput.parse(allocator, elf_file);
+ var binary_elf_output = try BinaryElfOutput.parse(allocator, elf_file);
defer binary_elf_output.deinit();
for (binary_elf_output.sections.toSlice()) |section| {
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index 5cb3c566af0cd141b8a3fe762196bb09edd9b64e..127dbe8a31c62e93d6afd095ea07c475c039fc2e 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -1,5 +1,5 @@
-const builtin = @import("builtin");
const std = @import("std.zig");
+const builtin = std.builtin;
const io = std.io;
const os = std.os;
const math = std.math;
@@ -352,7 +352,7 @@ pub fn readHeader(file: File) !Header {
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
- const endian = switch (hdr32.e_ident[EI_DATA]) {
+ const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) {
ELFDATA2LSB => .Little,
ELFDATA2MSB => .Big,
else => return error.InvalidElfEndian,
@@ -406,8 +406,8 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
// Treat section headers and program headers as byte buffers. For 32-bit ELF and
// non-matching endian files, we post-process to correct integer endianness and offsets.
- const shdr_buf = std.mem.sliceToBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];
- const phdr_buf = std.mem.sliceToBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
+ const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];
+ const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
try preadNoEof(file, shdr_buf, hdrs.header.shoff);
try preadNoEof(file, phdr_buf, hdrs.header.phoff);
@@ -430,14 +430,14 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
}
for (hdrs.program_headers) |*phdr, i| {
phdr.* = .{
- .p_type = int(is_64, need_bswap, phdrs32[i].p_type, shdr.p_type),
- .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, shdr.p_offset),
- .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, shdr.p_vaddr),
- .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, shdr.p_paddr),
- .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, shdr.p_filesz),
- .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, shdr.p_memsz),
- .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, shdr.p_flags),
- .p_align = int(is_64, need_bswap, phdrs32[i].p_align, shdr.p_align),
+ .p_type = int(is_64, need_bswap, phdrs32[i].p_type, phdr.p_type),
+ .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, phdr.p_offset),
+ .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, phdr.p_vaddr),
+ .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, phdr.p_paddr),
+ .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, phdr.p_filesz),
+ .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, phdr.p_memsz),
+ .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, phdr.p_flags),
+ .p_align = int(is_64, need_bswap, phdrs32[i].p_align, phdr.p_align),
};
}
return hdrs;
diff --git a/lib/std/io.zig b/lib/std/io.zig
index 22af5c06b11e6e309ae5877614b466f9069af09f..243dd5ca95e3775b5fce6bb355e4928284de0b8b 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -126,6 +126,8 @@ pub const deserializer = @import("io/serialization.zig").deserializer;
pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAtomicFile;
+pub const StreamSource = @import("io/stream_source.zig").StreamSource;
+
/// Deprecated; use `std.fs.Dir.writeFile`.
pub fn writeFile(path: []const u8, data: []const u8) !void {
return fs.cwd().writeFile(path, data);
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index 0f2b54220117a0ee74a9fb12d29c875a7bcf3fb0..cc4b9c0193f0ec0c022a0cf9262550be432d57a4 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -12,9 +12,9 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
buffer: Buffer,
pos: usize,
- pub const ReadError = error{EndOfStream};
- pub const WriteError = error{OutOfMemory};
- pub const SeekError = error{EndOfStream};
+ pub const ReadError = error{};
+ pub const WriteError = error{NoSpaceLeft};
+ pub const SeekError = error{};
pub const GetSeekPosError = error{};
pub const InStream = io.InStream(*Self, ReadError, read);
@@ -51,16 +51,16 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
mem.copy(u8, dest[0..size], self.buffer[self.pos..end]);
self.pos = end;
- if (size == 0) return error.EndOfStream;
return size;
}
/// If the returned number of bytes written is less than requested, the
- /// buffer is full. Returns `error.OutOfMemory` when no bytes would be written.
+ /// buffer is full. Returns `error.NoSpaceLeft` when no bytes would be written.
+ /// Note: `error.NoSpaceLeft` matches the corresponding error from
+ /// `std.fs.File.WriteError`.
pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
if (bytes.len == 0) return 0;
-
- assert(self.pos <= self.buffer.len);
+ if (self.pos >= self.buffer.len) return error.NoSpaceLeft;
const n = if (self.pos + bytes.len <= self.buffer.len)
bytes.len
@@ -70,26 +70,27 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
mem.copy(u8, self.buffer[self.pos .. self.pos + n], bytes[0..n]);
self.pos += n;
- if (n == 0) return error.OutOfMemory;
+ if (n == 0) return error.NoSpaceLeft;
return n;
}
pub fn seekTo(self: *Self, pos: u64) SeekError!void {
- const usize_pos = std.math.cast(usize, pos) catch return error.EndOfStream;
- if (usize_pos > self.buffer.len) return error.EndOfStream;
+ const usize_pos = std.math.cast(usize, pos) catch std.math.maxInt(usize);
self.pos = usize_pos;
}
pub fn seekBy(self: *Self, amt: i64) SeekError!void {
if (amt < 0) {
- const abs_amt = std.math.cast(usize, -amt) catch return error.EndOfStream;
- if (abs_amt > self.pos) return error.EndOfStream;
- self.pos -= abs_amt;
+ const abs_amt = std.math.cast(usize, -amt) catch std.math.maxInt(usize);
+ if (abs_amt > self.pos) {
+ self.pos = 0;
+ } else {
+ self.pos -= abs_amt;
+ }
} else {
- const usize_amt = std.math.cast(usize, amt) catch return error.EndOfStream;
- if (self.pos + usize_amt > self.buffer.len) return error.EndOfStream;
- self.pos += usize_amt;
+ const usize_amt = std.math.cast(usize, amt) catch std.math.maxInt(usize);
+ self.pos = std.math.add(usize, self.pos, usize_amt) catch std.math.maxInt(usize);
}
}
@@ -101,6 +102,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
return self.pos;
}
+ /// Asserts that the seek pos is within the buffer range.
pub fn getWritten(self: Self) []const u8 {
return self.buffer[0..self.pos];
}
@@ -140,13 +142,13 @@ test "FixedBufferStream output 2" {
try fbs.outStream().writeAll("world");
testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
- testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("!"));
+ testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("!"));
testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
fbs.reset();
testing.expect(fbs.getWritten().len == 0);
- testing.expectError(error.OutOfMemory, fbs.outStream().writeAll("Hello world!"));
+ testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("Hello world!"));
testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl"));
}
@@ -164,5 +166,6 @@ test "FixedBufferStream input" {
testing.expect(read == 3);
testing.expect(mem.eql(u8, dest[0..3], bytes[4..7]));
- testing.expectError(error.EndOfStream, fbs.inStream().read(dest[0..4]));
+ read = try fbs.inStream().read(dest[0..4]);
+ testing.expect(read == 0);
}
diff --git a/lib/std/io/stream_source.zig b/lib/std/io/stream_source.zig
new file mode 100644
index 0000000000000000000000000000000000000000..7e395543374c410ed3e1ddfae1cb95d596917d93
--- /dev/null
+++ b/lib/std/io/stream_source.zig
@@ -0,0 +1,90 @@
+const std = @import("../std.zig");
+const io = std.io;
+const testing = std.testing;
+
+/// Provides `io.InStream`, `io.OutStream`, and `io.SeekableStream` for in-memory buffers as
+/// well as files.
+/// For memory sources, if the supplied byte buffer is const, then `io.OutStream` is not available.
+/// The error set of the stream functions is the error set of the corresponding file functions.
+pub const StreamSource = union(enum) {
+ buffer: io.FixedBufferStream([]u8),
+ const_buffer: io.FixedBufferStream([]const u8),
+ file: std.fs.File,
+
+ pub const ReadError = std.fs.File.ReadError;
+ pub const WriteError = std.fs.File.WriteError;
+ pub const SeekError = std.fs.File.SeekError;
+ pub const GetSeekPosError = std.fs.File.GetPosError;
+
+ pub const InStream = io.InStream(*StreamSource, ReadError, read);
+ pub const OutStream = io.OutStream(*StreamSource, WriteError, write);
+ pub const SeekableStream = io.SeekableStream(
+ *StreamSource,
+ SeekError,
+ GetSeekPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
+ pub fn read(self: *StreamSource, dest: []u8) ReadError!usize {
+ switch (self.*) {
+ .buffer => |*x| return x.read(dest),
+ .const_buffer => |*x| return x.read(dest),
+ .file => |x| return x.read(dest),
+ }
+ }
+
+ pub fn write(self: *StreamSource, bytes: []const u8) WriteError!usize {
+ switch (self.*) {
+ .buffer => |*x| return x.write(bytes),
+ .const_buffer => |*x| return x.write(bytes),
+ .file => |x| return x.write(bytes),
+ }
+ }
+
+ pub fn seekTo(self: *StreamSource, pos: u64) SeekError!void {
+ switch (self.*) {
+ .buffer => |*x| return x.seekTo(pos),
+ .const_buffer => |*x| return x.seekTo(pos),
+ .file => |x| return x.seekTo(pos),
+ }
+ }
+
+ pub fn seekBy(self: *StreamSource, amt: i64) SeekError!void {
+ switch (self.*) {
+ .buffer => |*x| return x.seekBy(amt),
+ .const_buffer => |*x| return x.seekBy(amt),
+ .file => |x| return x.seekBy(amt),
+ }
+ }
+
+ pub fn getEndPos(self: *StreamSource) GetSeekPosError!u64 {
+ switch (self.*) {
+ .buffer => |*x| return x.getEndPos(),
+ .const_buffer => |*x| return x.getEndPos(),
+ .file => |x| return x.getEndPos(),
+ }
+ }
+
+ pub fn getPos(self: *StreamSource) GetSeekPosError!u64 {
+ switch (self.*) {
+ .buffer => |*x| return x.getPos(),
+ .const_buffer => |*x| return x.getPos(),
+ .file => |x| return x.getPos(),
+ }
+ }
+
+ pub fn inStream(self: *StreamSource) InStream {
+ return .{ .context = self };
+ }
+
+ pub fn outStream(self: *StreamSource) OutStream {
+ return .{ .context = self };
+ }
+
+ pub fn seekableStream(self: *StreamSource) SeekableStream {
+ return .{ .context = self };
+ }
+};
--
2.54.0
From 6892865ba72ea220a12a8238ce78aedab1237cce Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 16:14:12 -0400
Subject: [PATCH 061/111] FixedBufferStream: match file semantics more by
clamping pos
---
lib/std/io/fixed_buffer_stream.zig | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index cc4b9c0193f0ec0c022a0cf9262550be432d57a4..0d091eea72082008172527890dd5986c12d16d39 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -76,21 +76,22 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
}
pub fn seekTo(self: *Self, pos: u64) SeekError!void {
- const usize_pos = std.math.cast(usize, pos) catch std.math.maxInt(usize);
- self.pos = usize_pos;
+ self.pos = if (std.math.cast(usize, pos)) |x| x else |_| self.buffer.len;
}
pub fn seekBy(self: *Self, amt: i64) SeekError!void {
if (amt < 0) {
- const abs_amt = std.math.cast(usize, -amt) catch std.math.maxInt(usize);
- if (abs_amt > self.pos) {
+ const abs_amt = std.math.absCast(amt);
+ const abs_amt_usize = std.math.cast(usize, abs_amt) catch std.math.maxInt(usize);
+ if (abs_amt_usize > self.pos) {
self.pos = 0;
} else {
- self.pos -= abs_amt;
+ self.pos -= abs_amt_usize;
}
} else {
- const usize_amt = std.math.cast(usize, amt) catch std.math.maxInt(usize);
- self.pos = std.math.add(usize, self.pos, usize_amt) catch std.math.maxInt(usize);
+ const amt_usize = std.math.cast(usize, amt) catch std.math.maxInt(usize);
+ const new_pos = std.math.add(usize, self.pos, amt_usize) catch std.math.maxInt(usize);
+ self.pos = std.math.min(self.buffer.len, new_pos);
}
}
@@ -102,7 +103,6 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
return self.pos;
}
- /// Asserts that the seek pos is within the buffer range.
pub fn getWritten(self: Self) []const u8 {
return self.buffer[0..self.pos];
}
--
2.54.0
From 3657a54618dafa110fd1d16e02c48e04871c9370 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 17:34:12 -0400
Subject: [PATCH 062/111] fix regressions in elf parsing code
---
lib/std/elf.zig | 155 +++++++++++++++++++++++++++++++----------
lib/std/zig/system.zig | 17 ++++-
2 files changed, 133 insertions(+), 39 deletions(-)
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index 127dbe8a31c62e93d6afd095ea07c475c039fc2e..7b415f675a125961f2ff24b0dcc1d9b38fcf26ea 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -398,48 +398,123 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
const need_bswap = hdrs.header.endian != std.builtin.endian;
hdrs.section_headers = try allocator.alloc(Elf64_Shdr, hdrs.header.shnum);
- errdefer hdrs.allocator.free(hdrs.section_headers);
+ errdefer allocator.free(hdrs.section_headers);
hdrs.program_headers = try allocator.alloc(Elf64_Phdr, hdrs.header.phnum);
- errdefer hdrs.allocator.free(hdrs.program_headers);
+ errdefer allocator.free(hdrs.program_headers);
- // Treat section headers and program headers as byte buffers. For 32-bit ELF and
- // non-matching endian files, we post-process to correct integer endianness and offsets.
+ // If the ELF file is 64-bit and same-endianness, then all we have to do is
+ // yeet the bytes into memory.
+ // If only the endianness is different, they can be simply byte swapped.
+ if (is_64) {
+ const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers);
+ const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers);
+ try preadNoEof(file, shdr_buf, hdrs.header.shoff);
+ try preadNoEof(file, phdr_buf, hdrs.header.phoff);
- const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];
- const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];
+ if (need_bswap) {
+ for (hdrs.section_headers) |*shdr| {
+ shdr.* = .{
+ .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
+ .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
+ .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
+ .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
+ .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
+ .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
+ .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
+ .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
+ .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
+ .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
+ };
+ }
+ for (hdrs.program_headers) |*phdr| {
+ phdr.* = .{
+ .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
+ .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
+ .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
+ .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
+ .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
+ .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
+ .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
+ .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
+ };
+ }
+ }
+ return hdrs;
+ }
+
+ const shdrs_32 = try allocator.alloc(Elf32_Shdr, hdrs.header.shnum);
+ defer allocator.free(shdrs_32);
+
+ const phdrs_32 = try allocator.alloc(Elf32_Phdr, hdrs.header.phnum);
+ defer allocator.free(phdrs_32);
+
+ const shdr_buf = std.mem.sliceAsBytes(shdrs_32);
+ const phdr_buf = std.mem.sliceAsBytes(phdrs_32);
try preadNoEof(file, shdr_buf, hdrs.header.shoff);
try preadNoEof(file, phdr_buf, hdrs.header.phoff);
- const shdrs32 = @ptrCast([*]Elf32_Shdr, @alignCast(@alignOf(Elf32_Shdr), shdr_buf.ptr))[0..hdrs.header.shnum];
- const phdrs32 = @ptrCast([*]Elf32_Phdr, @alignCast(@alignOf(Elf32_Phdr), phdr_buf.ptr))[0..hdrs.header.phnum];
- for (hdrs.section_headers) |*shdr, i| {
- shdr.* = .{
- .sh_name = int(is_64, need_bswap, shdrs32[i].sh_name, shdr.sh_name),
- .sh_type = int(is_64, need_bswap, shdrs32[i].sh_type, shdr.sh_type),
- .sh_flags = int(is_64, need_bswap, shdrs32[i].sh_flags, shdr.sh_flags),
- .sh_addr = int(is_64, need_bswap, shdrs32[i].sh_addr, shdr.sh_addr),
- .sh_offset = int(is_64, need_bswap, shdrs32[i].sh_offset, shdr.sh_offset),
- .sh_size = int(is_64, need_bswap, shdrs32[i].sh_size, shdr.sh_size),
- .sh_link = int(is_64, need_bswap, shdrs32[i].sh_link, shdr.sh_link),
- .sh_info = int(is_64, need_bswap, shdrs32[i].sh_info, shdr.sh_info),
- .sh_addralign = int(is_64, need_bswap, shdrs32[i].sh_addralign, shdr.sh_addralign),
- .sh_entsize = int(is_64, need_bswap, shdrs32[i].sh_entsize, shdr.sh_entsize),
- };
- }
- for (hdrs.program_headers) |*phdr, i| {
- phdr.* = .{
- .p_type = int(is_64, need_bswap, phdrs32[i].p_type, phdr.p_type),
- .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, phdr.p_offset),
- .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, phdr.p_vaddr),
- .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, phdr.p_paddr),
- .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, phdr.p_filesz),
- .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, phdr.p_memsz),
- .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, phdr.p_flags),
- .p_align = int(is_64, need_bswap, phdrs32[i].p_align, phdr.p_align),
- };
+ if (need_bswap) {
+ for (hdrs.section_headers) |*shdr, i| {
+ const o = shdrs_32[i];
+ shdr.* = .{
+ .sh_name = @byteSwap(@TypeOf(o.sh_name), o.sh_name),
+ .sh_type = @byteSwap(@TypeOf(o.sh_type), o.sh_type),
+ .sh_flags = @byteSwap(@TypeOf(o.sh_flags), o.sh_flags),
+ .sh_addr = @byteSwap(@TypeOf(o.sh_addr), o.sh_addr),
+ .sh_offset = @byteSwap(@TypeOf(o.sh_offset), o.sh_offset),
+ .sh_size = @byteSwap(@TypeOf(o.sh_size), o.sh_size),
+ .sh_link = @byteSwap(@TypeOf(o.sh_link), o.sh_link),
+ .sh_info = @byteSwap(@TypeOf(o.sh_info), o.sh_info),
+ .sh_addralign = @byteSwap(@TypeOf(o.sh_addralign), o.sh_addralign),
+ .sh_entsize = @byteSwap(@TypeOf(o.sh_entsize), o.sh_entsize),
+ };
+ }
+ for (hdrs.program_headers) |*phdr, i| {
+ const o = phdrs_32[i];
+ phdr.* = .{
+ .p_type = @byteSwap(@TypeOf(o.p_type), o.p_type),
+ .p_offset = @byteSwap(@TypeOf(o.p_offset), o.p_offset),
+ .p_vaddr = @byteSwap(@TypeOf(o.p_vaddr), o.p_vaddr),
+ .p_paddr = @byteSwap(@TypeOf(o.p_paddr), o.p_paddr),
+ .p_filesz = @byteSwap(@TypeOf(o.p_filesz), o.p_filesz),
+ .p_memsz = @byteSwap(@TypeOf(o.p_memsz), o.p_memsz),
+ .p_flags = @byteSwap(@TypeOf(o.p_flags), o.p_flags),
+ .p_align = @byteSwap(@TypeOf(o.p_align), o.p_align),
+ };
+ }
+ } else {
+ for (hdrs.section_headers) |*shdr, i| {
+ const o = shdrs_32[i];
+ shdr.* = .{
+ .sh_name = o.sh_name,
+ .sh_type = o.sh_type,
+ .sh_flags = o.sh_flags,
+ .sh_addr = o.sh_addr,
+ .sh_offset = o.sh_offset,
+ .sh_size = o.sh_size,
+ .sh_link = o.sh_link,
+ .sh_info = o.sh_info,
+ .sh_addralign = o.sh_addralign,
+ .sh_entsize = o.sh_entsize,
+ };
+ }
+ for (hdrs.program_headers) |*phdr, i| {
+ const o = phdrs_32[i];
+ phdr.* = .{
+ .p_type = o.p_type,
+ .p_offset = o.p_offset,
+ .p_vaddr = o.p_vaddr,
+ .p_paddr = o.p_paddr,
+ .p_filesz = o.p_filesz,
+ .p_memsz = o.p_memsz,
+ .p_flags = o.p_flags,
+ .p_align = o.p_align,
+ };
+ }
}
+
return hdrs;
}
@@ -451,11 +526,15 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_
return int_64;
}
} else {
- if (need_bswap) {
- return @byteSwap(@TypeOf(int_32), int_32);
- } else {
- return int_32;
- }
+ return int32(need_bswap, int_32, @TypeOf(int_64));
+ }
+}
+
+pub fn int32(need_bswap: bool, int_32: var, comptime Int64: var) Int64 {
+ if (need_bswap) {
+ return @byteSwap(@TypeOf(int_32), int_32);
+ } else {
+ return int_32;
}
}
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index e7953a1a9127d7e492dba4b02c24b5548f8f77bd..558b50b5b38564f2699b4ce50b4342699710fdd0 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -587,7 +587,6 @@ pub const NativeTargetInfo = struct {
elf.ELFCLASS64 => true,
else => return error.InvalidElfClass,
};
- const elfInt = elf.int;
var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);
const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);
const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
@@ -854,6 +853,22 @@ pub const NativeTargetInfo = struct {
abi: Target.Abi,
};
+ pub fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
+ if (is_64) {
+ if (need_bswap) {
+ return @byteSwap(@TypeOf(int_64), int_64);
+ } else {
+ return int_64;
+ }
+ } else {
+ if (need_bswap) {
+ return @byteSwap(@TypeOf(int_32), int_32);
+ } else {
+ return int_32;
+ }
+ }
+ }
+
fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu {
// Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,
// although it is a runtime value, is guaranteed to be one of the architectures in the set
--
2.54.0
From 06d2f53ece7328e6beedd5c846a5b25798ba74e3 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 17:39:53 -0400
Subject: [PATCH 063/111] windows: detect HANDLE_EOF in ReadFile
---
lib/std/os/windows.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index d1201108dc4f577e40d398822022a8620ea31e87..6c9a1f24b7fe6abb7f05ffa3cbe85366a4d83ac8 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -407,6 +407,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usiz
switch (kernel32.GetLastError()) {
.OPERATION_ABORTED => continue,
.BROKEN_PIPE => return index,
+ .HANDLE_EOF => return index,
else => |err| return unexpectedError(err),
}
}
--
2.54.0
From 571f3ed161455074be5f296b39b24cba554da8e0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 11 Mar 2020 18:45:09 -0400
Subject: [PATCH 064/111] fix stray warn() in runtime safety test
---
test/runtime_safety.zig | 1 -
1 file changed, 1 deletion(-)
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
index 9855aae16bbfe2049eedc45fca58ef0aaf90e3aa..5047bfd0d0b606a40d9f1f3b69a17ab5b6791909 100644
--- a/test/runtime_safety.zig
+++ b/test/runtime_safety.zig
@@ -4,7 +4,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
cases.addRuntimeSafety("shift left by huge amount",
\\const std = @import("std");
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
- \\ std.debug.warn("{}\n", .{message});
\\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
\\ std.process.exit(126); // good
\\ }
--
2.54.0
From e0fe0f7f1e26c7cc0266b3f0168363135ec75ff4 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Wed, 11 Mar 2020 19:33:10 -0400
Subject: [PATCH 065/111] parse CPU features when --target is null
- fixes case where features are not parsed when `-target` is null
- `zig builtin -mcpu native+bogus` should return error/list of valid features
---
src-self-hosted/stage2.zig | 74 +++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 38 deletions(-)
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
index 8f2656de44385e7006553e2ef4400a03c8262fdf..bdd68925eeaa6809eebfc454f556c116debf4b1e 100644
--- a/src-self-hosted/stage2.zig
+++ b/src-self-hosted/stage2.zig
@@ -679,44 +679,42 @@ fn stage2TargetParse(
mcpu_oz: ?[*:0]const u8,
dynamic_linker_oz: ?[*:0]const u8,
) !void {
- const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: {
- const zig_triple = mem.toSliceConst(u8, zig_triple_z);
- const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;
- const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.toSliceConst(u8, dl_z) else null;
- var diags: CrossTarget.ParseOptions.Diagnostics = .{};
- break :blk CrossTarget.parse(.{
- .arch_os_abi = zig_triple,
- .cpu_features = mcpu,
- .dynamic_linker = dynamic_linker,
- .diagnostics = &diags,
- }) catch |err| switch (err) {
- error.UnknownCpuModel => {
- std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
- diags.cpu_name.?,
- @tagName(diags.arch.?),
- });
- for (diags.arch.?.allCpuModels()) |cpu| {
- std.debug.warn(" {}\n", .{cpu.name});
- }
- process.exit(1);
- },
- error.UnknownCpuFeature => {
- std.debug.warn(
- \\Unknown CPU feature: '{}'
- \\Available CPU features for architecture '{}':
- \\
- , .{
- diags.unknown_feature_name,
- @tagName(diags.arch.?),
- });
- for (diags.arch.?.allFeaturesList()) |feature| {
- std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
- }
- process.exit(1);
- },
- else => |e| return e,
- };
- } else .{};
+ const zig_triple = if (zig_triple_oz) |zig_triple_z| mem.toSliceConst(u8, zig_triple_z) else "native";
+ const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;
+ const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.toSliceConst(u8, dl_z) else null;
+ var diags: CrossTarget.ParseOptions.Diagnostics = .{};
+ const target: CrossTarget = CrossTarget.parse(.{
+ .arch_os_abi = zig_triple,
+ .cpu_features = mcpu,
+ .dynamic_linker = dynamic_linker,
+ .diagnostics = &diags,
+ }) catch |err| switch (err) {
+ error.UnknownCpuModel => {
+ std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
+ diags.cpu_name.?,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allCpuModels()) |cpu| {
+ std.debug.warn(" {}\n", .{cpu.name});
+ }
+ process.exit(1);
+ },
+ error.UnknownCpuFeature => {
+ std.debug.warn(
+ \\Unknown CPU feature: '{}'
+ \\Available CPU features for architecture '{}':
+ \\
+ , .{
+ diags.unknown_feature_name,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allFeaturesList()) |feature| {
+ std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
+ };
try stage1_target.fromTarget(target);
}
--
2.54.0
From c988167377c92359fed42f12ad32b5f349f9ffb8 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Wed, 11 Mar 2020 19:33:11 -0400
Subject: [PATCH 066/111] update/apply CPU features when -mcpu native
- fix: features were not applied if cpu is specified as native
---
lib/std/zig/system.zig | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 558b50b5b38564f2699b4ce50b4342699710fdd0..88b3022bb2dd65d04ea9cde5bab9074c9607ac89 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -325,22 +325,19 @@ pub const NativeTargetInfo = struct {
// native CPU architecture as being different than the current target), we use this:
const cpu_arch = cross_target.getCpuArch();
- const cpu = switch (cross_target.cpu_model) {
+ var cpu = switch (cross_target.cpu_model) {
.native => detectNativeCpuAndFeatures(cpu_arch, os, cross_target),
- .baseline => baselineCpuAndFeatures(cpu_arch, cross_target),
+ .baseline => Target.Cpu.baseline(cpu_arch),
.determined_by_cpu_arch => if (cross_target.cpu_arch == null)
detectNativeCpuAndFeatures(cpu_arch, os, cross_target)
else
- baselineCpuAndFeatures(cpu_arch, cross_target),
- .explicit => |model| blk: {
- var adjusted_model = model.toCpu(cpu_arch);
- cross_target.updateCpuFeatures(&adjusted_model.features);
- break :blk adjusted_model;
- },
+ Target.Cpu.baseline(cpu_arch),
+ .explicit => |model| model.toCpu(cpu_arch),
} orelse backup_cpu_detection: {
cpu_detection_unimplemented = true;
- break :backup_cpu_detection baselineCpuAndFeatures(cpu_arch, cross_target);
+ break :backup_cpu_detection Target.Cpu.baseline(cpu_arch);
};
+ cross_target.updateCpuFeatures(&cpu.features);
var target = try detectAbiAndDynamicLinker(allocator, cpu, os, cross_target);
target.cpu_detection_unimplemented = cpu_detection_unimplemented;
@@ -884,10 +881,4 @@ pub const NativeTargetInfo = struct {
},
}
}
-
- fn baselineCpuAndFeatures(cpu_arch: Target.Cpu.Arch, cross_target: CrossTarget) Target.Cpu {
- var adjusted_baseline = Target.Cpu.baseline(cpu_arch);
- cross_target.updateCpuFeatures(&adjusted_baseline.features);
- return adjusted_baseline;
- }
};
--
2.54.0
From bfebc11d0633e3f4a3fe86d1a9d6f90ffdb1fbb6 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Wed, 11 Mar 2020 19:33:12 -0400
Subject: [PATCH 067/111] fix zig-cache to treat cpu-features as raw-bytes
- add Stage2Target.cache_hash_len
- add cache_mem(ch, ptr, len)
- update call sites to use { ptr, len }
---
src-self-hosted/stage2.zig | 5 ++++-
src/cache_hash.cpp | 8 ++++++--
src/cache_hash.hpp | 1 +
src/codegen.cpp | 4 ++--
src/stage2.cpp | 3 +++
src/stage2.h | 1 +
6 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
index bdd68925eeaa6809eebfc454f556c116debf4b1e..83a70c29e04b94219d3cdb8d6c5093bbd7e10300 100644
--- a/src-self-hosted/stage2.zig
+++ b/src-self-hosted/stage2.zig
@@ -900,6 +900,7 @@ const Stage2Target = extern struct {
llvm_cpu_features: ?[*:0]const u8,
cpu_builtin_str: ?[*:0]const u8,
cache_hash: ?[*:0]const u8,
+ cache_hash_len: usize,
os_builtin_str: ?[*:0]const u8,
dynamic_linker: ?[*:0]const u8,
@@ -1129,6 +1130,7 @@ const Stage2Target = extern struct {
}
};
+ const cache_hash_slice = cache_hash.toOwnedSlice();
self.* = .{
.arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
.vendor = 0,
@@ -1138,7 +1140,8 @@ const Stage2Target = extern struct {
.llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr,
.cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
.os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
- .cache_hash = cache_hash.toOwnedSlice().ptr,
+ .cache_hash = cache_hash_slice.ptr,
+ .cache_hash_len = cache_hash_slice.len,
.is_native = cross_target.isNative(),
.glibc_or_darwin_version = glibc_or_darwin_version,
.dynamic_linker = dynamic_linker,
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
index 35b05a1ddf8be39afe0b4d24fad7b5c60925c766..3cff34ea5c4fb47ae1e5956c76cd10199f692cdd 100644
--- a/src/cache_hash.cpp
+++ b/src/cache_hash.cpp
@@ -24,11 +24,15 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) {
ch->b64_digest = BUF_INIT;
}
-void cache_str(CacheHash *ch, const char *ptr) {
+void cache_mem(CacheHash *ch, const char *ptr, size_t len) {
assert(ch->manifest_file_path == nullptr);
assert(ptr != nullptr);
// + 1 to include the null byte
- blake2b_update(&ch->blake, ptr, strlen(ptr) + 1);
+ blake2b_update(&ch->blake, ptr, len);
+}
+
+void cache_str(CacheHash *ch, const char *ptr) {
+ cache_mem(ch, ptr, strlen(ptr) + 1);
}
void cache_int(CacheHash *ch, int x) {
diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp
index e2a10270f3c9675be6ec7a1444dc7c09d9230a28..9e4c41b1e0036999b9a6a0939694a9f34d0369cd 100644
--- a/src/cache_hash.hpp
+++ b/src/cache_hash.hpp
@@ -35,6 +35,7 @@ struct CacheHash {
void cache_init(CacheHash *ch, Buf *manifest_dir);
// Next, use the hash population functions to add the initial parameters.
+void cache_mem(CacheHash *ch, const char *ptr, size_t len);
void cache_str(CacheHash *ch, const char *ptr);
void cache_int(CacheHash *ch, int x);
void cache_bool(CacheHash *ch, bool x);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d659e27d86761082e4b79d160a0c4c3d65418131..e692c7b80578450bae2ca9f8e0cd85f4e360ebb8 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8664,7 +8664,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_int(&cache_hash, g->zig_target->os);
cache_int(&cache_hash, g->zig_target->abi);
if (g->zig_target->cache_hash != nullptr) {
- cache_str(&cache_hash, g->zig_target->cache_hash);
+ cache_mem(&cache_hash, g->zig_target->cache_hash, g->zig_target->cache_hash_len);
}
if (g->zig_target->glibc_or_darwin_version != nullptr) {
cache_int(&cache_hash, g->zig_target->glibc_or_darwin_version->major);
@@ -10309,7 +10309,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target->os);
cache_int(ch, g->zig_target->abi);
if (g->zig_target->cache_hash != nullptr) {
- cache_str(ch, g->zig_target->cache_hash);
+ cache_mem(ch, g->zig_target->cache_hash, g->zig_target->cache_hash_len);
}
if (g->zig_target->glibc_or_darwin_version != nullptr) {
cache_int(ch, g->zig_target->glibc_or_darwin_version->major);
diff --git a/src/stage2.cpp b/src/stage2.cpp
index 1f6cb2d6aa07ba9cf6d257f13b67d3529e8a4307..afb7ebb54802baad7e0246c68f6cb9a1c6e4a87b 100644
--- a/src/stage2.cpp
+++ b/src/stage2.cpp
@@ -251,9 +251,12 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
target->cache_hash = "\n\n";
}
+ target->cache_hash_len = strlen(target->cache_hash);
+
if (dynamic_linker != nullptr) {
target->dynamic_linker = dynamic_linker;
}
+
return ErrorNone;
}
diff --git a/src/stage2.h b/src/stage2.h
index b73269f4e8782a06762fca3e7a713368335c02f9..1ff0b5e8264413afdc603f95fb43bb87ada5c3cb 100644
--- a/src/stage2.h
+++ b/src/stage2.h
@@ -293,6 +293,7 @@ struct ZigTarget {
const char *llvm_cpu_features;
const char *cpu_builtin_str;
const char *cache_hash;
+ size_t cache_hash_len;
const char *os_builtin_str;
const char *dynamic_linker;
};
--
2.54.0
From 3f1c8e3d58f31dabd22fd6d1fa408512e5cbbb07 Mon Sep 17 00:00:00 2001
From: Heppokoyuki
Date: Thu, 12 Mar 2020 13:26:00 +0900
Subject: [PATCH 068/111] fix bug
---
lib/std/os/uefi/protocols/file_protocol.zig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/std/os/uefi/protocols/file_protocol.zig b/lib/std/os/uefi/protocols/file_protocol.zig
index cc6785caf7c4795d62988e753f7c5ed836456ceb..6202231cfb47e2b9093f5b4170ba4aa5db835d64 100644
--- a/lib/std/os/uefi/protocols/file_protocol.zig
+++ b/lib/std/os/uefi/protocols/file_protocol.zig
@@ -2,7 +2,7 @@ const uefi = @import("std").os.uefi;
const Guid = uefi.Guid;
const Time = uefi.Time;
-const FileProtocol = extern struct {
+pub const FileProtocol = extern struct {
revision: u64,
_open: extern fn (*const FileProtocol, **const FileProtocol, *u16, u64, u64) usize,
_close: extern fn (*const FileProtocol) usize,
@@ -67,7 +67,7 @@ const FileProtocol = extern struct {
pub const efi_file_valid_attr: u64 = 0x0000000000000037;
};
-const FileInfo = extern struct {
+pub const FileInfo = extern struct {
size: u64,
file_size: u64,
physical_size: u64,
--
2.54.0
From f58705b4a623b39ad10fe25a9a41507fdfc0b089 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 12 Mar 2020 00:32:50 -0400
Subject: [PATCH 069/111] fix `zig targets` not reporting native info
---
src-self-hosted/stage2.zig | 47 +++++++++++++++++++-------------------
src/main.cpp | 2 +-
src/stage2.cpp | 2 +-
src/stage2.h | 6 ++---
4 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
index 83a70c29e04b94219d3cdb8d6c5093bbd7e10300..36941cc3a13830eac7ff13c3c09fd0533470f03a 100644
--- a/src-self-hosted/stage2.zig
+++ b/src-self-hosted/stage2.zig
@@ -626,16 +626,24 @@ fn detectNativeCpuWithLLVM(
}
// ABI warning
-export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
- cmdTargets(zig_triple) catch |err| {
+export fn stage2_cmd_targets(
+ zig_triple: ?[*:0]const u8,
+ mcpu: ?[*:0]const u8,
+ dynamic_linker: ?[*:0]const u8,
+) c_int {
+ cmdTargets(zig_triple, mcpu, dynamic_linker) catch |err| {
std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
return -1;
};
return 0;
}
-fn cmdTargets(zig_triple: [*:0]const u8) !void {
- var cross_target = try CrossTarget.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });
+fn cmdTargets(
+ zig_triple_oz: ?[*:0]const u8,
+ mcpu_oz: ?[*:0]const u8,
+ dynamic_linker_oz: ?[*:0]const u8,
+) !void {
+ const cross_target = try stage2CrossTarget(zig_triple_oz, mcpu_oz, dynamic_linker_oz);
var dynamic_linker: ?[*:0]u8 = null;
const target = try crossTargetToTarget(cross_target, &dynamic_linker);
return @import("print_targets.zig").cmdTargets(
@@ -673,12 +681,11 @@ export fn stage2_target_parse(
return .None;
}
-fn stage2TargetParse(
- stage1_target: *Stage2Target,
+fn stage2CrossTarget(
zig_triple_oz: ?[*:0]const u8,
mcpu_oz: ?[*:0]const u8,
dynamic_linker_oz: ?[*:0]const u8,
-) !void {
+) !CrossTarget {
const zig_triple = if (zig_triple_oz) |zig_triple_z| mem.toSliceConst(u8, zig_triple_z) else "native";
const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;
const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.toSliceConst(u8, dl_z) else null;
@@ -716,6 +723,16 @@ fn stage2TargetParse(
else => |e| return e,
};
+ return target;
+}
+
+fn stage2TargetParse(
+ stage1_target: *Stage2Target,
+ zig_triple_oz: ?[*:0]const u8,
+ mcpu_oz: ?[*:0]const u8,
+ dynamic_linker_oz: ?[*:0]const u8,
+) !void {
+ const target = try stage2CrossTarget(zig_triple_oz, mcpu_oz, dynamic_linker_oz);
try stage1_target.fromTarget(target);
}
@@ -905,22 +922,6 @@ const Stage2Target = extern struct {
dynamic_linker: ?[*:0]const u8,
- fn toTarget(in_target: Stage2Target) CrossTarget {
- if (in_target.is_native) return .{};
-
- const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch
- const in_os = in_target.os;
- const in_abi = in_target.abi;
-
- return .{
- .Cross = .{
- .cpu = Target.Cpu.baseline(enumInt(Target.Cpu.Arch, in_arch)),
- .os = Target.Os.defaultVersionRange(enumInt(Target.Os.Tag, in_os)),
- .abi = enumInt(Target.Abi, in_abi),
- },
- };
- }
-
fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
const allocator = std.heap.c_allocator;
diff --git a/src/main.cpp b/src/main.cpp
index 92d08bed4fc2ab70f0c93b7890cc0783dbc4a48a..1939606b037332baab7f2645df64d49c59407624 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1391,7 +1391,7 @@ static int main0(int argc, char **argv) {
return main_exit(root_progress_node, EXIT_SUCCESS);
}
case CmdTargets:
- return stage2_cmd_targets(buf_ptr(&zig_triple_buf));
+ return stage2_cmd_targets(target_string, mcpu, dynamic_linker);
case CmdNone:
return print_full_usage(arg0, stderr, EXIT_FAILURE);
}
diff --git a/src/stage2.cpp b/src/stage2.cpp
index afb7ebb54802baad7e0246c68f6cb9a1c6e4a87b..7495ffddb9940af270596e0a93f45335434a573a 100644
--- a/src/stage2.cpp
+++ b/src/stage2.cpp
@@ -260,7 +260,7 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
return ErrorNone;
}
-int stage2_cmd_targets(const char *zig_triple) {
+int stage2_cmd_targets(const char *zig_triple, const char *mcpu, const char *dynamic_linker) {
const char *msg = "stage0 called stage2_cmd_targets";
stage2_panic(msg, strlen(msg));
}
diff --git a/src/stage2.h b/src/stage2.h
index 1ff0b5e8264413afdc603f95fb43bb87ada5c3cb..50f891dca983becc4b111497afde7ccaebaee146 100644
--- a/src/stage2.h
+++ b/src/stage2.h
@@ -201,9 +201,6 @@ ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
size_t completed_count, size_t estimated_total_items);
-// ABI warning
-ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
-
// ABI warning
struct Stage2LibCInstallation {
const char *include_dir;
@@ -302,6 +299,9 @@ struct ZigTarget {
ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
const char *dynamic_linker);
+// ABI warning
+ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple, const char *mcpu, const char *dynamic_linker);
+
// ABI warning
struct Stage2NativePaths {
--
2.54.0
From 89d7fc773d66609a8d93106f9a6d84d479771690 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 11 Mar 2020 20:03:36 +0100
Subject: [PATCH 070/111] std: Fix pwrite invocation on 32bit architectures
---
lib/std/os/linux.zig | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 719e541846f1435c845b4bed795b74b20280e164..79f9ba9c951078e0aad25da72ba1c3d65b62baa9 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -350,7 +350,13 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize {
);
}
} else {
- return syscall4(SYS_pread, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, offset);
+ return syscall4(
+ SYS_pread,
+ @bitCast(usize, @as(isize, fd)),
+ @ptrToInt(buf),
+ count,
+ offset,
+ );
}
}
@@ -385,7 +391,36 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
}
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
- return syscall4(SYS_pwrite, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, offset);
+ if (@hasDecl(@This(), "SYS_pwrite64")) {
+ if (require_aligned_register_pair) {
+ return syscall6(
+ SYS_pwrite64,
+ @bitCast(usize, @as(isize, fd)),
+ @ptrToInt(buf),
+ count,
+ 0,
+ @truncate(usize, offset),
+ @truncate(usize, offset >> 32),
+ );
+ } else {
+ return syscall5(
+ SYS_pwrite64,
+ @bitCast(usize, @as(isize, fd)),
+ @ptrToInt(buf),
+ count,
+ @truncate(usize, offset),
+ @truncate(usize, offset >> 32),
+ );
+ }
+ } else {
+ return syscall4(
+ SYS_pwrite,
+ @bitCast(usize, @as(isize, fd)),
+ @ptrToInt(buf),
+ count,
+ offset,
+ );
+ }
}
pub fn rename(old: [*:0]const u8, new: [*:0]const u8) usize {
--
2.54.0
From 11df0d0cf8c786d5b502c21a42d47631657a42f4 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 11 Mar 2020 20:56:43 +0100
Subject: [PATCH 071/111] std: Add setEndPos to fs.file
Allow the user to shrink/grow the file size as needed.
---
lib/std/c.zig | 1 +
lib/std/c/linux.zig | 2 ++
lib/std/fs/file.zig | 8 ++++++++
lib/std/io/test.zig | 17 +++++++++++++++++
lib/std/os.zig | 33 +++++++++++++++++++++++++++++++++
lib/std/os/linux.zig | 27 +++++++++++++++++++++++++++
lib/std/os/windows/kernel32.zig | 1 +
7 files changed, 89 insertions(+)
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 7c019085403177e2a9cfba1ceeb6f100e8113422..39a865ebbcc550d6cb0a876c940a3e926578e23d 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -79,6 +79,7 @@ pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, fla
pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t;
pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int;
pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int;
+pub extern "c" fn ftruncate(fd: c_int, length: off_t) c_int;
pub extern "c" fn raise(sig: c_int) c_int;
pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize;
diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig
index 7ac5ecd3fe0cbdd73d8e5f7a527f7a6b908f1a8f..1da0db57d6008d740282214d43562b16a25148ca 100644
--- a/lib/std/c/linux.zig
+++ b/lib/std/c/linux.zig
@@ -82,6 +82,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
+pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
+
pub extern "c" fn sendfile(
out_fd: fd_t,
in_fd: fd_t,
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 8362f94ca57fe1300c169b3da4fdd825fcb1839b..8bb377c99fdadb7e541e9708bf95b566e16abcfc 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -99,6 +99,14 @@ pub const File = struct {
return false;
}
+ pub const SetEndPosError = os.TruncateError;
+
+ /// Shrinks or expands the file.
+ /// The file offset after this call is undefined.
+ pub fn setEndPos(self: File, length: u64) SetEndPosError!void {
+ try os.truncate(self.handle, length);
+ }
+
pub const SeekError = os.SeekError;
/// Repositions read/write file offset relative to the current offset.
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
index 38dd2bb67a82adb019beea50f122c169dc173e26..9615377070ba3bfdf5965f97972470f407408109 100644
--- a/lib/std/io/test.zig
+++ b/lib/std/io/test.zig
@@ -125,6 +125,23 @@ test "File seek ops" {
expect((try file.getPos()) == 1234);
}
+test "setEndPos" {
+ const tmp_file_name = "temp_test_file.txt";
+ var file = try fs.cwd().createFile(tmp_file_name, .{});
+ defer {
+ file.close();
+ fs.cwd().deleteFile(tmp_file_name) catch {};
+ }
+
+ std.testing.expect((try file.getEndPos()) == 0);
+ try file.setEndPos(8192);
+ std.testing.expect((try file.getEndPos()) == 8192);
+ try file.setEndPos(4096);
+ std.testing.expect((try file.getEndPos()) == 4096);
+ try file.setEndPos(0);
+ std.testing.expect((try file.getEndPos()) == 0);
+}
+
test "updateTimes" {
const tmp_file_name = "just_a_temporary_file.txt";
var file = try fs.cwd().createFile(tmp_file_name, .{ .read = true });
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 76a5dc2be55cf227ebe1240d9eb6448009f01389..62347c2ee96ae7096f3a5c51ac0a5a36cedc661f 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -438,6 +438,39 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
return index;
}
+pub const TruncateError = error{
+ /// The file descriptor is not open for writing.
+ NotFile,
+} || UnexpectedError;
+
+pub fn truncate(fd: fd_t, length: u64) TruncateError!void {
+ if (std.Target.current.os.tag == .windows) {
+ try windows.SetFilePointerEx_BEGIN(fd, length);
+
+ if (windows.kernel32.SetEndOfFile(fd) == 0)
+ return TruncateError.Unexpected;
+
+ return;
+ }
+
+ while (true) {
+ const rc = if (builtin.link_libc) blk: {
+ if (std.Target.current.os.tag == .linux)
+ break :blk system.ftruncate64(fd, @bitCast(off_t, length))
+ else
+ break :blk system.ftruncate(fd, @bitCast(off_t, length));
+ } else
+ system.ftruncate(fd, length);
+
+ switch (errno(rc)) {
+ 0 => return,
+ EINTR => continue,
+ EBADF, EINVAL => return error.NotFile,
+ else => |err| return unexpectedErrno(err),
+ }
+ }
+}
+
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
///
/// Retries when interrupted by a signal.
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 79f9ba9c951078e0aad25da72ba1c3d65b62baa9..ba7356d62ca8633b6a3643e144fd32c8f32188b0 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -390,6 +390,33 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count);
}
+pub fn ftruncate(fd: i32, length: u64) usize {
+ if (@hasDecl(@This(), "SYS_ftruncate64")) {
+ if (require_aligned_register_pair) {
+ return syscall4(
+ SYS_ftruncate64,
+ @bitCast(usize, @as(isize, fd)),
+ 0,
+ @truncate(usize, length),
+ @truncate(usize, length >> 32),
+ );
+ } else {
+ return syscall3(
+ SYS_ftruncate64,
+ @bitCast(usize, @as(isize, fd)),
+ @truncate(usize, length),
+ @truncate(usize, length >> 32),
+ );
+ }
+ } else {
+ return syscall2(
+ SYS_ftruncate,
+ @bitCast(usize, @as(isize, fd)),
+ @truncate(usize, length),
+ );
+ }
+}
+
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
if (@hasDecl(@This(), "SYS_pwrite64")) {
if (require_aligned_register_pair) {
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 05a7a8f6a323c2d62ce4d057d1434021aa8c2024..2e5214eb20681fe01998b239706fdbb1347d9968 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -8,6 +8,7 @@ pub extern "kernel32" fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) c
pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL;
+pub extern "kernel32" fn SetEndOfFile(hFile: HANDLE) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn CreateEventExW(
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
--
2.54.0
From dda711ba0d650b921108c6d13bd9b7d37c47a96e Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 14:18:41 +0200
Subject: [PATCH 072/111] translate-c treat c bools as ints
---
src-self-hosted/translate_c.zig | 65 ++++++++++++++++++++++++++++++---
test/translate_c.zig | 11 ++++++
2 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index f14ebe33061141fa3cd5f43b68d8150cbeee2050..934ed3634d5f0ee7e8fe6058c8b21f2837b4945d 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
+ const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name;
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
+ const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name;
if (mem.eql(u8, checked_name, "uint8_t"))
return transTypeDefAsBuiltin(c, typedef_decl, "u8")
@@ -4871,7 +4871,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
const name = try c.str(raw_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
+ const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name;
if (scope.containsNow(mangled_name)) {
continue;
}
@@ -5560,12 +5560,63 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}
}
+fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
+ if (!isBoolRes(node)) {
+ if (node.id != .InfixOp) return node;
+
+ const group_node = try c.a().create(ast.Node.GroupedExpression);
+ group_node.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = node,
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ return &group_node.base;
+ }
+
+ const builtin_node = try transCreateNodeBuiltinFnCall(c, "@boolToInt");
+ try builtin_node.params.push(node);
+ builtin_node.rparen_token = try appendToken(c, .RParen, ")");
+ return &builtin_node.base;
+}
+
+fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
+ if (isBoolRes(node)) {
+ if (node.id != .InfixOp) return node;
+
+ const group_node = try c.a().create(ast.Node.GroupedExpression);
+ group_node.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = node,
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ return &group_node.base;
+ }
+
+ const op_token = try appendToken(c, .BangEqual, "!=");
+ const zero = try transCreateNodeInt(c, 0);
+ const res = try c.a().create(ast.Node.InfixOp);
+ res.* = .{
+ .op_token = op_token,
+ .lhs = node,
+ .op = .BangEqual,
+ .rhs = zero,
+ };
+ const group_node = try c.a().create(ast.Node.GroupedExpression);
+ group_node.* = .{
+ .lparen = try appendToken(c, .LParen, "("),
+ .expr = &res.base,
+ .rparen = try appendToken(c, .RParen, ")"),
+ };
+ return &group_node.base;
+}
+
fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);
while (true) {
const tok = it.next().?;
var op_token: ast.TokenIndex = undefined;
var op_id: ast.Node.InfixOp.Op = undefined;
+ var bool_op = false;
switch (tok.id) {
.Period => {
const name_tok = it.next().?;
@@ -5654,10 +5705,12 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
.AmpersandAmpersand => {
op_token = try appendToken(c, .Keyword_and, "and");
op_id = .BoolAnd;
+ bool_op = true;
},
.PipePipe => {
op_token = try appendToken(c, .Keyword_or, "or");
op_id = .BoolOr;
+ bool_op = true;
},
.AngleBracketRight => {
op_token = try appendToken(c, .AngleBracketRight, ">");
@@ -5740,12 +5793,14 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return node;
},
}
+ const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const op_node = try c.a().create(ast.Node.InfixOp);
+ const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
op_node.* = .{
.op_token = op_token,
- .lhs = node,
+ .lhs = try cast_fn(c, node),
.op = op_id,
- .rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+ .rhs = try cast_fn(c, rhs_node),
};
node = &op_node.base;
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index e21c3c49ae92bff0460c9da81848309b8d460df5..29b07b86a99a390ce98c5f0064e1f5377e96b6ac 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,6 +3,17 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("c booleans are just ints",
+ \\#define FOO(x) ((x >= 0) + (x >= 0))
+ \\#define BAR 1 && 2 > 4
+ , &[_][]const u8{
+ \\pub inline fn FOO(x: var) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) {
+ \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0);
+ \\}
+ ,
+ \\pub const BAR = (1 != 0) and (2 > 4);
+ });
+
cases.add("struct with aligned fields",
\\struct foo {
\\ __attribute__((aligned(1))) short bar;
--
2.54.0
From ae3fb6df007807a37fe448fdef2b8ee669b29a5a Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 11:56:21 -0600
Subject: [PATCH 073/111] Copy fmtstream
---
lib/std/fmtstream.zig | 1754 +++++++++++++++++++++++++++++++++++++++++
lib/std/std.zig | 1 +
2 files changed, 1755 insertions(+)
create mode 100644 lib/std/fmtstream.zig
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
new file mode 100644
index 0000000000000000000000000000000000000000..a7525ba79545fc601ee17b6d2afee55d714efa49
--- /dev/null
+++ b/lib/std/fmtstream.zig
@@ -0,0 +1,1754 @@
+const std = @import("std.zig");
+const math = std.math;
+const assert = std.debug.assert;
+const mem = std.mem;
+const builtin = @import("builtin");
+const errol = @import("fmt/errol.zig");
+const lossyCast = std.math.lossyCast;
+
+pub const default_max_depth = 3;
+
+pub const Alignment = enum {
+ Left,
+ Center,
+ Right,
+};
+
+pub const FormatOptions = struct {
+ precision: ?usize = null,
+ width: ?usize = null,
+ alignment: ?Alignment = null,
+ fill: u8 = ' ',
+};
+
+fn peekIsAlign(comptime fmt: []const u8) bool {
+ // Should only be called during a state transition to the format segment.
+ comptime assert(fmt[0] == ':');
+
+ inline for (([_]u8{ 1, 2 })[0..]) |i| {
+ if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// Renders fmt string with args, calling output with slices of bytes.
+/// If `output` returns an error, the error is returned from `format` and
+/// `output` is not called again.
+///
+/// The format string must be comptime known and may contain placeholders following
+/// this format:
+/// `{[position][specifier]:[fill][alignment][width].[precision]}`
+///
+/// Each word between `[` and `]` is a parameter you have to replace with something:
+///
+/// - *position* is the index of the argument that should be inserted
+/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
+/// - *fill* is a single character which is used to pad the formatted text
+/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned
+/// - *width* is the total width of the field in characters
+/// - *precision* specifies how many decimals a formatted number should have
+///
+/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when
+/// all parameters after the separator are omitted.
+/// Only exception is the *fill* parameter. If *fill* is required, one has to specify *alignment* as well, as otherwise
+/// the digits after `:` is interpreted as *width*, not *fill*.
+///
+/// The *specifier* has several options for types:
+/// - `x` and `X`:
+/// - format the non-numeric value as a string of bytes in hexadecimal notation ("binary dump") in either lower case or upper case
+/// - output numeric value in hexadecimal notation
+/// - `s`: print a pointer-to-many as a c-string, use zero-termination
+/// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values.
+/// - `e`: output floating point value in scientific notation
+/// - `d`: output numeric value in decimal notation
+/// - `b`: output integer value in binary notation
+/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
+/// - `*`: output the address of the value instead of the value itself.
+///
+/// If a formatted user type contains a function of the type
+/// ```
+/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
+/// ```
+/// with `?` being the type formatted, this function will be called instead of the default implementation.
+/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
+///
+/// A user type may be a `struct`, `vector`, `union` or `enum` type.
+pub fn format(
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ comptime fmt: []const u8,
+ args: var,
+) Errors!void {
+ const ArgSetType = u32;
+ if (@typeInfo(@TypeOf(args)) != .Struct) {
+ @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
+ }
+ if (args.len > ArgSetType.bit_count) {
+ @compileError("32 arguments max are supported per format call");
+ }
+
+ const State = enum {
+ Start,
+ Positional,
+ CloseBrace,
+ Specifier,
+ FormatFillAndAlign,
+ FormatWidth,
+ FormatPrecision,
+ };
+
+ comptime var start_index = 0;
+ comptime var state = State.Start;
+ comptime var maybe_pos_arg: ?comptime_int = null;
+ comptime var specifier_start = 0;
+ comptime var specifier_end = 0;
+ comptime var options = FormatOptions{};
+ comptime var arg_state: struct {
+ next_arg: usize = 0,
+ used_args: ArgSetType = 0,
+ args_len: usize = args.len,
+
+ fn hasUnusedArgs(comptime self: *@This()) bool {
+ return (@popCount(ArgSetType, self.used_args) != self.args_len);
+ }
+
+ fn nextArg(comptime self: *@This(), comptime pos_arg: ?comptime_int) comptime_int {
+ const next_idx = pos_arg orelse blk: {
+ const arg = self.next_arg;
+ self.next_arg += 1;
+ break :blk arg;
+ };
+
+ if (next_idx >= self.args_len) {
+ @compileError("Too few arguments");
+ }
+
+ // Mark this argument as used
+ self.used_args |= 1 << next_idx;
+
+ return next_idx;
+ }
+ } = .{};
+
+ inline for (fmt) |c, i| {
+ switch (state) {
+ .Start => switch (c) {
+ '{' => {
+ if (start_index < i) {
+ try output(context, fmt[start_index..i]);
+ }
+
+ start_index = i;
+ specifier_start = i + 1;
+ specifier_end = i + 1;
+ maybe_pos_arg = null;
+ state = .Positional;
+ options = FormatOptions{};
+ },
+ '}' => {
+ if (start_index < i) {
+ try output(context, fmt[start_index..i]);
+ }
+ state = .CloseBrace;
+ },
+ else => {},
+ },
+ .Positional => switch (c) {
+ '{' => {
+ state = .Start;
+ start_index = i;
+ },
+ ':' => {
+ state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
+ specifier_end = i;
+ },
+ '0'...'9' => {
+ if (maybe_pos_arg == null) {
+ maybe_pos_arg = 0;
+ }
+
+ maybe_pos_arg.? *= 10;
+ maybe_pos_arg.? += c - '0';
+ specifier_start = i + 1;
+
+ if (maybe_pos_arg.? >= args.len) {
+ @compileError("Positional value refers to non-existent argument");
+ }
+ },
+ '}' => {
+ const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
+
+ try formatType(
+ args[arg_to_print],
+ fmt[0..0],
+ options,
+ context,
+ Errors,
+ output,
+ default_max_depth,
+ );
+
+ state = .Start;
+ start_index = i + 1;
+ },
+ else => {
+ state = .Specifier;
+ specifier_start = i;
+ },
+ },
+ .CloseBrace => switch (c) {
+ '}' => {
+ state = .Start;
+ start_index = i;
+ },
+ else => @compileError("Single '}' encountered in format string"),
+ },
+ .Specifier => switch (c) {
+ ':' => {
+ specifier_end = i;
+ state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
+ },
+ '}' => {
+ const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
+
+ try formatType(
+ args[arg_to_print],
+ fmt[specifier_start..i],
+ options,
+ context,
+ Errors,
+ output,
+ default_max_depth,
+ );
+ state = .Start;
+ start_index = i + 1;
+ },
+ else => {},
+ },
+ // Only entered if the format string contains a fill/align segment.
+ .FormatFillAndAlign => switch (c) {
+ '<' => {
+ options.alignment = Alignment.Left;
+ state = .FormatWidth;
+ },
+ '^' => {
+ options.alignment = Alignment.Center;
+ state = .FormatWidth;
+ },
+ '>' => {
+ options.alignment = Alignment.Right;
+ state = .FormatWidth;
+ },
+ else => {
+ options.fill = c;
+ },
+ },
+ .FormatWidth => switch (c) {
+ '0'...'9' => {
+ if (options.width == null) {
+ options.width = 0;
+ }
+
+ options.width.? *= 10;
+ options.width.? += c - '0';
+ },
+ '.' => {
+ state = .FormatPrecision;
+ },
+ '}' => {
+ const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
+
+ try formatType(
+ args[arg_to_print],
+ fmt[specifier_start..specifier_end],
+ options,
+ context,
+ Errors,
+ output,
+ default_max_depth,
+ );
+ state = .Start;
+ start_index = i + 1;
+ },
+ else => {
+ @compileError("Unexpected character in width value: " ++ [_]u8{c});
+ },
+ },
+ .FormatPrecision => switch (c) {
+ '0'...'9' => {
+ if (options.precision == null) {
+ options.precision = 0;
+ }
+
+ options.precision.? *= 10;
+ options.precision.? += c - '0';
+ },
+ '}' => {
+ const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
+
+ try formatType(
+ args[arg_to_print],
+ fmt[specifier_start..specifier_end],
+ options,
+ context,
+ Errors,
+ output,
+ default_max_depth,
+ );
+ state = .Start;
+ start_index = i + 1;
+ },
+ else => {
+ @compileError("Unexpected character in precision value: " ++ [_]u8{c});
+ },
+ },
+ }
+ }
+ comptime {
+ if (comptime arg_state.hasUnusedArgs()) {
+ @compileError("Unused arguments");
+ }
+ if (state != State.Start) {
+ @compileError("Incomplete format string: " ++ fmt);
+ }
+ }
+ if (start_index < fmt.len) {
+ try output(context, fmt[start_index..]);
+ }
+}
+
+pub fn formatType(
+ value: var,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ max_depth: usize,
+) Errors!void {
+ if (comptime std.mem.eql(u8, fmt, "*")) {
+ try output(context, @typeName(@TypeOf(value).Child));
+ try output(context, "@");
+ try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);
+ return;
+ }
+
+ const T = @TypeOf(value);
+ switch (@typeInfo(T)) {
+ .ComptimeInt, .Int, .Float => {
+ return formatValue(value, fmt, options, context, Errors, output);
+ },
+ .Void => {
+ return output(context, "void");
+ },
+ .Bool => {
+ return output(context, if (value) "true" else "false");
+ },
+ .Optional => {
+ if (value) |payload| {
+ return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ } else {
+ return output(context, "null");
+ }
+ },
+ .ErrorUnion => {
+ if (value) |payload| {
+ return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ } else |err| {
+ return formatType(err, fmt, options, context, Errors, output, max_depth);
+ }
+ },
+ .ErrorSet => {
+ try output(context, "error.");
+ return output(context, @errorName(value));
+ },
+ .Enum => |enumInfo| {
+ if (comptime std.meta.trait.hasFn("format")(T)) {
+ return value.format(fmt, options, context, Errors, output);
+ }
+
+ try output(context, @typeName(T));
+ if (enumInfo.is_exhaustive) {
+ try output(context, ".");
+ try output(context, @tagName(value));
+ } else {
+ // TODO: when @tagName works on exhaustive enums print known enum strings
+ try output(context, "(");
+ try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
+ try output(context, ")");
+ }
+ },
+ .Union => {
+ if (comptime std.meta.trait.hasFn("format")(T)) {
+ return value.format(fmt, options, context, Errors, output);
+ }
+
+ try output(context, @typeName(T));
+ if (max_depth == 0) {
+ return output(context, "{ ... }");
+ }
+ const info = @typeInfo(T).Union;
+ if (info.tag_type) |UnionTagType| {
+ try output(context, "{ .");
+ try output(context, @tagName(@as(UnionTagType, value)));
+ try output(context, " = ");
+ inline for (info.fields) |u_field| {
+ if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
+ try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);
+ }
+ }
+ try output(context, " }");
+ } else {
+ try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
+ }
+ },
+ .Struct => |StructT| {
+ if (comptime std.meta.trait.hasFn("format")(T)) {
+ return value.format(fmt, options, context, Errors, output);
+ }
+
+ try output(context, @typeName(T));
+ if (max_depth == 0) {
+ return output(context, "{ ... }");
+ }
+ try output(context, "{");
+ inline for (StructT.fields) |f, i| {
+ if (i == 0) {
+ try output(context, " .");
+ } else {
+ try output(context, ", .");
+ }
+ try output(context, f.name);
+ try output(context, " = ");
+ try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
+ }
+ try output(context, " }");
+ },
+ .Pointer => |ptr_info| switch (ptr_info.size) {
+ .One => switch (@typeInfo(ptr_info.child)) {
+ .Array => |info| {
+ if (info.child == u8) {
+ return formatText(value, fmt, options, context, Errors, output);
+ }
+ return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ },
+ .Enum, .Union, .Struct => {
+ return formatType(value.*, fmt, options, context, Errors, output, max_depth);
+ },
+ else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
+ },
+ .Many, .C => {
+ if (ptr_info.sentinel) |sentinel| {
+ return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);
+ }
+ if (ptr_info.child == u8) {
+ if (fmt.len > 0 and fmt[0] == 's') {
+ return formatText(mem.span(value), fmt, options, context, Errors, output);
+ }
+ }
+ return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ },
+ .Slice => {
+ if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
+ return formatText(value, fmt, options, context, Errors, output);
+ }
+ if (ptr_info.child == u8) {
+ return formatText(value, fmt, options, context, Errors, output);
+ }
+ return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
+ },
+ },
+ .Array => |info| {
+ const Slice = @Type(builtin.TypeInfo{
+ .Pointer = .{
+ .size = .Slice,
+ .is_const = true,
+ .is_volatile = false,
+ .is_allowzero = false,
+ .alignment = @alignOf(info.child),
+ .child = info.child,
+ .sentinel = null,
+ },
+ });
+ return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);
+ },
+ .Vector => {
+ const len = @typeInfo(T).Vector.len;
+ try output(context, "{ ");
+ var i: usize = 0;
+ while (i < len) : (i += 1) {
+ try formatValue(value[i], fmt, options, context, Errors, output);
+ if (i < len - 1) {
+ try output(context, ", ");
+ }
+ }
+ try output(context, " }");
+ },
+ .Fn => {
+ return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
+ },
+ .Type => return output(context, @typeName(T)),
+ .EnumLiteral => {
+ const buffer = [_]u8{'.'} ++ @tagName(value);
+ return formatType(buffer, fmt, options, context, Errors, output, max_depth);
+ },
+ else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
+ }
+}
+
+fn formatValue(
+ value: var,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (comptime std.mem.eql(u8, fmt, "B")) {
+ return formatBytes(value, options, 1000, context, Errors, output);
+ } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
+ return formatBytes(value, options, 1024, context, Errors, output);
+ }
+
+ const T = @TypeOf(value);
+ switch (@typeInfo(T)) {
+ .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
+ .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
+ .Bool => return output(context, if (value) "true" else "false"),
+ else => comptime unreachable,
+ }
+}
+
+pub fn formatIntValue(
+ value: var,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ comptime var radix = 10;
+ comptime var uppercase = false;
+
+ const int_value = if (@TypeOf(value) == comptime_int) blk: {
+ const Int = math.IntFittingRange(value, value);
+ break :blk @as(Int, value);
+ } else
+ value;
+
+ if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
+ radix = 10;
+ uppercase = false;
+ } else if (comptime std.mem.eql(u8, fmt, "c")) {
+ if (@TypeOf(int_value).bit_count <= 8) {
+ return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);
+ } else {
+ @compileError("Cannot print integer that is larger than 8 bits as a ascii");
+ }
+ } else if (comptime std.mem.eql(u8, fmt, "b")) {
+ radix = 2;
+ uppercase = false;
+ } else if (comptime std.mem.eql(u8, fmt, "x")) {
+ radix = 16;
+ uppercase = false;
+ } else if (comptime std.mem.eql(u8, fmt, "X")) {
+ radix = 16;
+ uppercase = true;
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+
+ return formatInt(int_value, radix, uppercase, options, context, Errors, output);
+}
+
+fn formatFloatValue(
+ value: var,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
+ return formatFloatScientific(value, options, context, Errors, output);
+ } else if (comptime std.mem.eql(u8, fmt, "d")) {
+ return formatFloatDecimal(value, options, context, Errors, output);
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+}
+
+pub fn formatText(
+ bytes: []const u8,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (fmt.len == 0) {
+ return output(context, bytes);
+ } else if (comptime std.mem.eql(u8, fmt, "s")) {
+ return formatBuf(bytes, options, context, Errors, output);
+ } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
+ for (bytes) |c| {
+ try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);
+ }
+ return;
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+}
+
+pub fn formatAsciiChar(
+ c: u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ return output(context, @as(*const [1]u8, &c)[0..]);
+}
+
+pub fn formatBuf(
+ buf: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ try output(context, buf);
+
+ const width = options.width orelse 0;
+ var leftover_padding = if (width > buf.len) (width - buf.len) else return;
+ const pad_byte: u8 = options.fill;
+ while (leftover_padding > 0) : (leftover_padding -= 1) {
+ try output(context, @as(*const [1]u8, &pad_byte)[0..1]);
+ }
+}
+
+// Print a float in scientific notation to the specified precision. Null uses full precision.
+// It should be the case that every full precision, printed value can be re-parsed back to the
+// same type unambiguously.
+pub fn formatFloatScientific(
+ value: var,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ var x = @floatCast(f64, value);
+
+ // Errol doesn't handle these special cases.
+ if (math.signbit(x)) {
+ try output(context, "-");
+ x = -x;
+ }
+
+ if (math.isNan(x)) {
+ return output(context, "nan");
+ }
+ if (math.isPositiveInf(x)) {
+ return output(context, "inf");
+ }
+ if (x == 0.0) {
+ try output(context, "0");
+
+ if (options.precision) |precision| {
+ if (precision != 0) {
+ try output(context, ".");
+ var i: usize = 0;
+ while (i < precision) : (i += 1) {
+ try output(context, "0");
+ }
+ }
+ } else {
+ try output(context, ".0");
+ }
+
+ try output(context, "e+00");
+ return;
+ }
+
+ var buffer: [32]u8 = undefined;
+ var float_decimal = errol.errol3(x, buffer[0..]);
+
+ if (options.precision) |precision| {
+ errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
+
+ try output(context, float_decimal.digits[0..1]);
+
+ // {e0} case prints no `.`
+ if (precision != 0) {
+ try output(context, ".");
+
+ var printed: usize = 0;
+ if (float_decimal.digits.len > 1) {
+ const num_digits = math.min(float_decimal.digits.len, precision + 1);
+ try output(context, float_decimal.digits[1..num_digits]);
+ printed += num_digits - 1;
+ }
+
+ while (printed < precision) : (printed += 1) {
+ try output(context, "0");
+ }
+ }
+ } else {
+ try output(context, float_decimal.digits[0..1]);
+ try output(context, ".");
+ if (float_decimal.digits.len > 1) {
+ const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
+
+ try output(context, float_decimal.digits[1..num_digits]);
+ } else {
+ try output(context, "0");
+ }
+ }
+
+ try output(context, "e");
+ const exp = float_decimal.exp - 1;
+
+ if (exp >= 0) {
+ try output(context, "+");
+ if (exp > -10 and exp < 10) {
+ try output(context, "0");
+ }
+ try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ } else {
+ try output(context, "-");
+ if (exp > -10 and exp < 10) {
+ try output(context, "0");
+ }
+ try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ }
+}
+
+// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
+// By default floats are printed at full precision (no rounding).
+pub fn formatFloatDecimal(
+ value: var,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ var x = @as(f64, value);
+
+ // Errol doesn't handle these special cases.
+ if (math.signbit(x)) {
+ try output(context, "-");
+ x = -x;
+ }
+
+ if (math.isNan(x)) {
+ return output(context, "nan");
+ }
+ if (math.isPositiveInf(x)) {
+ return output(context, "inf");
+ }
+ if (x == 0.0) {
+ try output(context, "0");
+
+ if (options.precision) |precision| {
+ if (precision != 0) {
+ try output(context, ".");
+ var i: usize = 0;
+ while (i < precision) : (i += 1) {
+ try output(context, "0");
+ }
+ } else {
+ try output(context, ".0");
+ }
+ }
+
+ return;
+ }
+
+ // non-special case, use errol3
+ var buffer: [32]u8 = undefined;
+ var float_decimal = errol.errol3(x, buffer[0..]);
+
+ if (options.precision) |precision| {
+ errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal);
+
+ // exp < 0 means the leading is always 0 as errol result is normalized.
+ var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
+
+ // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
+ var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
+
+ if (num_digits_whole > 0) {
+ // We may have to zero pad, for instance 1e4 requires zero padding.
+ try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+
+ var i = num_digits_whole_no_pad;
+ while (i < num_digits_whole) : (i += 1) {
+ try output(context, "0");
+ }
+ } else {
+ try output(context, "0");
+ }
+
+ // {.0} special case doesn't want a trailing '.'
+ if (precision == 0) {
+ return;
+ }
+
+ try output(context, ".");
+
+ // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
+ var printed: usize = 0;
+
+ // Zero-fill until we reach significant digits or run out of precision.
+ if (float_decimal.exp <= 0) {
+ const zero_digit_count = @intCast(usize, -float_decimal.exp);
+ const zeros_to_print = math.min(zero_digit_count, precision);
+
+ var i: usize = 0;
+ while (i < zeros_to_print) : (i += 1) {
+ try output(context, "0");
+ printed += 1;
+ }
+
+ if (printed >= precision) {
+ return;
+ }
+ }
+
+ // Remaining fractional portion, zero-padding if insufficient.
+ assert(precision >= printed);
+ if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
+ try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
+ return;
+ } else {
+ try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ printed += float_decimal.digits.len - num_digits_whole_no_pad;
+
+ while (printed < precision) : (printed += 1) {
+ try output(context, "0");
+ }
+ }
+ } else {
+ // exp < 0 means the leading is always 0 as errol result is normalized.
+ var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
+
+ // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
+ var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
+
+ if (num_digits_whole > 0) {
+ // We may have to zero pad, for instance 1e4 requires zero padding.
+ try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+
+ var i = num_digits_whole_no_pad;
+ while (i < num_digits_whole) : (i += 1) {
+ try output(context, "0");
+ }
+ } else {
+ try output(context, "0");
+ }
+
+ // Omit `.` if no fractional portion
+ if (float_decimal.exp >= 0 and num_digits_whole_no_pad == float_decimal.digits.len) {
+ return;
+ }
+
+ try output(context, ".");
+
+ // Zero-fill until we reach significant digits or run out of precision.
+ if (float_decimal.exp < 0) {
+ const zero_digit_count = @intCast(usize, -float_decimal.exp);
+
+ var i: usize = 0;
+ while (i < zero_digit_count) : (i += 1) {
+ try output(context, "0");
+ }
+ }
+
+ try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ }
+}
+
+pub fn formatBytes(
+ value: var,
+ options: FormatOptions,
+ comptime radix: usize,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ if (value == 0) {
+ return output(context, "0B");
+ }
+
+ const mags_si = " kMGTPEZY";
+ const mags_iec = " KMGTPEZY";
+ const magnitude = switch (radix) {
+ 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags_si.len - 1),
+ 1024 => math.min(math.log2(value) / 10, mags_iec.len - 1),
+ else => unreachable,
+ };
+ const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
+ const suffix = switch (radix) {
+ 1000 => mags_si[magnitude],
+ 1024 => mags_iec[magnitude],
+ else => unreachable,
+ };
+
+ try formatFloatDecimal(new_value, options, context, Errors, output);
+
+ if (suffix == ' ') {
+ return output(context, "B");
+ }
+
+ const buf = switch (radix) {
+ 1000 => &[_]u8{ suffix, 'B' },
+ 1024 => &[_]u8{ suffix, 'i', 'B' },
+ else => unreachable,
+ };
+ return output(context, buf);
+}
+
+pub fn formatInt(
+ value: var,
+ base: u8,
+ uppercase: bool,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ const int_value = if (@TypeOf(value) == comptime_int) blk: {
+ const Int = math.IntFittingRange(value, value);
+ break :blk @as(Int, value);
+ } else
+ value;
+
+ if (@TypeOf(int_value).is_signed) {
+ return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);
+ } else {
+ return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);
+ }
+}
+
+fn formatIntSigned(
+ value: var,
+ base: u8,
+ uppercase: bool,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ const new_options = FormatOptions{
+ .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
+ .precision = options.precision,
+ .fill = options.fill,
+ };
+ const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
+ const Uint = std.meta.IntType(false, bit_count);
+ if (value < 0) {
+ try output(context, "-");
+ const new_value = math.absCast(value);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ } else if (options.width == null or options.width.? == 0) {
+ return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);
+ } else {
+ try output(context, "+");
+ const new_value = @intCast(Uint, value);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ }
+}
+
+fn formatIntUnsigned(
+ value: var,
+ base: u8,
+ uppercase: bool,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ assert(base >= 2);
+ var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
+ const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
+ const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits);
+ var a: MinInt = value;
+ var index: usize = buf.len;
+
+ while (true) {
+ const digit = a % base;
+ index -= 1;
+ buf[index] = digitToChar(@intCast(u8, digit), uppercase);
+ a /= base;
+ if (a == 0) break;
+ }
+
+ const digits_buf = buf[index..];
+ const width = options.width orelse 0;
+ const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0;
+
+ if (padding > index) {
+ const zero_byte: u8 = options.fill;
+ var leftover_padding = padding - index;
+ while (true) {
+ try output(context, @as(*const [1]u8, &zero_byte)[0..]);
+ leftover_padding -= 1;
+ if (leftover_padding == 0) break;
+ }
+ mem.set(u8, buf[0..index], options.fill);
+ return output(context, &buf);
+ } else {
+ const padded_buf = buf[index - padding ..];
+ mem.set(u8, padded_buf[0..padding], options.fill);
+ return output(context, padded_buf);
+ }
+}
+
+pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
+ var context = FormatIntBuf{
+ .out_buf = out_buf,
+ .index = 0,
+ };
+ formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
+ return context.index;
+}
+const FormatIntBuf = struct {
+ out_buf: []u8,
+ index: usize,
+};
+fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
+ mem.copy(u8, context.out_buf[context.index..], bytes);
+ context.index += bytes.len;
+}
+
+pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
+ if (!T.is_signed) return parseUnsigned(T, buf, radix);
+ if (buf.len == 0) return @as(T, 0);
+ if (buf[0] == '-') {
+ return math.negate(try parseUnsigned(T, buf[1..], radix));
+ } else if (buf[0] == '+') {
+ return parseUnsigned(T, buf[1..], radix);
+ } else {
+ return parseUnsigned(T, buf, radix);
+ }
+}
+
+test "parseInt" {
+ std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
+ std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
+ std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
+ std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
+ std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
+ std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
+ std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
+}
+
+pub const ParseUnsignedError = error{
+ /// The result cannot fit in the type specified
+ Overflow,
+
+ /// The input had a byte that was not a digit
+ InvalidCharacter,
+};
+
+pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsignedError!T {
+ var x: T = 0;
+
+ for (buf) |c| {
+ const digit = try charToDigit(c, radix);
+
+ if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
+ x = try math.add(T, x, try math.cast(T, digit));
+ }
+
+ return x;
+}
+
+test "parseUnsigned" {
+ std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
+ std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
+ std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
+
+ std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
+ std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
+
+ std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
+
+ std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
+ std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
+
+ std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
+ std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
+
+ std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
+
+ // these numbers should fit even though the radix itself doesn't fit in the destination type
+ std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
+ std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
+ std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
+ std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
+ std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
+ std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
+}
+
+pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
+
+test "parseFloat" {
+ _ = @import("fmt/parse_float.zig");
+}
+
+pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
+ const value = switch (c) {
+ '0'...'9' => c - '0',
+ 'A'...'Z' => c - 'A' + 10,
+ 'a'...'z' => c - 'a' + 10,
+ else => return error.InvalidCharacter,
+ };
+
+ if (value >= radix) return error.InvalidCharacter;
+
+ return value;
+}
+
+fn digitToChar(digit: u8, uppercase: bool) u8 {
+ return switch (digit) {
+ 0...9 => digit + '0',
+ 10...35 => digit + ((if (uppercase) @as(u8, 'A') else @as(u8, 'a')) - 10),
+ else => unreachable,
+ };
+}
+
+const BufPrintContext = struct {
+ remaining: []u8,
+};
+
+fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
+ if (context.remaining.len < bytes.len) {
+ mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
+ return error.BufferTooSmall;
+ }
+ mem.copy(u8, context.remaining, bytes);
+ context.remaining = context.remaining[bytes.len..];
+}
+
+pub const BufPrintError = error{
+ /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
+ BufferTooSmall,
+};
+pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
+ var context = BufPrintContext{ .remaining = buf };
+ try format(&context, BufPrintError, bufPrintWrite, fmt, args);
+ return buf[0 .. buf.len - context.remaining.len];
+}
+
+pub const AllocPrintError = error{OutOfMemory};
+
+pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
+ var size: usize = 0;
+ format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
+ const buf = try allocator.alloc(u8, size);
+ return bufPrint(buf, fmt, args) catch |err| switch (err) {
+ error.BufferTooSmall => unreachable, // we just counted the size above
+ };
+}
+
+fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
+ size.* += bytes.len;
+}
+
+pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
+ const result = try allocPrint(allocator, fmt ++ "\x00", args);
+ return result[0 .. result.len - 1 :0];
+}
+
+test "bufPrintInt" {
+ var buffer: [100]u8 = undefined;
+ const buf = buffer[0..];
+
+ std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, false, FormatOptions{}));
+
+ std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}));
+ std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}));
+ std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}));
+ std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}));
+
+ std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}));
+
+ std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }));
+ std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }));
+ std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }));
+
+ std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }));
+ std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }));
+}
+
+fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
+ return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
+}
+
+test "parse u64 digit too big" {
+ _ = parseUnsigned(u64, "123a", 10) catch |err| {
+ if (err == error.InvalidCharacter) return;
+ unreachable;
+ };
+ unreachable;
+}
+
+test "parse unsigned comptime" {
+ comptime {
+ std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
+ }
+}
+
+test "optional" {
+ {
+ const value: ?i32 = 1234;
+ try testFmt("optional: 1234\n", "optional: {}\n", .{value});
+ }
+ {
+ const value: ?i32 = null;
+ try testFmt("optional: null\n", "optional: {}\n", .{value});
+ }
+}
+
+test "error" {
+ {
+ const value: anyerror!i32 = 1234;
+ try testFmt("error union: 1234\n", "error union: {}\n", .{value});
+ }
+ {
+ const value: anyerror!i32 = error.InvalidChar;
+ try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
+ }
+}
+
+test "int.small" {
+ {
+ const value: u3 = 0b101;
+ try testFmt("u3: 5\n", "u3: {}\n", .{value});
+ }
+}
+
+test "int.specifier" {
+ {
+ const value: u8 = 'a';
+ try testFmt("u8: a\n", "u8: {c}\n", .{value});
+ }
+ {
+ const value: u8 = 0b1100;
+ try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
+ }
+}
+
+test "int.padded" {
+ try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
+ try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
+}
+
+test "buffer" {
+ {
+ var buf1: [32]u8 = undefined;
+ var context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+ var res = buf1[0 .. buf1.len - context.remaining.len];
+ std.testing.expect(mem.eql(u8, res, "1234"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ std.testing.expect(mem.eql(u8, res, "a"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ std.testing.expect(mem.eql(u8, res, "1100"));
+ }
+}
+
+test "array" {
+ {
+ const value: [3]u8 = "abc".*;
+ try testFmt("array: abc\n", "array: {}\n", .{value});
+ try testFmt("array: abc\n", "array: {}\n", .{&value});
+
+ var buf: [100]u8 = undefined;
+ try testFmt(
+ try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
+ "array: {*}\n",
+ .{&value},
+ );
+ }
+}
+
+test "slice" {
+ {
+ const value: []const u8 = "abc";
+ try testFmt("slice: abc\n", "slice: {}\n", .{value});
+ }
+ {
+ const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
+ try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
+ }
+
+ try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
+ try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
+}
+
+test "pointer" {
+ {
+ const value = @intToPtr(*align(1) i32, 0xdeadbeef);
+ try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
+ try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+ }
+}
+
+test "cstr" {
+ try testFmt(
+ "cstr: Test C\n",
+ "cstr: {s}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
+ try testFmt(
+ "cstr: Test C \n",
+ "cstr: {s:10}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
+}
+
+test "filesize" {
+ try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
+ try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
+}
+
+test "struct" {
+ {
+ const Struct = struct {
+ field: u8,
+ };
+ const value = Struct{ .field = 42 };
+ try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
+ try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
+ }
+ {
+ const Struct = struct {
+ a: u0,
+ b: u1,
+ };
+ const value = Struct{ .a = 0, .b = 1 };
+ try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
+ }
+}
+
+test "enum" {
+ const Enum = enum {
+ One,
+ Two,
+ };
+ const value = Enum.Two;
+ try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
+ try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
+}
+
+test "non-exhaustive enum" {
+ const Enum = enum(u16) {
+ One = 0x000f,
+ Two = 0xbeef,
+ _,
+ };
+ try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
+ try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
+ try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
+ try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
+ try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
+ try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
+}
+
+test "float.scientific" {
+ try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
+ try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
+ try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
+ try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
+}
+
+test "float.scientific.precision" {
+ try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
+ try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
+ try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
+ // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
+ // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
+ try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
+}
+
+test "float.special" {
+ try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
+ // negative nan is not defined by IEE 754,
+ // and ARM thus normalizes it to positive nan
+ if (builtin.arch != builtin.Arch.arm) {
+ try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
+ }
+ try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
+ try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
+}
+
+test "float.decimal" {
+ try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
+ try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
+ try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
+ try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
+ // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
+ // -11.12339... is rounded back up to -11.1234
+ try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
+ try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
+ try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
+ try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
+ try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
+ try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
+ try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
+}
+
+test "float.libc.sanity" {
+ try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
+ try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
+ try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
+ try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
+ try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
+
+ // libc differences
+ //
+ // This is 0.015625 exactly according to gdb. We thus round down,
+ // however glibc rounds up for some reason. This occurs for all
+ // floats of the form x.yyyy25 on a precision point.
+ try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
+ // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
+ // also rounds to 630 so I'm inclined to believe libc is not
+ // optimal here.
+ try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
+}
+
+test "custom" {
+ const Vec2 = struct {
+ const SelfType = @This();
+ x: f32,
+ y: f32,
+
+ pub fn format(
+ self: SelfType,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ ) Errors!void {
+ if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
+ return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ } else if (comptime std.mem.eql(u8, fmt, "d")) {
+ return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y });
+ } else {
+ @compileError("Unknown format character: '" ++ fmt ++ "'");
+ }
+ }
+ };
+
+ var buf1: [32]u8 = undefined;
+ var value = Vec2{
+ .x = 10.2,
+ .y = 2.22,
+ };
+ try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
+ try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
+
+ // same thing but not passing a pointer
+ try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
+ try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
+}
+
+test "struct" {
+ const S = struct {
+ a: u32,
+ b: anyerror,
+ };
+
+ const inst = S{
+ .a = 456,
+ .b = error.Unused,
+ };
+
+ try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
+}
+
+test "union" {
+ const TU = union(enum) {
+ float: f32,
+ int: u32,
+ };
+
+ const UU = union {
+ float: f32,
+ int: u32,
+ };
+
+ const EU = extern union {
+ float: f32,
+ int: u32,
+ };
+
+ const tu_inst = TU{ .int = 123 };
+ const uu_inst = UU{ .int = 456 };
+ const eu_inst = EU{ .float = 321.123 };
+
+ try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
+
+ var buf: [100]u8 = undefined;
+ const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
+ std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
+
+ const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
+ std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
+}
+
+test "enum" {
+ const E = enum {
+ One,
+ Two,
+ Three,
+ };
+
+ const inst = E.Two;
+
+ try testFmt("E.Two", "{}", .{inst});
+}
+
+test "struct.self-referential" {
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ };
+
+ var inst = S{
+ .a = null,
+ };
+ inst.a = &inst;
+
+ try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
+}
+
+test "struct.zero-size" {
+ const A = struct {
+ fn foo() void {}
+ };
+ const B = struct {
+ a: A,
+ c: i32,
+ };
+
+ const a = A{};
+ const b = B{ .a = a, .c = 0 };
+
+ try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
+}
+
+test "bytes.hex" {
+ const some_bytes = "\xCA\xFE\xBA\xBE";
+ try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
+ try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
+ //Test Slices
+ try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
+ try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
+ const bytes_with_zeros = "\x00\x0E\xBA\xBE";
+ try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
+}
+
+fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
+ var buf: [100]u8 = undefined;
+ const result = try bufPrint(buf[0..], template, args);
+ if (mem.eql(u8, result, expected)) return;
+
+ std.debug.warn("\n====== expected this output: =========\n", .{});
+ std.debug.warn("{}", .{expected});
+ std.debug.warn("\n======== instead found this: =========\n", .{});
+ std.debug.warn("{}", .{result});
+ std.debug.warn("\n======================================\n", .{});
+ return error.TestFailed;
+}
+
+pub fn trim(buf: []const u8) []const u8 {
+ var start: usize = 0;
+ while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
+
+ var end: usize = buf.len;
+ while (true) {
+ if (end > start) {
+ const new_end = end - 1;
+ if (isWhiteSpace(buf[new_end])) {
+ end = new_end;
+ continue;
+ }
+ }
+ break;
+ }
+ return buf[start..end];
+}
+
+test "trim" {
+ std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
+ std.testing.expect(mem.eql(u8, "", trim(" ")));
+ std.testing.expect(mem.eql(u8, "", trim("")));
+ std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
+ std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
+}
+
+pub fn isWhiteSpace(byte: u8) bool {
+ return switch (byte) {
+ ' ', '\t', '\n', '\r' => true,
+ else => false,
+ };
+}
+
+pub fn hexToBytes(out: []u8, input: []const u8) !void {
+ if (out.len * 2 < input.len)
+ return error.InvalidLength;
+
+ var in_i: usize = 0;
+ while (in_i != input.len) : (in_i += 2) {
+ const hi = try charToDigit(input[in_i], 16);
+ const lo = try charToDigit(input[in_i + 1], 16);
+ out[in_i / 2] = (hi << 4) | lo;
+ }
+}
+
+test "hexToBytes" {
+ const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
+ var pb: [32]u8 = undefined;
+ try hexToBytes(pb[0..], test_hex_str);
+ try testFmt(test_hex_str, "{X}", .{pb});
+}
+
+test "formatIntValue with comptime_int" {
+ const value: comptime_int = 123456789123456789;
+
+ var buf = std.ArrayList(u8).init(std.testing.allocator);
+ defer buf.deinit();
+ try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
+ std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
+}
+
+test "formatType max_depth" {
+ const Vec2 = struct {
+ const SelfType = @This();
+ x: f32,
+ y: f32,
+
+ pub fn format(
+ self: SelfType,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ ) Errors!void {
+ if (fmt.len == 0) {
+ return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+ }
+ };
+ const E = enum {
+ One,
+ Two,
+ Three,
+ };
+ const TU = union(enum) {
+ const SelfType = @This();
+ float: f32,
+ int: u32,
+ ptr: ?*SelfType,
+ };
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ tu: TU,
+ e: E,
+ vec: Vec2,
+ };
+
+ var inst = S{
+ .a = null,
+ .tu = TU{ .ptr = null },
+ .e = E.Two,
+ .vec = Vec2{ .x = 10.2, .y = 2.22 },
+ };
+ inst.a = &inst;
+ inst.tu.ptr = &inst.tu;
+
+ var buf0 = std.ArrayList(u8).init(std.testing.allocator);
+ defer buf0.deinit();
+ try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
+ std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+
+ var buf1 = std.ArrayList(u8).init(std.testing.allocator);
+ defer buf1.deinit();
+ try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
+ std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+ var buf2 = std.ArrayList(u8).init(std.testing.allocator);
+ defer buf2.deinit();
+ try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
+ std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+ var buf3 = std.ArrayList(u8).init(std.testing.allocator);
+ defer buf3.deinit();
+ try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
+ std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+}
+
+test "positional" {
+ try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+ try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+ try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
+ try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
+ try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
+}
+
+test "positional with specifier" {
+ try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
+}
+
+test "positional/alignment/width/precision" {
+ try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
+}
+
+test "vector" {
+ // https://github.com/ziglang/zig/issues/3317
+ if (builtin.arch == .mipsel) return error.SkipZigTest;
+
+ const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
+ const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
+ const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
+
+ try testFmt("{ true, false, true, false }", "{}", .{vbool});
+ try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
+ try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
+ try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
+ try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
+ try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
+ try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
+}
+
+test "enum-literal" {
+ try testFmt(".hello_world", "{}", .{.hello_world});
+}
diff --git a/lib/std/std.zig b/lib/std/std.zig
index 9277370ca6abf6c020ce48ec059eca6161c63594..b7fe709c7c164d4f122da5e6b64df7ef52b65dcd 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -38,6 +38,7 @@ pub const elf = @import("elf.zig");
pub const event = @import("event.zig");
pub const fifo = @import("fifo.zig");
pub const fmt = @import("fmt.zig");
+pub const fmtstream = @import("fmtstream.zig");
pub const fs = @import("fs.zig");
pub const hash = @import("hash.zig");
pub const hash_map = @import("hash_map.zig");
--
2.54.0
From 278b9ec1aaabb8bcfbbf9c964012dc5bd2ad154a Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 11:59:37 -0600
Subject: [PATCH 074/111] Blind translation
---
lib/std/fmtstream.zig | 376 +++++++++++++++++++-----------------------
1 file changed, 170 insertions(+), 206 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index a7525ba79545fc601ee17b6d2afee55d714efa49..bb8d52d742e32aaf87b2e2246e882e292553ccf0 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
///
/// If a formatted user type contains a function of the type
/// ```
-/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
+/// fn format(value: ?, comptime fmt: []const u8, options: std.fmtstream.FormatOptions, out_stream: var) !void
/// ```
/// with `?` being the type formatted, this function will be called instead of the default implementation.
/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
///
/// A user type may be a `struct`, `vector`, `union` or `enum` type.
pub fn format(
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ out_stream: var,
comptime fmt: []const u8,
args: var,
-) Errors!void {
+) !void {
const ArgSetType = u32;
if (@typeInfo(@TypeOf(args)) != .Struct) {
@compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
@@ -138,7 +136,7 @@ pub fn format(
.Start => switch (c) {
'{' => {
if (start_index < i) {
- try output(context, fmt[start_index..i]);
+ try out_stream.writeAll(fmt[start_index..i]);
}
start_index = i;
@@ -150,7 +148,7 @@ pub fn format(
},
'}' => {
if (start_index < i) {
- try output(context, fmt[start_index..i]);
+ try out_stream.writeAll(fmt[start_index..i]);
}
state = .CloseBrace;
},
@@ -185,9 +183,7 @@ pub fn format(
args[arg_to_print],
fmt[0..0],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
@@ -218,9 +214,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..i],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -265,9 +259,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..specifier_end],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -293,9 +285,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..specifier_end],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -316,7 +306,7 @@ pub fn format(
}
}
if (start_index < fmt.len) {
- try output(context, fmt[start_index..]);
+ try out_stream.writeAll(fmt[start_index..]);
}
}
@@ -324,121 +314,119 @@ pub fn formatType(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ out_stream: var,
max_depth: usize,
-) Errors!void {
+) !void {
if (comptime std.mem.eql(u8, fmt, "*")) {
- try output(context, @typeName(@TypeOf(value).Child));
- try output(context, "@");
- try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);
+ try out_stream.writeAll(@typeName(@TypeOf(value).Child));
+ try out_stream.writeAll("@");
+ try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
return;
}
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.ComptimeInt, .Int, .Float => {
- return formatValue(value, fmt, options, context, Errors, output);
+ return formatValue(value, fmt, options, out_stream);
},
.Void => {
- return output(context, "void");
+ return out_stream.writeAll("void");
},
.Bool => {
- return output(context, if (value) "true" else "false");
+ return out_stream.writeAll(if (value) "true" else "false");
},
.Optional => {
if (value) |payload| {
- return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ return formatType(payload, fmt, options, out_stream, max_depth);
} else {
- return output(context, "null");
+ return out_stream.writeAll("null");
}
},
.ErrorUnion => {
if (value) |payload| {
- return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ return formatType(payload, fmt, options, out_stream, max_depth);
} else |err| {
- return formatType(err, fmt, options, context, Errors, output, max_depth);
+ return formatType(err, fmt, options, out_stream, max_depth);
}
},
.ErrorSet => {
- try output(context, "error.");
- return output(context, @errorName(value));
+ try out_stream.writeAll("error.");
+ return out_stream.writeAll(@errorName(value));
},
.Enum => |enumInfo| {
if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
+ return value.format(fmt, options, out_stream);
}
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (enumInfo.is_exhaustive) {
- try output(context, ".");
- try output(context, @tagName(value));
+ try out_stream.writeAll(".");
+ try out_stream.writeAll(@tagName(value));
} else {
// TODO: when @tagName works on exhaustive enums print known enum strings
- try output(context, "(");
- try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
- try output(context, ")");
+ try out_stream.writeAll("(");
+ try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
+ try out_stream.writeAll(")");
}
},
.Union => {
if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
+ return value.format(fmt, options, out_stream);
}
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
- return output(context, "{ ... }");
+ return out_stream.writeAll("{ ... }");
}
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
- try output(context, "{ .");
- try output(context, @tagName(@as(UnionTagType, value)));
- try output(context, " = ");
+ try out_stream.writeAll("{ .");
+ try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
+ try out_stream.writeAll(" = ");
inline for (info.fields) |u_field| {
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
- try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);
+ try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
}
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
} else {
- try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
+ try format(out_stream, "@{x}", .{@ptrToInt(&value)});
}
},
.Struct => |StructT| {
if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
+ return value.format(fmt, options, out_stream);
}
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
- return output(context, "{ ... }");
+ return out_stream.writeAll("{ ... }");
}
- try output(context, "{");
+ try out_stream.writeAll("{");
inline for (StructT.fields) |f, i| {
if (i == 0) {
- try output(context, " .");
+ try out_stream.writeAll(" .");
} else {
- try output(context, ", .");
+ try out_stream.writeAll(", .");
}
- try output(context, f.name);
- try output(context, " = ");
- try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
+ try out_stream.writeAll(f.name);
+ try out_stream.writeAll(" = ");
+ try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => switch (@typeInfo(ptr_info.child)) {
.Array => |info| {
if (info.child == u8) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
},
.Enum, .Union, .Struct => {
- return formatType(value.*, fmt, options, context, Errors, output, max_depth);
+ return formatType(value.*, fmt, options, out_stream, max_depth);
},
- else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
+ else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
},
.Many, .C => {
if (ptr_info.sentinel) |sentinel| {
@@ -446,19 +434,19 @@ pub fn formatType(
}
if (ptr_info.child == u8) {
if (fmt.len > 0 and fmt[0] == 's') {
- return formatText(mem.span(value), fmt, options, context, Errors, output);
+ return formatText(mem.span(value), fmt, options, out_stream);
}
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
},
.Slice => {
if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
if (ptr_info.child == u8) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
+ return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
},
},
.Array => |info| {
@@ -473,24 +461,24 @@ pub fn formatType(
.sentinel = null,
},
});
- return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);
+ return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
},
.Vector => {
const len = @typeInfo(T).Vector.len;
- try output(context, "{ ");
+ try out_stream.writeAll("{ ");
var i: usize = 0;
while (i < len) : (i += 1) {
- try formatValue(value[i], fmt, options, context, Errors, output);
+ try formatValue(value[i], fmt, options, out_stream);
if (i < len - 1) {
- try output(context, ", ");
+ try out_stream.writeAll(", ");
}
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
},
.Fn => {
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
},
- .Type => return output(context, @typeName(T)),
+ .Type => return out_stream.writeAll(@typeName(T)),
.EnumLiteral => {
const buffer = [_]u8{'.'} ++ @tagName(value);
return formatType(buffer, fmt, options, context, Errors, output, max_depth);
@@ -503,21 +491,19 @@ fn formatValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (comptime std.mem.eql(u8, fmt, "B")) {
- return formatBytes(value, options, 1000, context, Errors, output);
+ return formatBytes(value, options, 1000, out_stream);
} else if (comptime std.mem.eql(u8, fmt, "Bi")) {
- return formatBytes(value, options, 1024, context, Errors, output);
+ return formatBytes(value, options, 1024, out_stream);
}
const T = @TypeOf(value);
switch (@typeInfo(T)) {
- .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
- .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
- .Bool => return output(context, if (value) "true" else "false"),
+ .Float => return formatFloatValue(value, fmt, options, out_stream),
+ .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
+ .Bool => return out_stream.writeAll(if (value) "true" else "false"),
else => comptime unreachable,
}
}
@@ -526,10 +512,8 @@ pub fn formatIntValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
comptime var radix = 10;
comptime var uppercase = false;
@@ -544,7 +528,7 @@ pub fn formatIntValue(
uppercase = false;
} else if (comptime std.mem.eql(u8, fmt, "c")) {
if (@TypeOf(int_value).bit_count <= 8) {
- return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);
+ return formatAsciiChar(@as(u8, int_value), options, out_stream);
} else {
@compileError("Cannot print integer that is larger than 8 bits as a ascii");
}
@@ -561,21 +545,19 @@ pub fn formatIntValue(
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
- return formatInt(int_value, radix, uppercase, options, context, Errors, output);
+ return formatInt(int_value, radix, uppercase, options, out_stream);
}
fn formatFloatValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
- return formatFloatScientific(value, options, context, Errors, output);
+ return formatFloatScientific(value, options, out_stream);
} else if (comptime std.mem.eql(u8, fmt, "d")) {
- return formatFloatDecimal(value, options, context, Errors, output);
+ return formatFloatDecimal(value, options, out_stream);
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
@@ -585,17 +567,15 @@ pub fn formatText(
bytes: []const u8,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (fmt.len == 0) {
- return output(context, bytes);
+ return out_stream.writeAll(bytes);
} else if (comptime std.mem.eql(u8, fmt, "s")) {
- return formatBuf(bytes, options, context, Errors, output);
+ return formatBuf(bytes, options, out_stream);
} else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
for (bytes) |c| {
- try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);
+ try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
}
return;
} else {
@@ -606,27 +586,23 @@ pub fn formatText(
pub fn formatAsciiChar(
c: u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
- return output(context, @as(*const [1]u8, &c)[0..]);
+ out_stream: var,
+) !void {
+ return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
}
pub fn formatBuf(
buf: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
- try output(context, buf);
+ out_stream: var,
+) !void {
+ try out_stream.writeAll(buf);
const width = options.width orelse 0;
var leftover_padding = if (width > buf.len) (width - buf.len) else return;
const pad_byte: u8 = options.fill;
while (leftover_padding > 0) : (leftover_padding -= 1) {
- try output(context, @as(*const [1]u8, &pad_byte)[0..1]);
+ try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
}
}
@@ -636,40 +612,38 @@ pub fn formatBuf(
pub fn formatFloatScientific(
value: var,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
var x = @floatCast(f64, value);
// Errol doesn't handle these special cases.
if (math.signbit(x)) {
- try output(context, "-");
+ try out_stream.writeAll("-");
x = -x;
}
if (math.isNan(x)) {
- return output(context, "nan");
+ return out_stream.writeAll("nan");
}
if (math.isPositiveInf(x)) {
- return output(context, "inf");
+ return out_stream.writeAll("inf");
}
if (x == 0.0) {
- try output(context, "0");
+ try out_stream.writeAll("0");
if (options.precision) |precision| {
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var i: usize = 0;
while (i < precision) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
- try output(context, ".0");
+ try out_stream.writeAll(".0");
}
- try output(context, "e+00");
+ try out_stream.writeAll("e+00");
return;
}
@@ -679,50 +653,50 @@ pub fn formatFloatScientific(
if (options.precision) |precision| {
errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
- try output(context, float_decimal.digits[0..1]);
+ try out_stream.writeAll(float_decimal.digits[0..1]);
// {e0} case prints no `.`
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var printed: usize = 0;
if (float_decimal.digits.len > 1) {
const num_digits = math.min(float_decimal.digits.len, precision + 1);
- try output(context, float_decimal.digits[1..num_digits]);
+ try out_stream.writeAll(float_decimal.digits[1..num_digits]);
printed += num_digits - 1;
}
while (printed < precision) : (printed += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
- try output(context, float_decimal.digits[0..1]);
- try output(context, ".");
+ try out_stream.writeAll(float_decimal.digits[0..1]);
+ try out_stream.writeAll(".");
if (float_decimal.digits.len > 1) {
const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
- try output(context, float_decimal.digits[1..num_digits]);
+ try out_stream.writeAll(float_decimal.digits[1..num_digits]);
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
- try output(context, "e");
+ try out_stream.writeAll("e");
const exp = float_decimal.exp - 1;
if (exp >= 0) {
- try output(context, "+");
+ try out_stream.writeAll("+");
if (exp > -10 and exp < 10) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
- try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
} else {
- try output(context, "-");
+ try out_stream.writeAll("-");
if (exp > -10 and exp < 10) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
- try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
}
}
@@ -731,36 +705,34 @@ pub fn formatFloatScientific(
pub fn formatFloatDecimal(
value: var,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
var x = @as(f64, value);
// Errol doesn't handle these special cases.
if (math.signbit(x)) {
- try output(context, "-");
+ try out_stream.writeAll("-");
x = -x;
}
if (math.isNan(x)) {
- return output(context, "nan");
+ return out_stream.writeAll("nan");
}
if (math.isPositiveInf(x)) {
- return output(context, "inf");
+ return out_stream.writeAll("inf");
}
if (x == 0.0) {
- try output(context, "0");
+ try out_stream.writeAll("0");
if (options.precision) |precision| {
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var i: usize = 0;
while (i < precision) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, ".0");
+ try out_stream.writeAll(".0");
}
}
@@ -782,14 +754,14 @@ pub fn formatFloatDecimal(
if (num_digits_whole > 0) {
// We may have to zero pad, for instance 1e4 requires zero padding.
- try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+ try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
var i = num_digits_whole_no_pad;
while (i < num_digits_whole) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
// {.0} special case doesn't want a trailing '.'
@@ -797,7 +769,7 @@ pub fn formatFloatDecimal(
return;
}
- try output(context, ".");
+ try out_stream.writeAll(".");
// Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
var printed: usize = 0;
@@ -809,7 +781,7 @@ pub fn formatFloatDecimal(
var i: usize = 0;
while (i < zeros_to_print) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
printed += 1;
}
@@ -821,14 +793,14 @@ pub fn formatFloatDecimal(
// Remaining fractional portion, zero-padding if insufficient.
assert(precision >= printed);
if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
- try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
return;
} else {
- try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
printed += float_decimal.digits.len - num_digits_whole_no_pad;
while (printed < precision) : (printed += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
@@ -840,14 +812,14 @@ pub fn formatFloatDecimal(
if (num_digits_whole > 0) {
// We may have to zero pad, for instance 1e4 requires zero padding.
- try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+ try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
var i = num_digits_whole_no_pad;
while (i < num_digits_whole) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
// Omit `.` if no fractional portion
@@ -855,7 +827,7 @@ pub fn formatFloatDecimal(
return;
}
- try output(context, ".");
+ try out_stream.writeAll(".");
// Zero-fill until we reach significant digits or run out of precision.
if (float_decimal.exp < 0) {
@@ -863,11 +835,11 @@ pub fn formatFloatDecimal(
var i: usize = 0;
while (i < zero_digit_count) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
- try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
}
}
@@ -875,12 +847,10 @@ pub fn formatBytes(
value: var,
options: FormatOptions,
comptime radix: usize,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (value == 0) {
- return output(context, "0B");
+ return out_stream.writeAll("0B");
}
const mags_si = " kMGTPEZY";
@@ -897,10 +867,10 @@ pub fn formatBytes(
else => unreachable,
};
- try formatFloatDecimal(new_value, options, context, Errors, output);
+ try formatFloatDecimal(new_value, options, out_stream);
if (suffix == ' ') {
- return output(context, "B");
+ return out_stream.writeAll("B");
}
const buf = switch (radix) {
@@ -908,7 +878,7 @@ pub fn formatBytes(
1024 => &[_]u8{ suffix, 'i', 'B' },
else => unreachable,
};
- return output(context, buf);
+ return out_stream.writeAll(buf);
}
pub fn formatInt(
@@ -916,10 +886,8 @@ pub fn formatInt(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
const int_value = if (@TypeOf(value) == comptime_int) blk: {
const Int = math.IntFittingRange(value, value);
break :blk @as(Int, value);
@@ -927,9 +895,9 @@ pub fn formatInt(
value;
if (@TypeOf(int_value).is_signed) {
- return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);
+ return formatIntSigned(int_value, base, uppercase, options, out_stream);
} else {
- return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);
+ return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
}
}
@@ -938,10 +906,8 @@ fn formatIntSigned(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
const new_options = FormatOptions{
.width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
.precision = options.precision,
@@ -950,15 +916,15 @@ fn formatIntSigned(
const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
const Uint = std.meta.IntType(false, bit_count);
if (value < 0) {
- try output(context, "-");
+ try out_stream.writeAll("-");
const new_value = math.absCast(value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
} else if (options.width == null or options.width.? == 0) {
- return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);
+ return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
} else {
- try output(context, "+");
+ try out_stream.writeAll("+");
const new_value = @intCast(Uint, value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
}
}
@@ -967,10 +933,8 @@ fn formatIntUnsigned(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
assert(base >= 2);
var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
@@ -994,16 +958,16 @@ fn formatIntUnsigned(
const zero_byte: u8 = options.fill;
var leftover_padding = padding - index;
while (true) {
- try output(context, @as(*const [1]u8, &zero_byte)[0..]);
+ try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
leftover_padding -= 1;
if (leftover_padding == 0) break;
}
mem.set(u8, buf[0..index], options.fill);
- return output(context, &buf);
+ return out_stream.writeAll(&buf);
} else {
const padded_buf = buf[index - padding ..];
mem.set(u8, padded_buf[0..padding], options.fill);
- return output(context, padded_buf);
+ return out_stream.writeAll(padded_buf);
}
}
@@ -1451,12 +1415,12 @@ test "custom" {
options: FormatOptions,
context: var,
comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
- ) Errors!void {
+ comptime output: fn (@TypeOf(context), []const u8) !void,
+ ) !void {
if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
- return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
} else if (comptime std.mem.eql(u8, fmt, "d")) {
- return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y });
+ return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
} else {
@compileError("Unknown format character: '" ++ fmt ++ "'");
}
@@ -1658,10 +1622,10 @@ test "formatType max_depth" {
options: FormatOptions,
context: var,
comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
- ) Errors!void {
+ comptime output: fn (@TypeOf(context), []const u8) !void,
+ ) !void {
if (fmt.len == 0) {
- return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
--
2.54.0
From e1e9ff9546d0898764ff9c9383e57d0fa4e9bd0e Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 12:02:33 -0600
Subject: [PATCH 075/111] Get formatIntBuf working
---
lib/std/fmtstream.zig | 1215 ++++++++++++++++++++---------------------
1 file changed, 602 insertions(+), 613 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index bb8d52d742e32aaf87b2e2246e882e292553ccf0..d64c6cdf7f51f9f684d92a1a82752ed03b41321e 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -972,20 +972,9 @@ fn formatIntUnsigned(
}
pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
- var context = FormatIntBuf{
- .out_buf = out_buf,
- .index = 0,
- };
- formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
- return context.index;
-}
-const FormatIntBuf = struct {
- out_buf: []u8,
- index: usize,
-};
-fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
- mem.copy(u8, context.out_buf[context.index..], bytes);
- context.index += bytes.len;
+ var fbs = std.io.fixedBufferStream(out_buf);
+ formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
+ return fbs.pos;
}
pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
@@ -1085,48 +1074,48 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
};
}
-const BufPrintContext = struct {
- remaining: []u8,
-};
+// const BufPrintContext = struct {
+// remaining: []u8,
+// };
-fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
- if (context.remaining.len < bytes.len) {
- mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
- return error.BufferTooSmall;
- }
- mem.copy(u8, context.remaining, bytes);
- context.remaining = context.remaining[bytes.len..];
-}
+// fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
+// if (context.remaining.len < bytes.len) {
+// mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
+// return error.BufferTooSmall;
+// }
+// mem.copy(u8, context.remaining, bytes);
+// context.remaining = context.remaining[bytes.len..];
+// }
-pub const BufPrintError = error{
- /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
- BufferTooSmall,
-};
-pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
- var context = BufPrintContext{ .remaining = buf };
- try format(&context, BufPrintError, bufPrintWrite, fmt, args);
- return buf[0 .. buf.len - context.remaining.len];
-}
+// pub const BufPrintError = error{
+// /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
+// BufferTooSmall,
+// };
+// pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
+// var context = BufPrintContext{ .remaining = buf };
+// try format(&context, BufPrintError, bufPrintWrite, fmt, args);
+// return buf[0 .. buf.len - context.remaining.len];
+// }
-pub const AllocPrintError = error{OutOfMemory};
+// pub const AllocPrintError = error{OutOfMemory};
-pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- var size: usize = 0;
- format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
- const buf = try allocator.alloc(u8, size);
- return bufPrint(buf, fmt, args) catch |err| switch (err) {
- error.BufferTooSmall => unreachable, // we just counted the size above
- };
-}
+// pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
+// var size: usize = 0;
+// format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
+// const buf = try allocator.alloc(u8, size);
+// return bufPrint(buf, fmt, args) catch |err| switch (err) {
+// error.BufferTooSmall => unreachable, // we just counted the size above
+// };
+// }
-fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
- size.* += bytes.len;
-}
+// fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
+// size.* += bytes.len;
+// }
-pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
- const result = try allocPrint(allocator, fmt ++ "\x00", args);
- return result[0 .. result.len - 1 :0];
-}
+// pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
+// const result = try allocPrint(allocator, fmt ++ "\x00", args);
+// return result[0 .. result.len - 1 :0];
+// }
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
@@ -1153,566 +1142,566 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
}
-test "parse u64 digit too big" {
- _ = parseUnsigned(u64, "123a", 10) catch |err| {
- if (err == error.InvalidCharacter) return;
- unreachable;
- };
- unreachable;
-}
-
-test "parse unsigned comptime" {
- comptime {
- std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
- }
-}
-
-test "optional" {
- {
- const value: ?i32 = 1234;
- try testFmt("optional: 1234\n", "optional: {}\n", .{value});
- }
- {
- const value: ?i32 = null;
- try testFmt("optional: null\n", "optional: {}\n", .{value});
- }
-}
-
-test "error" {
- {
- const value: anyerror!i32 = 1234;
- try testFmt("error union: 1234\n", "error union: {}\n", .{value});
- }
- {
- const value: anyerror!i32 = error.InvalidChar;
- try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
- }
-}
-
-test "int.small" {
- {
- const value: u3 = 0b101;
- try testFmt("u3: 5\n", "u3: {}\n", .{value});
- }
-}
-
-test "int.specifier" {
- {
- const value: u8 = 'a';
- try testFmt("u8: a\n", "u8: {c}\n", .{value});
- }
- {
- const value: u8 = 0b1100;
- try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
- }
-}
-
-test "int.padded" {
- try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
- try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
-}
-
-test "buffer" {
- {
- var buf1: [32]u8 = undefined;
- var context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- var res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1234"));
-
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "a"));
-
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1100"));
- }
-}
-
-test "array" {
- {
- const value: [3]u8 = "abc".*;
- try testFmt("array: abc\n", "array: {}\n", .{value});
- try testFmt("array: abc\n", "array: {}\n", .{&value});
-
- var buf: [100]u8 = undefined;
- try testFmt(
- try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
- "array: {*}\n",
- .{&value},
- );
- }
-}
-
-test "slice" {
- {
- const value: []const u8 = "abc";
- try testFmt("slice: abc\n", "slice: {}\n", .{value});
- }
- {
- const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
- try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
- }
-
- try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
- try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
-}
-
-test "pointer" {
- {
- const value = @intToPtr(*align(1) i32, 0xdeadbeef);
- try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
- try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
-}
-
-test "cstr" {
- try testFmt(
- "cstr: Test C\n",
- "cstr: {s}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
- try testFmt(
- "cstr: Test C \n",
- "cstr: {s:10}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
-}
-
-test "filesize" {
- try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
- try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
-}
-
-test "struct" {
- {
- const Struct = struct {
- field: u8,
- };
- const value = Struct{ .field = 42 };
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
- }
- {
- const Struct = struct {
- a: u0,
- b: u1,
- };
- const value = Struct{ .a = 0, .b = 1 };
- try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
- }
-}
-
-test "enum" {
- const Enum = enum {
- One,
- Two,
- };
- const value = Enum.Two;
- try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
- try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
-}
-
-test "non-exhaustive enum" {
- const Enum = enum(u16) {
- One = 0x000f,
- Two = 0xbeef,
- _,
- };
- try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
- try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
- try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
- try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
- try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
- try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
-}
-
-test "float.scientific" {
- try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
- try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
- try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
- try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.scientific.precision" {
- try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
- try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
- try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
- // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
- // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
- try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
-}
-
-test "float.special" {
- try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
- // negative nan is not defined by IEE 754,
- // and ARM thus normalizes it to positive nan
- if (builtin.arch != builtin.Arch.arm) {
- try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
- }
- try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
- try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
-}
-
-test "float.decimal" {
- try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
- try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
- try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
- try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
- // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
- // -11.12339... is rounded back up to -11.1234
- try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
- try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
- try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
- try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
- try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
- try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
- try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.libc.sanity" {
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
- try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
- try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
- try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
-
- // libc differences
- //
- // This is 0.015625 exactly according to gdb. We thus round down,
- // however glibc rounds up for some reason. This occurs for all
- // floats of the form x.yyyy25 on a precision point.
- try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
- // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
- // also rounds to 630 so I'm inclined to believe libc is not
- // optimal here.
- try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
-}
-
-test "custom" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) !void,
- ) !void {
- if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else if (comptime std.mem.eql(u8, fmt, "d")) {
- return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
- } else {
- @compileError("Unknown format character: '" ++ fmt ++ "'");
- }
- }
- };
-
- var buf1: [32]u8 = undefined;
- var value = Vec2{
- .x = 10.2,
- .y = 2.22,
- };
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
-
- // same thing but not passing a pointer
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
-}
-
-test "struct" {
- const S = struct {
- a: u32,
- b: anyerror,
- };
-
- const inst = S{
- .a = 456,
- .b = error.Unused,
- };
-
- try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
-}
-
-test "union" {
- const TU = union(enum) {
- float: f32,
- int: u32,
- };
-
- const UU = union {
- float: f32,
- int: u32,
- };
-
- const EU = extern union {
- float: f32,
- int: u32,
- };
-
- const tu_inst = TU{ .int = 123 };
- const uu_inst = UU{ .int = 456 };
- const eu_inst = EU{ .float = 321.123 };
-
- try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
-
- var buf: [100]u8 = undefined;
- const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
-
- const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
-}
-
-test "enum" {
- const E = enum {
- One,
- Two,
- Three,
- };
-
- const inst = E.Two;
-
- try testFmt("E.Two", "{}", .{inst});
-}
-
-test "struct.self-referential" {
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- };
-
- var inst = S{
- .a = null,
- };
- inst.a = &inst;
-
- try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
-}
-
-test "struct.zero-size" {
- const A = struct {
- fn foo() void {}
- };
- const B = struct {
- a: A,
- c: i32,
- };
-
- const a = A{};
- const b = B{ .a = a, .c = 0 };
-
- try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
-}
-
-test "bytes.hex" {
- const some_bytes = "\xCA\xFE\xBA\xBE";
- try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
- try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
- //Test Slices
- try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
- try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
- const bytes_with_zeros = "\x00\x0E\xBA\xBE";
- try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
-}
-
-fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
- var buf: [100]u8 = undefined;
- const result = try bufPrint(buf[0..], template, args);
- if (mem.eql(u8, result, expected)) return;
-
- std.debug.warn("\n====== expected this output: =========\n", .{});
- std.debug.warn("{}", .{expected});
- std.debug.warn("\n======== instead found this: =========\n", .{});
- std.debug.warn("{}", .{result});
- std.debug.warn("\n======================================\n", .{});
- return error.TestFailed;
-}
-
-pub fn trim(buf: []const u8) []const u8 {
- var start: usize = 0;
- while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
-
- var end: usize = buf.len;
- while (true) {
- if (end > start) {
- const new_end = end - 1;
- if (isWhiteSpace(buf[new_end])) {
- end = new_end;
- continue;
- }
- }
- break;
- }
- return buf[start..end];
-}
-
-test "trim" {
- std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
- std.testing.expect(mem.eql(u8, "", trim(" ")));
- std.testing.expect(mem.eql(u8, "", trim("")));
- std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
- std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
-}
-
-pub fn isWhiteSpace(byte: u8) bool {
- return switch (byte) {
- ' ', '\t', '\n', '\r' => true,
- else => false,
- };
-}
-
-pub fn hexToBytes(out: []u8, input: []const u8) !void {
- if (out.len * 2 < input.len)
- return error.InvalidLength;
-
- var in_i: usize = 0;
- while (in_i != input.len) : (in_i += 2) {
- const hi = try charToDigit(input[in_i], 16);
- const lo = try charToDigit(input[in_i + 1], 16);
- out[in_i / 2] = (hi << 4) | lo;
- }
-}
-
-test "hexToBytes" {
- const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
- var pb: [32]u8 = undefined;
- try hexToBytes(pb[0..], test_hex_str);
- try testFmt(test_hex_str, "{X}", .{pb});
-}
-
-test "formatIntValue with comptime_int" {
- const value: comptime_int = 123456789123456789;
-
- var buf = std.ArrayList(u8).init(std.testing.allocator);
- defer buf.deinit();
- try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
- std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
-}
-
-test "formatType max_depth" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) !void,
- ) !void {
- if (fmt.len == 0) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
- }
- };
- const E = enum {
- One,
- Two,
- Three,
- };
- const TU = union(enum) {
- const SelfType = @This();
- float: f32,
- int: u32,
- ptr: ?*SelfType,
- };
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- tu: TU,
- e: E,
- vec: Vec2,
- };
-
- var inst = S{
- .a = null,
- .tu = TU{ .ptr = null },
- .e = E.Two,
- .vec = Vec2{ .x = 10.2, .y = 2.22 },
- };
- inst.a = &inst;
- inst.tu.ptr = &inst.tu;
-
- var buf0 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf0.deinit();
- try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
- std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
-
- var buf1 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf1.deinit();
- try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
- std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- var buf2 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf2.deinit();
- try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
- std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- var buf3 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf3.deinit();
- try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
- std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
-}
-
-test "positional" {
- try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
- try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
- try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
-}
-
-test "positional with specifier" {
- try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
-}
-
-test "positional/alignment/width/precision" {
- try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
-}
-
-test "vector" {
- // https://github.com/ziglang/zig/issues/3317
- if (builtin.arch == .mipsel) return error.SkipZigTest;
-
- const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
- const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
- const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
-
- try testFmt("{ true, false, true, false }", "{}", .{vbool});
- try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
- try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
- try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
- try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
- try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
- try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
-}
-
-test "enum-literal" {
- try testFmt(".hello_world", "{}", .{.hello_world});
-}
+// test "parse u64 digit too big" {
+// _ = parseUnsigned(u64, "123a", 10) catch |err| {
+// if (err == error.InvalidCharacter) return;
+// unreachable;
+// };
+// unreachable;
+// }
+
+// test "parse unsigned comptime" {
+// comptime {
+// std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
+// }
+// }
+
+// test "optional" {
+// {
+// const value: ?i32 = 1234;
+// try testFmt("optional: 1234\n", "optional: {}\n", .{value});
+// }
+// {
+// const value: ?i32 = null;
+// try testFmt("optional: null\n", "optional: {}\n", .{value});
+// }
+// }
+
+// test "error" {
+// {
+// const value: anyerror!i32 = 1234;
+// try testFmt("error union: 1234\n", "error union: {}\n", .{value});
+// }
+// {
+// const value: anyerror!i32 = error.InvalidChar;
+// try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
+// }
+// }
+
+// test "int.small" {
+// {
+// const value: u3 = 0b101;
+// try testFmt("u3: 5\n", "u3: {}\n", .{value});
+// }
+// }
+
+// test "int.specifier" {
+// {
+// const value: u8 = 'a';
+// try testFmt("u8: a\n", "u8: {c}\n", .{value});
+// }
+// {
+// const value: u8 = 0b1100;
+// try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
+// }
+// }
+
+// test "int.padded" {
+// try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
+// try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
+// }
+
+// test "buffer" {
+// {
+// var buf1: [32]u8 = undefined;
+// var context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// var res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "1234"));
+
+// context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "a"));
+
+// context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "1100"));
+// }
+// }
+
+// test "array" {
+// {
+// const value: [3]u8 = "abc".*;
+// try testFmt("array: abc\n", "array: {}\n", .{value});
+// try testFmt("array: abc\n", "array: {}\n", .{&value});
+
+// var buf: [100]u8 = undefined;
+// try testFmt(
+// try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
+// "array: {*}\n",
+// .{&value},
+// );
+// }
+// }
+
+// test "slice" {
+// {
+// const value: []const u8 = "abc";
+// try testFmt("slice: abc\n", "slice: {}\n", .{value});
+// }
+// {
+// const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
+// try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
+// }
+
+// try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
+// try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
+// }
+
+// test "pointer" {
+// {
+// const value = @intToPtr(*align(1) i32, 0xdeadbeef);
+// try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
+// try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
+// }
+// {
+// const value = @intToPtr(fn () void, 0xdeadbeef);
+// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+// }
+// {
+// const value = @intToPtr(fn () void, 0xdeadbeef);
+// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+// }
+// }
+
+// test "cstr" {
+// try testFmt(
+// "cstr: Test C\n",
+// "cstr: {s}\n",
+// .{@ptrCast([*c]const u8, "Test C")},
+// );
+// try testFmt(
+// "cstr: Test C \n",
+// "cstr: {s:10}\n",
+// .{@ptrCast([*c]const u8, "Test C")},
+// );
+// }
+
+// test "filesize" {
+// try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
+// try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
+// }
+
+// test "struct" {
+// {
+// const Struct = struct {
+// field: u8,
+// };
+// const value = Struct{ .field = 42 };
+// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
+// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
+// }
+// {
+// const Struct = struct {
+// a: u0,
+// b: u1,
+// };
+// const value = Struct{ .a = 0, .b = 1 };
+// try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
+// }
+// }
+
+// test "enum" {
+// const Enum = enum {
+// One,
+// Two,
+// };
+// const value = Enum.Two;
+// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
+// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
+// }
+
+// test "non-exhaustive enum" {
+// const Enum = enum(u16) {
+// One = 0x000f,
+// Two = 0xbeef,
+// _,
+// };
+// try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
+// try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
+// try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
+// try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
+// try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
+// try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
+// }
+
+// test "float.scientific" {
+// try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
+// try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
+// try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
+// try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
+// }
+
+// test "float.scientific.precision" {
+// try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
+// try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
+// try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
+// // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
+// // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
+// try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
+// }
+
+// test "float.special" {
+// try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
+// // negative nan is not defined by IEE 754,
+// // and ARM thus normalizes it to positive nan
+// if (builtin.arch != builtin.Arch.arm) {
+// try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
+// }
+// try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
+// try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
+// }
+
+// test "float.decimal" {
+// try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
+// try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
+// try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
+// try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
+// // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
+// // -11.12339... is rounded back up to -11.1234
+// try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
+// try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
+// try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
+// try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
+// try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
+// try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
+// try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
+// }
+
+// test "float.libc.sanity" {
+// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
+// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
+// try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
+// try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
+// try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
+
+// // libc differences
+// //
+// // This is 0.015625 exactly according to gdb. We thus round down,
+// // however glibc rounds up for some reason. This occurs for all
+// // floats of the form x.yyyy25 on a precision point.
+// try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
+// // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
+// // also rounds to 630 so I'm inclined to believe libc is not
+// // optimal here.
+// try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
+// }
+
+// test "custom" {
+// const Vec2 = struct {
+// const SelfType = @This();
+// x: f32,
+// y: f32,
+
+// pub fn format(
+// self: SelfType,
+// comptime fmt: []const u8,
+// options: FormatOptions,
+// context: var,
+// comptime Errors: type,
+// comptime output: fn (@TypeOf(context), []const u8) !void,
+// ) !void {
+// if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
+// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+// } else if (comptime std.mem.eql(u8, fmt, "d")) {
+// return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
+// } else {
+// @compileError("Unknown format character: '" ++ fmt ++ "'");
+// }
+// }
+// };
+
+// var buf1: [32]u8 = undefined;
+// var value = Vec2{
+// .x = 10.2,
+// .y = 2.22,
+// };
+// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
+// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
+
+// // same thing but not passing a pointer
+// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
+// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
+// }
+
+// test "struct" {
+// const S = struct {
+// a: u32,
+// b: anyerror,
+// };
+
+// const inst = S{
+// .a = 456,
+// .b = error.Unused,
+// };
+
+// try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
+// }
+
+// test "union" {
+// const TU = union(enum) {
+// float: f32,
+// int: u32,
+// };
+
+// const UU = union {
+// float: f32,
+// int: u32,
+// };
+
+// const EU = extern union {
+// float: f32,
+// int: u32,
+// };
+
+// const tu_inst = TU{ .int = 123 };
+// const uu_inst = UU{ .int = 456 };
+// const eu_inst = EU{ .float = 321.123 };
+
+// try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
+
+// var buf: [100]u8 = undefined;
+// const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
+// std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
+
+// const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
+// std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
+// }
+
+// test "enum" {
+// const E = enum {
+// One,
+// Two,
+// Three,
+// };
+
+// const inst = E.Two;
+
+// try testFmt("E.Two", "{}", .{inst});
+// }
+
+// test "struct.self-referential" {
+// const S = struct {
+// const SelfType = @This();
+// a: ?*SelfType,
+// };
+
+// var inst = S{
+// .a = null,
+// };
+// inst.a = &inst;
+
+// try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
+// }
+
+// test "struct.zero-size" {
+// const A = struct {
+// fn foo() void {}
+// };
+// const B = struct {
+// a: A,
+// c: i32,
+// };
+
+// const a = A{};
+// const b = B{ .a = a, .c = 0 };
+
+// try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
+// }
+
+// test "bytes.hex" {
+// const some_bytes = "\xCA\xFE\xBA\xBE";
+// try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
+// try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
+// //Test Slices
+// try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
+// try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
+// const bytes_with_zeros = "\x00\x0E\xBA\xBE";
+// try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
+// }
+
+// fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
+// var buf: [100]u8 = undefined;
+// const result = try bufPrint(buf[0..], template, args);
+// if (mem.eql(u8, result, expected)) return;
+
+// std.debug.warn("\n====== expected this output: =========\n", .{});
+// std.debug.warn("{}", .{expected});
+// std.debug.warn("\n======== instead found this: =========\n", .{});
+// std.debug.warn("{}", .{result});
+// std.debug.warn("\n======================================\n", .{});
+// return error.TestFailed;
+// }
+
+// pub fn trim(buf: []const u8) []const u8 {
+// var start: usize = 0;
+// while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
+
+// var end: usize = buf.len;
+// while (true) {
+// if (end > start) {
+// const new_end = end - 1;
+// if (isWhiteSpace(buf[new_end])) {
+// end = new_end;
+// continue;
+// }
+// }
+// break;
+// }
+// return buf[start..end];
+// }
+
+// test "trim" {
+// std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
+// std.testing.expect(mem.eql(u8, "", trim(" ")));
+// std.testing.expect(mem.eql(u8, "", trim("")));
+// std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
+// std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
+// }
+
+// pub fn isWhiteSpace(byte: u8) bool {
+// return switch (byte) {
+// ' ', '\t', '\n', '\r' => true,
+// else => false,
+// };
+// }
+
+// pub fn hexToBytes(out: []u8, input: []const u8) !void {
+// if (out.len * 2 < input.len)
+// return error.InvalidLength;
+
+// var in_i: usize = 0;
+// while (in_i != input.len) : (in_i += 2) {
+// const hi = try charToDigit(input[in_i], 16);
+// const lo = try charToDigit(input[in_i + 1], 16);
+// out[in_i / 2] = (hi << 4) | lo;
+// }
+// }
+
+// test "hexToBytes" {
+// const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
+// var pb: [32]u8 = undefined;
+// try hexToBytes(pb[0..], test_hex_str);
+// try testFmt(test_hex_str, "{X}", .{pb});
+// }
+
+// test "formatIntValue with comptime_int" {
+// const value: comptime_int = 123456789123456789;
+
+// var buf = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf.deinit();
+// try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
+// std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
+// }
+
+// test "formatType max_depth" {
+// const Vec2 = struct {
+// const SelfType = @This();
+// x: f32,
+// y: f32,
+
+// pub fn format(
+// self: SelfType,
+// comptime fmt: []const u8,
+// options: FormatOptions,
+// context: var,
+// comptime Errors: type,
+// comptime output: fn (@TypeOf(context), []const u8) !void,
+// ) !void {
+// if (fmt.len == 0) {
+// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+// } else {
+// @compileError("Unknown format string: '" ++ fmt ++ "'");
+// }
+// }
+// };
+// const E = enum {
+// One,
+// Two,
+// Three,
+// };
+// const TU = union(enum) {
+// const SelfType = @This();
+// float: f32,
+// int: u32,
+// ptr: ?*SelfType,
+// };
+// const S = struct {
+// const SelfType = @This();
+// a: ?*SelfType,
+// tu: TU,
+// e: E,
+// vec: Vec2,
+// };
+
+// var inst = S{
+// .a = null,
+// .tu = TU{ .ptr = null },
+// .e = E.Two,
+// .vec = Vec2{ .x = 10.2, .y = 2.22 },
+// };
+// inst.a = &inst;
+// inst.tu.ptr = &inst.tu;
+
+// var buf0 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf0.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
+// std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+
+// var buf1 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf1.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
+// std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+// var buf2 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf2.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
+// std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+// var buf3 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf3.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
+// std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+// }
+
+// test "positional" {
+// try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+// try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+// try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
+// try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
+// try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
+// }
+
+// test "positional with specifier" {
+// try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
+// }
+
+// test "positional/alignment/width/precision" {
+// try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
+// }
+
+// test "vector" {
+// // https://github.com/ziglang/zig/issues/3317
+// if (builtin.arch == .mipsel) return error.SkipZigTest;
+
+// const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
+// const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
+// const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
+
+// try testFmt("{ true, false, true, false }", "{}", .{vbool});
+// try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
+// try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
+// try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
+// try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
+// try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
+// try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
+// }
+
+// test "enum-literal" {
+// try testFmt(".hello_world", "{}", .{.hello_world});
+// }
--
2.54.0
From 8241b96f78fa8ee33f9a73d4d296509d49b6f351 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 12:25:12 -0600
Subject: [PATCH 076/111] Re-enable testFmt
---
lib/std/fmtstream.zig | 75 ++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 43 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index d64c6cdf7f51f9f684d92a1a82752ed03b41321e..4a7d8041c0296e2b7dd8061b5b1f4a0d7bd54b5e 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -1074,28 +1074,17 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
};
}
-// const BufPrintContext = struct {
-// remaining: []u8,
-// };
-
-// fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
-// if (context.remaining.len < bytes.len) {
-// mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
-// return error.BufferTooSmall;
-// }
-// mem.copy(u8, context.remaining, bytes);
-// context.remaining = context.remaining[bytes.len..];
-// }
-
-// pub const BufPrintError = error{
-// /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
-// BufferTooSmall,
-// };
-// pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
-// var context = BufPrintContext{ .remaining = buf };
-// try format(&context, BufPrintError, bufPrintWrite, fmt, args);
-// return buf[0 .. buf.len - context.remaining.len];
-// }
+pub const BufPrintError = error{
+ /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
+ BufferTooSmall,
+};
+pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
+ var os = std.io.SliceOutStream.init(buf);
+ format(&os.stream, fmt, args) catch |err| switch (err) {
+ error.OutOfMemory => return error.BufferTooSmall,
+ };
+ return buf[0..os.pos];
+}
// pub const AllocPrintError = error{OutOfMemory};
@@ -1514,29 +1503,29 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
// try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
// }
-// test "bytes.hex" {
-// const some_bytes = "\xCA\xFE\xBA\xBE";
-// try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
-// try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
-// //Test Slices
-// try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
-// try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
-// const bytes_with_zeros = "\x00\x0E\xBA\xBE";
-// try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
-// }
+test "bytes.hex" {
+ const some_bytes = "\xCA\xFE\xBA\xBE";
+ try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
+ try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
+ //Test Slices
+ try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
+ try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
+ const bytes_with_zeros = "\x00\x0E\xBA\xBE";
+ try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
+}
-// fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
-// var buf: [100]u8 = undefined;
-// const result = try bufPrint(buf[0..], template, args);
-// if (mem.eql(u8, result, expected)) return;
+fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
+ var buf: [100]u8 = undefined;
+ const result = try bufPrint(buf[0..], template, args);
+ if (mem.eql(u8, result, expected)) return;
-// std.debug.warn("\n====== expected this output: =========\n", .{});
-// std.debug.warn("{}", .{expected});
-// std.debug.warn("\n======== instead found this: =========\n", .{});
-// std.debug.warn("{}", .{result});
-// std.debug.warn("\n======================================\n", .{});
-// return error.TestFailed;
-// }
+ std.debug.warn("\n====== expected this output: =========\n", .{});
+ std.debug.warn("{}", .{expected});
+ std.debug.warn("\n======== instead found this: =========\n", .{});
+ std.debug.warn("{}", .{result});
+ std.debug.warn("\n======================================\n", .{});
+ return error.TestFailed;
+}
// pub fn trim(buf: []const u8) []const u8 {
// var start: usize = 0;
--
2.54.0
From 78d12762a9c78f9563a3cfd29541d0a04f78ab58 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 13:22:27 -0600
Subject: [PATCH 077/111] Re-enable a bunch of tests
---
lib/std/fmtstream.zig | 898 +++++++++++++++++++++---------------------
1 file changed, 448 insertions(+), 450 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index 4a7d8041c0296e2b7dd8061b5b1f4a0d7bd54b5e..3a2767c85ab327516b740975948a62cb4bcd27d8 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -430,7 +430,7 @@ pub fn formatType(
},
.Many, .C => {
if (ptr_info.sentinel) |sentinel| {
- return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);
+ return formatType(mem.span(value), fmt, options, out_stream, max_depth);
}
if (ptr_info.child == u8) {
if (fmt.len > 0 and fmt[0] == 's') {
@@ -481,7 +481,7 @@ pub fn formatType(
.Type => return out_stream.writeAll(@typeName(T)),
.EnumLiteral => {
const buffer = [_]u8{'.'} ++ @tagName(value);
- return formatType(buffer, fmt, options, context, Errors, output, max_depth);
+ return formatType(buffer, fmt, options, out_stream, max_depth);
},
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
}
@@ -1079,11 +1079,11 @@ pub const BufPrintError = error{
BufferTooSmall,
};
pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
- var os = std.io.SliceOutStream.init(buf);
- format(&os.stream, fmt, args) catch |err| switch (err) {
- error.OutOfMemory => return error.BufferTooSmall,
+ var fbs = std.io.fixedBufferStream(buf);
+ format(fbs.outStream(), fmt, args) catch |err| switch (err) {
+ error.NoSpaceLeft => return error.BufferTooSmall,
};
- return buf[0..os.pos];
+ return buf[0..fbs.pos];
}
// pub const AllocPrintError = error{OutOfMemory};
@@ -1131,348 +1131,346 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
}
-// test "parse u64 digit too big" {
-// _ = parseUnsigned(u64, "123a", 10) catch |err| {
-// if (err == error.InvalidCharacter) return;
-// unreachable;
-// };
-// unreachable;
-// }
-
-// test "parse unsigned comptime" {
-// comptime {
-// std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
-// }
-// }
-
-// test "optional" {
-// {
-// const value: ?i32 = 1234;
-// try testFmt("optional: 1234\n", "optional: {}\n", .{value});
-// }
-// {
-// const value: ?i32 = null;
-// try testFmt("optional: null\n", "optional: {}\n", .{value});
-// }
-// }
-
-// test "error" {
-// {
-// const value: anyerror!i32 = 1234;
-// try testFmt("error union: 1234\n", "error union: {}\n", .{value});
-// }
-// {
-// const value: anyerror!i32 = error.InvalidChar;
-// try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
-// }
-// }
-
-// test "int.small" {
-// {
-// const value: u3 = 0b101;
-// try testFmt("u3: 5\n", "u3: {}\n", .{value});
-// }
-// }
-
-// test "int.specifier" {
-// {
-// const value: u8 = 'a';
-// try testFmt("u8: a\n", "u8: {c}\n", .{value});
-// }
-// {
-// const value: u8 = 0b1100;
-// try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
-// }
-// }
-
-// test "int.padded" {
-// try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
-// try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
-// }
-
-// test "buffer" {
-// {
-// var buf1: [32]u8 = undefined;
-// var context = BufPrintContext{ .remaining = buf1[0..] };
-// try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
-// var res = buf1[0 .. buf1.len - context.remaining.len];
-// std.testing.expect(mem.eql(u8, res, "1234"));
-
-// context = BufPrintContext{ .remaining = buf1[0..] };
-// try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
-// res = buf1[0 .. buf1.len - context.remaining.len];
-// std.testing.expect(mem.eql(u8, res, "a"));
-
-// context = BufPrintContext{ .remaining = buf1[0..] };
-// try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
-// res = buf1[0 .. buf1.len - context.remaining.len];
-// std.testing.expect(mem.eql(u8, res, "1100"));
-// }
-// }
-
-// test "array" {
-// {
-// const value: [3]u8 = "abc".*;
-// try testFmt("array: abc\n", "array: {}\n", .{value});
-// try testFmt("array: abc\n", "array: {}\n", .{&value});
-
-// var buf: [100]u8 = undefined;
-// try testFmt(
-// try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
-// "array: {*}\n",
-// .{&value},
-// );
-// }
-// }
-
-// test "slice" {
-// {
-// const value: []const u8 = "abc";
-// try testFmt("slice: abc\n", "slice: {}\n", .{value});
-// }
-// {
-// const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
-// try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
-// }
-
-// try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
-// try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
-// }
-
-// test "pointer" {
-// {
-// const value = @intToPtr(*align(1) i32, 0xdeadbeef);
-// try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
-// try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
-// }
-// {
-// const value = @intToPtr(fn () void, 0xdeadbeef);
-// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
-// }
-// {
-// const value = @intToPtr(fn () void, 0xdeadbeef);
-// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
-// }
-// }
-
-// test "cstr" {
-// try testFmt(
-// "cstr: Test C\n",
-// "cstr: {s}\n",
-// .{@ptrCast([*c]const u8, "Test C")},
-// );
-// try testFmt(
-// "cstr: Test C \n",
-// "cstr: {s:10}\n",
-// .{@ptrCast([*c]const u8, "Test C")},
-// );
-// }
-
-// test "filesize" {
-// try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
-// try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
-// }
-
-// test "struct" {
-// {
-// const Struct = struct {
-// field: u8,
-// };
-// const value = Struct{ .field = 42 };
-// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
-// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
-// }
-// {
-// const Struct = struct {
-// a: u0,
-// b: u1,
-// };
-// const value = Struct{ .a = 0, .b = 1 };
-// try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
-// }
-// }
-
-// test "enum" {
-// const Enum = enum {
-// One,
-// Two,
-// };
-// const value = Enum.Two;
-// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
-// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
-// }
-
-// test "non-exhaustive enum" {
-// const Enum = enum(u16) {
-// One = 0x000f,
-// Two = 0xbeef,
-// _,
-// };
-// try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
-// try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
-// try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
-// try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
-// try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
-// try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
-// }
-
-// test "float.scientific" {
-// try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
-// try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
-// try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
-// try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
-// }
-
-// test "float.scientific.precision" {
-// try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
-// try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
-// try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
-// // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
-// // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
-// try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
-// }
-
-// test "float.special" {
-// try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
-// // negative nan is not defined by IEE 754,
-// // and ARM thus normalizes it to positive nan
-// if (builtin.arch != builtin.Arch.arm) {
-// try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
-// }
-// try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
-// try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
-// }
-
-// test "float.decimal" {
-// try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
-// try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
-// try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
-// try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
-// // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
-// // -11.12339... is rounded back up to -11.1234
-// try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
-// try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
-// try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
-// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
-// try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
-// try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
-// try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
-// try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
-// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
-// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
-// }
-
-// test "float.libc.sanity" {
-// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
-// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
-// try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
-// try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
-// try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
-
-// // libc differences
-// //
-// // This is 0.015625 exactly according to gdb. We thus round down,
-// // however glibc rounds up for some reason. This occurs for all
-// // floats of the form x.yyyy25 on a precision point.
-// try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
-// // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
-// // also rounds to 630 so I'm inclined to believe libc is not
-// // optimal here.
-// try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
-// }
-
-// test "custom" {
-// const Vec2 = struct {
-// const SelfType = @This();
-// x: f32,
-// y: f32,
-
-// pub fn format(
-// self: SelfType,
-// comptime fmt: []const u8,
-// options: FormatOptions,
-// context: var,
-// comptime Errors: type,
-// comptime output: fn (@TypeOf(context), []const u8) !void,
-// ) !void {
-// if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
-// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
-// } else if (comptime std.mem.eql(u8, fmt, "d")) {
-// return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
-// } else {
-// @compileError("Unknown format character: '" ++ fmt ++ "'");
-// }
-// }
-// };
-
-// var buf1: [32]u8 = undefined;
-// var value = Vec2{
-// .x = 10.2,
-// .y = 2.22,
-// };
-// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
-// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
-
-// // same thing but not passing a pointer
-// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
-// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
-// }
-
-// test "struct" {
-// const S = struct {
-// a: u32,
-// b: anyerror,
-// };
-
-// const inst = S{
-// .a = 456,
-// .b = error.Unused,
-// };
-
-// try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
-// }
-
-// test "union" {
-// const TU = union(enum) {
-// float: f32,
-// int: u32,
-// };
-
-// const UU = union {
-// float: f32,
-// int: u32,
-// };
-
-// const EU = extern union {
-// float: f32,
-// int: u32,
-// };
-
-// const tu_inst = TU{ .int = 123 };
-// const uu_inst = UU{ .int = 456 };
-// const eu_inst = EU{ .float = 321.123 };
-
-// try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
-
-// var buf: [100]u8 = undefined;
-// const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
-// std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
-
-// const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
-// std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
-// }
-
-// test "enum" {
-// const E = enum {
-// One,
-// Two,
-// Three,
-// };
-
-// const inst = E.Two;
-
-// try testFmt("E.Two", "{}", .{inst});
-// }
+test "parse u64 digit too big" {
+ _ = parseUnsigned(u64, "123a", 10) catch |err| {
+ if (err == error.InvalidCharacter) return;
+ unreachable;
+ };
+ unreachable;
+}
+
+test "parse unsigned comptime" {
+ comptime {
+ std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
+ }
+}
+
+test "optional" {
+ {
+ const value: ?i32 = 1234;
+ try testFmt("optional: 1234\n", "optional: {}\n", .{value});
+ }
+ {
+ const value: ?i32 = null;
+ try testFmt("optional: null\n", "optional: {}\n", .{value});
+ }
+}
+
+test "error" {
+ {
+ const value: anyerror!i32 = 1234;
+ try testFmt("error union: 1234\n", "error union: {}\n", .{value});
+ }
+ {
+ const value: anyerror!i32 = error.InvalidChar;
+ try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
+ }
+}
+
+test "int.small" {
+ {
+ const value: u3 = 0b101;
+ try testFmt("u3: 5\n", "u3: {}\n", .{value});
+ }
+}
+
+test "int.specifier" {
+ {
+ const value: u8 = 'a';
+ try testFmt("u8: a\n", "u8: {c}\n", .{value});
+ }
+ {
+ const value: u8 = 0b1100;
+ try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
+ }
+}
+
+test "int.padded" {
+ try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
+ try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
+}
+
+test "buffer" {
+ {
+ var buf1: [32]u8 = undefined;
+ var fbs = std.io.fixedBufferStream(&buf1);
+ try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
+ var res = buf1[0..fbs.pos];
+ std.testing.expect(mem.eql(u8, res, "1234"));
+
+ try fbs.seekTo(0);
+ try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
+ res = buf1[0..fbs.pos];
+ std.testing.expect(mem.eql(u8, res, "a"));
+
+ try fbs.seekTo(0);
+ try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
+ res = buf1[0..fbs.pos];
+ std.testing.expect(mem.eql(u8, res, "1100"));
+ }
+}
+
+test "array" {
+ {
+ const value: [3]u8 = "abc".*;
+ try testFmt("array: abc\n", "array: {}\n", .{value});
+ try testFmt("array: abc\n", "array: {}\n", .{&value});
+
+ var buf: [100]u8 = undefined;
+ try testFmt(
+ try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
+ "array: {*}\n",
+ .{&value},
+ );
+ }
+}
+
+test "slice" {
+ {
+ const value: []const u8 = "abc";
+ try testFmt("slice: abc\n", "slice: {}\n", .{value});
+ }
+ {
+ const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
+ try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
+ }
+
+ try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
+ try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
+}
+
+test "pointer" {
+ {
+ const value = @intToPtr(*align(1) i32, 0xdeadbeef);
+ try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
+ try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+ }
+}
+
+test "cstr" {
+ try testFmt(
+ "cstr: Test C\n",
+ "cstr: {s}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
+ try testFmt(
+ "cstr: Test C \n",
+ "cstr: {s:10}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
+}
+
+test "filesize" {
+ try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
+ try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
+}
+
+test "struct" {
+ {
+ const Struct = struct {
+ field: u8,
+ };
+ const value = Struct{ .field = 42 };
+ try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
+ try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
+ }
+ {
+ const Struct = struct {
+ a: u0,
+ b: u1,
+ };
+ const value = Struct{ .a = 0, .b = 1 };
+ try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
+ }
+}
+
+test "enum" {
+ const Enum = enum {
+ One,
+ Two,
+ };
+ const value = Enum.Two;
+ try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
+ try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
+}
+
+test "non-exhaustive enum" {
+ const Enum = enum(u16) {
+ One = 0x000f,
+ Two = 0xbeef,
+ _,
+ };
+ try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
+ try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
+ try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
+ try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
+ try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
+ try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
+}
+
+test "float.scientific" {
+ try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
+ try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
+ try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
+ try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
+}
+
+test "float.scientific.precision" {
+ try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
+ try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
+ try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
+ // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
+ // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
+ try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
+}
+
+test "float.special" {
+ try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
+ // negative nan is not defined by IEE 754,
+ // and ARM thus normalizes it to positive nan
+ if (builtin.arch != builtin.Arch.arm) {
+ try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
+ }
+ try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
+ try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
+}
+
+test "float.decimal" {
+ try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
+ try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
+ try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
+ try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
+ // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
+ // -11.12339... is rounded back up to -11.1234
+ try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
+ try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
+ try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
+ try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
+ try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
+ try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
+ try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
+ try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
+}
+
+test "float.libc.sanity" {
+ try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
+ try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
+ try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
+ try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
+ try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
+
+ // libc differences
+ //
+ // This is 0.015625 exactly according to gdb. We thus round down,
+ // however glibc rounds up for some reason. This occurs for all
+ // floats of the form x.yyyy25 on a precision point.
+ try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
+ // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
+ // also rounds to 630 so I'm inclined to believe libc is not
+ // optimal here.
+ try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
+}
+
+test "custom" {
+ const Vec2 = struct {
+ const SelfType = @This();
+ x: f32,
+ y: f32,
+
+ pub fn format(
+ self: SelfType,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ out_stream: var,
+ ) !void {
+ if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
+ return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+ } else if (comptime std.mem.eql(u8, fmt, "d")) {
+ return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
+ } else {
+ @compileError("Unknown format character: '" ++ fmt ++ "'");
+ }
+ }
+ };
+
+ var buf1: [32]u8 = undefined;
+ var value = Vec2{
+ .x = 10.2,
+ .y = 2.22,
+ };
+ try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
+ try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
+
+ // same thing but not passing a pointer
+ try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
+ try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
+}
+
+test "struct" {
+ const S = struct {
+ a: u32,
+ b: anyerror,
+ };
+
+ const inst = S{
+ .a = 456,
+ .b = error.Unused,
+ };
+
+ try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
+}
+
+test "union" {
+ const TU = union(enum) {
+ float: f32,
+ int: u32,
+ };
+
+ const UU = union {
+ float: f32,
+ int: u32,
+ };
+
+ const EU = extern union {
+ float: f32,
+ int: u32,
+ };
+
+ const tu_inst = TU{ .int = 123 };
+ const uu_inst = UU{ .int = 456 };
+ const eu_inst = EU{ .float = 321.123 };
+
+ try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
+
+ var buf: [100]u8 = undefined;
+ const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
+ std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
+
+ const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
+ std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
+}
+
+test "enum" {
+ const E = enum {
+ One,
+ Two,
+ Three,
+ };
+
+ const inst = E.Two;
+
+ try testFmt("E.Two", "{}", .{inst});
+}
// test "struct.self-referential" {
// const S = struct {
@@ -1488,20 +1486,20 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
// try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
// }
-// test "struct.zero-size" {
-// const A = struct {
-// fn foo() void {}
-// };
-// const B = struct {
-// a: A,
-// c: i32,
-// };
+test "struct.zero-size" {
+ const A = struct {
+ fn foo() void {}
+ };
+ const B = struct {
+ a: A,
+ c: i32,
+ };
-// const a = A{};
-// const b = B{ .a = a, .c = 0 };
+ const a = A{};
+ const b = B{ .a = a, .c = 0 };
-// try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
-// }
+ try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
+}
test "bytes.hex" {
const some_bytes = "\xCA\xFE\xBA\xBE";
@@ -1527,66 +1525,66 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void
return error.TestFailed;
}
-// pub fn trim(buf: []const u8) []const u8 {
-// var start: usize = 0;
-// while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
-
-// var end: usize = buf.len;
-// while (true) {
-// if (end > start) {
-// const new_end = end - 1;
-// if (isWhiteSpace(buf[new_end])) {
-// end = new_end;
-// continue;
-// }
-// }
-// break;
-// }
-// return buf[start..end];
-// }
-
-// test "trim" {
-// std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
-// std.testing.expect(mem.eql(u8, "", trim(" ")));
-// std.testing.expect(mem.eql(u8, "", trim("")));
-// std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
-// std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
-// }
-
-// pub fn isWhiteSpace(byte: u8) bool {
-// return switch (byte) {
-// ' ', '\t', '\n', '\r' => true,
-// else => false,
-// };
-// }
-
-// pub fn hexToBytes(out: []u8, input: []const u8) !void {
-// if (out.len * 2 < input.len)
-// return error.InvalidLength;
-
-// var in_i: usize = 0;
-// while (in_i != input.len) : (in_i += 2) {
-// const hi = try charToDigit(input[in_i], 16);
-// const lo = try charToDigit(input[in_i + 1], 16);
-// out[in_i / 2] = (hi << 4) | lo;
-// }
-// }
-
-// test "hexToBytes" {
-// const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
-// var pb: [32]u8 = undefined;
-// try hexToBytes(pb[0..], test_hex_str);
-// try testFmt(test_hex_str, "{X}", .{pb});
-// }
-
-// test "formatIntValue with comptime_int" {
-// const value: comptime_int = 123456789123456789;
-
-// var buf = std.ArrayList(u8).init(std.testing.allocator);
-// defer buf.deinit();
-// try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
-// std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
-// }
+pub fn trim(buf: []const u8) []const u8 {
+ var start: usize = 0;
+ while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
+
+ var end: usize = buf.len;
+ while (true) {
+ if (end > start) {
+ const new_end = end - 1;
+ if (isWhiteSpace(buf[new_end])) {
+ end = new_end;
+ continue;
+ }
+ }
+ break;
+ }
+ return buf[start..end];
+}
+
+test "trim" {
+ std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
+ std.testing.expect(mem.eql(u8, "", trim(" ")));
+ std.testing.expect(mem.eql(u8, "", trim("")));
+ std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
+ std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
+}
+
+pub fn isWhiteSpace(byte: u8) bool {
+ return switch (byte) {
+ ' ', '\t', '\n', '\r' => true,
+ else => false,
+ };
+}
+
+pub fn hexToBytes(out: []u8, input: []const u8) !void {
+ if (out.len * 2 < input.len)
+ return error.InvalidLength;
+
+ var in_i: usize = 0;
+ while (in_i != input.len) : (in_i += 2) {
+ const hi = try charToDigit(input[in_i], 16);
+ const lo = try charToDigit(input[in_i + 1], 16);
+ out[in_i / 2] = (hi << 4) | lo;
+ }
+}
+
+test "hexToBytes" {
+ const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
+ var pb: [32]u8 = undefined;
+ try hexToBytes(pb[0..], test_hex_str);
+ try testFmt(test_hex_str, "{X}", .{pb});
+}
+
+test "formatIntValue with comptime_int" {
+ const value: comptime_int = 123456789123456789;
+
+ var buf: [20]u8 = undefined;
+ var fbs = std.io.fixedBufferStream(&buf);
+ try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
+ std.testing.expect(mem.eql(u8, buf[0..fbs.pos], "123456789123456789"));
+}
// test "formatType max_depth" {
// const Vec2 = struct {
@@ -1658,39 +1656,39 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void
// std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
// }
-// test "positional" {
-// try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
-// try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
-// try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
-// try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
-// try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
-// }
+test "positional" {
+ try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+ try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+ try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
+ try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
+ try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
+}
-// test "positional with specifier" {
-// try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
-// }
+test "positional with specifier" {
+ try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
+}
-// test "positional/alignment/width/precision" {
-// try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
-// }
+test "positional/alignment/width/precision" {
+ try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
+}
-// test "vector" {
-// // https://github.com/ziglang/zig/issues/3317
-// if (builtin.arch == .mipsel) return error.SkipZigTest;
+test "vector" {
+ // https://github.com/ziglang/zig/issues/3317
+ if (builtin.arch == .mipsel) return error.SkipZigTest;
-// const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
-// const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
-// const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
+ const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
+ const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
+ const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
-// try testFmt("{ true, false, true, false }", "{}", .{vbool});
-// try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
-// try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
-// try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
-// try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
-// try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
-// try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
-// }
+ try testFmt("{ true, false, true, false }", "{}", .{vbool});
+ try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
+ try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
+ try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
+ try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
+ try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
+ try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
+}
-// test "enum-literal" {
-// try testFmt(".hello_world", "{}", .{.hello_world});
-// }
+test "enum-literal" {
+ try testFmt(".hello_world", "{}", .{.hello_world});
+}
--
2.54.0
From f51c8f26c195819bb49a641c82ee65bb2f8e3044 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 15:02:29 -0600
Subject: [PATCH 078/111] Apply explicit error type
---
lib/std/fmtstream.zig | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index 3a2767c85ab327516b740975948a62cb4bcd27d8..ff7c492a1933d1be48128ca91298f1d119a1f802 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -316,7 +316,7 @@ pub fn formatType(
options: FormatOptions,
out_stream: var,
max_depth: usize,
-) !void {
+) @TypeOf(out_stream).Error!void {
if (comptime std.mem.eql(u8, fmt, "*")) {
try out_stream.writeAll(@typeName(@TypeOf(value).Child));
try out_stream.writeAll("@");
@@ -1472,19 +1472,19 @@ test "enum" {
try testFmt("E.Two", "{}", .{inst});
}
-// test "struct.self-referential" {
-// const S = struct {
-// const SelfType = @This();
-// a: ?*SelfType,
-// };
+test "struct.self-referential" {
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ };
-// var inst = S{
-// .a = null,
-// };
-// inst.a = &inst;
+ var inst = S{
+ .a = null,
+ };
+ inst.a = &inst;
-// try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
-// }
+ try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
+}
test "struct.zero-size" {
const A = struct {
--
2.54.0
From 1c18ab01a44bf3cbef356ff215e97dfe2788265b Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 15:10:27 -0600
Subject: [PATCH 079/111] Add back max_depth test
---
lib/std/fmtstream.zig | 138 ++++++++++++++++++++----------------------
1 file changed, 66 insertions(+), 72 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index ff7c492a1933d1be48128ca91298f1d119a1f802..c062bbaa1b9ba67200886d2da6464cebbafdb2b1 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -1083,6 +1083,8 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]
format(fbs.outStream(), fmt, args) catch |err| switch (err) {
error.NoSpaceLeft => return error.BufferTooSmall,
};
+ //TODO: should we change one of these return signatures?
+ //return fbs.getWritten();
return buf[0..fbs.pos];
}
@@ -1195,18 +1197,15 @@ test "buffer" {
var buf1: [32]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf1);
try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
- var res = buf1[0..fbs.pos];
- std.testing.expect(mem.eql(u8, res, "1234"));
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
- try fbs.seekTo(0);
+ fbs.reset();
try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
- res = buf1[0..fbs.pos];
- std.testing.expect(mem.eql(u8, res, "a"));
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
- try fbs.seekTo(0);
+ fbs.reset();
try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
- res = buf1[0..fbs.pos];
- std.testing.expect(mem.eql(u8, res, "1100"));
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
}
}
@@ -1583,78 +1582,73 @@ test "formatIntValue with comptime_int" {
var buf: [20]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf);
try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
- std.testing.expect(mem.eql(u8, buf[0..fbs.pos], "123456789123456789"));
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
}
-// test "formatType max_depth" {
-// const Vec2 = struct {
-// const SelfType = @This();
-// x: f32,
-// y: f32,
+test "formatType max_depth" {
+ const Vec2 = struct {
+ const SelfType = @This();
+ x: f32,
+ y: f32,
-// pub fn format(
-// self: SelfType,
-// comptime fmt: []const u8,
-// options: FormatOptions,
-// context: var,
-// comptime Errors: type,
-// comptime output: fn (@TypeOf(context), []const u8) !void,
-// ) !void {
-// if (fmt.len == 0) {
-// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
-// } else {
-// @compileError("Unknown format string: '" ++ fmt ++ "'");
-// }
-// }
-// };
-// const E = enum {
-// One,
-// Two,
-// Three,
-// };
-// const TU = union(enum) {
-// const SelfType = @This();
-// float: f32,
-// int: u32,
-// ptr: ?*SelfType,
-// };
-// const S = struct {
-// const SelfType = @This();
-// a: ?*SelfType,
-// tu: TU,
-// e: E,
-// vec: Vec2,
-// };
+ pub fn format(
+ self: SelfType,
+ comptime fmt: []const u8,
+ options: FormatOptions,
+ out_stream: var,
+ ) !void {
+ if (fmt.len == 0) {
+ return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+ }
+ };
+ const E = enum {
+ One,
+ Two,
+ Three,
+ };
+ const TU = union(enum) {
+ const SelfType = @This();
+ float: f32,
+ int: u32,
+ ptr: ?*SelfType,
+ };
+ const S = struct {
+ const SelfType = @This();
+ a: ?*SelfType,
+ tu: TU,
+ e: E,
+ vec: Vec2,
+ };
-// var inst = S{
-// .a = null,
-// .tu = TU{ .ptr = null },
-// .e = E.Two,
-// .vec = Vec2{ .x = 10.2, .y = 2.22 },
-// };
-// inst.a = &inst;
-// inst.tu.ptr = &inst.tu;
+ var inst = S{
+ .a = null,
+ .tu = TU{ .ptr = null },
+ .e = E.Two,
+ .vec = Vec2{ .x = 10.2, .y = 2.22 },
+ };
+ inst.a = &inst;
+ inst.tu.ptr = &inst.tu;
-// var buf0 = std.ArrayList(u8).init(std.testing.allocator);
-// defer buf0.deinit();
-// try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
-// std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+ var buf: [1000]u8 = undefined;
+ var fbs = std.io.fixedBufferStream(&buf);
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
-// var buf1 = std.ArrayList(u8).init(std.testing.allocator);
-// defer buf1.deinit();
-// try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
-// std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
-// var buf2 = std.ArrayList(u8).init(std.testing.allocator);
-// defer buf2.deinit();
-// try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
-// std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
-// var buf3 = std.ArrayList(u8).init(std.testing.allocator);
-// defer buf3.deinit();
-// try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
-// std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
-// }
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+}
test "positional" {
try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
--
2.54.0
From 710b05b15302f05f98a31635af6d654858215f34 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 16:46:16 +0200
Subject: [PATCH 080/111] support `@atomicRmw` at comptime
---
src/ir.cpp | 82 +++++++++++++++++++++++++++++---
test/compile_errors.zig | 18 +++----
test/stage1/behavior/atomics.zig | 29 +++++++++++
3 files changed, 114 insertions(+), 15 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index dc3e7941d6203f8f02e5251efb5ccc616866cba8..4f139895b9acacdf3ae707c73e4d5af758283e8b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -28436,14 +28436,84 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
}
- if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar)
- {
- ir_add_error(ira, &instruction->base.base,
- buf_sprintf("compiler bug: TODO compile-time execution of @atomicRmw"));
- return ira->codegen->invalid_inst_gen;
+ IrInst *source_inst = &instruction->base.base;
+ if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) {
+ ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
+ if (ptr_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ ZigValue *op1_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.base.source_node);
+ if (op1_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ ZigValue *op2_val = ir_resolve_const(ira, casted_operand, UndefBad);
+ if (op2_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ if (op == AtomicRmwOp_xchg) {
+ ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false);
+ return ir_const_move(ira, source_inst, op1_val);
+ }
+
+ if (operand_type->id == ZigTypeIdPointer || operand_type->id == ZigTypeIdOptional) {
+ ir_add_error(ira, &instruction->ordering->base,
+ buf_sprintf("TODO comptime @atomicRmw with pointers other than .Xchg"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ if (op == AtomicRmwOp_min || op == AtomicRmwOp_max) {
+ IrBinOp bin_op;
+ if (op == AtomicRmwOp_min)
+ // store op2 if op2 < op1
+ bin_op = IrBinOpCmpGreaterThan;
+ else
+ // store op2 if op2 > op1
+ bin_op = IrBinOpCmpLessThan;
+
+ IrInstGen *dummy_value = ir_const(ira, source_inst, operand_type);
+ ir_eval_bin_op_cmp_scalar(ira, source_inst, op1_val, bin_op, op2_val, dummy_value->value);
+ if (dummy_value->value->data.x_bool)
+ ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false);
+ } else {
+ IrBinOp bin_op;
+ switch (op) {
+ case AtomicRmwOp_xchg:
+ case AtomicRmwOp_max:
+ case AtomicRmwOp_min:
+ zig_unreachable();
+ case AtomicRmwOp_add:
+ if (operand_type->id == ZigTypeIdFloat)
+ bin_op = IrBinOpAdd;
+ else
+ bin_op = IrBinOpAddWrap;
+ break;
+ case AtomicRmwOp_sub:
+ if (operand_type->id == ZigTypeIdFloat)
+ bin_op = IrBinOpSub;
+ else
+ bin_op = IrBinOpSubWrap;
+ break;
+ case AtomicRmwOp_and:
+ case AtomicRmwOp_nand:
+ bin_op = IrBinOpBinAnd;
+ break;
+ case AtomicRmwOp_or:
+ bin_op = IrBinOpBinOr;
+ break;
+ case AtomicRmwOp_xor:
+ bin_op = IrBinOpBinXor;
+ break;
+ }
+ ir_eval_math_op_scalar(ira, source_inst, operand_type, op1_val, bin_op, op2_val, op1_val);
+ if (op == AtomicRmwOp_nand) {
+ bigint_not(&op1_val->data.x_bigint, &op1_val->data.x_bigint,
+ operand_type->data.integral.bit_count, operand_type->data.integral.is_signed);
+ }
+ }
+ return ir_const_move(ira, source_inst, op1_val);
}
- return ir_build_atomic_rmw_gen(ira, &instruction->base.base, casted_ptr, casted_operand, op,
+ return ir_build_atomic_rmw_gen(ira, source_inst, casted_ptr, casted_operand, op,
ordering, operand_type);
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 28529b3f579c477c0bcc2eb27b5c9350afff5589..2881c7f6587228330abcb120fc66803579bccd47 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,15 +2,6 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
- cases.add("atomicrmw with bool op not .Xchg",
- \\export fn entry() void {
- \\ var x = false;
- \\ _ = @atomicRmw(bool, &x, .Add, true, .SeqCst);
- \\}
- , &[_][]const u8{
- "tmp.zig:3:30: error: @atomicRmw with bool only allowed with .Xchg",
- });
-
cases.addTest("combination of noasync and async",
\\export fn entry() void {
\\ noasync {
@@ -26,6 +17,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:5:9: error: resume in noasync scope",
});
+ cases.add("atomicrmw with bool op not .Xchg",
+ \\export fn entry() void {
+ \\ var x = false;
+ \\ _ = @atomicRmw(bool, &x, .Add, true, .SeqCst);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:3:30: error: @atomicRmw with bool only allowed with .Xchg",
+ });
+
cases.addTest("@TypeOf with no arguments",
\\export fn entry() void {
\\ _ = @TypeOf();
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index c655bfe7a4046fe8edd9d273ed172eadf2697346..aca5593c6ed9d7be197d7237657b2c15982d6da8 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -149,6 +149,7 @@ fn testAtomicStore() void {
}
test "atomicrmw with floats" {
+ comptime testAtomicRmwFloat();
if (builtin.arch == .aarch64 or builtin.arch == .arm or builtin.arch == .riscv64)
return error.SkipZigTest;
testAtomicRmwFloat();
@@ -165,6 +166,34 @@ fn testAtomicRmwFloat() void {
expect(x == 4);
}
+test "atomicrmw with ints" {
+ testAtomicRmwFloat();
+ comptime testAtomicRmwFloat();
+}
+
+fn testAtomicRmwInt() void {
+ var x: u8 = 1;
+ _ = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
+ expect(x == 3);
+ _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
+ expect(x == 6);
+ _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
+ expect(x == 5);
+ _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
+ expect(x == 4);
+ _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
+ expect(x == 0xfb);
+ _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
+ expect(x == 0xff);
+ _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
+ expect(x == 0xfd);
+ _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
+ expect(x == 0xfd);
+ _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
+ expect(x == 1);
+}
+
+
test "atomics with different types" {
testAtomicsWithType(bool, true, false);
inline for (.{ u1, i5, u15 }) |T| {
--
2.54.0
From 02c491e42affedf6dd33e75a456531bb60aff8a3 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 17:14:01 +0200
Subject: [PATCH 081/111] translate-c fix order of tokens
---
src-self-hosted/translate_c.zig | 9 +++++----
test/translate_c.zig | 8 ++++++++
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 934ed3634d5f0ee7e8fe6058c8b21f2837b4945d..40e7d7f79df3c2e0ec01a55e5b1672988c33e196 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -5375,7 +5375,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
const first_tok = it.list.at(0);
const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));
const node = try c.a().create(ast.Node.CharLiteral);
- node.* = ast.Node.CharLiteral{
+ node.* = .{
.token = token,
};
return &node.base;
@@ -5384,7 +5384,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
const first_tok = it.list.at(0);
const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));
const node = try c.a().create(ast.Node.StringLiteral);
- node.* = ast.Node.StringLiteral{
+ node.* = .{
.token = token,
};
return &node.base;
@@ -5793,12 +5793,13 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return node;
},
}
+ const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
+ const lhs_node = try cast_fn(c, node);
const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const op_node = try c.a().create(ast.Node.InfixOp);
- const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
op_node.* = .{
.op_token = op_token,
- .lhs = try cast_fn(c, node),
+ .lhs = lhs_node,
.op = op_id,
.rhs = try cast_fn(c, rhs_node),
};
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 29b07b86a99a390ce98c5f0064e1f5377e96b6ac..9890c4034e5b17aedfd30e78615d8c1b35db5107 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3,6 +3,14 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("correct semicolon after infixop",
+ \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)
+ , &[_][]const u8{
+ \\pub inline fn __ferror_unlocked_body(_fp: var) @TypeOf(((_fp.*._flags) & _IO_ERR_SEEN) != 0) {
+ \\ return ((_fp.*._flags) & _IO_ERR_SEEN) != 0;
+ \\}
+ });
+
cases.add("c booleans are just ints",
\\#define FOO(x) ((x >= 0) + (x >= 0))
\\#define BAR 1 && 2 > 4
--
2.54.0
From d2e4aafd64184017dc1f152a4b46eeafca94bbd8 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 15:16:04 -0600
Subject: [PATCH 082/111] Fixup allocPrint
---
lib/std/fmtstream.zig | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index c062bbaa1b9ba67200886d2da6464cebbafdb2b1..806ee3d04de09201ba85a958a4a5379b2feb69b8 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -1088,25 +1088,23 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]
return buf[0..fbs.pos];
}
-// pub const AllocPrintError = error{OutOfMemory};
+pub const AllocPrintError = error{OutOfMemory};
-// pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
-// var size: usize = 0;
-// format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
-// const buf = try allocator.alloc(u8, size);
-// return bufPrint(buf, fmt, args) catch |err| switch (err) {
-// error.BufferTooSmall => unreachable, // we just counted the size above
-// };
-// }
+pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
+ // Count the characters we need to preallocate
+ var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
+ format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
-// fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
-// size.* += bytes.len;
-// }
+ const buf = try allocator.alloc(u8, counting_stream.bytes_written);
+ return bufPrint(buf, fmt, args) catch |err| switch (err) {
+ error.BufferTooSmall => unreachable, // we just counted the size above
+ };
+}
-// pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
-// const result = try allocPrint(allocator, fmt ++ "\x00", args);
-// return result[0 .. result.len - 1 :0];
-// }
+pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
+ const result = try allocPrint(allocator, fmt ++ "\x00", args);
+ return result[0 .. result.len - 1 :0];
+}
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
--
2.54.0
From 7364e965f473147a86cc62ccf47feac4878a15de Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 15:24:03 -0600
Subject: [PATCH 083/111] Force error coercion of custom formatters
---
lib/std/fmtstream.zig | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index 806ee3d04de09201ba85a958a4a5379b2feb69b8..8db0052a761c388bfb5aa669220590adc35cb2c4 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -325,6 +325,10 @@ pub fn formatType(
}
const T = @TypeOf(value);
+ if (comptime std.meta.trait.hasFn("format")(T)) {
+ return try value.format(fmt, options, out_stream);
+ }
+
switch (@typeInfo(T)) {
.ComptimeInt, .Int, .Float => {
return formatValue(value, fmt, options, out_stream);
@@ -354,10 +358,6 @@ pub fn formatType(
return out_stream.writeAll(@errorName(value));
},
.Enum => |enumInfo| {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, out_stream);
- }
-
try out_stream.writeAll(@typeName(T));
if (enumInfo.is_exhaustive) {
try out_stream.writeAll(".");
@@ -370,10 +370,6 @@ pub fn formatType(
}
},
.Union => {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, out_stream);
- }
-
try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
return out_stream.writeAll("{ ... }");
@@ -394,10 +390,6 @@ pub fn formatType(
}
},
.Struct => |StructT| {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, out_stream);
- }
-
try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
return out_stream.writeAll("{ ... }");
--
2.54.0
From c11d1055b868add74cc58f3bf745e93110ae6071 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 15:35:18 -0600
Subject: [PATCH 084/111] Integrated outstreams with new formatter
---
lib/std/http/headers.zig | 18 ++++++++----------
lib/std/io/out_stream.zig | 2 +-
lib/std/math/big/int.zig | 8 +++-----
lib/std/net.zig | 22 ++++++++++------------
lib/std/net/test.zig | 4 ++--
lib/std/os/uefi.zig | 10 +++-------
6 files changed, 27 insertions(+), 37 deletions(-)
diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig
index a7a1464f990ace60913f1d2b666bc2ebb31e14fd..cb232a3e3e3e18d540988fee4e664d1329a4b496 100644
--- a/lib/std/http/headers.zig
+++ b/lib/std/http/headers.zig
@@ -349,16 +349,14 @@ pub const Headers = struct {
pub fn format(
self: Self,
comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- context: var,
- comptime Errors: type,
- output: fn (@TypeOf(context), []const u8) Errors!void,
- ) Errors!void {
+ options: std.fmtstream.FormatOptions,
+ out_stream: var,
+ ) !void {
for (self.toSlice()) |entry| {
- try output(context, entry.name);
- try output(context, ": ");
- try output(context, entry.value);
- try output(context, "\n");
+ try out_stream.writeAll(entry.name);
+ try out_stream.writeAll(": ");
+ try out_stream.writeAll(entry.value);
+ try out_stream.writeAll("\n");
}
}
};
@@ -593,5 +591,5 @@ test "Headers.format" {
\\foo: bar
\\cookie: somevalue
\\
- , try std.fmt.bufPrint(buf[0..], "{}", .{h}));
+ , try std.fmtstream.bufPrint(buf[0..], "{}", .{h}));
}
diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig
index 03901f6672be05e4a5556b52d39e5e6cec5ea63a..876a3b4701321920d048985875b96d7df002ae11 100644
--- a/lib/std/io/out_stream.zig
+++ b/lib/std/io/out_stream.zig
@@ -25,7 +25,7 @@ pub fn OutStream(
}
pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
- return std.fmt.format(self, Error, writeAll, format, args);
+ return std.fmtstream.format(self, format, args);
}
pub fn writeByte(self: Self, byte: u8) Error!void {
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index 8fda3f647a68054659eaf47886ac521c9c048f4f..cef2bae98c9375750c7a1bd1a94d123debdcaadf 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -518,17 +518,15 @@ pub const Int = struct {
pub fn format(
self: Int,
comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- context: var,
- comptime FmtError: type,
- output: fn (@TypeOf(context), []const u8) FmtError!void,
+ options: std.fmtstream.FormatOptions,
+ out_stream: var,
) FmtError!void {
self.assertWritable();
// TODO look at fmt and support other bases
// TODO support read-only fixed integers
const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
defer self.allocator.?.free(str);
- return output(context, str);
+ return out_stream.print(str);
}
/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
diff --git a/lib/std/net.zig b/lib/std/net.zig
index de10a17640c23841d501e2b83db09a13f6d2bd58..9395d34f4883a16ce3f0c26aa9659e533c7805a2 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -268,16 +268,14 @@ pub const Address = extern union {
pub fn format(
self: Address,
comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ options: std.fmtstream.FormatOptions,
+ out_stream: var,
) !void {
switch (self.any.family) {
os.AF_INET => {
const port = mem.bigToNative(u16, self.in.port);
const bytes = @ptrCast(*const [4]u8, &self.in.addr);
- try std.fmt.format(context, Errors, output, "{}.{}.{}.{}:{}", .{
+ try std.fmtstream.format(out_stream, "{}.{}.{}.{}:{}", .{
bytes[0],
bytes[1],
bytes[2],
@@ -288,7 +286,7 @@ pub const Address = extern union {
os.AF_INET6 => {
const port = mem.bigToNative(u16, self.in6.port);
if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
- try std.fmt.format(context, Errors, output, "[::ffff:{}.{}.{}.{}]:{}", .{
+ try std.fmtstream.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
self.in6.addr[12],
self.in6.addr[13],
self.in6.addr[14],
@@ -308,30 +306,30 @@ pub const Address = extern union {
break :blk buf;
},
};
- try output(context, "[");
+ try out_stream.writeAll("[");
var i: usize = 0;
var abbrv = false;
while (i < native_endian_parts.len) : (i += 1) {
if (native_endian_parts[i] == 0) {
if (!abbrv) {
- try output(context, if (i == 0) "::" else ":");
+ try out_stream.writeAll(if (i == 0) "::" else ":");
abbrv = true;
}
continue;
}
- try std.fmt.format(context, Errors, output, "{x}", .{native_endian_parts[i]});
+ try std.fmtstream.format(out_stream, "{x}", .{native_endian_parts[i]});
if (i != native_endian_parts.len - 1) {
- try output(context, ":");
+ try out_stream.writeAll(":");
}
}
- try std.fmt.format(context, Errors, output, "]:{}", .{port});
+ try std.fmtstream.format(out_stream, "]:{}", .{port});
},
os.AF_UNIX => {
if (!has_unix_sockets) {
unreachable;
}
- try std.fmt.format(context, Errors, output, "{}", .{&self.un.path});
+ try std.fmtstream.format(out_stream, "{}", .{&self.un.path});
},
else => unreachable,
}
diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig
index 087f965c4ee3de39ff83ed48c09ad40f2653f46f..0dc3b3020dd63fe65b53f134c770d2e83f1691f3 100644
--- a/lib/std/net/test.zig
+++ b/lib/std/net/test.zig
@@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" {
};
for (ips) |ip, i| {
var addr = net.Address.parseIp6(ip, 0) catch unreachable;
- var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
+ var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
}
@@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" {
"127.0.0.1",
}) |ip| {
var addr = net.Address.parseIp4(ip, 0) catch unreachable;
- var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
+ var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
}
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
index 81d13ac1c3140647ea3c13e506a4fbac90fd2066..5d9a678ce8b810e9d509006eec4bb4b96664c81c 100644
--- a/lib/std/os/uefi.zig
+++ b/lib/std/os/uefi.zig
@@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");
pub const status = @import("uefi/status.zig");
pub const tables = @import("uefi/tables.zig");
-const fmt = @import("std").fmt;
-
/// The EFI image's handle that is passed to its entry point.
pub var handle: Handle = undefined;
@@ -29,13 +27,11 @@ pub const Guid = extern struct {
pub fn format(
self: @This(),
comptime f: []const u8,
- options: fmt.FormatOptions,
- context: var,
- comptime Errors: type,
- output: fn (@TypeOf(context), []const u8) Errors!void,
+ options: std.fmtstream.FormatOptions,
+ out_stream: var,
) Errors!void {
if (f.len == 0) {
- return fmt.format(context, Errors, output, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
+ return std.fmtstream.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
self.time_low,
self.time_mid,
self.time_high_and_version,
--
2.54.0
From ce19638cd4690a8ac01a04500fcc525341d0de78 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 17:31:10 +0200
Subject: [PATCH 085/111] disable test on mipsel
---
test/stage1/behavior/atomics.zig | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index aca5593c6ed9d7be197d7237657b2c15982d6da8..36751e7d259dc9dc61a8313920aa56379894af0b 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -149,10 +149,10 @@ fn testAtomicStore() void {
}
test "atomicrmw with floats" {
- comptime testAtomicRmwFloat();
if (builtin.arch == .aarch64 or builtin.arch == .arm or builtin.arch == .riscv64)
return error.SkipZigTest;
testAtomicRmwFloat();
+ comptime testAtomicRmwFloat();
}
fn testAtomicRmwFloat() void {
@@ -167,8 +167,10 @@ fn testAtomicRmwFloat() void {
}
test "atomicrmw with ints" {
- testAtomicRmwFloat();
- comptime testAtomicRmwFloat();
+ if (builtin.arch == .mipsel)
+ return error.SkipZigTest;
+ testAtomicRmwInt();
+ comptime testAtomicRmwInt();
}
fn testAtomicRmwInt() void {
--
2.54.0
From 214af69814b3940236ace44ada0243726d29debf Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 12 Mar 2020 11:40:44 -0400
Subject: [PATCH 086/111] ci: remove workaround for FreeBSD upstream bug
---
ci/srht/freebsd_script | 7 -------
1 file changed, 7 deletions(-)
diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script
index 969e644d5d4686bdeed048192b9c566efcae6885..12cd2d5406a2aed359b64e9e3bfb1fc7758e2c17 100755
--- a/ci/srht/freebsd_script
+++ b/ci/srht/freebsd_script
@@ -3,13 +3,6 @@
set -x
set -e
-# The following line can be removed as soon as FreeBSD fixes
-# their packaging glitch. If not fixed by March 15, 2020
-# there is something wrong. Should be fixed much sooner.
-# note: this will cause some complaints when running
-# pkg commands but let's ignore them.
-sudo rm /usr/local/etc/pkg/repos/FreeBSD.conf
-
sudo pkg update -fq
sudo pkg install -y cmake py27-s3cmd wget curl jq
--
2.54.0
From 0fbccec000efcfe23188027e474530641daf67cd Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 08:59:21 -0600
Subject: [PATCH 087/111] Convert builtin to fmtstream
---
lib/std/builtin.zig | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index fa5b49db37d578931ef106b1e8c80a81c34791fb..5cac8c962276780eeca49c6ac5b9a4e2959819c4 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -426,29 +426,27 @@ pub const Version = struct {
pub fn parse(text: []const u8) !Version {
var it = std.mem.separate(text, ".");
return Version{
- .major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
- .minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
- .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
+ .major = try std.fmtstream.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
+ .minor = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
+ .patch = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
};
}
pub fn format(
self: Version,
comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- context: var,
- comptime Error: type,
- comptime output: fn (@TypeOf(context), []const u8) Error!void,
- ) Error!void {
+ options: std.fmtstream.FormatOptions,
+ out_stream: var,
+ ) !void {
if (fmt.len == 0) {
if (self.patch == 0) {
if (self.minor == 0) {
- return std.fmt.format(context, Error, output, "{}", .{self.major});
+ return std.fmtstream.format(out_stream, "{}", .{self.major});
} else {
- return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });
+ return std.fmtstream.format(out_stream, "{}.{}", .{ self.major, self.minor });
}
} else {
- return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch });
+ return std.fmtstream.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
}
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
--
2.54.0
From 2429fdd73bc2405034805893f169ae58c1c34c56 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 18:59:16 -0600
Subject: [PATCH 088/111] Convert JSON to fmtstream
---
lib/std/json.zig | 134 +++++++++++++++++++++++++----------------------
1 file changed, 72 insertions(+), 62 deletions(-)
diff --git a/lib/std/json.zig b/lib/std/json.zig
index 4e2440d4e9b50212a2c5539f3148b65de2db12ed..f3a0811078009a96b99da7bb2029c0dc8fef3fe7 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {
pub fn stringify(
value: var,
options: StringifyOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.Float, .ComptimeFloat => {
- return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output);
+ return std.fmtstream.formatFloatScientific(value, std.fmtstream.FormatOptions{}, out_stream);
},
.Int, .ComptimeInt => {
- return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output);
+ return std.fmtstream.formatIntValue(value, "", std.fmtstream.FormatOptions{}, out_stream);
},
.Bool => {
- return output(context, if (value) "true" else "false");
+ return out_stream.writeAll(if (value) "true" else "false");
},
.Optional => {
if (value) |payload| {
- return try stringify(payload, options, context, Errors, output);
+ return try stringify(payload, options, out_stream);
} else {
- return output(context, "null");
+ return out_stream.writeAll("null");
}
},
.Enum => {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
- return value.jsonStringify(options, context, Errors, output);
+ return value.jsonStringify(options, out_stream);
}
@compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
},
.Union => {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
- return value.jsonStringify(options, context, Errors, output);
+ return value.jsonStringify(options, out_stream);
}
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
inline for (info.fields) |u_field| {
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
- return try stringify(@field(value, u_field.name), options, context, Errors, output);
+ return try stringify(@field(value, u_field.name), options, out_stream);
}
}
} else {
@@ -2299,10 +2297,10 @@ pub fn stringify(
},
.Struct => |S| {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
- return value.jsonStringify(options, context, Errors, output);
+ return value.jsonStringify(options, out_stream);
}
- try output(context, "{");
+ try out_stream.writeAll("{");
comptime var field_output = false;
inline for (S.fields) |Field, field_i| {
// don't include void fields
@@ -2311,39 +2309,39 @@ pub fn stringify(
if (!field_output) {
field_output = true;
} else {
- try output(context, ",");
+ try out_stream.writeAll(",");
}
- try stringify(Field.name, options, context, Errors, output);
- try output(context, ":");
- try stringify(@field(value, Field.name), options, context, Errors, output);
+ try stringify(Field.name, options, out_stream);
+ try out_stream.writeAll(":");
+ try stringify(@field(value, Field.name), options, out_stream);
}
- try output(context, "}");
+ try out_stream.writeAll("}");
return;
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => {
// TODO: avoid loops?
- return try stringify(value.*, options, context, Errors, output);
+ return try stringify(value.*, options, out_stream);
},
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
.Slice => {
if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
- try output(context, "\"");
+ try out_stream.writeAll("\"");
var i: usize = 0;
while (i < value.len) : (i += 1) {
switch (value[i]) {
// normal ascii characters
- 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]),
+ 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try out_stream.writeAll(value[i .. i + 1]),
// control characters with short escapes
- '\\' => try output(context, "\\\\"),
- '\"' => try output(context, "\\\""),
- '/' => try output(context, "\\/"),
- 0x8 => try output(context, "\\b"),
- 0xC => try output(context, "\\f"),
- '\n' => try output(context, "\\n"),
- '\r' => try output(context, "\\r"),
- '\t' => try output(context, "\\t"),
+ '\\' => try out_stream.writeAll("\\\\"),
+ '\"' => try out_stream.writeAll("\\\""),
+ '/' => try out_stream.writeAll("\\/"),
+ 0x8 => try out_stream.writeAll("\\b"),
+ 0xC => try out_stream.writeAll("\\f"),
+ '\n' => try out_stream.writeAll("\\n"),
+ '\r' => try out_stream.writeAll("\\r"),
+ '\t' => try out_stream.writeAll("\\t"),
else => {
const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
@@ -2351,40 +2349,40 @@ pub fn stringify(
// If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
// then it may be represented as a six-character sequence: a reverse solidus, followed
// by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
- try output(context, "\\u");
- try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
+ try out_stream.writeAll("\\u");
+ try std.fmtstream.formatIntValue(codepoint, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
} else {
// To escape an extended character that is not in the Basic Multilingual Plane,
// the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
- try output(context, "\\u");
- try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
- try output(context, "\\u");
- try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
+ try out_stream.writeAll("\\u");
+ try std.fmtstream.formatIntValue(high, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
+ try out_stream.writeAll("\\u");
+ try std.fmtstream.formatIntValue(low, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
}
i += ulen - 1;
},
}
}
- try output(context, "\"");
+ try out_stream.writeAll("\"");
return;
}
- try output(context, "[");
+ try out_stream.writeAll("[");
for (value) |x, i| {
if (i != 0) {
- try output(context, ",");
+ try out_stream.writeAll(",");
}
- try stringify(x, options, context, Errors, output);
+ try stringify(x, options, out_stream);
}
- try output(context, "]");
+ try out_stream.writeAll("]");
return;
},
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
},
.Array => |info| {
- return try stringify(value[0..], options, context, Errors, output);
+ return try stringify(value[0..], options, out_stream);
},
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
}
@@ -2392,10 +2390,26 @@ pub fn stringify(
}
fn teststringify(expected: []const u8, value: var) !void {
- const TestStringifyContext = struct {
+ const ValidationOutStream = struct {
+ const Self = @This();
+ pub const OutStream = std.io.OutStream(*Self, Error, write);
+ pub const Error = error{
+ TooMuchData,
+ DifferentData,
+ };
+
expected_remaining: []const u8,
- fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {
- if (context.expected_remaining.len < bytes.len) {
+
+ fn init(exp: []const u8) Self {
+ return .{ .expected_remaining = exp };
+ }
+
+ pub fn outStream(self: *Self) OutStream {
+ return .{ .context = self };
+ }
+
+ fn write(self: *Self, bytes: []const u8) Error!usize {
+ if (self.expected_remaining.len < bytes.len) {
std.debug.warn(
\\====== expected this output: =========
\\{}
@@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {
\\{}
\\======================================
, .{
- context.expected_remaining,
+ self.expected_remaining,
bytes,
});
return error.TooMuchData;
}
- if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) {
+ if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
std.debug.warn(
\\====== expected this output: =========
\\{}
@@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {
\\{}
\\======================================
, .{
- context.expected_remaining[0..bytes.len],
+ self.expected_remaining[0..bytes.len],
bytes,
});
return error.DifferentData;
}
- context.expected_remaining = context.expected_remaining[bytes.len..];
+ self.expected_remaining = self.expected_remaining[bytes.len..];
+ return bytes.len;
}
};
- var buf: [100]u8 = undefined;
- var context = TestStringifyContext{ .expected_remaining = expected };
- try stringify(value, StringifyOptions{}, &context, error{
- TooMuchData,
- DifferentData,
- }, TestStringifyContext.testStringifyWrite);
- if (context.expected_remaining.len > 0) return error.NotEnoughData;
+
+ var vos = ValidationOutStream.init(expected);
+ try stringify(value, StringifyOptions{}, vos.outStream());
+ if (vos.expected_remaining.len > 0) return error.NotEnoughData;
}
test "stringify basic types" {
@@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {
pub fn jsonStringify(
value: Self,
options: StringifyOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ out_stream: var,
) !void {
- try output(context, "[\"something special\",");
- try stringify(42, options, context, Errors, output);
- try output(context, "]");
+ try out_stream.writeAll("[\"something special\",");
+ try stringify(42, options, out_stream);
+ try out_stream.writeAll("]");
}
}{ .foo = 42 });
}
--
2.54.0
From 8dd078b99a31f49194c07af93b0f555f2c7260dc Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Sat, 29 Feb 2020 21:43:54 -0600
Subject: [PATCH 089/111] Convert Buffer to use fmtstream
---
lib/std/buffer.zig | 12 +++---------
lib/std/fmtstream.zig | 13 ++++++++-----
2 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index 28ce2a561062f0a84f55c58c10c1c3b9d359a293..93281c35ec497509ab2850937bf6fb5b5111786a 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -65,15 +65,9 @@ pub const Buffer = struct {
}
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
- const countSize = struct {
- fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
- size.* += bytes.len;
- }
- }.countSize;
- var size: usize = 0;
- std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
+ const size = std.fmtstream.count(format, args);
var self = try Buffer.initSize(allocator, size);
- assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
+ assert((std.fmtstream.bufPrint(self.list.items, format, args) catch unreachable).len == size);
return self;
}
@@ -155,7 +149,7 @@ pub const Buffer = struct {
}
pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
- return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
+ return self.outStream().print(fmt, args);
}
pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index 8db0052a761c388bfb5aa669220590adc35cb2c4..237d0014501b46d3e09c33ae1cbad4ef92935309 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -1080,14 +1080,17 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]
return buf[0..fbs.pos];
}
-pub const AllocPrintError = error{OutOfMemory};
-
-pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- // Count the characters we need to preallocate
+// Count the characters needed for format. Useful for preallocating memory
+pub fn count(comptime fmt: []const u8, args: var) usize {
var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
+ return counting_stream.bytes_written;
+}
- const buf = try allocator.alloc(u8, counting_stream.bytes_written);
+pub const AllocPrintError = error{OutOfMemory};
+
+pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
+ const buf = try allocator.alloc(u8, count(fmt, args));
return bufPrint(buf, fmt, args) catch |err| switch (err) {
error.BufferTooSmall => unreachable, // we just counted the size above
};
--
2.54.0
From 4023ed56d4fd7b627aed73428b5fa4be4b7c05ad Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 09:33:12 -0600
Subject: [PATCH 090/111] Convert translate-c to fmtstream
---
src-self-hosted/translate_c.zig | 51 +++++++++++++++------------------
1 file changed, 23 insertions(+), 28 deletions(-)
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index f14ebe33061141fa3cd5f43b68d8150cbeee2050..7b05a76cb7cc39b9d50d2c971b33c18dc635a02f 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -89,7 +89,7 @@ const Scope = struct {
var proposed_name = name;
while (scope.contains(proposed_name)) {
scope.mangle_count += 1;
- proposed_name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
+ proposed_name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
}
try scope.variables.push(.{ .name = name, .alias = proposed_name });
return proposed_name;
@@ -246,7 +246,7 @@ pub const Context = struct {
const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
- return std.fmt.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
+ return std.fmtstream.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
}
};
@@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const arg_name = blk: {
const param_prefix = if (is_const) "" else "arg_";
- const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
+ const bare_arg_name = try std.fmtstream.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
break :blk try block_scope.makeMangledName(c, bare_arg_name);
};
@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
+ const checked_name = if (isZigPrimitiveType(var_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
_ = try appendToken(rp.c, .LParen, "(");
const expr = try transCreateNodeStringLiteral(
rp.c,
- try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
+ try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
);
_ = try appendToken(rp.c, .RParen, ")");
@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
+ const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
if (mem.eql(u8, checked_name, "uint8_t"))
return transTypeDefAsBuiltin(c, typedef_decl, "u8")
@@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
// Record declarations such as `struct {...} x` have no name but they're not
// anonymous hence here isAnonymousStructOrUnion is not needed
if (bare_name.len == 0) {
- bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_unnamed = true;
}
@@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
return null;
}
- const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
+ const name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
_ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
@@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
var is_anon = false;
var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
- raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ raw_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_anon = true;
}
const field_name = try appendIdentifier(c, raw_name);
@@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl)));
var is_unnamed = false;
if (bare_name.len == 0) {
- bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_unnamed = true;
}
- const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
+ const name = try std.fmtstream.allocPrint(c.a(), "enum_{}", .{bare_name});
_ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
node.eq_token = try appendToken(c, .Equal, "=");
@@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
// Handle the remaining escapes Zig doesn't support by turning them
// into their respective hex representation
if (std.ascii.isCntrl(c))
- return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
+ return std.fmtstream.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
else
- return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
+ return std.fmtstream.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
},
};
}
@@ -2436,7 +2436,7 @@ fn transCase(
) TransError!*ast.Node {
const block_scope = scope.findBlockScope(rp.c) catch unreachable;
const switch_scope = scope.getSwitch();
- const label = try std.fmt.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
+ const label = try std.fmtstream.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
_ = try appendToken(rp.c, .Semicolon, ";");
const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
@@ -4607,7 +4607,7 @@ fn finishTransFnProto(
_ = try appendToken(rp.c, .LParen, "(");
const expr = try transCreateNodeStringLiteral(
rp.c,
- try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
+ try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
);
_ = try appendToken(rp.c, .RParen, ")");
@@ -4752,15 +4752,10 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd
}
fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex {
- const S = struct {
- fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
- return context.source_buffer.append(bytes);
- }
- };
const start_index = c.source_buffer.len();
errdefer c.source_buffer.shrink(start_index);
- try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);
+ try c.source_buffer.print(format, args);
const end_index = c.source_buffer.len();
const token_index = c.tree.tokens.len;
const new_token = try c.tree.tokens.addOne();
@@ -4871,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
const name = try c.str(raw_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
+ const mangled_name = if (isZigPrimitiveType(name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
if (scope.containsNow(mangled_name)) {
continue;
}
@@ -5156,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
switch (lit_bytes[1]) {
'0'...'7' => {
// Octal
- lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{lit_bytes});
+ lit_bytes = try std.fmtstream.allocPrint(c.a(), "0o{}", .{lit_bytes});
},
'X' => {
// Hexadecimal with capital X, valid in C but not in Zig
- lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
+ lit_bytes = try std.fmtstream.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
},
else => {},
}
@@ -5191,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
return &cast_node.base;
} else if (tok.id == .FloatLiteral) {
if (lit_bytes[0] == '.')
- lit_bytes = try std.fmt.allocPrint(c.a(), "0{}", .{lit_bytes});
+ lit_bytes = try std.fmtstream.allocPrint(c.a(), "0{}", .{lit_bytes});
if (tok.id.FloatLiteral == .None) {
return transCreateNodeFloat(c, lit_bytes);
}
@@ -5324,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
num += c - 'A' + 10;
},
else => {
- i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
num = 0;
if (c == '\\')
state = .Escape
@@ -5350,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
};
num += c - '0';
} else {
- i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
num = 0;
count = 0;
if (c == '\\')
@@ -5364,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
}
}
if (state == .Hex or state == .Octal)
- i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
return bytes[0..i];
}
--
2.54.0
From 0059d9ee3e7298df03723d97adbea72ff142cacd Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 09:47:42 -0600
Subject: [PATCH 091/111] Convert fmt.bufPrint / fmt.allocPrint
---
lib/std/atomic/queue.zig | 4 ++--
lib/std/net.zig | 2 +-
lib/std/os.zig | 2 +-
lib/std/progress.zig | 6 +++---
lib/std/special/build_runner.zig | 6 +++---
lib/std/target.zig | 4 ++--
lib/std/zig/cross_target.zig | 2 +-
lib/std/zig/system.zig | 6 +++---
src-self-hosted/compilation.zig | 6 +++---
src-self-hosted/dep_tokenizer.zig | 2 +-
src-self-hosted/libc_installation.zig | 2 +-
src-self-hosted/link.zig | 20 ++++++++++----------
src-self-hosted/print_targets.zig | 2 +-
src-self-hosted/test.zig | 6 +++---
src-self-hosted/type.zig | 8 ++++----
test/src/compare_output.zig | 8 ++++----
test/src/run_translated_c.zig | 4 ++--
test/src/translate_c.zig | 4 ++--
test/tests.zig | 10 +++++-----
tools/process_headers.zig | 4 ++--
tools/update_glibc.zig | 4 ++--
21 files changed, 56 insertions(+), 56 deletions(-)
diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig
index 1a0f39587e96212b6c75a927d7ce4b9653ceaedb..c308fa681f8d21d2021beeacec62cf230bf4734b 100644
--- a/lib/std/atomic/queue.zig
+++ b/lib/std/atomic/queue.zig
@@ -348,7 +348,7 @@ test "std.atomic.Queue dump" {
fbs.reset();
try queue.dumpToStream(fbs.outStream());
- var expected = try std.fmt.bufPrint(expected_buffer[0..],
+ var expected = try std.fmtstream.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ (null)
\\tail: 0x{x}=1
@@ -368,7 +368,7 @@ test "std.atomic.Queue dump" {
fbs.reset();
try queue.dumpToStream(fbs.outStream());
- expected = try std.fmt.bufPrint(expected_buffer[0..],
+ expected = try std.fmtstream.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ 0x{x}=2
\\ (null)
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 9395d34f4883a16ce3f0c26aa9659e533c7805a2..a1225654f014ec234e6344565fb90c8f4c9247dd 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
const name_c = try std.cstr.addNullByte(allocator, name);
defer allocator.free(name_c);
- const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
+ const port_c = try std.fmtstream.allocPrint(allocator, "{}\x00", .{port});
defer allocator.free(port_c);
const hints = os.addrinfo{
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 76a5dc2be55cf227ebe1240d9eb6448009f01389..baea4cecc5933a8989e377eec0efa1ce413b3c54 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3049,7 +3049,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
defer close(fd);
var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
- const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
+ const proc_path = std.fmtstream.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
}
diff --git a/lib/std/progress.zig b/lib/std/progress.zig
index 0264d99c91a8fe02ce5a689b2c34c713874a4ede..ebb983cdc622bafee93a315be63b7305772fe9b7 100644
--- a/lib/std/progress.zig
+++ b/lib/std/progress.zig
@@ -130,11 +130,11 @@ pub const Progress = struct {
var end: usize = 0;
if (self.columns_written > 0) {
// restore cursor position
- end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
+ end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
self.columns_written = 0;
// clear rest of line
- end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
+ end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
}
if (!self.done) {
@@ -185,7 +185,7 @@ pub const Progress = struct {
}
fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: var) void {
- if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
+ if (std.fmtstream.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
const amt = written.len;
end.* += amt;
self.columns_written += amt;
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
index 974247e2a1b708bbbc270b70e4da5c7461205d80..c5a96df667fd758b0aeca4aa96aab1a04f9b8cc2 100644
--- a/lib/std/special/build_runner.zig
+++ b/lib/std/special/build_runner.zig
@@ -2,7 +2,7 @@ const root = @import("@build");
const std = @import("std");
const builtin = @import("builtin");
const io = std.io;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const Builder = std.build.Builder;
const mem = std.mem;
const process = std.process;
@@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
const allocator = builder.allocator;
for (builder.top_level_steps.toSliceConst()) |top_level_step| {
const name = if (&top_level_step.step == builder.default_step)
- try fmt.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
+ try fmtstream.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
else
top_level_step.step.name;
try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description });
@@ -175,7 +175,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
try out_stream.print(" (none)\n", .{});
} else {
for (builder.available_options_list.toSliceConst()) |option| {
- const name = try fmt.allocPrint(allocator, " -D{}=[{}]", .{
+ const name = try fmtstream.allocPrint(allocator, " -D{}=[{}]", .{
option.name,
Builder.typeIdName(option.type_id),
});
diff --git a/lib/std/target.zig b/lib/std/target.zig
index 8beb7c3011db21e052dc8568e6e19ee2774c57b7..c117f60cc04fddaf87cc9b78ff3a1c66e9ef30d5 100644
--- a/lib/std/target.zig
+++ b/lib/std/target.zig
@@ -972,7 +972,7 @@ pub const Target = struct {
}
pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 {
- return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
+ return std.fmtstream.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
}
pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
@@ -1158,7 +1158,7 @@ pub const Target = struct {
var result: DynamicLinker = .{};
const S = struct {
fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {
- r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
+ r.max_byte = @intCast(u8, (std.fmtstream.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
return r.*;
}
fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig
index cec3ea05e5ce82d90659c02c7497514da0100858..a60833f93cf3d8ae7baca242182ef10554a81887 100644
--- a/lib/std/zig/cross_target.zig
+++ b/lib/std/zig/cross_target.zig
@@ -573,7 +573,7 @@ pub const CrossTarget = struct {
.Dynamic => "",
};
- return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
+ return std.fmtstream.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
}
pub const Executor = union(enum) {
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 558b50b5b38564f2699b4ce50b4342699710fdd0..875ecd424c1028e88937f4baa6304a52b1a0ef42 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -130,7 +130,7 @@ pub const NativePaths = struct {
}
pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args);
+ const item = try std.fmtstream.allocPrint0(self.include_dirs.allocator, fmt, args);
errdefer self.include_dirs.allocator.free(item);
try self.include_dirs.append(item);
}
@@ -140,7 +140,7 @@ pub const NativePaths = struct {
}
pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args);
+ const item = try std.fmtstream.allocPrint0(self.lib_dirs.allocator, fmt, args);
errdefer self.lib_dirs.allocator.free(item);
try self.lib_dirs.append(item);
}
@@ -150,7 +150,7 @@ pub const NativePaths = struct {
}
pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args);
+ const item = try std.fmtstream.allocPrint0(self.warnings.allocator, fmt, args);
errdefer self.warnings.allocator.free(item);
try self.warnings.append(item);
}
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
index 7a45bb3c37f12cc634e781ee3e2e73b67e791ce3..fdaee7d12ff9f1e473a56dbd99dc816656644486 100644
--- a/src-self-hosted/compilation.zig
+++ b/src-self-hosted/compilation.zig
@@ -1051,7 +1051,7 @@ pub const Compilation = struct {
}
fn addCompileError(self: *Compilation, tree_scope: *Scope.AstTree, span: Span, comptime fmt: []const u8, args: var) !void {
- const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
+ const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
errdefer self.gpa().free(text);
const msg = try Msg.createFromScope(self, tree_scope, span, text);
@@ -1061,7 +1061,7 @@ pub const Compilation = struct {
}
fn addCompileErrorCli(self: *Compilation, realpath: []const u8, comptime fmt: []const u8, args: var) !void {
- const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
+ const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
errdefer self.gpa().free(text);
const msg = try Msg.createFromCli(self, realpath, text);
@@ -1154,7 +1154,7 @@ pub const Compilation = struct {
const tmp_dir = try self.getTmpDir();
const file_prefix = self.getRandomFileName();
- const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
+ const file_name = try std.fmtstream.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
defer self.gpa().free(file_name);
const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] });
diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig
index 5c250cdb994b524b8e49aa52882303326834becb..11724a3d2cb6f3c098223af91f5753113a881e99 100644
--- a/src-self-hosted/dep_tokenizer.zig
+++ b/src-self-hosted/dep_tokenizer.zig
@@ -894,7 +894,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
var buf: [80]u8 = undefined;
- var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
+ var text = try std.fmtstream.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
try out.write(text);
var i: usize = text.len;
const end = 79;
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 0f9736456a0ef408041a8bf86a174d3eeec0dba7..3b65fb172bdbf6debeb7f7b1be5684f33b07aebb 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
const allocator = args.allocator;
const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
- const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
+ const arg1 = try std.fmtstream.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
defer allocator.free(arg1);
const argv = [_][]const u8{ cc_exe, arg1 };
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig
index 1efa15574a788435b8ad42793035a1a710e8913b..b63e6c24f47271b394427cbe63eb750b73175edb 100644
--- a/src-self-hosted/link.zig
+++ b/src-self-hosted/link.zig
@@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
const is_library = ctx.comp.kind == .Lib;
- const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
+ const out_arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
if (ctx.comp.haveLibC()) {
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
}
if (ctx.link_in_crt) {
@@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
if (ctx.comp.is_static) {
- const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
+ const cmt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
} else {
- const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
+ const msvcrt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
}
- const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
+ const vcruntime_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
lib_str,
d_str,
});
try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
- const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
+ const crt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
// Visual C++ 2015 Conformance Changes
@@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
.IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
.IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
}
- const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
+ const ver_str = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
platform.major,
platform.minor,
platform.micro,
@@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append("-lSystem");
} else {
if (mem.indexOfScalar(u8, lib.name, '/') == null) {
- const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
+ const arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
} else {
const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig
index ad506425d2af144e4b906e8781510a58c769d4b2..408c39fe7b93bb5a2a71b34cc1e91b2e80475b7a 100644
--- a/src-self-hosted/print_targets.zig
+++ b/src-self-hosted/print_targets.zig
@@ -138,7 +138,7 @@ pub fn cmdTargets(
for (available_glibcs) |glibc| {
try jws.arrayElem();
- const tmp = try std.fmt.allocPrint(allocator, "{}", .{glibc});
+ const tmp = try std.fmtstream.allocPrint(allocator, "{}", .{glibc});
defer allocator.free(tmp);
try jws.emitString(tmp);
}
diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig
index e87164c9fb471f243a85c6708902f4c333f9d7a8..98e9fb06dfc916141e66fcb80da444d5056c7472 100644
--- a/src-self-hosted/test.zig
+++ b/src-self-hosted/test.zig
@@ -81,7 +81,7 @@ pub const TestContext = struct {
msg: []const u8,
) !void {
var file_index_buf: [20]u8 = undefined;
- const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
+ const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
if (std.fs.path.dirname(file1_path)) |dirname| {
@@ -114,10 +114,10 @@ pub const TestContext = struct {
expected_output: []const u8,
) !void {
var file_index_buf: [20]u8 = undefined;
- const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
+ const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
- const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
+ const output_file = try std.fmtstream.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
if (std.fs.path.dirname(file1_path)) |dirname| {
try std.fs.cwd().makePath(dirname);
}
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
index 70ed754cea752c9015541ace7df5365463cd7ea0..c2b406823ddc0d8cb130850989667c7e73d31543 100644
--- a/src-self-hosted/type.zig
+++ b/src-self-hosted/type.zig
@@ -581,7 +581,7 @@ pub const Type = struct {
errdefer comp.gpa().destroy(self);
const u_or_i = "ui"[@boolToInt(key.is_signed)];
- const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
+ const name = try std.fmtstream.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
errdefer comp.gpa().free(name);
self.base.init(comp, .Int, name);
@@ -764,13 +764,13 @@ pub const Type = struct {
.Non => "",
};
const name = switch (self.key.alignment) {
- .Abi => try std.fmt.allocPrint(comp.gpa(), "{}{}{}{}", .{
+ .Abi => try std.fmtstream.allocPrint(comp.gpa(), "{}{}{}{}", .{
size_str,
mut_str,
vol_str,
self.key.child_type.name,
}),
- .Override => |alignment| try std.fmt.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
+ .Override => |alignment| try std.fmtstream.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
size_str,
alignment,
mut_str,
@@ -845,7 +845,7 @@ pub const Type = struct {
};
errdefer comp.gpa().destroy(self);
- const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
+ const name = try std.fmtstream.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
errdefer comp.gpa().free(name);
self.base.init(comp, .Array, name);
diff --git a/test/src/compare_output.zig b/test/src/compare_output.zig
index ae994a0697d5031bf2814b5355aaa0361a26d471..c68eb1eebf6166153ac8b82028078593a2c536cc 100644
--- a/test/src/compare_output.zig
+++ b/test/src/compare_output.zig
@@ -4,7 +4,7 @@ const std = @import("std");
const builtin = std.builtin;
const build = std.build;
const ArrayList = std.ArrayList;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -97,7 +97,7 @@ pub const CompareOutputContext = struct {
switch (case.special) {
Special.Asm => {
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", .{
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "assemble-and-link {}", .{
case.name,
}) catch unreachable;
if (self.test_filter) |filter| {
@@ -116,7 +116,7 @@ pub const CompareOutputContext = struct {
},
Special.None => {
for (self.modes) |mode| {
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
"compare-output",
case.name,
@tagName(mode),
@@ -141,7 +141,7 @@ pub const CompareOutputContext = struct {
}
},
Special.RuntimeSafety => {
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig
index 14b0ce593c59ef04af075ff7bfc825a1cee7a698..6304137e4a6c204e268a192bca1f701671eb1cd4 100644
--- a/test/src/run_translated_c.zig
+++ b/test/src/run_translated_c.zig
@@ -3,7 +3,7 @@
const std = @import("std");
const build = std.build;
const ArrayList = std.ArrayList;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct {
pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
const b = self.b;
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig
index 9a6bd0d3234457eef6b89414e923adc21cf29ba8..250ec6175ee9edda2a93650d7edc7fd4df9ea565 100644
--- a/test/src/translate_c.zig
+++ b/test/src/translate_c.zig
@@ -3,7 +3,7 @@
const std = @import("std");
const build = std.build;
const ArrayList = std.ArrayList;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -99,7 +99,7 @@ pub const TranslateCContext = struct {
const b = self.b;
const translate_c_cmd = "translate-c";
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/tests.zig b/test/tests.zig
index 22dad10e3e46c6edccd7c001fbe0705392b264bb..61f694bedb6f9829ff3e7309eba55db0a7bfe127 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -8,7 +8,7 @@ const Buffer = std.Buffer;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const ArrayList = std.ArrayList;
const Mode = builtin.Mode;
const LibExeObjStep = build.LibExeObjStep;
@@ -484,7 +484,7 @@ pub const StackTracesContext = struct {
const expect_for_mode = expect[@enumToInt(mode)];
if (expect_for_mode.len == 0) continue;
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
"stack-trace",
name,
@tagName(mode),
@@ -943,7 +943,7 @@ pub const CompileErrorContext = struct {
pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
const b = self.b;
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", .{
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "compile-error {}", .{
case.name,
}) catch unreachable;
if (self.test_filter) |filter| {
@@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct {
const b = self.b;
for (self.modes) |mode| {
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", .{
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "build {} ({})", .{
root_src,
@tagName(mode),
}) catch unreachable;
@@ -1152,7 +1152,7 @@ pub const GenHContext = struct {
const b = self.b;
const mode = builtin.Mode.Debug;
- const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
+ const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/tools/process_headers.zig b/tools/process_headers.zig
index abdc9fabf944c38683677d266e26f1e5a7d9a179..43950750e9e44b82f51954f81c1f6efbe49909ae 100644
--- a/tools/process_headers.zig
+++ b/tools/process_headers.zig
@@ -299,7 +299,7 @@ pub fn main() !void {
std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});
usageAndExit(args[0]);
};
- const generic_name = try std.fmt.allocPrint(allocator, "generic-{}", .{abi_name});
+ const generic_name = try std.fmtstream.allocPrint(allocator, "generic-{}", .{abi_name});
// TODO compiler crashed when I wrote this the canonical way
var libc_targets: []const LibCTarget = undefined;
@@ -440,7 +440,7 @@ pub fn main() !void {
.specific => |a| @tagName(a),
else => @tagName(dest_target.arch),
};
- const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{
+ const out_subpath = try std.fmtstream.allocPrint(allocator, "{}-{}-{}", .{
arch_name,
@tagName(dest_target.os),
@tagName(dest_target.abi),
diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig
index 84522aabe450b990dce959133d35dd005c0a19a1..35351e4d2a3ffbc9508383f819840b4622daa874 100644
--- a/tools/update_glibc.zig
+++ b/tools/update_glibc.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const fs = std.fs;
-const fmt = std.fmt;
+const fmtstream = std.fmtstream;
const assert = std.debug.assert;
// Example abilist path:
@@ -154,7 +154,7 @@ pub fn main() !void {
const fn_set = &target_funcs_gop.kv.value.list;
for (lib_names) |lib_name, lib_name_index| {
- const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});
+ const basename = try fmtstream.allocPrint(allocator, "lib{}.abilist", .{lib_name});
const abi_list_filename = blk: {
if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });
--
2.54.0
From 6a53fe7c93ddc6216e7cd41514bebe701531c9c3 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 12:03:15 -0600
Subject: [PATCH 092/111] Handle potential downcast when translating stream
size
---
lib/std/buffer.zig | 4 +++-
lib/std/fmtstream.zig | 10 +++++++---
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index 93281c35ec497509ab2850937bf6fb5b5111786a..6d361bdb4ae1f9c107b2f89ce6c421d0d599ec2b 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -65,7 +65,9 @@ pub const Buffer = struct {
}
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
- const size = std.fmtstream.count(format, args);
+ const size = std.fmtstream.count(format, args) catch |err| switch (err) {
+ error.Overflow => return error.OutOfMemory,
+ };
var self = try Buffer.initSize(allocator, size);
assert((std.fmtstream.bufPrint(self.list.items, format, args) catch unreachable).len == size);
return self;
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
index 237d0014501b46d3e09c33ae1cbad4ef92935309..93734d42aa334c2e476dcfc00a0b3c455211fc6e 100644
--- a/lib/std/fmtstream.zig
+++ b/lib/std/fmtstream.zig
@@ -1081,16 +1081,20 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]
}
// Count the characters needed for format. Useful for preallocating memory
-pub fn count(comptime fmt: []const u8, args: var) usize {
+pub fn count(comptime fmt: []const u8, args: var) !usize {
var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
- return counting_stream.bytes_written;
+ return std.math.cast(usize, counting_stream.bytes_written);
}
pub const AllocPrintError = error{OutOfMemory};
pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- const buf = try allocator.alloc(u8, count(fmt, args));
+ const size = count(fmt, args) catch |err| switch (err) {
+ // Output too long. Can't possibly allocate enough memory to display it.
+ error.Overflow => return error.OutOfMemory,
+ };
+ const buf = try allocator.alloc(u8, size);
return bufPrint(buf, fmt, args) catch |err| switch (err) {
error.BufferTooSmall => unreachable, // we just counted the size above
};
--
2.54.0
From 786216ca5a7cc992d1be895702d37798bc85bf14 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 16:52:46 -0600
Subject: [PATCH 093/111] Slap in workaround for Fifo
---
lib/std/fifo.zig | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig
index 85a0e4c9d265a0ea5e65c7c86042cee2df85e9c1..65ddc65d3c09efbf862edae5ac13b5bf78940e21 100644
--- a/lib/std/fifo.zig
+++ b/lib/std/fifo.zig
@@ -294,7 +294,19 @@ pub fn LinearFifo(
pub usingnamespace if (T == u8)
struct {
pub fn print(self: *Self, comptime format: []const u8, args: var) !void {
- return std.fmt.format(self, error{OutOfMemory}, Self.write, format, args);
+ // TODO: maybe expose this stream as a method?
+ const FifoStream = struct {
+ const OutStream = std.io.OutStream(*Self, Error, write);
+ const Error = error{OutOfMemory};
+
+ fn write(fifo: *Self, bytes: []const u8) Error!usize {
+ try fifo.write(bytes);
+ return bytes.len;
+ }
+ };
+
+ var out_stream = FifoStream.OutStream{ .context = self };
+ try out_stream.print(format, args);
}
}
else
--
2.54.0
From ed7f30e1cd0c00c82c511ad826fe8d8b60b2f57f Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 16:45:42 -0600
Subject: [PATCH 094/111] Migrate last vestiges of fmt
---
src-self-hosted/dep_tokenizer.zig | 26 ++++++++++------------
test/stage1/behavior/enum_with_members.zig | 6 ++---
2 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig
index 11724a3d2cb6f3c098223af91f5753113a881e99..233b6781719f0654a25e0f1f7b1c1539cbf8329e 100644
--- a/src-self-hosted/dep_tokenizer.zig
+++ b/src-self-hosted/dep_tokenizer.zig
@@ -306,12 +306,12 @@ pub const Tokenizer = struct {
fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
- std.fmt.format(&buffer, anyerror, std.Buffer.append, fmt, args) catch {};
+ try buffer.print(fmt, args);
try buffer.append(" '");
var out = makeOutput(std.Buffer.append, &buffer);
try printCharValues(&out, bytes);
try buffer.append("'");
- std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position - (bytes.len - 1)}) catch {};
+ try buffer.print(" at position {}", .{position - (bytes.len - 1)});
self.error_text = buffer.toSlice();
return Error.InvalidInput;
}
@@ -319,10 +319,9 @@ pub const Tokenizer = struct {
fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
try buffer.append("illegal char ");
- var out = makeOutput(std.Buffer.append, &buffer);
- try printUnderstandableChar(&out, char);
- std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position}) catch {};
- if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
+ try printUnderstandableChar(&buffer, char);
+ try buffer.print(" at position {}", .{position});
+ if (fmt.len != 0) try buffer.print(": " ++ fmt, args);
self.error_text = buffer.toSlice();
return Error.InvalidInput;
}
@@ -980,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {
fn printDecValue(out: var, value: u64, width: u8) !void {
var buffer: [20]u8 = undefined;
- const len = std.fmt.formatIntBuf(buffer[0..], value, 10, false, width);
+ const len = std.fmtstream.formatIntBuf(buffer[0..], value, 10, false, width);
try out.write(buffer[0..len]);
}
fn printHexValue(out: var, value: u64, width: u8) !void {
var buffer: [16]u8 = undefined;
- const len = std.fmt.formatIntBuf(buffer[0..], value, 16, false, width);
+ const len = std.fmtstream.formatIntBuf(buffer[0..], value, 16, false, width);
try out.write(buffer[0..len]);
}
@@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {
}
}
-fn printUnderstandableChar(out: var, char: u8) !void {
+fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void {
if (!std.ascii.isPrint(char) or char == ' ') {
- const output = @typeInfo(@TypeOf(out)).Pointer.child.output;
- std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {};
+ try buffer.print("\\x{X:2}", .{char});
} else {
- try out.write("'");
- try out.write(&[_]u8{printable_char_tab[char]});
- try out.write("'");
+ try buffer.append("'");
+ try buffer.appendByte(printable_char_tab[char]);
+ try buffer.append("'");
}
}
diff --git a/test/stage1/behavior/enum_with_members.zig b/test/stage1/behavior/enum_with_members.zig
index 08b195494b546238fbe1c7096ea5d7e8dcfe43d8..b299301ced01b93ee5a77cbacdb60953013c93a8 100644
--- a/test/stage1/behavior/enum_with_members.zig
+++ b/test/stage1/behavior/enum_with_members.zig
@@ -1,6 +1,6 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
-const fmt = @import("std").fmt;
+const fmtstream = @import("std").fmtstream;
const ET = union(enum) {
SINT: i32,
@@ -8,8 +8,8 @@ const ET = union(enum) {
pub fn print(a: *const ET, buf: []u8) anyerror!usize {
return switch (a.*) {
- ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
- ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
+ ET.SINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
+ ET.UINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
};
}
};
--
2.54.0
From 4aae55b4ccf44fa3c2c2a81a6a34f3c898dece30 Mon Sep 17 00:00:00 2001
From: Benjamin Feng
Date: Fri, 6 Mar 2020 16:59:21 -0600
Subject: [PATCH 095/111] Replace fmt with new fmtstream
---
lib/std/atomic/queue.zig | 4 +-
lib/std/buffer.zig | 4 +-
lib/std/builtin.zig | 14 +-
lib/std/fmt.zig | 509 +++---
lib/std/fmtstream.zig | 1685 --------------------
lib/std/http/headers.zig | 4 +-
lib/std/io/out_stream.zig | 2 +-
lib/std/json.zig | 10 +-
lib/std/math/big/int.zig | 2 +-
lib/std/net.zig | 14 +-
lib/std/net/test.zig | 4 +-
lib/std/os.zig | 2 +-
lib/std/os/uefi.zig | 4 +-
lib/std/progress.zig | 6 +-
lib/std/special/build_runner.zig | 6 +-
lib/std/std.zig | 1 -
lib/std/target.zig | 4 +-
lib/std/zig/cross_target.zig | 2 +-
lib/std/zig/system.zig | 6 +-
src-self-hosted/compilation.zig | 6 +-
src-self-hosted/dep_tokenizer.zig | 6 +-
src-self-hosted/libc_installation.zig | 2 +-
src-self-hosted/link.zig | 20 +-
src-self-hosted/print_targets.zig | 2 +-
src-self-hosted/test.zig | 6 +-
src-self-hosted/translate_c.zig | 44 +-
src-self-hosted/type.zig | 8 +-
test/src/compare_output.zig | 8 +-
test/src/run_translated_c.zig | 4 +-
test/src/translate_c.zig | 4 +-
test/stage1/behavior/enum_with_members.zig | 6 +-
test/tests.zig | 10 +-
tools/process_headers.zig | 4 +-
tools/update_glibc.zig | 4 +-
34 files changed, 331 insertions(+), 2086 deletions(-)
delete mode 100644 lib/std/fmtstream.zig
diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig
index c308fa681f8d21d2021beeacec62cf230bf4734b..1a0f39587e96212b6c75a927d7ce4b9653ceaedb 100644
--- a/lib/std/atomic/queue.zig
+++ b/lib/std/atomic/queue.zig
@@ -348,7 +348,7 @@ test "std.atomic.Queue dump" {
fbs.reset();
try queue.dumpToStream(fbs.outStream());
- var expected = try std.fmtstream.bufPrint(expected_buffer[0..],
+ var expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ (null)
\\tail: 0x{x}=1
@@ -368,7 +368,7 @@ test "std.atomic.Queue dump" {
fbs.reset();
try queue.dumpToStream(fbs.outStream());
- expected = try std.fmtstream.bufPrint(expected_buffer[0..],
+ expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ 0x{x}=2
\\ (null)
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index 6d361bdb4ae1f9c107b2f89ce6c421d0d599ec2b..cf028f104ea4e64fe9c4dc58abacf697aa01de24 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -65,11 +65,11 @@ pub const Buffer = struct {
}
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
- const size = std.fmtstream.count(format, args) catch |err| switch (err) {
+ const size = std.fmt.count(format, args) catch |err| switch (err) {
error.Overflow => return error.OutOfMemory,
};
var self = try Buffer.initSize(allocator, size);
- assert((std.fmtstream.bufPrint(self.list.items, format, args) catch unreachable).len == size);
+ assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
return self;
}
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 5cac8c962276780eeca49c6ac5b9a4e2959819c4..c8cd6c05cf7bf5fc30362ddc96d97b69000936fb 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -426,27 +426,27 @@ pub const Version = struct {
pub fn parse(text: []const u8) !Version {
var it = std.mem.separate(text, ".");
return Version{
- .major = try std.fmtstream.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
- .minor = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
- .patch = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
+ .major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
+ .minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
+ .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
};
}
pub fn format(
self: Version,
comptime fmt: []const u8,
- options: std.fmtstream.FormatOptions,
+ options: std.fmt.FormatOptions,
out_stream: var,
) !void {
if (fmt.len == 0) {
if (self.patch == 0) {
if (self.minor == 0) {
- return std.fmtstream.format(out_stream, "{}", .{self.major});
+ return std.fmt.format(out_stream, "{}", .{self.major});
} else {
- return std.fmtstream.format(out_stream, "{}.{}", .{ self.major, self.minor });
+ return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
}
} else {
- return std.fmtstream.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
+ return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
}
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index a7525ba79545fc601ee17b6d2afee55d714efa49..5173015b38d038dac4cedf3bfc720cad0d7b76f5 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
///
/// If a formatted user type contains a function of the type
/// ```
-/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
+/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void
/// ```
/// with `?` being the type formatted, this function will be called instead of the default implementation.
/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
///
/// A user type may be a `struct`, `vector`, `union` or `enum` type.
pub fn format(
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ out_stream: var,
comptime fmt: []const u8,
args: var,
-) Errors!void {
+) !void {
const ArgSetType = u32;
if (@typeInfo(@TypeOf(args)) != .Struct) {
@compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
@@ -138,7 +136,7 @@ pub fn format(
.Start => switch (c) {
'{' => {
if (start_index < i) {
- try output(context, fmt[start_index..i]);
+ try out_stream.writeAll(fmt[start_index..i]);
}
start_index = i;
@@ -150,7 +148,7 @@ pub fn format(
},
'}' => {
if (start_index < i) {
- try output(context, fmt[start_index..i]);
+ try out_stream.writeAll(fmt[start_index..i]);
}
state = .CloseBrace;
},
@@ -185,9 +183,7 @@ pub fn format(
args[arg_to_print],
fmt[0..0],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
@@ -218,9 +214,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..i],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -265,9 +259,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..specifier_end],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -293,9 +285,7 @@ pub fn format(
args[arg_to_print],
fmt[specifier_start..specifier_end],
options,
- context,
- Errors,
- output,
+ out_stream,
default_max_depth,
);
state = .Start;
@@ -316,7 +306,7 @@ pub fn format(
}
}
if (start_index < fmt.len) {
- try output(context, fmt[start_index..]);
+ try out_stream.writeAll(fmt[start_index..]);
}
}
@@ -324,141 +314,131 @@ pub fn formatType(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ out_stream: var,
max_depth: usize,
-) Errors!void {
+) @TypeOf(out_stream).Error!void {
if (comptime std.mem.eql(u8, fmt, "*")) {
- try output(context, @typeName(@TypeOf(value).Child));
- try output(context, "@");
- try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);
+ try out_stream.writeAll(@typeName(@TypeOf(value).Child));
+ try out_stream.writeAll("@");
+ try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
return;
}
const T = @TypeOf(value);
+ if (comptime std.meta.trait.hasFn("format")(T)) {
+ return try value.format(fmt, options, out_stream);
+ }
+
switch (@typeInfo(T)) {
.ComptimeInt, .Int, .Float => {
- return formatValue(value, fmt, options, context, Errors, output);
+ return formatValue(value, fmt, options, out_stream);
},
.Void => {
- return output(context, "void");
+ return out_stream.writeAll("void");
},
.Bool => {
- return output(context, if (value) "true" else "false");
+ return out_stream.writeAll(if (value) "true" else "false");
},
.Optional => {
if (value) |payload| {
- return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ return formatType(payload, fmt, options, out_stream, max_depth);
} else {
- return output(context, "null");
+ return out_stream.writeAll("null");
}
},
.ErrorUnion => {
if (value) |payload| {
- return formatType(payload, fmt, options, context, Errors, output, max_depth);
+ return formatType(payload, fmt, options, out_stream, max_depth);
} else |err| {
- return formatType(err, fmt, options, context, Errors, output, max_depth);
+ return formatType(err, fmt, options, out_stream, max_depth);
}
},
.ErrorSet => {
- try output(context, "error.");
- return output(context, @errorName(value));
+ try out_stream.writeAll("error.");
+ return out_stream.writeAll(@errorName(value));
},
.Enum => |enumInfo| {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
- }
-
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (enumInfo.is_exhaustive) {
- try output(context, ".");
- try output(context, @tagName(value));
+ try out_stream.writeAll(".");
+ try out_stream.writeAll(@tagName(value));
} else {
// TODO: when @tagName works on exhaustive enums print known enum strings
- try output(context, "(");
- try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
- try output(context, ")");
+ try out_stream.writeAll("(");
+ try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
+ try out_stream.writeAll(")");
}
},
.Union => {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
- }
-
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
- return output(context, "{ ... }");
+ return out_stream.writeAll("{ ... }");
}
const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| {
- try output(context, "{ .");
- try output(context, @tagName(@as(UnionTagType, value)));
- try output(context, " = ");
+ try out_stream.writeAll("{ .");
+ try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
+ try out_stream.writeAll(" = ");
inline for (info.fields) |u_field| {
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
- try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);
+ try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
}
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
} else {
- try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
+ try format(out_stream, "@{x}", .{@ptrToInt(&value)});
}
},
.Struct => |StructT| {
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return value.format(fmt, options, context, Errors, output);
- }
-
- try output(context, @typeName(T));
+ try out_stream.writeAll(@typeName(T));
if (max_depth == 0) {
- return output(context, "{ ... }");
+ return out_stream.writeAll("{ ... }");
}
- try output(context, "{");
+ try out_stream.writeAll("{");
inline for (StructT.fields) |f, i| {
if (i == 0) {
- try output(context, " .");
+ try out_stream.writeAll(" .");
} else {
- try output(context, ", .");
+ try out_stream.writeAll(", .");
}
- try output(context, f.name);
- try output(context, " = ");
- try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
+ try out_stream.writeAll(f.name);
+ try out_stream.writeAll(" = ");
+ try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => switch (@typeInfo(ptr_info.child)) {
.Array => |info| {
if (info.child == u8) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
},
.Enum, .Union, .Struct => {
- return formatType(value.*, fmt, options, context, Errors, output, max_depth);
+ return formatType(value.*, fmt, options, out_stream, max_depth);
},
- else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
+ else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
},
.Many, .C => {
if (ptr_info.sentinel) |sentinel| {
- return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);
+ return formatType(mem.span(value), fmt, options, out_stream, max_depth);
}
if (ptr_info.child == u8) {
if (fmt.len > 0 and fmt[0] == 's') {
- return formatText(mem.span(value), fmt, options, context, Errors, output);
+ return formatText(mem.span(value), fmt, options, out_stream);
}
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
},
.Slice => {
if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
if (ptr_info.child == u8) {
- return formatText(value, fmt, options, context, Errors, output);
+ return formatText(value, fmt, options, out_stream);
}
- return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
+ return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
},
},
.Array => |info| {
@@ -473,27 +453,27 @@ pub fn formatType(
.sentinel = null,
},
});
- return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);
+ return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
},
.Vector => {
const len = @typeInfo(T).Vector.len;
- try output(context, "{ ");
+ try out_stream.writeAll("{ ");
var i: usize = 0;
while (i < len) : (i += 1) {
- try formatValue(value[i], fmt, options, context, Errors, output);
+ try formatValue(value[i], fmt, options, out_stream);
if (i < len - 1) {
- try output(context, ", ");
+ try out_stream.writeAll(", ");
}
}
- try output(context, " }");
+ try out_stream.writeAll(" }");
},
.Fn => {
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
+ return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
},
- .Type => return output(context, @typeName(T)),
+ .Type => return out_stream.writeAll(@typeName(T)),
.EnumLiteral => {
const buffer = [_]u8{'.'} ++ @tagName(value);
- return formatType(buffer, fmt, options, context, Errors, output, max_depth);
+ return formatType(buffer, fmt, options, out_stream, max_depth);
},
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
}
@@ -503,21 +483,19 @@ fn formatValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (comptime std.mem.eql(u8, fmt, "B")) {
- return formatBytes(value, options, 1000, context, Errors, output);
+ return formatBytes(value, options, 1000, out_stream);
} else if (comptime std.mem.eql(u8, fmt, "Bi")) {
- return formatBytes(value, options, 1024, context, Errors, output);
+ return formatBytes(value, options, 1024, out_stream);
}
const T = @TypeOf(value);
switch (@typeInfo(T)) {
- .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
- .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
- .Bool => return output(context, if (value) "true" else "false"),
+ .Float => return formatFloatValue(value, fmt, options, out_stream),
+ .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
+ .Bool => return out_stream.writeAll(if (value) "true" else "false"),
else => comptime unreachable,
}
}
@@ -526,10 +504,8 @@ pub fn formatIntValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
comptime var radix = 10;
comptime var uppercase = false;
@@ -544,7 +520,7 @@ pub fn formatIntValue(
uppercase = false;
} else if (comptime std.mem.eql(u8, fmt, "c")) {
if (@TypeOf(int_value).bit_count <= 8) {
- return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);
+ return formatAsciiChar(@as(u8, int_value), options, out_stream);
} else {
@compileError("Cannot print integer that is larger than 8 bits as a ascii");
}
@@ -561,21 +537,19 @@ pub fn formatIntValue(
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
- return formatInt(int_value, radix, uppercase, options, context, Errors, output);
+ return formatInt(int_value, radix, uppercase, options, out_stream);
}
fn formatFloatValue(
value: var,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
- return formatFloatScientific(value, options, context, Errors, output);
+ return formatFloatScientific(value, options, out_stream);
} else if (comptime std.mem.eql(u8, fmt, "d")) {
- return formatFloatDecimal(value, options, context, Errors, output);
+ return formatFloatDecimal(value, options, out_stream);
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
@@ -585,17 +559,15 @@ pub fn formatText(
bytes: []const u8,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (fmt.len == 0) {
- return output(context, bytes);
+ return out_stream.writeAll(bytes);
} else if (comptime std.mem.eql(u8, fmt, "s")) {
- return formatBuf(bytes, options, context, Errors, output);
+ return formatBuf(bytes, options, out_stream);
} else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
for (bytes) |c| {
- try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);
+ try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
}
return;
} else {
@@ -606,27 +578,23 @@ pub fn formatText(
pub fn formatAsciiChar(
c: u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
- return output(context, @as(*const [1]u8, &c)[0..]);
+ out_stream: var,
+) !void {
+ return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
}
pub fn formatBuf(
buf: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
- try output(context, buf);
+ out_stream: var,
+) !void {
+ try out_stream.writeAll(buf);
const width = options.width orelse 0;
var leftover_padding = if (width > buf.len) (width - buf.len) else return;
const pad_byte: u8 = options.fill;
while (leftover_padding > 0) : (leftover_padding -= 1) {
- try output(context, @as(*const [1]u8, &pad_byte)[0..1]);
+ try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
}
}
@@ -636,40 +604,38 @@ pub fn formatBuf(
pub fn formatFloatScientific(
value: var,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
var x = @floatCast(f64, value);
// Errol doesn't handle these special cases.
if (math.signbit(x)) {
- try output(context, "-");
+ try out_stream.writeAll("-");
x = -x;
}
if (math.isNan(x)) {
- return output(context, "nan");
+ return out_stream.writeAll("nan");
}
if (math.isPositiveInf(x)) {
- return output(context, "inf");
+ return out_stream.writeAll("inf");
}
if (x == 0.0) {
- try output(context, "0");
+ try out_stream.writeAll("0");
if (options.precision) |precision| {
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var i: usize = 0;
while (i < precision) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
- try output(context, ".0");
+ try out_stream.writeAll(".0");
}
- try output(context, "e+00");
+ try out_stream.writeAll("e+00");
return;
}
@@ -679,50 +645,50 @@ pub fn formatFloatScientific(
if (options.precision) |precision| {
errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
- try output(context, float_decimal.digits[0..1]);
+ try out_stream.writeAll(float_decimal.digits[0..1]);
// {e0} case prints no `.`
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var printed: usize = 0;
if (float_decimal.digits.len > 1) {
const num_digits = math.min(float_decimal.digits.len, precision + 1);
- try output(context, float_decimal.digits[1..num_digits]);
+ try out_stream.writeAll(float_decimal.digits[1..num_digits]);
printed += num_digits - 1;
}
while (printed < precision) : (printed += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
- try output(context, float_decimal.digits[0..1]);
- try output(context, ".");
+ try out_stream.writeAll(float_decimal.digits[0..1]);
+ try out_stream.writeAll(".");
if (float_decimal.digits.len > 1) {
const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
- try output(context, float_decimal.digits[1..num_digits]);
+ try out_stream.writeAll(float_decimal.digits[1..num_digits]);
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
- try output(context, "e");
+ try out_stream.writeAll("e");
const exp = float_decimal.exp - 1;
if (exp >= 0) {
- try output(context, "+");
+ try out_stream.writeAll("+");
if (exp > -10 and exp < 10) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
- try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
} else {
- try output(context, "-");
+ try out_stream.writeAll("-");
if (exp > -10 and exp < 10) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
- try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
+ try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
}
}
@@ -731,36 +697,34 @@ pub fn formatFloatScientific(
pub fn formatFloatDecimal(
value: var,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
var x = @as(f64, value);
// Errol doesn't handle these special cases.
if (math.signbit(x)) {
- try output(context, "-");
+ try out_stream.writeAll("-");
x = -x;
}
if (math.isNan(x)) {
- return output(context, "nan");
+ return out_stream.writeAll("nan");
}
if (math.isPositiveInf(x)) {
- return output(context, "inf");
+ return out_stream.writeAll("inf");
}
if (x == 0.0) {
- try output(context, "0");
+ try out_stream.writeAll("0");
if (options.precision) |precision| {
if (precision != 0) {
- try output(context, ".");
+ try out_stream.writeAll(".");
var i: usize = 0;
while (i < precision) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, ".0");
+ try out_stream.writeAll(".0");
}
}
@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(
if (num_digits_whole > 0) {
// We may have to zero pad, for instance 1e4 requires zero padding.
- try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+ try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
var i = num_digits_whole_no_pad;
while (i < num_digits_whole) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
// {.0} special case doesn't want a trailing '.'
@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(
return;
}
- try output(context, ".");
+ try out_stream.writeAll(".");
// Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
var printed: usize = 0;
@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(
var i: usize = 0;
while (i < zeros_to_print) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
printed += 1;
}
@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(
// Remaining fractional portion, zero-padding if insufficient.
assert(precision >= printed);
if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
- try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
return;
} else {
- try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
printed += float_decimal.digits.len - num_digits_whole_no_pad;
while (printed < precision) : (printed += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
} else {
@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(
if (num_digits_whole > 0) {
// We may have to zero pad, for instance 1e4 requires zero padding.
- try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
+ try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
var i = num_digits_whole_no_pad;
while (i < num_digits_whole) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
} else {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
// Omit `.` if no fractional portion
@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(
return;
}
- try output(context, ".");
+ try out_stream.writeAll(".");
// Zero-fill until we reach significant digits or run out of precision.
if (float_decimal.exp < 0) {
@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(
var i: usize = 0;
while (i < zero_digit_count) : (i += 1) {
- try output(context, "0");
+ try out_stream.writeAll("0");
}
}
- try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
+ try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
}
}
@@ -875,12 +839,10 @@ pub fn formatBytes(
value: var,
options: FormatOptions,
comptime radix: usize,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
if (value == 0) {
- return output(context, "0B");
+ return out_stream.writeAll("0B");
}
const mags_si = " kMGTPEZY";
@@ -897,10 +859,10 @@ pub fn formatBytes(
else => unreachable,
};
- try formatFloatDecimal(new_value, options, context, Errors, output);
+ try formatFloatDecimal(new_value, options, out_stream);
if (suffix == ' ') {
- return output(context, "B");
+ return out_stream.writeAll("B");
}
const buf = switch (radix) {
@@ -908,7 +870,7 @@ pub fn formatBytes(
1024 => &[_]u8{ suffix, 'i', 'B' },
else => unreachable,
};
- return output(context, buf);
+ return out_stream.writeAll(buf);
}
pub fn formatInt(
@@ -916,10 +878,8 @@ pub fn formatInt(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
const int_value = if (@TypeOf(value) == comptime_int) blk: {
const Int = math.IntFittingRange(value, value);
break :blk @as(Int, value);
@@ -927,9 +887,9 @@ pub fn formatInt(
value;
if (@TypeOf(int_value).is_signed) {
- return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);
+ return formatIntSigned(int_value, base, uppercase, options, out_stream);
} else {
- return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);
+ return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
}
}
@@ -938,10 +898,8 @@ fn formatIntSigned(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
const new_options = FormatOptions{
.width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
.precision = options.precision,
@@ -950,15 +908,15 @@ fn formatIntSigned(
const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
const Uint = std.meta.IntType(false, bit_count);
if (value < 0) {
- try output(context, "-");
+ try out_stream.writeAll("-");
const new_value = math.absCast(value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
} else if (options.width == null or options.width.? == 0) {
- return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);
+ return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
} else {
- try output(context, "+");
+ try out_stream.writeAll("+");
const new_value = @intCast(Uint, value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
+ return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
}
}
@@ -967,10 +925,8 @@ fn formatIntUnsigned(
base: u8,
uppercase: bool,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
-) Errors!void {
+ out_stream: var,
+) !void {
assert(base >= 2);
var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
@@ -994,34 +950,23 @@ fn formatIntUnsigned(
const zero_byte: u8 = options.fill;
var leftover_padding = padding - index;
while (true) {
- try output(context, @as(*const [1]u8, &zero_byte)[0..]);
+ try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
leftover_padding -= 1;
if (leftover_padding == 0) break;
}
mem.set(u8, buf[0..index], options.fill);
- return output(context, &buf);
+ return out_stream.writeAll(&buf);
} else {
const padded_buf = buf[index - padding ..];
mem.set(u8, padded_buf[0..padding], options.fill);
- return output(context, padded_buf);
+ return out_stream.writeAll(padded_buf);
}
}
pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
- var context = FormatIntBuf{
- .out_buf = out_buf,
- .index = 0,
- };
- formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
- return context.index;
-}
-const FormatIntBuf = struct {
- out_buf: []u8,
- index: usize,
-};
-fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
- mem.copy(u8, context.out_buf[context.index..], bytes);
- context.index += bytes.len;
+ var fbs = std.io.fixedBufferStream(out_buf);
+ formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
+ return fbs.pos;
}
pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
@@ -1121,44 +1066,40 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
};
}
-const BufPrintContext = struct {
- remaining: []u8,
-};
-
-fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
- if (context.remaining.len < bytes.len) {
- mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
- return error.BufferTooSmall;
- }
- mem.copy(u8, context.remaining, bytes);
- context.remaining = context.remaining[bytes.len..];
-}
-
pub const BufPrintError = error{
/// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
BufferTooSmall,
};
pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
- var context = BufPrintContext{ .remaining = buf };
- try format(&context, BufPrintError, bufPrintWrite, fmt, args);
- return buf[0 .. buf.len - context.remaining.len];
+ var fbs = std.io.fixedBufferStream(buf);
+ format(fbs.outStream(), fmt, args) catch |err| switch (err) {
+ error.NoSpaceLeft => return error.BufferTooSmall,
+ };
+ //TODO: should we change one of these return signatures?
+ //return fbs.getWritten();
+ return buf[0..fbs.pos];
+}
+
+// Count the characters needed for format. Useful for preallocating memory
+pub fn count(comptime fmt: []const u8, args: var) !usize {
+ var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
+ format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
+ return std.math.cast(usize, counting_stream.bytes_written);
}
pub const AllocPrintError = error{OutOfMemory};
pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- var size: usize = 0;
- format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
+ const size = count(fmt, args) catch |err| switch (err) {
+ // Output too long. Can't possibly allocate enough memory to display it.
+ error.Overflow => return error.OutOfMemory,
+ };
const buf = try allocator.alloc(u8, size);
return bufPrint(buf, fmt, args) catch |err| switch (err) {
error.BufferTooSmall => unreachable, // we just counted the size above
};
}
-fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
- size.* += bytes.len;
-}
-
pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
const result = try allocPrint(allocator, fmt ++ "\x00", args);
return result[0 .. result.len - 1 :0];
@@ -1251,20 +1192,17 @@ test "int.padded" {
test "buffer" {
{
var buf1: [32]u8 = undefined;
- var context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- var res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1234"));
+ var fbs = std.io.fixedBufferStream(&buf1);
+ try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "a"));
+ fbs.reset();
+ try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1100"));
+ fbs.reset();
+ try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
}
}
@@ -1449,14 +1387,12 @@ test "custom" {
self: SelfType,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
- ) Errors!void {
+ out_stream: var,
+ ) !void {
if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
- return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
} else if (comptime std.mem.eql(u8, fmt, "d")) {
- return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y });
+ return std.fmt.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
} else {
@compileError("Unknown format character: '" ++ fmt ++ "'");
}
@@ -1640,10 +1576,10 @@ test "hexToBytes" {
test "formatIntValue with comptime_int" {
const value: comptime_int = 123456789123456789;
- var buf = std.ArrayList(u8).init(std.testing.allocator);
- defer buf.deinit();
- try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
- std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
+ var buf: [20]u8 = undefined;
+ var fbs = std.io.fixedBufferStream(&buf);
+ try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
}
test "formatType max_depth" {
@@ -1656,12 +1592,10 @@ test "formatType max_depth" {
self: SelfType,
comptime fmt: []const u8,
options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) Errors!void,
- ) Errors!void {
+ out_stream: var,
+ ) !void {
if (fmt.len == 0) {
- return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
+ return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
@@ -1695,25 +1629,22 @@ test "formatType max_depth" {
inst.a = &inst;
inst.tu.ptr = &inst.tu;
- var buf0 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf0.deinit();
- try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
- std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+ var buf: [1000]u8 = undefined;
+ var fbs = std.io.fixedBufferStream(&buf);
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
- var buf1 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf1.deinit();
- try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
- std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
- var buf2 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf2.deinit();
- try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
- std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
- var buf3 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf3.deinit();
- try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
- std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+ fbs.reset();
+ try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
+ std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
}
test "positional" {
diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig
deleted file mode 100644
index 93734d42aa334c2e476dcfc00a0b3c455211fc6e..0000000000000000000000000000000000000000
--- a/lib/std/fmtstream.zig
+++ /dev/null
@@ -1,1685 +0,0 @@
-const std = @import("std.zig");
-const math = std.math;
-const assert = std.debug.assert;
-const mem = std.mem;
-const builtin = @import("builtin");
-const errol = @import("fmt/errol.zig");
-const lossyCast = std.math.lossyCast;
-
-pub const default_max_depth = 3;
-
-pub const Alignment = enum {
- Left,
- Center,
- Right,
-};
-
-pub const FormatOptions = struct {
- precision: ?usize = null,
- width: ?usize = null,
- alignment: ?Alignment = null,
- fill: u8 = ' ',
-};
-
-fn peekIsAlign(comptime fmt: []const u8) bool {
- // Should only be called during a state transition to the format segment.
- comptime assert(fmt[0] == ':');
-
- inline for (([_]u8{ 1, 2 })[0..]) |i| {
- if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {
- return true;
- }
- }
- return false;
-}
-
-/// Renders fmt string with args, calling output with slices of bytes.
-/// If `output` returns an error, the error is returned from `format` and
-/// `output` is not called again.
-///
-/// The format string must be comptime known and may contain placeholders following
-/// this format:
-/// `{[position][specifier]:[fill][alignment][width].[precision]}`
-///
-/// Each word between `[` and `]` is a parameter you have to replace with something:
-///
-/// - *position* is the index of the argument that should be inserted
-/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
-/// - *fill* is a single character which is used to pad the formatted text
-/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned
-/// - *width* is the total width of the field in characters
-/// - *precision* specifies how many decimals a formatted number should have
-///
-/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when
-/// all parameters after the separator are omitted.
-/// Only exception is the *fill* parameter. If *fill* is required, one has to specify *alignment* as well, as otherwise
-/// the digits after `:` is interpreted as *width*, not *fill*.
-///
-/// The *specifier* has several options for types:
-/// - `x` and `X`:
-/// - format the non-numeric value as a string of bytes in hexadecimal notation ("binary dump") in either lower case or upper case
-/// - output numeric value in hexadecimal notation
-/// - `s`: print a pointer-to-many as a c-string, use zero-termination
-/// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values.
-/// - `e`: output floating point value in scientific notation
-/// - `d`: output numeric value in decimal notation
-/// - `b`: output integer value in binary notation
-/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
-/// - `*`: output the address of the value instead of the value itself.
-///
-/// If a formatted user type contains a function of the type
-/// ```
-/// fn format(value: ?, comptime fmt: []const u8, options: std.fmtstream.FormatOptions, out_stream: var) !void
-/// ```
-/// with `?` being the type formatted, this function will be called instead of the default implementation.
-/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
-///
-/// A user type may be a `struct`, `vector`, `union` or `enum` type.
-pub fn format(
- out_stream: var,
- comptime fmt: []const u8,
- args: var,
-) !void {
- const ArgSetType = u32;
- if (@typeInfo(@TypeOf(args)) != .Struct) {
- @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
- }
- if (args.len > ArgSetType.bit_count) {
- @compileError("32 arguments max are supported per format call");
- }
-
- const State = enum {
- Start,
- Positional,
- CloseBrace,
- Specifier,
- FormatFillAndAlign,
- FormatWidth,
- FormatPrecision,
- };
-
- comptime var start_index = 0;
- comptime var state = State.Start;
- comptime var maybe_pos_arg: ?comptime_int = null;
- comptime var specifier_start = 0;
- comptime var specifier_end = 0;
- comptime var options = FormatOptions{};
- comptime var arg_state: struct {
- next_arg: usize = 0,
- used_args: ArgSetType = 0,
- args_len: usize = args.len,
-
- fn hasUnusedArgs(comptime self: *@This()) bool {
- return (@popCount(ArgSetType, self.used_args) != self.args_len);
- }
-
- fn nextArg(comptime self: *@This(), comptime pos_arg: ?comptime_int) comptime_int {
- const next_idx = pos_arg orelse blk: {
- const arg = self.next_arg;
- self.next_arg += 1;
- break :blk arg;
- };
-
- if (next_idx >= self.args_len) {
- @compileError("Too few arguments");
- }
-
- // Mark this argument as used
- self.used_args |= 1 << next_idx;
-
- return next_idx;
- }
- } = .{};
-
- inline for (fmt) |c, i| {
- switch (state) {
- .Start => switch (c) {
- '{' => {
- if (start_index < i) {
- try out_stream.writeAll(fmt[start_index..i]);
- }
-
- start_index = i;
- specifier_start = i + 1;
- specifier_end = i + 1;
- maybe_pos_arg = null;
- state = .Positional;
- options = FormatOptions{};
- },
- '}' => {
- if (start_index < i) {
- try out_stream.writeAll(fmt[start_index..i]);
- }
- state = .CloseBrace;
- },
- else => {},
- },
- .Positional => switch (c) {
- '{' => {
- state = .Start;
- start_index = i;
- },
- ':' => {
- state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
- specifier_end = i;
- },
- '0'...'9' => {
- if (maybe_pos_arg == null) {
- maybe_pos_arg = 0;
- }
-
- maybe_pos_arg.? *= 10;
- maybe_pos_arg.? += c - '0';
- specifier_start = i + 1;
-
- if (maybe_pos_arg.? >= args.len) {
- @compileError("Positional value refers to non-existent argument");
- }
- },
- '}' => {
- const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
-
- try formatType(
- args[arg_to_print],
- fmt[0..0],
- options,
- out_stream,
- default_max_depth,
- );
-
- state = .Start;
- start_index = i + 1;
- },
- else => {
- state = .Specifier;
- specifier_start = i;
- },
- },
- .CloseBrace => switch (c) {
- '}' => {
- state = .Start;
- start_index = i;
- },
- else => @compileError("Single '}' encountered in format string"),
- },
- .Specifier => switch (c) {
- ':' => {
- specifier_end = i;
- state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
- },
- '}' => {
- const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
-
- try formatType(
- args[arg_to_print],
- fmt[specifier_start..i],
- options,
- out_stream,
- default_max_depth,
- );
- state = .Start;
- start_index = i + 1;
- },
- else => {},
- },
- // Only entered if the format string contains a fill/align segment.
- .FormatFillAndAlign => switch (c) {
- '<' => {
- options.alignment = Alignment.Left;
- state = .FormatWidth;
- },
- '^' => {
- options.alignment = Alignment.Center;
- state = .FormatWidth;
- },
- '>' => {
- options.alignment = Alignment.Right;
- state = .FormatWidth;
- },
- else => {
- options.fill = c;
- },
- },
- .FormatWidth => switch (c) {
- '0'...'9' => {
- if (options.width == null) {
- options.width = 0;
- }
-
- options.width.? *= 10;
- options.width.? += c - '0';
- },
- '.' => {
- state = .FormatPrecision;
- },
- '}' => {
- const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
-
- try formatType(
- args[arg_to_print],
- fmt[specifier_start..specifier_end],
- options,
- out_stream,
- default_max_depth,
- );
- state = .Start;
- start_index = i + 1;
- },
- else => {
- @compileError("Unexpected character in width value: " ++ [_]u8{c});
- },
- },
- .FormatPrecision => switch (c) {
- '0'...'9' => {
- if (options.precision == null) {
- options.precision = 0;
- }
-
- options.precision.? *= 10;
- options.precision.? += c - '0';
- },
- '}' => {
- const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
-
- try formatType(
- args[arg_to_print],
- fmt[specifier_start..specifier_end],
- options,
- out_stream,
- default_max_depth,
- );
- state = .Start;
- start_index = i + 1;
- },
- else => {
- @compileError("Unexpected character in precision value: " ++ [_]u8{c});
- },
- },
- }
- }
- comptime {
- if (comptime arg_state.hasUnusedArgs()) {
- @compileError("Unused arguments");
- }
- if (state != State.Start) {
- @compileError("Incomplete format string: " ++ fmt);
- }
- }
- if (start_index < fmt.len) {
- try out_stream.writeAll(fmt[start_index..]);
- }
-}
-
-pub fn formatType(
- value: var,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
- max_depth: usize,
-) @TypeOf(out_stream).Error!void {
- if (comptime std.mem.eql(u8, fmt, "*")) {
- try out_stream.writeAll(@typeName(@TypeOf(value).Child));
- try out_stream.writeAll("@");
- try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
- return;
- }
-
- const T = @TypeOf(value);
- if (comptime std.meta.trait.hasFn("format")(T)) {
- return try value.format(fmt, options, out_stream);
- }
-
- switch (@typeInfo(T)) {
- .ComptimeInt, .Int, .Float => {
- return formatValue(value, fmt, options, out_stream);
- },
- .Void => {
- return out_stream.writeAll("void");
- },
- .Bool => {
- return out_stream.writeAll(if (value) "true" else "false");
- },
- .Optional => {
- if (value) |payload| {
- return formatType(payload, fmt, options, out_stream, max_depth);
- } else {
- return out_stream.writeAll("null");
- }
- },
- .ErrorUnion => {
- if (value) |payload| {
- return formatType(payload, fmt, options, out_stream, max_depth);
- } else |err| {
- return formatType(err, fmt, options, out_stream, max_depth);
- }
- },
- .ErrorSet => {
- try out_stream.writeAll("error.");
- return out_stream.writeAll(@errorName(value));
- },
- .Enum => |enumInfo| {
- try out_stream.writeAll(@typeName(T));
- if (enumInfo.is_exhaustive) {
- try out_stream.writeAll(".");
- try out_stream.writeAll(@tagName(value));
- } else {
- // TODO: when @tagName works on exhaustive enums print known enum strings
- try out_stream.writeAll("(");
- try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
- try out_stream.writeAll(")");
- }
- },
- .Union => {
- try out_stream.writeAll(@typeName(T));
- if (max_depth == 0) {
- return out_stream.writeAll("{ ... }");
- }
- const info = @typeInfo(T).Union;
- if (info.tag_type) |UnionTagType| {
- try out_stream.writeAll("{ .");
- try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
- try out_stream.writeAll(" = ");
- inline for (info.fields) |u_field| {
- if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
- try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
- }
- }
- try out_stream.writeAll(" }");
- } else {
- try format(out_stream, "@{x}", .{@ptrToInt(&value)});
- }
- },
- .Struct => |StructT| {
- try out_stream.writeAll(@typeName(T));
- if (max_depth == 0) {
- return out_stream.writeAll("{ ... }");
- }
- try out_stream.writeAll("{");
- inline for (StructT.fields) |f, i| {
- if (i == 0) {
- try out_stream.writeAll(" .");
- } else {
- try out_stream.writeAll(", .");
- }
- try out_stream.writeAll(f.name);
- try out_stream.writeAll(" = ");
- try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
- }
- try out_stream.writeAll(" }");
- },
- .Pointer => |ptr_info| switch (ptr_info.size) {
- .One => switch (@typeInfo(ptr_info.child)) {
- .Array => |info| {
- if (info.child == u8) {
- return formatText(value, fmt, options, out_stream);
- }
- return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
- },
- .Enum, .Union, .Struct => {
- return formatType(value.*, fmt, options, out_stream, max_depth);
- },
- else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
- },
- .Many, .C => {
- if (ptr_info.sentinel) |sentinel| {
- return formatType(mem.span(value), fmt, options, out_stream, max_depth);
- }
- if (ptr_info.child == u8) {
- if (fmt.len > 0 and fmt[0] == 's') {
- return formatText(mem.span(value), fmt, options, out_stream);
- }
- }
- return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
- },
- .Slice => {
- if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
- return formatText(value, fmt, options, out_stream);
- }
- if (ptr_info.child == u8) {
- return formatText(value, fmt, options, out_stream);
- }
- return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
- },
- },
- .Array => |info| {
- const Slice = @Type(builtin.TypeInfo{
- .Pointer = .{
- .size = .Slice,
- .is_const = true,
- .is_volatile = false,
- .is_allowzero = false,
- .alignment = @alignOf(info.child),
- .child = info.child,
- .sentinel = null,
- },
- });
- return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
- },
- .Vector => {
- const len = @typeInfo(T).Vector.len;
- try out_stream.writeAll("{ ");
- var i: usize = 0;
- while (i < len) : (i += 1) {
- try formatValue(value[i], fmt, options, out_stream);
- if (i < len - 1) {
- try out_stream.writeAll(", ");
- }
- }
- try out_stream.writeAll(" }");
- },
- .Fn => {
- return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
- },
- .Type => return out_stream.writeAll(@typeName(T)),
- .EnumLiteral => {
- const buffer = [_]u8{'.'} ++ @tagName(value);
- return formatType(buffer, fmt, options, out_stream, max_depth);
- },
- else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
- }
-}
-
-fn formatValue(
- value: var,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- if (comptime std.mem.eql(u8, fmt, "B")) {
- return formatBytes(value, options, 1000, out_stream);
- } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
- return formatBytes(value, options, 1024, out_stream);
- }
-
- const T = @TypeOf(value);
- switch (@typeInfo(T)) {
- .Float => return formatFloatValue(value, fmt, options, out_stream),
- .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
- .Bool => return out_stream.writeAll(if (value) "true" else "false"),
- else => comptime unreachable,
- }
-}
-
-pub fn formatIntValue(
- value: var,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- comptime var radix = 10;
- comptime var uppercase = false;
-
- const int_value = if (@TypeOf(value) == comptime_int) blk: {
- const Int = math.IntFittingRange(value, value);
- break :blk @as(Int, value);
- } else
- value;
-
- if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
- radix = 10;
- uppercase = false;
- } else if (comptime std.mem.eql(u8, fmt, "c")) {
- if (@TypeOf(int_value).bit_count <= 8) {
- return formatAsciiChar(@as(u8, int_value), options, out_stream);
- } else {
- @compileError("Cannot print integer that is larger than 8 bits as a ascii");
- }
- } else if (comptime std.mem.eql(u8, fmt, "b")) {
- radix = 2;
- uppercase = false;
- } else if (comptime std.mem.eql(u8, fmt, "x")) {
- radix = 16;
- uppercase = false;
- } else if (comptime std.mem.eql(u8, fmt, "X")) {
- radix = 16;
- uppercase = true;
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
-
- return formatInt(int_value, radix, uppercase, options, out_stream);
-}
-
-fn formatFloatValue(
- value: var,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
- return formatFloatScientific(value, options, out_stream);
- } else if (comptime std.mem.eql(u8, fmt, "d")) {
- return formatFloatDecimal(value, options, out_stream);
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
-}
-
-pub fn formatText(
- bytes: []const u8,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- if (fmt.len == 0) {
- return out_stream.writeAll(bytes);
- } else if (comptime std.mem.eql(u8, fmt, "s")) {
- return formatBuf(bytes, options, out_stream);
- } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
- for (bytes) |c| {
- try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
- }
- return;
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
-}
-
-pub fn formatAsciiChar(
- c: u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
-}
-
-pub fn formatBuf(
- buf: []const u8,
- options: FormatOptions,
- out_stream: var,
-) !void {
- try out_stream.writeAll(buf);
-
- const width = options.width orelse 0;
- var leftover_padding = if (width > buf.len) (width - buf.len) else return;
- const pad_byte: u8 = options.fill;
- while (leftover_padding > 0) : (leftover_padding -= 1) {
- try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
- }
-}
-
-// Print a float in scientific notation to the specified precision. Null uses full precision.
-// It should be the case that every full precision, printed value can be re-parsed back to the
-// same type unambiguously.
-pub fn formatFloatScientific(
- value: var,
- options: FormatOptions,
- out_stream: var,
-) !void {
- var x = @floatCast(f64, value);
-
- // Errol doesn't handle these special cases.
- if (math.signbit(x)) {
- try out_stream.writeAll("-");
- x = -x;
- }
-
- if (math.isNan(x)) {
- return out_stream.writeAll("nan");
- }
- if (math.isPositiveInf(x)) {
- return out_stream.writeAll("inf");
- }
- if (x == 0.0) {
- try out_stream.writeAll("0");
-
- if (options.precision) |precision| {
- if (precision != 0) {
- try out_stream.writeAll(".");
- var i: usize = 0;
- while (i < precision) : (i += 1) {
- try out_stream.writeAll("0");
- }
- }
- } else {
- try out_stream.writeAll(".0");
- }
-
- try out_stream.writeAll("e+00");
- return;
- }
-
- var buffer: [32]u8 = undefined;
- var float_decimal = errol.errol3(x, buffer[0..]);
-
- if (options.precision) |precision| {
- errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
-
- try out_stream.writeAll(float_decimal.digits[0..1]);
-
- // {e0} case prints no `.`
- if (precision != 0) {
- try out_stream.writeAll(".");
-
- var printed: usize = 0;
- if (float_decimal.digits.len > 1) {
- const num_digits = math.min(float_decimal.digits.len, precision + 1);
- try out_stream.writeAll(float_decimal.digits[1..num_digits]);
- printed += num_digits - 1;
- }
-
- while (printed < precision) : (printed += 1) {
- try out_stream.writeAll("0");
- }
- }
- } else {
- try out_stream.writeAll(float_decimal.digits[0..1]);
- try out_stream.writeAll(".");
- if (float_decimal.digits.len > 1) {
- const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
-
- try out_stream.writeAll(float_decimal.digits[1..num_digits]);
- } else {
- try out_stream.writeAll("0");
- }
- }
-
- try out_stream.writeAll("e");
- const exp = float_decimal.exp - 1;
-
- if (exp >= 0) {
- try out_stream.writeAll("+");
- if (exp > -10 and exp < 10) {
- try out_stream.writeAll("0");
- }
- try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
- } else {
- try out_stream.writeAll("-");
- if (exp > -10 and exp < 10) {
- try out_stream.writeAll("0");
- }
- try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
- }
-}
-
-// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
-// By default floats are printed at full precision (no rounding).
-pub fn formatFloatDecimal(
- value: var,
- options: FormatOptions,
- out_stream: var,
-) !void {
- var x = @as(f64, value);
-
- // Errol doesn't handle these special cases.
- if (math.signbit(x)) {
- try out_stream.writeAll("-");
- x = -x;
- }
-
- if (math.isNan(x)) {
- return out_stream.writeAll("nan");
- }
- if (math.isPositiveInf(x)) {
- return out_stream.writeAll("inf");
- }
- if (x == 0.0) {
- try out_stream.writeAll("0");
-
- if (options.precision) |precision| {
- if (precision != 0) {
- try out_stream.writeAll(".");
- var i: usize = 0;
- while (i < precision) : (i += 1) {
- try out_stream.writeAll("0");
- }
- } else {
- try out_stream.writeAll(".0");
- }
- }
-
- return;
- }
-
- // non-special case, use errol3
- var buffer: [32]u8 = undefined;
- var float_decimal = errol.errol3(x, buffer[0..]);
-
- if (options.precision) |precision| {
- errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal);
-
- // exp < 0 means the leading is always 0 as errol result is normalized.
- var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
-
- // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
- var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
-
- if (num_digits_whole > 0) {
- // We may have to zero pad, for instance 1e4 requires zero padding.
- try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
-
- var i = num_digits_whole_no_pad;
- while (i < num_digits_whole) : (i += 1) {
- try out_stream.writeAll("0");
- }
- } else {
- try out_stream.writeAll("0");
- }
-
- // {.0} special case doesn't want a trailing '.'
- if (precision == 0) {
- return;
- }
-
- try out_stream.writeAll(".");
-
- // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
- var printed: usize = 0;
-
- // Zero-fill until we reach significant digits or run out of precision.
- if (float_decimal.exp <= 0) {
- const zero_digit_count = @intCast(usize, -float_decimal.exp);
- const zeros_to_print = math.min(zero_digit_count, precision);
-
- var i: usize = 0;
- while (i < zeros_to_print) : (i += 1) {
- try out_stream.writeAll("0");
- printed += 1;
- }
-
- if (printed >= precision) {
- return;
- }
- }
-
- // Remaining fractional portion, zero-padding if insufficient.
- assert(precision >= printed);
- if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
- try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
- return;
- } else {
- try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
- printed += float_decimal.digits.len - num_digits_whole_no_pad;
-
- while (printed < precision) : (printed += 1) {
- try out_stream.writeAll("0");
- }
- }
- } else {
- // exp < 0 means the leading is always 0 as errol result is normalized.
- var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
-
- // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
- var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
-
- if (num_digits_whole > 0) {
- // We may have to zero pad, for instance 1e4 requires zero padding.
- try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
-
- var i = num_digits_whole_no_pad;
- while (i < num_digits_whole) : (i += 1) {
- try out_stream.writeAll("0");
- }
- } else {
- try out_stream.writeAll("0");
- }
-
- // Omit `.` if no fractional portion
- if (float_decimal.exp >= 0 and num_digits_whole_no_pad == float_decimal.digits.len) {
- return;
- }
-
- try out_stream.writeAll(".");
-
- // Zero-fill until we reach significant digits or run out of precision.
- if (float_decimal.exp < 0) {
- const zero_digit_count = @intCast(usize, -float_decimal.exp);
-
- var i: usize = 0;
- while (i < zero_digit_count) : (i += 1) {
- try out_stream.writeAll("0");
- }
- }
-
- try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
- }
-}
-
-pub fn formatBytes(
- value: var,
- options: FormatOptions,
- comptime radix: usize,
- out_stream: var,
-) !void {
- if (value == 0) {
- return out_stream.writeAll("0B");
- }
-
- const mags_si = " kMGTPEZY";
- const mags_iec = " KMGTPEZY";
- const magnitude = switch (radix) {
- 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags_si.len - 1),
- 1024 => math.min(math.log2(value) / 10, mags_iec.len - 1),
- else => unreachable,
- };
- const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
- const suffix = switch (radix) {
- 1000 => mags_si[magnitude],
- 1024 => mags_iec[magnitude],
- else => unreachable,
- };
-
- try formatFloatDecimal(new_value, options, out_stream);
-
- if (suffix == ' ') {
- return out_stream.writeAll("B");
- }
-
- const buf = switch (radix) {
- 1000 => &[_]u8{ suffix, 'B' },
- 1024 => &[_]u8{ suffix, 'i', 'B' },
- else => unreachable,
- };
- return out_stream.writeAll(buf);
-}
-
-pub fn formatInt(
- value: var,
- base: u8,
- uppercase: bool,
- options: FormatOptions,
- out_stream: var,
-) !void {
- const int_value = if (@TypeOf(value) == comptime_int) blk: {
- const Int = math.IntFittingRange(value, value);
- break :blk @as(Int, value);
- } else
- value;
-
- if (@TypeOf(int_value).is_signed) {
- return formatIntSigned(int_value, base, uppercase, options, out_stream);
- } else {
- return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
- }
-}
-
-fn formatIntSigned(
- value: var,
- base: u8,
- uppercase: bool,
- options: FormatOptions,
- out_stream: var,
-) !void {
- const new_options = FormatOptions{
- .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
- .precision = options.precision,
- .fill = options.fill,
- };
- const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
- const Uint = std.meta.IntType(false, bit_count);
- if (value < 0) {
- try out_stream.writeAll("-");
- const new_value = math.absCast(value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
- } else if (options.width == null or options.width.? == 0) {
- return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
- } else {
- try out_stream.writeAll("+");
- const new_value = @intCast(Uint, value);
- return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
- }
-}
-
-fn formatIntUnsigned(
- value: var,
- base: u8,
- uppercase: bool,
- options: FormatOptions,
- out_stream: var,
-) !void {
- assert(base >= 2);
- var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
- const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
- const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits);
- var a: MinInt = value;
- var index: usize = buf.len;
-
- while (true) {
- const digit = a % base;
- index -= 1;
- buf[index] = digitToChar(@intCast(u8, digit), uppercase);
- a /= base;
- if (a == 0) break;
- }
-
- const digits_buf = buf[index..];
- const width = options.width orelse 0;
- const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0;
-
- if (padding > index) {
- const zero_byte: u8 = options.fill;
- var leftover_padding = padding - index;
- while (true) {
- try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
- leftover_padding -= 1;
- if (leftover_padding == 0) break;
- }
- mem.set(u8, buf[0..index], options.fill);
- return out_stream.writeAll(&buf);
- } else {
- const padded_buf = buf[index - padding ..];
- mem.set(u8, padded_buf[0..padding], options.fill);
- return out_stream.writeAll(padded_buf);
- }
-}
-
-pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
- var fbs = std.io.fixedBufferStream(out_buf);
- formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
- return fbs.pos;
-}
-
-pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
- if (!T.is_signed) return parseUnsigned(T, buf, radix);
- if (buf.len == 0) return @as(T, 0);
- if (buf[0] == '-') {
- return math.negate(try parseUnsigned(T, buf[1..], radix));
- } else if (buf[0] == '+') {
- return parseUnsigned(T, buf[1..], radix);
- } else {
- return parseUnsigned(T, buf, radix);
- }
-}
-
-test "parseInt" {
- std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
- std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
- std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
- std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
- std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
- std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
- std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
-}
-
-pub const ParseUnsignedError = error{
- /// The result cannot fit in the type specified
- Overflow,
-
- /// The input had a byte that was not a digit
- InvalidCharacter,
-};
-
-pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsignedError!T {
- var x: T = 0;
-
- for (buf) |c| {
- const digit = try charToDigit(c, radix);
-
- if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
- x = try math.add(T, x, try math.cast(T, digit));
- }
-
- return x;
-}
-
-test "parseUnsigned" {
- std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
- std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
- std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
-
- std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
- std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
-
- std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
-
- std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
- std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
-
- std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
- std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
-
- std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
-
- // these numbers should fit even though the radix itself doesn't fit in the destination type
- std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
- std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
- std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
- std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
- std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
- std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
-}
-
-pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
-
-test "parseFloat" {
- _ = @import("fmt/parse_float.zig");
-}
-
-pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
- const value = switch (c) {
- '0'...'9' => c - '0',
- 'A'...'Z' => c - 'A' + 10,
- 'a'...'z' => c - 'a' + 10,
- else => return error.InvalidCharacter,
- };
-
- if (value >= radix) return error.InvalidCharacter;
-
- return value;
-}
-
-fn digitToChar(digit: u8, uppercase: bool) u8 {
- return switch (digit) {
- 0...9 => digit + '0',
- 10...35 => digit + ((if (uppercase) @as(u8, 'A') else @as(u8, 'a')) - 10),
- else => unreachable,
- };
-}
-
-pub const BufPrintError = error{
- /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
- BufferTooSmall,
-};
-pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
- var fbs = std.io.fixedBufferStream(buf);
- format(fbs.outStream(), fmt, args) catch |err| switch (err) {
- error.NoSpaceLeft => return error.BufferTooSmall,
- };
- //TODO: should we change one of these return signatures?
- //return fbs.getWritten();
- return buf[0..fbs.pos];
-}
-
-// Count the characters needed for format. Useful for preallocating memory
-pub fn count(comptime fmt: []const u8, args: var) !usize {
- var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
- format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
- return std.math.cast(usize, counting_stream.bytes_written);
-}
-
-pub const AllocPrintError = error{OutOfMemory};
-
-pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- const size = count(fmt, args) catch |err| switch (err) {
- // Output too long. Can't possibly allocate enough memory to display it.
- error.Overflow => return error.OutOfMemory,
- };
- const buf = try allocator.alloc(u8, size);
- return bufPrint(buf, fmt, args) catch |err| switch (err) {
- error.BufferTooSmall => unreachable, // we just counted the size above
- };
-}
-
-pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
- const result = try allocPrint(allocator, fmt ++ "\x00", args);
- return result[0 .. result.len - 1 :0];
-}
-
-test "bufPrintInt" {
- var buffer: [100]u8 = undefined;
- const buf = buffer[0..];
-
- std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, false, FormatOptions{}));
-
- std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}));
- std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}));
- std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}));
- std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}));
-
- std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}));
-
- std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }));
- std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }));
- std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }));
-
- std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }));
- std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }));
-}
-
-fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
- return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
-}
-
-test "parse u64 digit too big" {
- _ = parseUnsigned(u64, "123a", 10) catch |err| {
- if (err == error.InvalidCharacter) return;
- unreachable;
- };
- unreachable;
-}
-
-test "parse unsigned comptime" {
- comptime {
- std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
- }
-}
-
-test "optional" {
- {
- const value: ?i32 = 1234;
- try testFmt("optional: 1234\n", "optional: {}\n", .{value});
- }
- {
- const value: ?i32 = null;
- try testFmt("optional: null\n", "optional: {}\n", .{value});
- }
-}
-
-test "error" {
- {
- const value: anyerror!i32 = 1234;
- try testFmt("error union: 1234\n", "error union: {}\n", .{value});
- }
- {
- const value: anyerror!i32 = error.InvalidChar;
- try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
- }
-}
-
-test "int.small" {
- {
- const value: u3 = 0b101;
- try testFmt("u3: 5\n", "u3: {}\n", .{value});
- }
-}
-
-test "int.specifier" {
- {
- const value: u8 = 'a';
- try testFmt("u8: a\n", "u8: {c}\n", .{value});
- }
- {
- const value: u8 = 0b1100;
- try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
- }
-}
-
-test "int.padded" {
- try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
- try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
-}
-
-test "buffer" {
- {
- var buf1: [32]u8 = undefined;
- var fbs = std.io.fixedBufferStream(&buf1);
- try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
-
- fbs.reset();
- try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
-
- fbs.reset();
- try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
- }
-}
-
-test "array" {
- {
- const value: [3]u8 = "abc".*;
- try testFmt("array: abc\n", "array: {}\n", .{value});
- try testFmt("array: abc\n", "array: {}\n", .{&value});
-
- var buf: [100]u8 = undefined;
- try testFmt(
- try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
- "array: {*}\n",
- .{&value},
- );
- }
-}
-
-test "slice" {
- {
- const value: []const u8 = "abc";
- try testFmt("slice: abc\n", "slice: {}\n", .{value});
- }
- {
- const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
- try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
- }
-
- try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
- try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
-}
-
-test "pointer" {
- {
- const value = @intToPtr(*align(1) i32, 0xdeadbeef);
- try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
- try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
-}
-
-test "cstr" {
- try testFmt(
- "cstr: Test C\n",
- "cstr: {s}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
- try testFmt(
- "cstr: Test C \n",
- "cstr: {s:10}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
-}
-
-test "filesize" {
- try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
- try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
-}
-
-test "struct" {
- {
- const Struct = struct {
- field: u8,
- };
- const value = Struct{ .field = 42 };
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
- }
- {
- const Struct = struct {
- a: u0,
- b: u1,
- };
- const value = Struct{ .a = 0, .b = 1 };
- try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
- }
-}
-
-test "enum" {
- const Enum = enum {
- One,
- Two,
- };
- const value = Enum.Two;
- try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
- try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
-}
-
-test "non-exhaustive enum" {
- const Enum = enum(u16) {
- One = 0x000f,
- Two = 0xbeef,
- _,
- };
- try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
- try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
- try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
- try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
- try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
- try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
-}
-
-test "float.scientific" {
- try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
- try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
- try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
- try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.scientific.precision" {
- try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
- try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
- try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
- // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
- // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
- try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
-}
-
-test "float.special" {
- try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
- // negative nan is not defined by IEE 754,
- // and ARM thus normalizes it to positive nan
- if (builtin.arch != builtin.Arch.arm) {
- try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
- }
- try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
- try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
-}
-
-test "float.decimal" {
- try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
- try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
- try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
- try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
- // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
- // -11.12339... is rounded back up to -11.1234
- try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
- try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
- try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
- try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
- try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
- try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
- try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.libc.sanity" {
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
- try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
- try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
- try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
-
- // libc differences
- //
- // This is 0.015625 exactly according to gdb. We thus round down,
- // however glibc rounds up for some reason. This occurs for all
- // floats of the form x.yyyy25 on a precision point.
- try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
- // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
- // also rounds to 630 so I'm inclined to believe libc is not
- // optimal here.
- try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
-}
-
-test "custom" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
- ) !void {
- if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else if (comptime std.mem.eql(u8, fmt, "d")) {
- return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
- } else {
- @compileError("Unknown format character: '" ++ fmt ++ "'");
- }
- }
- };
-
- var buf1: [32]u8 = undefined;
- var value = Vec2{
- .x = 10.2,
- .y = 2.22,
- };
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
-
- // same thing but not passing a pointer
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
-}
-
-test "struct" {
- const S = struct {
- a: u32,
- b: anyerror,
- };
-
- const inst = S{
- .a = 456,
- .b = error.Unused,
- };
-
- try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
-}
-
-test "union" {
- const TU = union(enum) {
- float: f32,
- int: u32,
- };
-
- const UU = union {
- float: f32,
- int: u32,
- };
-
- const EU = extern union {
- float: f32,
- int: u32,
- };
-
- const tu_inst = TU{ .int = 123 };
- const uu_inst = UU{ .int = 456 };
- const eu_inst = EU{ .float = 321.123 };
-
- try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
-
- var buf: [100]u8 = undefined;
- const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
-
- const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
-}
-
-test "enum" {
- const E = enum {
- One,
- Two,
- Three,
- };
-
- const inst = E.Two;
-
- try testFmt("E.Two", "{}", .{inst});
-}
-
-test "struct.self-referential" {
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- };
-
- var inst = S{
- .a = null,
- };
- inst.a = &inst;
-
- try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
-}
-
-test "struct.zero-size" {
- const A = struct {
- fn foo() void {}
- };
- const B = struct {
- a: A,
- c: i32,
- };
-
- const a = A{};
- const b = B{ .a = a, .c = 0 };
-
- try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
-}
-
-test "bytes.hex" {
- const some_bytes = "\xCA\xFE\xBA\xBE";
- try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
- try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
- //Test Slices
- try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
- try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
- const bytes_with_zeros = "\x00\x0E\xBA\xBE";
- try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
-}
-
-fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
- var buf: [100]u8 = undefined;
- const result = try bufPrint(buf[0..], template, args);
- if (mem.eql(u8, result, expected)) return;
-
- std.debug.warn("\n====== expected this output: =========\n", .{});
- std.debug.warn("{}", .{expected});
- std.debug.warn("\n======== instead found this: =========\n", .{});
- std.debug.warn("{}", .{result});
- std.debug.warn("\n======================================\n", .{});
- return error.TestFailed;
-}
-
-pub fn trim(buf: []const u8) []const u8 {
- var start: usize = 0;
- while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
-
- var end: usize = buf.len;
- while (true) {
- if (end > start) {
- const new_end = end - 1;
- if (isWhiteSpace(buf[new_end])) {
- end = new_end;
- continue;
- }
- }
- break;
- }
- return buf[start..end];
-}
-
-test "trim" {
- std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
- std.testing.expect(mem.eql(u8, "", trim(" ")));
- std.testing.expect(mem.eql(u8, "", trim("")));
- std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
- std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
-}
-
-pub fn isWhiteSpace(byte: u8) bool {
- return switch (byte) {
- ' ', '\t', '\n', '\r' => true,
- else => false,
- };
-}
-
-pub fn hexToBytes(out: []u8, input: []const u8) !void {
- if (out.len * 2 < input.len)
- return error.InvalidLength;
-
- var in_i: usize = 0;
- while (in_i != input.len) : (in_i += 2) {
- const hi = try charToDigit(input[in_i], 16);
- const lo = try charToDigit(input[in_i + 1], 16);
- out[in_i / 2] = (hi << 4) | lo;
- }
-}
-
-test "hexToBytes" {
- const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
- var pb: [32]u8 = undefined;
- try hexToBytes(pb[0..], test_hex_str);
- try testFmt(test_hex_str, "{X}", .{pb});
-}
-
-test "formatIntValue with comptime_int" {
- const value: comptime_int = 123456789123456789;
-
- var buf: [20]u8 = undefined;
- var fbs = std.io.fixedBufferStream(&buf);
- try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
-}
-
-test "formatType max_depth" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- out_stream: var,
- ) !void {
- if (fmt.len == 0) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
- }
- };
- const E = enum {
- One,
- Two,
- Three,
- };
- const TU = union(enum) {
- const SelfType = @This();
- float: f32,
- int: u32,
- ptr: ?*SelfType,
- };
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- tu: TU,
- e: E,
- vec: Vec2,
- };
-
- var inst = S{
- .a = null,
- .tu = TU{ .ptr = null },
- .e = E.Two,
- .vec = Vec2{ .x = 10.2, .y = 2.22 },
- };
- inst.a = &inst;
- inst.tu.ptr = &inst.tu;
-
- var buf: [1000]u8 = undefined;
- var fbs = std.io.fixedBufferStream(&buf);
- try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
-
- fbs.reset();
- try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- fbs.reset();
- try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- fbs.reset();
- try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
- std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
-}
-
-test "positional" {
- try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
- try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
- try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
-}
-
-test "positional with specifier" {
- try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
-}
-
-test "positional/alignment/width/precision" {
- try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
-}
-
-test "vector" {
- // https://github.com/ziglang/zig/issues/3317
- if (builtin.arch == .mipsel) return error.SkipZigTest;
-
- const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
- const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
- const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
-
- try testFmt("{ true, false, true, false }", "{}", .{vbool});
- try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
- try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
- try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
- try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
- try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
- try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
-}
-
-test "enum-literal" {
- try testFmt(".hello_world", "{}", .{.hello_world});
-}
diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig
index cb232a3e3e3e18d540988fee4e664d1329a4b496..1e1e71e3eb21faee6fc4d8601f795eded644199e 100644
--- a/lib/std/http/headers.zig
+++ b/lib/std/http/headers.zig
@@ -349,7 +349,7 @@ pub const Headers = struct {
pub fn format(
self: Self,
comptime fmt: []const u8,
- options: std.fmtstream.FormatOptions,
+ options: std.fmt.FormatOptions,
out_stream: var,
) !void {
for (self.toSlice()) |entry| {
@@ -591,5 +591,5 @@ test "Headers.format" {
\\foo: bar
\\cookie: somevalue
\\
- , try std.fmtstream.bufPrint(buf[0..], "{}", .{h}));
+ , try std.fmt.bufPrint(buf[0..], "{}", .{h}));
}
diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig
index 876a3b4701321920d048985875b96d7df002ae11..bf3ae791a17ed5532cbe4f2263636a15c170b598 100644
--- a/lib/std/io/out_stream.zig
+++ b/lib/std/io/out_stream.zig
@@ -25,7 +25,7 @@ pub fn OutStream(
}
pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
- return std.fmtstream.format(self, format, args);
+ return std.fmt.format(self, format, args);
}
pub fn writeByte(self: Self, byte: u8) Error!void {
diff --git a/lib/std/json.zig b/lib/std/json.zig
index f3a0811078009a96b99da7bb2029c0dc8fef3fe7..f5a72d86da233f4c5371624e0df31d5858db4220 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -2257,10 +2257,10 @@ pub fn stringify(
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.Float, .ComptimeFloat => {
- return std.fmtstream.formatFloatScientific(value, std.fmtstream.FormatOptions{}, out_stream);
+ return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
},
.Int, .ComptimeInt => {
- return std.fmtstream.formatIntValue(value, "", std.fmtstream.FormatOptions{}, out_stream);
+ return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
},
.Bool => {
return out_stream.writeAll(if (value) "true" else "false");
@@ -2350,16 +2350,16 @@ pub fn stringify(
// then it may be represented as a six-character sequence: a reverse solidus, followed
// by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
try out_stream.writeAll("\\u");
- try std.fmtstream.formatIntValue(codepoint, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
+ try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
} else {
// To escape an extended character that is not in the Basic Multilingual Plane,
// the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
try out_stream.writeAll("\\u");
- try std.fmtstream.formatIntValue(high, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
+ try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
try out_stream.writeAll("\\u");
- try std.fmtstream.formatIntValue(low, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
+ try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
}
i += ulen - 1;
},
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index cef2bae98c9375750c7a1bd1a94d123debdcaadf..95d0764f6866e429225e8872dc205c045fe2d9cf 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -518,7 +518,7 @@ pub const Int = struct {
pub fn format(
self: Int,
comptime fmt: []const u8,
- options: std.fmtstream.FormatOptions,
+ options: std.fmt.FormatOptions,
out_stream: var,
) FmtError!void {
self.assertWritable();
diff --git a/lib/std/net.zig b/lib/std/net.zig
index a1225654f014ec234e6344565fb90c8f4c9247dd..c2328b9bd0eb39854788d6e387ce64a0c3681f02 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -268,14 +268,14 @@ pub const Address = extern union {
pub fn format(
self: Address,
comptime fmt: []const u8,
- options: std.fmtstream.FormatOptions,
+ options: std.fmt.FormatOptions,
out_stream: var,
) !void {
switch (self.any.family) {
os.AF_INET => {
const port = mem.bigToNative(u16, self.in.port);
const bytes = @ptrCast(*const [4]u8, &self.in.addr);
- try std.fmtstream.format(out_stream, "{}.{}.{}.{}:{}", .{
+ try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
bytes[0],
bytes[1],
bytes[2],
@@ -286,7 +286,7 @@ pub const Address = extern union {
os.AF_INET6 => {
const port = mem.bigToNative(u16, self.in6.port);
if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
- try std.fmtstream.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
+ try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
self.in6.addr[12],
self.in6.addr[13],
self.in6.addr[14],
@@ -317,19 +317,19 @@ pub const Address = extern union {
}
continue;
}
- try std.fmtstream.format(out_stream, "{x}", .{native_endian_parts[i]});
+ try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
if (i != native_endian_parts.len - 1) {
try out_stream.writeAll(":");
}
}
- try std.fmtstream.format(out_stream, "]:{}", .{port});
+ try std.fmt.format(out_stream, "]:{}", .{port});
},
os.AF_UNIX => {
if (!has_unix_sockets) {
unreachable;
}
- try std.fmtstream.format(out_stream, "{}", .{&self.un.path});
+ try std.fmt.format(out_stream, "{}", .{&self.un.path});
},
else => unreachable,
}
@@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
const name_c = try std.cstr.addNullByte(allocator, name);
defer allocator.free(name_c);
- const port_c = try std.fmtstream.allocPrint(allocator, "{}\x00", .{port});
+ const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
defer allocator.free(port_c);
const hints = os.addrinfo{
diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig
index 0dc3b3020dd63fe65b53f134c770d2e83f1691f3..087f965c4ee3de39ff83ed48c09ad40f2653f46f 100644
--- a/lib/std/net/test.zig
+++ b/lib/std/net/test.zig
@@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" {
};
for (ips) |ip, i| {
var addr = net.Address.parseIp6(ip, 0) catch unreachable;
- var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
+ var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
}
@@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" {
"127.0.0.1",
}) |ip| {
var addr = net.Address.parseIp4(ip, 0) catch unreachable;
- var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
+ var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index baea4cecc5933a8989e377eec0efa1ce413b3c54..76a5dc2be55cf227ebe1240d9eb6448009f01389 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3049,7 +3049,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
defer close(fd);
var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
- const proc_path = std.fmtstream.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
+ const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
}
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
index 5d9a678ce8b810e9d509006eec4bb4b96664c81c..5c16483ecfe922faa48dd105b825d81cd2ee4903 100644
--- a/lib/std/os/uefi.zig
+++ b/lib/std/os/uefi.zig
@@ -27,11 +27,11 @@ pub const Guid = extern struct {
pub fn format(
self: @This(),
comptime f: []const u8,
- options: std.fmtstream.FormatOptions,
+ options: std.fmt.FormatOptions,
out_stream: var,
) Errors!void {
if (f.len == 0) {
- return std.fmtstream.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
+ return std.fmt.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
self.time_low,
self.time_mid,
self.time_high_and_version,
diff --git a/lib/std/progress.zig b/lib/std/progress.zig
index ebb983cdc622bafee93a315be63b7305772fe9b7..0264d99c91a8fe02ce5a689b2c34c713874a4ede 100644
--- a/lib/std/progress.zig
+++ b/lib/std/progress.zig
@@ -130,11 +130,11 @@ pub const Progress = struct {
var end: usize = 0;
if (self.columns_written > 0) {
// restore cursor position
- end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
+ end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
self.columns_written = 0;
// clear rest of line
- end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
+ end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
}
if (!self.done) {
@@ -185,7 +185,7 @@ pub const Progress = struct {
}
fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: var) void {
- if (std.fmtstream.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
+ if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
const amt = written.len;
end.* += amt;
self.columns_written += amt;
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
index c5a96df667fd758b0aeca4aa96aab1a04f9b8cc2..974247e2a1b708bbbc270b70e4da5c7461205d80 100644
--- a/lib/std/special/build_runner.zig
+++ b/lib/std/special/build_runner.zig
@@ -2,7 +2,7 @@ const root = @import("@build");
const std = @import("std");
const builtin = @import("builtin");
const io = std.io;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const Builder = std.build.Builder;
const mem = std.mem;
const process = std.process;
@@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
const allocator = builder.allocator;
for (builder.top_level_steps.toSliceConst()) |top_level_step| {
const name = if (&top_level_step.step == builder.default_step)
- try fmtstream.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
+ try fmt.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
else
top_level_step.step.name;
try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description });
@@ -175,7 +175,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
try out_stream.print(" (none)\n", .{});
} else {
for (builder.available_options_list.toSliceConst()) |option| {
- const name = try fmtstream.allocPrint(allocator, " -D{}=[{}]", .{
+ const name = try fmt.allocPrint(allocator, " -D{}=[{}]", .{
option.name,
Builder.typeIdName(option.type_id),
});
diff --git a/lib/std/std.zig b/lib/std/std.zig
index b7fe709c7c164d4f122da5e6b64df7ef52b65dcd..9277370ca6abf6c020ce48ec059eca6161c63594 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -38,7 +38,6 @@ pub const elf = @import("elf.zig");
pub const event = @import("event.zig");
pub const fifo = @import("fifo.zig");
pub const fmt = @import("fmt.zig");
-pub const fmtstream = @import("fmtstream.zig");
pub const fs = @import("fs.zig");
pub const hash = @import("hash.zig");
pub const hash_map = @import("hash_map.zig");
diff --git a/lib/std/target.zig b/lib/std/target.zig
index c117f60cc04fddaf87cc9b78ff3a1c66e9ef30d5..8beb7c3011db21e052dc8568e6e19ee2774c57b7 100644
--- a/lib/std/target.zig
+++ b/lib/std/target.zig
@@ -972,7 +972,7 @@ pub const Target = struct {
}
pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 {
- return std.fmtstream.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
+ return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
}
pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
@@ -1158,7 +1158,7 @@ pub const Target = struct {
var result: DynamicLinker = .{};
const S = struct {
fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {
- r.max_byte = @intCast(u8, (std.fmtstream.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
+ r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
return r.*;
}
fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig
index a60833f93cf3d8ae7baca242182ef10554a81887..cec3ea05e5ce82d90659c02c7497514da0100858 100644
--- a/lib/std/zig/cross_target.zig
+++ b/lib/std/zig/cross_target.zig
@@ -573,7 +573,7 @@ pub const CrossTarget = struct {
.Dynamic => "",
};
- return std.fmtstream.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
+ return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
}
pub const Executor = union(enum) {
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 875ecd424c1028e88937f4baa6304a52b1a0ef42..558b50b5b38564f2699b4ce50b4342699710fdd0 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -130,7 +130,7 @@ pub const NativePaths = struct {
}
pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmtstream.allocPrint0(self.include_dirs.allocator, fmt, args);
+ const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args);
errdefer self.include_dirs.allocator.free(item);
try self.include_dirs.append(item);
}
@@ -140,7 +140,7 @@ pub const NativePaths = struct {
}
pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmtstream.allocPrint0(self.lib_dirs.allocator, fmt, args);
+ const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args);
errdefer self.lib_dirs.allocator.free(item);
try self.lib_dirs.append(item);
}
@@ -150,7 +150,7 @@ pub const NativePaths = struct {
}
pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
- const item = try std.fmtstream.allocPrint0(self.warnings.allocator, fmt, args);
+ const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args);
errdefer self.warnings.allocator.free(item);
try self.warnings.append(item);
}
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
index fdaee7d12ff9f1e473a56dbd99dc816656644486..7a45bb3c37f12cc634e781ee3e2e73b67e791ce3 100644
--- a/src-self-hosted/compilation.zig
+++ b/src-self-hosted/compilation.zig
@@ -1051,7 +1051,7 @@ pub const Compilation = struct {
}
fn addCompileError(self: *Compilation, tree_scope: *Scope.AstTree, span: Span, comptime fmt: []const u8, args: var) !void {
- const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
+ const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
errdefer self.gpa().free(text);
const msg = try Msg.createFromScope(self, tree_scope, span, text);
@@ -1061,7 +1061,7 @@ pub const Compilation = struct {
}
fn addCompileErrorCli(self: *Compilation, realpath: []const u8, comptime fmt: []const u8, args: var) !void {
- const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
+ const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
errdefer self.gpa().free(text);
const msg = try Msg.createFromCli(self, realpath, text);
@@ -1154,7 +1154,7 @@ pub const Compilation = struct {
const tmp_dir = try self.getTmpDir();
const file_prefix = self.getRandomFileName();
- const file_name = try std.fmtstream.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
+ const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
defer self.gpa().free(file_name);
const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] });
diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig
index 233b6781719f0654a25e0f1f7b1c1539cbf8329e..c73719ebeaabec2864d1c036d774f6272038d84d 100644
--- a/src-self-hosted/dep_tokenizer.zig
+++ b/src-self-hosted/dep_tokenizer.zig
@@ -893,7 +893,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
var buf: [80]u8 = undefined;
- var text = try std.fmtstream.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
+ var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
try out.write(text);
var i: usize = text.len;
const end = 79;
@@ -979,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {
fn printDecValue(out: var, value: u64, width: u8) !void {
var buffer: [20]u8 = undefined;
- const len = std.fmtstream.formatIntBuf(buffer[0..], value, 10, false, width);
+ const len = std.fmt.formatIntBuf(buffer[0..], value, 10, false, width);
try out.write(buffer[0..len]);
}
fn printHexValue(out: var, value: u64, width: u8) !void {
var buffer: [16]u8 = undefined;
- const len = std.fmtstream.formatIntBuf(buffer[0..], value, 16, false, width);
+ const len = std.fmt.formatIntBuf(buffer[0..], value, 16, false, width);
try out.write(buffer[0..len]);
}
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 3b65fb172bdbf6debeb7f7b1be5684f33b07aebb..0f9736456a0ef408041a8bf86a174d3eeec0dba7 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
const allocator = args.allocator;
const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
- const arg1 = try std.fmtstream.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
+ const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
defer allocator.free(arg1);
const argv = [_][]const u8{ cc_exe, arg1 };
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig
index b63e6c24f47271b394427cbe63eb750b73175edb..1efa15574a788435b8ad42793035a1a710e8913b 100644
--- a/src-self-hosted/link.zig
+++ b/src-self-hosted/link.zig
@@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
const is_library = ctx.comp.kind == .Lib;
- const out_arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
+ const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
if (ctx.comp.haveLibC()) {
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
- try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
+ try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
}
if (ctx.link_in_crt) {
@@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
if (ctx.comp.is_static) {
- const cmt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
+ const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
} else {
- const msvcrt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
+ const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
}
- const vcruntime_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
+ const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
lib_str,
d_str,
});
try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
- const crt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
+ const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
// Visual C++ 2015 Conformance Changes
@@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
.IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
.IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
}
- const ver_str = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
+ const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
platform.major,
platform.minor,
platform.micro,
@@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append("-lSystem");
} else {
if (mem.indexOfScalar(u8, lib.name, '/') == null) {
- const arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
+ const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
} else {
const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig
index 408c39fe7b93bb5a2a71b34cc1e91b2e80475b7a..ad506425d2af144e4b906e8781510a58c769d4b2 100644
--- a/src-self-hosted/print_targets.zig
+++ b/src-self-hosted/print_targets.zig
@@ -138,7 +138,7 @@ pub fn cmdTargets(
for (available_glibcs) |glibc| {
try jws.arrayElem();
- const tmp = try std.fmtstream.allocPrint(allocator, "{}", .{glibc});
+ const tmp = try std.fmt.allocPrint(allocator, "{}", .{glibc});
defer allocator.free(tmp);
try jws.emitString(tmp);
}
diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig
index 98e9fb06dfc916141e66fcb80da444d5056c7472..e87164c9fb471f243a85c6708902f4c333f9d7a8 100644
--- a/src-self-hosted/test.zig
+++ b/src-self-hosted/test.zig
@@ -81,7 +81,7 @@ pub const TestContext = struct {
msg: []const u8,
) !void {
var file_index_buf: [20]u8 = undefined;
- const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
+ const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
if (std.fs.path.dirname(file1_path)) |dirname| {
@@ -114,10 +114,10 @@ pub const TestContext = struct {
expected_output: []const u8,
) !void {
var file_index_buf: [20]u8 = undefined;
- const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
+ const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
- const output_file = try std.fmtstream.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
+ const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
if (std.fs.path.dirname(file1_path)) |dirname| {
try std.fs.cwd().makePath(dirname);
}
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 7b05a76cb7cc39b9d50d2c971b33c18dc635a02f..89d6f94d7bbfbcbd80f4ca7a9becce6870c25749 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -89,7 +89,7 @@ const Scope = struct {
var proposed_name = name;
while (scope.contains(proposed_name)) {
scope.mangle_count += 1;
- proposed_name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
+ proposed_name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
}
try scope.variables.push(.{ .name = name, .alias = proposed_name });
return proposed_name;
@@ -246,7 +246,7 @@ pub const Context = struct {
const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
- return std.fmtstream.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
+ return std.fmt.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
}
};
@@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const arg_name = blk: {
const param_prefix = if (is_const) "" else "arg_";
- const bare_arg_name = try std.fmtstream.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
+ const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
break :blk try block_scope.makeMangledName(c, bare_arg_name);
};
@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(var_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
+ const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name;
const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
@@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
_ = try appendToken(rp.c, .LParen, "(");
const expr = try transCreateNodeStringLiteral(
rp.c,
- try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
+ try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
);
_ = try appendToken(rp.c, .RParen, ")");
@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
+ const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name;
if (mem.eql(u8, checked_name, "uint8_t"))
return transTypeDefAsBuiltin(c, typedef_decl, "u8")
@@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
// Record declarations such as `struct {...} x` have no name but they're not
// anonymous hence here isAnonymousStructOrUnion is not needed
if (bare_name.len == 0) {
- bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_unnamed = true;
}
@@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
return null;
}
- const name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
+ const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
_ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
@@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
var is_anon = false;
var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
- raw_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_anon = true;
}
const field_name = try appendIdentifier(c, raw_name);
@@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl)));
var is_unnamed = false;
if (bare_name.len == 0) {
- bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
+ bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
is_unnamed = true;
}
- const name = try std.fmtstream.allocPrint(c.a(), "enum_{}", .{bare_name});
+ const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
_ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
node.eq_token = try appendToken(c, .Equal, "=");
@@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
// Handle the remaining escapes Zig doesn't support by turning them
// into their respective hex representation
if (std.ascii.isCntrl(c))
- return std.fmtstream.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
+ return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
else
- return std.fmtstream.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
+ return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
},
};
}
@@ -2436,7 +2436,7 @@ fn transCase(
) TransError!*ast.Node {
const block_scope = scope.findBlockScope(rp.c) catch unreachable;
const switch_scope = scope.getSwitch();
- const label = try std.fmtstream.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
+ const label = try std.fmt.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
_ = try appendToken(rp.c, .Semicolon, ";");
const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
@@ -4607,7 +4607,7 @@ fn finishTransFnProto(
_ = try appendToken(rp.c, .LParen, "(");
const expr = try transCreateNodeStringLiteral(
rp.c,
- try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
+ try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
);
_ = try appendToken(rp.c, .RParen, ")");
@@ -4866,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
const name = try c.str(raw_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
- const mangled_name = if (isZigPrimitiveType(name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
+ const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name;
if (scope.containsNow(mangled_name)) {
continue;
}
@@ -5151,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
switch (lit_bytes[1]) {
'0'...'7' => {
// Octal
- lit_bytes = try std.fmtstream.allocPrint(c.a(), "0o{}", .{lit_bytes});
+ lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{lit_bytes});
},
'X' => {
// Hexadecimal with capital X, valid in C but not in Zig
- lit_bytes = try std.fmtstream.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
+ lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
},
else => {},
}
@@ -5186,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
return &cast_node.base;
} else if (tok.id == .FloatLiteral) {
if (lit_bytes[0] == '.')
- lit_bytes = try std.fmtstream.allocPrint(c.a(), "0{}", .{lit_bytes});
+ lit_bytes = try std.fmt.allocPrint(c.a(), "0{}", .{lit_bytes});
if (tok.id.FloatLiteral == .None) {
return transCreateNodeFloat(c, lit_bytes);
}
@@ -5319,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
num += c - 'A' + 10;
},
else => {
- i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
num = 0;
if (c == '\\')
state = .Escape
@@ -5345,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
};
num += c - '0';
} else {
- i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
num = 0;
count = 0;
if (c == '\\')
@@ -5359,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
}
}
if (state == .Hex or state == .Octal)
- i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
+ i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
return bytes[0..i];
}
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
index c2b406823ddc0d8cb130850989667c7e73d31543..70ed754cea752c9015541ace7df5365463cd7ea0 100644
--- a/src-self-hosted/type.zig
+++ b/src-self-hosted/type.zig
@@ -581,7 +581,7 @@ pub const Type = struct {
errdefer comp.gpa().destroy(self);
const u_or_i = "ui"[@boolToInt(key.is_signed)];
- const name = try std.fmtstream.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
+ const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
errdefer comp.gpa().free(name);
self.base.init(comp, .Int, name);
@@ -764,13 +764,13 @@ pub const Type = struct {
.Non => "",
};
const name = switch (self.key.alignment) {
- .Abi => try std.fmtstream.allocPrint(comp.gpa(), "{}{}{}{}", .{
+ .Abi => try std.fmt.allocPrint(comp.gpa(), "{}{}{}{}", .{
size_str,
mut_str,
vol_str,
self.key.child_type.name,
}),
- .Override => |alignment| try std.fmtstream.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
+ .Override => |alignment| try std.fmt.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
size_str,
alignment,
mut_str,
@@ -845,7 +845,7 @@ pub const Type = struct {
};
errdefer comp.gpa().destroy(self);
- const name = try std.fmtstream.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
+ const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
errdefer comp.gpa().free(name);
self.base.init(comp, .Array, name);
diff --git a/test/src/compare_output.zig b/test/src/compare_output.zig
index c68eb1eebf6166153ac8b82028078593a2c536cc..ae994a0697d5031bf2814b5355aaa0361a26d471 100644
--- a/test/src/compare_output.zig
+++ b/test/src/compare_output.zig
@@ -4,7 +4,7 @@ const std = @import("std");
const builtin = std.builtin;
const build = std.build;
const ArrayList = std.ArrayList;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -97,7 +97,7 @@ pub const CompareOutputContext = struct {
switch (case.special) {
Special.Asm => {
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "assemble-and-link {}", .{
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", .{
case.name,
}) catch unreachable;
if (self.test_filter) |filter| {
@@ -116,7 +116,7 @@ pub const CompareOutputContext = struct {
},
Special.None => {
for (self.modes) |mode| {
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
"compare-output",
case.name,
@tagName(mode),
@@ -141,7 +141,7 @@ pub const CompareOutputContext = struct {
}
},
Special.RuntimeSafety => {
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig
index 6304137e4a6c204e268a192bca1f701671eb1cd4..14b0ce593c59ef04af075ff7bfc825a1cee7a698 100644
--- a/test/src/run_translated_c.zig
+++ b/test/src/run_translated_c.zig
@@ -3,7 +3,7 @@
const std = @import("std");
const build = std.build;
const ArrayList = std.ArrayList;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct {
pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
const b = self.b;
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig
index 250ec6175ee9edda2a93650d7edc7fd4df9ea565..9a6bd0d3234457eef6b89414e923adc21cf29ba8 100644
--- a/test/src/translate_c.zig
+++ b/test/src/translate_c.zig
@@ -3,7 +3,7 @@
const std = @import("std");
const build = std.build;
const ArrayList = std.ArrayList;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
@@ -99,7 +99,7 @@ pub const TranslateCContext = struct {
const b = self.b;
const translate_c_cmd = "translate-c";
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/test/stage1/behavior/enum_with_members.zig b/test/stage1/behavior/enum_with_members.zig
index b299301ced01b93ee5a77cbacdb60953013c93a8..08b195494b546238fbe1c7096ea5d7e8dcfe43d8 100644
--- a/test/stage1/behavior/enum_with_members.zig
+++ b/test/stage1/behavior/enum_with_members.zig
@@ -1,6 +1,6 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
-const fmtstream = @import("std").fmtstream;
+const fmt = @import("std").fmt;
const ET = union(enum) {
SINT: i32,
@@ -8,8 +8,8 @@ const ET = union(enum) {
pub fn print(a: *const ET, buf: []u8) anyerror!usize {
return switch (a.*) {
- ET.SINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
- ET.UINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
+ ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
+ ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
};
}
};
diff --git a/test/tests.zig b/test/tests.zig
index 61f694bedb6f9829ff3e7309eba55db0a7bfe127..22dad10e3e46c6edccd7c001fbe0705392b264bb 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -8,7 +8,7 @@ const Buffer = std.Buffer;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const ArrayList = std.ArrayList;
const Mode = builtin.Mode;
const LibExeObjStep = build.LibExeObjStep;
@@ -484,7 +484,7 @@ pub const StackTracesContext = struct {
const expect_for_mode = expect[@enumToInt(mode)];
if (expect_for_mode.len == 0) continue;
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
"stack-trace",
name,
@tagName(mode),
@@ -943,7 +943,7 @@ pub const CompileErrorContext = struct {
pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
const b = self.b;
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "compile-error {}", .{
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", .{
case.name,
}) catch unreachable;
if (self.test_filter) |filter| {
@@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct {
const b = self.b;
for (self.modes) |mode| {
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "build {} ({})", .{
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", .{
root_src,
@tagName(mode),
}) catch unreachable;
@@ -1152,7 +1152,7 @@ pub const GenHContext = struct {
const b = self.b;
const mode = builtin.Mode.Debug;
- const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
+ const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
diff --git a/tools/process_headers.zig b/tools/process_headers.zig
index 43950750e9e44b82f51954f81c1f6efbe49909ae..abdc9fabf944c38683677d266e26f1e5a7d9a179 100644
--- a/tools/process_headers.zig
+++ b/tools/process_headers.zig
@@ -299,7 +299,7 @@ pub fn main() !void {
std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});
usageAndExit(args[0]);
};
- const generic_name = try std.fmtstream.allocPrint(allocator, "generic-{}", .{abi_name});
+ const generic_name = try std.fmt.allocPrint(allocator, "generic-{}", .{abi_name});
// TODO compiler crashed when I wrote this the canonical way
var libc_targets: []const LibCTarget = undefined;
@@ -440,7 +440,7 @@ pub fn main() !void {
.specific => |a| @tagName(a),
else => @tagName(dest_target.arch),
};
- const out_subpath = try std.fmtstream.allocPrint(allocator, "{}-{}-{}", .{
+ const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{
arch_name,
@tagName(dest_target.os),
@tagName(dest_target.abi),
diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig
index 35351e4d2a3ffbc9508383f819840b4622daa874..84522aabe450b990dce959133d35dd005c0a19a1 100644
--- a/tools/update_glibc.zig
+++ b/tools/update_glibc.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const fs = std.fs;
-const fmtstream = std.fmtstream;
+const fmt = std.fmt;
const assert = std.debug.assert;
// Example abilist path:
@@ -154,7 +154,7 @@ pub fn main() !void {
const fn_set = &target_funcs_gop.kv.value.list;
for (lib_names) |lib_name, lib_name_index| {
- const basename = try fmtstream.allocPrint(allocator, "lib{}.abilist", .{lib_name});
+ const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});
const abi_list_filename = blk: {
if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });
--
2.54.0
From 8a22c50c081e4495216ef961a9c1f2db6fbac916 Mon Sep 17 00:00:00 2001
From: daurnimator
Date: Fri, 13 Mar 2020 00:55:52 +1100
Subject: [PATCH 096/111] Remove unused static_crt_dir field from libc config
---
src-self-hosted/libc_installation.zig | 25 -------------------------
src-self-hosted/stage2.zig | 12 ------------
src/stage2.cpp | 2 --
src/stage2.h | 2 --
4 files changed, 41 deletions(-)
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 0f9736456a0ef408041a8bf86a174d3eeec0dba7..c07ef03b5175b690a16bf54d319f7b031bbe5d1f 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -17,7 +17,6 @@ pub const LibCInstallation = struct {
include_dir: ?[:0]const u8 = null,
sys_include_dir: ?[:0]const u8 = null,
crt_dir: ?[:0]const u8 = null,
- static_crt_dir: ?[:0]const u8 = null,
msvc_lib_dir: ?[:0]const u8 = null,
kernel32_lib_dir: ?[:0]const u8 = null,
@@ -98,13 +97,6 @@ pub const LibCInstallation = struct {
try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.os.tag)});
return error.ParseError;
}
- if (self.static_crt_dir == null and is_windows and is_gnu) {
- try stderr.print("static_crt_dir may not be empty for {}-{}\n", .{
- @tagName(Target.current.os.tag),
- @tagName(Target.current.abi),
- });
- return error.ParseError;
- }
if (self.msvc_lib_dir == null and is_windows and !is_gnu) {
try stderr.print("msvc_lib_dir may not be empty for {}-{}\n", .{
@tagName(Target.current.os.tag),
@@ -128,7 +120,6 @@ pub const LibCInstallation = struct {
const include_dir = self.include_dir orelse "";
const sys_include_dir = self.sys_include_dir orelse "";
const crt_dir = self.crt_dir orelse "";
- const static_crt_dir = self.static_crt_dir orelse "";
const msvc_lib_dir = self.msvc_lib_dir orelse "";
const kernel32_lib_dir = self.kernel32_lib_dir orelse "";
@@ -147,11 +138,6 @@ pub const LibCInstallation = struct {
\\# Not needed when targeting MacOS.
\\crt_dir={}
\\
- \\# The directory that contains `crtbegin.o`.
- \\# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.
- \\# Only needed when targeting MinGW-w64 on Windows.
- \\static_crt_dir={}
- \\
\\# The directory that contains `vcruntime.lib`.
\\# Only needed when targeting MSVC on Windows.
\\msvc_lib_dir={}
@@ -164,7 +150,6 @@ pub const LibCInstallation = struct {
include_dir,
sys_include_dir,
crt_dir,
- static_crt_dir,
msvc_lib_dir,
kernel32_lib_dir,
});
@@ -186,7 +171,6 @@ pub const LibCInstallation = struct {
var batch = Batch(FindError!void, 3, .auto_async).init();
batch.add(&async self.findNativeIncludeDirPosix(args));
batch.add(&async self.findNativeCrtDirPosix(args));
- batch.add(&async self.findNativeStaticCrtDirPosix(args));
try batch.wait();
} else {
var sdk: *ZigWindowsSDK = undefined;
@@ -428,15 +412,6 @@ pub const LibCInstallation = struct {
});
}
- fn findNativeStaticCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
- self.static_crt_dir = try ccPrintFileName(.{
- .allocator = args.allocator,
- .search_basename = "crtbegin.o",
- .want_dirname = .only_dir,
- .verbose = args.verbose,
- });
- }
-
fn findNativeKernel32LibDir(
self: *LibCInstallation,
args: FindNativeOptions,
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
index 36941cc3a13830eac7ff13c3c09fd0533470f03a..b355f8f02a7d47d7a10a2f27f1b2fe2c52a42cfa 100644
--- a/src-self-hosted/stage2.zig
+++ b/src-self-hosted/stage2.zig
@@ -744,8 +744,6 @@ const Stage2LibCInstallation = extern struct {
sys_include_dir_len: usize,
crt_dir: [*:0]const u8,
crt_dir_len: usize,
- static_crt_dir: [*:0]const u8,
- static_crt_dir_len: usize,
msvc_lib_dir: [*:0]const u8,
msvc_lib_dir_len: usize,
kernel32_lib_dir: [*:0]const u8,
@@ -773,13 +771,6 @@ const Stage2LibCInstallation = extern struct {
self.crt_dir = "";
self.crt_dir_len = 0;
}
- if (libc.static_crt_dir) |s| {
- self.static_crt_dir = s.ptr;
- self.static_crt_dir_len = s.len;
- } else {
- self.static_crt_dir = "";
- self.static_crt_dir_len = 0;
- }
if (libc.msvc_lib_dir) |s| {
self.msvc_lib_dir = s.ptr;
self.msvc_lib_dir_len = s.len;
@@ -807,9 +798,6 @@ const Stage2LibCInstallation = extern struct {
if (self.crt_dir_len != 0) {
libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0];
}
- if (self.static_crt_dir_len != 0) {
- libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0];
- }
if (self.msvc_lib_dir_len != 0) {
libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0];
}
diff --git a/src/stage2.cpp b/src/stage2.cpp
index 7495ffddb9940af270596e0a93f45335434a573a..a8d8b7cf971fb0ae98f1df66f969ea85af043e42 100644
--- a/src/stage2.cpp
+++ b/src/stage2.cpp
@@ -272,8 +272,6 @@ enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *li
libc->sys_include_dir_len = strlen(libc->sys_include_dir);
libc->crt_dir = "";
libc->crt_dir_len = strlen(libc->crt_dir);
- libc->static_crt_dir = "";
- libc->static_crt_dir_len = strlen(libc->static_crt_dir);
libc->msvc_lib_dir = "";
libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir);
libc->kernel32_lib_dir = "";
diff --git a/src/stage2.h b/src/stage2.h
index 50f891dca983becc4b111497afde7ccaebaee146..24fd664b3cbaabe3d71de5c1e8b58b70f9e7205a 100644
--- a/src/stage2.h
+++ b/src/stage2.h
@@ -209,8 +209,6 @@ struct Stage2LibCInstallation {
size_t sys_include_dir_len;
const char *crt_dir;
size_t crt_dir_len;
- const char *static_crt_dir;
- size_t static_crt_dir_len;
const char *msvc_lib_dir;
size_t msvc_lib_dir_len;
const char *kernel32_lib_dir;
--
2.54.0
From bd0b51477a6cb0dc7ea7739f61a70110d39ba601 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Thu, 12 Mar 2020 19:40:42 +0100
Subject: [PATCH 097/111] Address review comments
---
lib/std/fs/file.zig | 2 +-
lib/std/os.zig | 22 ++++++++++++++--------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 8bb377c99fdadb7e541e9708bf95b566e16abcfc..c3809cd51005216708ffcb7508d4f9bb3f669573 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -104,7 +104,7 @@ pub const File = struct {
/// Shrinks or expands the file.
/// The file offset after this call is undefined.
pub fn setEndPos(self: File, length: u64) SetEndPosError!void {
- try os.truncate(self.handle, length);
+ try os.ftruncate(self.handle, length);
}
pub const SeekError = os.SeekError;
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 62347c2ee96ae7096f3a5c51ac0a5a36cedc661f..6614453a3845ab18f6de2e1219a16f307721d482 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -439,11 +439,13 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
}
pub const TruncateError = error{
- /// The file descriptor is not open for writing.
- NotFile,
+ FileTooBig,
+ InputOutput,
+ CannotTruncate,
+ FileBusy,
} || UnexpectedError;
-pub fn truncate(fd: fd_t, length: u64) TruncateError!void {
+pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
if (std.Target.current.os.tag == .windows) {
try windows.SetFilePointerEx_BEGIN(fd, length);
@@ -454,18 +456,22 @@ pub fn truncate(fd: fd_t, length: u64) TruncateError!void {
}
while (true) {
- const rc = if (builtin.link_libc) blk: {
+ const rc = if (builtin.link_libc)
if (std.Target.current.os.tag == .linux)
- break :blk system.ftruncate64(fd, @bitCast(off_t, length))
+ system.ftruncate64(fd, @bitCast(off_t, length))
else
- break :blk system.ftruncate(fd, @bitCast(off_t, length));
- } else
+ system.ftruncate(fd, @bitCast(off_t, length))
+ else
system.ftruncate(fd, length);
switch (errno(rc)) {
0 => return,
EINTR => continue,
- EBADF, EINVAL => return error.NotFile,
+ EFBIG => return error.FileTooBig,
+ EIO => return error.InputOutput,
+ EPERM => return error.CannotTruncate,
+ ETXTBSY => return error.FileBusy,
+ EBADF, EINVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
--
2.54.0
From 6dde769279aaa0cc09d13dd0670b74a8dd24f547 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 21:15:58 +0200
Subject: [PATCH 098/111] Simplify stores, use sext for signed ints
---
src/codegen.cpp | 22 ++++++++++---
src/ir.cpp | 53 +++++++++++++++++++++++---------
test/stage1/behavior/atomics.zig | 4 +--
3 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 55713c1b88c8fc7de08c1983b5143c1dd33cc87e..a9c539224646ef4643bbce7e51ba8cba1de46ac6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5259,8 +5259,13 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
// operand needs widening and truncating
ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
LLVMPointerType(actual_abi_type, 0), "");
- cmp_val = LLVMBuildZExt(g->builder, cmp_val, actual_abi_type, "");
- new_val = LLVMBuildZExt(g->builder, new_val, actual_abi_type, "");
+ if (operand_type->data.integral.is_signed) {
+ cmp_val = LLVMBuildSExt(g->builder, cmp_val, actual_abi_type, "");
+ new_val = LLVMBuildSExt(g->builder, new_val, actual_abi_type, "");
+ } else {
+ cmp_val = LLVMBuildZExt(g->builder, cmp_val, actual_abi_type, "");
+ new_val = LLVMBuildZExt(g->builder, new_val, actual_abi_type, "");
+ }
}
LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
@@ -5877,7 +5882,12 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
// operand needs widening and truncating
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
LLVMPointerType(actual_abi_type, 0), "");
- LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, actual_abi_type, "");
+ LLVMValueRef casted_operand;
+ if (operand_type->data.integral.is_signed) {
+ casted_operand = LLVMBuildSExt(g->builder, operand, actual_abi_type, "");
+ } else {
+ casted_operand = LLVMBuildZExt(g->builder, operand, actual_abi_type, "");
+ }
LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
g->is_single_threaded);
return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
@@ -5929,7 +5939,11 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
// operand needs widening
ptr = LLVMBuildBitCast(g->builder, ptr,
LLVMPointerType(actual_abi_type, 0), "");
- value = LLVMBuildZExt(g->builder, value, actual_abi_type, "");
+ if (instruction->value->value->type->data.integral.is_signed) {
+ value = LLVMBuildSExt(g->builder, value, actual_abi_type, "");
+ } else {
+ value = LLVMBuildZExt(g->builder, value, actual_abi_type, "");
+ }
}
LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
LLVMSetOrdering(store_inst, ordering);
diff --git a/src/ir.cpp b/src/ir.cpp
index 4f139895b9acacdf3ae707c73e4d5af758283e8b..ede403c722fadf0012ee73d409baa42e4a4174b1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25197,10 +25197,16 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
ZigType *result_type = get_optional_type(ira->codegen, operand_type);
// special case zero bit types
- if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
- IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
- set_optional_value_to_null(result->value);
- return result;
+ switch (type_has_one_possible_value(ira->codegen, operand_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_inst_gen;
+ case OnePossibleValueYes: {
+ IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
+ set_optional_value_to_null(result->value);
+ return result;
+ }
+ case OnePossibleValueNo:
+ break;
}
if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
@@ -28432,8 +28438,13 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
}
// special case zero bit types
- if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
- return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
+ switch (type_has_one_possible_value(ira->codegen, operand_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_inst_gen;
+ case OnePossibleValueYes:
+ return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
+ case OnePossibleValueNo:
+ break;
}
IrInst *source_inst = &instruction->base.base;
@@ -28450,9 +28461,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
if (op2_val == nullptr)
return ira->codegen->invalid_inst_gen;
+ IrInstGen *result = ir_const(ira, source_inst, operand_type);
+ copy_const_val(ira->codegen, result->value, op1_val);
if (op == AtomicRmwOp_xchg) {
- ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false);
- return ir_const_move(ira, source_inst, op1_val);
+ copy_const_val(ira->codegen, op1_val, op2_val);
+ return result;
}
if (operand_type->id == ZigTypeIdPointer || operand_type->id == ZigTypeIdOptional) {
@@ -28461,6 +28474,7 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
return ira->codegen->invalid_inst_gen;
}
+ ErrorMsg *msg;
if (op == AtomicRmwOp_min || op == AtomicRmwOp_max) {
IrBinOp bin_op;
if (op == AtomicRmwOp_min)
@@ -28471,9 +28485,12 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
bin_op = IrBinOpCmpLessThan;
IrInstGen *dummy_value = ir_const(ira, source_inst, operand_type);
- ir_eval_bin_op_cmp_scalar(ira, source_inst, op1_val, bin_op, op2_val, dummy_value->value);
+ msg = ir_eval_bin_op_cmp_scalar(ira, source_inst, op1_val, bin_op, op2_val, dummy_value->value);
+ if (msg != nullptr) {
+ return ira->codegen->invalid_inst_gen;
+ }
if (dummy_value->value->data.x_bool)
- ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false);
+ copy_const_val(ira->codegen, op1_val, op2_val);
} else {
IrBinOp bin_op;
switch (op) {
@@ -28504,13 +28521,16 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
bin_op = IrBinOpBinXor;
break;
}
- ir_eval_math_op_scalar(ira, source_inst, operand_type, op1_val, bin_op, op2_val, op1_val);
+ msg = ir_eval_math_op_scalar(ira, source_inst, operand_type, op1_val, bin_op, op2_val, op1_val);
+ if (msg != nullptr) {
+ return ira->codegen->invalid_inst_gen;
+ }
if (op == AtomicRmwOp_nand) {
bigint_not(&op1_val->data.x_bigint, &op1_val->data.x_bigint,
operand_type->data.integral.bit_count, operand_type->data.integral.is_signed);
}
}
- return ir_const_move(ira, source_inst, op1_val);
+ return result;
}
return ir_build_atomic_rmw_gen(ira, source_inst, casted_ptr, casted_operand, op,
@@ -28586,8 +28606,13 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
}
// special case zero bit types
- if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
- return ir_const_void(ira, &instruction->base.base);
+ switch (type_has_one_possible_value(ira->codegen, operand_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_inst_gen;
+ case OnePossibleValueYes:
+ return ir_const_void(ira, &instruction->base.base);
+ case OnePossibleValueNo:
+ break;
}
if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index 36751e7d259dc9dc61a8313920aa56379894af0b..8870091d75e9a19b8cade939bcf117ec8ee8dc8c 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -175,8 +175,8 @@ test "atomicrmw with ints" {
fn testAtomicRmwInt() void {
var x: u8 = 1;
- _ = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
- expect(x == 3);
+ var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
+ expect(x == 3 and res == 1);
_ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
expect(x == 6);
_ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
--
2.54.0
From 205c4139620cddb083cff16e5d9264918f3876c2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 12 Mar 2020 16:26:14 -0400
Subject: [PATCH 099/111] update musl headers to v1.2.0
---
.../aarch64-linux-musl/bits/alltypes.h | 121 +++++++++-------
.../include/aarch64-linux-musl/bits/endian.h | 5 -
.../include/aarch64-linux-musl/bits/socket.h | 33 -----
.../include/aarch64-linux-musl/bits/syscall.h | 6 +-
.../include/arm-linux-musl/bits/alltypes.h | 122 +++++++++-------
lib/libc/include/arm-linux-musl/bits/endian.h | 5 -
.../include/arm-linux-musl/bits/ipcstat.h | 1 +
lib/libc/include/arm-linux-musl/bits/limits.h | 7 -
lib/libc/include/arm-linux-musl/bits/msg.h | 15 +-
lib/libc/include/arm-linux-musl/bits/sem.h | 10 +-
lib/libc/include/arm-linux-musl/bits/shm.h | 16 ++-
lib/libc/include/arm-linux-musl/bits/stat.h | 6 +-
.../include/arm-linux-musl/bits/syscall.h | 46 +++---
lib/libc/include/generic-musl/aio.h | 4 +
lib/libc/include/generic-musl/alloca.h | 2 -
lib/libc/include/generic-musl/arpa/nameser.h | 1 -
lib/libc/include/generic-musl/bits/dirent.h | 11 ++
lib/libc/include/generic-musl/bits/endian.h | 1 -
lib/libc/include/generic-musl/bits/ioctl.h | 5 +
lib/libc/include/generic-musl/bits/limits.h | 7 -
lib/libc/include/generic-musl/bits/socket.h | 15 --
lib/libc/include/generic-musl/dirent.h | 14 +-
lib/libc/include/generic-musl/dlfcn.h | 4 +
lib/libc/include/generic-musl/endian.h | 46 +++---
lib/libc/include/generic-musl/features.h | 2 +
lib/libc/include/generic-musl/limits.h | 18 ++-
lib/libc/include/generic-musl/mqueue.h | 5 +
lib/libc/include/generic-musl/netinet/icmp6.h | 1 -
.../include/generic-musl/netinet/if_ether.h | 1 +
lib/libc/include/generic-musl/netinet/ip.h | 3 +-
lib/libc/include/generic-musl/netinet/ip6.h | 1 -
lib/libc/include/generic-musl/netinet/tcp.h | 4 +-
lib/libc/include/generic-musl/poll.h | 6 +
lib/libc/include/generic-musl/pthread.h | 10 ++
lib/libc/include/generic-musl/sched.h | 8 ++
lib/libc/include/generic-musl/semaphore.h | 4 +
lib/libc/include/generic-musl/signal.h | 8 ++
lib/libc/include/generic-musl/sys/acct.h | 1 -
lib/libc/include/generic-musl/sys/ioctl.h | 1 +
lib/libc/include/generic-musl/sys/mman.h | 2 +
lib/libc/include/generic-musl/sys/prctl.h | 4 +
lib/libc/include/generic-musl/sys/procfs.h | 7 +-
lib/libc/include/generic-musl/sys/ptrace.h | 29 ++++
lib/libc/include/generic-musl/sys/resource.h | 7 +-
lib/libc/include/generic-musl/sys/select.h | 5 +
lib/libc/include/generic-musl/sys/sem.h | 8 +-
lib/libc/include/generic-musl/sys/socket.h | 69 ++++++++-
lib/libc/include/generic-musl/sys/stat.h | 9 ++
lib/libc/include/generic-musl/sys/statvfs.h | 2 -
lib/libc/include/generic-musl/sys/time.h | 14 ++
lib/libc/include/generic-musl/sys/timeb.h | 6 +
lib/libc/include/generic-musl/sys/timerfd.h | 5 +
lib/libc/include/generic-musl/sys/timex.h | 5 +
.../include/generic-musl/sys/ttydefaults.h | 7 +-
lib/libc/include/generic-musl/sys/wait.h | 10 +-
lib/libc/include/generic-musl/threads.h | 6 +
lib/libc/include/generic-musl/time.h | 28 ++++
lib/libc/include/generic-musl/utime.h | 6 +
lib/libc/include/generic-musl/utmpx.h | 7 +-
.../include/i386-linux-musl/bits/alltypes.h | 134 +++++++++---------
.../include/i386-linux-musl/bits/ipcstat.h | 1 +
.../include/i386-linux-musl/bits/limits.h | 9 +-
lib/libc/include/i386-linux-musl/bits/msg.h | 15 +-
lib/libc/include/i386-linux-musl/bits/sem.h | 10 +-
lib/libc/include/i386-linux-musl/bits/shm.h | 16 ++-
lib/libc/include/i386-linux-musl/bits/stat.h | 6 +-
.../include/i386-linux-musl/bits/syscall.h | 46 +++---
.../include/mips-linux-musl/bits/alltypes.h | 122 +++++++++-------
.../include/mips-linux-musl/bits/endian.h | 5 -
lib/libc/include/mips-linux-musl/bits/hwcap.h | 13 +-
lib/libc/include/mips-linux-musl/bits/ioctl.h | 4 +-
.../include/mips-linux-musl/bits/ipcstat.h | 1 +
.../include/mips-linux-musl/bits/limits.h | 7 -
lib/libc/include/mips-linux-musl/bits/msg.h | 27 ++--
lib/libc/include/mips-linux-musl/bits/sem.h | 16 +++
lib/libc/include/mips-linux-musl/bits/shm.h | 29 ++++
.../include/mips-linux-musl/bits/signal.h | 8 +-
.../include/mips-linux-musl/bits/socket.h | 18 ---
lib/libc/include/mips-linux-musl/bits/stat.h | 12 +-
.../include/mips-linux-musl/bits/syscall.h | 46 +++---
.../include/mips64-linux-musl/bits/alltypes.h | 121 +++++++++-------
.../include/mips64-linux-musl/bits/endian.h | 5 -
.../include/mips64-linux-musl/bits/limits.h | 7 -
.../include/mips64-linux-musl/bits/socket.h | 34 -----
.../include/mips64-linux-musl/bits/syscall.h | 6 +-
.../powerpc-linux-musl/bits/alltypes.h | 121 ++++++++--------
.../include/powerpc-linux-musl/bits/endian.h | 15 --
.../include/powerpc-linux-musl/bits/ioctl.h | 4 +-
.../include/powerpc-linux-musl/bits/ipcstat.h | 1 +
.../include/powerpc-linux-musl/bits/limits.h | 7 -
.../include/powerpc-linux-musl/bits/msg.h | 15 +-
.../include/powerpc-linux-musl/bits/sem.h | 10 +-
.../include/powerpc-linux-musl/bits/shm.h | 16 ++-
.../include/powerpc-linux-musl/bits/signal.h | 2 +-
.../include/powerpc-linux-musl/bits/socket.h | 18 ---
.../include/powerpc-linux-musl/bits/stat.h | 6 +-
.../include/powerpc-linux-musl/bits/syscall.h | 46 +++---
.../powerpc64-linux-musl/bits/alltypes.h | 121 +++++++++-------
.../powerpc64-linux-musl/bits/endian.h | 5 -
.../powerpc64-linux-musl/bits/signal.h | 8 +-
.../powerpc64-linux-musl/bits/socket.h | 34 -----
.../powerpc64-linux-musl/bits/syscall.h | 6 +-
.../riscv64-linux-musl/bits/alltypes.h | 120 ++++++++--------
.../include/riscv64-linux-musl/bits/reg.h | 8 --
.../include/riscv64-linux-musl/bits/signal.h | 9 ++
.../include/riscv64-linux-musl/bits/socket.h | 19 ---
.../include/riscv64-linux-musl/bits/syscall.h | 4 +
.../include/s390x-linux-musl/bits/alltypes.h | 120 ++++++++--------
.../include/s390x-linux-musl/bits/endian.h | 1 -
.../include/s390x-linux-musl/bits/limits.h | 9 +-
.../include/s390x-linux-musl/bits/socket.h | 17 ---
.../include/s390x-linux-musl/bits/syscall.h | 6 +-
.../include/x86_64-linux-musl/bits/alltypes.h | 120 ++++++++--------
.../include/x86_64-linux-musl/bits/limits.h | 9 +-
.../include/x86_64-linux-musl/bits/socket.h | 16 ---
.../include/x86_64-linux-musl/bits/syscall.h | 6 +-
116 files changed, 1300 insertions(+), 1129 deletions(-)
delete mode 100644 lib/libc/include/aarch64-linux-musl/bits/endian.h
delete mode 100644 lib/libc/include/aarch64-linux-musl/bits/socket.h
delete mode 100644 lib/libc/include/arm-linux-musl/bits/endian.h
create mode 100644 lib/libc/include/arm-linux-musl/bits/ipcstat.h
delete mode 100644 lib/libc/include/arm-linux-musl/bits/limits.h
create mode 100644 lib/libc/include/generic-musl/bits/dirent.h
delete mode 100644 lib/libc/include/generic-musl/bits/endian.h
create mode 100644 lib/libc/include/i386-linux-musl/bits/ipcstat.h
delete mode 100644 lib/libc/include/mips-linux-musl/bits/endian.h
create mode 100644 lib/libc/include/mips-linux-musl/bits/ipcstat.h
delete mode 100644 lib/libc/include/mips-linux-musl/bits/limits.h
create mode 100644 lib/libc/include/mips-linux-musl/bits/sem.h
create mode 100644 lib/libc/include/mips-linux-musl/bits/shm.h
delete mode 100644 lib/libc/include/mips64-linux-musl/bits/endian.h
delete mode 100644 lib/libc/include/mips64-linux-musl/bits/limits.h
delete mode 100644 lib/libc/include/powerpc-linux-musl/bits/endian.h
create mode 100644 lib/libc/include/powerpc-linux-musl/bits/ipcstat.h
delete mode 100644 lib/libc/include/powerpc-linux-musl/bits/limits.h
delete mode 100644 lib/libc/include/powerpc64-linux-musl/bits/endian.h
delete mode 100644 lib/libc/include/riscv64-linux-musl/bits/reg.h
delete mode 100644 lib/libc/include/riscv64-linux-musl/bits/socket.h
delete mode 100644 lib/libc/include/s390x-linux-musl/bits/endian.h
delete mode 100644 lib/libc/include/s390x-linux-musl/bits/socket.h
delete mode 100644 lib/libc/include/x86_64-linux-musl/bits/socket.h
diff --git a/lib/libc/include/aarch64-linux-musl/bits/alltypes.h b/lib/libc/include/aarch64-linux-musl/bits/alltypes.h
index 0ee3cb4646b6f5fc31e73dfa3f84c425615eeb81..fd60fe3a0fb728206e9a1f0549d5f6ef7b3dc2f4 100644
--- a/lib/libc/include/aarch64-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/aarch64-linux-musl/bits/alltypes.h
@@ -2,16 +2,13 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
+#if __AARCH64EB__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
#endif
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -53,52 +50,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -135,6 +89,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -270,7 +234,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -366,6 +330,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -401,6 +376,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/aarch64-linux-musl/bits/endian.h b/lib/libc/include/aarch64-linux-musl/bits/endian.h
deleted file mode 100644
index 3ab24cc932287bfdb8170b6cda4f5f75b15c460b..0000000000000000000000000000000000000000
--- a/lib/libc/include/aarch64-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __AARCH64EB__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/aarch64-linux-musl/bits/socket.h b/lib/libc/include/aarch64-linux-musl/bits/socket.h
deleted file mode 100644
index b4e9fb6a1cd407ada73476d64b2a6c33ab649a9a..0000000000000000000000000000000000000000
--- a/lib/libc/include/aarch64-linux-musl/bits/socket.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
\ No newline at end of file
diff --git a/lib/libc/include/aarch64-linux-musl/bits/syscall.h b/lib/libc/include/aarch64-linux-musl/bits/syscall.h
index 53f296e037f3b08a1227a1b3ef0f39e763fc84ca..72392b874fc2a8974bc5cfb64d7471b399d84500 100644
--- a/lib/libc/include/aarch64-linux-musl/bits/syscall.h
+++ b/lib/libc/include/aarch64-linux-musl/bits/syscall.h
@@ -287,6 +287,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_io_setup 0
#define SYS_io_destroy 1
@@ -576,4 +578,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/alltypes.h b/lib/libc/include/arm-linux-musl/bits/alltypes.h
index d1ad5774d5ffece3f3b73fe21f4bd68d64833367..a99e771958b343664c34468e1668b5c88af635ce 100644
--- a/lib/libc/include/arm-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/arm-linux-musl/bits/alltypes.h
@@ -1,17 +1,15 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
+#if __ARMEB__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
#endif
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -37,52 +35,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -119,6 +74,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -254,7 +219,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -350,6 +315,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -385,6 +361,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/endian.h b/lib/libc/include/arm-linux-musl/bits/endian.h
deleted file mode 100644
index e4d86deb111d15b2e331e364e12649ec8155d03b..0000000000000000000000000000000000000000
--- a/lib/libc/include/arm-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __ARMEB__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/ipcstat.h b/lib/libc/include/arm-linux-musl/bits/ipcstat.h
new file mode 100644
index 0000000000000000000000000000000000000000..d055f3e83716e7d28975b2f1836b04e8714f793e
--- /dev/null
+++ b/lib/libc/include/arm-linux-musl/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/limits.h b/lib/libc/include/arm-linux-musl/bits/limits.h
deleted file mode 100644
index ba9c3aa003aea39ddb20eccc06cea142ec15de84..0000000000000000000000000000000000000000
--- a/lib/libc/include/arm-linux-musl/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/msg.h b/lib/libc/include/arm-linux-musl/bits/msg.h
index e5c8ba75208c2ed80da66995f1afe78fdab39893..037fd956d4fc97531893940f657f2ca61c5cc63d 100644
--- a/lib/libc/include/arm-linux-musl/bits/msg.h
+++ b/lib/libc/include/arm-linux-musl/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/sem.h b/lib/libc/include/arm-linux-musl/bits/sem.h
index 9097f9ffdb7e7474fe09be608ddafa8cb4c52e5b..eaa885a8b52bde814a4196fcef8a629b4b1c62a1 100644
--- a/lib/libc/include/arm-linux-musl/bits/sem.h
+++ b/lib/libc/include/arm-linux-musl/bits/sem.h
@@ -1,9 +1,9 @@
struct semid_ds {
struct ipc_perm sem_perm;
- time_t sem_otime;
- long __unused1;
- time_t sem_ctime;
- long __unused2;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -13,4 +13,6 @@ struct semid_ds {
#endif
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/shm.h b/lib/libc/include/arm-linux-musl/bits/shm.h
index aa5587127ab24a71b87e7bef5946234c46a9c916..1ecb03ca0e4ac95ea0a2c9c4236293ff024472ca 100644
--- a/lib/libc/include/arm-linux-musl/bits/shm.h
+++ b/lib/libc/include/arm-linux-musl/bits/shm.h
@@ -3,17 +3,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
- time_t shm_atime;
- int __unused1;
- time_t shm_dtime;
- int __unused2;
- time_t shm_ctime;
- int __unused3;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ unsigned long __pad3;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/include/arm-linux-musl/bits/stat.h b/lib/libc/include/arm-linux-musl/bits/stat.h
index 78e91b40281427d98133894da7574cde7e83396b..3bf02b37564c0380675344ce1e9f9d82395256bd 100644
--- a/lib/libc/include/arm-linux-musl/bits/stat.h
+++ b/lib/libc/include/arm-linux-musl/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ ino_t st_ino;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- ino_t st_ino;
};
\ No newline at end of file
diff --git a/lib/libc/include/arm-linux-musl/bits/syscall.h b/lib/libc/include/arm-linux-musl/bits/syscall.h
index 778430b8744a7f5cb036640cfcea33317a8407b1..5429a867e38363c47a20464b62adae2e8cfe84ee 100644
--- a/lib/libc/include/arm-linux-musl/bits/syscall.h
+++ b/lib/libc/include/arm-linux-musl/bits/syscall.h
@@ -55,8 +55,8 @@
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_symlink 83
@@ -211,14 +211,14 @@
#define __NR_remap_file_pages 253
#define __NR_set_tid_address 256
#define __NR_timer_create 257
-#define __NR_timer_settime 258
-#define __NR_timer_gettime 259
+#define __NR_timer_settime32 258
+#define __NR_timer_gettime32 259
#define __NR_timer_getoverrun 260
#define __NR_timer_delete 261
-#define __NR_clock_settime 262
-#define __NR_clock_gettime 263
-#define __NR_clock_getres 264
-#define __NR_clock_nanosleep 265
+#define __NR_clock_settime32 262
+#define __NR_clock_gettime32 263
+#define __NR_clock_getres_time32 264
+#define __NR_clock_nanosleep_time32 265
#define __NR_statfs64 266
#define __NR_fstatfs64 267
#define __NR_tgkill 268
@@ -308,8 +308,8 @@
#define __NR_timerfd_create 350
#define __NR_eventfd 351
#define __NR_fallocate 352
-#define __NR_timerfd_settime 353
-#define __NR_timerfd_gettime 354
+#define __NR_timerfd_settime32 353
+#define __NR_timerfd_gettime32 354
#define __NR_signalfd4 355
#define __NR_eventfd2 356
#define __NR_epoll_create1 357
@@ -387,6 +387,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define __ARM_NR_breakpoint 0x0f0001
#define __ARM_NR_cacheflush 0x0f0002
@@ -452,8 +454,8 @@
#define SYS_sethostname 74
#define SYS_setrlimit 75
#define SYS_getrusage 77
-#define SYS_gettimeofday 78
-#define SYS_settimeofday 79
+#define SYS_gettimeofday_time32 78
+#define SYS_settimeofday_time32 79
#define SYS_getgroups 80
#define SYS_setgroups 81
#define SYS_symlink 83
@@ -608,14 +610,14 @@
#define SYS_remap_file_pages 253
#define SYS_set_tid_address 256
#define SYS_timer_create 257
-#define SYS_timer_settime 258
-#define SYS_timer_gettime 259
+#define SYS_timer_settime32 258
+#define SYS_timer_gettime32 259
#define SYS_timer_getoverrun 260
#define SYS_timer_delete 261
-#define SYS_clock_settime 262
-#define SYS_clock_gettime 263
-#define SYS_clock_getres 264
-#define SYS_clock_nanosleep 265
+#define SYS_clock_settime32 262
+#define SYS_clock_gettime32 263
+#define SYS_clock_getres_time32 264
+#define SYS_clock_nanosleep_time32 265
#define SYS_statfs64 266
#define SYS_fstatfs64 267
#define SYS_tgkill 268
@@ -705,8 +707,8 @@
#define SYS_timerfd_create 350
#define SYS_eventfd 351
#define SYS_fallocate 352
-#define SYS_timerfd_settime 353
-#define SYS_timerfd_gettime 354
+#define SYS_timerfd_settime32 353
+#define SYS_timerfd_gettime32 354
#define SYS_signalfd4 355
#define SYS_eventfd2 356
#define SYS_epoll_create1 357
@@ -783,4 +785,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/aio.h b/lib/libc/include/generic-musl/aio.h
index 0830b10c2cdc733fc1d6d26c0b86f1ebbe68dd08..4588ff2e3941488a31089dc710522682502b6b97 100644
--- a/lib/libc/include/generic-musl/aio.h
+++ b/lib/libc/include/generic-musl/aio.h
@@ -62,6 +62,10 @@ int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sige
#define off64_t off_t
#endif
+#if _REDIR_TIME64
+__REDIR(aio_suspend, __aio_suspend_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/alloca.h b/lib/libc/include/generic-musl/alloca.h
index 53dd20479d29d8b51d406876569d642f480342ec..28390cee6b5577328f3a6ba5fddfc112c19e3a76 100644
--- a/lib/libc/include/generic-musl/alloca.h
+++ b/lib/libc/include/generic-musl/alloca.h
@@ -10,9 +10,7 @@ extern "C" {
void *alloca(size_t);
-#ifdef __GNUC__
#define alloca __builtin_alloca
-#endif
#ifdef __cplusplus
}
diff --git a/lib/libc/include/generic-musl/arpa/nameser.h b/lib/libc/include/generic-musl/arpa/nameser.h
index bd411459eb496fec950c06c96b79d5ace36b7049..10db66745e2235f1144ed7436dad32781146bcdd 100644
--- a/lib/libc/include/generic-musl/arpa/nameser.h
+++ b/lib/libc/include/generic-musl/arpa/nameser.h
@@ -7,7 +7,6 @@ extern "C" {
#include
#include
-#include
#define __NAMESER 19991006
#define NS_PACKETSZ 512
diff --git a/lib/libc/include/generic-musl/bits/dirent.h b/lib/libc/include/generic-musl/bits/dirent.h
new file mode 100644
index 0000000000000000000000000000000000000000..16f37f69828fb05197b5ac68c046ef37c520571d
--- /dev/null
+++ b/lib/libc/include/generic-musl/bits/dirent.h
@@ -0,0 +1,11 @@
+#define _DIRENT_HAVE_D_RECLEN
+#define _DIRENT_HAVE_D_OFF
+#define _DIRENT_HAVE_D_TYPE
+
+struct dirent {
+ ino_t d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/bits/endian.h b/lib/libc/include/generic-musl/bits/endian.h
deleted file mode 100644
index b1a7affbbb6f6a0f504b5ef4b4b2022d90636159..0000000000000000000000000000000000000000
--- a/lib/libc/include/generic-musl/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __LITTLE_ENDIAN
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/bits/ioctl.h b/lib/libc/include/generic-musl/bits/ioctl.h
index 3af94ce07ac75dc9d36e5c729ee7d325c21a3ab4..1f814548d3baf05173868d8c20d76e783ae8a0c8 100644
--- a/lib/libc/include/generic-musl/bits/ioctl.h
+++ b/lib/libc/include/generic-musl/bits/ioctl.h
@@ -104,7 +104,12 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
+#if __LONG_MAX == 0x7fffffff
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
+#else
#define SIOCGSTAMP 0x8906
#define SIOCGSTAMPNS 0x8907
+#endif
#include
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/bits/limits.h b/lib/libc/include/generic-musl/bits/limits.h
index 1be0deba7abfc5619657e0b90912d054efc53313..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/lib/libc/include/generic-musl/bits/limits.h
+++ b/lib/libc/include/generic-musl/bits/limits.h
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/bits/socket.h b/lib/libc/include/generic-musl/bits/socket.h
index 34aba4d2a22d0318a556880a69eb36cc8af74ce9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/lib/libc/include/generic-musl/bits/socket.h
+++ b/lib/libc/include/generic-musl/bits/socket.h
@@ -1,15 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/dirent.h b/lib/libc/include/generic-musl/dirent.h
index 2be943aa18d7dafade841c253e65382c7937462a..665c411a6f608dda465e7242defaa92d726866f6 100644
--- a/lib/libc/include/generic-musl/dirent.h
+++ b/lib/libc/include/generic-musl/dirent.h
@@ -15,20 +15,10 @@ extern "C" {
#include
+#include
+
typedef struct __dirstream DIR;
-#define _DIRENT_HAVE_D_RECLEN
-#define _DIRENT_HAVE_D_OFF
-#define _DIRENT_HAVE_D_TYPE
-
-struct dirent {
- ino_t d_ino;
- off_t d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[256];
-};
-
#define d_fileno d_ino
int closedir(DIR *);
diff --git a/lib/libc/include/generic-musl/dlfcn.h b/lib/libc/include/generic-musl/dlfcn.h
index 871f385859ad3961db79d9a5dd7c2aecb07a6eb3..c38b56c4707191aa5d3a58c3d164b7a84137a076 100644
--- a/lib/libc/include/generic-musl/dlfcn.h
+++ b/lib/libc/include/generic-musl/dlfcn.h
@@ -35,6 +35,10 @@ int dladdr(const void *, Dl_info *);
int dlinfo(void *, int, void *);
#endif
+#if _REDIR_TIME64
+__REDIR(dlsym, __dlsym_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/endian.h b/lib/libc/include/generic-musl/endian.h
index 35198b06a5ec13dbb1e3f6a1887c1a44638e7fd9..12b8d3038405b6c01d2506e98335ad0091aac4b1 100644
--- a/lib/libc/include/generic-musl/endian.h
+++ b/lib/libc/include/generic-musl/endian.h
@@ -3,25 +3,19 @@
#include
-#define __LITTLE_ENDIAN 1234
-#define __BIG_ENDIAN 4321
+#define __NEED_uint16_t
+#define __NEED_uint32_t
+#define __NEED_uint64_t
+
+#include
+
#define __PDP_ENDIAN 3412
-#if defined(__GNUC__) && defined(__BYTE_ORDER__)
-#define __BYTE_ORDER __BYTE_ORDER__
-#else
-#include
-#endif
-
-#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-
#define BIG_ENDIAN __BIG_ENDIAN
#define LITTLE_ENDIAN __LITTLE_ENDIAN
#define PDP_ENDIAN __PDP_ENDIAN
#define BYTE_ORDER __BYTE_ORDER
-#include
-
static __inline uint16_t __bswap16(uint16_t __x)
{
return __x<<8 | __x>>8;
@@ -40,43 +34,47 @@ static __inline uint64_t __bswap64(uint64_t __x)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define htobe16(x) __bswap16(x)
#define be16toh(x) __bswap16(x)
-#define betoh16(x) __bswap16(x)
#define htobe32(x) __bswap32(x)
#define be32toh(x) __bswap32(x)
-#define betoh32(x) __bswap32(x)
#define htobe64(x) __bswap64(x)
#define be64toh(x) __bswap64(x)
-#define betoh64(x) __bswap64(x)
#define htole16(x) (uint16_t)(x)
#define le16toh(x) (uint16_t)(x)
-#define letoh16(x) (uint16_t)(x)
#define htole32(x) (uint32_t)(x)
#define le32toh(x) (uint32_t)(x)
-#define letoh32(x) (uint32_t)(x)
#define htole64(x) (uint64_t)(x)
#define le64toh(x) (uint64_t)(x)
-#define letoh64(x) (uint64_t)(x)
#else
#define htobe16(x) (uint16_t)(x)
#define be16toh(x) (uint16_t)(x)
-#define betoh16(x) (uint16_t)(x)
#define htobe32(x) (uint32_t)(x)
#define be32toh(x) (uint32_t)(x)
-#define betoh32(x) (uint32_t)(x)
#define htobe64(x) (uint64_t)(x)
#define be64toh(x) (uint64_t)(x)
-#define betoh64(x) (uint64_t)(x)
#define htole16(x) __bswap16(x)
#define le16toh(x) __bswap16(x)
-#define letoh16(x) __bswap16(x)
#define htole32(x) __bswap32(x)
#define le32toh(x) __bswap32(x)
-#define letoh32(x) __bswap32(x)
#define htole64(x) __bswap64(x)
#define le64toh(x) __bswap64(x)
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define betoh16(x) __bswap16(x)
+#define betoh32(x) __bswap32(x)
+#define betoh64(x) __bswap64(x)
+#define letoh16(x) (uint16_t)(x)
+#define letoh32(x) (uint32_t)(x)
+#define letoh64(x) (uint64_t)(x)
+#else
+#define betoh16(x) (uint16_t)(x)
+#define betoh32(x) (uint32_t)(x)
+#define betoh64(x) (uint64_t)(x)
+#define letoh16(x) __bswap16(x)
+#define letoh32(x) __bswap32(x)
#define letoh64(x) __bswap64(x)
#endif
-
#endif
#endif
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/features.h b/lib/libc/include/generic-musl/features.h
index f649c1773b6c987593789c42450dc72ace073d42..6b8e6aa25acc63d2f5872085c83536ac3a7222ca 100644
--- a/lib/libc/include/generic-musl/features.h
+++ b/lib/libc/include/generic-musl/features.h
@@ -35,4 +35,6 @@
#define _Noreturn
#endif
+#define __REDIR(x,y) __typeof__(x) x __asm__(#y)
+
#endif
\ No newline at end of file
diff --git a/lib/libc/include/generic-musl/limits.h b/lib/libc/include/generic-musl/limits.h
index 38ad59e60187fd200e345bc5c9b17804a23db481..78db5b776ba57bbd2bc7142ded747d802c8f1447 100644
--- a/lib/libc/include/generic-musl/limits.h
+++ b/lib/libc/include/generic-musl/limits.h
@@ -3,9 +3,7 @@
#include
-/* Most limits are system-specific */
-
-#include
+#include /* __LONG_MAX */
/* Support signed or unsigned plain-char */
@@ -17,8 +15,6 @@
#define CHAR_MAX 127
#endif
-/* Some universal constants... */
-
#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
@@ -30,8 +26,10 @@
#define INT_MAX 0x7fffffff
#define UINT_MAX 0xffffffffU
#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MAX __LONG_MAX
#define ULONG_MAX (2UL*LONG_MAX+1)
#define LLONG_MIN (-LLONG_MAX-1)
+#define LLONG_MAX 0x7fffffffffffffffLL
#define ULLONG_MAX (2ULL*LLONG_MAX+1)
#define MB_LEN_MAX 4
@@ -39,9 +37,13 @@
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#include
+
#define PIPE_BUF 4096
#define FILESIZEBITS 64
+#ifndef NAME_MAX
#define NAME_MAX 255
+#endif
#define PATH_MAX 4096
#define NGROUPS_MAX 32
#define ARG_MAX 131072
@@ -53,6 +55,12 @@
#define TTY_NAME_MAX 32
#define HOST_NAME_MAX 255
+#if LONG_MAX == 0x7fffffffL
+#define LONG_BIT 32
+#else
+#define LONG_BIT 64
+#endif
+
/* Implementation choices... */
#define PTHREAD_KEYS_MAX 128
diff --git a/lib/libc/include/generic-musl/mqueue.h b/lib/libc/include/generic-musl/mqueue.h
index 917b80c2e348d73cc544cacdb9d250a295b2f5b5..1b0a1b16e34909b952f0a1619a342d4b77db32da 100644
--- a/lib/libc/include/generic-musl/mqueue.h
+++ b/lib/libc/include/generic-musl/mqueue.h
@@ -30,6 +30,11 @@ ssize_t mq_timedreceive(mqd_t, char *__restrict, size_t, unsigned *__restrict, c
int mq_timedsend(mqd_t, const char *, size_t, unsigned, const struct timespec *);
int mq_unlink(const char *);
+#if _REDIR_TIME64
+__REDIR(mq_timedreceive, __mq_timedreceive_time64);
+__REDIR(mq_timedsend, __mq_timedsend_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/netinet/icmp6.h b/lib/libc/include/generic-musl/netinet/icmp6.h
index 6419a5a0a78565c287dce8df328968f6e5c65597..44a2d8b0f3d8502271cb308e33e46d3b9f8e97e9 100644
--- a/lib/libc/include/generic-musl/netinet/icmp6.h
+++ b/lib/libc/include/generic-musl/netinet/icmp6.h
@@ -9,7 +9,6 @@ extern "C" {
#include
#include
#include
-#include
#define ICMP6_FILTER 1
diff --git a/lib/libc/include/generic-musl/netinet/if_ether.h b/lib/libc/include/generic-musl/netinet/if_ether.h
index 37d81698eb003fbf1665639974ee16b5cfc474e0..8be01cd4efd4861b54772d46b936d7a207da97b3 100644
--- a/lib/libc/include/generic-musl/netinet/if_ether.h
+++ b/lib/libc/include/generic-musl/netinet/if_ether.h
@@ -58,6 +58,7 @@
#define ETH_P_ERSPAN 0x88BE
#define ETH_P_PREAUTH 0x88C7
#define ETH_P_TIPC 0x88CA
+#define ETH_P_LLDP 0x88CC
#define ETH_P_MACSEC 0x88E5
#define ETH_P_8021AH 0x88E7
#define ETH_P_MVRP 0x88F5
diff --git a/lib/libc/include/generic-musl/netinet/ip.h b/lib/libc/include/generic-musl/netinet/ip.h
index 95baf6bdb1458082b926550f53be5835641c9a51..4a8a746f8ecfeeaf0102a1f522fcbaba420cfd29 100644
--- a/lib/libc/include/generic-musl/netinet/ip.h
+++ b/lib/libc/include/generic-musl/netinet/ip.h
@@ -7,7 +7,6 @@ extern "C" {
#include
#include
-#include
struct timestamp {
uint8_t len;
@@ -191,6 +190,8 @@ struct ip_timestamp {
#define IP_MSS 576
+#define __UAPI_DEF_IPHDR 0
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/netinet/ip6.h b/lib/libc/include/generic-musl/netinet/ip6.h
index cb1292a6476e9ef057b88612059de7855d52d339..dfb237795f345fad1444fd72c3ae051a534dbe00 100644
--- a/lib/libc/include/generic-musl/netinet/ip6.h
+++ b/lib/libc/include/generic-musl/netinet/ip6.h
@@ -7,7 +7,6 @@ extern "C" {
#include
#include
-#include
struct ip6_hdr {
union {
diff --git a/lib/libc/include/generic-musl/netinet/tcp.h b/lib/libc/include/generic-musl/netinet/tcp.h
index 949f701493aaa2b0a3836cafb9e88162f6057348..f0bdb1923279e6ab0d8d70104c9676810d2966e0 100644
--- a/lib/libc/include/generic-musl/netinet/tcp.h
+++ b/lib/libc/include/generic-musl/netinet/tcp.h
@@ -38,6 +38,7 @@
#define TCP_FASTOPEN_NO_COOKIE 34
#define TCP_ZEROCOPY_RECEIVE 35
#define TCP_INQ 36
+#define TCP_TX_DELAY 37
#define TCP_CM_INQ TCP_INQ
@@ -97,7 +98,6 @@ enum {
#include
#include
#include
-#include
typedef uint32_t tcp_seq;
@@ -234,6 +234,8 @@ struct tcp_info {
uint64_t tcpi_bytes_retrans;
uint32_t tcpi_dsack_dups;
uint32_t tcpi_reord_seen;
+ uint32_t tcpi_rcv_ooopack;
+ uint32_t tcpi_snd_wnd;
};
#define TCP_MD5SIG_MAXKEYLEN 80
diff --git a/lib/libc/include/generic-musl/poll.h b/lib/libc/include/generic-musl/poll.h
index be58c6417462c1a9a2f39fcf138facaa5b2cd79a..45078b866dabf961baa350b5a21d6b65b8035689 100644
--- a/lib/libc/include/generic-musl/poll.h
+++ b/lib/libc/include/generic-musl/poll.h
@@ -44,6 +44,12 @@ int poll (struct pollfd *, nfds_t, int);
int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
#endif
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(ppoll, __ppoll_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/pthread.h b/lib/libc/include/generic-musl/pthread.h
index 6bfa3a5acec93bb299c73ecb5cd70e643c5e7607..e812c675c2620f23386905bcec165c01a740d623 100644
--- a/lib/libc/include/generic-musl/pthread.h
+++ b/lib/libc/include/generic-musl/pthread.h
@@ -224,6 +224,16 @@ int pthread_tryjoin_np(pthread_t, void **);
int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
#endif
+#if _REDIR_TIME64
+__REDIR(pthread_mutex_timedlock, __pthread_mutex_timedlock_time64);
+__REDIR(pthread_cond_timedwait, __pthread_cond_timedwait_time64);
+__REDIR(pthread_rwlock_timedrdlock, __pthread_rwlock_timedrdlock_time64);
+__REDIR(pthread_rwlock_timedwrlock, __pthread_rwlock_timedwrlock_time64);
+#ifdef _GNU_SOURCE
+__REDIR(pthread_timedjoin_np, __pthread_timedjoin_np_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sched.h b/lib/libc/include/generic-musl/sched.h
index 7963785f67b34ad59657117c0943a94381091ab2..6225d25d5389b28ed2bd0429a2745f4fba59152c 100644
--- a/lib/libc/include/generic-musl/sched.h
+++ b/lib/libc/include/generic-musl/sched.h
@@ -19,10 +19,14 @@ extern "C" {
struct sched_param {
int sched_priority;
int __reserved1;
+#if _REDIR_TIME64
+ long __reserved2[4];
+#else
struct {
time_t __reserved1;
long __reserved2;
} __reserved2[2];
+#endif
int __reserved3;
};
@@ -133,6 +137,10 @@ __CPU_op_func_S(XOR, ^)
#endif
+#if _REDIR_TIME64
+__REDIR(sched_rr_get_interval, __sched_rr_get_interval_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/semaphore.h b/lib/libc/include/generic-musl/semaphore.h
index 52f956ad23a870446c6c739ff08d879abf1f020b..8f26fb75f79612084402f881bdb5f65329667eb5 100644
--- a/lib/libc/include/generic-musl/semaphore.h
+++ b/lib/libc/include/generic-musl/semaphore.h
@@ -29,6 +29,10 @@ int sem_trywait(sem_t *);
int sem_unlink(const char *);
int sem_wait(sem_t *);
+#if _REDIR_TIME64
+__REDIR(sem_timedwait, __sem_timedwait_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/signal.h b/lib/libc/include/generic-musl/signal.h
index 37ee858c48af971425591fb3e3f648d13c166507..99d473c50eef56628955d347ccfd9ddc42892149 100644
--- a/lib/libc/include/generic-musl/signal.h
+++ b/lib/libc/include/generic-musl/signal.h
@@ -271,6 +271,14 @@ typedef int sig_atomic_t;
void (*signal(int, void (*)(int)))(int);
int raise(int);
+#if _REDIR_TIME64
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+ || defined(_BSD_SOURCE)
+__REDIR(sigtimedwait, __sigtimedwait_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/acct.h b/lib/libc/include/generic-musl/sys/acct.h
index 02e4c7887cf89c1c871bd43ee8bd2048c7f5b952..b4161dec6b540ad607e7aceeab8563c501a6045c 100644
--- a/lib/libc/include/generic-musl/sys/acct.h
+++ b/lib/libc/include/generic-musl/sys/acct.h
@@ -6,7 +6,6 @@ extern "C" {
#endif
#include
-#include
#include
#include
diff --git a/lib/libc/include/generic-musl/sys/ioctl.h b/lib/libc/include/generic-musl/sys/ioctl.h
index 7d3a88079a14f56cb1450ced47b18c0b7975b335..28c9b6e24fb7e06cf5aaf0d7cc33eb941ab2ab50 100644
--- a/lib/libc/include/generic-musl/sys/ioctl.h
+++ b/lib/libc/include/generic-musl/sys/ioctl.h
@@ -4,6 +4,7 @@
extern "C" {
#endif
+#include
#include
#define N_TTY 0
diff --git a/lib/libc/include/generic-musl/sys/mman.h b/lib/libc/include/generic-musl/sys/mman.h
index 85c605b75f0d32312a2fa8f7a2aaaf4f9692c5d3..9bfd0a1075f45d0b820bb3c41c18b886e7ba7c6b 100644
--- a/lib/libc/include/generic-musl/sys/mman.h
+++ b/lib/libc/include/generic-musl/sys/mman.h
@@ -92,6 +92,8 @@ extern "C" {
#define MADV_DODUMP 17
#define MADV_WIPEONFORK 18
#define MADV_KEEPONFORK 19
+#define MADV_COLD 20
+#define MADV_PAGEOUT 21
#define MADV_HWPOISON 100
#define MADV_SOFT_OFFLINE 101
#endif
diff --git a/lib/libc/include/generic-musl/sys/prctl.h b/lib/libc/include/generic-musl/sys/prctl.h
index 4cc6567f936fb63c0522162664f387ca9d33befe..c5f79d86d2e59050957b6dab69a558681bdec049 100644
--- a/lib/libc/include/generic-musl/sys/prctl.h
+++ b/lib/libc/include/generic-musl/sys/prctl.h
@@ -154,6 +154,10 @@ struct prctl_mm_map {
#define PR_PAC_APDBKEY (1UL << 3)
#define PR_PAC_APGAKEY (1UL << 4)
+#define PR_SET_TAGGED_ADDR_CTRL 55
+#define PR_GET_TAGGED_ADDR_CTRL 56
+#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+
int prctl (int, ...);
#ifdef __cplusplus
diff --git a/lib/libc/include/generic-musl/sys/procfs.h b/lib/libc/include/generic-musl/sys/procfs.h
index 6c255d3a8beb6f7f0325f8816161089fa9a0db5d..03db62abfa40f4efaabe70aec2d63818cc792501 100644
--- a/lib/libc/include/generic-musl/sys/procfs.h
+++ b/lib/libc/include/generic-musl/sys/procfs.h
@@ -23,10 +23,9 @@ struct elf_prstatus {
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
- struct timeval pr_utime;
- struct timeval pr_stime;
- struct timeval pr_cutime;
- struct timeval pr_cstime;
+ struct {
+ long tv_sec, tv_usec;
+ } pr_utime, pr_stime, pr_cutime, pr_cstime;
elf_gregset_t pr_reg;
int pr_fpvalid;
};
diff --git a/lib/libc/include/generic-musl/sys/ptrace.h b/lib/libc/include/generic-musl/sys/ptrace.h
index a37ef97bcfda7638777c521fbed016960008289c..1f0c6890fee218cecbffac72a316a8bb8fae2887 100644
--- a/lib/libc/include/generic-musl/sys/ptrace.h
+++ b/lib/libc/include/generic-musl/sys/ptrace.h
@@ -41,6 +41,7 @@ extern "C" {
#define PTRACE_SETSIGMASK 0x420b
#define PTRACE_SECCOMP_GET_FILTER 0x420c
#define PTRACE_SECCOMP_GET_METADATA 0x420d
+#define PTRACE_GET_SYSCALL_INFO 0x420e
#define PT_READ_I PTRACE_PEEKTEXT
#define PT_READ_D PTRACE_PEEKDATA
@@ -88,6 +89,11 @@ extern "C" {
#define PTRACE_PEEKSIGINFO_SHARED 1
+#define PTRACE_SYSCALL_INFO_NONE 0
+#define PTRACE_SYSCALL_INFO_ENTRY 1
+#define PTRACE_SYSCALL_INFO_EXIT 2
+#define PTRACE_SYSCALL_INFO_SECCOMP 3
+
#include
struct __ptrace_peeksiginfo_args {
@@ -101,6 +107,29 @@ struct __ptrace_seccomp_metadata {
uint64_t flags;
};
+struct __ptrace_syscall_info {
+ uint8_t op;
+ uint8_t __pad[3];
+ uint32_t arch;
+ uint64_t instruction_pointer;
+ uint64_t stack_pointer;
+ union {
+ struct {
+ uint64_t nr;
+ uint64_t args[6];
+ } entry;
+ struct {
+ int64_t rval;
+ uint8_t is_error;
+ } exit;
+ struct {
+ uint64_t nr;
+ uint64_t args[6];
+ uint32_t ret_data;
+ } seccomp;
+ };
+};
+
long ptrace(int, ...);
#ifdef __cplusplus
diff --git a/lib/libc/include/generic-musl/sys/resource.h b/lib/libc/include/generic-musl/sys/resource.h
index 90def956e6c4971f602f42131eb6949bd2649519..8ef18ec050691f4417c563ea15b3eca9b3b71f4f 100644
--- a/lib/libc/include/generic-musl/sys/resource.h
+++ b/lib/libc/include/generic-musl/sys/resource.h
@@ -90,7 +90,8 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
#define RLIMIT_MSGQUEUE 12
#define RLIMIT_NICE 13
#define RLIMIT_RTPRIO 14
-#define RLIMIT_NLIMITS 15
+#define RLIMIT_RTTIME 15
+#define RLIMIT_NLIMITS 16
#define RLIM_NLIMITS RLIMIT_NLIMITS
@@ -104,6 +105,10 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
#define rlim64_t rlim_t
#endif
+#if _REDIR_TIME64
+__REDIR(getrusage, __getrusage_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/select.h b/lib/libc/include/generic-musl/sys/select.h
index 1a54ab5880c1027f99bae544b0006fb862be3002..8ebe0c8b083f562a5a72db18826eaa5eacccafdf 100644
--- a/lib/libc/include/generic-musl/sys/select.h
+++ b/lib/libc/include/generic-musl/sys/select.h
@@ -35,6 +35,11 @@ int pselect (int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, co
#define NFDBITS (8*(int)sizeof(long))
#endif
+#if _REDIR_TIME64
+__REDIR(select, __select_time64);
+__REDIR(pselect, __pselect_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/sem.h b/lib/libc/include/generic-musl/sys/sem.h
index 95e5d9433c668395a80a5d52e5a071267ae9daf7..41362fab28a3dcedd9c2c00c7b8f2a1047d72d6f 100644
--- a/lib/libc/include/generic-musl/sys/sem.h
+++ b/lib/libc/include/generic-musl/sys/sem.h
@@ -25,8 +25,6 @@ extern "C" {
#define SETVAL 16
#define SETALL 17
-#include
-
#include
#define _SEM_SEMUN_UNDEFINED 1
@@ -62,6 +60,12 @@ int semop(int, struct sembuf *, size_t);
int semtimedop(int, struct sembuf *, size_t, const struct timespec *);
#endif
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(semtimedop, __semtimedop_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/socket.h b/lib/libc/include/generic-musl/sys/socket.h
index 2c82ee12b209d698d32c877eb916629f4957cdbe..957d3da9f0dc86e677544601822ef5af7c4ec7b5 100644
--- a/lib/libc/include/generic-musl/sys/socket.h
+++ b/lib/libc/include/generic-musl/sys/socket.h
@@ -19,6 +19,40 @@ extern "C" {
#include
+struct msghdr {
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+ int __pad1;
+#endif
+ int msg_iovlen;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+ int __pad1;
+#endif
+ void *msg_control;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+ int __pad2;
+#endif
+ socklen_t msg_controllen;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+ int __pad2;
+#endif
+ int msg_flags;
+};
+
+struct cmsghdr {
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+ int __pad1;
+#endif
+ socklen_t cmsg_len;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+ int __pad1;
+#endif
+ int cmsg_level;
+ int cmsg_type;
+};
+
#ifdef _GNU_SOURCE
struct ucred {
pid_t pid;
@@ -182,8 +216,6 @@ struct linger {
#define SO_PEERCRED 17
#define SO_RCVLOWAT 18
#define SO_SNDLOWAT 19
-#define SO_RCVTIMEO 20
-#define SO_SNDTIMEO 21
#define SO_ACCEPTCONN 30
#define SO_PEERSEC 31
#define SO_SNDBUFFORCE 32
@@ -192,6 +224,28 @@ struct linger {
#define SO_DOMAIN 39
#endif
+#ifndef SO_RCVTIMEO
+#if __LONG_MAX == 0x7fffffff
+#define SO_RCVTIMEO 66
+#define SO_SNDTIMEO 67
+#else
+#define SO_RCVTIMEO 20
+#define SO_SNDTIMEO 21
+#endif
+#endif
+
+#ifndef SO_TIMESTAMP
+#if __LONG_MAX == 0x7fffffff
+#define SO_TIMESTAMP 63
+#define SO_TIMESTAMPNS 64
+#define SO_TIMESTAMPING 65
+#else
+#define SO_TIMESTAMP 29
+#define SO_TIMESTAMPNS 35
+#define SO_TIMESTAMPING 37
+#endif
+#endif
+
#define SO_SECURITY_AUTHENTICATION 22
#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
#define SO_SECURITY_ENCRYPTION_NETWORK 24
@@ -203,14 +257,10 @@ struct linger {
#define SO_GET_FILTER SO_ATTACH_FILTER
#define SO_PEERNAME 28
-#define SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
-
#define SO_PASSSEC 34
-#define SO_TIMESTAMPNS 35
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#define SO_MARK 36
-#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
#define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
@@ -238,6 +288,7 @@ struct linger {
#define SO_TXTIME 61
#define SCM_TXTIME SO_TXTIME
#define SO_BINDTOIFINDEX 62
+#define SO_DETACH_REUSEPORT_BPF 68
#ifndef SOL_SOCKET
#define SOL_SOCKET 1
@@ -350,6 +401,12 @@ int setsockopt (int, int, int, const void *, socklen_t);
int sockatmark (int);
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(recvmmsg, __recvmmsg_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/stat.h b/lib/libc/include/generic-musl/sys/stat.h
index 521b873afa13c2dbc4095b6e7c483112ed769b2a..e8a3753445ed321eb60580d2b0de97694a056be0 100644
--- a/lib/libc/include/generic-musl/sys/stat.h
+++ b/lib/libc/include/generic-musl/sys/stat.h
@@ -110,6 +110,15 @@ int lchmod(const char *, mode_t);
#define off64_t off_t
#endif
+#if _REDIR_TIME64
+__REDIR(stat, __stat_time64);
+__REDIR(fstat, __fstat_time64);
+__REDIR(lstat, __lstat_time64);
+__REDIR(fstatat, __fstatat_time64);
+__REDIR(futimens, __futimens_time64);
+__REDIR(utimensat, __utimensat_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/statvfs.h b/lib/libc/include/generic-musl/sys/statvfs.h
index b2fb003b324ba927a7224016ae8fe3890ce16bd1..0da838f1ef94c07ca87fa24c520bd71ff7abe640 100644
--- a/lib/libc/include/generic-musl/sys/statvfs.h
+++ b/lib/libc/include/generic-musl/sys/statvfs.h
@@ -11,8 +11,6 @@ extern "C" {
#define __NEED_fsfilcnt_t
#include
-#include
-
struct statvfs {
unsigned long f_bsize, f_frsize;
fsblkcnt_t f_blocks, f_bfree, f_bavail;
diff --git a/lib/libc/include/generic-musl/sys/time.h b/lib/libc/include/generic-musl/sys/time.h
index cb3022c7789078b49ad7e3195a30eca4058e180c..301c098ab43cab078655638fe25de7279e553e51 100644
--- a/lib/libc/include/generic-musl/sys/time.h
+++ b/lib/libc/include/generic-musl/sys/time.h
@@ -56,6 +56,20 @@ int adjtime (const struct timeval *, struct timeval *);
(void)0 )
#endif
+#if _REDIR_TIME64
+__REDIR(gettimeofday, __gettimeofday_time64);
+__REDIR(getitimer, __getitimer_time64);
+__REDIR(setitimer, __setitimer_time64);
+__REDIR(utimes, __utimes_time64);
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(futimes, __futimes_time64);
+__REDIR(futimesat, __futimesat_time64);
+__REDIR(lutimes, __lutimes_time64);
+__REDIR(settimeofday, __settimeofday_time64);
+__REDIR(adjtime, __adjtime64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/timeb.h b/lib/libc/include/generic-musl/sys/timeb.h
index acbde569f28bfc0979f3da2ed56d22800d7d02c6..6da1226b16a16791724cf5ab826029ac6104f711 100644
--- a/lib/libc/include/generic-musl/sys/timeb.h
+++ b/lib/libc/include/generic-musl/sys/timeb.h
@@ -4,6 +4,8 @@
extern "C" {
#endif
+#include
+
#define __NEED_time_t
#include
@@ -16,6 +18,10 @@ struct timeb {
int ftime(struct timeb *);
+#if _REDIR_TIME64
+__REDIR(ftime, __ftime64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/timerfd.h b/lib/libc/include/generic-musl/sys/timerfd.h
index 3bea27f45a2031afa8d8ba6677ca8abc15ef2449..ff158861cff5329c9c5586374263d5fa2918264a 100644
--- a/lib/libc/include/generic-musl/sys/timerfd.h
+++ b/lib/libc/include/generic-musl/sys/timerfd.h
@@ -20,6 +20,11 @@ int timerfd_create(int, int);
int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *);
int timerfd_gettime(int, struct itimerspec *);
+#if _REDIR_TIME64
+__REDIR(timerfd_settime, __timerfd_settime64);
+__REDIR(timerfd_gettime, __timerfd_gettime64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/timex.h b/lib/libc/include/generic-musl/sys/timex.h
index fc42fc653bd3f3d2360ecb10f7272008bcd81304..cab33a954cacb1ae14ab73ad40a84b54331ac5ea 100644
--- a/lib/libc/include/generic-musl/sys/timex.h
+++ b/lib/libc/include/generic-musl/sys/timex.h
@@ -91,6 +91,11 @@ struct timex {
int adjtimex(struct timex *);
int clock_adjtime(clockid_t, struct timex *);
+#if _REDIR_TIME64
+__REDIR(adjtimex, __adjtimex_time64);
+__REDIR(clock_adjtime, __clock_adjtime64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/sys/ttydefaults.h b/lib/libc/include/generic-musl/sys/ttydefaults.h
index 2324873319a1e966499e61c7487380582975ca5d..602a4af79ae0fa7adc93c6ceca8703e8b8f18592 100644
--- a/lib/libc/include/generic-musl/sys/ttydefaults.h
+++ b/lib/libc/include/generic-musl/sys/ttydefaults.h
@@ -6,16 +6,11 @@
#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
#define TTYDEF_CFLAG (CREAD | CS7 | PARENB | HUPCL)
#define TTYDEF_SPEED (B9600)
-#define CTRL(x) (x&037)
+#define CTRL(x) ((x)&037)
#define CEOF CTRL('d')
-#ifdef _POSIX_VDISABLE
-#define CEOL _POSIX_VDISABLE
-#define CSTATUS _POSIX_VDISABLE
-#else
#define CEOL '\0'
#define CSTATUS '\0'
-#endif
#define CERASE 0177
#define CINTR CTRL('c')
diff --git a/lib/libc/include/generic-musl/sys/wait.h b/lib/libc/include/generic-musl/sys/wait.h
index 352fdcadf1ba510a27b34cf367db88c7e7a13cd2..0ad11ab54f9417e29704d0b5e9de001b548ad3ab 100644
--- a/lib/libc/include/generic-musl/sys/wait.h
+++ b/lib/libc/include/generic-musl/sys/wait.h
@@ -13,7 +13,8 @@ extern "C" {
typedef enum {
P_ALL = 0,
P_PID = 1,
- P_PGID = 2
+ P_PGID = 2,
+ P_PIDFD = 3
} idtype_t;
pid_t wait (int *);
@@ -53,6 +54,13 @@ pid_t wait4 (pid_t, int *, int, struct rusage *);
#define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu)
#define WIFCONTINUED(s) ((s) == 0xffff)
+#if _REDIR_TIME64
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(wait3, __wait3_time64);
+__REDIR(wait4, __wait4_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/threads.h b/lib/libc/include/generic-musl/threads.h
index 51ef3bad7b25b67ecb5b214d9dd0fdabaf20d790..cecff6647c445ac50ca49e8b7ee9dd71bf751ebf 100644
--- a/lib/libc/include/generic-musl/threads.h
+++ b/lib/libc/include/generic-musl/threads.h
@@ -80,6 +80,12 @@ void tss_delete(tss_t);
int tss_set(tss_t, void *);
void *tss_get(tss_t);
+#if _REDIR_TIME64
+__REDIR(thrd_sleep, __thrd_sleep_time64);
+__REDIR(mtx_timedlock, __mtx_timedlock_time64);
+__REDIR(cnd_timedwait, __cnd_timedwait_time64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/time.h b/lib/libc/include/generic-musl/time.h
index 755c6ad7aa04f1bebb9e8a0097a7ce211bfe5cdc..5a9f61eb4d6a22cda03a5624ebbf18aeb14a4283 100644
--- a/lib/libc/include/generic-musl/time.h
+++ b/lib/libc/include/generic-musl/time.h
@@ -130,6 +130,34 @@ int stime(const time_t *);
time_t timegm(struct tm *);
#endif
+#if _REDIR_TIME64
+__REDIR(time, __time64);
+__REDIR(difftime, __difftime64);
+__REDIR(mktime, __mktime64);
+__REDIR(gmtime, __gmtime64);
+__REDIR(localtime, __localtime64);
+__REDIR(ctime, __ctime64);
+__REDIR(timespec_get, __timespec_get_time64);
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+ || defined(_BSD_SOURCE)
+__REDIR(gmtime_r, __gmtime64_r);
+__REDIR(localtime_r, __localtime64_r);
+__REDIR(ctime_r, __ctime64_r);
+__REDIR(nanosleep, __nanosleep_time64);
+__REDIR(clock_getres, __clock_getres_time64);
+__REDIR(clock_gettime, __clock_gettime64);
+__REDIR(clock_settime, __clock_settime64);
+__REDIR(clock_nanosleep, __clock_nanosleep_time64);
+__REDIR(timer_settime, __timer_settime64);
+__REDIR(timer_gettime, __timer_gettime64);
+#endif
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(stime, __stime64);
+__REDIR(timegm, __timegm_time64);
+#endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/utime.h b/lib/libc/include/generic-musl/utime.h
index 89c2bc8013b1f45fcde894bceef59a76e257b8f9..1ad5c49c5d8580b012f005803aa79e2c707f8ff5 100644
--- a/lib/libc/include/generic-musl/utime.h
+++ b/lib/libc/include/generic-musl/utime.h
@@ -5,6 +5,8 @@
extern "C" {
#endif
+#include
+
#define __NEED_time_t
#include
@@ -16,6 +18,10 @@ struct utimbuf {
int utime (const char *, const struct utimbuf *);
+#if _REDIR_TIME64
+__REDIR(utime, __utime64);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/generic-musl/utmpx.h b/lib/libc/include/generic-musl/utmpx.h
index 769101a2fe9d959409f1ef0ecaab6f442a804a57..29fa60d2f1a6135c827f5de653d3f12c157a9174 100644
--- a/lib/libc/include/generic-musl/utmpx.h
+++ b/lib/libc/include/generic-musl/utmpx.h
@@ -16,6 +16,7 @@ extern "C" {
struct utmpx {
short ut_type;
+ short __ut_pad1;
pid_t ut_pid;
char ut_line[32];
char ut_id[4];
@@ -25,7 +26,11 @@ struct utmpx {
short __e_termination;
short __e_exit;
} ut_exit;
- long ut_session;
+#if __BYTE_ORDER == 1234
+ int ut_session, __ut_pad2;
+#else
+ int __ut_pad2, ut_session;
+#endif
struct timeval ut_tv;
unsigned ut_addr_v6[4];
char __unused[20];
diff --git a/lib/libc/include/i386-linux-musl/bits/alltypes.h b/lib/libc/include/i386-linux-musl/bits/alltypes.h
index b4a1272fe6a6db92b31add2741c4e9a4aa647047..c330f5dd05962d0bd3958cb8cd6e1c9c741dde7c 100644
--- a/lib/libc/include/i386-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/i386-linux-musl/bits/alltypes.h
@@ -1,30 +1,10 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-#if __GNUC__ >= 3
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
-#else
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef struct __va_list * va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef struct __va_list * __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
-#endif
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#ifdef __WCHAR_TYPE__
@@ -85,52 +65,9 @@ typedef struct { alignas(8) long long __ll; long double __ld; } max_align_t;
#endif
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -167,6 +104,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -302,7 +249,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -398,6 +345,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -433,6 +391,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/ipcstat.h b/lib/libc/include/i386-linux-musl/bits/ipcstat.h
new file mode 100644
index 0000000000000000000000000000000000000000..d055f3e83716e7d28975b2f1836b04e8714f793e
--- /dev/null
+++ b/lib/libc/include/i386-linux-musl/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/limits.h b/lib/libc/include/i386-linux-musl/bits/limits.h
index 208e36bcd7438919a9145fbd447a7b7329991d65..fc11433d980df7405e8995f67023006f0f5b85c6 100644
--- a/lib/libc/include/i386-linux-musl/bits/limits.h
+++ b/lib/libc/include/i386-linux-musl/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define PAGESIZE 4096
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
+#define PAGESIZE 4096
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/msg.h b/lib/libc/include/i386-linux-musl/bits/msg.h
index e5c8ba75208c2ed80da66995f1afe78fdab39893..037fd956d4fc97531893940f657f2ca61c5cc63d 100644
--- a/lib/libc/include/i386-linux-musl/bits/msg.h
+++ b/lib/libc/include/i386-linux-musl/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/sem.h b/lib/libc/include/i386-linux-musl/bits/sem.h
index e63d0732bb46a1de99588265deaf5b98b6bf2930..f4936d6f5aad4b0d64de7158623fc9532be97e81 100644
--- a/lib/libc/include/i386-linux-musl/bits/sem.h
+++ b/lib/libc/include/i386-linux-musl/bits/sem.h
@@ -1,11 +1,13 @@
struct semid_ds {
struct ipc_perm sem_perm;
- time_t sem_otime;
- long __unused1;
- time_t sem_ctime;
- long __unused2;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/shm.h b/lib/libc/include/i386-linux-musl/bits/shm.h
index aa5587127ab24a71b87e7bef5946234c46a9c916..1ecb03ca0e4ac95ea0a2c9c4236293ff024472ca 100644
--- a/lib/libc/include/i386-linux-musl/bits/shm.h
+++ b/lib/libc/include/i386-linux-musl/bits/shm.h
@@ -3,17 +3,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
- time_t shm_atime;
- int __unused1;
- time_t shm_dtime;
- int __unused2;
- time_t shm_ctime;
- int __unused3;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ unsigned long __pad3;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/include/i386-linux-musl/bits/stat.h b/lib/libc/include/i386-linux-musl/bits/stat.h
index 78e91b40281427d98133894da7574cde7e83396b..3bf02b37564c0380675344ce1e9f9d82395256bd 100644
--- a/lib/libc/include/i386-linux-musl/bits/stat.h
+++ b/lib/libc/include/i386-linux-musl/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ ino_t st_ino;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- ino_t st_ino;
};
\ No newline at end of file
diff --git a/lib/libc/include/i386-linux-musl/bits/syscall.h b/lib/libc/include/i386-linux-musl/bits/syscall.h
index 482f1d1d19c4c2933235746c27184dd3509fc88a..c9bfc7f95e077f5ed9d5c4cf5c832076ef24982b 100644
--- a/lib/libc/include/i386-linux-musl/bits/syscall.h
+++ b/lib/libc/include/i386-linux-musl/bits/syscall.h
@@ -76,8 +76,8 @@
#define __NR_setrlimit 75
#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
@@ -257,14 +257,14 @@
#define __NR_remap_file_pages 257
#define __NR_set_tid_address 258
#define __NR_timer_create 259
-#define __NR_timer_settime (__NR_timer_create+1)
-#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_settime32 (__NR_timer_create+1)
+#define __NR_timer_gettime32 (__NR_timer_create+2)
#define __NR_timer_getoverrun (__NR_timer_create+3)
#define __NR_timer_delete (__NR_timer_create+4)
-#define __NR_clock_settime (__NR_timer_create+5)
-#define __NR_clock_gettime (__NR_timer_create+6)
-#define __NR_clock_getres (__NR_timer_create+7)
-#define __NR_clock_nanosleep (__NR_timer_create+8)
+#define __NR_clock_settime32 (__NR_timer_create+5)
+#define __NR_clock_gettime32 (__NR_timer_create+6)
+#define __NR_clock_getres_time32 (__NR_timer_create+7)
+#define __NR_clock_nanosleep_time32 (__NR_timer_create+8)
#define __NR_statfs64 268
#define __NR_fstatfs64 269
#define __NR_tgkill 270
@@ -322,8 +322,8 @@
#define __NR_timerfd_create 322
#define __NR_eventfd 323
#define __NR_fallocate 324
-#define __NR_timerfd_settime 325
-#define __NR_timerfd_gettime 326
+#define __NR_timerfd_settime32 325
+#define __NR_timerfd_gettime32 326
#define __NR_signalfd4 327
#define __NR_eventfd2 328
#define __NR_epoll_create1 329
@@ -424,6 +424,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -503,8 +505,8 @@
#define SYS_setrlimit 75
#define SYS_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define SYS_getrusage 77
-#define SYS_gettimeofday 78
-#define SYS_settimeofday 79
+#define SYS_gettimeofday_time32 78
+#define SYS_settimeofday_time32 79
#define SYS_getgroups 80
#define SYS_setgroups 81
#define SYS_select 82
@@ -682,14 +684,14 @@
#define SYS_remap_file_pages 257
#define SYS_set_tid_address 258
#define SYS_timer_create 259
-#define SYS_timer_settime (__NR_timer_create+1)
-#define SYS_timer_gettime (__NR_timer_create+2)
+#define SYS_timer_settime32 (__NR_timer_create+1)
+#define SYS_timer_gettime32 (__NR_timer_create+2)
#define SYS_timer_getoverrun (__NR_timer_create+3)
#define SYS_timer_delete (__NR_timer_create+4)
-#define SYS_clock_settime (__NR_timer_create+5)
-#define SYS_clock_gettime (__NR_timer_create+6)
-#define SYS_clock_getres (__NR_timer_create+7)
-#define SYS_clock_nanosleep (__NR_timer_create+8)
+#define SYS_clock_settime32 (__NR_timer_create+5)
+#define SYS_clock_gettime32 (__NR_timer_create+6)
+#define SYS_clock_getres_time32 (__NR_timer_create+7)
+#define SYS_clock_nanosleep_time32 (__NR_timer_create+8)
#define SYS_statfs64 268
#define SYS_fstatfs64 269
#define SYS_tgkill 270
@@ -747,8 +749,8 @@
#define SYS_timerfd_create 322
#define SYS_eventfd 323
#define SYS_fallocate 324
-#define SYS_timerfd_settime 325
-#define SYS_timerfd_gettime 326
+#define SYS_timerfd_settime32 325
+#define SYS_timerfd_gettime32 326
#define SYS_signalfd4 327
#define SYS_eventfd2 328
#define SYS_epoll_create1 329
@@ -848,4 +850,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/alltypes.h b/lib/libc/include/mips-linux-musl/bits/alltypes.h
index d0f00474bd8fda7b70f9b62af72bfe8d811c2328..c714577aaac4be6ba32723daf077b7d8cec18f4c 100644
--- a/lib/libc/include/mips-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/mips-linux-musl/bits/alltypes.h
@@ -1,17 +1,15 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
+#if _MIPSEL || __MIPSEL || __MIPSEL__
+#define __BYTE_ORDER 1234
+#else
+#define __BYTE_ORDER 4321
#endif
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -37,52 +35,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -119,6 +74,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -254,7 +219,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -350,6 +315,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -385,6 +361,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/endian.h b/lib/libc/include/mips-linux-musl/bits/endian.h
deleted file mode 100644
index e888a1939f559d2e58684c14e938f8dea4a962fd..0000000000000000000000000000000000000000
--- a/lib/libc/include/mips-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if _MIPSEL || __MIPSEL || __MIPSEL__
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/hwcap.h b/lib/libc/include/mips-linux-musl/bits/hwcap.h
index 0cc1faa9f77a1596dcbba04310760c3901611f86..bcdd936f16c81849cb4a8b1f93258ccbba60b250 100644
--- a/lib/libc/include/mips-linux-musl/bits/hwcap.h
+++ b/lib/libc/include/mips-linux-musl/bits/hwcap.h
@@ -1,3 +1,14 @@
#define HWCAP_MIPS_R6 (1 << 0)
#define HWCAP_MIPS_MSA (1 << 1)
-#define HWCAP_MIPS_CRC32 (1 << 2)
\ No newline at end of file
+#define HWCAP_MIPS_CRC32 (1 << 2)
+#define HWCAP_MIPS_MIPS16 (1 << 3)
+#define HWCAP_MIPS_MDMX (1 << 4)
+#define HWCAP_MIPS_MIPS3D (1 << 5)
+#define HWCAP_MIPS_SMARTMIPS (1 << 6)
+#define HWCAP_MIPS_DSP (1 << 7)
+#define HWCAP_MIPS_DSP2 (1 << 8)
+#define HWCAP_MIPS_DSP3 (1 << 9)
+#define HWCAP_MIPS_MIPS16E2 (1 << 10)
+#define HWCAP_LOONGSON_MMI (1 << 11)
+#define HWCAP_LOONGSON_EXT (1 << 12)
+#define HWCAP_LOONGSON_EXT2 (1 << 13)
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/ioctl.h b/lib/libc/include/mips-linux-musl/bits/ioctl.h
index ce20d2e760859b557f23e37cd91c009b211b2e35..c4fbd0d8dfa26f399852fd726df2c50ec00d49de 100644
--- a/lib/libc/include/mips-linux-musl/bits/ioctl.h
+++ b/lib/libc/include/mips-linux-musl/bits/ioctl.h
@@ -110,5 +110,5 @@
#define SIOCATMARK _IOR('s', 7, int)
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
\ No newline at end of file
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/ipcstat.h b/lib/libc/include/mips-linux-musl/bits/ipcstat.h
new file mode 100644
index 0000000000000000000000000000000000000000..d055f3e83716e7d28975b2f1836b04e8714f793e
--- /dev/null
+++ b/lib/libc/include/mips-linux-musl/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/limits.h b/lib/libc/include/mips-linux-musl/bits/limits.h
deleted file mode 100644
index ba9c3aa003aea39ddb20eccc06cea142ec15de84..0000000000000000000000000000000000000000
--- a/lib/libc/include/mips-linux-musl/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/msg.h b/lib/libc/include/mips-linux-musl/bits/msg.h
index f310867d192bcbb664f4c174350c018af5762369..9e428cabd53e2fa8c105bae01ae615741cf7f91d 100644
--- a/lib/libc/include/mips-linux-musl/bits/msg.h
+++ b/lib/libc/include/mips-linux-musl/bits/msg.h
@@ -1,19 +1,19 @@
struct msqid_ds {
struct ipc_perm msg_perm;
#if _MIPSEL || __MIPSEL || __MIPSEL__
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
#else
- int __unused1;
- time_t msg_stime;
- int __unused2;
- time_t msg_rtime;
- int __unused3;
- time_t msg_ctime;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long __msg_ctime_lo;
#endif
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
@@ -21,4 +21,7 @@ struct msqid_ds {
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/sem.h b/lib/libc/include/mips-linux-musl/bits/sem.h
new file mode 100644
index 0000000000000000000000000000000000000000..87b05d488d13c7b568c5b8f59ac5b62b5742f8b0
--- /dev/null
+++ b/lib/libc/include/mips-linux-musl/bits/sem.h
@@ -0,0 +1,16 @@
+struct semid_ds {
+ struct ipc_perm sem_perm;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_ctime_lo;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned short sem_nsems;
+ char __sem_nsems_pad[sizeof(long)-sizeof(short)];
+#else
+ char __sem_nsems_pad[sizeof(long)-sizeof(short)];
+ unsigned short sem_nsems;
+#endif
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_hi;
+ time_t sem_otime;
+ time_t sem_ctime;
+};
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/shm.h b/lib/libc/include/mips-linux-musl/bits/shm.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e5357d24f3d60abab4d06f5bf482a932272abff
--- /dev/null
+++ b/lib/libc/include/mips-linux-musl/bits/shm.h
@@ -0,0 +1,29 @@
+#define SHMLBA 4096
+
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_ctime_lo;
+ pid_t shm_cpid;
+ pid_t shm_lpid;
+ unsigned long shm_nattch;
+ unsigned short __shm_atime_hi;
+ unsigned short __shm_dtime_hi;
+ unsigned short __shm_ctime_hi;
+ unsigned short __pad1;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+};
+
+struct shminfo {
+ unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+ int __used_ids;
+ unsigned long shm_tot, shm_rss, shm_swp;
+ unsigned long __swap_attempts, __swap_successes;
+};
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/signal.h b/lib/libc/include/mips-linux-musl/bits/signal.h
index 8a7d5852ed141264cfb950c300fdcaec3bf7bacb..f9a6ea657a41f6f15b7d07af6204a95f4132f81d 100644
--- a/lib/libc/include/mips-linux-musl/bits/signal.h
+++ b/lib/libc/include/mips-linux-musl/bits/signal.h
@@ -19,14 +19,18 @@ typedef struct {
} fpregset_t;
struct sigcontext {
unsigned sc_regmask, sc_status;
- unsigned long long sc_pc, sc_regs[32], sc_fpregs[32];
+ unsigned long long sc_pc;
+ gregset_t sc_regs;
+ fpregset_t sc_fpregs;
unsigned sc_ownedfp, sc_fpc_csr, sc_fpc_eir, sc_used_math, sc_dsp;
unsigned long long sc_mdhi, sc_mdlo;
unsigned long sc_hi1, sc_lo1, sc_hi2, sc_lo2, sc_hi3, sc_lo3;
};
typedef struct {
unsigned regmask, status;
- unsigned long long pc, gregs[32], fpregs[32];
+ unsigned long long pc;
+ gregset_t gregs;
+ fpregset_t fpregs;
unsigned ownedfp, fpc_csr, fpc_eir, used_math, dsp;
unsigned long long mdhi, mdlo;
unsigned long hi1, lo1, hi2, lo2, hi3, lo3;
diff --git a/lib/libc/include/mips-linux-musl/bits/socket.h b/lib/libc/include/mips-linux-musl/bits/socket.h
index dd4c03b7f6e788370135ba401b066ecf8be22a37..751f71fc475d68b8132a422bc79a1541c66ae34d 100644
--- a/lib/libc/include/mips-linux-musl/bits/socket.h
+++ b/lib/libc/include/mips-linux-musl/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
#define SOCK_STREAM 2
#define SOCK_DGRAM 1
@@ -32,8 +16,6 @@ struct cmsghdr {
#define SO_RCVBUF 0x1002
#define SO_SNDLOWAT 0x1003
#define SO_RCVLOWAT 0x1004
-#define SO_RCVTIMEO 0x1006
-#define SO_SNDTIMEO 0x1005
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
#define SO_ACCEPTCONN 0x1009
diff --git a/lib/libc/include/mips-linux-musl/bits/stat.h b/lib/libc/include/mips-linux-musl/bits/stat.h
index 5e9d7ce475aed6cd502044184891ff07fb2fef94..f247f6983de595c9da9a615a39242383d015e3f5 100644
--- a/lib/libc/include/mips-linux-musl/bits/stat.h
+++ b/lib/libc/include/mips-linux-musl/bits/stat.h
@@ -12,11 +12,15 @@ struct stat {
dev_t st_rdev;
long __st_padding2[2];
off_t st_size;
- struct timespec st_atim;
- struct timespec st_mtim;
- struct timespec st_ctim;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
blksize_t st_blksize;
long __st_padding3;
blkcnt_t st_blocks;
- long __st_padding4[14];
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+ long __st_padding4[2];
};
\ No newline at end of file
diff --git a/lib/libc/include/mips-linux-musl/bits/syscall.h b/lib/libc/include/mips-linux-musl/bits/syscall.h
index 67bd95fa5c78eb931329e01122bcc9627ff48ece..3f2666e56f6138d76a03018d1cb3a5e4f8bbf952 100644
--- a/lib/libc/include/mips-linux-musl/bits/syscall.h
+++ b/lib/libc/include/mips-linux-musl/bits/syscall.h
@@ -76,8 +76,8 @@
#define __NR_setrlimit 4075
#define __NR_getrlimit 4076
#define __NR_getrusage 4077
-#define __NR_gettimeofday 4078
-#define __NR_settimeofday 4079
+#define __NR_gettimeofday_time32 4078
+#define __NR_settimeofday_time32 4079
#define __NR_getgroups 4080
#define __NR_setgroups 4081
#define __NR_reserved82 4082
@@ -256,14 +256,14 @@
#define __NR_statfs64 4255
#define __NR_fstatfs64 4256
#define __NR_timer_create 4257
-#define __NR_timer_settime 4258
-#define __NR_timer_gettime 4259
+#define __NR_timer_settime32 4258
+#define __NR_timer_gettime32 4259
#define __NR_timer_getoverrun 4260
#define __NR_timer_delete 4261
-#define __NR_clock_settime 4262
-#define __NR_clock_gettime 4263
-#define __NR_clock_getres 4264
-#define __NR_clock_nanosleep 4265
+#define __NR_clock_settime32 4262
+#define __NR_clock_gettime32 4263
+#define __NR_clock_getres_time32 4264
+#define __NR_clock_nanosleep_time32 4265
#define __NR_tgkill 4266
#define __NR_utimes 4267
#define __NR_mbind 4268
@@ -319,8 +319,8 @@
#define __NR_eventfd 4319
#define __NR_fallocate 4320
#define __NR_timerfd_create 4321
-#define __NR_timerfd_gettime 4322
-#define __NR_timerfd_settime 4323
+#define __NR_timerfd_gettime32 4322
+#define __NR_timerfd_settime32 4323
#define __NR_signalfd4 4324
#define __NR_eventfd2 4325
#define __NR_epoll_create1 4326
@@ -406,6 +406,8 @@
#define __NR_fsconfig 4431
#define __NR_fsmount 4432
#define __NR_fspick 4433
+#define __NR_pidfd_open 4434
+#define __NR_clone3 4435
#define SYS_syscall 4000
#define SYS_exit 4001
@@ -485,8 +487,8 @@
#define SYS_setrlimit 4075
#define SYS_getrlimit 4076
#define SYS_getrusage 4077
-#define SYS_gettimeofday 4078
-#define SYS_settimeofday 4079
+#define SYS_gettimeofday_time32 4078
+#define SYS_settimeofday_time32 4079
#define SYS_getgroups 4080
#define SYS_setgroups 4081
#define SYS_reserved82 4082
@@ -665,14 +667,14 @@
#define SYS_statfs64 4255
#define SYS_fstatfs64 4256
#define SYS_timer_create 4257
-#define SYS_timer_settime 4258
-#define SYS_timer_gettime 4259
+#define SYS_timer_settime32 4258
+#define SYS_timer_gettime32 4259
#define SYS_timer_getoverrun 4260
#define SYS_timer_delete 4261
-#define SYS_clock_settime 4262
-#define SYS_clock_gettime 4263
-#define SYS_clock_getres 4264
-#define SYS_clock_nanosleep 4265
+#define SYS_clock_settime32 4262
+#define SYS_clock_gettime32 4263
+#define SYS_clock_getres_time32 4264
+#define SYS_clock_nanosleep_time32 4265
#define SYS_tgkill 4266
#define SYS_utimes 4267
#define SYS_mbind 4268
@@ -728,8 +730,8 @@
#define SYS_eventfd 4319
#define SYS_fallocate 4320
#define SYS_timerfd_create 4321
-#define SYS_timerfd_gettime 4322
-#define SYS_timerfd_settime 4323
+#define SYS_timerfd_gettime32 4322
+#define SYS_timerfd_settime32 4323
#define SYS_signalfd4 4324
#define SYS_eventfd2 4325
#define SYS_epoll_create1 4326
@@ -814,4 +816,6 @@
#define SYS_fsopen 4430
#define SYS_fsconfig 4431
#define SYS_fsmount 4432
-#define SYS_fspick 4433
\ No newline at end of file
+#define SYS_fspick 4433
+#define SYS_pidfd_open 4434
+#define SYS_clone3 4435
\ No newline at end of file
diff --git a/lib/libc/include/mips64-linux-musl/bits/alltypes.h b/lib/libc/include/mips64-linux-musl/bits/alltypes.h
index 2078964487f3c70f41ac8f61b52935d2da428745..9745553d1671a4bd140f8a0f680d869fc5cdb211 100644
--- a/lib/libc/include/mips64-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/mips64-linux-musl/bits/alltypes.h
@@ -2,16 +2,13 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
+#if _MIPSEL || __MIPSEL || __MIPSEL__
+#define __BYTE_ORDER 1234
+#else
+#define __BYTE_ORDER 4321
#endif
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -38,57 +35,14 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#endif
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t)
typedef unsigned nlink_t;
#define __DEFINED_nlink_t
#endif
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -125,6 +79,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -260,7 +224,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -356,6 +320,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -391,6 +366,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/mips64-linux-musl/bits/endian.h b/lib/libc/include/mips64-linux-musl/bits/endian.h
deleted file mode 100644
index e888a1939f559d2e58684c14e938f8dea4a962fd..0000000000000000000000000000000000000000
--- a/lib/libc/include/mips64-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if _MIPSEL || __MIPSEL || __MIPSEL__
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/mips64-linux-musl/bits/limits.h b/lib/libc/include/mips64-linux-musl/bits/limits.h
deleted file mode 100644
index ac11a8d7bf616d40717cfe0ccc0849e442b3c64d..0000000000000000000000000000000000000000
--- a/lib/libc/include/mips64-linux-musl/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
diff --git a/lib/libc/include/mips64-linux-musl/bits/socket.h b/lib/libc/include/mips64-linux-musl/bits/socket.h
index 87d555b12d1340ecae980a9e4a22a17e677f84b9..4207084528add35103ae62ae84c93341bc01d319 100644
--- a/lib/libc/include/mips64-linux-musl/bits/socket.h
+++ b/lib/libc/include/mips64-linux-musl/bits/socket.h
@@ -1,37 +1,3 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
-
#define SOCK_STREAM 2
#define SOCK_DGRAM 1
#define SOL_SOCKET 65535
diff --git a/lib/libc/include/mips64-linux-musl/bits/syscall.h b/lib/libc/include/mips64-linux-musl/bits/syscall.h
index e14881035bda3b57217a9cfce9033e5307b36453..b3d86fe1d838bfb768fcc5c4c477c2ff468fba79 100644
--- a/lib/libc/include/mips64-linux-musl/bits/syscall.h
+++ b/lib/libc/include/mips64-linux-musl/bits/syscall.h
@@ -336,6 +336,8 @@
#define __NR_fsconfig 5431
#define __NR_fsmount 5432
#define __NR_fspick 5433
+#define __NR_pidfd_open 5434
+#define __NR_clone3 5435
#define SYS_read 5000
#define SYS_write 5001
@@ -674,4 +676,6 @@
#define SYS_fsopen 5430
#define SYS_fsconfig 5431
#define SYS_fsmount 5432
-#define SYS_fspick 5433
\ No newline at end of file
+#define SYS_fspick 5433
+#define SYS_pidfd_open 5434
+#define SYS_clone3 5435
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/alltypes.h b/lib/libc/include/powerpc-linux-musl/bits/alltypes.h
index f94f3e2f448a60ac270b946171e0bb296274f439..f655b43e3ddce0fe12df528ebb18cbe4ce7669cd 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/alltypes.h
@@ -1,17 +1,10 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
+#define __BYTE_ORDER 4321
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#ifdef __WCHAR_TYPE__
@@ -45,52 +38,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -127,6 +77,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -262,7 +222,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -358,6 +318,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -393,6 +364,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/endian.h b/lib/libc/include/powerpc-linux-musl/bits/endian.h
deleted file mode 100644
index ca2af1ed577b135232fc013836d070d18354f3fc..0000000000000000000000000000000000000000
--- a/lib/libc/include/powerpc-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifdef __BIG_ENDIAN__
- #if __BIG_ENDIAN__
- #define __BYTE_ORDER __BIG_ENDIAN
- #endif
-#endif /* __BIG_ENDIAN__ */
-
-#ifdef __LITTLE_ENDIAN__
- #if __LITTLE_ENDIAN__
- #define __BYTE_ORDER __LITTLE_ENDIAN
- #endif
-#endif /* __LITTLE_ENDIAN__ */
-
-#ifndef __BYTE_ORDER
- #define __BYTE_ORDER __BIG_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/ioctl.h b/lib/libc/include/powerpc-linux-musl/bits/ioctl.h
index 98eff9a7d502534fe14b23986c93fed9a888b22c..bce4b193204688816f96d6aeb7a5b80d9e294b76 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/ioctl.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/ioctl.h
@@ -116,5 +116,5 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
\ No newline at end of file
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/ipcstat.h b/lib/libc/include/powerpc-linux-musl/bits/ipcstat.h
new file mode 100644
index 0000000000000000000000000000000000000000..d055f3e83716e7d28975b2f1836b04e8714f793e
--- /dev/null
+++ b/lib/libc/include/powerpc-linux-musl/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/limits.h b/lib/libc/include/powerpc-linux-musl/bits/limits.h
deleted file mode 100644
index ba9c3aa003aea39ddb20eccc06cea142ec15de84..0000000000000000000000000000000000000000
--- a/lib/libc/include/powerpc-linux-musl/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/msg.h b/lib/libc/include/powerpc-linux-musl/bits/msg.h
index 1bbca229c7fa5bfed72bf5f5b77bef6c2a017bec..9232e03800d56ec4525043cb166b7688c189c555 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/msg.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- int __unused1;
- time_t msg_stime;
- int __unused2;
- time_t msg_rtime;
- int __unused3;
- time_t msg_ctime;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long __msg_ctime_lo;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/sem.h b/lib/libc/include/powerpc-linux-musl/bits/sem.h
index fefd211aa9eba35ed5b6fd2fbe2cd114a7413ec6..715a0ac85c3bdaf210ad15f44869f21c1a523e0b 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/sem.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/sem.h
@@ -1,10 +1,12 @@
struct semid_ds {
struct ipc_perm sem_perm;
- int __unused1;
- time_t sem_otime;
- int __unused2;
- time_t sem_ctime;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_ctime_hi;
+ unsigned long __sem_ctime_lo;
unsigned short __sem_nsems_pad, sem_nsems;
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/shm.h b/lib/libc/include/powerpc-linux-musl/bits/shm.h
index ef46d7f1010a90b1910c483689beb2cf8c5c9598..e45c2ab19a700dddbd09d3a09907319bc66749e0 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/shm.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/shm.h
@@ -2,19 +2,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
- int __unused1;
- time_t shm_atime;
- int __unused2;
- time_t shm_dtime;
- int __unused3;
- time_t shm_ctime;
- int __unused4;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_ctime_hi;
+ unsigned long __shm_ctime_lo;
size_t shm_segsz;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/include/powerpc-linux-musl/bits/signal.h b/lib/libc/include/powerpc-linux-musl/bits/signal.h
index 12e00013168ea0bbb6330d358c2dbf58aea31908..48051afb6332c6d5465de62812b0aeb24fdaa53d 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/signal.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/signal.h
@@ -28,7 +28,7 @@ struct sigcontext {
int signal;
unsigned long handler;
unsigned long oldmask;
- void *regs;
+ struct pt_regs *regs;
};
typedef struct {
diff --git a/lib/libc/include/powerpc-linux-musl/bits/socket.h b/lib/libc/include/powerpc-linux-musl/bits/socket.h
index ba5e2b50d2c30979d51f99473c0cbf614d023cbf..4225b9177925668f11a7071055d3e382315bee39 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/socket.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
@@ -31,8 +15,6 @@ struct cmsghdr {
#define SO_REUSEPORT 15
#define SO_RCVLOWAT 16
#define SO_SNDLOWAT 17
-#define SO_RCVTIMEO 18
-#define SO_SNDTIMEO 19
#define SO_PASSCRED 20
#define SO_PEERCRED 21
#define SO_ACCEPTCONN 30
diff --git a/lib/libc/include/powerpc-linux-musl/bits/stat.h b/lib/libc/include/powerpc-linux-musl/bits/stat.h
index e5298772daca95f03ec78c9261f9dfc68d10eb61..fa6d8dfdb8b09a20b5e7f57268f4ee91a2744403 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/stat.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/stat.h
@@ -13,8 +13,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ unsigned __unused[2];
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- unsigned __unused[2];
};
\ No newline at end of file
diff --git a/lib/libc/include/powerpc-linux-musl/bits/syscall.h b/lib/libc/include/powerpc-linux-musl/bits/syscall.h
index 888868ad5c4d47d931e6f0ccd6eb923538d04f0a..ce2818352c6deb4ca216939aa978ae1333217587 100644
--- a/lib/libc/include/powerpc-linux-musl/bits/syscall.h
+++ b/lib/libc/include/powerpc-linux-musl/bits/syscall.h
@@ -76,8 +76,8 @@
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
@@ -238,14 +238,14 @@
#define __NR_epoll_wait 238
#define __NR_remap_file_pages 239
#define __NR_timer_create 240
-#define __NR_timer_settime 241
-#define __NR_timer_gettime 242
+#define __NR_timer_settime32 241
+#define __NR_timer_gettime32 242
#define __NR_timer_getoverrun 243
#define __NR_timer_delete 244
-#define __NR_clock_settime 245
-#define __NR_clock_gettime 246
-#define __NR_clock_getres 247
-#define __NR_clock_nanosleep 248
+#define __NR_clock_settime32 245
+#define __NR_clock_gettime32 246
+#define __NR_clock_getres_time32 247
+#define __NR_clock_nanosleep_time32 248
#define __NR_swapcontext 249
#define __NR_tgkill 250
#define __NR_utimes 251
@@ -307,8 +307,8 @@
#define __NR_sync_file_range2 308
#define __NR_fallocate 309
#define __NR_subpage_prot 310
-#define __NR_timerfd_settime 311
-#define __NR_timerfd_gettime 312
+#define __NR_timerfd_settime32 311
+#define __NR_timerfd_gettime32 312
#define __NR_signalfd4 313
#define __NR_eventfd2 314
#define __NR_epoll_create1 315
@@ -413,6 +413,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -492,8 +494,8 @@
#define SYS_setrlimit 75
#define SYS_getrlimit 76
#define SYS_getrusage 77
-#define SYS_gettimeofday 78
-#define SYS_settimeofday 79
+#define SYS_gettimeofday_time32 78
+#define SYS_settimeofday_time32 79
#define SYS_getgroups 80
#define SYS_setgroups 81
#define SYS_select 82
@@ -654,14 +656,14 @@
#define SYS_epoll_wait 238
#define SYS_remap_file_pages 239
#define SYS_timer_create 240
-#define SYS_timer_settime 241
-#define SYS_timer_gettime 242
+#define SYS_timer_settime32 241
+#define SYS_timer_gettime32 242
#define SYS_timer_getoverrun 243
#define SYS_timer_delete 244
-#define SYS_clock_settime 245
-#define SYS_clock_gettime 246
-#define SYS_clock_getres 247
-#define SYS_clock_nanosleep 248
+#define SYS_clock_settime32 245
+#define SYS_clock_gettime32 246
+#define SYS_clock_getres_time32 247
+#define SYS_clock_nanosleep_time32 248
#define SYS_swapcontext 249
#define SYS_tgkill 250
#define SYS_utimes 251
@@ -723,8 +725,8 @@
#define SYS_sync_file_range2 308
#define SYS_fallocate 309
#define SYS_subpage_prot 310
-#define SYS_timerfd_settime 311
-#define SYS_timerfd_gettime 312
+#define SYS_timerfd_settime32 311
+#define SYS_timerfd_gettime32 312
#define SYS_signalfd4 313
#define SYS_eventfd2 314
#define SYS_epoll_create1 315
@@ -828,4 +830,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/powerpc64-linux-musl/bits/alltypes.h b/lib/libc/include/powerpc64-linux-musl/bits/alltypes.h
index b650fe8f9a1f7efbadf8167e63e8222911d91fd1..6177874ffa5f0340531b72ba43c91f67bd51e290 100644
--- a/lib/libc/include/powerpc64-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/powerpc64-linux-musl/bits/alltypes.h
@@ -2,16 +2,13 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
+#if __BIG_ENDIAN__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
#endif
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -37,52 +34,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -119,6 +73,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -254,7 +218,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -350,6 +314,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -385,6 +360,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/powerpc64-linux-musl/bits/endian.h b/lib/libc/include/powerpc64-linux-musl/bits/endian.h
deleted file mode 100644
index 4f3a41f0c199caa54eb6809a3692514569a7d914..0000000000000000000000000000000000000000
--- a/lib/libc/include/powerpc64-linux-musl/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __BIG_ENDIAN__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/powerpc64-linux-musl/bits/signal.h b/lib/libc/include/powerpc64-linux-musl/bits/signal.h
index c312b0d4590a946a89523f17ea5a3f4307024d1b..de82cf9ec77037e82fe86e1a894ba3b1f17b4267 100644
--- a/lib/libc/include/powerpc64-linux-musl/bits/signal.h
+++ b/lib/libc/include/powerpc64-linux-musl/bits/signal.h
@@ -9,11 +9,7 @@
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef unsigned long greg_t, gregset_t[48];
-
-typedef struct {
- double fpregs[32];
- double fpscr;
-} fpregset_t;
+typedef double fpregset_t[33];
typedef struct {
#ifdef __GNUC__
@@ -36,7 +32,7 @@ typedef struct sigcontext {
int _pad0;
unsigned long handler;
unsigned long oldmask;
- void *regs;
+ struct pt_regs *regs;
gregset_t gp_regs;
fpregset_t fp_regs;
vrregset_t *v_regs;
diff --git a/lib/libc/include/powerpc64-linux-musl/bits/socket.h b/lib/libc/include/powerpc64-linux-musl/bits/socket.h
index d453d65ce4a05434714ed21fb17c55d73bba9a32..1fa551d93e3c8dc05cbe6c0382d4d519acac93df 100644
--- a/lib/libc/include/powerpc64-linux-musl/bits/socket.h
+++ b/lib/libc/include/powerpc64-linux-musl/bits/socket.h
@@ -1,37 +1,3 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
-
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
diff --git a/lib/libc/include/powerpc64-linux-musl/bits/syscall.h b/lib/libc/include/powerpc64-linux-musl/bits/syscall.h
index 38b8263144a80fa0a20c97757b66b2d9b823905f..4592aac64db178d8c26915c52754461746f55130 100644
--- a/lib/libc/include/powerpc64-linux-musl/bits/syscall.h
+++ b/lib/libc/include/powerpc64-linux-musl/bits/syscall.h
@@ -385,6 +385,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -772,4 +774,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/riscv64-linux-musl/bits/alltypes.h b/lib/libc/include/riscv64-linux-musl/bits/alltypes.h
index c326d32774a904616a9cbbf649bcf84206a916d0..8db53c82938482111d07d463ef63c8e4b6048194 100644
--- a/lib/libc/include/riscv64-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/riscv64-linux-musl/bits/alltypes.h
@@ -2,16 +2,8 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -48,52 +40,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -130,6 +79,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -265,7 +224,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -361,6 +320,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -396,6 +366,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/riscv64-linux-musl/bits/reg.h b/lib/libc/include/riscv64-linux-musl/bits/reg.h
deleted file mode 100644
index b449472ae91ff047c331d97a8d893d0802753d29..0000000000000000000000000000000000000000
--- a/lib/libc/include/riscv64-linux-musl/bits/reg.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#undef __WORDSIZE
-#define __WORDSIZE 64
-#define REG_PC 0
-#define REG_RA 1
-#define REG_SP 2
-#define REG_TP 4
-#define REG_S0 8
-#define REG_A0 10
\ No newline at end of file
diff --git a/lib/libc/include/riscv64-linux-musl/bits/signal.h b/lib/libc/include/riscv64-linux-musl/bits/signal.h
index 5eddfd18bc98a267216e137865bbf164eae45150..87ae2ee7d1b8bc93c54b1060ef5d67903b3263d0 100644
--- a/lib/libc/include/riscv64-linux-musl/bits/signal.h
+++ b/lib/libc/include/riscv64-linux-musl/bits/signal.h
@@ -35,6 +35,15 @@ typedef struct mcontext_t {
union __riscv_mc_fp_state __fpregs;
} mcontext_t;
+#if defined(_GNU_SOURCE)
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
+#endif
+
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef unsigned long greg_t;
typedef unsigned long gregset_t[32];
diff --git a/lib/libc/include/riscv64-linux-musl/bits/socket.h b/lib/libc/include/riscv64-linux-musl/bits/socket.h
deleted file mode 100644
index dfedbe836f02d690e89a502b2d80aa4bf0c153d4..0000000000000000000000000000000000000000
--- a/lib/libc/include/riscv64-linux-musl/bits/socket.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen, __pad1;
- void *msg_control;
- socklen_t msg_controllen;
- int __pad2;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int __pad1;
- int cmsg_level;
- int cmsg_type;
-};
\ No newline at end of file
diff --git a/lib/libc/include/riscv64-linux-musl/bits/syscall.h b/lib/libc/include/riscv64-linux-musl/bits/syscall.h
index 423de02ab13da2e568ef2882b1ed987f0e4f81e9..808207fb4b4472270d29ebd8680b86a63eee8e43 100644
--- a/lib/libc/include/riscv64-linux-musl/bits/syscall.h
+++ b/lib/libc/include/riscv64-linux-musl/bits/syscall.h
@@ -287,6 +287,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
@@ -579,5 +581,7 @@
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
#define SYS_sysriscv __NR_arch_specific_syscall
#define SYS_riscv_flush_icache (__NR_sysriscv + 15)
\ No newline at end of file
diff --git a/lib/libc/include/s390x-linux-musl/bits/alltypes.h b/lib/libc/include/s390x-linux-musl/bits/alltypes.h
index e831219e08e3350a4a1187e9c7fbc5f6754ef5c8..55dbfa500cfe81f41eb9dcdf6cca67faf26d2a4d 100644
--- a/lib/libc/include/s390x-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/s390x-linux-musl/bits/alltypes.h
@@ -2,16 +2,8 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
+#define __BYTE_ORDER 4321
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -37,52 +29,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -119,6 +68,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -254,7 +213,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -350,6 +309,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -385,6 +355,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/s390x-linux-musl/bits/endian.h b/lib/libc/include/s390x-linux-musl/bits/endian.h
deleted file mode 100644
index 19063e7423a14c881e033008f6d9e4d25068407b..0000000000000000000000000000000000000000
--- a/lib/libc/include/s390x-linux-musl/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __BIG_ENDIAN
\ No newline at end of file
diff --git a/lib/libc/include/s390x-linux-musl/bits/limits.h b/lib/libc/include/s390x-linux-musl/bits/limits.h
index e984295854e013fc250a8c8b81bce9731e458843..fc11433d980df7405e8995f67023006f0f5b85c6 100644
--- a/lib/libc/include/s390x-linux-musl/bits/limits.h
+++ b/lib/libc/include/s390x-linux-musl/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define PAGESIZE 4096
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
+#define PAGESIZE 4096
\ No newline at end of file
diff --git a/lib/libc/include/s390x-linux-musl/bits/socket.h b/lib/libc/include/s390x-linux-musl/bits/socket.h
deleted file mode 100644
index decce207336b7a45b438793938f3c9b5bf409ddb..0000000000000000000000000000000000000000
--- a/lib/libc/include/s390x-linux-musl/bits/socket.h
+++ /dev/null
@@ -1,17 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int __pad1, msg_iovlen;
- void *msg_control;
- int __pad2;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- int __pad1;
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
\ No newline at end of file
diff --git a/lib/libc/include/s390x-linux-musl/bits/syscall.h b/lib/libc/include/s390x-linux-musl/bits/syscall.h
index e2436d95c8f4756634ab5924e129e9a16945f961..790f5137362634e46e3ca499810f69a5d5424c7c 100644
--- a/lib/libc/include/s390x-linux-musl/bits/syscall.h
+++ b/lib/libc/include/s390x-linux-musl/bits/syscall.h
@@ -350,6 +350,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_exit 1
#define SYS_fork 2
@@ -702,4 +704,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-linux-musl/bits/alltypes.h b/lib/libc/include/x86_64-linux-musl/bits/alltypes.h
index ec6a904f5884e06687b7580401c5e37416a9f6ad..7418a4823444d8c3f97d0fe5d556cbabaf6f6689 100644
--- a/lib/libc/include/x86_64-linux-musl/bits/alltypes.h
+++ b/lib/libc/include/x86_64-linux-musl/bits/alltypes.h
@@ -2,16 +2,8 @@
#define _Int64 long
#define _Reg long
-#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
-typedef __builtin_va_list va_list;
-#define __DEFINED_va_list
-#endif
-
-#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
-typedef __builtin_va_list __isoc_va_list;
-#define __DEFINED___isoc_va_list
-#endif
-
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
@@ -50,52 +42,9 @@ typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
-
-#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
-typedef long time_t;
-#define __DEFINED_time_t
-#endif
-
-#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
-typedef long suseconds_t;
-#define __DEFINED_suseconds_t
-#endif
-
-
-#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-#define __DEFINED_pthread_attr_t
-#endif
-
-#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-#define __DEFINED_pthread_mutex_t
-#endif
-
-#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
-typedef struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-#define __DEFINED_mtx_t
-#endif
-
-#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-#define __DEFINED_pthread_cond_t
-#endif
-
-#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
-typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-#define __DEFINED_cnd_t
-#endif
-
-#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
-typedef struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-#define __DEFINED_pthread_rwlock_t
-#endif
-
-#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
-typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
-#define __DEFINED_pthread_barrier_t
-#endif
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __USE_TIME_BITS64 1
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
@@ -132,6 +81,16 @@ typedef _Reg register_t;
#define __DEFINED_register_t
#endif
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef _Int64 time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef _Int64 suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
typedef signed char int8_t;
@@ -267,7 +226,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; };
#endif
#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
-struct timespec { time_t tv_sec; long tv_nsec; };
+struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); };
#define __DEFINED_struct_timespec
#endif
@@ -363,6 +322,17 @@ typedef struct _IO_FILE FILE;
#endif
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
#define __DEFINED_mbstate_t
@@ -398,6 +368,42 @@ typedef unsigned short sa_family_t;
#endif
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+
#undef _Addr
#undef _Int64
#undef _Reg
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-linux-musl/bits/limits.h b/lib/libc/include/x86_64-linux-musl/bits/limits.h
index e984295854e013fc250a8c8b81bce9731e458843..fc11433d980df7405e8995f67023006f0f5b85c6 100644
--- a/lib/libc/include/x86_64-linux-musl/bits/limits.h
+++ b/lib/libc/include/x86_64-linux-musl/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define PAGESIZE 4096
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
\ No newline at end of file
+#define PAGESIZE 4096
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-linux-musl/bits/socket.h b/lib/libc/include/x86_64-linux-musl/bits/socket.h
deleted file mode 100644
index 0372d7dd0e4dc85342eeb42a7424edf6abc7d371..0000000000000000000000000000000000000000
--- a/lib/libc/include/x86_64-linux-musl/bits/socket.h
+++ /dev/null
@@ -1,16 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen, __pad1;
- void *msg_control;
- socklen_t msg_controllen, __pad2;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int __pad1;
- int cmsg_level;
- int cmsg_type;
-};
\ No newline at end of file
diff --git a/lib/libc/include/x86_64-linux-musl/bits/syscall.h b/lib/libc/include/x86_64-linux-musl/bits/syscall.h
index fed8f0384ee172f01780de03f88185514c5b344c..e4dbe4b061aadd4234e74190b5ac7c1bd39bd3ad 100644
--- a/lib/libc/include/x86_64-linux-musl/bits/syscall.h
+++ b/lib/libc/include/x86_64-linux-musl/bits/syscall.h
@@ -343,6 +343,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define SYS_read 0
#define SYS_write 1
@@ -688,4 +690,6 @@
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
-#define SYS_fspick 433
\ No newline at end of file
+#define SYS_fspick 433
+#define SYS_pidfd_open 434
+#define SYS_clone3 435
\ No newline at end of file
--
2.54.0
From 71d776c3be91f6b4e982b45fbfe03e3696a397f5 Mon Sep 17 00:00:00 2001
From: Vexu
Date: Thu, 12 Mar 2020 22:42:01 +0200
Subject: [PATCH 100/111] add note to disabled tests, improve comptime cmpxchg
---
lib/std/atomic/stack.zig | 10 +++++-----
lib/std/event/channel.zig | 9 +++------
src/ir.cpp | 18 +++++++++++-------
test/stage1/behavior/atomics.zig | 6 ++++--
4 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/lib/std/atomic/stack.zig b/lib/std/atomic/stack.zig
index 07cb16e450132668e8726d6ad795a1e58f6affea..092dce15b07c70490989693f4611943f7553c44b 100644
--- a/lib/std/atomic/stack.zig
+++ b/lib/std/atomic/stack.zig
@@ -38,8 +38,8 @@ pub fn Stack(comptime T: type) type {
node.next = self.root;
self.root = node;
} else {
- while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst) != false) {}
- defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst) == true);
+ while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst)) {}
+ defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst));
node.next = self.root;
self.root = node;
@@ -52,8 +52,8 @@ pub fn Stack(comptime T: type) type {
self.root = root.next;
return root;
} else {
- while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst) != false) {}
- defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst) == true);
+ while (@atomicRmw(bool, &self.lock, .Xchg, true, .SeqCst)) {}
+ defer assert(@atomicRmw(bool, &self.lock, .Xchg, false, .SeqCst));
const root = self.root orelse return null;
self.root = root.next;
@@ -164,7 +164,7 @@ fn startPuts(ctx: *Context) u8 {
fn startGets(ctx: *Context) u8 {
while (true) {
- const last = @atomicLoad(bool, &ctx.puts_done, .SeqCst) == true;
+ const last = @atomicLoad(bool, &ctx.puts_done, .SeqCst);
while (ctx.stack.pop()) |node| {
std.time.sleep(1); // let the os scheduler be our fuzz
diff --git a/lib/std/event/channel.zig b/lib/std/event/channel.zig
index 355bd782922582dc3e8ec3bc4273de439d63895b..83c77bcac50321490f5ad09927230bfe8a41fe9f 100644
--- a/lib/std/event/channel.zig
+++ b/lib/std/event/channel.zig
@@ -169,8 +169,7 @@ pub fn Channel(comptime T: type) type {
lock: while (true) {
// set the lock flag
- const prev_lock = @atomicRmw(bool, &self.dispatch_lock, .Xchg, true, .SeqCst);
- if (prev_lock != 0) return;
+ if (@atomicRmw(bool, &self.dispatch_lock, .Xchg, true, .SeqCst)) return;
// clear the need_dispatch flag since we're about to do it
@atomicStore(bool, &self.need_dispatch, false, .SeqCst);
@@ -250,11 +249,9 @@ pub fn Channel(comptime T: type) type {
}
// clear need-dispatch flag
- const need_dispatch = @atomicRmw(bool, &self.need_dispatch, .Xchg, false, .SeqCst);
- if (need_dispatch) continue;
+ if (@atomicRmw(bool, &self.need_dispatch, .Xchg, false, .SeqCst)) continue;
- const my_lock = @atomicRmw(bool, &self.dispatch_lock, .Xchg, false, .SeqCst);
- assert(my_lock);
+ assert(@atomicRmw(bool, &self.dispatch_lock, .Xchg, false, .SeqCst));
// we have to check again now that we unlocked
if (@atomicLoad(bool, &self.need_dispatch, .SeqCst)) continue :lock;
diff --git a/src/ir.cpp b/src/ir.cpp
index ede403c722fadf0012ee73d409baa42e4a4174b1..5facc3eb49a70995fcec4eecd76c1aaccead6b47 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -25215,21 +25215,25 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
if (ptr_val == nullptr)
return ira->codegen->invalid_inst_gen;
- ZigValue *op1_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.base.source_node);
- if (op1_val == nullptr)
+ ZigValue *stored_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.base.source_node);
+ if (stored_val == nullptr)
return ira->codegen->invalid_inst_gen;
- ZigValue *op2_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
- if (op2_val == nullptr)
+ ZigValue *expected_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
+ if (expected_val == nullptr)
return ira->codegen->invalid_inst_gen;
- bool eql = const_values_equal(ira->codegen, op1_val, op2_val);
+ ZigValue *new_val = ir_resolve_const(ira, casted_new_value, UndefBad);
+ if (new_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ bool eql = const_values_equal(ira->codegen, stored_val, expected_val);
IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
if (eql) {
- ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, casted_new_value, false);
+ copy_const_val(ira->codegen, stored_val, new_val);
set_optional_value_to_null(result->value);
} else {
- set_optional_payload(result->value, op1_val);
+ set_optional_payload(result->value, stored_val);
}
return result;
}
diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig
index 8870091d75e9a19b8cade939bcf117ec8ee8dc8c..3e6d0b3d0f611708f6dfa2f9d4c6e0585e37a51b 100644
--- a/test/stage1/behavior/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -149,6 +149,7 @@ fn testAtomicStore() void {
}
test "atomicrmw with floats" {
+ // TODO https://github.com/ziglang/zig/issues/4457
if (builtin.arch == .aarch64 or builtin.arch == .arm or builtin.arch == .riscv64)
return error.SkipZigTest;
testAtomicRmwFloat();
@@ -167,8 +168,6 @@ fn testAtomicRmwFloat() void {
}
test "atomicrmw with ints" {
- if (builtin.arch == .mipsel)
- return error.SkipZigTest;
testAtomicRmwInt();
comptime testAtomicRmwInt();
}
@@ -189,6 +188,9 @@ fn testAtomicRmwInt() void {
expect(x == 0xff);
_ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
expect(x == 0xfd);
+
+ // TODO https://github.com/ziglang/zig/issues/4724
+ if (builtin.arch == .mipsel) return;
_ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
expect(x == 0xfd);
_ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
--
2.54.0
From edd6643a26c1c54160babc9568dec9a8f7ed36d6 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 12 Mar 2020 17:17:57 -0400
Subject: [PATCH 101/111] update musl src files to v1.2.0
---
lib/libc/musl/COPYRIGHT | 4 +-
lib/libc/musl/arch/aarch64/bits/alltypes.h.in | 20 +-
lib/libc/musl/arch/aarch64/bits/endian.h | 5 -
lib/libc/musl/arch/aarch64/bits/limits.h | 7 -
lib/libc/musl/arch/aarch64/bits/socket.h | 33 --
lib/libc/musl/arch/aarch64/bits/syscall.h.in | 2 +
lib/libc/musl/arch/aarch64/reloc.h | 2 -
lib/libc/musl/arch/arm/bits/alltypes.h.in | 21 +-
lib/libc/musl/arch/arm/bits/endian.h | 5 -
lib/libc/musl/arch/arm/bits/ipcstat.h | 2 +-
lib/libc/musl/arch/arm/bits/limits.h | 7 -
lib/libc/musl/arch/arm/bits/msg.h | 15 +-
lib/libc/musl/arch/arm/bits/sem.h | 10 +-
lib/libc/musl/arch/arm/bits/shm.h | 16 +-
lib/libc/musl/arch/arm/bits/stat.h | 6 +-
lib/libc/musl/arch/arm/bits/syscall.h.in | 22 +-
lib/libc/musl/arch/arm/reloc.h | 2 -
lib/libc/musl/arch/arm/syscall_arch.h | 4 +-
lib/libc/musl/arch/generic/bits/dirent.h | 11 +
lib/libc/musl/arch/generic/bits/ioctl.h | 5 +
lib/libc/musl/arch/generic/bits/limits.h | 0
lib/libc/musl/arch/generic/bits/socket.h | 15 -
lib/libc/musl/arch/i386/bits/alltypes.h.in | 21 +-
lib/libc/musl/arch/i386/bits/endian.h | 1 -
lib/libc/musl/arch/i386/bits/ipcstat.h | 2 +-
lib/libc/musl/arch/i386/bits/limits.h | 7 -
lib/libc/musl/arch/i386/bits/msg.h | 15 +-
lib/libc/musl/arch/i386/bits/sem.h | 10 +-
lib/libc/musl/arch/i386/bits/shm.h | 16 +-
lib/libc/musl/arch/i386/bits/stat.h | 6 +-
lib/libc/musl/arch/i386/bits/syscall.h.in | 22 +-
lib/libc/musl/arch/i386/syscall_arch.h | 4 +-
lib/libc/musl/arch/mips/bits/alltypes.h.in | 21 +-
lib/libc/musl/arch/mips/bits/endian.h | 5 -
lib/libc/musl/arch/mips/bits/hwcap.h | 11 +
lib/libc/musl/arch/mips/bits/ioctl.h | 4 +-
lib/libc/musl/arch/mips/bits/ipcstat.h | 2 +-
lib/libc/musl/arch/mips/bits/limits.h | 7 -
lib/libc/musl/arch/mips/bits/msg.h | 27 +-
lib/libc/musl/arch/mips/bits/sem.h | 10 +-
lib/libc/musl/arch/mips/bits/shm.h | 15 +-
lib/libc/musl/arch/mips/bits/signal.h | 8 +-
lib/libc/musl/arch/mips/bits/socket.h | 18 -
lib/libc/musl/arch/mips/bits/stat.h | 12 +-
lib/libc/musl/arch/mips/bits/syscall.h.in | 22 +-
lib/libc/musl/arch/mips/reloc.h | 2 -
lib/libc/musl/arch/mips/syscall_arch.h | 4 +-
lib/libc/musl/arch/mips64/bits/alltypes.h.in | 20 +-
lib/libc/musl/arch/mips64/bits/endian.h | 5 -
lib/libc/musl/arch/mips64/bits/limits.h | 7 -
lib/libc/musl/arch/mips64/bits/socket.h | 34 --
lib/libc/musl/arch/mips64/bits/syscall.h.in | 2 +
lib/libc/musl/arch/mips64/reloc.h | 10 +-
lib/libc/musl/arch/powerpc/bits/alltypes.h.in | 16 +-
lib/libc/musl/arch/powerpc/bits/endian.h | 15 -
lib/libc/musl/arch/powerpc/bits/ioctl.h | 4 +-
lib/libc/musl/arch/powerpc/bits/ipcstat.h | 2 +-
lib/libc/musl/arch/powerpc/bits/limits.h | 7 -
lib/libc/musl/arch/powerpc/bits/msg.h | 15 +-
lib/libc/musl/arch/powerpc/bits/sem.h | 10 +-
lib/libc/musl/arch/powerpc/bits/shm.h | 16 +-
lib/libc/musl/arch/powerpc/bits/signal.h | 2 +-
lib/libc/musl/arch/powerpc/bits/socket.h | 18 -
lib/libc/musl/arch/powerpc/bits/stat.h | 6 +-
lib/libc/musl/arch/powerpc/bits/syscall.h.in | 22 +-
.../musl/arch/powerpc64/bits/alltypes.h.in | 20 +-
lib/libc/musl/arch/powerpc64/bits/endian.h | 5 -
lib/libc/musl/arch/powerpc64/bits/limits.h | 7 -
lib/libc/musl/arch/powerpc64/bits/signal.h | 8 +-
lib/libc/musl/arch/powerpc64/bits/socket.h | 34 --
.../musl/arch/powerpc64/bits/syscall.h.in | 2 +
lib/libc/musl/arch/powerpc64/reloc.h | 2 -
lib/libc/musl/arch/riscv64/atomic_arch.h | 2 +-
lib/libc/musl/arch/riscv64/bits/alltypes.h.in | 15 +-
lib/libc/musl/arch/riscv64/bits/endian.h | 1 -
lib/libc/musl/arch/riscv64/bits/limits.h | 7 -
lib/libc/musl/arch/riscv64/bits/reg.h | 6 -
lib/libc/musl/arch/riscv64/bits/signal.h | 9 +
lib/libc/musl/arch/riscv64/bits/socket.h | 19 -
lib/libc/musl/arch/riscv64/bits/syscall.h.in | 2 +
lib/libc/musl/arch/s390x/bits/alltypes.h.in | 15 +-
lib/libc/musl/arch/s390x/bits/endian.h | 1 -
lib/libc/musl/arch/s390x/bits/limits.h | 7 -
lib/libc/musl/arch/s390x/bits/socket.h | 17 -
lib/libc/musl/arch/s390x/bits/syscall.h.in | 2 +
lib/libc/musl/arch/s390x/reloc.h | 2 -
lib/libc/musl/arch/x86_64/bits/alltypes.h.in | 15 +-
lib/libc/musl/arch/x86_64/bits/endian.h | 1 -
lib/libc/musl/arch/x86_64/bits/limits.h | 7 -
lib/libc/musl/arch/x86_64/bits/socket.h | 16 -
lib/libc/musl/arch/x86_64/bits/syscall.h.in | 2 +
lib/libc/musl/compat/time32/__xstat.c | 24 ++
lib/libc/musl/compat/time32/adjtime32.c | 21 ++
lib/libc/musl/compat/time32/adjtimex_time32.c | 10 +
.../musl/compat/time32/aio_suspend_time32.c | 11 +
lib/libc/musl/compat/time32/clock_adjtime32.c | 70 ++++
.../musl/compat/time32/clock_getres_time32.c | 13 +
lib/libc/musl/compat/time32/clock_gettime32.c | 18 +
.../compat/time32/clock_nanosleep_time32.c | 15 +
lib/libc/musl/compat/time32/clock_settime32.c | 9 +
.../musl/compat/time32/cnd_timedwait_time32.c | 9 +
lib/libc/musl/compat/time32/ctime32.c | 7 +
lib/libc/musl/compat/time32/ctime32_r.c | 7 +
lib/libc/musl/compat/time32/difftime32.c | 7 +
lib/libc/musl/compat/time32/fstat_time32.c | 17 +
lib/libc/musl/compat/time32/fstatat_time32.c | 17 +
lib/libc/musl/compat/time32/ftime32.c | 25 ++
lib/libc/musl/compat/time32/futimens_time32.c | 10 +
lib/libc/musl/compat/time32/futimes_time32.c | 12 +
.../musl/compat/time32/futimesat_time32.c | 12 +
.../musl/compat/time32/getitimer_time32.c | 15 +
.../musl/compat/time32/getrusage_time32.c | 39 ++
.../musl/compat/time32/gettimeofday_time32.c | 19 +
lib/libc/musl/compat/time32/gmtime32.c | 7 +
lib/libc/musl/compat/time32/gmtime32_r.c | 7 +
lib/libc/musl/compat/time32/localtime32.c | 7 +
lib/libc/musl/compat/time32/localtime32_r.c | 7 +
lib/libc/musl/compat/time32/lstat_time32.c | 17 +
lib/libc/musl/compat/time32/lutimes_time32.c | 12 +
lib/libc/musl/compat/time32/mktime32.c | 16 +
.../compat/time32/mq_timedreceive_time32.c | 9 +
.../musl/compat/time32/mq_timedsend_time32.c | 9 +
.../musl/compat/time32/mtx_timedlock_time32.c | 9 +
.../musl/compat/time32/nanosleep_time32.c | 15 +
lib/libc/musl/compat/time32/ppoll_time32.c | 10 +
lib/libc/musl/compat/time32/pselect_time32.c | 9 +
.../time32/pthread_cond_timedwait_time32.c | 9 +
.../time32/pthread_mutex_timedlock_time32.c | 9 +
.../pthread_rwlock_timedrdlock_time32.c | 9 +
.../pthread_rwlock_timedwrlock_time32.c | 9 +
.../time32/pthread_timedjoin_np_time32.c | 10 +
lib/libc/musl/compat/time32/recvmmsg_time32.c | 10 +
.../time32/sched_rr_get_interval_time32.c | 13 +
lib/libc/musl/compat/time32/select_time32.c | 10 +
.../musl/compat/time32/sem_timedwait_time32.c | 9 +
.../musl/compat/time32/semtimedop_time32.c | 10 +
.../musl/compat/time32/setitimer_time32.c | 25 ++
.../musl/compat/time32/settimeofday_time32.c | 10 +
.../musl/compat/time32/sigtimedwait_time32.c | 9 +
lib/libc/musl/compat/time32/stat_time32.c | 17 +
lib/libc/musl/compat/time32/stime32.c | 8 +
.../musl/compat/time32/thrd_sleep_time32.c | 16 +
lib/libc/musl/compat/time32/time32.c | 15 +
lib/libc/musl/compat/time32/time32.h | 91 +++++
lib/libc/musl/compat/time32/time32gm.c | 15 +
lib/libc/musl/compat/time32/timer_gettime32.c | 15 +
lib/libc/musl/compat/time32/timer_settime32.c | 25 ++
.../musl/compat/time32/timerfd_gettime32.c | 16 +
.../musl/compat/time32/timerfd_settime32.c | 26 ++
.../musl/compat/time32/timespec_get_time32.c | 18 +
lib/libc/musl/compat/time32/utime_time32.c | 14 +
.../musl/compat/time32/utimensat_time32.c | 11 +
lib/libc/musl/compat/time32/utimes_time32.c | 11 +
lib/libc/musl/compat/time32/wait3_time32.c | 40 ++
lib/libc/musl/compat/time32/wait4_time32.c | 40 ++
lib/libc/musl/include/aio.h | 4 +
lib/libc/musl/include/alloca.h | 2 -
lib/libc/musl/include/alltypes.h.in | 19 +-
lib/libc/musl/include/arpa/nameser.h | 1 -
lib/libc/musl/include/dirent.h | 14 +-
lib/libc/musl/include/dlfcn.h | 4 +
lib/libc/musl/include/endian.h | 46 ++-
lib/libc/musl/include/features.h | 2 +
lib/libc/musl/include/limits.h | 18 +-
lib/libc/musl/include/mqueue.h | 5 +
lib/libc/musl/include/netinet/icmp6.h | 1 -
lib/libc/musl/include/netinet/if_ether.h | 1 +
lib/libc/musl/include/netinet/ip.h | 3 +-
lib/libc/musl/include/netinet/ip6.h | 1 -
lib/libc/musl/include/netinet/tcp.h | 4 +-
lib/libc/musl/include/poll.h | 6 +
lib/libc/musl/include/pthread.h | 10 +
lib/libc/musl/include/sched.h | 8 +
lib/libc/musl/include/semaphore.h | 4 +
lib/libc/musl/include/signal.h | 8 +
lib/libc/musl/include/sys/acct.h | 1 -
lib/libc/musl/include/sys/ioctl.h | 1 +
lib/libc/musl/include/sys/mman.h | 2 +
lib/libc/musl/include/sys/prctl.h | 4 +
lib/libc/musl/include/sys/procfs.h | 7 +-
lib/libc/musl/include/sys/ptrace.h | 29 ++
lib/libc/musl/include/sys/resource.h | 7 +-
lib/libc/musl/include/sys/select.h | 5 +
lib/libc/musl/include/sys/sem.h | 8 +-
lib/libc/musl/include/sys/socket.h | 69 +++-
lib/libc/musl/include/sys/stat.h | 9 +
lib/libc/musl/include/sys/statvfs.h | 2 -
lib/libc/musl/include/sys/time.h | 14 +
lib/libc/musl/include/sys/timeb.h | 6 +
lib/libc/musl/include/sys/timerfd.h | 5 +
lib/libc/musl/include/sys/timex.h | 5 +
lib/libc/musl/include/sys/ttydefaults.h | 7 +-
lib/libc/musl/include/sys/wait.h | 10 +-
lib/libc/musl/include/threads.h | 6 +
lib/libc/musl/include/time.h | 28 ++
lib/libc/musl/include/utime.h | 6 +
lib/libc/musl/include/utmpx.h | 7 +-
lib/libc/musl/src/aio/aio_suspend.c | 2 +
lib/libc/musl/src/complex/cacosh.c | 5 +-
lib/libc/musl/src/complex/cacoshf.c | 5 +-
lib/libc/musl/src/complex/cacoshl.c | 5 +-
lib/libc/musl/src/complex/catanf.c | 14 +-
lib/libc/musl/src/complex/catanl.c | 14 +-
lib/libc/musl/src/ctype/alpha.h | 159 ++++----
lib/libc/musl/src/ctype/casemap.h | 297 +++++++++++++++
lib/libc/musl/src/ctype/nonspacing.h | 88 +++--
lib/libc/musl/src/ctype/punct.h | 160 ++++----
lib/libc/musl/src/ctype/towctrans.c | 348 +++---------------
lib/libc/musl/src/ctype/wcwidth.c | 2 +-
lib/libc/musl/src/ctype/wide.h | 26 +-
lib/libc/musl/src/fenv/riscv64/fenv.S | 5 +-
lib/libc/musl/src/internal/dynlink.h | 1 -
lib/libc/musl/src/internal/floatscan.c | 5 +-
lib/libc/musl/src/internal/syscall.h | 46 +++
lib/libc/musl/src/internal/version.h | 2 +-
lib/libc/musl/src/ldso/__dlsym.c | 4 +
lib/libc/musl/src/ldso/arm/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/i386/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/m68k/dlsym_time64.S | 3 +
.../musl/src/ldso/microblaze/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/mips/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/mipsn32/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/or1k/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/powerpc/dlsym_time64.S | 3 +
lib/libc/musl/src/ldso/sh/dlsym_time64.S | 3 +
lib/libc/musl/src/linux/clock_adjtime.c | 57 ++-
lib/libc/musl/src/linux/wait4.c | 34 +-
lib/libc/musl/src/math/i386/acos.s | 16 +-
lib/libc/musl/src/math/i386/acosf.s | 17 +-
lib/libc/musl/src/math/i386/acosl.s | 15 +-
lib/libc/musl/src/math/i386/asin.s | 32 +-
lib/libc/musl/src/math/i386/asinf.s | 24 +-
lib/libc/musl/src/math/i386/asinl.s | 13 +-
lib/libc/musl/src/math/i386/atan.s | 2 +
lib/libc/musl/src/math/i386/atan2.s | 3 +-
lib/libc/musl/src/math/i386/atan2f.s | 3 +-
lib/libc/musl/src/math/i386/atanf.s | 2 +
lib/libc/musl/src/math/i386/exp2.s | 1 -
lib/libc/musl/src/math/i386/exp2f.s | 1 -
lib/libc/musl/src/math/i386/exp2l.s | 2 +-
.../musl/src/math/i386/{exp.s => exp_ld.s} | 55 +--
lib/libc/musl/src/math/i386/expf.s | 1 -
lib/libc/musl/src/math/i386/expm1.s | 1 -
lib/libc/musl/src/math/i386/expm1f.s | 1 -
lib/libc/musl/src/math/i386/expm1l.s | 2 +-
lib/libc/musl/src/math/i386/log.s | 2 +
lib/libc/musl/src/math/i386/log10.s | 2 +
lib/libc/musl/src/math/i386/log10f.s | 2 +
lib/libc/musl/src/math/i386/log1p.s | 4 +
lib/libc/musl/src/math/i386/log1pf.s | 4 +
lib/libc/musl/src/math/i386/log2.s | 2 +
lib/libc/musl/src/math/i386/log2f.s | 2 +
lib/libc/musl/src/math/i386/logf.s | 2 +
lib/libc/musl/src/math/mips/fabs.c | 16 +
lib/libc/musl/src/math/mips/fabsf.c | 16 +
lib/libc/musl/src/math/mips/sqrt.c | 16 +
lib/libc/musl/src/math/mips/sqrtf.c | 16 +
lib/libc/musl/src/math/powerpc/fabs.c | 2 +-
lib/libc/musl/src/math/powerpc/fma.c | 2 +-
lib/libc/musl/src/math/x32/lrintl.s | 4 +-
lib/libc/musl/src/misc/getrusage.c | 30 +-
lib/libc/musl/src/misc/ioctl.c | 136 ++++++-
lib/libc/musl/src/misc/pty.c | 4 +-
lib/libc/musl/src/network/getsockopt.c | 9 +
lib/libc/musl/src/network/recvmmsg.c | 14 +-
lib/libc/musl/src/network/recvmsg.c | 47 +++
lib/libc/musl/src/network/setsockopt.c | 9 +
lib/libc/musl/src/signal/arm/sigsetjmp.s | 5 +-
lib/libc/musl/src/stat/__xstat.c | 4 +
lib/libc/musl/src/stat/fchmodat.c | 3 +-
lib/libc/musl/src/stat/fstat.c | 2 +
lib/libc/musl/src/stat/fstatat.c | 18 +
lib/libc/musl/src/stat/lstat.c | 2 +
lib/libc/musl/src/stat/stat.c | 2 +
lib/libc/musl/src/stdio/tempnam.c | 5 +-
lib/libc/musl/src/stdio/tmpnam.c | 5 +-
lib/libc/musl/src/stdio/ungetc.c | 2 +-
lib/libc/musl/src/string/arm/memcpy.c | 2 +-
lib/libc/musl/src/string/arm/memcpy_le.S | 13 +-
lib/libc/musl/src/time/__map_file.c | 3 +-
280 files changed, 2886 insertions(+), 1379 deletions(-)
delete mode 100644 lib/libc/musl/arch/aarch64/bits/endian.h
delete mode 100644 lib/libc/musl/arch/aarch64/bits/limits.h
delete mode 100644 lib/libc/musl/arch/aarch64/bits/socket.h
delete mode 100644 lib/libc/musl/arch/arm/bits/endian.h
delete mode 100644 lib/libc/musl/arch/arm/bits/limits.h
create mode 100644 lib/libc/musl/arch/generic/bits/dirent.h
create mode 100644 lib/libc/musl/arch/generic/bits/limits.h
delete mode 100644 lib/libc/musl/arch/i386/bits/endian.h
delete mode 100644 lib/libc/musl/arch/mips/bits/endian.h
delete mode 100644 lib/libc/musl/arch/mips/bits/limits.h
delete mode 100644 lib/libc/musl/arch/mips64/bits/endian.h
delete mode 100644 lib/libc/musl/arch/mips64/bits/limits.h
delete mode 100644 lib/libc/musl/arch/powerpc/bits/endian.h
delete mode 100644 lib/libc/musl/arch/powerpc/bits/limits.h
delete mode 100644 lib/libc/musl/arch/powerpc64/bits/endian.h
delete mode 100644 lib/libc/musl/arch/powerpc64/bits/limits.h
delete mode 100644 lib/libc/musl/arch/riscv64/bits/endian.h
delete mode 100644 lib/libc/musl/arch/riscv64/bits/limits.h
delete mode 100644 lib/libc/musl/arch/riscv64/bits/socket.h
delete mode 100644 lib/libc/musl/arch/s390x/bits/endian.h
delete mode 100644 lib/libc/musl/arch/s390x/bits/socket.h
delete mode 100644 lib/libc/musl/arch/x86_64/bits/endian.h
delete mode 100644 lib/libc/musl/arch/x86_64/bits/socket.h
create mode 100644 lib/libc/musl/compat/time32/__xstat.c
create mode 100644 lib/libc/musl/compat/time32/adjtime32.c
create mode 100644 lib/libc/musl/compat/time32/adjtimex_time32.c
create mode 100644 lib/libc/musl/compat/time32/aio_suspend_time32.c
create mode 100644 lib/libc/musl/compat/time32/clock_adjtime32.c
create mode 100644 lib/libc/musl/compat/time32/clock_getres_time32.c
create mode 100644 lib/libc/musl/compat/time32/clock_gettime32.c
create mode 100644 lib/libc/musl/compat/time32/clock_nanosleep_time32.c
create mode 100644 lib/libc/musl/compat/time32/clock_settime32.c
create mode 100644 lib/libc/musl/compat/time32/cnd_timedwait_time32.c
create mode 100644 lib/libc/musl/compat/time32/ctime32.c
create mode 100644 lib/libc/musl/compat/time32/ctime32_r.c
create mode 100644 lib/libc/musl/compat/time32/difftime32.c
create mode 100644 lib/libc/musl/compat/time32/fstat_time32.c
create mode 100644 lib/libc/musl/compat/time32/fstatat_time32.c
create mode 100644 lib/libc/musl/compat/time32/ftime32.c
create mode 100644 lib/libc/musl/compat/time32/futimens_time32.c
create mode 100644 lib/libc/musl/compat/time32/futimes_time32.c
create mode 100644 lib/libc/musl/compat/time32/futimesat_time32.c
create mode 100644 lib/libc/musl/compat/time32/getitimer_time32.c
create mode 100644 lib/libc/musl/compat/time32/getrusage_time32.c
create mode 100644 lib/libc/musl/compat/time32/gettimeofday_time32.c
create mode 100644 lib/libc/musl/compat/time32/gmtime32.c
create mode 100644 lib/libc/musl/compat/time32/gmtime32_r.c
create mode 100644 lib/libc/musl/compat/time32/localtime32.c
create mode 100644 lib/libc/musl/compat/time32/localtime32_r.c
create mode 100644 lib/libc/musl/compat/time32/lstat_time32.c
create mode 100644 lib/libc/musl/compat/time32/lutimes_time32.c
create mode 100644 lib/libc/musl/compat/time32/mktime32.c
create mode 100644 lib/libc/musl/compat/time32/mq_timedreceive_time32.c
create mode 100644 lib/libc/musl/compat/time32/mq_timedsend_time32.c
create mode 100644 lib/libc/musl/compat/time32/mtx_timedlock_time32.c
create mode 100644 lib/libc/musl/compat/time32/nanosleep_time32.c
create mode 100644 lib/libc/musl/compat/time32/ppoll_time32.c
create mode 100644 lib/libc/musl/compat/time32/pselect_time32.c
create mode 100644 lib/libc/musl/compat/time32/pthread_cond_timedwait_time32.c
create mode 100644 lib/libc/musl/compat/time32/pthread_mutex_timedlock_time32.c
create mode 100644 lib/libc/musl/compat/time32/pthread_rwlock_timedrdlock_time32.c
create mode 100644 lib/libc/musl/compat/time32/pthread_rwlock_timedwrlock_time32.c
create mode 100644 lib/libc/musl/compat/time32/pthread_timedjoin_np_time32.c
create mode 100644 lib/libc/musl/compat/time32/recvmmsg_time32.c
create mode 100644 lib/libc/musl/compat/time32/sched_rr_get_interval_time32.c
create mode 100644 lib/libc/musl/compat/time32/select_time32.c
create mode 100644 lib/libc/musl/compat/time32/sem_timedwait_time32.c
create mode 100644 lib/libc/musl/compat/time32/semtimedop_time32.c
create mode 100644 lib/libc/musl/compat/time32/setitimer_time32.c
create mode 100644 lib/libc/musl/compat/time32/settimeofday_time32.c
create mode 100644 lib/libc/musl/compat/time32/sigtimedwait_time32.c
create mode 100644 lib/libc/musl/compat/time32/stat_time32.c
create mode 100644 lib/libc/musl/compat/time32/stime32.c
create mode 100644 lib/libc/musl/compat/time32/thrd_sleep_time32.c
create mode 100644 lib/libc/musl/compat/time32/time32.c
create mode 100644 lib/libc/musl/compat/time32/time32.h
create mode 100644 lib/libc/musl/compat/time32/time32gm.c
create mode 100644 lib/libc/musl/compat/time32/timer_gettime32.c
create mode 100644 lib/libc/musl/compat/time32/timer_settime32.c
create mode 100644 lib/libc/musl/compat/time32/timerfd_gettime32.c
create mode 100644 lib/libc/musl/compat/time32/timerfd_settime32.c
create mode 100644 lib/libc/musl/compat/time32/timespec_get_time32.c
create mode 100644 lib/libc/musl/compat/time32/utime_time32.c
create mode 100644 lib/libc/musl/compat/time32/utimensat_time32.c
create mode 100644 lib/libc/musl/compat/time32/utimes_time32.c
create mode 100644 lib/libc/musl/compat/time32/wait3_time32.c
create mode 100644 lib/libc/musl/compat/time32/wait4_time32.c
create mode 100644 lib/libc/musl/src/ctype/casemap.h
create mode 100644 lib/libc/musl/src/ldso/arm/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/i386/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/m68k/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/microblaze/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/mips/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/mipsn32/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/or1k/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/powerpc/dlsym_time64.S
create mode 100644 lib/libc/musl/src/ldso/sh/dlsym_time64.S
delete mode 100644 lib/libc/musl/src/math/i386/exp2.s
delete mode 100644 lib/libc/musl/src/math/i386/exp2f.s
rename lib/libc/musl/src/math/i386/{exp.s => exp_ld.s} (67%)
delete mode 100644 lib/libc/musl/src/math/i386/expf.s
delete mode 100644 lib/libc/musl/src/math/i386/expm1.s
delete mode 100644 lib/libc/musl/src/math/i386/expm1f.s
create mode 100644 lib/libc/musl/src/math/mips/fabs.c
create mode 100644 lib/libc/musl/src/math/mips/fabsf.c
create mode 100644 lib/libc/musl/src/math/mips/sqrt.c
create mode 100644 lib/libc/musl/src/math/mips/sqrtf.c
diff --git a/lib/libc/musl/COPYRIGHT b/lib/libc/musl/COPYRIGHT
index 67802d11907fdd3ff5dc04cf3e3b4bc435e8a223..e6472371462f7ce7c23a2d477dbb14445aecbf77 100644
--- a/lib/libc/musl/COPYRIGHT
+++ b/lib/libc/musl/COPYRIGHT
@@ -1,7 +1,7 @@
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
-Copyright © 2005-2019 Rich Felker, et al.
+Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -26,6 +26,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Authors/contributors include:
A. Wilcox
+Ada Worcester
Alex Dowad
Alex Suykov
Alexander Monakov
@@ -65,7 +66,6 @@ Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
-Josiah Worcester
Julien Ramseier
Justin Cormack
Kaarle Ritvanen
diff --git a/lib/libc/musl/arch/aarch64/bits/alltypes.h.in b/lib/libc/musl/arch/aarch64/bits/alltypes.h.in
index d56abdac96732253ad6d65961bc7fb3194d55f8c..c547ca0b72a3fc2a1a77a30997e66a2d597b73ee 100644
--- a/lib/libc/musl/arch/aarch64/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/aarch64/bits/alltypes.h.in
@@ -2,8 +2,13 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#if __AARCH64EB__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
+#endif
+
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF unsigned wchar_t;
@@ -17,14 +22,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/aarch64/bits/endian.h b/lib/libc/musl/arch/aarch64/bits/endian.h
deleted file mode 100644
index 7a74d2febceedd63d37e6877758adcf757801b0f..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/aarch64/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __AARCH64EB__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/aarch64/bits/limits.h b/lib/libc/musl/arch/aarch64/bits/limits.h
deleted file mode 100644
index 0226588c3df9730c5eebcf6dad106f6202237978..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/aarch64/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/aarch64/bits/socket.h b/lib/libc/musl/arch/aarch64/bits/socket.h
deleted file mode 100644
index c11677e9d0d2c212bdad66ebc82332162eef1592..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/aarch64/bits/socket.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
diff --git a/lib/libc/musl/arch/aarch64/bits/syscall.h.in b/lib/libc/musl/arch/aarch64/bits/syscall.h.in
index 955e2cabada6ae1384f98c61a4957116b4abce1c..93648afdfee636733f4b92a8c482c4d74b6a4278 100644
--- a/lib/libc/musl/arch/aarch64/bits/syscall.h.in
+++ b/lib/libc/musl/arch/aarch64/bits/syscall.h.in
@@ -287,4 +287,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/arch/aarch64/reloc.h b/lib/libc/musl/arch/aarch64/reloc.h
index 40cf0b2891660dca6b6b51e03b096113941bd7cd..b1b68c7255ffbcf2049993800a4ff43ed30d7991 100644
--- a/lib/libc/musl/arch/aarch64/reloc.h
+++ b/lib/libc/musl/arch/aarch64/reloc.h
@@ -1,5 +1,3 @@
-#include
-
#if __BYTE_ORDER == __BIG_ENDIAN
#define ENDIAN_SUFFIX "_be"
#else
diff --git a/lib/libc/musl/arch/arm/bits/alltypes.h.in b/lib/libc/musl/arch/arm/bits/alltypes.h.in
index 667963c7e101148f7c0600e182f8be17482184cc..d62bd7bde666531941e4c44d2d4aa8cebc792bcf 100644
--- a/lib/libc/musl/arch/arm/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/arm/bits/alltypes.h.in
@@ -1,9 +1,15 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#if __ARMEB__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
+#endif
+
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
TYPEDEF unsigned wchar_t;
@@ -13,14 +19,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/arm/bits/endian.h b/lib/libc/musl/arch/arm/bits/endian.h
deleted file mode 100644
index 5953724a0b69603238653b75cccfc2686c3ccb96..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/arm/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __ARMEB__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/arm/bits/ipcstat.h b/lib/libc/musl/arch/arm/bits/ipcstat.h
index 0018ad1e20f62a4bb426908c9397ee1253954cd5..4f4fcb0c5b74d7142e781f232b7615f9c86ef2ce 100644
--- a/lib/libc/musl/arch/arm/bits/ipcstat.h
+++ b/lib/libc/musl/arch/arm/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/lib/libc/musl/arch/arm/bits/limits.h b/lib/libc/musl/arch/arm/bits/limits.h
deleted file mode 100644
index fbc6d238dc89b91dbe94af93ea60e862c67ac154..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/arm/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/arm/bits/msg.h b/lib/libc/musl/arch/arm/bits/msg.h
index bc8436c4ad26797d69e762b701aa906b9bed1271..7bbbb2bf43bebae1ec8fe785d38c5bbba0e77cfe 100644
--- a/lib/libc/musl/arch/arm/bits/msg.h
+++ b/lib/libc/musl/arch/arm/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
diff --git a/lib/libc/musl/arch/arm/bits/sem.h b/lib/libc/musl/arch/arm/bits/sem.h
index d383d4ea552d9a092e3960e36d1dc3f97feaecdd..544e3d2a522816553148b2d5d9dcfb86943baa8f 100644
--- a/lib/libc/musl/arch/arm/bits/sem.h
+++ b/lib/libc/musl/arch/arm/bits/sem.h
@@ -1,9 +1,9 @@
struct semid_ds {
struct ipc_perm sem_perm;
- time_t sem_otime;
- long __unused1;
- time_t sem_ctime;
- long __unused2;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -13,4 +13,6 @@ struct semid_ds {
#endif
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
diff --git a/lib/libc/musl/arch/arm/bits/shm.h b/lib/libc/musl/arch/arm/bits/shm.h
index 81b2a29abb87642a2d1a56cf45ee932f16db1603..725fb46968a7eeeb67cd4ae31810de6e2fffa2b0 100644
--- a/lib/libc/musl/arch/arm/bits/shm.h
+++ b/lib/libc/musl/arch/arm/bits/shm.h
@@ -3,17 +3,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
- time_t shm_atime;
- int __unused1;
- time_t shm_dtime;
- int __unused2;
- time_t shm_ctime;
- int __unused3;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ unsigned long __pad3;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/musl/arch/arm/bits/stat.h b/lib/libc/musl/arch/arm/bits/stat.h
index 22b19bbfecf52c0b0158a2f84273c9bb7efd3d64..5d7828cf792baa9109d9868e2939ea9a5508f25c 100644
--- a/lib/libc/musl/arch/arm/bits/stat.h
+++ b/lib/libc/musl/arch/arm/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ ino_t st_ino;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- ino_t st_ino;
};
diff --git a/lib/libc/musl/arch/arm/bits/syscall.h.in b/lib/libc/musl/arch/arm/bits/syscall.h.in
index a565a4ee1f0bf64111b7020925190d0965a92536..11d677635be39e7b05d7e387dff39b82869c278b 100644
--- a/lib/libc/musl/arch/arm/bits/syscall.h.in
+++ b/lib/libc/musl/arch/arm/bits/syscall.h.in
@@ -55,8 +55,8 @@
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_symlink 83
@@ -211,14 +211,14 @@
#define __NR_remap_file_pages 253
#define __NR_set_tid_address 256
#define __NR_timer_create 257
-#define __NR_timer_settime 258
-#define __NR_timer_gettime 259
+#define __NR_timer_settime32 258
+#define __NR_timer_gettime32 259
#define __NR_timer_getoverrun 260
#define __NR_timer_delete 261
-#define __NR_clock_settime 262
-#define __NR_clock_gettime 263
-#define __NR_clock_getres 264
-#define __NR_clock_nanosleep 265
+#define __NR_clock_settime32 262
+#define __NR_clock_gettime32 263
+#define __NR_clock_getres_time32 264
+#define __NR_clock_nanosleep_time32 265
#define __NR_statfs64 266
#define __NR_fstatfs64 267
#define __NR_tgkill 268
@@ -308,8 +308,8 @@
#define __NR_timerfd_create 350
#define __NR_eventfd 351
#define __NR_fallocate 352
-#define __NR_timerfd_settime 353
-#define __NR_timerfd_gettime 354
+#define __NR_timerfd_settime32 353
+#define __NR_timerfd_gettime32 354
#define __NR_signalfd4 355
#define __NR_eventfd2 356
#define __NR_epoll_create1 357
@@ -387,6 +387,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define __ARM_NR_breakpoint 0x0f0001
#define __ARM_NR_cacheflush 0x0f0002
diff --git a/lib/libc/musl/arch/arm/reloc.h b/lib/libc/musl/arch/arm/reloc.h
index 2c2e7f58f968cd4478d980bde4a4e1a2da09f136..d091d2ad92fbf9e54a8c6b55f4f57c6ee6cee54d 100644
--- a/lib/libc/musl/arch/arm/reloc.h
+++ b/lib/libc/musl/arch/arm/reloc.h
@@ -1,5 +1,3 @@
-#include
-
#if __BYTE_ORDER == __BIG_ENDIAN
#define ENDIAN_SUFFIX "eb"
#else
diff --git a/lib/libc/musl/arch/arm/syscall_arch.h b/lib/libc/musl/arch/arm/syscall_arch.h
index 53fb155c0dcb7e94d3878f3a0634890003552bda..4b08762d7b35b056506d9532dcd538d142c20636 100644
--- a/lib/libc/musl/arch/arm/syscall_arch.h
+++ b/lib/libc/musl/arch/arm/syscall_arch.h
@@ -99,7 +99,9 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
}
#define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
#define VDSO_CGT_VER "LINUX_2.6"
#define SYSCALL_FADVISE_6_ARG
diff --git a/lib/libc/musl/arch/generic/bits/dirent.h b/lib/libc/musl/arch/generic/bits/dirent.h
new file mode 100644
index 0000000000000000000000000000000000000000..c845fe82dda20257d1bae78754bb110d7f7a2aa6
--- /dev/null
+++ b/lib/libc/musl/arch/generic/bits/dirent.h
@@ -0,0 +1,11 @@
+#define _DIRENT_HAVE_D_RECLEN
+#define _DIRENT_HAVE_D_OFF
+#define _DIRENT_HAVE_D_TYPE
+
+struct dirent {
+ ino_t d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
diff --git a/lib/libc/musl/arch/generic/bits/ioctl.h b/lib/libc/musl/arch/generic/bits/ioctl.h
index d1a6c035f8323123dfac53d31211e36af2075250..60ae8b850b17b7ad5a658967e6d595188f63eba2 100644
--- a/lib/libc/musl/arch/generic/bits/ioctl.h
+++ b/lib/libc/musl/arch/generic/bits/ioctl.h
@@ -104,7 +104,12 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
+#if __LONG_MAX == 0x7fffffff
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
+#else
#define SIOCGSTAMP 0x8906
#define SIOCGSTAMPNS 0x8907
+#endif
#include
diff --git a/lib/libc/musl/arch/generic/bits/limits.h b/lib/libc/musl/arch/generic/bits/limits.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lib/libc/musl/arch/generic/bits/socket.h b/lib/libc/musl/arch/generic/bits/socket.h
index 1f73b995c68a61e5c1a291cb7dc4f98ea8ae9885..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/lib/libc/musl/arch/generic/bits/socket.h
+++ b/lib/libc/musl/arch/generic/bits/socket.h
@@ -1,15 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
diff --git a/lib/libc/musl/arch/i386/bits/alltypes.h.in b/lib/libc/musl/arch/i386/bits/alltypes.h.in
index 1a8432d3e7bbbc550684d55b0dceec037bf1ae5f..6feb03a6c3f5ebef82100a2295911e25766c1583 100644
--- a/lib/libc/musl/arch/i386/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/i386/bits/alltypes.h.in
@@ -1,14 +1,10 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-#if __GNUC__ >= 3
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
-#else
-TYPEDEF struct __va_list * va_list;
-TYPEDEF struct __va_list * __isoc_va_list;
-#endif
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#ifdef __WCHAR_TYPE__
@@ -33,14 +29,3 @@ TYPEDEF struct { __attribute__((__aligned__(8))) long long __ll; long double __l
#else
TYPEDEF struct { alignas(8) long long __ll; long double __ld; } max_align_t;
#endif
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/i386/bits/endian.h b/lib/libc/musl/arch/i386/bits/endian.h
deleted file mode 100644
index 172c338f5080a09c1f776237e761ea3001ebf1bf..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/i386/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/lib/libc/musl/arch/i386/bits/ipcstat.h b/lib/libc/musl/arch/i386/bits/ipcstat.h
index 0018ad1e20f62a4bb426908c9397ee1253954cd5..4f4fcb0c5b74d7142e781f232b7615f9c86ef2ce 100644
--- a/lib/libc/musl/arch/i386/bits/ipcstat.h
+++ b/lib/libc/musl/arch/i386/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/lib/libc/musl/arch/i386/bits/limits.h b/lib/libc/musl/arch/i386/bits/limits.h
index c340ceb220afe396641fb0f9cf013401f7c64297..07743b6fd61fe0c71d78ba15dca10f2488c1061f 100644
--- a/lib/libc/musl/arch/i386/bits/limits.h
+++ b/lib/libc/musl/arch/i386/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define PAGESIZE 4096
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/i386/bits/msg.h b/lib/libc/musl/arch/i386/bits/msg.h
index bc8436c4ad26797d69e762b701aa906b9bed1271..7bbbb2bf43bebae1ec8fe785d38c5bbba0e77cfe 100644
--- a/lib/libc/musl/arch/i386/bits/msg.h
+++ b/lib/libc/musl/arch/i386/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
diff --git a/lib/libc/musl/arch/i386/bits/sem.h b/lib/libc/musl/arch/i386/bits/sem.h
index e61571c121fc781d1254c33c39575025e6dcb436..65661542a56bce5bc0a23dceb4dff7a42e722f4b 100644
--- a/lib/libc/musl/arch/i386/bits/sem.h
+++ b/lib/libc/musl/arch/i386/bits/sem.h
@@ -1,11 +1,13 @@
struct semid_ds {
struct ipc_perm sem_perm;
- time_t sem_otime;
- long __unused1;
- time_t sem_ctime;
- long __unused2;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
diff --git a/lib/libc/musl/arch/i386/bits/shm.h b/lib/libc/musl/arch/i386/bits/shm.h
index 81b2a29abb87642a2d1a56cf45ee932f16db1603..725fb46968a7eeeb67cd4ae31810de6e2fffa2b0 100644
--- a/lib/libc/musl/arch/i386/bits/shm.h
+++ b/lib/libc/musl/arch/i386/bits/shm.h
@@ -3,17 +3,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
- time_t shm_atime;
- int __unused1;
- time_t shm_dtime;
- int __unused2;
- time_t shm_ctime;
- int __unused3;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ unsigned long __pad3;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/musl/arch/i386/bits/stat.h b/lib/libc/musl/arch/i386/bits/stat.h
index 22b19bbfecf52c0b0158a2f84273c9bb7efd3d64..5d7828cf792baa9109d9868e2939ea9a5508f25c 100644
--- a/lib/libc/musl/arch/i386/bits/stat.h
+++ b/lib/libc/musl/arch/i386/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ ino_t st_ino;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- ino_t st_ino;
};
diff --git a/lib/libc/musl/arch/i386/bits/syscall.h.in b/lib/libc/musl/arch/i386/bits/syscall.h.in
index c95e108e55d577b16eb1c4396b07d272aad778cc..1ae4e48a8fea1a49cc189db7a5a19a4fb26da61d 100644
--- a/lib/libc/musl/arch/i386/bits/syscall.h.in
+++ b/lib/libc/musl/arch/i386/bits/syscall.h.in
@@ -76,8 +76,8 @@
#define __NR_setrlimit 75
#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
@@ -257,14 +257,14 @@
#define __NR_remap_file_pages 257
#define __NR_set_tid_address 258
#define __NR_timer_create 259
-#define __NR_timer_settime (__NR_timer_create+1)
-#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_settime32 (__NR_timer_create+1)
+#define __NR_timer_gettime32 (__NR_timer_create+2)
#define __NR_timer_getoverrun (__NR_timer_create+3)
#define __NR_timer_delete (__NR_timer_create+4)
-#define __NR_clock_settime (__NR_timer_create+5)
-#define __NR_clock_gettime (__NR_timer_create+6)
-#define __NR_clock_getres (__NR_timer_create+7)
-#define __NR_clock_nanosleep (__NR_timer_create+8)
+#define __NR_clock_settime32 (__NR_timer_create+5)
+#define __NR_clock_gettime32 (__NR_timer_create+6)
+#define __NR_clock_getres_time32 (__NR_timer_create+7)
+#define __NR_clock_nanosleep_time32 (__NR_timer_create+8)
#define __NR_statfs64 268
#define __NR_fstatfs64 269
#define __NR_tgkill 270
@@ -322,8 +322,8 @@
#define __NR_timerfd_create 322
#define __NR_eventfd 323
#define __NR_fallocate 324
-#define __NR_timerfd_settime 325
-#define __NR_timerfd_gettime 326
+#define __NR_timerfd_settime32 325
+#define __NR_timerfd_gettime32 326
#define __NR_signalfd4 327
#define __NR_eventfd2 328
#define __NR_epoll_create1 329
@@ -424,4 +424,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/arch/i386/syscall_arch.h b/lib/libc/musl/arch/i386/syscall_arch.h
index 22b0b28b8349c5e80f59b44637b5bec56f071050..69642e578a5f16e783c2afe4f67744a9b17e8c73 100644
--- a/lib/libc/musl/arch/i386/syscall_arch.h
+++ b/lib/libc/musl/arch/i386/syscall_arch.h
@@ -83,7 +83,9 @@ static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a
}
#define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
#define VDSO_CGT_VER "LINUX_2.6"
#define SYSCALL_USE_SOCKETCALL
diff --git a/lib/libc/musl/arch/mips/bits/alltypes.h.in b/lib/libc/musl/arch/mips/bits/alltypes.h.in
index 66ca18ad61af9e0c327868f74e49fdd2c7951047..ff934a4c422ab737ac47c6ba906ac989d67fa705 100644
--- a/lib/libc/musl/arch/mips/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/mips/bits/alltypes.h.in
@@ -1,9 +1,15 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#if _MIPSEL || __MIPSEL || __MIPSEL__
+#define __BYTE_ORDER 1234
+#else
+#define __BYTE_ORDER 4321
+#endif
+
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -13,14 +19,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/mips/bits/endian.h b/lib/libc/musl/arch/mips/bits/endian.h
deleted file mode 100644
index 5399dcb54433380d7b10e2c0c011307e2656d273..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/mips/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if _MIPSEL || __MIPSEL || __MIPSEL__
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/mips/bits/hwcap.h b/lib/libc/musl/arch/mips/bits/hwcap.h
index 13e86fe702eefb44fbf38ce4df12401d19d6d79b..7986deb7f68f5236c50c9b95b8f375b233c3420e 100644
--- a/lib/libc/musl/arch/mips/bits/hwcap.h
+++ b/lib/libc/musl/arch/mips/bits/hwcap.h
@@ -1,3 +1,14 @@
#define HWCAP_MIPS_R6 (1 << 0)
#define HWCAP_MIPS_MSA (1 << 1)
#define HWCAP_MIPS_CRC32 (1 << 2)
+#define HWCAP_MIPS_MIPS16 (1 << 3)
+#define HWCAP_MIPS_MDMX (1 << 4)
+#define HWCAP_MIPS_MIPS3D (1 << 5)
+#define HWCAP_MIPS_SMARTMIPS (1 << 6)
+#define HWCAP_MIPS_DSP (1 << 7)
+#define HWCAP_MIPS_DSP2 (1 << 8)
+#define HWCAP_MIPS_DSP3 (1 << 9)
+#define HWCAP_MIPS_MIPS16E2 (1 << 10)
+#define HWCAP_LOONGSON_MMI (1 << 11)
+#define HWCAP_LOONGSON_EXT (1 << 12)
+#define HWCAP_LOONGSON_EXT2 (1 << 13)
diff --git a/lib/libc/musl/arch/mips/bits/ioctl.h b/lib/libc/musl/arch/mips/bits/ioctl.h
index e277c3f05c62fec053dbc5847e4a6cb6dcf19e58..e20bf19eaa77b44230ec054ee331b8b1971ec79c 100644
--- a/lib/libc/musl/arch/mips/bits/ioctl.h
+++ b/lib/libc/musl/arch/mips/bits/ioctl.h
@@ -110,5 +110,5 @@
#define SIOCATMARK _IOR('s', 7, int)
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
diff --git a/lib/libc/musl/arch/mips/bits/ipcstat.h b/lib/libc/musl/arch/mips/bits/ipcstat.h
index 0018ad1e20f62a4bb426908c9397ee1253954cd5..4f4fcb0c5b74d7142e781f232b7615f9c86ef2ce 100644
--- a/lib/libc/musl/arch/mips/bits/ipcstat.h
+++ b/lib/libc/musl/arch/mips/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/lib/libc/musl/arch/mips/bits/limits.h b/lib/libc/musl/arch/mips/bits/limits.h
deleted file mode 100644
index fbc6d238dc89b91dbe94af93ea60e862c67ac154..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/mips/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/mips/bits/msg.h b/lib/libc/musl/arch/mips/bits/msg.h
index f28aece8fa4bd662f0df89931cb6174a5db92047..c734dbb5708525bd2e045290b02b5ac718730df9 100644
--- a/lib/libc/musl/arch/mips/bits/msg.h
+++ b/lib/libc/musl/arch/mips/bits/msg.h
@@ -1,19 +1,19 @@
struct msqid_ds {
struct ipc_perm msg_perm;
#if _MIPSEL || __MIPSEL || __MIPSEL__
- time_t msg_stime;
- int __unused1;
- time_t msg_rtime;
- int __unused2;
- time_t msg_ctime;
- int __unused3;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
#else
- int __unused1;
- time_t msg_stime;
- int __unused2;
- time_t msg_rtime;
- int __unused3;
- time_t msg_ctime;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long __msg_ctime_lo;
#endif
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
@@ -21,4 +21,7 @@ struct msqid_ds {
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
diff --git a/lib/libc/musl/arch/mips/bits/sem.h b/lib/libc/musl/arch/mips/bits/sem.h
index 5184eb5977ece3775fe5f7a6659a83d6da24ca44..fe6f0948582b9bb241fc600c34c625e085cca32b 100644
--- a/lib/libc/musl/arch/mips/bits/sem.h
+++ b/lib/libc/musl/arch/mips/bits/sem.h
@@ -1,7 +1,7 @@
struct semid_ds {
struct ipc_perm sem_perm;
- time_t sem_otime;
- time_t sem_ctime;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_ctime_lo;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -9,6 +9,8 @@ struct semid_ds {
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
unsigned short sem_nsems;
#endif
- long __unused3;
- long __unused4;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_hi;
+ time_t sem_otime;
+ time_t sem_ctime;
};
diff --git a/lib/libc/musl/arch/mips/bits/shm.h b/lib/libc/musl/arch/mips/bits/shm.h
index 8d19378191bacd8a43080a7f96027befcfd30e4c..ab8c642d825aba458641de167f3e250f6f3c4514 100644
--- a/lib/libc/musl/arch/mips/bits/shm.h
+++ b/lib/libc/musl/arch/mips/bits/shm.h
@@ -3,14 +3,19 @@
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz;
- time_t shm_atime;
- time_t shm_dtime;
- time_t shm_ctime;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_ctime_lo;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
- unsigned long __pad1;
- unsigned long __pad2;
+ unsigned short __shm_atime_hi;
+ unsigned short __shm_dtime_hi;
+ unsigned short __shm_ctime_hi;
+ unsigned short __pad1;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/musl/arch/mips/bits/signal.h b/lib/libc/musl/arch/mips/bits/signal.h
index 1a84de5904bbe93aa688c33446ae2fcd656dd6ca..e1d97ac781595f651ceffec304c37cca142112c2 100644
--- a/lib/libc/musl/arch/mips/bits/signal.h
+++ b/lib/libc/musl/arch/mips/bits/signal.h
@@ -19,14 +19,18 @@ typedef struct {
} fpregset_t;
struct sigcontext {
unsigned sc_regmask, sc_status;
- unsigned long long sc_pc, sc_regs[32], sc_fpregs[32];
+ unsigned long long sc_pc;
+ gregset_t sc_regs;
+ fpregset_t sc_fpregs;
unsigned sc_ownedfp, sc_fpc_csr, sc_fpc_eir, sc_used_math, sc_dsp;
unsigned long long sc_mdhi, sc_mdlo;
unsigned long sc_hi1, sc_lo1, sc_hi2, sc_lo2, sc_hi3, sc_lo3;
};
typedef struct {
unsigned regmask, status;
- unsigned long long pc, gregs[32], fpregs[32];
+ unsigned long long pc;
+ gregset_t gregs;
+ fpregset_t fpregs;
unsigned ownedfp, fpc_csr, fpc_eir, used_math, dsp;
unsigned long long mdhi, mdlo;
unsigned long hi1, lo1, hi2, lo2, hi3, lo3;
diff --git a/lib/libc/musl/arch/mips/bits/socket.h b/lib/libc/musl/arch/mips/bits/socket.h
index b82c7d341f0f880bc800414100a7db60dd44f994..02fbb88b4d25f0e23f882e9d39d48a958f428dc9 100644
--- a/lib/libc/musl/arch/mips/bits/socket.h
+++ b/lib/libc/musl/arch/mips/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
#define SOCK_STREAM 2
#define SOCK_DGRAM 1
@@ -32,8 +16,6 @@ struct cmsghdr {
#define SO_RCVBUF 0x1002
#define SO_SNDLOWAT 0x1003
#define SO_RCVLOWAT 0x1004
-#define SO_RCVTIMEO 0x1006
-#define SO_SNDTIMEO 0x1005
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
#define SO_ACCEPTCONN 0x1009
diff --git a/lib/libc/musl/arch/mips/bits/stat.h b/lib/libc/musl/arch/mips/bits/stat.h
index 3291a63620a2d491ef788102d267de91e6284d1a..48d4ac8044dbfa032f63c088e08f39a216d8e20a 100644
--- a/lib/libc/musl/arch/mips/bits/stat.h
+++ b/lib/libc/musl/arch/mips/bits/stat.h
@@ -12,11 +12,15 @@ struct stat {
dev_t st_rdev;
long __st_padding2[2];
off_t st_size;
- struct timespec st_atim;
- struct timespec st_mtim;
- struct timespec st_ctim;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
blksize_t st_blksize;
long __st_padding3;
blkcnt_t st_blocks;
- long __st_padding4[14];
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+ long __st_padding4[2];
};
diff --git a/lib/libc/musl/arch/mips/bits/syscall.h.in b/lib/libc/musl/arch/mips/bits/syscall.h.in
index 582fa3b51c7d9dcb23e61b7d1e67bb49c885e29e..86251bf31b41413e5ff6f62c408304365b77ff99 100644
--- a/lib/libc/musl/arch/mips/bits/syscall.h.in
+++ b/lib/libc/musl/arch/mips/bits/syscall.h.in
@@ -76,8 +76,8 @@
#define __NR_setrlimit 4075
#define __NR_getrlimit 4076
#define __NR_getrusage 4077
-#define __NR_gettimeofday 4078
-#define __NR_settimeofday 4079
+#define __NR_gettimeofday_time32 4078
+#define __NR_settimeofday_time32 4079
#define __NR_getgroups 4080
#define __NR_setgroups 4081
#define __NR_reserved82 4082
@@ -256,14 +256,14 @@
#define __NR_statfs64 4255
#define __NR_fstatfs64 4256
#define __NR_timer_create 4257
-#define __NR_timer_settime 4258
-#define __NR_timer_gettime 4259
+#define __NR_timer_settime32 4258
+#define __NR_timer_gettime32 4259
#define __NR_timer_getoverrun 4260
#define __NR_timer_delete 4261
-#define __NR_clock_settime 4262
-#define __NR_clock_gettime 4263
-#define __NR_clock_getres 4264
-#define __NR_clock_nanosleep 4265
+#define __NR_clock_settime32 4262
+#define __NR_clock_gettime32 4263
+#define __NR_clock_getres_time32 4264
+#define __NR_clock_nanosleep_time32 4265
#define __NR_tgkill 4266
#define __NR_utimes 4267
#define __NR_mbind 4268
@@ -319,8 +319,8 @@
#define __NR_eventfd 4319
#define __NR_fallocate 4320
#define __NR_timerfd_create 4321
-#define __NR_timerfd_gettime 4322
-#define __NR_timerfd_settime 4323
+#define __NR_timerfd_gettime32 4322
+#define __NR_timerfd_settime32 4323
#define __NR_signalfd4 4324
#define __NR_eventfd2 4325
#define __NR_epoll_create1 4326
@@ -406,4 +406,6 @@
#define __NR_fsconfig 4431
#define __NR_fsmount 4432
#define __NR_fspick 4433
+#define __NR_pidfd_open 4434
+#define __NR_clone3 4435
diff --git a/lib/libc/musl/arch/mips/reloc.h b/lib/libc/musl/arch/mips/reloc.h
index b3d59a45ca2c8022f6f92cefe463851ba09c8179..88d236390edaf7d8b87e6a955b3adb213d308c4f 100644
--- a/lib/libc/musl/arch/mips/reloc.h
+++ b/lib/libc/musl/arch/mips/reloc.h
@@ -1,5 +1,3 @@
-#include
-
#if __mips_isa_rev >= 6
#define ISA_SUFFIX "r6"
#else
diff --git a/lib/libc/musl/arch/mips/syscall_arch.h b/lib/libc/musl/arch/mips/syscall_arch.h
index 6ea73437b52baf7e53b7dc218a36d6c3c7bbf85c..f821e73fcc574ac47f70931e37a3e4a809c69917 100644
--- a/lib/libc/musl/arch/mips/syscall_arch.h
+++ b/lib/libc/musl/arch/mips/syscall_arch.h
@@ -142,7 +142,9 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
}
#define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
#define VDSO_CGT_VER "LINUX_2.6"
#define SO_SNDTIMEO_OLD 0x1005
diff --git a/lib/libc/musl/arch/mips64/bits/alltypes.h.in b/lib/libc/musl/arch/mips64/bits/alltypes.h.in
index 2b2e34a831f15a98542fca50ea81b17765c75c12..fcd61ee853be9ee92037d316acbad041434668d6 100644
--- a/lib/libc/musl/arch/mips64/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/mips64/bits/alltypes.h.in
@@ -2,8 +2,13 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#if _MIPSEL || __MIPSEL || __MIPSEL__
+#define __BYTE_ORDER 1234
+#else
+#define __BYTE_ORDER 4321
+#endif
+
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -14,15 +19,4 @@ TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
TYPEDEF unsigned nlink_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/mips64/bits/endian.h b/lib/libc/musl/arch/mips64/bits/endian.h
deleted file mode 100644
index 5399dcb54433380d7b10e2c0c011307e2656d273..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/mips64/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if _MIPSEL || __MIPSEL || __MIPSEL__
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/mips64/bits/limits.h b/lib/libc/musl/arch/mips64/bits/limits.h
deleted file mode 100644
index 58698c62dce289327a10146b6d8235e418768a3d..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/mips64/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/mips64/bits/socket.h b/lib/libc/musl/arch/mips64/bits/socket.h
index 5aff0d91c29c02bb33104fb1458e93d97a1addb3..519b9c8ead4f6ffd23868d7c2a9a9575c91d3425 100644
--- a/lib/libc/musl/arch/mips64/bits/socket.h
+++ b/lib/libc/musl/arch/mips64/bits/socket.h
@@ -1,37 +1,3 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
-
#define SOCK_STREAM 2
#define SOCK_DGRAM 1
#define SOL_SOCKET 65535
diff --git a/lib/libc/musl/arch/mips64/bits/syscall.h.in b/lib/libc/musl/arch/mips64/bits/syscall.h.in
index 34b9752e6a695b98c6da52d6c4b25d3b0c6d604e..9b406e9a4d9e937a5cdc524df29695a93c6606ab 100644
--- a/lib/libc/musl/arch/mips64/bits/syscall.h.in
+++ b/lib/libc/musl/arch/mips64/bits/syscall.h.in
@@ -336,4 +336,6 @@
#define __NR_fsconfig 5431
#define __NR_fsmount 5432
#define __NR_fspick 5433
+#define __NR_pidfd_open 5434
+#define __NR_clone3 5435
diff --git a/lib/libc/musl/arch/mips64/reloc.h b/lib/libc/musl/arch/mips64/reloc.h
index bbd9bd9d2d6e07a9c65f1ffdab20e3eb2fe19d73..fdb5edc9ca52fa13ed3ef84d6ffa63f74749b390 100644
--- a/lib/libc/musl/arch/mips64/reloc.h
+++ b/lib/libc/musl/arch/mips64/reloc.h
@@ -1,9 +1,3 @@
-#ifndef __RELOC_H__
-#define __RELOC_H__
-
-#define _GNU_SOURCE
-#include
-
#if __mips_isa_rev >= 6
#define ISA_SUFFIX "r6"
#else
@@ -33,6 +27,8 @@
#define REL_DTPOFF R_MIPS_TLS_DTPREL64
#define REL_TPOFF R_MIPS_TLS_TPREL64
+#include
+
#undef R_TYPE
#undef R_SYM
#undef R_INFO
@@ -62,5 +58,3 @@
" daddu %0, %0, $ra \n" \
".set pop \n" \
: "=r"(*(fp)) : : "memory", "ra" )
-
-#endif
diff --git a/lib/libc/musl/arch/powerpc/bits/alltypes.h.in b/lib/libc/musl/arch/powerpc/bits/alltypes.h.in
index 8e687ef16dd3d24d64f4e7fd7ba91cee2b4677c7..b48df6a6254d0042fe47ed869c2363ad4436f678 100644
--- a/lib/libc/musl/arch/powerpc/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/powerpc/bits/alltypes.h.in
@@ -1,9 +1,10 @@
+#define _REDIR_TIME64 1
#define _Addr int
#define _Int64 long long
#define _Reg int
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#define __BYTE_ORDER 4321
+#define __LONG_MAX 0x7fffffffL
#ifndef __cplusplus
#ifdef __WCHAR_TYPE__
@@ -17,14 +18,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/powerpc/bits/endian.h b/lib/libc/musl/arch/powerpc/bits/endian.h
deleted file mode 100644
index 4442abf4eb95f66e6f6770559a5ad98c711f92ce..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/powerpc/bits/endian.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifdef __BIG_ENDIAN__
- #if __BIG_ENDIAN__
- #define __BYTE_ORDER __BIG_ENDIAN
- #endif
-#endif /* __BIG_ENDIAN__ */
-
-#ifdef __LITTLE_ENDIAN__
- #if __LITTLE_ENDIAN__
- #define __BYTE_ORDER __LITTLE_ENDIAN
- #endif
-#endif /* __LITTLE_ENDIAN__ */
-
-#ifndef __BYTE_ORDER
- #define __BYTE_ORDER __BIG_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/powerpc/bits/ioctl.h b/lib/libc/musl/arch/powerpc/bits/ioctl.h
index b6cbb18f4776521d0ad07c6f1ffa97c3513db87e..ac9bfd204a84006e8d871600aae3f0e9d10ec1b0 100644
--- a/lib/libc/musl/arch/powerpc/bits/ioctl.h
+++ b/lib/libc/musl/arch/powerpc/bits/ioctl.h
@@ -116,5 +116,5 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
+#define SIOCGSTAMP _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS _IOR(0x89, 7, char[16])
diff --git a/lib/libc/musl/arch/powerpc/bits/ipcstat.h b/lib/libc/musl/arch/powerpc/bits/ipcstat.h
index 0018ad1e20f62a4bb426908c9397ee1253954cd5..4f4fcb0c5b74d7142e781f232b7615f9c86ef2ce 100644
--- a/lib/libc/musl/arch/powerpc/bits/ipcstat.h
+++ b/lib/libc/musl/arch/powerpc/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/lib/libc/musl/arch/powerpc/bits/limits.h b/lib/libc/musl/arch/powerpc/bits/limits.h
deleted file mode 100644
index fbc6d238dc89b91dbe94af93ea60e862c67ac154..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/powerpc/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 32
-#endif
-
-#define LONG_MAX 0x7fffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/powerpc/bits/msg.h b/lib/libc/musl/arch/powerpc/bits/msg.h
index 171c11a34f8f0db180362a1ed32e8969a516ff76..9fb15dccb2e0d6e91cd5fccfb75d3f93bd955019 100644
--- a/lib/libc/musl/arch/powerpc/bits/msg.h
+++ b/lib/libc/musl/arch/powerpc/bits/msg.h
@@ -1,15 +1,18 @@
struct msqid_ds {
struct ipc_perm msg_perm;
- int __unused1;
- time_t msg_stime;
- int __unused2;
- time_t msg_rtime;
- int __unused3;
- time_t msg_ctime;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long __msg_ctime_lo;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
};
diff --git a/lib/libc/musl/arch/powerpc/bits/sem.h b/lib/libc/musl/arch/powerpc/bits/sem.h
index bc2d6d1f514dffc7eafddd5c34adee8c86a34a09..28be484528574b2fa87c038818b947d393048b0f 100644
--- a/lib/libc/musl/arch/powerpc/bits/sem.h
+++ b/lib/libc/musl/arch/powerpc/bits/sem.h
@@ -1,10 +1,12 @@
struct semid_ds {
struct ipc_perm sem_perm;
- int __unused1;
- time_t sem_otime;
- int __unused2;
- time_t sem_ctime;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_ctime_hi;
+ unsigned long __sem_ctime_lo;
unsigned short __sem_nsems_pad, sem_nsems;
long __unused3;
long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
};
diff --git a/lib/libc/musl/arch/powerpc/bits/shm.h b/lib/libc/musl/arch/powerpc/bits/shm.h
index b19801d51a067d8211b1b211dd395ebfaff7ce1f..fb1d4020f683cc22885195ac63a384ecd9880dba 100644
--- a/lib/libc/musl/arch/powerpc/bits/shm.h
+++ b/lib/libc/musl/arch/powerpc/bits/shm.h
@@ -2,19 +2,21 @@
struct shmid_ds {
struct ipc_perm shm_perm;
- int __unused1;
- time_t shm_atime;
- int __unused2;
- time_t shm_dtime;
- int __unused3;
- time_t shm_ctime;
- int __unused4;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_ctime_hi;
+ unsigned long __shm_ctime_lo;
size_t shm_segsz;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
};
struct shminfo {
diff --git a/lib/libc/musl/arch/powerpc/bits/signal.h b/lib/libc/musl/arch/powerpc/bits/signal.h
index 06efb11cf271326301b90156ada7afa4a9912430..c1bf3caf34e27b51edd0267957f0eda583ec7416 100644
--- a/lib/libc/musl/arch/powerpc/bits/signal.h
+++ b/lib/libc/musl/arch/powerpc/bits/signal.h
@@ -28,7 +28,7 @@ struct sigcontext {
int signal;
unsigned long handler;
unsigned long oldmask;
- void *regs;
+ struct pt_regs *regs;
};
typedef struct {
diff --git a/lib/libc/musl/arch/powerpc/bits/socket.h b/lib/libc/musl/arch/powerpc/bits/socket.h
index a94b8bdb8c5ebbb84ffa49c9f5f180db989b03c6..b19ed42bfa9013cea272f2b85fa720ab4c7bb14b 100644
--- a/lib/libc/musl/arch/powerpc/bits/socket.h
+++ b/lib/libc/musl/arch/powerpc/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen;
- void *msg_control;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
@@ -31,8 +15,6 @@ struct cmsghdr {
#define SO_REUSEPORT 15
#define SO_RCVLOWAT 16
#define SO_SNDLOWAT 17
-#define SO_RCVTIMEO 18
-#define SO_SNDTIMEO 19
#define SO_PASSCRED 20
#define SO_PEERCRED 21
#define SO_ACCEPTCONN 30
diff --git a/lib/libc/musl/arch/powerpc/bits/stat.h b/lib/libc/musl/arch/powerpc/bits/stat.h
index dcb896fd5fba811fa190c7cc1e6246f76ec4de76..585d98e908081eb1e6c1b19b8812d1b017fe7f07 100644
--- a/lib/libc/musl/arch/powerpc/bits/stat.h
+++ b/lib/libc/musl/arch/powerpc/bits/stat.h
@@ -13,8 +13,12 @@ struct stat {
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ unsigned __unused[2];
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
- unsigned __unused[2];
};
diff --git a/lib/libc/musl/arch/powerpc/bits/syscall.h.in b/lib/libc/musl/arch/powerpc/bits/syscall.h.in
index adcf63dbbc8d3038654e22a4b4028d1f2a095756..8d4f79b524c22cf9e8f13e7dceb77a84b1205e64 100644
--- a/lib/libc/musl/arch/powerpc/bits/syscall.h.in
+++ b/lib/libc/musl/arch/powerpc/bits/syscall.h.in
@@ -76,8 +76,8 @@
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
+#define __NR_gettimeofday_time32 78
+#define __NR_settimeofday_time32 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
@@ -238,14 +238,14 @@
#define __NR_epoll_wait 238
#define __NR_remap_file_pages 239
#define __NR_timer_create 240
-#define __NR_timer_settime 241
-#define __NR_timer_gettime 242
+#define __NR_timer_settime32 241
+#define __NR_timer_gettime32 242
#define __NR_timer_getoverrun 243
#define __NR_timer_delete 244
-#define __NR_clock_settime 245
-#define __NR_clock_gettime 246
-#define __NR_clock_getres 247
-#define __NR_clock_nanosleep 248
+#define __NR_clock_settime32 245
+#define __NR_clock_gettime32 246
+#define __NR_clock_getres_time32 247
+#define __NR_clock_nanosleep_time32 248
#define __NR_swapcontext 249
#define __NR_tgkill 250
#define __NR_utimes 251
@@ -307,8 +307,8 @@
#define __NR_sync_file_range2 308
#define __NR_fallocate 309
#define __NR_subpage_prot 310
-#define __NR_timerfd_settime 311
-#define __NR_timerfd_gettime 312
+#define __NR_timerfd_settime32 311
+#define __NR_timerfd_gettime32 312
#define __NR_signalfd4 313
#define __NR_eventfd2 314
#define __NR_epoll_create1 315
@@ -413,4 +413,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/arch/powerpc64/bits/alltypes.h.in b/lib/libc/musl/arch/powerpc64/bits/alltypes.h.in
index 5b205851f1e312b5076e98a6fe27942650f6e5fe..143ffa8d25b97c2ba6961289fd77e3d0c5e10c43 100644
--- a/lib/libc/musl/arch/powerpc64/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/powerpc64/bits/alltypes.h.in
@@ -2,8 +2,13 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#if __BIG_ENDIAN__
+#define __BYTE_ORDER 4321
+#else
+#define __BYTE_ORDER 1234
+#endif
+
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -13,14 +18,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/powerpc64/bits/endian.h b/lib/libc/musl/arch/powerpc64/bits/endian.h
deleted file mode 100644
index 2016cb2074191be20ad57193416a9d5118d53fb6..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/powerpc64/bits/endian.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#if __BIG_ENDIAN__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
diff --git a/lib/libc/musl/arch/powerpc64/bits/limits.h b/lib/libc/musl/arch/powerpc64/bits/limits.h
deleted file mode 100644
index 0226588c3df9730c5eebcf6dad106f6202237978..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/powerpc64/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/powerpc64/bits/signal.h b/lib/libc/musl/arch/powerpc64/bits/signal.h
index 2cc0604c5e4b279a4d89aae2b094010a053bfe0a..d5493b185623413bd71622f6cfb470724d25ff4e 100644
--- a/lib/libc/musl/arch/powerpc64/bits/signal.h
+++ b/lib/libc/musl/arch/powerpc64/bits/signal.h
@@ -9,11 +9,7 @@
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef unsigned long greg_t, gregset_t[48];
-
-typedef struct {
- double fpregs[32];
- double fpscr;
-} fpregset_t;
+typedef double fpregset_t[33];
typedef struct {
#ifdef __GNUC__
@@ -36,7 +32,7 @@ typedef struct sigcontext {
int _pad0;
unsigned long handler;
unsigned long oldmask;
- void *regs;
+ struct pt_regs *regs;
gregset_t gp_regs;
fpregset_t fp_regs;
vrregset_t *v_regs;
diff --git a/lib/libc/musl/arch/powerpc64/bits/socket.h b/lib/libc/musl/arch/powerpc64/bits/socket.h
index 0f3c9aac90fb24d280c7a9416b3c28b13c825536..557e324fde9d7eb5415943c33b3cda7912f739f3 100644
--- a/lib/libc/musl/arch/powerpc64/bits/socket.h
+++ b/lib/libc/musl/arch/powerpc64/bits/socket.h
@@ -1,37 +1,3 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1, msg_iovlen;
-#else
- int msg_iovlen, __pad1;
-#endif
- void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad2;
- socklen_t msg_controllen;
-#else
- socklen_t msg_controllen;
- int __pad2;
-#endif
- int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
- int __pad1;
- socklen_t cmsg_len;
-#else
- socklen_t cmsg_len;
- int __pad1;
-#endif
- int cmsg_level;
- int cmsg_type;
-};
-
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
diff --git a/lib/libc/musl/arch/powerpc64/bits/syscall.h.in b/lib/libc/musl/arch/powerpc64/bits/syscall.h.in
index 32545b3940f14152d4960acf1c2f22a223ab62ef..b935864c41526a96aedd14af21d54e8998cc6d0b 100644
--- a/lib/libc/musl/arch/powerpc64/bits/syscall.h.in
+++ b/lib/libc/musl/arch/powerpc64/bits/syscall.h.in
@@ -385,4 +385,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/arch/powerpc64/reloc.h b/lib/libc/musl/arch/powerpc64/reloc.h
index 5bdaeede5437bbc99b5f47bd1271e5ef87c55d3d..2f1bba059fd416cd0e16fc53d98957e6cfe9d1ed 100644
--- a/lib/libc/musl/arch/powerpc64/reloc.h
+++ b/lib/libc/musl/arch/powerpc64/reloc.h
@@ -1,5 +1,3 @@
-#include
-
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ENDIAN_SUFFIX "le"
#else
diff --git a/lib/libc/musl/arch/riscv64/atomic_arch.h b/lib/libc/musl/arch/riscv64/atomic_arch.h
index 41ad4d04907cb2627c484da9eb756a9f635134a5..0c382588686c48ed5af2b8dcf9f816c0aacbea9e 100644
--- a/lib/libc/musl/arch/riscv64/atomic_arch.h
+++ b/lib/libc/musl/arch/riscv64/atomic_arch.h
@@ -15,7 +15,7 @@ static inline int a_cas(volatile int *p, int t, int s)
" bnez %1, 1b\n"
"1:"
: "=&r"(old), "=&r"(tmp)
- : "r"(p), "r"(t), "r"(s)
+ : "r"(p), "r"((long)t), "r"((long)s)
: "memory");
return old;
}
diff --git a/lib/libc/musl/arch/riscv64/bits/alltypes.h.in b/lib/libc/musl/arch/riscv64/bits/alltypes.h.in
index ae9ba41daf54ae90e88960bc3bcb65a6b598b7a3..4579d1740b689b16fdf91868b483ba0de07635da 100644
--- a/lib/libc/musl/arch/riscv64/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/riscv64/bits/alltypes.h.in
@@ -2,8 +2,8 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -16,14 +16,3 @@ TYPEDEF float float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/riscv64/bits/endian.h b/lib/libc/musl/arch/riscv64/bits/endian.h
deleted file mode 100644
index 172c338f5080a09c1f776237e761ea3001ebf1bf..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/riscv64/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/lib/libc/musl/arch/riscv64/bits/limits.h b/lib/libc/musl/arch/riscv64/bits/limits.h
deleted file mode 100644
index 0226588c3df9730c5eebcf6dad106f6202237978..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/riscv64/bits/limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/riscv64/bits/reg.h b/lib/libc/musl/arch/riscv64/bits/reg.h
index c800788c3fffe5bb5c511c0f387dc1669ec6964e..2633f39d77739ffd4a9100508c3bbfd6286ffa43 100644
--- a/lib/libc/musl/arch/riscv64/bits/reg.h
+++ b/lib/libc/musl/arch/riscv64/bits/reg.h
@@ -1,8 +1,2 @@
#undef __WORDSIZE
#define __WORDSIZE 64
-#define REG_PC 0
-#define REG_RA 1
-#define REG_SP 2
-#define REG_TP 4
-#define REG_S0 8
-#define REG_A0 10
diff --git a/lib/libc/musl/arch/riscv64/bits/signal.h b/lib/libc/musl/arch/riscv64/bits/signal.h
index 2ff4be302c62130d69c0733ed51067faec2675be..b006334f78d7bbc971b195d7b51e108b1a36780b 100644
--- a/lib/libc/musl/arch/riscv64/bits/signal.h
+++ b/lib/libc/musl/arch/riscv64/bits/signal.h
@@ -35,6 +35,15 @@ typedef struct mcontext_t {
union __riscv_mc_fp_state __fpregs;
} mcontext_t;
+#if defined(_GNU_SOURCE)
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
+#endif
+
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef unsigned long greg_t;
typedef unsigned long gregset_t[32];
diff --git a/lib/libc/musl/arch/riscv64/bits/socket.h b/lib/libc/musl/arch/riscv64/bits/socket.h
deleted file mode 100644
index aae537d3434e76af0a0f56ea98cd1795e85ad30b..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/riscv64/bits/socket.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#include
-
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen, __pad1;
- void *msg_control;
- socklen_t msg_controllen;
- int __pad2;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int __pad1;
- int cmsg_level;
- int cmsg_type;
-};
diff --git a/lib/libc/musl/arch/riscv64/bits/syscall.h.in b/lib/libc/musl/arch/riscv64/bits/syscall.h.in
index 1db70cfbf562a02d67f310ae631104753f7694b5..0043eeba3c1c29b63e8b55631a2309789173cfc9 100644
--- a/lib/libc/musl/arch/riscv64/bits/syscall.h.in
+++ b/lib/libc/musl/arch/riscv64/bits/syscall.h.in
@@ -287,6 +287,8 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
diff --git a/lib/libc/musl/arch/s390x/bits/alltypes.h.in b/lib/libc/musl/arch/s390x/bits/alltypes.h.in
index 1a838462091f5d46a09acb19dbf2df0f081ba6a1..15d18c8f4a9c906f0f5c1a848de787b9bdf6f0ad 100644
--- a/lib/libc/musl/arch/s390x/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/s390x/bits/alltypes.h.in
@@ -2,8 +2,8 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#define __BYTE_ORDER 4321
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -13,14 +13,3 @@ TYPEDEF double float_t;
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/s390x/bits/endian.h b/lib/libc/musl/arch/s390x/bits/endian.h
deleted file mode 100644
index ef074b776ed9e094c468854670fc1a2bc635d7e3..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/s390x/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __BIG_ENDIAN
diff --git a/lib/libc/musl/arch/s390x/bits/limits.h b/lib/libc/musl/arch/s390x/bits/limits.h
index 86ef7663fd0cb06ab4ddc0f8670a88c3121a4d73..07743b6fd61fe0c71d78ba15dca10f2488c1061f 100644
--- a/lib/libc/musl/arch/s390x/bits/limits.h
+++ b/lib/libc/musl/arch/s390x/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define PAGESIZE 4096
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/s390x/bits/socket.h b/lib/libc/musl/arch/s390x/bits/socket.h
deleted file mode 100644
index bd4b20c4298ac1c0a22e2650a636ea2009bf229e..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/s390x/bits/socket.h
+++ /dev/null
@@ -1,17 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int __pad1, msg_iovlen;
- void *msg_control;
- int __pad2;
- socklen_t msg_controllen;
- int msg_flags;
-};
-
-struct cmsghdr {
- int __pad1;
- socklen_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
diff --git a/lib/libc/musl/arch/s390x/bits/syscall.h.in b/lib/libc/musl/arch/s390x/bits/syscall.h.in
index c4c70474efe273c64b8ac5ff491534dd07d0b778..e89f3782992769503f579fef1ec4cec3768b2a13 100644
--- a/lib/libc/musl/arch/s390x/bits/syscall.h.in
+++ b/lib/libc/musl/arch/s390x/bits/syscall.h.in
@@ -350,4 +350,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/arch/s390x/reloc.h b/lib/libc/musl/arch/s390x/reloc.h
index a238dc654c06297c0a2609d3493cf11c8a37f49e..6e5c1fb87666075a138f8e1c740cd0296293c8d9 100644
--- a/lib/libc/musl/arch/s390x/reloc.h
+++ b/lib/libc/musl/arch/s390x/reloc.h
@@ -1,5 +1,3 @@
-#include
-
#define LDSO_ARCH "s390x"
#define REL_SYMBOLIC R_390_64
diff --git a/lib/libc/musl/arch/x86_64/bits/alltypes.h.in b/lib/libc/musl/arch/x86_64/bits/alltypes.h.in
index dc551d4720bad294334e4747d722756fc4f2cc23..5cd8a2997f626fe743518fadc3a9c59991c0ddff 100644
--- a/lib/libc/musl/arch/x86_64/bits/alltypes.h.in
+++ b/lib/libc/musl/arch/x86_64/bits/alltypes.h.in
@@ -2,8 +2,8 @@
#define _Int64 long
#define _Reg long
-TYPEDEF __builtin_va_list va_list;
-TYPEDEF __builtin_va_list __isoc_va_list;
+#define __BYTE_ORDER 1234
+#define __LONG_MAX 0x7fffffffffffffffL
#ifndef __cplusplus
TYPEDEF int wchar_t;
@@ -18,14 +18,3 @@ TYPEDEF double double_t;
#endif
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
-TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
-TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
-TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
-TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/lib/libc/musl/arch/x86_64/bits/endian.h b/lib/libc/musl/arch/x86_64/bits/endian.h
deleted file mode 100644
index 172c338f5080a09c1f776237e761ea3001ebf1bf..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/x86_64/bits/endian.h
+++ /dev/null
@@ -1 +0,0 @@
-#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/lib/libc/musl/arch/x86_64/bits/limits.h b/lib/libc/musl/arch/x86_64/bits/limits.h
index 86ef7663fd0cb06ab4ddc0f8670a88c3121a4d73..07743b6fd61fe0c71d78ba15dca10f2488c1061f 100644
--- a/lib/libc/musl/arch/x86_64/bits/limits.h
+++ b/lib/libc/musl/arch/x86_64/bits/limits.h
@@ -1,8 +1 @@
-#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
- || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define PAGESIZE 4096
-#define LONG_BIT 64
-#endif
-
-#define LONG_MAX 0x7fffffffffffffffL
-#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/lib/libc/musl/arch/x86_64/bits/socket.h b/lib/libc/musl/arch/x86_64/bits/socket.h
deleted file mode 100644
index a4c89f3d7a97353a979944918a30136753fadac0..0000000000000000000000000000000000000000
--- a/lib/libc/musl/arch/x86_64/bits/socket.h
+++ /dev/null
@@ -1,16 +0,0 @@
-struct msghdr {
- void *msg_name;
- socklen_t msg_namelen;
- struct iovec *msg_iov;
- int msg_iovlen, __pad1;
- void *msg_control;
- socklen_t msg_controllen, __pad2;
- int msg_flags;
-};
-
-struct cmsghdr {
- socklen_t cmsg_len;
- int __pad1;
- int cmsg_level;
- int cmsg_type;
-};
diff --git a/lib/libc/musl/arch/x86_64/bits/syscall.h.in b/lib/libc/musl/arch/x86_64/bits/syscall.h.in
index 2d4634f68359d5514e0e762ad834cf65fe7926cd..6a646ad3462322aaafe42a076f4bf3b4df048c19 100644
--- a/lib/libc/musl/arch/x86_64/bits/syscall.h.in
+++ b/lib/libc/musl/arch/x86_64/bits/syscall.h.in
@@ -343,4 +343,6 @@
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
diff --git a/lib/libc/musl/compat/time32/__xstat.c b/lib/libc/musl/compat/time32/__xstat.c
new file mode 100644
index 0000000000000000000000000000000000000000..acfbd3cc522a2fbea6fc448b7f9fe1a9ff2cc13e
--- /dev/null
+++ b/lib/libc/musl/compat/time32/__xstat.c
@@ -0,0 +1,24 @@
+#include "time32.h"
+#include
+
+struct stat32;
+
+int __fxstat64(int ver, int fd, struct stat32 *buf)
+{
+ return __fstat_time32(fd, buf);
+}
+
+int __fxstatat64(int ver, int fd, const char *path, struct stat32 *buf, int flag)
+{
+ return __fstatat_time32(fd, path, buf, flag);
+}
+
+int __lxstat64(int ver, const char *path, struct stat32 *buf)
+{
+ return __lstat_time32(path, buf);
+}
+
+int __xstat64(int ver, const char *path, struct stat32 *buf)
+{
+ return __stat_time32(path, buf);
+}
diff --git a/lib/libc/musl/compat/time32/adjtime32.c b/lib/libc/musl/compat/time32/adjtime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..b0042c631736bbfb8e5e6495b919025937d0afc0
--- /dev/null
+++ b/lib/libc/musl/compat/time32/adjtime32.c
@@ -0,0 +1,21 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+int __adjtime32(const struct timeval32 *in32, struct timeval32 *out32)
+{
+ struct timeval out;
+ int r = adjtime((&(struct timeval){
+ .tv_sec = in32->tv_sec,
+ .tv_usec = in32->tv_usec}), &out);
+ if (r) return r;
+ /* We can't range-check the result because success was already
+ * committed by the above call. */
+ if (out32) {
+ out32->tv_sec = out.tv_sec;
+ out32->tv_usec = out.tv_usec;
+ }
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/adjtimex_time32.c b/lib/libc/musl/compat/time32/adjtimex_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c6f190abe030a03a9bfed298ecc9b6364960865
--- /dev/null
+++ b/lib/libc/musl/compat/time32/adjtimex_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#include
+#include
+
+struct timex32;
+
+int __adjtimex_time32(struct timex32 *tx32)
+{
+ return __clock_adjtime32(CLOCK_REALTIME, tx32);
+}
diff --git a/lib/libc/musl/compat/time32/aio_suspend_time32.c b/lib/libc/musl/compat/time32/aio_suspend_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed5119bd7df791da94e6230395cfd459ce4a5eb3
--- /dev/null
+++ b/lib/libc/musl/compat/time32/aio_suspend_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include
+#include
+
+int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct timespec32 *ts32)
+{
+ return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
+
+weak_alias(aio_suspend, aio_suspend64);
diff --git a/lib/libc/musl/compat/time32/clock_adjtime32.c b/lib/libc/musl/compat/time32/clock_adjtime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a25b8ac02a5acc84a50ac1ed6ac336b9d2c28ba
--- /dev/null
+++ b/lib/libc/musl/compat/time32/clock_adjtime32.c
@@ -0,0 +1,70 @@
+#include "time32.h"
+#include
+#include
+#include
+#include
+#include
+
+struct timex32 {
+ unsigned modes;
+ long offset, freq, maxerror, esterror;
+ int status;
+ long constant, precision, tolerance;
+ struct timeval32 time;
+ long tick, ppsfreq, jitter;
+ int shift;
+ long stabil, jitcnt, calcnt, errcnt, stbcnt;
+ int tai;
+ int __padding[11];
+};
+
+int __clock_adjtime32(clockid_t clock_id, struct timex32 *tx32)
+{
+ struct timex utx = {
+ .modes = tx32->modes,
+ .offset = tx32->offset,
+ .freq = tx32->freq,
+ .maxerror = tx32->maxerror,
+ .esterror = tx32->esterror,
+ .status = tx32->status,
+ .constant = tx32->constant,
+ .precision = tx32->precision,
+ .tolerance = tx32->tolerance,
+ .time.tv_sec = tx32->time.tv_sec,
+ .time.tv_usec = tx32->time.tv_usec,
+ .tick = tx32->tick,
+ .ppsfreq = tx32->ppsfreq,
+ .jitter = tx32->jitter,
+ .shift = tx32->shift,
+ .stabil = tx32->stabil,
+ .jitcnt = tx32->jitcnt,
+ .calcnt = tx32->calcnt,
+ .errcnt = tx32->errcnt,
+ .stbcnt = tx32->stbcnt,
+ .tai = tx32->tai,
+ };
+ int r = clock_adjtime(clock_id, &utx);
+ if (r<0) return r;
+ tx32->modes = utx.modes;
+ tx32->offset = utx.offset;
+ tx32->freq = utx.freq;
+ tx32->maxerror = utx.maxerror;
+ tx32->esterror = utx.esterror;
+ tx32->status = utx.status;
+ tx32->constant = utx.constant;
+ tx32->precision = utx.precision;
+ tx32->tolerance = utx.tolerance;
+ tx32->time.tv_sec = utx.time.tv_sec;
+ tx32->time.tv_usec = utx.time.tv_usec;
+ tx32->tick = utx.tick;
+ tx32->ppsfreq = utx.ppsfreq;
+ tx32->jitter = utx.jitter;
+ tx32->shift = utx.shift;
+ tx32->stabil = utx.stabil;
+ tx32->jitcnt = utx.jitcnt;
+ tx32->calcnt = utx.calcnt;
+ tx32->errcnt = utx.errcnt;
+ tx32->stbcnt = utx.stbcnt;
+ tx32->tai = utx.tai;
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/clock_getres_time32.c b/lib/libc/musl/compat/time32/clock_getres_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..47a24c1350893504a1e143fad3f6192b1e880f56
--- /dev/null
+++ b/lib/libc/musl/compat/time32/clock_getres_time32.c
@@ -0,0 +1,13 @@
+#include "time32.h"
+#include
+
+int __clock_getres_time32(clockid_t clk, struct timespec32 *ts32)
+{
+ struct timespec ts;
+ int r = clock_getres(clk, &ts);
+ if (!r && ts32) {
+ ts32->tv_sec = ts.tv_sec;
+ ts32->tv_nsec = ts.tv_nsec;
+ }
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/clock_gettime32.c b/lib/libc/musl/compat/time32/clock_gettime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..0cac7bbdf6dc1f2963e25ea0a592820eb3193ea6
--- /dev/null
+++ b/lib/libc/musl/compat/time32/clock_gettime32.c
@@ -0,0 +1,18 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __clock_gettime32(clockid_t clk, struct timespec32 *ts32)
+{
+ struct timespec ts;
+ int r = clock_gettime(clk, &ts);
+ if (r) return r;
+ if (ts.tv_sec < INT32_MIN || ts.tv_sec > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ ts32->tv_sec = ts.tv_sec;
+ ts32->tv_nsec = ts.tv_nsec;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/clock_nanosleep_time32.c b/lib/libc/musl/compat/time32/clock_nanosleep_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..91ef067d0294a9b9ad3f06858354ae5151f5e225
--- /dev/null
+++ b/lib/libc/musl/compat/time32/clock_nanosleep_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include
+#include
+
+int __clock_nanosleep_time32(clockid_t clk, int flags, const struct timespec32 *req32, struct timespec32 *rem32)
+{
+ struct timespec rem;
+ int ret = clock_nanosleep(clk, flags, (&(struct timespec){
+ .tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+ if (ret==EINTR && rem32 && !(flags & TIMER_ABSTIME)) {
+ rem32->tv_sec = rem.tv_sec;
+ rem32->tv_nsec = rem.tv_nsec;
+ }
+ return ret;
+}
diff --git a/lib/libc/musl/compat/time32/clock_settime32.c b/lib/libc/musl/compat/time32/clock_settime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ca4f0e9c79d2776fa76c1abb780c2255ed147ec
--- /dev/null
+++ b/lib/libc/musl/compat/time32/clock_settime32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+
+int __clock_settime32(clockid_t clk, const struct timespec32 *ts32)
+{
+ return clock_settime(clk, (&(struct timespec){
+ .tv_sec = ts32->tv_sec,
+ .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/cnd_timedwait_time32.c b/lib/libc/musl/compat/time32/cnd_timedwait_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..314251d1c16374f7d8f3c6a59b2b39158aae19d9
--- /dev/null
+++ b/lib/libc/musl/compat/time32/cnd_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __cnd_timedwait_time32(cnd_t *restrict c, mtx_t *restrict m, const struct timespec32 *restrict ts32)
+{
+ return cnd_timedwait(c, m, ts32 ? (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/lib/libc/musl/compat/time32/ctime32.c b/lib/libc/musl/compat/time32/ctime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..a057274e155ab7affe3b8e8a015603eb96f707cc
--- /dev/null
+++ b/lib/libc/musl/compat/time32/ctime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+char *__ctime32(time32_t *t)
+{
+ return ctime(&(time_t){*t});
+}
diff --git a/lib/libc/musl/compat/time32/ctime32_r.c b/lib/libc/musl/compat/time32/ctime32_r.c
new file mode 100644
index 0000000000000000000000000000000000000000..e1ad2e283aedff676e8c516deb982f2f7f833c4d
--- /dev/null
+++ b/lib/libc/musl/compat/time32/ctime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+char *__ctime32_r(time32_t *t, char *buf)
+{
+ return ctime_r(&(time_t){*t}, buf);
+}
diff --git a/lib/libc/musl/compat/time32/difftime32.c b/lib/libc/musl/compat/time32/difftime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..5950943a00345e02284eca55bae522781acca35a
--- /dev/null
+++ b/lib/libc/musl/compat/time32/difftime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+double __difftime32(time32_t t1, time32_t t2)
+{
+ return difftime(t1, t2);
+}
diff --git a/lib/libc/musl/compat/time32/fstat_time32.c b/lib/libc/musl/compat/time32/fstat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e084398879b6e62327bbdc6f724c9f5e310e3fc
--- /dev/null
+++ b/lib/libc/musl/compat/time32/fstat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include
+#include
+#include
+#include
+
+struct stat32;
+
+int __fstat_time32(int fd, struct stat32 *restrict st32)
+{
+ struct stat st;
+ int r = fstat(fd, &st);
+ if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+ return r;
+}
+
+weak_alias(fstat, fstat64);
diff --git a/lib/libc/musl/compat/time32/fstatat_time32.c b/lib/libc/musl/compat/time32/fstatat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..85dcb008edf621076800d6d2dbed4afae7cb7250
--- /dev/null
+++ b/lib/libc/musl/compat/time32/fstatat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include
+#include
+#include
+#include
+
+struct stat32;
+
+int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict st32, int flag)
+{
+ struct stat st;
+ int r = fstatat(fd, path, &st, flag);
+ if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+ return r;
+}
+
+weak_alias(fstatat, fstatat64);
diff --git a/lib/libc/musl/compat/time32/ftime32.c b/lib/libc/musl/compat/time32/ftime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..166a6daeb6b5c17ae0ac5c685dad9678e54c0049
--- /dev/null
+++ b/lib/libc/musl/compat/time32/ftime32.c
@@ -0,0 +1,25 @@
+#include "time32.h"
+#include
+#include
+#include
+
+struct timeb32 {
+ int32_t time;
+ unsigned short millitm;
+ short timezone, dstflag;
+};
+
+int __ftime32(struct timeb32 *tp)
+{
+ struct timeb tb;
+ if (ftime(&tb) < 0) return -1;
+ if (tb.time < INT32_MIN || tb.time > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ tp->time = tb.time;
+ tp->millitm = tb.millitm;
+ tp->timezone = tb.timezone;
+ tp->dstflag = tb.dstflag;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/futimens_time32.c b/lib/libc/musl/compat/time32/futimens_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..7856f176e68d5481319d1cde16c4345bf0b0d02f
--- /dev/null
+++ b/lib/libc/musl/compat/time32/futimens_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#include
+#include
+
+int __futimens_time32(int fd, const struct timespec32 *times32)
+{
+ return futimens(fd, !times32 ? 0 : ((struct timespec[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
+ {.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}));
+}
diff --git a/lib/libc/musl/compat/time32/futimes_time32.c b/lib/libc/musl/compat/time32/futimes_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..f29533f12fb1fcdc561048057652b39ee7116c01
--- /dev/null
+++ b/lib/libc/musl/compat/time32/futimes_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+int __futimes_time32(int fd, const struct timeval32 times32[2])
+{
+ return futimes(fd, !times32 ? 0 : ((struct timeval[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+ {.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/lib/libc/musl/compat/time32/futimesat_time32.c b/lib/libc/musl/compat/time32/futimesat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a1295bde9d7b4dd8b84f1482abbfc7a836c5164
--- /dev/null
+++ b/lib/libc/musl/compat/time32/futimesat_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+int __futimesat_time32(int dirfd, const char *pathname, const struct timeval32 times32[2])
+{
+ return futimesat(dirfd, pathname, !times32 ? 0 : ((struct timeval[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+ {.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/lib/libc/musl/compat/time32/getitimer_time32.c b/lib/libc/musl/compat/time32/getitimer_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..4bac4bf5265704249e81424ece91f308471d7feb
--- /dev/null
+++ b/lib/libc/musl/compat/time32/getitimer_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include
+#include
+
+int __getitimer_time32(int which, struct itimerval32 *old32)
+{
+ struct itimerval old;
+ int r = getitimer(which, &old);
+ if (r) return r;
+ old32->it_interval.tv_sec = old.it_interval.tv_sec;
+ old32->it_interval.tv_usec = old.it_interval.tv_usec;
+ old32->it_value.tv_sec = old.it_value.tv_sec;
+ old32->it_value.tv_usec = old.it_value.tv_usec;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/getrusage_time32.c b/lib/libc/musl/compat/time32/getrusage_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7487dee6eab09dddbb8bd8bdc444b051ab91926
--- /dev/null
+++ b/lib/libc/musl/compat/time32/getrusage_time32.c
@@ -0,0 +1,39 @@
+#include "time32.h"
+#include
+#include
+#include
+
+struct compat_rusage {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ long ru_maxrss;
+ long ru_ixrss;
+ long ru_idrss;
+ long ru_isrss;
+ long ru_minflt;
+ long ru_majflt;
+ long ru_nswap;
+ long ru_inblock;
+ long ru_oublock;
+ long ru_msgsnd;
+ long ru_msgrcv;
+ long ru_nsignals;
+ long ru_nvcsw;
+ long ru_nivcsw;
+};
+
+int __getrusage_time32(int who, struct compat_rusage *usage)
+{
+ struct rusage ru;
+ int r = getrusage(who, &ru);
+ if (!r) {
+ usage->ru_utime.tv_sec = ru.ru_utime.tv_sec;
+ usage->ru_utime.tv_usec = ru.ru_utime.tv_usec;
+ usage->ru_stime.tv_sec = ru.ru_stime.tv_sec;
+ usage->ru_stime.tv_usec = ru.ru_stime.tv_usec;
+ memcpy(&usage->ru_maxrss, &ru.ru_maxrss,
+ sizeof(struct compat_rusage) -
+ offsetof(struct compat_rusage, ru_maxrss));
+ }
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/gettimeofday_time32.c b/lib/libc/musl/compat/time32/gettimeofday_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f3ce68e3e66535f2f92654d85007b709501a87a
--- /dev/null
+++ b/lib/libc/musl/compat/time32/gettimeofday_time32.c
@@ -0,0 +1,19 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __gettimeofday_time32(struct timeval32 *tv32, void *tz)
+{
+ struct timeval tv;
+ if (!tv32) return 0;
+ int r = gettimeofday(&tv, 0);
+ if (r) return r;
+ if (tv.tv_sec < INT32_MIN || tv.tv_sec > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ tv32->tv_sec = tv.tv_sec;
+ tv32->tv_usec = tv.tv_usec;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/gmtime32.c b/lib/libc/musl/compat/time32/gmtime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..963f0e0525983be3a31e8493511bbadf1afcd0aa
--- /dev/null
+++ b/lib/libc/musl/compat/time32/gmtime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+struct tm *__gmtime32(time32_t *t)
+{
+ return gmtime(&(time_t){*t});
+}
diff --git a/lib/libc/musl/compat/time32/gmtime32_r.c b/lib/libc/musl/compat/time32/gmtime32_r.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d72bfb3205ebdfaf985413eab2b73ca4dbe3a1d
--- /dev/null
+++ b/lib/libc/musl/compat/time32/gmtime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+struct tm *__gmtime32_r(time32_t *t, struct tm *tm)
+{
+ return gmtime_r(&(time_t){*t}, tm);
+}
diff --git a/lib/libc/musl/compat/time32/localtime32.c b/lib/libc/musl/compat/time32/localtime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..96bc303490106191ec6547d2f907da6720cb6f9c
--- /dev/null
+++ b/lib/libc/musl/compat/time32/localtime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+struct tm *__localtime32(time32_t *t)
+{
+ return localtime(&(time_t){*t});
+}
diff --git a/lib/libc/musl/compat/time32/localtime32_r.c b/lib/libc/musl/compat/time32/localtime32_r.c
new file mode 100644
index 0000000000000000000000000000000000000000..633ec8293f1fd630b53b988b8cde85f9c8b05679
--- /dev/null
+++ b/lib/libc/musl/compat/time32/localtime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include
+
+struct tm *__localtime32_r(time32_t *t, struct tm *tm)
+{
+ return localtime_r(&(time_t){*t}, tm);
+}
diff --git a/lib/libc/musl/compat/time32/lstat_time32.c b/lib/libc/musl/compat/time32/lstat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..c1257a1449a69baa03638070c81d900b8d629c9f
--- /dev/null
+++ b/lib/libc/musl/compat/time32/lstat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include
+#include
+#include
+#include
+
+struct stat32;
+
+int __lstat_time32(const char *restrict path, struct stat32 *restrict st32)
+{
+ struct stat st;
+ int r = lstat(path, &st);
+ if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+ return r;
+}
+
+weak_alias(lstat, lstat64);
diff --git a/lib/libc/musl/compat/time32/lutimes_time32.c b/lib/libc/musl/compat/time32/lutimes_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f75cd4a185ad1b3655adacea049b317b3c014f5
--- /dev/null
+++ b/lib/libc/musl/compat/time32/lutimes_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+int __lutimes_time32(const char *path, const struct timeval32 times32[2])
+{
+ return lutimes(path, !times32 ? 0 : ((struct timeval[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+ {.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/lib/libc/musl/compat/time32/mktime32.c b/lib/libc/musl/compat/time32/mktime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6f15d513a4dc3a40b57bbe2c93482f593a43ef8
--- /dev/null
+++ b/lib/libc/musl/compat/time32/mktime32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include
+#include
+#include
+
+time32_t __mktime32(struct tm *tm)
+{
+ struct tm tmp = *tm;
+ time_t t = mktime(&tmp);
+ if (t < INT32_MIN || t > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ *tm = tmp;
+ return t;
+}
diff --git a/lib/libc/musl/compat/time32/mq_timedreceive_time32.c b/lib/libc/musl/compat/time32/mq_timedreceive_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..211cea4ba4ed6fe91c8f35ebf41e05dd7c4b04e1
--- /dev/null
+++ b/lib/libc/musl/compat/time32/mq_timedreceive_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+ssize_t __mq_timedreceive_time32(mqd_t mqd, char *restrict msg, size_t len, unsigned *restrict prio, const struct timespec32 *restrict ts32)
+{
+ return mq_timedreceive(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/lib/libc/musl/compat/time32/mq_timedsend_time32.c b/lib/libc/musl/compat/time32/mq_timedsend_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..93b697a7e1206f00311fe5666eb11cb4030536ac
--- /dev/null
+++ b/lib/libc/musl/compat/time32/mq_timedsend_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __mq_timedsend_time32(mqd_t mqd, const char *msg, size_t len, unsigned prio, const struct timespec32 *ts32)
+{
+ return mq_timedsend(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/lib/libc/musl/compat/time32/mtx_timedlock_time32.c b/lib/libc/musl/compat/time32/mtx_timedlock_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..a01f09b89dfbcf1ca7582b81b57447fb81aabc83
--- /dev/null
+++ b/lib/libc/musl/compat/time32/mtx_timedlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __mtx_timedlock_time32(mtx_t *restrict m, const struct timespec32 *restrict ts32)
+{
+ return mtx_timedlock(m, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/nanosleep_time32.c b/lib/libc/musl/compat/time32/nanosleep_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea6bdd81b14add4838dd94ba8985294a5d2fd006
--- /dev/null
+++ b/lib/libc/musl/compat/time32/nanosleep_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include
+#include
+
+int __nanosleep_time32(const struct timespec32 *req32, struct timespec32 *rem32)
+{
+ struct timespec rem;
+ int ret = nanosleep((&(struct timespec){
+ .tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+ if (ret<0 && errno==EINTR && rem32) {
+ rem32->tv_sec = rem.tv_sec;
+ rem32->tv_nsec = rem.tv_nsec;
+ }
+ return ret;
+}
diff --git a/lib/libc/musl/compat/time32/ppoll_time32.c b/lib/libc/musl/compat/time32/ppoll_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..43b4b0df6f8e99cf3301e229aa65777878056055
--- /dev/null
+++ b/lib/libc/musl/compat/time32/ppoll_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include
+#include
+
+int __ppoll_time32(struct pollfd *fds, nfds_t n, const struct timespec32 *ts32, const sigset_t *mask)
+{
+ return ppoll(fds, n, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
+}
diff --git a/lib/libc/musl/compat/time32/pselect_time32.c b/lib/libc/musl/compat/time32/pselect_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..ecaa8f868dbf49315c00ad0951642e74cd4d83f1
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pselect_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __pselect_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, const struct timespec32 *restrict ts32, const sigset_t *restrict mask)
+{
+ return pselect(n, rfds, wfds, efds, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
+}
diff --git a/lib/libc/musl/compat/time32/pthread_cond_timedwait_time32.c b/lib/libc/musl/compat/time32/pthread_cond_timedwait_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fba1f2a9140655e69245852fa2283d82f019e8a7
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pthread_cond_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __pthread_cond_timedwait_time32(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
+{
+ return pthread_cond_timedwait(c, m, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/pthread_mutex_timedlock_time32.c b/lib/libc/musl/compat/time32/pthread_mutex_timedlock_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d29602cb7c804a6fc8d301931162949aa51426c
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pthread_mutex_timedlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __pthread_mutex_timedlock_time32(pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
+{
+ return pthread_mutex_timedlock(m, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/pthread_rwlock_timedrdlock_time32.c b/lib/libc/musl/compat/time32/pthread_rwlock_timedrdlock_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..33df27a4ad62b0bab5f2bd00d067b5fe4c7f6eb6
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pthread_rwlock_timedrdlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __pthread_rwlock_timedrdlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
+{
+ return pthread_rwlock_timedrdlock(rw, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/pthread_rwlock_timedwrlock_time32.c b/lib/libc/musl/compat/time32/pthread_rwlock_timedwrlock_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..99f24f734dcc1d1c0c5962795e64945a7ea08848
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pthread_rwlock_timedwrlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __pthread_rwlock_timedwrlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
+{
+ return pthread_rwlock_timedwrlock(rw, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/pthread_timedjoin_np_time32.c b/lib/libc/musl/compat/time32/pthread_timedjoin_np_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ec2995115345144d0d3e1b45e2c9638c21bfb6a
--- /dev/null
+++ b/lib/libc/musl/compat/time32/pthread_timedjoin_np_time32.c
@@ -0,0 +1,10 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+
+int __pthread_timedjoin_np_time32(pthread_t t, void **res, const struct timespec32 *at32)
+{
+ return pthread_timedjoin_np(t, res, !at32 ? 0 : (&(struct timespec){
+ .tv_sec = at32->tv_sec, .tv_nsec = at32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/recvmmsg_time32.c b/lib/libc/musl/compat/time32/recvmmsg_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..acf1cfb8c0a55b5f857080d0de51877727060f68
--- /dev/null
+++ b/lib/libc/musl/compat/time32/recvmmsg_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include
+#include
+
+int __recvmmsg_time32(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec32 *ts32)
+{
+ return recvmmsg(fd, msgvec, vlen, flags, ts32 ? (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/lib/libc/musl/compat/time32/sched_rr_get_interval_time32.c b/lib/libc/musl/compat/time32/sched_rr_get_interval_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..36cbbaca02f9105a33268c18739fce842500b236
--- /dev/null
+++ b/lib/libc/musl/compat/time32/sched_rr_get_interval_time32.c
@@ -0,0 +1,13 @@
+#include "time32.h"
+#include
+#include
+
+int __sched_rr_get_interval_time32(pid_t pid, struct timespec32 *ts32)
+{
+ struct timespec ts;
+ int r = sched_rr_get_interval(pid, &ts);
+ if (r) return r;
+ ts32->tv_sec = ts.tv_sec;
+ ts32->tv_nsec = ts.tv_nsec;
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/select_time32.c b/lib/libc/musl/compat/time32/select_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d8df9acaf4e8f00b8836448afb49b1902a79059
--- /dev/null
+++ b/lib/libc/musl/compat/time32/select_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __select_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval32 *restrict tv32)
+{
+ return select(n, rfds, wfds, efds, !tv32 ? 0 : (&(struct timeval){
+ .tv_sec = tv32->tv_sec, .tv_usec = tv32->tv_usec}));
+}
diff --git a/lib/libc/musl/compat/time32/sem_timedwait_time32.c b/lib/libc/musl/compat/time32/sem_timedwait_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..c3469f9bc3c81328823d745fd59de72ffa79e993
--- /dev/null
+++ b/lib/libc/musl/compat/time32/sem_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __sem_timedwait_time32(sem_t *sem, const struct timespec32 *restrict ts32)
+{
+ return sem_timedwait(sem, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/semtimedop_time32.c b/lib/libc/musl/compat/time32/semtimedop_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..34ec528199aafc57f76bcfb173a6c315dc82f6df
--- /dev/null
+++ b/lib/libc/musl/compat/time32/semtimedop_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include
+#include
+
+int __semtimedop_time32(int id, struct sembuf *buf, size_t n, const struct timespec32 *ts32)
+{
+ return semtimedop(id, buf, n, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/setitimer_time32.c b/lib/libc/musl/compat/time32/setitimer_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..2475fd8c1110c78b21f15baf2e8a979e6861bc26
--- /dev/null
+++ b/lib/libc/musl/compat/time32/setitimer_time32.c
@@ -0,0 +1,25 @@
+#include "time32.h"
+#include
+#include
+
+int __setitimer_time32(int which, const struct itimerval32 *restrict new32, struct itimerval32 *restrict old32)
+{
+ struct itimerval old;
+ int r = setitimer(which, (&(struct itimerval){
+ .it_interval.tv_sec = new32->it_interval.tv_sec,
+ .it_interval.tv_usec = new32->it_interval.tv_usec,
+ .it_value.tv_sec = new32->it_value.tv_sec,
+ .it_value.tv_usec = new32->it_value.tv_usec}), &old);
+ if (r) return r;
+ /* The above call has already committed to success by changing the
+ * timer setting, so we can't fail on out-of-range old value.
+ * Since these are relative times, values large enough to overflow
+ * don't make sense anyway. */
+ if (old32) {
+ old32->it_interval.tv_sec = old.it_interval.tv_sec;
+ old32->it_interval.tv_usec = old.it_interval.tv_usec;
+ old32->it_value.tv_sec = old.it_value.tv_sec;
+ old32->it_value.tv_usec = old.it_value.tv_usec;
+ }
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/settimeofday_time32.c b/lib/libc/musl/compat/time32/settimeofday_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..09e625cba3fe9c86eb952339bfb190c2517cc42a
--- /dev/null
+++ b/lib/libc/musl/compat/time32/settimeofday_time32.c
@@ -0,0 +1,10 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include
+
+int __settimeofday_time32(const struct timeval32 *tv32, const void *tz)
+{
+ return settimeofday(!tv32 ? 0 : (&(struct timeval){
+ .tv_sec = tv32->tv_sec,
+ .tv_usec = tv32->tv_usec}), 0);
+}
diff --git a/lib/libc/musl/compat/time32/sigtimedwait_time32.c b/lib/libc/musl/compat/time32/sigtimedwait_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b3aa39c72fb6d2fb65dfcbf293511869d0e2774
--- /dev/null
+++ b/lib/libc/musl/compat/time32/sigtimedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include
+#include
+
+int __sigtimedwait_time32(const sigset_t *restrict set, siginfo_t *restrict si, const struct timespec32 *restrict ts32)
+{
+ return sigtimedwait(set, si, !ts32 ? 0 : (&(struct timespec){
+ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/lib/libc/musl/compat/time32/stat_time32.c b/lib/libc/musl/compat/time32/stat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c6121dadd2ba197906ec1728790ee216071442e
--- /dev/null
+++ b/lib/libc/musl/compat/time32/stat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include
+#include
+#include
+#include
+
+struct stat32;
+
+int __stat_time32(const char *restrict path, struct stat32 *restrict st32)
+{
+ struct stat st;
+ int r = stat(path, &st);
+ if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+ return r;
+}
+
+weak_alias(stat, stat64);
diff --git a/lib/libc/musl/compat/time32/stime32.c b/lib/libc/musl/compat/time32/stime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc76364d3b91e1e8c6f9718a6a90667c3d4934a9
--- /dev/null
+++ b/lib/libc/musl/compat/time32/stime32.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+
+int __stime32(const time32_t *t)
+{
+ return stime(&(time_t){*t});
+}
diff --git a/lib/libc/musl/compat/time32/thrd_sleep_time32.c b/lib/libc/musl/compat/time32/thrd_sleep_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..59088001b22039bafc5a637669816f2dd3357a67
--- /dev/null
+++ b/lib/libc/musl/compat/time32/thrd_sleep_time32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __thrd_sleep_time32(const struct timespec32 *req32, struct timespec32 *rem32)
+{
+ struct timespec rem;
+ int ret = thrd_sleep((&(struct timespec){
+ .tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+ if (ret<0 && errno==EINTR && rem32) {
+ rem32->tv_sec = rem.tv_sec;
+ rem32->tv_nsec = rem.tv_nsec;
+ }
+ return ret;
+}
diff --git a/lib/libc/musl/compat/time32/time32.c b/lib/libc/musl/compat/time32/time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b8fac1c291eb941dd531d0f450656a6cf1cb82e
--- /dev/null
+++ b/lib/libc/musl/compat/time32/time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include
+#include
+#include
+
+time32_t __time32(time32_t *p)
+{
+ time_t t = time(0);
+ if (t < INT32_MIN || t > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ if (p) *p = t;
+ return t;
+}
diff --git a/lib/libc/musl/compat/time32/time32.h b/lib/libc/musl/compat/time32/time32.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdec17c345d0e489034c956cd7454c61d971e8f2
--- /dev/null
+++ b/lib/libc/musl/compat/time32/time32.h
@@ -0,0 +1,91 @@
+#ifndef TIME32_H
+#define TIME32_H
+
+#include
+
+typedef long time32_t;
+
+struct timeval32 {
+ long tv_sec;
+ long tv_usec;
+};
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+struct timespec32 {
+ long tv_sec;
+ long tv_nsec;
+};
+
+struct itimerspec32 {
+ struct timespec32 it_interval;
+ struct timespec32 it_value;
+};
+
+int __adjtime32() __asm__("adjtime");
+int __adjtimex_time32() __asm__("adjtimex");
+int __aio_suspend_time32() __asm__("aio_suspend");
+int __clock_adjtime32() __asm__("clock_adjtime");
+int __clock_getres_time32() __asm__("clock_getres");
+int __clock_gettime32() __asm__("clock_gettime");
+int __clock_nanosleep_time32() __asm__("clock_nanosleep");
+int __clock_settime32() __asm__("clock_settime");
+int __cnd_timedwait_time32() __asm__("cnd_timedwait");
+char *__ctime32() __asm__("ctime");
+char *__ctime32_r() __asm__("ctime_r");
+double __difftime32() __asm__("difftime");
+int __fstat_time32() __asm__("fstat");
+int __fstatat_time32() __asm__("fstatat");
+int __ftime32() __asm__("ftime");
+int __futimens_time32() __asm__("futimens");
+int __futimes_time32() __asm__("futimes");
+int __futimesat_time32() __asm__("futimesat");
+int __getitimer_time32() __asm__("getitimer");
+int __getrusage_time32() __asm__("getrusage");
+int __gettimeofday_time32() __asm__("gettimeofday");
+struct tm *__gmtime32() __asm__("gmtime");
+struct tm *__gmtime32_r() __asm__("gmtime_r");
+struct tm *__localtime32() __asm__("localtime");
+struct tm *__localtime32_r() __asm__("localtime_r");
+int __lstat_time32() __asm__("lstat");
+int __lutimes_time32() __asm__("lutimes");
+time32_t __mktime32() __asm__("mktime");
+ssize_t __mq_timedreceive_time32() __asm__("mq_timedreceive");
+int __mq_timedsend_time32() __asm__("mq_timedsend");
+int __mtx_timedlock_time32() __asm__("mtx_timedlock");
+int __nanosleep_time32() __asm__("nanosleep");
+int __ppoll_time32() __asm__("ppoll");
+int __pselect_time32() __asm__("pselect");
+int __pthread_cond_timedwait_time32() __asm__("pthread_cond_timedwait");
+int __pthread_mutex_timedlock_time32() __asm__("pthread_mutex_timedlock");
+int __pthread_rwlock_timedrdlock_time32() __asm__("pthread_rwlock_timedrdlock");
+int __pthread_rwlock_timedwrlock_time32() __asm__("pthread_rwlock_timedwrlock");
+int __pthread_timedjoin_np_time32() __asm__("pthread_timedjoin_np");
+int __recvmmsg_time32() __asm__("recvmmsg");
+int __sched_rr_get_interval_time32() __asm__("sched_rr_get_interval");
+int __select_time32() __asm__("select");
+int __sem_timedwait_time32() __asm__("sem_timedwait");
+int __semtimedop_time32() __asm__("semtimedop");
+int __setitimer_time32() __asm__("setitimer");
+int __settimeofday_time32() __asm__("settimeofday");
+int __sigtimedwait_time32() __asm__("sigtimedwait");
+int __stat_time32() __asm__("stat");
+int __stime32() __asm__("stime");
+int __thrd_sleep_time32() __asm__("thrd_sleep");
+time32_t __time32() __asm__("time");
+time32_t __time32gm() __asm__("timegm");
+int __timer_gettime32() __asm__("timer_gettime");
+int __timer_settime32() __asm__("timer_settime");
+int __timerfd_gettime32() __asm__("timerfd_gettime");
+int __timerfd_settime32() __asm__("timerfd_settime");
+int __timespec_get_time32() __asm__("timespec_get");
+int __utime_time32() __asm__("utime");
+int __utimensat_time32() __asm__("utimensat");
+int __utimes_time32() __asm__("utimes");
+pid_t __wait3_time32() __asm__("wait3");
+pid_t __wait4_time32() __asm__("wait4");
+
+#endif
diff --git a/lib/libc/musl/compat/time32/time32gm.c b/lib/libc/musl/compat/time32/time32gm.c
new file mode 100644
index 0000000000000000000000000000000000000000..60d68fbf84922e4b2fea41a25c9aa4860cf7fed4
--- /dev/null
+++ b/lib/libc/musl/compat/time32/time32gm.c
@@ -0,0 +1,15 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+time32_t __time32gm(struct tm *tm)
+{
+ time_t t = timegm(tm);
+ if (t < INT32_MIN || t > INT32_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ return t;
+}
diff --git a/lib/libc/musl/compat/time32/timer_gettime32.c b/lib/libc/musl/compat/time32/timer_gettime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..b4184cc28374c984b406cb54829f9c4f62c6d61e
--- /dev/null
+++ b/lib/libc/musl/compat/time32/timer_gettime32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include
+
+int __timer_gettime32(timer_t t, struct itimerspec32 *val32)
+{
+ struct itimerspec old;
+ int r = timer_gettime(t, &old);
+ if (r) return r;
+ /* No range checking for consistency with settime */
+ val32->it_interval.tv_sec = old.it_interval.tv_sec;
+ val32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+ val32->it_value.tv_sec = old.it_value.tv_sec;
+ val32->it_value.tv_nsec = old.it_value.tv_nsec;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/timer_settime32.c b/lib/libc/musl/compat/time32/timer_settime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..a447e7d41aa79081b106e396e52822923d85d334
--- /dev/null
+++ b/lib/libc/musl/compat/time32/timer_settime32.c
@@ -0,0 +1,25 @@
+#include "time32.h"
+#include
+
+int __timer_settime32(timer_t t, int flags, const struct itimerspec32 *restrict val32, struct itimerspec32 *restrict old32)
+{
+ struct itimerspec old;
+ int r = timer_settime(t, flags, (&(struct itimerspec){
+ .it_interval.tv_sec = val32->it_interval.tv_sec,
+ .it_interval.tv_nsec = val32->it_interval.tv_nsec,
+ .it_value.tv_sec = val32->it_value.tv_sec,
+ .it_value.tv_nsec = val32->it_value.tv_nsec}),
+ old32 ? &old : 0);
+ if (r) return r;
+ /* The above call has already committed to success by changing the
+ * timer setting, so we can't fail on out-of-range old value.
+ * Since these are relative times, values large enough to overflow
+ * don't make sense anyway. */
+ if (old32) {
+ old32->it_interval.tv_sec = old.it_interval.tv_sec;
+ old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+ old32->it_value.tv_sec = old.it_value.tv_sec;
+ old32->it_value.tv_nsec = old.it_value.tv_nsec;
+ }
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/timerfd_gettime32.c b/lib/libc/musl/compat/time32/timerfd_gettime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..75e5435f18b06455fa3b1d47a32017e823b35ea4
--- /dev/null
+++ b/lib/libc/musl/compat/time32/timerfd_gettime32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include
+#include
+
+int __timerfd_gettime32(int t, struct itimerspec32 *val32)
+{
+ struct itimerspec old;
+ int r = timerfd_gettime(t, &old);
+ if (r) return r;
+ /* No range checking for consistency with settime */
+ val32->it_interval.tv_sec = old.it_interval.tv_sec;
+ val32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+ val32->it_value.tv_sec = old.it_value.tv_sec;
+ val32->it_value.tv_nsec = old.it_value.tv_nsec;
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/timerfd_settime32.c b/lib/libc/musl/compat/time32/timerfd_settime32.c
new file mode 100644
index 0000000000000000000000000000000000000000..67830d34189e30318e077125705ecd246c725d3b
--- /dev/null
+++ b/lib/libc/musl/compat/time32/timerfd_settime32.c
@@ -0,0 +1,26 @@
+#include "time32.h"
+#include
+#include
+
+int __timerfd_settime32(int t, int flags, const struct itimerspec32 *restrict val32, struct itimerspec32 *restrict old32)
+{
+ struct itimerspec old;
+ int r = timerfd_settime(t, flags, (&(struct itimerspec){
+ .it_interval.tv_sec = val32->it_interval.tv_sec,
+ .it_interval.tv_nsec = val32->it_interval.tv_nsec,
+ .it_value.tv_sec = val32->it_value.tv_sec,
+ .it_value.tv_nsec = val32->it_value.tv_nsec}),
+ old32 ? &old : 0);
+ if (r) return r;
+ /* The above call has already committed to success by changing the
+ * timer setting, so we can't fail on out-of-range old value.
+ * Since these are relative times, values large enough to overflow
+ * don't make sense anyway. */
+ if (old32) {
+ old32->it_interval.tv_sec = old.it_interval.tv_sec;
+ old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+ old32->it_value.tv_sec = old.it_value.tv_sec;
+ old32->it_value.tv_nsec = old.it_value.tv_nsec;
+ }
+ return 0;
+}
diff --git a/lib/libc/musl/compat/time32/timespec_get_time32.c b/lib/libc/musl/compat/time32/timespec_get_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..e9ca94cb42a58ccb142676f0cce1776e8bed8585
--- /dev/null
+++ b/lib/libc/musl/compat/time32/timespec_get_time32.c
@@ -0,0 +1,18 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __timespec_get_time32(struct timespec32 *ts32, int base)
+{
+ struct timespec ts;
+ int r = timespec_get(&ts, base);
+ if (!r) return r;
+ if (ts.tv_sec < INT32_MIN || ts.tv_sec > INT32_MAX) {
+ errno = EOVERFLOW;
+ return 0;
+ }
+ ts32->tv_sec = ts.tv_sec;
+ ts32->tv_nsec = ts.tv_nsec;
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/utime_time32.c b/lib/libc/musl/compat/time32/utime_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..65f11d463413f78b37b7e0511918ffa9569408cb
--- /dev/null
+++ b/lib/libc/musl/compat/time32/utime_time32.c
@@ -0,0 +1,14 @@
+#include "time32.h"
+#include
+#include
+
+struct utimbuf32 {
+ time32_t actime;
+ time32_t modtime;
+};
+
+int __utime_time32(const char *path, const struct utimbuf32 *times32)
+{
+ return utime(path, !times32 ? 0 : (&(struct utimbuf){
+ .actime = times32->actime, .modtime = times32->modtime}));
+}
diff --git a/lib/libc/musl/compat/time32/utimensat_time32.c b/lib/libc/musl/compat/time32/utimensat_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..c687b8d1b4fb8d0cc579fb3fbb36fea37c669724
--- /dev/null
+++ b/lib/libc/musl/compat/time32/utimensat_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include
+#include
+
+int __utimensat_time32(int fd, const char *path, const struct timespec32 times32[2], int flags)
+{
+ return utimensat(fd, path, !times32 ? 0 : ((struct timespec[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
+ {.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}),
+ flags);
+}
diff --git a/lib/libc/musl/compat/time32/utimes_time32.c b/lib/libc/musl/compat/time32/utimes_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..59248f623bec7766171301ce45776e41fbb298a8
--- /dev/null
+++ b/lib/libc/musl/compat/time32/utimes_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include
+#include
+#include
+
+int __utimes_time32(const char *path, const struct timeval32 times32[2])
+{
+ return utimes(path, !times32 ? 0 : ((struct timeval[2]){
+ {.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+ {.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/lib/libc/musl/compat/time32/wait3_time32.c b/lib/libc/musl/compat/time32/wait3_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..8fe128edbfae0b12bb5001d48ce9c4940a5e9979
--- /dev/null
+++ b/lib/libc/musl/compat/time32/wait3_time32.c
@@ -0,0 +1,40 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include
+#include
+#include
+
+struct compat_rusage {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ long ru_maxrss;
+ long ru_ixrss;
+ long ru_idrss;
+ long ru_isrss;
+ long ru_minflt;
+ long ru_majflt;
+ long ru_nswap;
+ long ru_inblock;
+ long ru_oublock;
+ long ru_msgsnd;
+ long ru_msgrcv;
+ long ru_nsignals;
+ long ru_nvcsw;
+ long ru_nivcsw;
+};
+
+pid_t __wait3_time32(int *status, int options, struct compat_rusage *usage)
+{
+ struct rusage ru;
+ int r = wait3(status, options, usage ? &ru : 0);
+ if (!r && usage) {
+ usage->ru_utime.tv_sec = ru.ru_utime.tv_sec;
+ usage->ru_utime.tv_usec = ru.ru_utime.tv_usec;
+ usage->ru_stime.tv_sec = ru.ru_stime.tv_sec;
+ usage->ru_stime.tv_usec = ru.ru_stime.tv_usec;
+ memcpy(&usage->ru_maxrss, &ru.ru_maxrss,
+ sizeof(struct compat_rusage) -
+ offsetof(struct compat_rusage, ru_maxrss));
+ }
+ return r;
+}
diff --git a/lib/libc/musl/compat/time32/wait4_time32.c b/lib/libc/musl/compat/time32/wait4_time32.c
new file mode 100644
index 0000000000000000000000000000000000000000..918548e74f9add2e88d97e7846043b47de6a5df6
--- /dev/null
+++ b/lib/libc/musl/compat/time32/wait4_time32.c
@@ -0,0 +1,40 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include
+#include
+#include