WASI: implement argsAlloc and argsFree (#2364)

* wasi: change URL to canon WASI-core.md

* wasi: import args_get and args_sizes_get

* wasi: Implement argsAlloc and argsFree

* test return value for wasi arg syscalls

* wasi: return unexpectedErrorPosix in argsAlloc

* wasi: Add TODO for ArgIterator
This commit is contained in:
Shritesh Bhattarai 2019-04-29 20:54:30 -05:00 committed by Andrew Kelley
parent 77383f968d
commit 01365be82f
3 changed files with 47 additions and 1 deletions

View File

@ -2134,6 +2134,11 @@ pub const ArgIterator = struct {
inner: InnerType,
pub fn init() ArgIterator {
if (builtin.os == Os.wasi) {
// TODO: Figure out a compatible interface accomodating WASI
@compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
}
return ArgIterator{ .inner = InnerType.init() };
}
@ -2166,6 +2171,34 @@ pub fn args() ArgIterator {
/// Caller must call argsFree on result.
pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
if (builtin.os == Os.wasi) {
var count: usize = undefined;
var buf_size: usize = undefined;
const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);
if (args_sizes_get_ret != os.wasi.ESUCCESS) {
return unexpectedErrorPosix(args_sizes_get_ret);
}
var argv = try allocator.alloc([*]u8, count);
defer allocator.free(argv);
var argv_buf = try allocator.alloc(u8, buf_size);
const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);
if (args_get_ret != os.wasi.ESUCCESS) {
return unexpectedErrorPosix(args_get_ret);
}
var result_slice = try allocator.alloc([]u8, count);
var i: usize = 0;
while (i < count) : (i += 1) {
result_slice[i] = mem.toSlice(u8, argv[i]);
}
return result_slice;
}
// TODO refactor to only make 1 allocation.
var it = args();
var contents = try Buffer.initSize(allocator, 0);
@ -2203,6 +2236,16 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
}
pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
if (builtin.os == Os.wasi) {
const last_item = args_alloc[args_alloc.len - 1];
const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
const first_item_ptr = args_alloc[0].ptr;
const len = last_byte_addr - @ptrToInt(first_item_ptr);
allocator.free(first_item_ptr[0..len]);
return allocator.free(args_alloc);
}
var total_bytes: usize = 0;
for (args_alloc) |arg| {
total_bytes += @sizeOf([]u8) + arg.len;

View File

@ -1,7 +1,7 @@
pub use @import("wasi/core.zig");
// Based on https://github.com/CraneStation/wasi-sysroot/blob/wasi/libc-bottom-half/headers/public/wasi/core.h
// and https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md
// and https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;

View File

@ -10,6 +10,9 @@ pub const ciovec_t = extern struct {
pub const SIGABRT: signal_t = 6;
pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t;
pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
pub extern "wasi_unstable" fn proc_raise(sig: signal_t) errno_t;
pub extern "wasi_unstable" fn proc_exit(rval: exitcode_t) noreturn;