| author | |
| committer | |
| log | c65fe384ddb5f5f6a5f22cb636539fd91701de4d |
| tree | 8ae6966a01439c347bd69f87e40a9fc5e4f62476 |
| parent | 06f2f4d64b63cf78a3ff77cc64dbc822123f454d |
| parent | f1761632dae8951d21e62cb13e14bd4b4b0ed8a8 |
Closes #18911 files changed, 334 insertions(+), 92 deletions(-)
CMakeLists.txt+2| ... | ... | @@ -213,6 +213,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/io.zig" DESTINATION "${ZIG_STD_DEST}") |
| 213 | 213 | install(FILES "${CMAKE_SOURCE_DIR}/std/linux.zig" DESTINATION "${ZIG_STD_DEST}") |
| 214 | 214 | install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}") |
| 215 | 215 | install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}") |
| 216 | install(FILES "${CMAKE_SOURCE_DIR}/std/darwin.zig" DESTINATION "${ZIG_STD_DEST}") | |
| 217 | install(FILES "${CMAKE_SOURCE_DIR}/std/darwin_x86_64.zig" DESTINATION "${ZIG_STD_DEST}") | |
| 216 | 218 | install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}") |
| 217 | 219 | install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}") |
| 218 | 220 | install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}") |
src/codegen.cpp-2| ... | ... | @@ -42,8 +42,6 @@ static void init_darwin_native(CodeGen *g) { |
| 42 | 42 | g->mmacosx_version_min = buf_create_from_str(osx_target); |
| 43 | 43 | } else if (ios_target) { |
| 44 | 44 | g->mios_version_min = buf_create_from_str(ios_target); |
| 45 | } else { | |
| 46 | zig_panic("unable to determine -mmacosx-version-min or -mios-version-min"); | |
| 47 | 45 | } |
| 48 | 46 | } |
| 49 | 47 |
src/link.cpp+6| ... | ... | @@ -643,6 +643,12 @@ static void construct_linker_job_darwin(LinkJob *lj) { |
| 643 | 643 | |
| 644 | 644 | lj->args.append((const char *)buf_ptr(&lj->out_file_o)); |
| 645 | 645 | |
| 646 | if (g->is_test_build) { | |
| 647 | const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; | |
| 648 | Buf *test_runner_o_path = build_o(g, test_runner_name); | |
| 649 | lj->args.append(buf_ptr(test_runner_o_path)); | |
| 650 | } | |
| 651 | ||
| 646 | 652 | for (int i = 0; i < g->link_libs.length; i += 1) { |
| 647 | 653 | Buf *link_lib = g->link_libs.at(i); |
| 648 | 654 | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib)); |
src/main.cpp+2| ... | ... | @@ -388,9 +388,11 @@ int main(int argc, char **argv) { |
| 388 | 388 | fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n"); |
| 389 | 389 | return EXIT_FAILURE; |
| 390 | 390 | } |
| 391 | ||
| 391 | 392 | if (mmacosx_version_min) { |
| 392 | 393 | codegen_set_mmacosx_version_min(g, buf_create_from_str(mmacosx_version_min)); |
| 393 | 394 | } |
| 395 | ||
| 394 | 396 | if (mios_version_min) { |
| 395 | 397 | codegen_set_mios_version_min(g, buf_create_from_str(mios_version_min)); |
| 396 | 398 | } |
std/darwin.zig created+113| ... | ... | @@ -0,0 +1,113 @@ |
| 1 | ||
| 2 | const arch = switch (@compileVar("arch")) { | |
| 3 | x86_64 => @import("darwin_x86_64.zig"), | |
| 4 | else => @compile_err("unsupported arch"), | |
| 5 | }; | |
| 6 | ||
| 7 | const errno = @import("errno.zig"); | |
| 8 | ||
| 9 | pub const O_LARGEFILE = 0x0000; | |
| 10 | pub const O_RDONLY = 0x0000; | |
| 11 | ||
| 12 | pub const SEEK_SET = 0x0; | |
| 13 | pub const SEEK_CUR = 0x1; | |
| 14 | pub const SEEK_END = 0x2; | |
| 15 | ||
| 16 | pub const SIGHUP = 1; | |
| 17 | pub const SIGINT = 2; | |
| 18 | pub const SIGQUIT = 3; | |
| 19 | pub const SIGILL = 4; | |
| 20 | pub const SIGTRAP = 5; | |
| 21 | pub const SIGABRT = 6; | |
| 22 | pub const SIGIOT = SIGABRT; | |
| 23 | pub const SIGBUS = 7; | |
| 24 | pub const SIGFPE = 8; | |
| 25 | pub const SIGKILL = 9; | |
| 26 | pub const SIGUSR1 = 10; | |
| 27 | pub const SIGSEGV = 11; | |
| 28 | pub const SIGUSR2 = 12; | |
| 29 | pub const SIGPIPE = 13; | |
| 30 | pub const SIGALRM = 14; | |
| 31 | pub const SIGTERM = 15; | |
| 32 | pub const SIGSTKFLT = 16; | |
| 33 | pub const SIGCHLD = 17; | |
| 34 | pub const SIGCONT = 18; | |
| 35 | pub const SIGSTOP = 19; | |
| 36 | pub const SIGTSTP = 20; | |
| 37 | pub const SIGTTIN = 21; | |
| 38 | pub const SIGTTOU = 22; | |
| 39 | pub const SIGURG = 23; | |
| 40 | pub const SIGXCPU = 24; | |
| 41 | pub const SIGXFSZ = 25; | |
| 42 | pub const SIGVTALRM = 26; | |
| 43 | pub const SIGPROF = 27; | |
| 44 | pub const SIGWINCH = 28; | |
| 45 | pub const SIGIO = 29; | |
| 46 | pub const SIGPOLL = 29; | |
| 47 | pub const SIGPWR = 30; | |
| 48 | pub const SIGSYS = 31; | |
| 49 | pub const SIGUNUSED = SIGSYS; | |
| 50 | ||
| 51 | /// Get the errno from a syscall return value, or 0 for no error. | |
| 52 | pub fn getErrno(r: usize) -> usize { | |
| 53 | const signed_r = *(&isize)(&r); | |
| 54 | if (signed_r > -4096 && signed_r < 0) usize(-signed_r) else 0 | |
| 55 | } | |
| 56 | ||
| 57 | pub fn write(fd: i32, buf: &const u8, count: usize) -> usize { | |
| 58 | arch.syscall3(arch.SYS_write, usize(fd), usize(buf), count) | |
| 59 | } | |
| 60 | ||
| 61 | pub fn close(fd: i32) -> usize { | |
| 62 | arch.syscall1(arch.SYS_close, usize(fd)) | |
| 63 | } | |
| 64 | ||
| 65 | pub fn open_c(path: &const u8, flags: usize, perm: usize) -> usize { | |
| 66 | arch.syscall3(arch.SYS_open, usize(path), flags, perm) | |
| 67 | } | |
| 68 | ||
| 69 | pub fn open(path: []const u8, flags: usize, perm: usize) -> usize { | |
| 70 | var buf: [path.len + 1]u8 = undefined; | |
| 71 | @memcpy(&buf[0], &path[0], path.len); | |
| 72 | buf[path.len] = 0; | |
| 73 | return open_c(buf.ptr, flags, perm); | |
| 74 | } | |
| 75 | ||
| 76 | pub fn read(fd: i32, buf: &u8, count: usize) -> usize { | |
| 77 | arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count) | |
| 78 | } | |
| 79 | ||
| 80 | pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize { | |
| 81 | arch.syscall3(arch.SYS_lseek, usize(fd), offset, ref_pos) | |
| 82 | } | |
| 83 | ||
| 84 | pub const stat = arch.stat; | |
| 85 | pub const timespec = arch.timespec; | |
| 86 | ||
| 87 | pub fn fstat(fd: i32, stat_buf: &stat) -> usize { | |
| 88 | arch.syscall2(arch.SYS_fstat, usize(fd), usize(stat_buf)) | |
| 89 | } | |
| 90 | ||
| 91 | pub error Unexpected; | |
| 92 | ||
| 93 | pub fn getrandom(buf: &u8, count: usize) -> usize { | |
| 94 | const rr = open_c(c"/dev/urandom", O_LARGEFILE | O_RDONLY, 0); | |
| 95 | ||
| 96 | if(getErrno(rr) > 0) return rr; | |
| 97 | ||
| 98 | var fd: i32 = i32(rr); | |
| 99 | const readRes = read(fd, buf, count); | |
| 100 | readRes | |
| 101 | } | |
| 102 | ||
| 103 | pub fn raise(sig: i32) -> i32 { | |
| 104 | // TODO investigate whether we need to block signals before calling kill | |
| 105 | // like we do in the linux version of raise | |
| 106 | ||
| 107 | //var set: sigset_t = undefined; | |
| 108 | //blockAppSignals(&set); | |
| 109 | const pid = i32(arch.syscall0(arch.SYS_getpid)); | |
| 110 | const ret = i32(arch.syscall2(arch.SYS_kill, usize(pid), usize(sig))); | |
| 111 | //restoreSignals(&set); | |
| 112 | return ret; | |
| 113 | } |
std/darwin_x86_64.zig created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | ||
| 2 | pub const SYSCALL_CLASS_SHIFT = 24; | |
| 3 | pub const SYSCALL_CLASS_MASK = 0xFF << SYSCALL_CLASS_SHIFT; | |
| 4 | // pub const SYSCALL_NUMBER_MASK = ~SYSCALL_CLASS_MASK; // ~ modifier not supported yet | |
| 5 | ||
| 6 | pub const SYSCALL_CLASS_NONE = 0; // Invalid | |
| 7 | pub const SYSCALL_CLASS_MACH = 1; // Mach | |
| 8 | pub const SYSCALL_CLASS_UNIX = 2; // Unix/BSD | |
| 9 | pub const SYSCALL_CLASS_MDEP = 3; // Machine-dependent | |
| 10 | pub const SYSCALL_CLASS_DIAG = 4; // Diagnostics | |
| 11 | ||
| 12 | // TODO: use the above constants to create the below values | |
| 13 | ||
| 14 | pub const SYS_read = 0x2000003; | |
| 15 | pub const SYS_write = 0x2000004; | |
| 16 | pub const SYS_open = 0x2000005; | |
| 17 | pub const SYS_close = 0x2000006; | |
| 18 | pub const SYS_kill = 0x2000025; | |
| 19 | pub const SYS_getpid = 0x2000030; | |
| 20 | pub const SYS_fstat = 0x20000BD; | |
| 21 | pub const SYS_lseek = 0x20000C7; | |
| 22 | ||
| 23 | pub inline fn syscall0(number: usize) -> usize { | |
| 24 | asm volatile ("syscall" | |
| 25 | : [ret] "={rax}" (-> usize) | |
| 26 | : [number] "{rax}" (number) | |
| 27 | : "rcx", "r11") | |
| 28 | } | |
| 29 | ||
| 30 | pub inline fn syscall1(number: usize, arg1: usize) -> usize { | |
| 31 | asm volatile ("syscall" | |
| 32 | : [ret] "={rax}" (-> usize) | |
| 33 | : [number] "{rax}" (number), | |
| 34 | [arg1] "{rdi}" (arg1) | |
| 35 | : "rcx", "r11") | |
| 36 | } | |
| 37 | ||
| 38 | pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { | |
| 39 | asm volatile ("syscall" | |
| 40 | : [ret] "={rax}" (-> usize) | |
| 41 | : [number] "{rax}" (number), | |
| 42 | [arg1] "{rdi}" (arg1), | |
| 43 | [arg2] "{rsi}" (arg2) | |
| 44 | : "rcx", "r11") | |
| 45 | } | |
| 46 | ||
| 47 | pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | |
| 48 | asm volatile ("syscall" | |
| 49 | : [ret] "={rax}" (-> usize) | |
| 50 | : [number] "{rax}" (number), | |
| 51 | [arg1] "{rdi}" (arg1), | |
| 52 | [arg2] "{rsi}" (arg2), | |
| 53 | [arg3] "{rdx}" (arg3) | |
| 54 | : "rcx", "r11") | |
| 55 | } | |
| 56 | ||
| 57 | ||
| 58 | ||
| 59 | ||
| 60 | export struct stat { | |
| 61 | dev: u32, | |
| 62 | mode: u16, | |
| 63 | nlink: u16, | |
| 64 | ino: u64, | |
| 65 | uid: u32, | |
| 66 | gid: u32, | |
| 67 | rdev: u64, | |
| 68 | ||
| 69 | atim: timespec, | |
| 70 | mtim: timespec, | |
| 71 | ctim: timespec, | |
| 72 | ||
| 73 | size: u64, | |
| 74 | blocks: u64, | |
| 75 | blksize: u32, | |
| 76 | flags: u32, | |
| 77 | gen: u32, | |
| 78 | lspare: i32, | |
| 79 | qspare: [2]u64, | |
| 80 | ||
| 81 | } | |
| 82 | ||
| 83 | export struct timespec { | |
| 84 | tv_sec: isize, | |
| 85 | tv_nsec: isize, | |
| 86 | } |
std/debug.zig+1-1| ... | ... | @@ -49,7 +49,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { |
| 49 | 49 | out_stream.write("(stack trace unavailable for COFF object format)\n"); |
| 50 | 50 | }, |
| 51 | 51 | macho => { |
| 52 | out_stream.write("(stack trace unavailable for Mach-O object format)\n"); | |
| 52 | %return out_stream.write("(stack trace unavailable for Mach-O object format)\n"); | |
| 53 | 53 | }, |
| 54 | 54 | unknown => { |
| 55 | 55 | out_stream.write("(stack trace unavailable for unknown object format)\n"); |
std/index.zig+4-1| ... | ... | @@ -13,5 +13,8 @@ pub const linux = switch(@compileVar("os")) { |
| 13 | 13 | linux => @import("linux.zig"), |
| 14 | 14 | else => null_import, |
| 15 | 15 | }; |
| 16 | ||
| 16 | pub const darwin = switch(@compileVar("os")) { | |
| 17 | darwin => @import("darwin.zig"), | |
| 18 | else => null_import, | |
| 19 | }; | |
| 17 | 20 | const null_import = @import("empty.zig"); |
std/io.zig+57-47| ... | ... | @@ -1,9 +1,15 @@ |
| 1 | const linux = @import("linux.zig"); | |
| 1 | const system = switch(@compileVar("os")) { | |
| 2 | linux => @import("linux.zig"), | |
| 3 | darwin => @import("darwin.zig"), | |
| 4 | else => @compileError("Unsupported OS"), | |
| 5 | }; | |
| 6 | ||
| 2 | 7 | const errno = @import("errno.zig"); |
| 3 | 8 | const math = @import("math.zig"); |
| 4 | 9 | const endian = @import("endian.zig"); |
| 5 | 10 | const debug = @import("debug.zig"); |
| 6 | 11 | const assert = debug.assert; |
| 12 | const os = @import("os.zig"); | |
| 7 | 13 | |
| 8 | 14 | pub const stdin_fileno = 0; |
| 9 | 15 | pub const stdout_fileno = 1; |
| ... | ... | @@ -67,23 +73,23 @@ pub struct OutStream { |
| 67 | 73 | buffer: [buffer_size]u8, |
| 68 | 74 | index: usize, |
| 69 | 75 | |
| 70 | pub fn writeByte(os: &OutStream, b: u8) -> %void { | |
| 71 | if (os.buffer.len == os.index) %return os.flush(); | |
| 72 | os.buffer[os.index] = b; | |
| 73 | os.index += 1; | |
| 76 | pub fn writeByte(self: &OutStream, b: u8) -> %void { | |
| 77 | if (self.buffer.len == self.index) %return self.flush(); | |
| 78 | self.buffer[self.index] = b; | |
| 79 | self.index += 1; | |
| 74 | 80 | } |
| 75 | 81 | |
| 76 | pub fn write(os: &OutStream, bytes: []const u8) -> %usize { | |
| 82 | pub fn write(self: &OutStream, bytes: []const u8) -> %usize { | |
| 77 | 83 | var src_bytes_left = bytes.len; |
| 78 | 84 | var src_index: @typeOf(bytes.len) = 0; |
| 79 | const dest_space_left = os.buffer.len - os.index; | |
| 85 | const dest_space_left = self.buffer.len - self.index; | |
| 80 | 86 | |
| 81 | 87 | while (src_bytes_left > 0) { |
| 82 | 88 | const copy_amt = math.min(dest_space_left, src_bytes_left); |
| 83 | @memcpy(&os.buffer[os.index], &bytes[src_index], copy_amt); | |
| 84 | os.index += copy_amt; | |
| 85 | if (os.index == os.buffer.len) { | |
| 86 | %return os.flush(); | |
| 89 | @memcpy(&self.buffer[self.index], &bytes[src_index], copy_amt); | |
| 90 | self.index += copy_amt; | |
| 91 | if (self.index == self.buffer.len) { | |
| 92 | %return self.flush(); | |
| 87 | 93 | } |
| 88 | 94 | src_bytes_left -= copy_amt; |
| 89 | 95 | } |
| ... | ... | @@ -92,30 +98,29 @@ pub struct OutStream { |
| 92 | 98 | |
| 93 | 99 | /// Prints a byte buffer, flushes the buffer, then returns the number of |
| 94 | 100 | /// bytes printed. The "f" is for "flush". |
| 95 | pub fn printf(os: &OutStream, str: []const u8) -> %usize { | |
| 96 | const byte_count = %return os.write(str); | |
| 97 | %return os.flush(); | |
| 101 | pub fn printf(self: &OutStream, str: []const u8) -> %usize { | |
| 102 | const byte_count = %return self.write(str); | |
| 103 | %return self.flush(); | |
| 98 | 104 | return byte_count; |
| 99 | 105 | } |
| 100 | 106 | |
| 101 | pub fn printInt(os: &OutStream, inline T: type, x: T) -> %usize { | |
| 107 | pub fn printInt(self: &OutStream, inline T: type, x: T) -> %usize { | |
| 102 | 108 | // TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T))) |
| 103 | if (os.index + max_u64_base10_digits >= os.buffer.len) { | |
| 104 | %return os.flush(); | |
| 109 | if (self.index + max_u64_base10_digits >= self.buffer.len) { | |
| 110 | %return self.flush(); | |
| 105 | 111 | } |
| 106 | const amt_printed = bufPrintInt(T, os.buffer[os.index...], x); | |
| 107 | os.index += amt_printed; | |
| 112 | const amt_printed = bufPrintInt(T, self.buffer[self.index...], x); | |
| 113 | self.index += amt_printed; | |
| 108 | 114 | return amt_printed; |
| 109 | 115 | } |
| 110 | 116 | |
| 111 | pub fn flush(os: &OutStream) -> %void { | |
| 117 | pub fn flush(self: &OutStream) -> %void { | |
| 112 | 118 | while (true) { |
| 113 | const write_ret = linux.write(os.fd, &os.buffer[0], os.index); | |
| 114 | const write_err = linux.getErrno(write_ret); | |
| 119 | const write_ret = system.write(self.fd, &self.buffer[0], self.index); | |
| 120 | const write_err = system.getErrno(write_ret); | |
| 115 | 121 | if (write_err > 0) { |
| 116 | 122 | return switch (write_err) { |
| 117 | 123 | errno.EINTR => continue, |
| 118 | ||
| 119 | 124 | errno.EINVAL => @unreachable(), |
| 120 | 125 | errno.EDQUOT => error.DiskQuota, |
| 121 | 126 | errno.EFBIG => error.FileTooBig, |
| ... | ... | @@ -126,15 +131,15 @@ pub struct OutStream { |
| 126 | 131 | else => error.Unexpected, |
| 127 | 132 | } |
| 128 | 133 | } |
| 129 | os.index = 0; | |
| 134 | self.index = 0; | |
| 130 | 135 | return; |
| 131 | 136 | } |
| 132 | 137 | } |
| 133 | 138 | |
| 134 | pub fn close(os: &OutStream) -> %void { | |
| 139 | pub fn close(self: &OutStream) -> %void { | |
| 135 | 140 | while (true) { |
| 136 | const close_ret = linux.close(os.fd); | |
| 137 | const close_err = linux.getErrno(close_ret); | |
| 141 | const close_ret = system.close(self.fd); | |
| 142 | const close_err = system.getErrno(close_ret); | |
| 138 | 143 | if (close_err > 0) { |
| 139 | 144 | return switch (close_err) { |
| 140 | 145 | errno.EINTR => continue, |
| ... | ... | @@ -157,10 +162,10 @@ pub struct InStream { |
| 157 | 162 | /// Call close to clean up. |
| 158 | 163 | pub fn open(is: &InStream, path: []const u8) -> %void { |
| 159 | 164 | switch (@compileVar("os")) { |
| 160 | linux => { | |
| 165 | linux, darwin => { | |
| 161 | 166 | while (true) { |
| 162 | const result = linux.open(path, linux.O_LARGEFILE|linux.O_RDONLY, 0); | |
| 163 | const err = linux.getErrno(result); | |
| 167 | const result = system.open(path, system.O_LARGEFILE|system.O_RDONLY, 0); | |
| 168 | const err = system.getErrno(result); | |
| 164 | 169 | if (err > 0) { |
| 165 | 170 | return switch (err) { |
| 166 | 171 | errno.EINTR => continue, |
| ... | ... | @@ -189,16 +194,17 @@ pub struct InStream { |
| 189 | 194 | }, |
| 190 | 195 | else => @compileError("unsupported OS"), |
| 191 | 196 | } |
| 197 | ||
| 192 | 198 | } |
| 193 | 199 | |
| 194 | 200 | /// Upon success, the stream is in an uninitialized state. To continue using it, |
| 195 | 201 | /// you must use the open() function. |
| 196 | 202 | pub fn close(is: &InStream) -> %void { |
| 197 | 203 | switch (@compileVar("os")) { |
| 198 | linux => { | |
| 204 | linux, darwin => { | |
| 199 | 205 | while (true) { |
| 200 | const close_ret = linux.close(is.fd); | |
| 201 | const close_err = linux.getErrno(close_ret); | |
| 206 | const close_ret = system.close(is.fd); | |
| 207 | const close_err = system.getErrno(close_ret); | |
| 202 | 208 | if (close_err > 0) { |
| 203 | 209 | return switch (close_err) { |
| 204 | 210 | errno.EINTR => continue, |
| ... | ... | @@ -219,11 +225,11 @@ pub struct InStream { |
| 219 | 225 | /// the stream reached End Of File. |
| 220 | 226 | pub fn read(is: &InStream, buf: []u8) -> %usize { |
| 221 | 227 | switch (@compileVar("os")) { |
| 222 | linux => { | |
| 228 | linux, darwin => { | |
| 223 | 229 | var index: usize = 0; |
| 224 | 230 | while (index < buf.len) { |
| 225 | const amt_read = linux.read(is.fd, &buf[index], buf.len - index); | |
| 226 | const read_err = linux.getErrno(amt_read); | |
| 231 | const amt_read = system.read(is.fd, &buf[index], buf.len - index); | |
| 232 | const read_err = system.getErrno(amt_read); | |
| 227 | 233 | if (read_err > 0) { |
| 228 | 234 | switch (read_err) { |
| 229 | 235 | errno.EINTR => continue, |
| ... | ... | @@ -287,9 +293,9 @@ pub struct InStream { |
| 287 | 293 | |
| 288 | 294 | pub fn seekForward(is: &InStream, amount: usize) -> %void { |
| 289 | 295 | switch (@compileVar("os")) { |
| 290 | linux => { | |
| 291 | const result = linux.lseek(is.fd, amount, linux.SEEK_CUR); | |
| 292 | const err = linux.getErrno(result); | |
| 296 | linux, darwin => { | |
| 297 | const result = system.lseek(is.fd, amount, system.SEEK_CUR); | |
| 298 | const err = system.getErrno(result); | |
| 293 | 299 | if (err > 0) { |
| 294 | 300 | return switch (err) { |
| 295 | 301 | errno.EBADF => error.BadFd, |
| ... | ... | @@ -307,9 +313,9 @@ pub struct InStream { |
| 307 | 313 | |
| 308 | 314 | pub fn seekTo(is: &InStream, pos: usize) -> %void { |
| 309 | 315 | switch (@compileVar("os")) { |
| 310 | linux => { | |
| 311 | const result = linux.lseek(is.fd, pos, linux.SEEK_SET); | |
| 312 | const err = linux.getErrno(result); | |
| 316 | linux, darwin => { | |
| 317 | const result = system.lseek(is.fd, pos, system.SEEK_SET); | |
| 318 | const err = system.getErrno(result); | |
| 313 | 319 | if (err > 0) { |
| 314 | 320 | return switch (err) { |
| 315 | 321 | errno.EBADF => error.BadFd, |
| ... | ... | @@ -327,9 +333,9 @@ pub struct InStream { |
| 327 | 333 | |
| 328 | 334 | pub fn getPos(is: &InStream) -> %usize { |
| 329 | 335 | switch (@compileVar("os")) { |
| 330 | linux => { | |
| 331 | const result = linux.lseek(is.fd, 0, linux.SEEK_CUR); | |
| 332 | const err = linux.getErrno(result); | |
| 336 | linux, darwin => { | |
| 337 | const result = system.lseek(is.fd, 0, system.SEEK_CUR); | |
| 338 | const err = system.getErrno(result); | |
| 333 | 339 | if (err > 0) { |
| 334 | 340 | return switch (err) { |
| 335 | 341 | errno.EBADF => error.BadFd, |
| ... | ... | @@ -347,8 +353,8 @@ pub struct InStream { |
| 347 | 353 | } |
| 348 | 354 | |
| 349 | 355 | pub fn getEndPos(is: &InStream) -> %usize { |
| 350 | var stat: linux.stat = undefined; | |
| 351 | const err = linux.getErrno(linux.fstat(is.fd, &stat)); | |
| 356 | var stat: system.stat = undefined; | |
| 357 | const err = system.getErrno(system.fstat(is.fd, &stat)); | |
| 352 | 358 | if (err > 0) { |
| 353 | 359 | return switch (err) { |
| 354 | 360 | errno.EBADF => error.BadFd, |
| ... | ... | @@ -436,6 +442,10 @@ pub fn openSelfExe(stream: &InStream) -> %void { |
| 436 | 442 | linux => { |
| 437 | 443 | %return stream.open("/proc/self/exe"); |
| 438 | 444 | }, |
| 445 | darwin => { | |
| 446 | %%stderr.printf("TODO: openSelfExe on Darwin\n"); | |
| 447 | os.abort(); | |
| 448 | }, | |
| 439 | 449 | else => @compileError("unsupported os"), |
| 440 | 450 | } |
| 441 | 451 | } |
std/os.zig+23-18| ... | ... | @@ -1,33 +1,38 @@ |
| 1 | const linux = @import("linux.zig"); | |
| 1 | const system = switch(@compileVar("os")) { | |
| 2 | linux => @import("linux.zig"), | |
| 3 | darwin => @import("darwin.zig"), | |
| 4 | else => @compileError("Unsupported OS"), | |
| 5 | }; | |
| 2 | 6 | const errno = @import("errno.zig"); |
| 3 | 7 | |
| 4 | pub error SigInterrupt; | |
| 5 | 8 | pub error Unexpected; |
| 6 | 9 | |
| 7 | 10 | pub fn getRandomBytes(buf: []u8) -> %void { |
| 8 | switch (@compileVar("os")) { | |
| 9 | linux => { | |
| 10 | const ret = linux.getrandom(buf.ptr, buf.len, 0); | |
| 11 | const err = linux.getErrno(ret); | |
| 12 | if (err > 0) { | |
| 13 | return switch (err) { | |
| 14 | errno.EINVAL => @unreachable(), | |
| 15 | errno.EFAULT => @unreachable(), | |
| 16 | errno.EINTR => error.SigInterrupt, | |
| 17 | else => error.Unexpected, | |
| 18 | } | |
| 11 | while (true) { | |
| 12 | const ret = switch (@compileVar("os")) { | |
| 13 | linux => system.getrandom(buf.ptr, buf.len, 0), | |
| 14 | darwin => system.getrandom(buf.ptr, buf.len), | |
| 15 | else => @compileError("unsupported os"), | |
| 16 | }; | |
| 17 | const err = system.getErrno(ret); | |
| 18 | if (err > 0) { | |
| 19 | return switch (err) { | |
| 20 | errno.EINVAL => @unreachable(), | |
| 21 | errno.EFAULT => @unreachable(), | |
| 22 | errno.EINTR => continue, | |
| 23 | else => error.Unexpected, | |
| 19 | 24 | } |
| 20 | }, | |
| 21 | else => @compileError("unsupported os"), | |
| 25 | } | |
| 26 | return; | |
| 22 | 27 | } |
| 23 | 28 | } |
| 24 | 29 | |
| 25 | 30 | #attribute("cold") |
| 26 | 31 | pub fn abort() -> unreachable { |
| 27 | 32 | switch (@compileVar("os")) { |
| 28 | linux => { | |
| 29 | linux.raise(linux.SIGABRT); | |
| 30 | linux.raise(linux.SIGKILL); | |
| 33 | linux, darwin => { | |
| 34 | system.raise(system.SIGABRT); | |
| 35 | system.raise(system.SIGKILL); | |
| 31 | 36 | while (true) {} |
| 32 | 37 | }, |
| 33 | 38 | else => @compileError("unsupported os"), |
test/run_tests.cpp+40-23| ... | ... | @@ -18,6 +18,11 @@ struct TestSourceFile { |
| 18 | 18 | const char *source_code; |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | enum AllowWarnings { | |
| 22 | AllowWarningsNo, | |
| 23 | AllowWarningsYes, | |
| 24 | }; | |
| 25 | ||
| 21 | 26 | struct TestCase { |
| 22 | 27 | const char *case_name; |
| 23 | 28 | const char *output; |
| ... | ... | @@ -29,6 +34,7 @@ struct TestCase { |
| 29 | 34 | bool is_self_hosted; |
| 30 | 35 | bool is_release_mode; |
| 31 | 36 | bool is_debug_safety; |
| 37 | AllowWarnings allow_warnings; | |
| 32 | 38 | }; |
| 33 | 39 | |
| 34 | 40 | static ZigList<TestCase*> test_cases = {0}; |
| ... | ... | @@ -173,13 +179,16 @@ static void add_debug_safety_case(const char *case_name, const char *source) { |
| 173 | 179 | } |
| 174 | 180 | } |
| 175 | 181 | |
| 176 | static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) { | |
| 182 | static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings, | |
| 183 | const char *source, int count, ...) | |
| 184 | { | |
| 177 | 185 | va_list ap; |
| 178 | 186 | va_start(ap, count); |
| 179 | 187 | |
| 180 | 188 | TestCase *test_case = allocate<TestCase>(1); |
| 181 | 189 | test_case->case_name = case_name; |
| 182 | 190 | test_case->is_parseh = true; |
| 191 | test_case->allow_warnings = allow_warnings; | |
| 183 | 192 | |
| 184 | 193 | test_case->source_files.resize(1); |
| 185 | 194 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| ... | ... | @@ -1635,7 +1644,7 @@ fn unsigned_cast(x: i32) -> u32 { |
| 1635 | 1644 | ////////////////////////////////////////////////////////////////////////////// |
| 1636 | 1645 | |
| 1637 | 1646 | static void add_parseh_test_cases(void) { |
| 1638 | add_parseh_case("simple data types", R"SOURCE( | |
| 1647 | add_parseh_case("simple data types", AllowWarningsYes, R"SOURCE( | |
| 1639 | 1648 | #include <stdint.h> |
| 1640 | 1649 | int foo(char a, unsigned char b, signed char c); |
| 1641 | 1650 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype |
| ... | ... | @@ -1646,11 +1655,11 @@ void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1646 | 1655 | "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", |
| 1647 | 1656 | "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); |
| 1648 | 1657 | |
| 1649 | add_parseh_case("noreturn attribute", R"SOURCE( | |
| 1658 | add_parseh_case("noreturn attribute", AllowWarningsNo, R"SOURCE( | |
| 1650 | 1659 | void foo(void) __attribute__((noreturn)); |
| 1651 | 1660 | )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1652 | 1661 | |
| 1653 | add_parseh_case("enums", R"SOURCE( | |
| 1662 | add_parseh_case("enums", AllowWarningsNo, R"SOURCE( | |
| 1654 | 1663 | enum Foo { |
| 1655 | 1664 | FooA, |
| 1656 | 1665 | FooB, |
| ... | ... | @@ -1665,11 +1674,11 @@ pub const FooB = enum_Foo.B; |
| 1665 | 1674 | pub const Foo1 = enum_Foo.@"1";)", |
| 1666 | 1675 | R"(pub const Foo = enum_Foo;)"); |
| 1667 | 1676 | |
| 1668 | add_parseh_case("restrict -> noalias", R"SOURCE( | |
| 1677 | add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( | |
| 1669 | 1678 | void foo(void *restrict bar, void *restrict); |
| 1670 | 1679 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); |
| 1671 | 1680 | |
| 1672 | add_parseh_case("simple struct", R"SOURCE( | |
| 1681 | add_parseh_case("simple struct", AllowWarningsNo, R"SOURCE( | |
| 1673 | 1682 | struct Foo { |
| 1674 | 1683 | int x; |
| 1675 | 1684 | char *y; |
| ... | ... | @@ -1680,7 +1689,7 @@ struct Foo { |
| 1680 | 1689 | y: ?&u8, |
| 1681 | 1690 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1682 | 1691 | |
| 1683 | add_parseh_case("qualified struct and enum", R"SOURCE( | |
| 1692 | add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( | |
| 1684 | 1693 | struct Foo { |
| 1685 | 1694 | int x; |
| 1686 | 1695 | int y; |
| ... | ... | @@ -1703,12 +1712,13 @@ pub const BarB = enum_Bar.B;)OUTPUT", |
| 1703 | 1712 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1704 | 1713 | pub const Bar = enum_Bar;)OUTPUT"); |
| 1705 | 1714 | |
| 1706 | add_parseh_case("constant size array", R"SOURCE( | |
| 1715 | add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( | |
| 1707 | 1716 | void func(int array[20]); |
| 1708 | 1717 | )SOURCE", 1, "pub extern fn func(array: ?&c_int);"); |
| 1709 | 1718 | |
| 1710 | 1719 | |
| 1711 | add_parseh_case("self referential struct with function pointer", R"SOURCE( | |
| 1720 | add_parseh_case("self referential struct with function pointer", | |
| 1721 | AllowWarningsNo, R"SOURCE( | |
| 1712 | 1722 | struct Foo { |
| 1713 | 1723 | void (*derp)(struct Foo *foo); |
| 1714 | 1724 | }; |
| ... | ... | @@ -1717,7 +1727,7 @@ struct Foo { |
| 1717 | 1727 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1718 | 1728 | |
| 1719 | 1729 | |
| 1720 | add_parseh_case("struct prototype used in func", R"SOURCE( | |
| 1730 | add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( | |
| 1721 | 1731 | struct Foo; |
| 1722 | 1732 | struct Foo *some_func(struct Foo *foo, int x); |
| 1723 | 1733 | )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; |
| ... | ... | @@ -1725,17 +1735,19 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1725 | 1735 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1726 | 1736 | |
| 1727 | 1737 | |
| 1728 | add_parseh_case("#define a char literal", R"SOURCE( | |
| 1738 | add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( | |
| 1729 | 1739 | #define A_CHAR 'a' |
| 1730 | 1740 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); |
| 1731 | 1741 | |
| 1732 | 1742 | |
| 1733 | add_parseh_case("#define an unsigned integer literal", R"SOURCE( | |
| 1743 | add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, | |
| 1744 | R"SOURCE( | |
| 1734 | 1745 | #define CHANNEL_COUNT 24 |
| 1735 | 1746 | )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); |
| 1736 | 1747 | |
| 1737 | 1748 | |
| 1738 | add_parseh_case("#define referencing another #define", R"SOURCE( | |
| 1749 | add_parseh_case("#define referencing another #define", AllowWarningsNo, | |
| 1750 | R"SOURCE( | |
| 1739 | 1751 | #define THING2 THING1 |
| 1740 | 1752 | #define THING1 1234 |
| 1741 | 1753 | )SOURCE", 2, |
| ... | ... | @@ -1743,7 +1755,7 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1743 | 1755 | "pub const THING2 = THING1;"); |
| 1744 | 1756 | |
| 1745 | 1757 | |
| 1746 | add_parseh_case("variables", R"SOURCE( | |
| 1758 | add_parseh_case("variables", AllowWarningsNo, R"SOURCE( | |
| 1747 | 1759 | extern int extern_var; |
| 1748 | 1760 | static const int int_var = 13; |
| 1749 | 1761 | )SOURCE", 2, |
| ... | ... | @@ -1751,7 +1763,7 @@ static const int int_var = 13; |
| 1751 | 1763 | "pub const int_var: c_int = 13;"); |
| 1752 | 1764 | |
| 1753 | 1765 | |
| 1754 | add_parseh_case("circular struct definitions", R"SOURCE( | |
| 1766 | add_parseh_case("circular struct definitions", AllowWarningsNo, R"SOURCE( | |
| 1755 | 1767 | struct Bar; |
| 1756 | 1768 | |
| 1757 | 1769 | struct Foo { |
| ... | ... | @@ -1770,14 +1782,15 @@ struct Bar { |
| 1770 | 1782 | })SOURCE"); |
| 1771 | 1783 | |
| 1772 | 1784 | |
| 1773 | add_parseh_case("typedef void", R"SOURCE( | |
| 1785 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( | |
| 1774 | 1786 | typedef void Foo; |
| 1775 | 1787 | Foo fun(Foo *a); |
| 1776 | 1788 | )SOURCE", 2, |
| 1777 | 1789 | "pub const Foo = c_void;", |
| 1778 | 1790 | "pub extern fn fun(a: ?&c_void);"); |
| 1779 | 1791 | |
| 1780 | add_parseh_case("generate inline func for #define global extern fn", R"SOURCE( | |
| 1792 | add_parseh_case("generate inline func for #define global extern fn", AllowWarningsNo, | |
| 1793 | R"SOURCE( | |
| 1781 | 1794 | extern void (*fn_ptr)(void); |
| 1782 | 1795 | #define foo fn_ptr |
| 1783 | 1796 | )SOURCE", 2, |
| ... | ... | @@ -1787,19 +1800,19 @@ extern void (*fn_ptr)(void); |
| 1787 | 1800 | })SOURCE"); |
| 1788 | 1801 | |
| 1789 | 1802 | |
| 1790 | add_parseh_case("#define string", R"SOURCE( | |
| 1803 | add_parseh_case("#define string", AllowWarningsNo, R"SOURCE( | |
| 1791 | 1804 | #define foo "a string" |
| 1792 | 1805 | )SOURCE", 1, "pub const foo = c\"a string\";"); |
| 1793 | 1806 | |
| 1794 | add_parseh_case("__cdecl doesn't mess up function pointers", R"SOURCE( | |
| 1807 | add_parseh_case("__cdecl doesn't mess up function pointers", AllowWarningsNo, R"SOURCE( | |
| 1795 | 1808 | void foo(void (__cdecl *fn_ptr)(void)); |
| 1796 | 1809 | )SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());"); |
| 1797 | 1810 | |
| 1798 | add_parseh_case("comment after integer literal", R"SOURCE( | |
| 1811 | add_parseh_case("comment after integer literal", AllowWarningsNo, R"SOURCE( | |
| 1799 | 1812 | #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ |
| 1800 | 1813 | )SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;"); |
| 1801 | 1814 | |
| 1802 | add_parseh_case("zig keywords in C code", R"SOURCE( | |
| 1815 | add_parseh_case("zig keywords in C code", AllowWarningsNo, R"SOURCE( | |
| 1803 | 1816 | struct type { |
| 1804 | 1817 | int defer; |
| 1805 | 1818 | }; |
| ... | ... | @@ -1807,7 +1820,7 @@ struct type { |
| 1807 | 1820 | @"defer": c_int, |
| 1808 | 1821 | })", R"(pub const @"type" = struct_type;)"); |
| 1809 | 1822 | |
| 1810 | add_parseh_case("macro defines string literal with octal", R"SOURCE( | |
| 1823 | add_parseh_case("macro defines string literal with octal", AllowWarningsNo, R"SOURCE( | |
| 1811 | 1824 | #define FOO "aoeu\023 derp" |
| 1812 | 1825 | #define FOO2 "aoeu\0234 derp" |
| 1813 | 1826 | #define FOO_CHAR '\077' |
| ... | ... | @@ -1926,9 +1939,13 @@ static void run_test(TestCase *test_case) { |
| 1926 | 1939 | if (test_case->is_parseh) { |
| 1927 | 1940 | if (buf_len(&zig_stderr) > 0) { |
| 1928 | 1941 | printf("\nparseh emitted warnings:\n"); |
| 1942 | printf("------------------------------\n"); | |
| 1929 | 1943 | print_compiler_invocation(test_case); |
| 1930 | 1944 | printf("%s\n", buf_ptr(&zig_stderr)); |
| 1931 | exit(1); | |
| 1945 | printf("------------------------------\n"); | |
| 1946 | if (test_case->allow_warnings == AllowWarningsNo) { | |
| 1947 | exit(1); | |
| 1948 | } | |
| 1932 | 1949 | } |
| 1933 | 1950 | |
| 1934 | 1951 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |