Merge remote-tracking branch 'origin/master' into self-hosted-libc-hello-world
commit
5a919dd82d
|
@ -556,7 +556,7 @@ set(ZIG_STD_FILES
|
|||
"net.zig"
|
||||
"os/child_process.zig"
|
||||
"os/darwin.zig"
|
||||
"os/darwin_errno.zig"
|
||||
"os/darwin/errno.zig"
|
||||
"os/epoch.zig"
|
||||
"os/file.zig"
|
||||
"os/get_app_data_dir.zig"
|
||||
|
|
|
@ -70,7 +70,7 @@ that counts as "freestanding" for the purposes of this table.
|
|||
|
||||
## Community
|
||||
|
||||
* IRC: `#zig` on Freenode.
|
||||
* IRC: `#zig` on Freenode ([Channel Logs](https://irclog.whitequark.org/zig/)).
|
||||
* Reddit: [/r/zig](https://www.reddit.com/r/zig)
|
||||
* Email list: [ziglang@googlegroups.com](https://groups.google.com/forum/#!forum/ziglang)
|
||||
|
||||
|
|
|
@ -2172,8 +2172,7 @@ const Analyze = struct {
|
|||
break :fits true;
|
||||
}
|
||||
if (dest_type.cast(Type.Int)) |int| {
|
||||
break :fits (from_int.positive or from_int.eqZero() or int.key.is_signed) and
|
||||
int.key.bit_count >= from_int.bitcount();
|
||||
break :fits from_int.fitsInTwosComp(int.key.is_signed, int.key.bit_count);
|
||||
}
|
||||
break :cast;
|
||||
};
|
||||
|
|
|
@ -60,6 +60,33 @@ PackageTableEntry *new_anonymous_package(void) {
|
|||
return new_package("", "");
|
||||
}
|
||||
|
||||
static const char *symbols_that_llvm_depends_on[] = {
|
||||
"memcpy",
|
||||
"memset",
|
||||
"sqrt",
|
||||
"powi",
|
||||
"sin",
|
||||
"cos",
|
||||
"pow",
|
||||
"exp",
|
||||
"exp2",
|
||||
"log",
|
||||
"log10",
|
||||
"log2",
|
||||
"fma",
|
||||
"fabs",
|
||||
"minnum",
|
||||
"maxnum",
|
||||
"copysign",
|
||||
"floor",
|
||||
"ceil",
|
||||
"trunc",
|
||||
"rint",
|
||||
"nearbyint",
|
||||
"round",
|
||||
// TODO probably all of compiler-rt needs to go here
|
||||
};
|
||||
|
||||
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
|
||||
Buf *zig_lib_dir)
|
||||
{
|
||||
|
@ -94,6 +121,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
|
|||
g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
|
||||
buf_resize(&g->global_asm, 0);
|
||||
|
||||
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
|
||||
g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr);
|
||||
}
|
||||
|
||||
if (root_src_path) {
|
||||
Buf *src_basename = buf_alloc();
|
||||
Buf *src_dir = buf_alloc();
|
||||
|
|
84
src/ir.cpp
84
src/ir.cpp
|
@ -2961,16 +2961,34 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
|
|||
results[ReturnKindUnconditional] = 0;
|
||||
results[ReturnKindError] = 0;
|
||||
|
||||
while (inner_scope != outer_scope) {
|
||||
assert(inner_scope);
|
||||
if (inner_scope->id == ScopeIdDefer) {
|
||||
AstNode *defer_node = inner_scope->source_node;
|
||||
assert(defer_node->type == NodeTypeDefer);
|
||||
ReturnKind defer_kind = defer_node->data.defer.kind;
|
||||
results[defer_kind] += 1;
|
||||
Scope *scope = inner_scope;
|
||||
|
||||
while (scope != outer_scope) {
|
||||
assert(scope);
|
||||
switch (scope->id) {
|
||||
case ScopeIdDefer: {
|
||||
AstNode *defer_node = scope->source_node;
|
||||
assert(defer_node->type == NodeTypeDefer);
|
||||
ReturnKind defer_kind = defer_node->data.defer.kind;
|
||||
results[defer_kind] += 1;
|
||||
scope = scope->parent;
|
||||
continue;
|
||||
}
|
||||
case ScopeIdDecls:
|
||||
case ScopeIdFnDef:
|
||||
return;
|
||||
case ScopeIdBlock:
|
||||
case ScopeIdVarDecl:
|
||||
case ScopeIdLoop:
|
||||
case ScopeIdSuspend:
|
||||
case ScopeIdCompTime:
|
||||
scope = scope->parent;
|
||||
continue;
|
||||
case ScopeIdDeferExpr:
|
||||
case ScopeIdCImport:
|
||||
case ScopeIdCoroPrelude:
|
||||
zig_unreachable();
|
||||
}
|
||||
inner_scope = inner_scope->parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2986,27 +3004,43 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
|
|||
if (!scope)
|
||||
return is_noreturn;
|
||||
|
||||
if (scope->id == ScopeIdDefer) {
|
||||
AstNode *defer_node = scope->source_node;
|
||||
assert(defer_node->type == NodeTypeDefer);
|
||||
ReturnKind defer_kind = defer_node->data.defer.kind;
|
||||
if (defer_kind == ReturnKindUnconditional ||
|
||||
(gen_error_defers && defer_kind == ReturnKindError))
|
||||
{
|
||||
AstNode *defer_expr_node = defer_node->data.defer.expr;
|
||||
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
|
||||
IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
|
||||
if (defer_expr_value != irb->codegen->invalid_instruction) {
|
||||
if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) {
|
||||
is_noreturn = true;
|
||||
} else {
|
||||
ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
|
||||
switch (scope->id) {
|
||||
case ScopeIdDefer: {
|
||||
AstNode *defer_node = scope->source_node;
|
||||
assert(defer_node->type == NodeTypeDefer);
|
||||
ReturnKind defer_kind = defer_node->data.defer.kind;
|
||||
if (defer_kind == ReturnKindUnconditional ||
|
||||
(gen_error_defers && defer_kind == ReturnKindError))
|
||||
{
|
||||
AstNode *defer_expr_node = defer_node->data.defer.expr;
|
||||
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
|
||||
IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
|
||||
if (defer_expr_value != irb->codegen->invalid_instruction) {
|
||||
if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) {
|
||||
is_noreturn = true;
|
||||
} else {
|
||||
ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
scope = scope->parent;
|
||||
continue;
|
||||
}
|
||||
|
||||
case ScopeIdDecls:
|
||||
case ScopeIdFnDef:
|
||||
return is_noreturn;
|
||||
case ScopeIdBlock:
|
||||
case ScopeIdVarDecl:
|
||||
case ScopeIdLoop:
|
||||
case ScopeIdSuspend:
|
||||
case ScopeIdCompTime:
|
||||
scope = scope->parent;
|
||||
continue;
|
||||
case ScopeIdDeferExpr:
|
||||
case ScopeIdCImport:
|
||||
case ScopeIdCoroPrelude:
|
||||
zig_unreachable();
|
||||
}
|
||||
scope = scope->parent;
|
||||
}
|
||||
return is_noreturn;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlen
|
|||
pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
|
||||
pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
|
||||
|
||||
pub use @import("../os/darwin_errno.zig");
|
||||
pub use @import("../os/darwin/errno.zig");
|
||||
|
||||
pub const _errno = __error;
|
||||
|
||||
|
|
|
@ -125,8 +125,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File
|
|||
test "listen on a port, send bytes, receive bytes" {
|
||||
if (builtin.os != builtin.Os.linux) {
|
||||
// TODO build abstractions for other operating systems
|
||||
return;
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
|
||||
const MyServer = struct {
|
||||
tcp_server: Server,
|
||||
|
||||
|
|
|
@ -116,13 +116,63 @@ pub const Int = struct {
|
|||
return !r.isOdd();
|
||||
}
|
||||
|
||||
fn bitcount(self: Int) usize {
|
||||
const u_bit_count = (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
|
||||
return @boolToInt(!self.positive) + u_bit_count;
|
||||
// Returns the number of bits required to represent the absolute value of self.
|
||||
fn bitCountAbs(self: Int) usize {
|
||||
return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
|
||||
}
|
||||
|
||||
// Returns the number of bits required to represent the integer in twos-complement form.
|
||||
//
|
||||
// If the integer is negative the value returned is the number of bits needed by a signed
|
||||
// integer to represent the value. If positive the value is the number of bits for an
|
||||
// unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
|
||||
// one greater than the returned value.
|
||||
//
|
||||
// e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
|
||||
fn bitCountTwosComp(self: Int) usize {
|
||||
var bits = self.bitCountAbs();
|
||||
|
||||
// If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos
|
||||
// complement requires one less bit.
|
||||
if (!self.positive) block: {
|
||||
bits += 1;
|
||||
|
||||
if (@popCount(self.limbs[self.len - 1]) == 1) {
|
||||
for (self.limbs[0 .. self.len - 1]) |limb| {
|
||||
if (@popCount(limb) != 0) {
|
||||
break :block;
|
||||
}
|
||||
}
|
||||
|
||||
bits -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
|
||||
if (self.eqZero()) {
|
||||
return true;
|
||||
}
|
||||
if (!is_signed and !self.positive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed);
|
||||
return bit_count >= req_bits;
|
||||
}
|
||||
|
||||
pub fn fits(self: Int, comptime T: type) bool {
|
||||
return self.fitsInTwosComp(T.is_signed, T.bit_count);
|
||||
}
|
||||
|
||||
// Returns the approximate size of the integer in the given base. Negative values accomodate for
|
||||
// the minus sign. This is used for determining the number of characters needed to print the
|
||||
// value. It is inexact and will exceed the given value by 1-2 digits.
|
||||
pub fn sizeInBase(self: Int, base: usize) usize {
|
||||
return (self.bitcount() / math.log2(base)) + 1;
|
||||
const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs();
|
||||
return (bit_count / math.log2(base)) + 1;
|
||||
}
|
||||
|
||||
pub fn set(self: *Int, value: var) Allocator.Error!void {
|
||||
|
@ -190,9 +240,9 @@ pub const Int = struct {
|
|||
pub fn to(self: Int, comptime T: type) ConvertError!T {
|
||||
switch (@typeId(T)) {
|
||||
TypeId.Int => {
|
||||
const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
|
||||
const UT = @IntType(false, T.bit_count);
|
||||
|
||||
if (self.bitcount() > 8 * @sizeOf(UT)) {
|
||||
if (self.bitCountTwosComp() > T.bit_count) {
|
||||
return error.TargetTooSmall;
|
||||
}
|
||||
|
||||
|
@ -209,9 +259,17 @@ pub const Int = struct {
|
|||
}
|
||||
|
||||
if (!T.is_signed) {
|
||||
return if (self.positive) r else error.NegativeIntoUnsigned;
|
||||
return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;
|
||||
} else {
|
||||
return if (self.positive) @intCast(T, r) else -@intCast(T, r);
|
||||
if (self.positive) {
|
||||
return @intCast(T, r);
|
||||
} else {
|
||||
if (math.cast(T, r)) |ok| {
|
||||
return -ok;
|
||||
} else |_| {
|
||||
return @minValue(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {
|
||||
|
@ -1137,24 +1195,88 @@ test "big.int bitcount + sizeInBase" {
|
|||
var a = try Int.init(al);
|
||||
|
||||
try a.set(0b100);
|
||||
debug.assert(a.bitcount() == 3);
|
||||
debug.assert(a.bitCountAbs() == 3);
|
||||
debug.assert(a.sizeInBase(2) >= 3);
|
||||
debug.assert(a.sizeInBase(10) >= 1);
|
||||
|
||||
a.negate();
|
||||
debug.assert(a.bitCountAbs() == 3);
|
||||
debug.assert(a.sizeInBase(2) >= 4);
|
||||
debug.assert(a.sizeInBase(10) >= 2);
|
||||
|
||||
try a.set(0xffffffff);
|
||||
debug.assert(a.bitcount() == 32);
|
||||
debug.assert(a.bitCountAbs() == 32);
|
||||
debug.assert(a.sizeInBase(2) >= 32);
|
||||
debug.assert(a.sizeInBase(10) >= 10);
|
||||
|
||||
try a.shiftLeft(a, 5000);
|
||||
debug.assert(a.bitcount() == 5032);
|
||||
debug.assert(a.bitCountAbs() == 5032);
|
||||
debug.assert(a.sizeInBase(2) >= 5032);
|
||||
a.positive = false;
|
||||
|
||||
debug.assert(a.bitcount() == 5033);
|
||||
debug.assert(a.bitCountAbs() == 5032);
|
||||
debug.assert(a.sizeInBase(2) >= 5033);
|
||||
}
|
||||
|
||||
test "big.int bitcount/to" {
|
||||
var a = try Int.init(al);
|
||||
|
||||
try a.set(0);
|
||||
debug.assert(a.bitCountTwosComp() == 0);
|
||||
|
||||
// TODO: stack smashing
|
||||
// debug.assert((try a.to(u0)) == 0);
|
||||
// TODO: sigsegv
|
||||
// debug.assert((try a.to(i0)) == 0);
|
||||
|
||||
try a.set(-1);
|
||||
debug.assert(a.bitCountTwosComp() == 1);
|
||||
debug.assert((try a.to(i1)) == -1);
|
||||
|
||||
try a.set(-8);
|
||||
debug.assert(a.bitCountTwosComp() == 4);
|
||||
debug.assert((try a.to(i4)) == -8);
|
||||
|
||||
try a.set(127);
|
||||
debug.assert(a.bitCountTwosComp() == 7);
|
||||
debug.assert((try a.to(u7)) == 127);
|
||||
|
||||
try a.set(-128);
|
||||
debug.assert(a.bitCountTwosComp() == 8);
|
||||
debug.assert((try a.to(i8)) == -128);
|
||||
|
||||
try a.set(-129);
|
||||
debug.assert(a.bitCountTwosComp() == 9);
|
||||
debug.assert((try a.to(i9)) == -129);
|
||||
}
|
||||
|
||||
test "big.int fits" {
|
||||
var a = try Int.init(al);
|
||||
|
||||
try a.set(0);
|
||||
debug.assert(a.fits(u0));
|
||||
debug.assert(a.fits(i0));
|
||||
|
||||
try a.set(255);
|
||||
debug.assert(!a.fits(u0));
|
||||
debug.assert(!a.fits(u1));
|
||||
debug.assert(!a.fits(i8));
|
||||
debug.assert(a.fits(u8));
|
||||
debug.assert(a.fits(u9));
|
||||
debug.assert(a.fits(i9));
|
||||
|
||||
try a.set(-128);
|
||||
debug.assert(!a.fits(i7));
|
||||
debug.assert(a.fits(i8));
|
||||
debug.assert(a.fits(i9));
|
||||
debug.assert(!a.fits(u9));
|
||||
|
||||
try a.set(0x1ffffffffeeeeeeee);
|
||||
debug.assert(!a.fits(u32));
|
||||
debug.assert(!a.fits(u64));
|
||||
debug.assert(a.fits(u65));
|
||||
}
|
||||
|
||||
test "big.int string set" {
|
||||
var a = try Int.init(al);
|
||||
try a.setString(10, "120317241209124781241290847124");
|
||||
|
|
|
@ -2,7 +2,7 @@ const std = @import("../index.zig");
|
|||
const c = std.c;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
pub use @import("darwin_errno.zig");
|
||||
pub use @import("darwin/errno.zig");
|
||||
|
||||
pub const PATH_MAX = 1024;
|
||||
|
||||
|
@ -482,6 +482,92 @@ pub const NOTE_MACH_CONTINUOUS_TIME = 0x00000080;
|
|||
/// data is mach absolute time units
|
||||
pub const NOTE_MACHTIME = 0x00000100;
|
||||
|
||||
pub const AF_UNSPEC: c_int = 0;
|
||||
pub const AF_LOCAL: c_int = 1;
|
||||
pub const AF_UNIX: c_int = AF_LOCAL;
|
||||
pub const AF_INET: c_int = 2;
|
||||
pub const AF_SYS_CONTROL: c_int = 2;
|
||||
pub const AF_IMPLINK: c_int = 3;
|
||||
pub const AF_PUP: c_int = 4;
|
||||
pub const AF_CHAOS: c_int = 5;
|
||||
pub const AF_NS: c_int = 6;
|
||||
pub const AF_ISO: c_int = 7;
|
||||
pub const AF_OSI: c_int = AF_ISO;
|
||||
pub const AF_ECMA: c_int = 8;
|
||||
pub const AF_DATAKIT: c_int = 9;
|
||||
pub const AF_CCITT: c_int = 10;
|
||||
pub const AF_SNA: c_int = 11;
|
||||
pub const AF_DECnet: c_int = 12;
|
||||
pub const AF_DLI: c_int = 13;
|
||||
pub const AF_LAT: c_int = 14;
|
||||
pub const AF_HYLINK: c_int = 15;
|
||||
pub const AF_APPLETALK: c_int = 16;
|
||||
pub const AF_ROUTE: c_int = 17;
|
||||
pub const AF_LINK: c_int = 18;
|
||||
pub const AF_XTP: c_int = 19;
|
||||
pub const AF_COIP: c_int = 20;
|
||||
pub const AF_CNT: c_int = 21;
|
||||
pub const AF_RTIP: c_int = 22;
|
||||
pub const AF_IPX: c_int = 23;
|
||||
pub const AF_SIP: c_int = 24;
|
||||
pub const AF_PIP: c_int = 25;
|
||||
pub const AF_ISDN: c_int = 28;
|
||||
pub const AF_E164: c_int = AF_ISDN;
|
||||
pub const AF_KEY: c_int = 29;
|
||||
pub const AF_INET6: c_int = 30;
|
||||
pub const AF_NATM: c_int = 31;
|
||||
pub const AF_SYSTEM: c_int = 32;
|
||||
pub const AF_NETBIOS: c_int = 33;
|
||||
pub const AF_PPP: c_int = 34;
|
||||
pub const AF_MAX: c_int = 40;
|
||||
|
||||
pub const PF_UNSPEC: c_int = AF_UNSPEC;
|
||||
pub const PF_LOCAL: c_int = AF_LOCAL;
|
||||
pub const PF_UNIX: c_int = PF_LOCAL;
|
||||
pub const PF_INET: c_int = AF_INET;
|
||||
pub const PF_IMPLINK: c_int = AF_IMPLINK;
|
||||
pub const PF_PUP: c_int = AF_PUP;
|
||||
pub const PF_CHAOS: c_int = AF_CHAOS;
|
||||
pub const PF_NS: c_int = AF_NS;
|
||||
pub const PF_ISO: c_int = AF_ISO;
|
||||
pub const PF_OSI: c_int = AF_ISO;
|
||||
pub const PF_ECMA: c_int = AF_ECMA;
|
||||
pub const PF_DATAKIT: c_int = AF_DATAKIT;
|
||||
pub const PF_CCITT: c_int = AF_CCITT;
|
||||
pub const PF_SNA: c_int = AF_SNA;
|
||||
pub const PF_DECnet: c_int = AF_DECnet;
|
||||
pub const PF_DLI: c_int = AF_DLI;
|
||||
pub const PF_LAT: c_int = AF_LAT;
|
||||
pub const PF_HYLINK: c_int = AF_HYLINK;
|
||||
pub const PF_APPLETALK: c_int = AF_APPLETALK;
|
||||
pub const PF_ROUTE: c_int = AF_ROUTE;
|
||||
pub const PF_LINK: c_int = AF_LINK;
|
||||
pub const PF_XTP: c_int = AF_XTP;
|
||||
pub const PF_COIP: c_int = AF_COIP;
|
||||
pub const PF_CNT: c_int = AF_CNT;
|
||||
pub const PF_SIP: c_int = AF_SIP;
|
||||
pub const PF_IPX: c_int = AF_IPX;
|
||||
pub const PF_RTIP: c_int = AF_RTIP;
|
||||
pub const PF_PIP: c_int = AF_PIP;
|
||||
pub const PF_ISDN: c_int = AF_ISDN;
|
||||
pub const PF_KEY: c_int = AF_KEY;
|
||||
pub const PF_INET6: c_int = AF_INET6;
|
||||
pub const PF_NATM: c_int = AF_NATM;
|
||||
pub const PF_SYSTEM: c_int = AF_SYSTEM;
|
||||
pub const PF_NETBIOS: c_int = AF_NETBIOS;
|
||||
pub const PF_PPP: c_int = AF_PPP;
|
||||
pub const PF_MAX: c_int = AF_MAX;
|
||||
|
||||
pub const SYSPROTO_EVENT: c_int = 1;
|
||||
pub const SYSPROTO_CONTROL: c_int = 2;
|
||||
|
||||
pub const SOCK_STREAM: c_int = 1;
|
||||
pub const SOCK_DGRAM: c_int = 2;
|
||||
pub const SOCK_RAW: c_int = 3;
|
||||
pub const SOCK_RDM: c_int = 4;
|
||||
pub const SOCK_SEQPACKET: c_int = 5;
|
||||
pub const SOCK_MAXADDRLEN: c_int = 255;
|
||||
|
||||
fn wstatus(x: i32) i32 {
|
||||
return x & 0o177;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ pub const File = struct {
|
|||
/// The OS-specific file descriptor or file handle.
|
||||
handle: os.FileHandle,
|
||||
|
||||
const OpenError = os.WindowsOpenError || os.PosixOpenError;
|
||||
pub const OpenError = os.WindowsOpenError || os.PosixOpenError;
|
||||
|
||||
/// `path` needs to be copied in memory to add a null terminating byte, hence the allocator.
|
||||
/// Call close to clean up.
|
||||
|
@ -239,7 +239,7 @@ pub const File = struct {
|
|||
},
|
||||
Os.windows => {
|
||||
var pos: windows.LARGE_INTEGER = undefined;
|
||||
if (windows.SetFilePointerEx(self.handle, 0, *pos, windows.FILE_CURRENT) == 0) {
|
||||
if (windows.SetFilePointerEx(self.handle, 0, &pos, windows.FILE_CURRENT) == 0) {
|
||||
const err = windows.GetLastError();
|
||||
return switch (err) {
|
||||
windows.ERROR.INVALID_PARAMETER => error.BadFd,
|
||||
|
@ -248,13 +248,7 @@ pub const File = struct {
|
|||
}
|
||||
|
||||
assert(pos >= 0);
|
||||
if (@sizeOf(@typeOf(pos)) > @sizeOf(usize)) {
|
||||
if (pos > @maxValue(usize)) {
|
||||
return error.FilePosLargerThanPointerRange;
|
||||
}
|
||||
}
|
||||
|
||||
return usize(pos);
|
||||
return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange;
|
||||
},
|
||||
else => @compileError("unsupported OS"),
|
||||
}
|
||||
|
@ -286,7 +280,7 @@ pub const File = struct {
|
|||
Unexpected,
|
||||
};
|
||||
|
||||
fn mode(self: *File) ModeError!os.FileMode {
|
||||
pub fn mode(self: *File) ModeError!os.FileMode {
|
||||
if (is_posix) {
|
||||
var stat: posix.Stat = undefined;
|
||||
const err = posix.getErrno(posix.fstat(self.handle, &stat));
|
||||
|
@ -361,7 +355,7 @@ pub const File = struct {
|
|||
|
||||
pub const WriteError = os.WindowsWriteError || os.PosixWriteError;
|
||||
|
||||
fn write(self: *File, bytes: []const u8) WriteError!void {
|
||||
pub fn write(self: *File, bytes: []const u8) WriteError!void {
|
||||
if (is_posix) {
|
||||
try os.posixWrite(self.handle, bytes);
|
||||
} else if (is_windows) {
|
||||
|
|
|
@ -11,7 +11,7 @@ const os = this;
|
|||
test "std.os" {
|
||||
_ = @import("child_process.zig");
|
||||
_ = @import("darwin.zig");
|
||||
_ = @import("darwin_errno.zig");
|
||||
_ = @import("darwin/errno.zig");
|
||||
_ = @import("get_user_id.zig");
|
||||
_ = @import("linux/index.zig");
|
||||
_ = @import("path.zig");
|
||||
|
|
|
@ -5,11 +5,25 @@ const test_fn_list = builtin.__zig_test_fn_slice;
|
|||
const warn = std.debug.warn;
|
||||
|
||||
pub fn main() !void {
|
||||
var ok_count: usize = 0;
|
||||
var skip_count: usize = 0;
|
||||
for (test_fn_list) |test_fn, i| {
|
||||
warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
|
||||
|
||||
try test_fn.func();
|
||||
|
||||
warn("OK\n");
|
||||
if (test_fn.func()) |_| {
|
||||
ok_count += 1;
|
||||
warn("OK\n");
|
||||
} else |err| switch (err) {
|
||||
error.SkipZigTest => {
|
||||
skip_count += 1;
|
||||
warn("SKIP\n");
|
||||
},
|
||||
else => return err,
|
||||
}
|
||||
}
|
||||
if (ok_count == test_fn_list.len) {
|
||||
warn("All tests passed.\n");
|
||||
} else {
|
||||
warn("{} passed; {} skipped.\n", ok_count, skip_count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,3 +61,18 @@ test "defer and labeled break" {
|
|||
|
||||
assert(i == 1);
|
||||
}
|
||||
|
||||
test "errdefer does not apply to fn inside fn" {
|
||||
if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
|
||||
}
|
||||
|
||||
fn testNestedFnErrDefer() error!void {
|
||||
var a: i32 = 0;
|
||||
errdefer a += 1;
|
||||
const S = struct {
|
||||
fn baz() error {
|
||||
return error.Bad;
|
||||
}
|
||||
};
|
||||
return S.baz();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue