Commit ff2c794612

Andrew Kelley <superjoe30@gmail.com>
2017-08-27 11:15:24
all behavior tests passing for macos
See #273
1 parent 9153681
ci/travis_osx_script
@@ -12,5 +12,7 @@ cd build
 cmake .. -DCMAKE_PREFIX_PATH=$PREFIX_DIR -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $($CC -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=$(echo -n | $CC -E -x c - -v 2>&1 | grep -B1 "End of search list." | head -n1 | cut -c 2- | sed "s/ .*//") -DZIG_LIBC_STATIC_LIB_DIR=$(dirname $($CC -print-file-name=crtbegin.o))
 make VERBOSE=1
 make install
-# TODO get tests passing on macos
+# TODO get full test suite passing on macos
+./zig test ../test/behavior.zig
+./zig test ../test/behavior.zig --release-fast
 # ./zig build --build-file ../build.zig test
src/link.cpp
@@ -325,6 +325,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
         lj->args.append(get_libc_static_file(g, "crtend.o"));
         lj->args.append(get_libc_file(g, "crtn.o"));
     }
+
+    if (!g->is_native_target) {
+        lj->args.append("--allow-shlib-undefined");
+    }
 }
 
 static bool is_target_cyg_mingw(const ZigTarget *target) {
std/c/darwin.zig
@@ -1,5 +1,7 @@
 extern "c" fn __error() -> &c_int;
 
+pub use @import("../os/darwin_errno.zig");
+
 pub const _errno = __error;
 
 /// Renamed to Stat to not conflict with the stat function.
std/c/index.zig
@@ -1,4 +1,3 @@
-pub use @import("../os/errno.zig");
 const builtin = @import("builtin");
 const Os = builtin.Os;
 
std/c/linux.zig
@@ -1,3 +1,5 @@
+pub use @import("../os/linux_errno.zig");
+
 pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) -> c_int;
 extern "c" fn __errno_location() -> &c_int;
 pub const _errno = __errno_location;
std/os/child_process.zig
@@ -3,7 +3,6 @@ const os = @import("index.zig");
 const posix = os.posix;
 const mem = @import("../mem.zig");
 const Allocator = mem.Allocator;
-const errno = @import("errno.zig");
 const debug = @import("../debug.zig");
 const assert = debug.assert;
 const BufMap = @import("../buf_map.zig").BufMap;
