mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
commit
c65fe384dd
@ -213,6 +213,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/io.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/linux.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/darwin.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/darwin_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
|
||||
@ -42,8 +42,6 @@ static void init_darwin_native(CodeGen *g) {
|
||||
g->mmacosx_version_min = buf_create_from_str(osx_target);
|
||||
} else if (ios_target) {
|
||||
g->mios_version_min = buf_create_from_str(ios_target);
|
||||
} else {
|
||||
zig_panic("unable to determine -mmacosx-version-min or -mios-version-min");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -643,6 +643,12 @@ static void construct_linker_job_darwin(LinkJob *lj) {
|
||||
|
||||
lj->args.append((const char *)buf_ptr(&lj->out_file_o));
|
||||
|
||||
if (g->is_test_build) {
|
||||
const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc";
|
||||
Buf *test_runner_o_path = build_o(g, test_runner_name);
|
||||
lj->args.append(buf_ptr(test_runner_o_path));
|
||||
}
|
||||
|
||||
for (int i = 0; i < g->link_libs.length; i += 1) {
|
||||
Buf *link_lib = g->link_libs.at(i);
|
||||
Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib));
|
||||
|
||||
@ -388,9 +388,11 @@ int main(int argc, char **argv) {
|
||||
fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (mmacosx_version_min) {
|
||||
codegen_set_mmacosx_version_min(g, buf_create_from_str(mmacosx_version_min));
|
||||
}
|
||||
|
||||
if (mios_version_min) {
|
||||
codegen_set_mios_version_min(g, buf_create_from_str(mios_version_min));
|
||||
}
|
||||
|
||||
113
std/darwin.zig
Normal file
113
std/darwin.zig
Normal file
@ -0,0 +1,113 @@
|
||||
|
||||
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 {
|
||||
// TODO investigate whether we need to block signals before calling kill
|
||||
// like we do in the linux version of raise
|
||||
|
||||
//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;
|
||||
}
|
||||
86
std/darwin_x86_64.zig
Normal file
86
std/darwin_x86_64.zig
Normal file
@ -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,
|
||||
}
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
104
std/io.zig
104
std/io.zig
@ -1,9 +1,15 @@
|
||||
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");
|
||||
const debug = @import("debug.zig");
|
||||
const assert = debug.assert;
|
||||
const os = @import("os.zig");
|
||||
|
||||
pub const stdin_fileno = 0;
|
||||
pub const stdout_fileno = 1;
|
||||
@ -67,23 +73,23 @@ pub struct OutStream {
|
||||
buffer: [buffer_size]u8,
|
||||
index: usize,
|
||||
|
||||
pub fn writeByte(os: &OutStream, b: u8) -> %void {
|
||||
if (os.buffer.len == os.index) %return os.flush();
|
||||
os.buffer[os.index] = b;
|
||||
os.index += 1;
|
||||
pub fn writeByte(self: &OutStream, b: u8) -> %void {
|
||||
if (self.buffer.len == self.index) %return self.flush();
|
||||
self.buffer[self.index] = b;
|
||||
self.index += 1;
|
||||
}
|
||||
|
||||
pub fn write(os: &OutStream, bytes: []const u8) -> %usize {
|
||||
pub fn write(self: &OutStream, bytes: []const u8) -> %usize {
|
||||
var src_bytes_left = bytes.len;
|
||||
var src_index: @typeOf(bytes.len) = 0;
|
||||
const dest_space_left = os.buffer.len - os.index;
|
||||
const dest_space_left = self.buffer.len - self.index;
|
||||
|
||||
while (src_bytes_left > 0) {
|
||||
const copy_amt = math.min(dest_space_left, src_bytes_left);
|
||||
@memcpy(&os.buffer[os.index], &bytes[src_index], copy_amt);
|
||||
os.index += copy_amt;
|
||||
if (os.index == os.buffer.len) {
|
||||
%return os.flush();
|
||||
@memcpy(&self.buffer[self.index], &bytes[src_index], copy_amt);
|
||||
self.index += copy_amt;
|
||||
if (self.index == self.buffer.len) {
|
||||
%return self.flush();
|
||||
}
|
||||
src_bytes_left -= copy_amt;
|
||||
}
|
||||
@ -92,30 +98,29 @@ pub struct OutStream {
|
||||
|
||||
/// Prints a byte buffer, flushes the buffer, then returns the number of
|
||||
/// bytes printed. The "f" is for "flush".
|
||||
pub fn printf(os: &OutStream, str: []const u8) -> %usize {
|
||||
const byte_count = %return os.write(str);
|
||||
%return os.flush();
|
||||
pub fn printf(self: &OutStream, str: []const u8) -> %usize {
|
||||
const byte_count = %return self.write(str);
|
||||
%return self.flush();
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
pub fn printInt(os: &OutStream, inline T: type, x: T) -> %usize {
|
||||
pub fn printInt(self: &OutStream, inline T: type, x: T) -> %usize {
|
||||
// TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T)))
|
||||
if (os.index + max_u64_base10_digits >= os.buffer.len) {
|
||||
%return os.flush();
|
||||
if (self.index + max_u64_base10_digits >= self.buffer.len) {
|
||||
%return self.flush();
|
||||
}
|
||||
const amt_printed = bufPrintInt(T, os.buffer[os.index...], x);
|
||||
os.index += amt_printed;
|
||||
const amt_printed = bufPrintInt(T, self.buffer[self.index...], x);
|
||||
self.index += amt_printed;
|
||||
return amt_printed;
|
||||
}
|
||||
|
||||
pub fn flush(os: &OutStream) -> %void {
|
||||
pub fn flush(self: &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(self.fd, &self.buffer[0], self.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,
|
||||
@ -126,15 +131,15 @@ pub struct OutStream {
|
||||
else => error.Unexpected,
|
||||
}
|
||||
}
|
||||
os.index = 0;
|
||||
self.index = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(os: &OutStream) -> %void {
|
||||
pub fn close(self: &OutStream) -> %void {
|
||||
while (true) {
|
||||
const close_ret = linux.close(os.fd);
|
||||
const close_err = linux.getErrno(close_ret);
|
||||
const close_ret = system.close(self.fd);
|
||||
const close_err = system.getErrno(close_ret);
|
||||
if (close_err > 0) {
|
||||
return switch (close_err) {
|
||||
errno.EINTR => continue,
|
||||
@ -157,10 +162,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 +194,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 +225,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 +293,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 +313,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 +333,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 +353,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,
|
||||
@ -436,6 +442,10 @@ pub fn openSelfExe(stream: &InStream) -> %void {
|
||||
linux => {
|
||||
%return stream.open("/proc/self/exe");
|
||||
},
|
||||
darwin => {
|
||||
%%stderr.printf("TODO: openSelfExe on Darwin\n");
|
||||
os.abort();
|
||||
},
|
||||
else => @compileError("unsupported os"),
|
||||
}
|
||||
}
|
||||
|
||||
41
std/os.zig
41
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"),
|
||||
|
||||
@ -18,6 +18,11 @@ struct TestSourceFile {
|
||||
const char *source_code;
|
||||
};
|
||||
|
||||
enum AllowWarnings {
|
||||
AllowWarningsNo,
|
||||
AllowWarningsYes,
|
||||
};
|
||||
|
||||
struct TestCase {
|
||||
const char *case_name;
|
||||
const char *output;
|
||||
@ -29,6 +34,7 @@ struct TestCase {
|
||||
bool is_self_hosted;
|
||||
bool is_release_mode;
|
||||
bool is_debug_safety;
|
||||
AllowWarnings allow_warnings;
|
||||
};
|
||||
|
||||
static ZigList<TestCase*> test_cases = {0};
|
||||
@ -173,13 +179,16 @@ static void add_debug_safety_case(const char *case_name, const char *source) {
|
||||
}
|
||||
}
|
||||
|
||||
static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) {
|
||||
static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings,
|
||||
const char *source, int count, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, count);
|
||||
|
||||
TestCase *test_case = allocate<TestCase>(1);
|
||||
test_case->case_name = case_name;
|
||||
test_case->is_parseh = true;
|
||||
test_case->allow_warnings = allow_warnings;
|
||||
|
||||
test_case->source_files.resize(1);
|
||||
test_case->source_files.at(0).relative_path = tmp_h_path;
|
||||
@ -1635,7 +1644,7 @@ fn unsigned_cast(x: i32) -> u32 {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void add_parseh_test_cases(void) {
|
||||
add_parseh_case("simple data types", R"SOURCE(
|
||||
add_parseh_case("simple data types", AllowWarningsYes, R"SOURCE(
|
||||
#include <stdint.h>
|
||||
int foo(char a, unsigned char b, signed char c);
|
||||
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);
|
||||
"pub extern fn bar(a: u8, b: u16, c: u32, d: u64);",
|
||||
"pub extern fn baz(a: i8, b: i16, c: i32, d: i64);");
|
||||
|
||||
add_parseh_case("noreturn attribute", R"SOURCE(
|
||||
add_parseh_case("noreturn attribute", AllowWarningsNo, R"SOURCE(
|
||||
void foo(void) __attribute__((noreturn));
|
||||
)SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");
|
||||
|
||||
add_parseh_case("enums", R"SOURCE(
|
||||
add_parseh_case("enums", AllowWarningsNo, R"SOURCE(
|
||||
enum Foo {
|
||||
FooA,
|
||||
FooB,
|
||||
@ -1665,11 +1674,11 @@ pub const FooB = enum_Foo.B;
|
||||
pub const Foo1 = enum_Foo.@"1";)",
|
||||
R"(pub const Foo = enum_Foo;)");
|
||||
|
||||
add_parseh_case("restrict -> noalias", R"SOURCE(
|
||||
add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE(
|
||||
void foo(void *restrict bar, void *restrict);
|
||||
)SOURCE", 1, R"OUTPUT(pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");
|
||||
|
||||
add_parseh_case("simple struct", R"SOURCE(
|
||||
add_parseh_case("simple struct", AllowWarningsNo, R"SOURCE(
|
||||
struct Foo {
|
||||
int x;
|
||||
char *y;
|
||||
@ -1680,7 +1689,7 @@ struct Foo {
|
||||
y: ?&u8,
|
||||
})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
|
||||
|
||||
add_parseh_case("qualified struct and enum", R"SOURCE(
|
||||
add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE(
|
||||
struct Foo {
|
||||
int x;
|
||||
int y;
|
||||
@ -1703,12 +1712,13 @@ pub const BarB = enum_Bar.B;)OUTPUT",
|
||||
R"OUTPUT(pub const Foo = struct_Foo;
|
||||
pub const Bar = enum_Bar;)OUTPUT");
|
||||
|
||||
add_parseh_case("constant size array", R"SOURCE(
|
||||
add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE(
|
||||
void func(int array[20]);
|
||||
)SOURCE", 1, "pub extern fn func(array: ?&c_int);");
|
||||
|
||||
|
||||
add_parseh_case("self referential struct with function pointer", R"SOURCE(
|
||||
add_parseh_case("self referential struct with function pointer",
|
||||
AllowWarningsNo, R"SOURCE(
|
||||
struct Foo {
|
||||
void (*derp)(struct Foo *foo);
|
||||
};
|
||||
@ -1717,7 +1727,7 @@ struct Foo {
|
||||
})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
|
||||
|
||||
|
||||
add_parseh_case("struct prototype used in func", R"SOURCE(
|
||||
add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE(
|
||||
struct Foo;
|
||||
struct Foo *some_func(struct Foo *foo, int x);
|
||||
)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",
|
||||
R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
|
||||
|
||||
|
||||
add_parseh_case("#define a char literal", R"SOURCE(
|
||||
add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE(
|
||||
#define A_CHAR 'a'
|
||||
)SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT");
|
||||
|
||||
|
||||
add_parseh_case("#define an unsigned integer literal", R"SOURCE(
|
||||
add_parseh_case("#define an unsigned integer literal", AllowWarningsNo,
|
||||
R"SOURCE(
|
||||
#define CHANNEL_COUNT 24
|
||||
)SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT");
|
||||
|
||||
|
||||
add_parseh_case("#define referencing another #define", R"SOURCE(
|
||||
add_parseh_case("#define referencing another #define", AllowWarningsNo,
|
||||
R"SOURCE(
|
||||
#define THING2 THING1
|
||||
#define THING1 1234
|
||||
)SOURCE", 2,
|
||||
@ -1743,7 +1755,7 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
|
||||
"pub const THING2 = THING1;");
|
||||
|
||||
|
||||
add_parseh_case("variables", R"SOURCE(
|
||||
add_parseh_case("variables", AllowWarningsNo, R"SOURCE(
|
||||
extern int extern_var;
|
||||
static const int int_var = 13;
|
||||
)SOURCE", 2,
|
||||
@ -1751,7 +1763,7 @@ static const int int_var = 13;
|
||||
"pub const int_var: c_int = 13;");
|
||||
|
||||
|
||||
add_parseh_case("circular struct definitions", R"SOURCE(
|
||||
add_parseh_case("circular struct definitions", AllowWarningsNo, R"SOURCE(
|
||||
struct Bar;
|
||||
|
||||
struct Foo {
|
||||
@ -1770,14 +1782,15 @@ struct Bar {
|
||||
})SOURCE");
|
||||
|
||||
|
||||
add_parseh_case("typedef void", R"SOURCE(
|
||||
add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE(
|
||||
typedef void Foo;
|
||||
Foo fun(Foo *a);
|
||||
)SOURCE", 2,
|
||||
"pub const Foo = c_void;",
|
||||
"pub extern fn fun(a: ?&c_void);");
|
||||
|
||||
add_parseh_case("generate inline func for #define global extern fn", R"SOURCE(
|
||||
add_parseh_case("generate inline func for #define global extern fn", AllowWarningsNo,
|
||||
R"SOURCE(
|
||||
extern void (*fn_ptr)(void);
|
||||
#define foo fn_ptr
|
||||
)SOURCE", 2,
|
||||
@ -1787,19 +1800,19 @@ extern void (*fn_ptr)(void);
|
||||
})SOURCE");
|
||||
|
||||
|
||||
add_parseh_case("#define string", R"SOURCE(
|
||||
add_parseh_case("#define string", AllowWarningsNo, R"SOURCE(
|
||||
#define foo "a string"
|
||||
)SOURCE", 1, "pub const foo = c\"a string\";");
|
||||
|
||||
add_parseh_case("__cdecl doesn't mess up function pointers", R"SOURCE(
|
||||
add_parseh_case("__cdecl doesn't mess up function pointers", AllowWarningsNo, R"SOURCE(
|
||||
void foo(void (__cdecl *fn_ptr)(void));
|
||||
)SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());");
|
||||
|
||||
add_parseh_case("comment after integer literal", R"SOURCE(
|
||||
add_parseh_case("comment after integer literal", AllowWarningsNo, R"SOURCE(
|
||||
#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
||||
)SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;");
|
||||
|
||||
add_parseh_case("zig keywords in C code", R"SOURCE(
|
||||
add_parseh_case("zig keywords in C code", AllowWarningsNo, R"SOURCE(
|
||||
struct type {
|
||||
int defer;
|
||||
};
|
||||
@ -1807,7 +1820,7 @@ struct type {
|
||||
@"defer": c_int,
|
||||
})", R"(pub const @"type" = struct_type;)");
|
||||
|
||||
add_parseh_case("macro defines string literal with octal", R"SOURCE(
|
||||
add_parseh_case("macro defines string literal with octal", AllowWarningsNo, R"SOURCE(
|
||||
#define FOO "aoeu\023 derp"
|
||||
#define FOO2 "aoeu\0234 derp"
|
||||
#define FOO_CHAR '\077'
|
||||
@ -1926,9 +1939,13 @@ static void run_test(TestCase *test_case) {
|
||||
if (test_case->is_parseh) {
|
||||
if (buf_len(&zig_stderr) > 0) {
|
||||
printf("\nparseh emitted warnings:\n");
|
||||
printf("------------------------------\n");
|
||||
print_compiler_invocation(test_case);
|
||||
printf("%s\n", buf_ptr(&zig_stderr));
|
||||
exit(1);
|
||||
printf("------------------------------\n");
|
||||
if (test_case->allow_warnings == AllowWarningsNo) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < test_case->compile_errors.length; i += 1) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user