Commit 320e26590a
example/guess_number/main.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const io = std.io;
-const Rand = std.Rand;
+const Rand = std.rand.Rand;
const os = std.os;
pub fn main(args: [][]u8) -> %void {
@@ -18,7 +18,9 @@ pub fn main(args: [][]u8) -> %void {
var line_buf : [20]u8 = undefined;
const line_len = io.stdin.read(line_buf) %% |err| {
- %%io.stdout.printf("Unable to read from stdin.\n");
+ %%io.stdout.printf("Unable to read from stdin: ");
+ %%io.stdout.printf(@errName(err));
+ %%io.stdout.printf("\n");
return err;
};
std/debug.zig
@@ -119,7 +119,7 @@ fn arangesOffset(st: &ElfStackTrace, target_address: usize) -> %?u64 {
unit_index += 1;
const align = segment_size + 2 * address_size;
- const padding = st.self_exe_stream.offset % align;
+ const padding = (%return st.self_exe_stream.getPos()) % align;
%return st.self_exe_stream.seekForward(padding);
unit_index += padding;
std/elf.zig
@@ -170,7 +170,7 @@ pub struct Elf {
const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);
const end_ph = %return math.addOverflow(u64, elf.program_header_offset, ph_byte_count);
- const stream_end = %return elf.in_stream.endPos();
+ const stream_end = %return elf.in_stream.getEndPos();
if (stream_end < end_sh || stream_end < end_ph) {
return error.InvalidFormat;
}
std/index.zig
@@ -1,4 +1,4 @@
-pub const Rand = @import("rand.zig").Rand;
+pub const rand = @import("rand.zig");
pub const io = @import("io.zig");
pub const os = @import("os.zig");
pub const math = @import("math.zig");
std/io.zig
@@ -11,7 +11,6 @@ pub const stderr_fileno = 2;
pub var stdin = InStream {
.fd = stdin_fileno,
- .offset = 0,
};
pub var stdout = OutStream {
@@ -37,9 +36,6 @@ pub error Unexpected;
pub error DiskQuota;
pub error FileTooBig;
-// TODO hide interrupts at this layer by retrying. Users can use the linux specific APIs if they
-// want to handle interrupts.
-pub error SigInterrupt;
pub error Io;
pub error NoSpaceLeft;
pub error BadPerm;
@@ -113,34 +109,42 @@ pub struct OutStream {
}
pub fn flush(os: &OutStream) -> %void {
- const write_ret = linux.write(os.fd, &os.buffer[0], os.index);
- const write_err = linux.getErrno(write_ret);
- if (write_err > 0) {
- return switch (write_err) {
- errno.EINVAL => unreachable{},
- errno.EDQUOT => error.DiskQuota,
- errno.EFBIG => error.FileTooBig,
- errno.EINTR => error.SigInterrupt,
- errno.EIO => error.Io,
- errno.ENOSPC => error.NoSpaceLeft,
- errno.EPERM => error.BadPerm,
- errno.EPIPE => error.PipeFail,
- else => error.Unexpected,
+ while (true) {
+ const write_ret = linux.write(os.fd, &os.buffer[0], os.index);
+ const write_err = linux.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,
+ errno.EIO => error.Io,
+ errno.ENOSPC => error.NoSpaceLeft,
+ errno.EPERM => error.BadPerm,
+ errno.EPIPE => error.PipeFail,
+ else => error.Unexpected,
+ }
}
+ os.index = 0;
+ return;
}
- os.index = 0;
}
pub fn close(os: &OutStream) -> %void {
- const close_ret = linux.close(os.fd);
- const close_err = linux.getErrno(close_ret);
- if (close_err > 0) {
- return switch (close_err) {
- errno.EIO => error.Io,
- errno.EBADF => error.BadFd,
- errno.EINTR => error.SigInterrupt,
- else => error.Unexpected,
+ while (true) {
+ const close_ret = linux.close(os.fd);
+ const close_err = linux.getErrno(close_ret);
+ if (close_err > 0) {
+ return switch (close_err) {
+ errno.EINTR => continue,
+
+ errno.EIO => error.Io,
+ errno.EBADF => error.BadFd,
+ else => error.Unexpected,
+ }
}
+ return;
}
}
}
@@ -149,47 +153,62 @@ pub struct OutStream {
// BufferedInStream API goes on top of minimal InStream API.
pub struct InStream {
fd: i32,
- offset: usize,
/// Call close to clean up.
pub fn open(is: &InStream, path: []const u8) -> %void {
- const result = linux.open(path, linux.O_LARGEFILE|linux.O_RDONLY, 0);
- const err = linux.getErrno(result);
- if (err > 0) {
- return switch (err) {
- errno.EFAULT => unreachable{},
- errno.EINVAL => unreachable{},
- errno.EACCES => error.BadPerm,
- errno.EFBIG, errno.EOVERFLOW => error.FileTooBig,
- errno.EINTR => error.SigInterrupt,
- 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.NoMem,
- errno.ENOSPC => error.NoSpaceLeft,
- errno.ENOTDIR => error.NotDir,
- errno.EPERM => error.BadPerm,
- else => error.Unexpected,
- }
+ switch (@compileVar("os")) {
+ linux => {
+ while (true) {
+ const result = linux.open(path, linux.O_LARGEFILE|linux.O_RDONLY, 0);
+ const err = linux.getErrno(result);
+ if (err > 0) {
+ return switch (err) {
+ errno.EINTR => continue,
+
+ errno.EFAULT => unreachable{},
+ errno.EINVAL => unreachable{},
+ errno.EACCES => error.BadPerm,
+ 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.NoMem,
+ errno.ENOSPC => error.NoSpaceLeft,
+ errno.ENOTDIR => error.NotDir,
+ errno.EPERM => error.BadPerm,
+ else => error.Unexpected,
+ }
+ }
+ is.fd = i32(result);
+ return;
+ }
+ },
+ else => @compileErr("unsupported OS"),
}
- is.fd = i32(result);
- is.offset = 0;
}
pub fn close(is: &InStream) -> %void {
- const close_ret = linux.close(is.fd);
- const close_err = linux.getErrno(close_ret);
- if (close_err > 0) {
- return switch (close_err) {
- errno.EIO => error.Io,
- errno.EBADF => error.BadFd,
- errno.EINTR => error.SigInterrupt,
- else => error.Unexpected,
- }
+ switch (@compileVar("os")) {
+ linux => {
+ while (true) {
+ const close_ret = linux.close(is.fd);
+ const close_err = linux.getErrno(close_ret);
+ if (close_err > 0) {
+ return switch (close_err) {
+ errno.EINTR => continue,
+
+ errno.EIO => error.Io,
+ errno.EBADF => error.BadFd,
+ else => error.Unexpected,
+ }
+ }
+ }
+ },
+ else => @compileErr("unsupported OS"),
}
}
@@ -198,12 +217,14 @@ pub struct InStream {
pub fn read(is: &InStream, buf: []u8) -> %usize {
switch (@compileVar("os")) {
linux => {
- while (true) {
- const amt_read = linux.pread(is.fd, buf.ptr, buf.len, is.offset);
+ 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);
if (read_err > 0) {
switch (read_err) {
errno.EINTR => continue,
+
errno.EINVAL => unreachable{},
errno.EFAULT => unreachable{},
errno.EBADF => return error.BadFd,
@@ -211,9 +232,10 @@ pub struct InStream {
else => return error.Unexpected,
}
}
- is.offset += amt_read;
- return amt_read;
+ if (amt_read == 0) return index;
+ index += amt_read;
}
+ return index;
},
else => @compileErr("unsupported OS"),
}
@@ -261,14 +283,67 @@ pub struct InStream {
}
pub fn seekForward(is: &InStream, amount: usize) -> %void {
- is.offset += amount;
+ switch (@compileVar("os")) {
+ linux => {
+ const result = linux.lseek(is.fd, amount, linux.SEEK_CUR);
+ const err = linux.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,
+ else => error.Unexpected,
+ };
+ }
+ },
+ else => @compileErr("unsupported OS"),
+ }
}
pub fn seekTo(is: &InStream, pos: usize) -> %void {
- is.offset = pos;
+ switch (@compileVar("os")) {
+ linux => {
+ const result = linux.lseek(is.fd, pos, linux.SEEK_SET);
+ const err = linux.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,
+ else => error.Unexpected,
+ };
+ }
+ },
+ else => @compileErr("unsupported OS"),
+ }
+ }
+
+ 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);
+ 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,
+ else => error.Unexpected,
+ };
+ }
+ return result;
+ },
+ else => @compileErr("unsupported OS"),
+ }
}
- pub fn endPos(is: &InStream) -> %usize {
+ pub fn getEndPos(is: &InStream) -> %usize {
var stat: linux.stat = undefined;
const err = linux.getErrno(linux.fstat(is.fd, &stat));
if (err > 0) {