@@ -56,8 +55,8 @@ pub const ChildProcess = struct {
             const err = posix.getErrno(posix.waitpid(self.pid, &status, 0));
             if (err > 0) {
                 switch (err) {
-                    errno.EINVAL, errno.ECHILD => unreachable,
-                    errno.EINTR => continue,
+                    posix.EINVAL, posix.ECHILD => unreachable,
+                    posix.EINTR => continue,
                     else => {
                         if (self.stdin) |*stdin| { stdin.close(); }
                         if (self.stdout) |*stdout| { stdout.close(); }
@@ -130,7 +129,7 @@ pub const ChildProcess = struct {
         const pid_err = posix.getErrno(pid);
         if (pid_err > 0) {
             return switch (pid_err) {
-                errno.EAGAIN, errno.ENOMEM, errno.ENOSYS => error.SystemResources,
+                posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources,
                 else => error.Unexpected,
             };
         }
@@ -209,7 +208,7 @@ fn makePipe() -> %[2]i32 {
     const err = posix.getErrno(posix.pipe(&fds));
     if (err > 0) {
         return switch (err) {
-            errno.EMFILE, errno.ENFILE => error.SystemResources,
+            posix.EMFILE, posix.ENFILE => error.SystemResources,
             else => error.Unexpected,
         }
     }
std/os/darwin.zig
@@ -1,6 +1,8 @@
 const c = @import("../c/index.zig");
 const assert = @import("../debug.zig").assert;
 
+pub use @import("darwin_errno.zig");
+
 pub const STDIN_FILENO = 0;
 pub const STDOUT_FILENO = 1;
 pub const STDERR_FILENO = 2;
std/os/darwin_errno.zig
@@ -0,0 +1,142 @@
+
+pub const EPERM = 1; /// Operation not permitted
+pub const ENOENT = 2; /// No such file or directory
+pub const ESRCH = 3; /// No such process
+pub const EINTR = 4; /// Interrupted system call
+pub const EIO = 5; /// Input/output error
+pub const ENXIO = 6; /// Device not configured
+pub const E2BIG = 7; /// Argument list too long
+pub const ENOEXEC = 8; /// Exec format error
+pub const EBADF = 9; /// Bad file descriptor
+pub const ECHILD = 10; /// No child processes
+pub const EDEADLK = 11; /// Resource deadlock avoided
+
+pub const ENOMEM = 12; /// Cannot allocate memory
+pub const EACCES = 13; /// Permission denied
+pub const EFAULT = 14; /// Bad address
+pub const ENOTBLK = 15; /// Block device required
+pub const EBUSY = 16; /// Device / Resource busy
+pub const EEXIST = 17; /// File exists
+pub const EXDEV = 18; /// Cross-device link
+pub const ENODEV = 19; /// Operation not supported by device
+pub const ENOTDIR = 20; /// Not a directory
+pub const EISDIR = 21; /// Is a directory
+pub const EINVAL = 22; /// Invalid argument
+pub const ENFILE = 23; /// Too many open files in system
+pub const EMFILE = 24; /// Too many open files
+pub const ENOTTY = 25; /// Inappropriate ioctl for device
+pub const ETXTBSY = 26; /// Text file busy
+pub const EFBIG = 27; /// File too large
+pub const ENOSPC = 28; /// No space left on device
+pub const ESPIPE = 29; /// Illegal seek
+pub const EROFS = 30; /// Read-only file system
+pub const EMLINK = 31; /// Too many links
+pub const EPIPE = 32; /// Broken pipe
+
+// math software
+pub const EDOM = 33; /// Numerical argument out of domain
+pub const ERANGE = 34; /// Result too large
+
+// non-blocking and interrupt i/o
+pub const EAGAIN = 35; /// Resource temporarily unavailable
+pub const EWOULDBLOCK = EAGAIN; /// Operation would block
+pub const EINPROGRESS = 36; /// Operation now in progress
+pub const EALREADY = 37; /// Operation already in progress
+
+// ipc/network software -- argument errors
+pub const ENOTSOCK = 38; /// Socket operation on non-socket
+pub const EDESTADDRREQ = 39; /// Destination address required
+pub const EMSGSIZE = 40; /// Message too long
+pub const EPROTOTYPE = 41; /// Protocol wrong type for socket
+pub const ENOPROTOOPT = 42; /// Protocol not available
+pub const EPROTONOSUPPORT = 43; /// Protocol not supported
+
+pub const ESOCKTNOSUPPORT = 44; /// Socket type not supported
+
+pub const ENOTSUP = 45; /// Operation not supported
+
+pub const EPFNOSUPPORT = 46; /// Protocol family not supported
+pub const EAFNOSUPPORT = 47; /// Address family not supported by protocol family
+pub const EADDRINUSE = 48; /// Address already in use
+pub const EADDRNOTAVAIL = 49; /// Can't assign requested address
+
+// ipc/network software -- operational errors
+pub const ENETDOWN = 50; /// Network is down
+pub const ENETUNREACH = 51; /// Network is unreachable
+pub const ENETRESET = 52; /// Network dropped connection on reset
+pub const ECONNABORTED = 53; /// Software caused connection abort
+pub const ECONNRESET = 54; /// Connection reset by peer
+pub const ENOBUFS = 55; /// No buffer space available
+pub const EISCONN = 56; /// Socket is already connected
+pub const ENOTCONN = 57; /// Socket is not connected
+
+pub const ESHUTDOWN = 58; /// Can't send after socket shutdown
+pub const ETOOMANYREFS = 59; /// Too many references: can't splice
+
+pub const ETIMEDOUT = 60; /// Operation timed out
+pub const ECONNREFUSED = 61; /// Connection refused
+
+pub const ELOOP = 62; /// Too many levels of symbolic links
+pub const ENAMETOOLONG = 63; /// File name too long
+
+pub const EHOSTDOWN = 64; /// Host is down
+pub const EHOSTUNREACH = 65; /// No route to host
+pub const ENOTEMPTY = 66; /// Directory not empty
+
+// quotas & mush
+pub const EPROCLIM = 67; /// Too many processes
+pub const EUSERS = 68; /// Too many users
+pub const EDQUOT = 69; /// Disc quota exceeded
+
+// Network File System
+pub const ESTALE = 70; /// Stale NFS file handle
+pub const EREMOTE = 71; /// Too many levels of remote in path
+pub const EBADRPC = 72; /// RPC struct is bad
+pub const ERPCMISMATCH = 73; /// RPC version wrong
+pub const EPROGUNAVAIL = 74; /// RPC prog. not avail
+pub const EPROGMISMATCH = 75; /// Program version wrong
+pub const EPROCUNAVAIL = 76; /// Bad procedure for program
+
+pub const ENOLCK = 77; /// No locks available
+pub const ENOSYS = 78; /// Function not implemented
+
+pub const EFTYPE = 79; /// Inappropriate file type or format
+pub const EAUTH = 80; /// Authentication error
+pub const ENEEDAUTH = 81; /// Need authenticator
+
+// Intelligent device errors
+pub const EPWROFF = 82; /// Device power is off
+pub const EDEVERR = 83; /// Device error, e.g. paper out
+
+pub const EOVERFLOW = 84; /// Value too large to be stored in data type
+
+// Program loading errors
+pub const EBADEXEC = 85; /// Bad executable
+pub const EBADARCH = 86; /// Bad CPU type in executable
+pub const ESHLIBVERS = 87; /// Shared library version mismatch
+pub const EBADMACHO = 88; /// Malformed Macho file
+
+pub const ECANCELED = 89; /// Operation canceled
+
+pub const EIDRM = 90; /// Identifier removed
+pub const ENOMSG = 91; /// No message of desired type
+pub const EILSEQ = 92; /// Illegal byte sequence
+pub const ENOATTR = 93; /// Attribute not found
+
+pub const EBADMSG = 94; /// Bad message
+pub const EMULTIHOP = 95; /// Reserved
+pub const ENODATA = 96; /// No message available on STREAM
+pub const ENOLINK = 97; /// Reserved
+pub const ENOSR = 98; /// No STREAM resources
+pub const ENOSTR = 99; /// Not a STREAM
+pub const EPROTO = 100; /// Protocol error
+pub const ETIME = 101; /// STREAM ioctl timeout
+
+pub const ENOPOLICY = 103; /// No such policy registered
+
+pub const ENOTRECOVERABLE = 104; /// State not recoverable
+pub const EOWNERDEAD = 105; /// Previous owner died
+
+pub const EQFULL = 106; /// Interface output queue is full
+pub const ELAST = 106; /// Must be equal largest errno
+
std/os/index.zig
@@ -23,7 +23,6 @@ pub const page_size = 4 * 1024;
 const debug = @import("../debug.zig");
 const assert = debug.assert;
 
-const errno = @import("errno.zig");
 const c = @import("../c/index.zig");
 
 const mem = @import("../mem.zig");
@@ -63,9 +62,9 @@ pub fn getRandomBytes(buf: []u8) -> %void {
             const err = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
             if (err > 0) {
                 return switch (err) {
-                    errno.EINVAL => unreachable,
-                    errno.EFAULT => unreachable,
-                    errno.EINTR  => continue,
+                    posix.EINVAL => unreachable,
+                    posix.EFAULT => unreachable,
+                    posix.EINTR  => continue,
                     else         => error.Unexpected,
                 }
             }
@@ -117,7 +116,7 @@ pub coldcc fn abort() -> noreturn {
 pub fn posixClose(fd: i32) {
     while (true) {
         const err = posix.getErrno(posix.close(fd));
-        if (err == errno.EINTR) {
+        if (err == posix.EINTR) {
             continue;
         } else {
             return;
@@ -133,13 +132,13 @@ pub fn posixRead(fd: i32, buf: []u8) -> %void {
         const err = posix.getErrno(amt_written);
         if (err > 0) {
             return switch (err) {
-                errno.EINTR => continue,
-                errno.EINVAL, errno.EFAULT => unreachable,
-                errno.EAGAIN => error.WouldBlock,
-                errno.EBADF => error.FileClosed,
-                errno.EIO => error.InputOutput,
-                errno.EISDIR => error.IsDir,
-                errno.ENOBUFS, errno.ENOMEM => error.SystemResources,
+                posix.EINTR => continue,
+                posix.EINVAL, posix.EFAULT => unreachable,
+                posix.EAGAIN => error.WouldBlock,
+                posix.EBADF => error.FileClosed,
+                posix.EIO => error.InputOutput,
+                posix.EISDIR => error.IsDir,
+                posix.ENOBUFS, posix.ENOMEM => error.SystemResources,
                 else => return error.Unexpected,
             }
         }
@@ -164,17 +163,17 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
         const write_err = posix.getErrno(write_ret);
         if (write_err > 0) {
             return switch (write_err) {
-                errno.EINTR  => continue,
-                errno.EINVAL, errno.EFAULT => unreachable,
-                errno.EAGAIN => error.WouldBlock,
-                errno.EBADF => error.FileClosed,
-                errno.EDESTADDRREQ => error.DestinationAddressRequired,
-                errno.EDQUOT => error.DiskQuota,
-                errno.EFBIG  => error.FileTooBig,
-                errno.EIO    => error.InputOutput,
-                errno.ENOSPC => error.NoSpaceLeft,
-                errno.EPERM  => error.AccessDenied,
-                errno.EPIPE  => error.BrokenPipe,
+                posix.EINTR  => continue,
+                posix.EINVAL, posix.EFAULT => unreachable,
+                posix.EAGAIN => error.WouldBlock,
+                posix.EBADF => error.FileClosed,
+                posix.EDESTADDRREQ => error.DestinationAddressRequired,
+                posix.EDQUOT => error.DiskQuota,
+                posix.EFBIG  => error.FileTooBig,
+                posix.EIO    => error.InputOutput,
+                posix.ENOSPC => error.NoSpaceLeft,
+                posix.EPERM  => error.AccessDenied,
+                posix.EPIPE  => error.BrokenPipe,
                 else         => error.Unexpected,
             }
         }
@@ -256,23 +255,23 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
         const err = posix.getErrno(result);
         if (err > 0) {
             return switch (err) {
-                errno.EINTR => continue,
-
-                errno.EFAULT => unreachable,
-                errno.EINVAL => unreachable,
-                errno.EACCES => error.AccessDenied,
-                errno.EFBIG, errno.EOVERFLOW => error.FileTooBig,
-                errno.EISDIR => error.IsDir,
-                errno.ELOOP => error.SymLinkLoop,
-                errno.EMFILE => error.ProcessFdQuotaExceeded,
-                errno.ENAMETOOLONG => error.NameTooLong,
-                errno.ENFILE => error.SystemFdQuotaExceeded,
-                errno.ENODEV => error.NoDevice,
-                errno.ENOENT => error.PathNotFound,
-                errno.ENOMEM => error.SystemResources,
-                errno.ENOSPC => error.NoSpaceLeft,
-                errno.ENOTDIR => error.NotDir,
-                errno.EPERM => error.AccessDenied,
+                posix.EINTR => continue,
+
+                posix.EFAULT => unreachable,
+                posix.EINVAL => unreachable,
+                posix.EACCES => error.AccessDenied,
+                posix.EFBIG, posix.EOVERFLOW => error.FileTooBig,
+                posix.EISDIR => error.IsDir,
+                posix.ELOOP => error.SymLinkLoop,
+                posix.EMFILE => error.ProcessFdQuotaExceeded,
+                posix.ENAMETOOLONG => error.NameTooLong,
+                posix.ENFILE => error.SystemFdQuotaExceeded,
+                posix.ENODEV => error.NoDevice,
+                posix.ENOENT => error.PathNotFound,
+                posix.ENOMEM => error.SystemResources,
+                posix.ENOSPC => error.NoSpaceLeft,
+                posix.ENOTDIR => error.NotDir,
+                posix.EPERM => error.AccessDenied,
                 else => error.Unexpected,
             }
         }
@@ -285,9 +284,9 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void {
         const err = posix.getErrno(posix.dup2(old_fd, new_fd));
         if (err > 0) {
             return switch (err) {
-                errno.EBUSY, errno.EINTR => continue,
-                errno.EMFILE => error.ProcessFdQuotaExceeded,
-                errno.EINVAL => unreachable,
+                posix.EBUSY, posix.EINTR => continue,
+                posix.EMFILE => error.ProcessFdQuotaExceeded,
+                posix.EINVAL => unreachable,
                 else => error.Unexpected,
             };
         }
@@ -381,14 +380,14 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
         path_buf[search_path.len + exe_path.len + 1] = 0;
         err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr));
         assert(err > 0);
-        if (err == errno.EACCES) {
+        if (err == posix.EACCES) {
             seen_eacces = true;
-        } else if (err != errno.ENOENT) {
+        } else if (err != posix.ENOENT) {
             return posixExecveErrnoToErr(err);
         }
     }
     if (seen_eacces) {
-        err = errno.EACCES;
+        err = posix.EACCES;
     }
     return posixExecveErrnoToErr(err);
 }
@@ -396,15 +395,15 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
 fn posixExecveErrnoToErr(err: usize) -> error {
     assert(err > 0);
     return switch (err) {
-        errno.EFAULT => unreachable,
-        errno.E2BIG, errno.EMFILE, errno.ENAMETOOLONG, errno.ENFILE, errno.ENOMEM => error.SystemResources,
-        errno.EACCES, errno.EPERM => error.AccessDenied,
-        errno.EINVAL, errno.ENOEXEC => error.InvalidExe,
-        errno.EIO, errno.ELOOP => error.FileSystem,
-        errno.EISDIR => error.IsDir,
-        errno.ENOENT => error.FileNotFound,
-        errno.ENOTDIR => error.NotDir,
-        errno.ETXTBSY => error.FileBusy,
+        posix.EFAULT => unreachable,
+        posix.E2BIG, posix.EMFILE, posix.ENAMETOOLONG, posix.ENFILE, posix.ENOMEM => error.SystemResources,
+        posix.EACCES, posix.EPERM => error.AccessDenied,
+        posix.EINVAL, posix.ENOEXEC => error.InvalidExe,
+        posix.EIO, posix.ELOOP => error.FileSystem,
+        posix.EISDIR => error.IsDir,
+        posix.ENOENT => error.FileNotFound,
+        posix.ENOTDIR => error.NotDir,
+        posix.ETXTBSY => error.FileBusy,
         else => error.Unexpected,
     };
 }
@@ -464,7 +463,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
     %defer allocator.free(buf);
     while (true) {
         const err = posix.getErrno(posix.getcwd(buf.ptr, buf.len));
-        if (err == errno.ERANGE) {
+        if (err == posix.ERANGE) {
             buf = %return allocator.realloc(u8, buf, buf.len * 2);
             continue;
         } else if (err > 0) {
@@ -490,18 +489,18 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con
     const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr));
     if (err > 0) {
         return switch (err) {
-            errno.EFAULT, errno.EINVAL => unreachable,
-            errno.EACCES, errno.EPERM => error.AccessDenied,
-            errno.EDQUOT => error.DiskQuota,
-            errno.EEXIST => error.PathAlreadyExists,
-            errno.EIO => error.FileSystem,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOTDIR => error.NotDir,
-            errno.ENOMEM => error.SystemResources,
-            errno.ENOSPC => error.NoSpaceLeft,
-            errno.EROFS => error.ReadOnlyFileSystem,
+            posix.EFAULT, posix.EINVAL => unreachable,
+            posix.EACCES, posix.EPERM => error.AccessDenied,
+            posix.EDQUOT => error.DiskQuota,
+            posix.EEXIST => error.PathAlreadyExists,
+            posix.EIO => error.FileSystem,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOTDIR => error.NotDir,
+            posix.ENOMEM => error.SystemResources,
+            posix.ENOSPC => error.NoSpaceLeft,
+            posix.EROFS => error.ReadOnlyFileSystem,
             else => error.Unexpected,
         };
     }
@@ -549,17 +548,17 @@ pub fn deleteFile(allocator: &Allocator, file_path: []const u8) -> %void {
     const err = posix.getErrno(posix.unlink(buf.ptr));
     if (err > 0) {
         return switch (err) {
-            errno.EACCES, errno.EPERM => error.AccessDenied,
-            errno.EBUSY => error.FileBusy,
-            errno.EFAULT, errno.EINVAL => unreachable,
-            errno.EIO => error.FileSystem,
-            errno.EISDIR => error.IsDir,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOTDIR => error.NotDir,
-            errno.ENOMEM => error.SystemResources,
-            errno.EROFS => error.ReadOnlyFileSystem,
+            posix.EACCES, posix.EPERM => error.AccessDenied,
+            posix.EBUSY => error.FileBusy,
+            posix.EFAULT, posix.EINVAL => unreachable,
+            posix.EIO => error.FileSystem,
+            posix.EISDIR => error.IsDir,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOTDIR => error.NotDir,
+            posix.ENOMEM => error.SystemResources,
+            posix.EROFS => error.ReadOnlyFileSystem,
             else => error.Unexpected,
         };
     }
@@ -612,21 +611,21 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
     const err = posix.getErrno(posix.rename(old_buf.ptr, new_buf.ptr));
     if (err > 0) {
         return switch (err) {
-            errno.EACCES, errno.EPERM => error.AccessDenied,
-            errno.EBUSY => error.FileBusy,
-            errno.EDQUOT => error.DiskQuota,
-            errno.EFAULT, errno.EINVAL => unreachable,
-            errno.EISDIR => error.IsDir,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.EMLINK => error.LinkQuotaExceeded,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOTDIR => error.NotDir,
-            errno.ENOMEM => error.SystemResources,
-            errno.ENOSPC => error.NoSpaceLeft,
-            errno.EEXIST, errno.ENOTEMPTY => error.PathAlreadyExists,
-            errno.EROFS => error.ReadOnlyFileSystem,
-            errno.EXDEV => error.RenameAcrossMountPoints,
+            posix.EACCES, posix.EPERM => error.AccessDenied,
+            posix.EBUSY => error.FileBusy,
+            posix.EDQUOT => error.DiskQuota,
+            posix.EFAULT, posix.EINVAL => unreachable,
+            posix.EISDIR => error.IsDir,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.EMLINK => error.LinkQuotaExceeded,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOTDIR => error.NotDir,
+            posix.ENOMEM => error.SystemResources,
+            posix.ENOSPC => error.NoSpaceLeft,
+            posix.EEXIST, posix.ENOTEMPTY => error.PathAlreadyExists,
+            posix.EROFS => error.ReadOnlyFileSystem,
+            posix.EXDEV => error.RenameAcrossMountPoints,
             else => error.Unexpected,
         };
     }
@@ -642,18 +641,18 @@ pub fn makeDir(allocator: &Allocator, dir_path: []const u8) -> %void {
     const err = posix.getErrno(posix.mkdir(path_buf.ptr, 0o755));
     if (err > 0) {
         return switch (err) {
-            errno.EACCES, errno.EPERM => error.AccessDenied,
-            errno.EDQUOT => error.DiskQuota,
-            errno.EEXIST => error.PathAlreadyExists,
-            errno.EFAULT => unreachable,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.EMLINK => error.LinkQuotaExceeded,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOMEM => error.SystemResources,
-            errno.ENOSPC => error.NoSpaceLeft,
-            errno.ENOTDIR => error.NotDir,
-            errno.EROFS => error.ReadOnlyFileSystem,
+            posix.EACCES, posix.EPERM => error.AccessDenied,
+            posix.EDQUOT => error.DiskQuota,
+            posix.EEXIST => error.PathAlreadyExists,
+            posix.EFAULT => unreachable,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.EMLINK => error.LinkQuotaExceeded,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOMEM => error.SystemResources,
+            posix.ENOSPC => error.NoSpaceLeft,
+            posix.ENOTDIR => error.NotDir,
+            posix.EROFS => error.ReadOnlyFileSystem,
             else => error.Unexpected,
         };
     }
@@ -709,16 +708,16 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) -> %void {
     const err = posix.getErrno(posix.rmdir(path_buf.ptr));
     if (err > 0) {
         return switch (err) {
-            errno.EACCES, errno.EPERM => error.AccessDenied,
-            errno.EBUSY => error.FileBusy,
-            errno.EFAULT, errno.EINVAL => unreachable,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOMEM => error.SystemResources,
-            errno.ENOTDIR => error.NotDir,
-            errno.EEXIST, errno.ENOTEMPTY => error.DirNotEmpty,
-            errno.EROFS => error.ReadOnlyFileSystem,
+            posix.EACCES, posix.EPERM => error.AccessDenied,
+            posix.EBUSY => error.FileBusy,
+            posix.EFAULT, posix.EINVAL => unreachable,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOMEM => error.SystemResources,
+            posix.ENOTDIR => error.NotDir,
+            posix.EEXIST, posix.ENOTEMPTY => error.DirNotEmpty,
+            posix.EROFS => error.ReadOnlyFileSystem,
             else => error.Unexpected,
         };
     }
@@ -825,8 +824,8 @@ pub const Dir = struct {
                 const err = linux.getErrno(result);
                 if (err > 0) {
                     switch (err) {
-                        errno.EBADF, errno.EFAULT, errno.ENOTDIR => unreachable,
-                        errno.EINVAL => {
+                        posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
+                        posix.EINVAL => {
                             self.buf = %return self.allocator.realloc(u8, self.buf, self.buf.len * 2);
                             continue;
                         },
@@ -879,14 +878,14 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void {
     const err = posix.getErrno(posix.chdir(path_buf.ptr));
     if (err > 0) {
         return switch (err) {
-            errno.EACCES => error.AccessDenied,
-            errno.EFAULT => unreachable,
-            errno.EIO => error.FileSystem,
-            errno.ELOOP => error.SymLinkLoop,
-            errno.ENAMETOOLONG => error.NameTooLong,
-            errno.ENOENT => error.FileNotFound,
-            errno.ENOMEM => error.SystemResources,
-            errno.ENOTDIR => error.NotDir,
+            posix.EACCES => error.AccessDenied,
+            posix.EFAULT => unreachable,
+            posix.EIO => error.FileSystem,
+            posix.ELOOP => error.SymLinkLoop,
+            posix.ENAMETOOLONG => error.NameTooLong,
+            posix.ENOENT => error.FileNotFound,
+            posix.ENOMEM => error.SystemResources,
+            posix.ENOTDIR => error.NotDir,
             else => error.Unexpected,
         };
     }
@@ -907,14 +906,14 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
         const err = posix.getErrno(ret_val);
         if (err > 0) {
             return switch (err) {
-                errno.EACCES => error.AccessDenied,
-                errno.EFAULT, errno.EINVAL => unreachable,
-                errno.EIO => error.FileSystem,
-                errno.ELOOP => error.SymLinkLoop,
-                errno.ENAMETOOLONG => error.NameTooLong,
-                errno.ENOENT => error.FileNotFound,
-                errno.ENOMEM => error.SystemResources,
-                errno.ENOTDIR => error.NotDir,
+                posix.EACCES => error.AccessDenied,
+                posix.EFAULT, posix.EINVAL => unreachable,
+                posix.EIO => error.FileSystem,
+                posix.ELOOP => error.SymLinkLoop,
+                posix.ENAMETOOLONG => error.NameTooLong,
+                posix.ENOENT => error.FileNotFound,
+                posix.ENOMEM => error.SystemResources,
+                posix.ENOTDIR => error.NotDir,
                 else => error.Unexpected,
             };
         }
std/os/linux.zig
@@ -4,7 +4,7 @@ const arch = switch (builtin.arch) {
     builtin.Arch.i386 => @import("linux_i386.zig"),
     else => @compileError("unsupported arch"),
 };
-const errno = @import("errno.zig");
+pub use @import("linux_errno.zig");
 
 pub const STDIN_FILENO = 0;
 pub const STDOUT_FILENO = 1;
std/os/errno.zig → std/os/linux_errno.zig
File renamed without changes
std/special/builtin.zig
@@ -30,16 +30,21 @@ export fn __stack_chk_fail() {
     @panic("stack smashing detected");
 }
 
+const math = @import("../math/index.zig");
+
 export fn fmodf(x: f32, y: f32) -> f32 { generic_fmod(f32, x, y) }
 export fn fmod(x: f64, y: f64) -> f64 { generic_fmod(f64, x, y) }
 
-const Log2Int = @import("../math/index.zig").Log2Int;
+// TODO add intrinsics for these (and probably the double version too)
+// and have the math stuff use the intrinsic. same as @mod and @rem
+export fn floorf(x: f32) -> f32 { math.floor(x) }
+export fn ceilf(x: f32) -> f32 { math.ceil(x) }
 
 fn generic_fmod(comptime T: type, x: T, y: T) -> T {
     @setDebugSafety(this, false);
 
     const uint = @IntType(false, T.bit_count);
-    const log2uint = Log2Int(uint);
+    const log2uint = math.Log2Int(uint);
     const digits = if (T == f32) 23 else 52;
     const exp_bits = if (T == f32) 9 else 12;
     const bits_minus_1 = T.bit_count - 1;
std/io.zig
@@ -8,7 +8,6 @@ const system = switch(builtin.os) {
 };
 const c = @import("c/index.zig");
 
-const errno = @import("os/errno.zig");
 const math = @import("math/index.zig");
 const debug = @import("debug.zig");
 const assert = debug.assert;
@@ -269,11 +268,11 @@ pub const InStream = struct {
                 const read_err = system.getErrno(amt_read);
                 if (read_err > 0) {
                     switch (read_err) {
-                        errno.EINTR  => continue,
-                        errno.EINVAL => unreachable,
-                        errno.EFAULT => unreachable,
-                        errno.EBADF  => return error.BadFd,
-                        errno.EIO    => return error.Io,
+                        system.EINTR  => continue,
+                        system.EINVAL => unreachable,
+                        system.EFAULT => unreachable,
+                        system.EBADF  => return error.BadFd,
+                        system.EIO    => return error.Io,
                         else         => return error.Unexpected,
                     }
                 }
@@ -335,11 +334,11 @@ pub const InStream = struct {
                 const err = system.getErrno(result);
                 if (err > 0) {
                     return switch (err) {
-                        errno.EBADF => error.BadFd,
-                        errno.EINVAL => error.Unseekable,
-                        errno.EOVERFLOW => error.Unseekable,
-                        errno.ESPIPE => error.Unseekable,
-                        errno.ENXIO => error.Unseekable,
+                        system.EBADF => error.BadFd,
+                        system.EINVAL => error.Unseekable,
+                        system.EOVERFLOW => error.Unseekable,
+                        system.ESPIPE => error.Unseekable,
+                        system.ENXIO => error.Unseekable,
                         else => error.Unexpected,
                     };
                 }
@@ -355,11 +354,11 @@ pub const InStream = struct {
                 const err = system.getErrno(result);
                 if (err > 0) {
                     return switch (err) {
-                        errno.EBADF => error.BadFd,
-                        errno.EINVAL => error.Unseekable,
-                        errno.EOVERFLOW => error.Unseekable,
-                        errno.ESPIPE => error.Unseekable,
-                        errno.ENXIO => error.Unseekable,
+                        system.EBADF => error.BadFd,
+                        system.EINVAL => error.Unseekable,
+                        system.EOVERFLOW => error.Unseekable,
+                        system.ESPIPE => error.Unseekable,
+                        system.ENXIO => error.Unseekable,
                         else => error.Unexpected,
                     };
                 }
@@ -375,11 +374,11 @@ pub const InStream = struct {
                 const err = system.getErrno(result);
                 if (err > 0) {
                     return switch (err) {
-                        errno.EBADF => error.BadFd,
-                        errno.EINVAL => error.Unseekable,
-                        errno.EOVERFLOW => error.Unseekable,
-                        errno.ESPIPE => error.Unseekable,
-                        errno.ENXIO => error.Unseekable,
+                        system.EBADF => error.BadFd,
+                        system.EINVAL => error.Unseekable,
+                        system.EOVERFLOW => error.Unseekable,
+                        system.ESPIPE => error.Unseekable,
+                        system.ENXIO => error.Unseekable,
                         else => error.Unexpected,
                     };
                 }
@@ -394,8 +393,8 @@ pub const InStream = struct {
         const err = system.getErrno(system.fstat(is.fd, &stat));
         if (err > 0) {
             return switch (err) {
-                errno.EBADF => error.BadFd,
-                errno.ENOMEM => error.NoMem,
+                system.EBADF => error.BadFd,
+                system.ENOMEM => error.NoMem,
                 else => error.Unexpected,
             }
         }
std/net.zig
@@ -1,5 +1,4 @@
 const linux = @import("os/linux.zig");
-const errno = @import("os/errno.zig");
 const assert = @import("debug.zig").assert;
 const endian = @import("endian.zig");
 
@@ -21,10 +20,10 @@ const Connection = struct {
         const send_err = linux.getErrno(send_ret);
         switch (send_err) {
             0 => return send_ret,
-            errno.EINVAL => unreachable,
-            errno.EFAULT => unreachable,
-            errno.ECONNRESET => return error.ConnectionReset,
-            errno.EINTR => return error.SigInterrupt,
+            linux.EINVAL => unreachable,
+            linux.EFAULT => unreachable,
+            linux.ECONNRESET => return error.ConnectionReset,
+            linux.EINTR => return error.SigInterrupt,
             // TODO there are more possible errors
             else => return error.Unexpected,
         }
@@ -35,13 +34,13 @@ const Connection = struct {
         const recv_err = linux.getErrno(recv_ret);
         switch (recv_err) {
             0 => return buf[0..recv_ret],
-            errno.EINVAL => unreachable,
-            errno.EFAULT => unreachable,
-            errno.ENOTSOCK => return error.NotSocket,
-            errno.EINTR => return error.SigInterrupt,
-            errno.ENOMEM => return error.NoMem,
-            errno.ECONNREFUSED => return error.ConnectionRefused,
-            errno.EBADF => return error.BadFd,
+            linux.EINVAL => unreachable,
+            linux.EFAULT => unreachable,
+            linux.ENOTSOCK => return error.NotSocket,
+            linux.EINTR => return error.SigInterrupt,
+            linux.ENOMEM => return error.NoMem,
+            linux.ECONNREFUSED => return error.ConnectionRefused,
+            linux.EBADF => return error.BadFd,
             // TODO more error values
             else => return error.Unexpected,
         }
@@ -50,9 +49,9 @@ const Connection = struct {
     pub fn close(c: Connection) -> %void {
         switch (linux.getErrno(linux.close(c.socket_fd))) {
             0 => return,
-            errno.EBADF => unreachable,
-            errno.EINTR => return error.SigInterrupt,
-            errno.EIO => return error.Io,
+            linux.EBADF => unreachable,
+            linux.EINTR => return error.SigInterrupt,
+            linux.EIO => return error.Io,
             else => return error.Unexpected,
         }
     }
@@ -119,7 +118,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
     const connect_err = linux.getErrno(connect_ret);
     if (connect_err > 0) {
         switch (connect_err) {
-            errno.ETIMEDOUT => return error.TimedOut,
+            linux.ETIMEDOUT => return error.TimedOut,
             else => {
                 // TODO figure out possible errors from connect()
                 return error.Unexpected;
test/cases/switch.zig
@@ -72,7 +72,7 @@ fn nonConstSwitch(foo: SwitchStatmentFoo) {
         SwitchStatmentFoo.C => 3,
         SwitchStatmentFoo.D => 4,
     };
-    if (val != 3) unreachable;
+    assert(val == 3);
 }
 const SwitchStatmentFoo = enum {
     A,
@@ -95,10 +95,10 @@ const SwitchProngWithVarEnum = enum {
 fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {
     switch(*a) {
         SwitchProngWithVarEnum.One => |x| {
-            if (x != 13) unreachable;
+            assert(x == 13);
         },
         SwitchProngWithVarEnum.Two => |x| {
-            if (x != 13.0) unreachable;
+            assert(x == 13.0);
         },
         SwitchProngWithVarEnum.Meh => |x| {
             const v: void = x;
CMakeLists.txt
@@ -297,9 +297,10 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")
 install(FILES "${CMAKE_SOURCE_DIR}/std/net.zig" DESTINATION "${ZIG_STD_DEST}")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/child_process.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/darwin.zig" DESTINATION "${ZIG_STD_DEST}/os")
-install(FILES "${CMAKE_SOURCE_DIR}/std/os/errno.zig" DESTINATION "${ZIG_STD_DEST}/os")
+install(FILES "${CMAKE_SOURCE_DIR}/std/os/darwin_errno.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/index.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux.zig" DESTINATION "${ZIG_STD_DEST}/os")
+install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_errno.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}/os")
 install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")