diff options
| author | alter <p@scene.cl> | 2016-09-12 01:01:06 -0300 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-09-14 02:46:02 -0400 |
| commit | cf9b21c09fc641b4697e06981ac5114a8d3d09ab (patch) | |
| tree | a69ab92c864c8807209eb09214b868bf8cce39ec /std | |
| parent | 06f2f4d64b63cf78a3ff77cc64dbc822123f454d (diff) | |
| download | zig-cf9b21c09fc641b4697e06981ac5114a8d3d09ab.tar.gz zig-cf9b21c09fc641b4697e06981ac5114a8d3d09ab.zip | |
MacOSX compatibility
- Implemented some syscall for MacOSX
- tested on : El Capitan 10.11 x86_64
- make self hosted test run on macosx
- modified run_test so it does not fail when parseh throws
warnings (most of them are related to buildin types from
gcc that arent defined in header files and unions)
- making -mmacosx-version-min and -mios-version-min works like
gcc (command line paramers have precedence over enviroment variables)
Diffstat (limited to 'std')
| -rw-r--r-- | std/darwin.zig | 110 | ||||
| -rw-r--r-- | std/darwin_x86_64.zig | 86 | ||||
| -rw-r--r-- | std/debug.zig | 2 | ||||
| -rw-r--r-- | std/index.zig | 5 | ||||
| -rw-r--r-- | std/io.zig | 59 | ||||
| -rw-r--r-- | std/os.zig | 41 |
6 files changed, 256 insertions, 47 deletions
diff --git a/std/darwin.zig b/std/darwin.zig new file mode 100644 index 0000000000..99eca52065 --- /dev/null +++ b/std/darwin.zig @@ -0,0 +1,110 @@ + +const arch = switch (@compileVar("arch")) { + x86_64 => @import("darwin_x86_64.zig"), + else => @compile_err("unsupported arch"), +}; + +const errno = @import("errno.zig"); + +pub const O_LARGEFILE = 0x0000; +pub const O_RDONLY = 0x0000; + +pub const SEEK_SET = 0x0; +pub const SEEK_CUR = 0x1; +pub const SEEK_END = 0x2; + +pub const SIGHUP = 1; +pub const SIGINT = 2; +pub const SIGQUIT = 3; +pub const SIGILL = 4; +pub const SIGTRAP = 5; +pub const SIGABRT = 6; +pub const SIGIOT = SIGABRT; +pub const SIGBUS = 7; +pub const SIGFPE = 8; +pub const SIGKILL = 9; +pub const SIGUSR1 = 10; +pub const SIGSEGV = 11; +pub const SIGUSR2 = 12; +pub const SIGPIPE = 13; +pub const SIGALRM = 14; +pub const SIGTERM = 15; +pub const SIGSTKFLT = 16; +pub const SIGCHLD = 17; +pub const SIGCONT = 18; +pub const SIGSTOP = 19; +pub const SIGTSTP = 20; +pub const SIGTTIN = 21; +pub const SIGTTOU = 22; +pub const SIGURG = 23; +pub const SIGXCPU = 24; +pub const SIGXFSZ = 25; +pub const SIGVTALRM = 26; +pub const SIGPROF = 27; +pub const SIGWINCH = 28; +pub const SIGIO = 29; +pub const SIGPOLL = 29; +pub const SIGPWR = 30; +pub const SIGSYS = 31; +pub const SIGUNUSED = SIGSYS; + +/// Get the errno from a syscall return value, or 0 for no error. +pub fn getErrno(r: usize) -> usize { + const signed_r = *(&isize)(&r); + if (signed_r > -4096 && signed_r < 0) usize(-signed_r) else 0 +} + +pub fn write(fd: i32, buf: &const u8, count: usize) -> usize { + arch.syscall3(arch.SYS_write, usize(fd), usize(buf), count) +} + +pub fn close(fd: i32) -> usize { + arch.syscall1(arch.SYS_close, usize(fd)) +} + +pub fn open_c(path: &const u8, flags: usize, perm: usize) -> usize { + arch.syscall3(arch.SYS_open, usize(path), flags, perm) +} + +pub fn open(path: []const u8, flags: usize, perm: usize) -> usize { + var buf: [path.len + 1]u8 = undefined; + @memcpy(&buf[0], &path[0], path.len); + buf[path.len] = 0; + return open_c(buf.ptr, flags, perm); +} + +pub fn read(fd: i32, buf: &u8, count: usize) -> usize { + arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count) +} + +pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize { + arch.syscall3(arch.SYS_lseek, usize(fd), offset, ref_pos) +} + +pub const stat = arch.stat; +pub const timespec = arch.timespec; + +pub fn fstat(fd: i32, stat_buf: &stat) -> usize { + arch.syscall2(arch.SYS_fstat, usize(fd), usize(stat_buf)) +} + +pub error Unexpected; + +pub fn getrandom(buf: &u8, count: usize) -> usize { + const rr = open_c(c"/dev/urandom", O_LARGEFILE | O_RDONLY, 0); + + if(getErrno(rr) > 0) return rr; + + var fd: i32 = i32(rr); + const readRes = read(fd, buf, count); + readRes +} + +pub fn raise(sig: i32) -> i32 { + //var set: sigset_t = undefined; + //blockAppSignals(&set); + const pid = i32(arch.syscall0(arch.SYS_getpid)); + const ret = i32(arch.syscall2(arch.SYS_kill, usize(pid), usize(sig))); + //restoreSignals(&set); + return ret; +} diff --git a/std/darwin_x86_64.zig b/std/darwin_x86_64.zig new file mode 100644 index 0000000000..2dc98513e9 --- /dev/null +++ b/std/darwin_x86_64.zig @@ -0,0 +1,86 @@ + +pub const SYSCALL_CLASS_SHIFT = 24; +pub const SYSCALL_CLASS_MASK = 0xFF << SYSCALL_CLASS_SHIFT; +// pub const SYSCALL_NUMBER_MASK = ~SYSCALL_CLASS_MASK; // ~ modifier not supported yet + +pub const SYSCALL_CLASS_NONE = 0; // Invalid +pub const SYSCALL_CLASS_MACH = 1; // Mach +pub const SYSCALL_CLASS_UNIX = 2; // Unix/BSD +pub const SYSCALL_CLASS_MDEP = 3; // Machine-dependent +pub const SYSCALL_CLASS_DIAG = 4; // Diagnostics + +// TODO: use the above constants to create the below values + +pub const SYS_read = 0x2000003; +pub const SYS_write = 0x2000004; +pub const SYS_open = 0x2000005; +pub const SYS_close = 0x2000006; +pub const SYS_kill = 0x2000025; +pub const SYS_getpid = 0x2000030; +pub const SYS_fstat = 0x20000BD; +pub const SYS_lseek = 0x20000C7; + +pub inline fn syscall0(number: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number) + : "rcx", "r11") +} + +pub inline fn syscall1(number: usize, arg1: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1) + : "rcx", "r11") +} + +pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2) + : "rcx", "r11") +} + +pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3) + : "rcx", "r11") +} + + + + +export struct stat { + dev: u32, + mode: u16, + nlink: u16, + ino: u64, + uid: u32, + gid: u32, + rdev: u64, + + atim: timespec, + mtim: timespec, + ctim: timespec, + + size: u64, + blocks: u64, + blksize: u32, + flags: u32, + gen: u32, + lspare: i32, + qspare: [2]u64, + +} + +export struct timespec { + tv_sec: isize, + tv_nsec: isize, +} diff --git a/std/debug.zig b/std/debug.zig index dd864f4f0a..8b3d4c9b05 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -49,7 +49,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { out_stream.write("(stack trace unavailable for COFF object format)\n"); }, macho => { - out_stream.write("(stack trace unavailable for Mach-O object format)\n"); + %return out_stream.write("(stack trace unavailable for Mach-O object format)\n"); }, unknown => { out_stream.write("(stack trace unavailable for unknown object format)\n"); diff --git a/std/index.zig b/std/index.zig index e7cda17b28..0b7333b138 100644 --- a/std/index.zig +++ b/std/index.zig @@ -13,5 +13,8 @@ pub const linux = switch(@compileVar("os")) { linux => @import("linux.zig"), else => null_import, }; - +pub const darwin = switch(@compileVar("os")) { + darwin => @import("darwin.zig"), + else => null_import, +}; const null_import = @import("empty.zig"); diff --git a/std/io.zig b/std/io.zig index 762d65cc64..ba63eac418 100644 --- a/std/io.zig +++ b/std/io.zig @@ -1,4 +1,9 @@ -const linux = @import("linux.zig"); +const system = switch(@compileVar("os")) { + linux => @import("linux.zig"), + darwin => @import("darwin.zig"), + else => @compileError("Unsupported OS"), +}; + const errno = @import("errno.zig"); const math = @import("math.zig"); const endian = @import("endian.zig"); @@ -110,12 +115,11 @@ pub struct OutStream { pub fn flush(os: &OutStream) -> %void { while (true) { - const write_ret = linux.write(os.fd, &os.buffer[0], os.index); - const write_err = linux.getErrno(write_ret); + const write_ret = system.write(os.fd, &os.buffer[0], os.index); + const write_err = system.getErrno(write_ret); if (write_err > 0) { return switch (write_err) { errno.EINTR => continue, - errno.EINVAL => @unreachable(), errno.EDQUOT => error.DiskQuota, errno.EFBIG => error.FileTooBig, @@ -133,8 +137,8 @@ pub struct OutStream { pub fn close(os: &OutStream) -> %void { while (true) { - const close_ret = linux.close(os.fd); - const close_err = linux.getErrno(close_ret); + const close_ret = system.close(os.fd); + const close_err = system.getErrno(close_ret); if (close_err > 0) { return switch (close_err) { errno.EINTR => continue, @@ -157,10 +161,10 @@ pub struct InStream { /// Call close to clean up. pub fn open(is: &InStream, path: []const u8) -> %void { switch (@compileVar("os")) { - linux => { + linux, darwin => { while (true) { - const result = linux.open(path, linux.O_LARGEFILE|linux.O_RDONLY, 0); - const err = linux.getErrno(result); + const result = system.open(path, system.O_LARGEFILE|system.O_RDONLY, 0); + const err = system.getErrno(result); if (err > 0) { return switch (err) { errno.EINTR => continue, @@ -189,16 +193,17 @@ pub struct InStream { }, else => @compileError("unsupported OS"), } + } /// Upon success, the stream is in an uninitialized state. To continue using it, /// you must use the open() function. pub fn close(is: &InStream) -> %void { switch (@compileVar("os")) { - linux => { + linux, darwin => { while (true) { - const close_ret = linux.close(is.fd); - const close_err = linux.getErrno(close_ret); + const close_ret = system.close(is.fd); + const close_err = system.getErrno(close_ret); if (close_err > 0) { return switch (close_err) { errno.EINTR => continue, @@ -219,11 +224,11 @@ pub struct InStream { /// the stream reached End Of File. pub fn read(is: &InStream, buf: []u8) -> %usize { switch (@compileVar("os")) { - linux => { + linux, darwin => { var index: usize = 0; while (index < buf.len) { - const amt_read = linux.read(is.fd, &buf[index], buf.len - index); - const read_err = linux.getErrno(amt_read); + const amt_read = system.read(is.fd, &buf[index], buf.len - index); + const read_err = system.getErrno(amt_read); if (read_err > 0) { switch (read_err) { errno.EINTR => continue, @@ -287,9 +292,9 @@ pub struct InStream { pub fn seekForward(is: &InStream, amount: usize) -> %void { switch (@compileVar("os")) { - linux => { - const result = linux.lseek(is.fd, amount, linux.SEEK_CUR); - const err = linux.getErrno(result); + linux, darwin => { + const result = system.lseek(is.fd, amount, system.SEEK_CUR); + const err = system.getErrno(result); if (err > 0) { return switch (err) { errno.EBADF => error.BadFd, @@ -307,9 +312,9 @@ pub struct InStream { pub fn seekTo(is: &InStream, pos: usize) -> %void { switch (@compileVar("os")) { - linux => { - const result = linux.lseek(is.fd, pos, linux.SEEK_SET); - const err = linux.getErrno(result); + linux, darwin => { + const result = system.lseek(is.fd, pos, system.SEEK_SET); + const err = system.getErrno(result); if (err > 0) { return switch (err) { errno.EBADF => error.BadFd, @@ -327,9 +332,9 @@ pub struct InStream { pub fn getPos(is: &InStream) -> %usize { switch (@compileVar("os")) { - linux => { - const result = linux.lseek(is.fd, 0, linux.SEEK_CUR); - const err = linux.getErrno(result); + linux, darwin => { + const result = system.lseek(is.fd, 0, system.SEEK_CUR); + const err = system.getErrno(result); if (err > 0) { return switch (err) { errno.EBADF => error.BadFd, @@ -347,8 +352,8 @@ pub struct InStream { } pub fn getEndPos(is: &InStream) -> %usize { - var stat: linux.stat = undefined; - const err = linux.getErrno(linux.fstat(is.fd, &stat)); + var stat: system.stat = undefined; + const err = system.getErrno(system.fstat(is.fd, &stat)); if (err > 0) { return switch (err) { errno.EBADF => error.BadFd, @@ -433,7 +438,7 @@ fn parseU64DigitTooBig() { pub fn openSelfExe(stream: &InStream) -> %void { switch (@compileVar("os")) { - linux => { + linux,darwin => { %return stream.open("/proc/self/exe"); }, else => @compileError("unsupported os"), diff --git a/std/os.zig b/std/os.zig index bfdc97220a..806cc43f33 100644 --- a/std/os.zig +++ b/std/os.zig @@ -1,33 +1,38 @@ -const linux = @import("linux.zig"); +const system = switch(@compileVar("os")) { + linux => @import("linux.zig"), + darwin => @import("darwin.zig"), + else => @compileError("Unsupported OS"), +}; const errno = @import("errno.zig"); -pub error SigInterrupt; pub error Unexpected; pub fn getRandomBytes(buf: []u8) -> %void { - switch (@compileVar("os")) { - linux => { - const ret = linux.getrandom(buf.ptr, buf.len, 0); - const err = linux.getErrno(ret); - if (err > 0) { - return switch (err) { - errno.EINVAL => @unreachable(), - errno.EFAULT => @unreachable(), - errno.EINTR => error.SigInterrupt, - else => error.Unexpected, - } + while (true) { + const ret = switch (@compileVar("os")) { + linux => system.getrandom(buf.ptr, buf.len, 0), + darwin => system.getrandom(buf.ptr, buf.len), + else => @compileError("unsupported os"), + }; + const err = system.getErrno(ret); + if (err > 0) { + return switch (err) { + errno.EINVAL => @unreachable(), + errno.EFAULT => @unreachable(), + errno.EINTR => continue, + else => error.Unexpected, } - }, - else => @compileError("unsupported os"), + } + return; } } #attribute("cold") pub fn abort() -> unreachable { switch (@compileVar("os")) { - linux => { - linux.raise(linux.SIGABRT); - linux.raise(linux.SIGKILL); + linux, darwin => { + system.raise(system.SIGABRT); + system.raise(system.SIGKILL); while (true) {} }, else => @compileError("unsupported os"), |
