aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authoralter <p@scene.cl>2016-09-12 01:01:06 -0300
committerAndrew Kelley <superjoe30@gmail.com>2016-09-14 02:46:02 -0400
commitcf9b21c09fc641b4697e06981ac5114a8d3d09ab (patch)
treea69ab92c864c8807209eb09214b868bf8cce39ec /std
parent06f2f4d64b63cf78a3ff77cc64dbc822123f454d (diff)
downloadzig-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.zig110
-rw-r--r--std/darwin_x86_64.zig86
-rw-r--r--std/debug.zig2
-rw-r--r--std/index.zig5
-rw-r--r--std/io.zig59
-rw-r--r--std/os.zig41
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"),