diff --git a/CMakeLists.txt b/CMakeLists.txt index c3f0721bb549a482a94adae838a9017256c4b69f..867f2684dbf85c13099167ef47da9cc620513572 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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" diff --git a/README.md b/README.md index f4daee9e591a64a0a60359c70cb607f93d04d31a..6e582a27e78fb8a5eac0f72cfd8bcd8a81f5213f 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index d624fe4dac4a66632e123c12383e065d7c96e3dd..c34f06753da52d3e8ad1552457e139b925f3cd23 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -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; }; diff --git a/src/codegen.cpp b/src/codegen.cpp index 6e121be270d45aa765a3b6ff321acc588bdf677b..7420da97976300809059df8a9d792530cb8107e4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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(); diff --git a/src/ir.cpp b/src/ir.cpp index 96ade9d392711290fdb7d2d87468d38961ed9d38..fe5fb77085690f78a1465693cd4c85cd8e8b03af 100644 --- a/src/ir.cpp +++ b/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; } diff --git a/std/c/darwin.zig b/std/c/darwin.zig index 4189dfeadcda8e73a5699e80edfd27a271e1ea0f..1bd1d6c4c997ee99bd8998cf4a5a9c22f4f845dd 100644 --- a/std/c/darwin.zig +++ b/std/c/darwin.zig @@ -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; diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 5151ecf9344d085c9d375c74b022610d415deaee..416a8c07dc1015d054ce5d40271bab09f10f0e04 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -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, diff --git a/std/math/big/int.zig b/std/math/big/int.zig index 9af033bd08588a18fa4e65a0126de5a45c2ece8c..41e1503d49b4ab78fc4db82bbe35dfab3d41c933 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -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"); diff --git a/std/os/darwin.zig b/std/os/darwin.zig index 4134e382fcb5f26dc8547c5eb343fce7052c7515..cf67b01d5a25a728f0fd36ff2e237071a2a20aa3 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -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; } diff --git a/std/os/darwin/errno.zig b/std/os/darwin/errno.zig new file mode 100644 index 0000000000000000000000000000000000000000..438f3382ad3bbe0b2190958d743d914b62437999 --- /dev/null +++ b/std/os/darwin/errno.zig @@ -0,0 +1,328 @@ +/// Operation not permitted +pub const EPERM = 1; + +/// No such file or directory +pub const ENOENT = 2; + +/// No such process +pub const ESRCH = 3; + +/// Interrupted system call +pub const EINTR = 4; + +/// Input/output error +pub const EIO = 5; + +/// Device not configured +pub const ENXIO = 6; + +/// Argument list too long +pub const E2BIG = 7; + +/// Exec format error +pub const ENOEXEC = 8; + +/// Bad file descriptor +pub const EBADF = 9; + +/// No child processes +pub const ECHILD = 10; + +/// Resource deadlock avoided +pub const EDEADLK = 11; + +/// Cannot allocate memory +pub const ENOMEM = 12; + +/// Permission denied +pub const EACCES = 13; + +/// Bad address +pub const EFAULT = 14; + +/// Block device required +pub const ENOTBLK = 15; + +/// Device / Resource busy +pub const EBUSY = 16; + +/// File exists +pub const EEXIST = 17; + +/// Cross-device link +pub const EXDEV = 18; + +/// Operation not supported by device +pub const ENODEV = 19; + +/// Not a directory +pub const ENOTDIR = 20; + +/// Is a directory +pub const EISDIR = 21; + +/// Invalid argument +pub const EINVAL = 22; + +/// Too many open files in system +pub const ENFILE = 23; + +/// Too many open files +pub const EMFILE = 24; + +/// Inappropriate ioctl for device +pub const ENOTTY = 25; + +/// Text file busy +pub const ETXTBSY = 26; + +/// File too large +pub const EFBIG = 27; + +/// No space left on device +pub const ENOSPC = 28; + +/// Illegal seek +pub const ESPIPE = 29; + +/// Read-only file system +pub const EROFS = 30; + +/// Too many links +pub const EMLINK = 31; +/// Broken pipe + +// math software +pub const EPIPE = 32; + +/// Numerical argument out of domain +pub const EDOM = 33; +/// Result too large + +// non-blocking and interrupt i/o +pub const ERANGE = 34; + +/// Resource temporarily unavailable +pub const EAGAIN = 35; + +/// Operation would block +pub const EWOULDBLOCK = EAGAIN; + +/// Operation now in progress +pub const EINPROGRESS = 36; +/// Operation already in progress + +// ipc/network software -- argument errors +pub const EALREADY = 37; + +/// Socket operation on non-socket +pub const ENOTSOCK = 38; + +/// Destination address required +pub const EDESTADDRREQ = 39; + +/// Message too long +pub const EMSGSIZE = 40; + +/// Protocol wrong type for socket +pub const EPROTOTYPE = 41; + +/// Protocol not available +pub const ENOPROTOOPT = 42; + +/// Protocol not supported +pub const EPROTONOSUPPORT = 43; + +/// Socket type not supported +pub const ESOCKTNOSUPPORT = 44; + +/// Operation not supported +pub const ENOTSUP = 45; + +/// Protocol family not supported +pub const EPFNOSUPPORT = 46; + +/// Address family not supported by protocol family +pub const EAFNOSUPPORT = 47; + +/// Address already in use +pub const EADDRINUSE = 48; +/// Can't assign requested address + +// ipc/network software -- operational errors +pub const EADDRNOTAVAIL = 49; + +/// Network is down +pub const ENETDOWN = 50; + +/// Network is unreachable +pub const ENETUNREACH = 51; + +/// Network dropped connection on reset +pub const ENETRESET = 52; + +/// Software caused connection abort +pub const ECONNABORTED = 53; + +/// Connection reset by peer +pub const ECONNRESET = 54; + +/// No buffer space available +pub const ENOBUFS = 55; + +/// Socket is already connected +pub const EISCONN = 56; + +/// Socket is not connected +pub const ENOTCONN = 57; + +/// Can't send after socket shutdown +pub const ESHUTDOWN = 58; + +/// Too many references: can't splice +pub const ETOOMANYREFS = 59; + +/// Operation timed out +pub const ETIMEDOUT = 60; + +/// Connection refused +pub const ECONNREFUSED = 61; + +/// Too many levels of symbolic links +pub const ELOOP = 62; + +/// File name too long +pub const ENAMETOOLONG = 63; + +/// Host is down +pub const EHOSTDOWN = 64; + +/// No route to host +pub const EHOSTUNREACH = 65; +/// Directory not empty + +// quotas & mush +pub const ENOTEMPTY = 66; + +/// Too many processes +pub const EPROCLIM = 67; + +/// Too many users +pub const EUSERS = 68; +/// Disc quota exceeded + +// Network File System +pub const EDQUOT = 69; + +/// Stale NFS file handle +pub const ESTALE = 70; + +/// Too many levels of remote in path +pub const EREMOTE = 71; + +/// RPC struct is bad +pub const EBADRPC = 72; + +/// RPC version wrong +pub const ERPCMISMATCH = 73; + +/// RPC prog. not avail +pub const EPROGUNAVAIL = 74; + +/// Program version wrong +pub const EPROGMISMATCH = 75; + +/// Bad procedure for program +pub const EPROCUNAVAIL = 76; + +/// No locks available +pub const ENOLCK = 77; + +/// Function not implemented +pub const ENOSYS = 78; + +/// Inappropriate file type or format +pub const EFTYPE = 79; + +/// Authentication error +pub const EAUTH = 80; +/// Need authenticator + +// Intelligent device errors +pub const ENEEDAUTH = 81; + +/// Device power is off +pub const EPWROFF = 82; + +/// Device error, e.g. paper out +pub const EDEVERR = 83; +/// Value too large to be stored in data type + +// Program loading errors +pub const EOVERFLOW = 84; + +/// Bad executable +pub const EBADEXEC = 85; + +/// Bad CPU type in executable +pub const EBADARCH = 86; + +/// Shared library version mismatch +pub const ESHLIBVERS = 87; + +/// Malformed Macho file +pub const EBADMACHO = 88; + +/// Operation canceled +pub const ECANCELED = 89; + +/// Identifier removed +pub const EIDRM = 90; + +/// No message of desired type +pub const ENOMSG = 91; + +/// Illegal byte sequence +pub const EILSEQ = 92; + +/// Attribute not found +pub const ENOATTR = 93; + +/// Bad message +pub const EBADMSG = 94; + +/// Reserved +pub const EMULTIHOP = 95; + +/// No message available on STREAM +pub const ENODATA = 96; + +/// Reserved +pub const ENOLINK = 97; + +/// No STREAM resources +pub const ENOSR = 98; + +/// Not a STREAM +pub const ENOSTR = 99; + +/// Protocol error +pub const EPROTO = 100; + +/// STREAM ioctl timeout +pub const ETIME = 101; + +/// No such policy registered +pub const ENOPOLICY = 103; + +/// State not recoverable +pub const ENOTRECOVERABLE = 104; + +/// Previous owner died +pub const EOWNERDEAD = 105; + +/// Interface output queue is full +pub const EQFULL = 106; + +/// Must be equal largest errno +pub const ELAST = 106; diff --git a/std/os/darwin_errno.zig b/std/os/darwin_errno.zig deleted file mode 100644 index 438f3382ad3bbe0b2190958d743d914b62437999..0000000000000000000000000000000000000000 --- a/std/os/darwin_errno.zig +++ /dev/null @@ -1,328 +0,0 @@ -/// Operation not permitted -pub const EPERM = 1; - -/// No such file or directory -pub const ENOENT = 2; - -/// No such process -pub const ESRCH = 3; - -/// Interrupted system call -pub const EINTR = 4; - -/// Input/output error -pub const EIO = 5; - -/// Device not configured -pub const ENXIO = 6; - -/// Argument list too long -pub const E2BIG = 7; - -/// Exec format error -pub const ENOEXEC = 8; - -/// Bad file descriptor -pub const EBADF = 9; - -/// No child processes -pub const ECHILD = 10; - -/// Resource deadlock avoided -pub const EDEADLK = 11; - -/// Cannot allocate memory -pub const ENOMEM = 12; - -/// Permission denied -pub const EACCES = 13; - -/// Bad address -pub const EFAULT = 14; - -/// Block device required -pub const ENOTBLK = 15; - -/// Device / Resource busy -pub const EBUSY = 16; - -/// File exists -pub const EEXIST = 17; - -/// Cross-device link -pub const EXDEV = 18; - -/// Operation not supported by device -pub const ENODEV = 19; - -/// Not a directory -pub const ENOTDIR = 20; - -/// Is a directory -pub const EISDIR = 21; - -/// Invalid argument -pub const EINVAL = 22; - -/// Too many open files in system -pub const ENFILE = 23; - -/// Too many open files -pub const EMFILE = 24; - -/// Inappropriate ioctl for device -pub const ENOTTY = 25; - -/// Text file busy -pub const ETXTBSY = 26; - -/// File too large -pub const EFBIG = 27; - -/// No space left on device -pub const ENOSPC = 28; - -/// Illegal seek -pub const ESPIPE = 29; - -/// Read-only file system -pub const EROFS = 30; - -/// Too many links -pub const EMLINK = 31; -/// Broken pipe - -// math software -pub const EPIPE = 32; - -/// Numerical argument out of domain -pub const EDOM = 33; -/// Result too large - -// non-blocking and interrupt i/o -pub const ERANGE = 34; - -/// Resource temporarily unavailable -pub const EAGAIN = 35; - -/// Operation would block -pub const EWOULDBLOCK = EAGAIN; - -/// Operation now in progress -pub const EINPROGRESS = 36; -/// Operation already in progress - -// ipc/network software -- argument errors -pub const EALREADY = 37; - -/// Socket operation on non-socket -pub const ENOTSOCK = 38; - -/// Destination address required -pub const EDESTADDRREQ = 39; - -/// Message too long -pub const EMSGSIZE = 40; - -/// Protocol wrong type for socket -pub const EPROTOTYPE = 41; - -/// Protocol not available -pub const ENOPROTOOPT = 42; - -/// Protocol not supported -pub const EPROTONOSUPPORT = 43; - -/// Socket type not supported -pub const ESOCKTNOSUPPORT = 44; - -/// Operation not supported -pub const ENOTSUP = 45; - -/// Protocol family not supported -pub const EPFNOSUPPORT = 46; - -/// Address family not supported by protocol family -pub const EAFNOSUPPORT = 47; - -/// Address already in use -pub const EADDRINUSE = 48; -/// Can't assign requested address - -// ipc/network software -- operational errors -pub const EADDRNOTAVAIL = 49; - -/// Network is down -pub const ENETDOWN = 50; - -/// Network is unreachable -pub const ENETUNREACH = 51; - -/// Network dropped connection on reset -pub const ENETRESET = 52; - -/// Software caused connection abort -pub const ECONNABORTED = 53; - -/// Connection reset by peer -pub const ECONNRESET = 54; - -/// No buffer space available -pub const ENOBUFS = 55; - -/// Socket is already connected -pub const EISCONN = 56; - -/// Socket is not connected -pub const ENOTCONN = 57; - -/// Can't send after socket shutdown -pub const ESHUTDOWN = 58; - -/// Too many references: can't splice -pub const ETOOMANYREFS = 59; - -/// Operation timed out -pub const ETIMEDOUT = 60; - -/// Connection refused -pub const ECONNREFUSED = 61; - -/// Too many levels of symbolic links -pub const ELOOP = 62; - -/// File name too long -pub const ENAMETOOLONG = 63; - -/// Host is down -pub const EHOSTDOWN = 64; - -/// No route to host -pub const EHOSTUNREACH = 65; -/// Directory not empty - -// quotas & mush -pub const ENOTEMPTY = 66; - -/// Too many processes -pub const EPROCLIM = 67; - -/// Too many users -pub const EUSERS = 68; -/// Disc quota exceeded - -// Network File System -pub const EDQUOT = 69; - -/// Stale NFS file handle -pub const ESTALE = 70; - -/// Too many levels of remote in path -pub const EREMOTE = 71; - -/// RPC struct is bad -pub const EBADRPC = 72; - -/// RPC version wrong -pub const ERPCMISMATCH = 73; - -/// RPC prog. not avail -pub const EPROGUNAVAIL = 74; - -/// Program version wrong -pub const EPROGMISMATCH = 75; - -/// Bad procedure for program -pub const EPROCUNAVAIL = 76; - -/// No locks available -pub const ENOLCK = 77; - -/// Function not implemented -pub const ENOSYS = 78; - -/// Inappropriate file type or format -pub const EFTYPE = 79; - -/// Authentication error -pub const EAUTH = 80; -/// Need authenticator - -// Intelligent device errors -pub const ENEEDAUTH = 81; - -/// Device power is off -pub const EPWROFF = 82; - -/// Device error, e.g. paper out -pub const EDEVERR = 83; -/// Value too large to be stored in data type - -// Program loading errors -pub const EOVERFLOW = 84; - -/// Bad executable -pub const EBADEXEC = 85; - -/// Bad CPU type in executable -pub const EBADARCH = 86; - -/// Shared library version mismatch -pub const ESHLIBVERS = 87; - -/// Malformed Macho file -pub const EBADMACHO = 88; - -/// Operation canceled -pub const ECANCELED = 89; - -/// Identifier removed -pub const EIDRM = 90; - -/// No message of desired type -pub const ENOMSG = 91; - -/// Illegal byte sequence -pub const EILSEQ = 92; - -/// Attribute not found -pub const ENOATTR = 93; - -/// Bad message -pub const EBADMSG = 94; - -/// Reserved -pub const EMULTIHOP = 95; - -/// No message available on STREAM -pub const ENODATA = 96; - -/// Reserved -pub const ENOLINK = 97; - -/// No STREAM resources -pub const ENOSR = 98; - -/// Not a STREAM -pub const ENOSTR = 99; - -/// Protocol error -pub const EPROTO = 100; - -/// STREAM ioctl timeout -pub const ETIME = 101; - -/// No such policy registered -pub const ENOPOLICY = 103; - -/// State not recoverable -pub const ENOTRECOVERABLE = 104; - -/// Previous owner died -pub const EOWNERDEAD = 105; - -/// Interface output queue is full -pub const EQFULL = 106; - -/// Must be equal largest errno -pub const ELAST = 106; diff --git a/std/os/file.zig b/std/os/file.zig index f468615ec0ef7fb6f18bb425aabd0b06116de9d3..52bc590f77bd96c7da067a4a41d9730e31383adb 100644 --- a/std/os/file.zig +++ b/std/os/file.zig @@ -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) { diff --git a/std/os/index.zig b/std/os/index.zig index 87053fd8dfefcafb5617d4f3f69f934ac9854e00..77fd2a78ad69a242b756e527d61697d5ef560116 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -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"); diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index 76a54a5018da9bc4b8ae9df456256618968dc8dd..857739e82d29191a7f77ef74651461c06875c30c 100644 --- a/std/special/test_runner.zig +++ b/std/special/test_runner.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); } } diff --git a/test/cases/defer.zig b/test/cases/defer.zig index d2b00d1f911f8627cc6577097d1b3b3e997c954a..7d4d1bc3d8cd7a7bbf3cc517ff6c00251741db25 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -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(); +}