Merge remote-tracking branch 'origin/master' into error-sets

This commit is contained in:
Andrew Kelley 2018-02-08 20:45:26 -05:00
commit f9be970375
17 changed files with 276 additions and 74 deletions

View File

@ -172,17 +172,17 @@ else()
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
LINK_FLAGS " "
)
target_include_directories(embedded_lld_lib PUBLIC
target_include_directories(embedded_lld_lib PRIVATE
"${CMAKE_SOURCE_DIR}/deps/lld/include"
"${CMAKE_SOURCE_DIR}/deps/lld-prebuilt"
)
target_include_directories(embedded_lld_elf PUBLIC
target_include_directories(embedded_lld_elf PRIVATE
"${CMAKE_SOURCE_DIR}/deps/lld/ELF"
"${CMAKE_SOURCE_DIR}/deps/lld/include"
"${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/ELF"
"${CMAKE_SOURCE_DIR}/deps/lld-prebuilt"
)
target_include_directories(embedded_lld_coff PUBLIC
target_include_directories(embedded_lld_coff PRIVATE
"${CMAKE_SOURCE_DIR}/deps/lld/COFF"
"${CMAKE_SOURCE_DIR}/deps/lld/include"
"${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/COFF"
@ -439,10 +439,10 @@ set(ZIG_STD_FILES
"os/darwin_errno.zig"
"os/get_user_id.zig"
"os/index.zig"
"os/linux.zig"
"os/linux_errno.zig"
"os/linux_i386.zig"
"os/linux_x86_64.zig"
"os/linux/index.zig"
"os/linux/errno.zig"
"os/linux/i386.zig"
"os/linux/x86_64.zig"
"os/path.zig"
"os/windows/error.zig"
"os/windows/index.zig"

View File

@ -134,16 +134,6 @@ pub fn main() void {
</p>
{#see_also|Values|@import|Errors|Root Source File#}
{#header_close#}
{#header_open|Source Encoding#}
<p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p>
<p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p>
<ul>
<li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>
<li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
</ul>
<p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
<p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p>
{#header_close#}
{#header_open|Values#}
{#code_begin|exe|values#}
const std = @import("std");
@ -2780,6 +2770,16 @@ test "implicitly cast to const pointer" {
use the C calling convention may pass structs and unions by value.
</p>
{#header_close#}
{#header_open|Function Reflection#}
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "fn reflection" {
assert(@typeOf(assert).ReturnType == void);
assert(@typeOf(assert).is_var_args == false);
}
{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|Errors#}
<p>
@ -2986,6 +2986,32 @@ fn createFoo(param: i32) !Foo {
</li>
</ul>
{#see_also|defer|if|switch#}
{#header_open|Error Union Type#}
<p>An error union is created with the <code>!</code> binary operator.
You can use compile-time reflection to access the child type of an error union:</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "error union" {
var foo: error!i32 = undefined;
// Implicitly cast from child type of an error union:
foo = 1234;
// Implicitly cast from an error set:
foo = error.SomeError;
// Use compile-time reflection to access the payload type of an error union:
comptime assert(@typeOf(foo).Payload == i32);
// Use compile-time reflection to access the error set type of an error union:
comptime assert(@typeOf(foo).ErrorSet == error);
}
{#code_end#}
{#header_close#}
{#header_open|Error Set Type#}
<p>TODO</p>
{#header_close#}
{#header_close#}
{#header_open|Nullables#}
<p>
@ -3087,6 +3113,24 @@ fn doAThing(nullable_foo: ?&Foo) void {
The optimizer can sometimes make better decisions knowing that pointer arguments
cannot be null.
</p>
{#header_open|Nullable Type#}
<p>A nullable is created by putting <code>?</code> in front of a type. You can use compile-time
reflection to access the child type of a nullable:</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "nullable type" {
// Declare a nullable and implicitly cast from null:
var foo: ?i32 = null;
// Implicitly cast from child type of a nullable
foo = 1234;
// Use compile-time reflection to access the child type of the nullable:
comptime assert(@typeOf(foo).Child == i32);
}
{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|Casting#}
<p>TODO: explain implicit vs explicit casting</p>
@ -3822,6 +3866,17 @@ comptime {
<code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work
within this expression, appending to a temporary buffer which is then parsed as C code.
</p>
<p>
Usually you should only have one <code>@cImport</code> in your entire application, because it saves the compiler
from invoking clang multiple times, and prevents inline functions from being duplicated.
</p>
<p>
Reasons for having multiple <code>@cImport</code> expressions would be:
</p>
<ul>
<li>To avoid a symbol collision, for example if foo.h and bar.h both <code>#define CONNECTION_COUNT</code></li>
<li>To analyze the C code with different preprocessor defines</li>
</ul>
{#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
{#header_close#}
{#header_open|@cInclude#}
@ -4151,17 +4206,28 @@ fn add(a: i32, b: i32) i32 { return a + b; }
{#header_open|@memberCount#}
<pre><code class="zig">@memberCount(comptime T: type) -&gt; (number literal)</code></pre>
<p>
This function returns the number of enum values in an enum type.
This function returns the number of members in a struct, enum, or union type.
</p>
<p>
The result is a compile time constant.
</p>
<p>
It does not include functions, variables, or constants.
</p>
{#header_close#}
{#header_open|@memberName#}
<p>TODO</p>
<pre><code class="zig">@memberName(comptime T: type, comptime index: usize) -&gt; [N]u8</code></pre>
<p>Returns the field name of a struct, union, or enum.</p>
<p>
The result is a compile time constant.
</p>
<p>
It does not include functions, variables, or constants.
</p>
{#header_close#}
{#header_open|@memberType#}
<p>TODO</p>
<pre><code class="zig">@memberType(comptime T: type, comptime index: usize) -&gt; type</code></pre>
<p>Returns the field type of a struct or union.</p>
{#header_close#}
{#header_open|@memcpy#}
<pre><code class="zig">@memcpy(noalias dest: &u8, noalias source: &const u8, byte_count: usize)</code></pre>
@ -5546,6 +5612,16 @@ fn readU32Be() u32 {}
</p>
{#header_close#}
{#header_close#}
{#header_open|Source Encoding#}
<p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p>
<p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p>
<ul>
<li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>
<li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
</ul>
<p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
<p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p>
{#header_close#}
{#header_open|Grammar#}
<pre><code class="nohighlight">Root = many(TopLevelItem) EOF
@ -5716,9 +5792,6 @@ ContainerDecl = option("extern" | "packed")
<li>Together we serve end users.</li>
</ul>
{#header_close#}
{#header_open|TODO#}
<p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p>
{#header_close#}
</div>
<script>
/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */
@ -5780,7 +5853,7 @@ hljs.registerLanguage("zig", function(t) {
a = t.IR + "\\s*\\(",
c = {
keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate",
built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate",
literal: "true false null undefined"
},
n = [e, t.CLCM, t.CBCM, s, r];

View File

@ -3309,6 +3309,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
is_const, init_val, &tld_var->base);
tld_var->var->linkage = linkage;
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
tld_var->var->value->type = g->builtin_types.entry_invalid;
}
if (var_decl->align_expr != nullptr) {
if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
tld_var->var->value->type = g->builtin_types.entry_invalid;

View File

@ -6408,6 +6408,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
if (other_type->id == TypeTableEntryIdFloat) {
return true;
} else if (other_type->id == TypeTableEntryIdInt && const_val_is_int) {
if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
ir_add_error(ira, instruction,
buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
buf_ptr(val_buf),
buf_ptr(&other_type->name)));
return false;
}
if (bigint_fits_in_bits(&const_val->data.x_bigint, other_type->data.integral.bit_count,
other_type->data.integral.is_signed))
{
@ -6420,6 +6429,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
if (const_val_fits_in_num_lit(const_val, child_type)) {
return true;
} else if (child_type->id == TypeTableEntryIdInt && const_val_is_int) {
if (!child_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
ir_add_error(ira, instruction,
buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
buf_ptr(val_buf),
buf_ptr(&child_type->name)));
return false;
}
if (bigint_fits_in_bits(&const_val->data.x_bigint,
child_type->data.integral.bit_count,
child_type->data.integral.is_signed))
@ -6590,9 +6608,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
}
// slice const
if (expected_type->id == TypeTableEntryIdStruct && actual_type->id == TypeTableEntryIdStruct &&
expected_type->data.structure.is_slice && actual_type->data.structure.is_slice)
{
if (is_slice(expected_type) && is_slice(actual_type)) {
TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
if ((!actual_ptr_type->data.pointer.is_const || expected_ptr_type->data.pointer.is_const) &&
@ -6872,10 +6888,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
}
// implicit [N]T to []const T
if (expected_type->id == TypeTableEntryIdStruct &&
expected_type->data.structure.is_slice &&
actual_type->id == TypeTableEntryIdArray)
{
if (is_slice(expected_type) && actual_type->id == TypeTableEntryIdArray) {
TypeTableEntry *ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == TypeTableEntryIdPointer);
@ -6887,8 +6900,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
}
// implicit &const [N]T to []const T
if (expected_type->id == TypeTableEntryIdStruct &&
expected_type->data.structure.is_slice &&
if (is_slice(expected_type) &&
actual_type->id == TypeTableEntryIdPointer &&
actual_type->data.pointer.is_const &&
actual_type->data.pointer.child_type->id == TypeTableEntryIdArray)

View File

@ -341,6 +341,7 @@ int main(int argc, char **argv) {
const char *zig_exe_path = arg0;
const char *build_file = "build.zig";
bool asked_for_help = false;
bool asked_to_init = false;
init_all_targets();
@ -352,6 +353,9 @@ int main(int argc, char **argv) {
if (strcmp(argv[i], "--help") == 0) {
asked_for_help = true;
args.append(argv[i]);
} else if (strcmp(argv[i], "--init") == 0) {
asked_to_init = true;
args.append(argv[i]);
} else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
build_file = argv[i + 1];
i += 1;
@ -416,6 +420,7 @@ int main(int argc, char **argv) {
"\n"
"General Options:\n"
" --help Print this help and exit\n"
" --init Generate a build.zig template\n"
" --build-file [file] Override path to build.zig\n"
" --cache-dir [path] Override path to cache directory\n"
" --verbose Print commands before executing them\n"
@ -428,7 +433,6 @@ int main(int argc, char **argv) {
" --prefix [path] Override default install prefix\n"
"\n"
"Project-specific options become available when the build file is found.\n"
"Run this command with no options to generate a build.zig template.\n"
"\n"
"Advanced Options:\n"
" --build-file [file] Override path to build.zig\n"
@ -441,17 +445,26 @@ int main(int argc, char **argv) {
" --verbose-cimport Enable compiler debug output for C imports\n"
"\n"
, zig_exe_path);
return 0;
}
Buf *build_template_path = buf_alloc();
os_path_join(special_dir, buf_create_from_str("build_file_template.zig"), build_template_path);
return EXIT_SUCCESS;
} else if (asked_to_init) {
Buf *build_template_path = buf_alloc();
os_path_join(special_dir, buf_create_from_str("build_file_template.zig"), build_template_path);
if ((err = os_copy_file(build_template_path, &build_file_abs))) {
fprintf(stderr, "Unable to write build.zig template: %s\n", err_str(err));
} else {
fprintf(stderr, "Wrote build.zig template\n");
if ((err = os_copy_file(build_template_path, &build_file_abs))) {
fprintf(stderr, "Unable to write build.zig template: %s\n", err_str(err));
} else {
fprintf(stderr, "Wrote build.zig template\n");
}
return EXIT_SUCCESS;
}
return 1;
fprintf(stderr,
"No 'build.zig' file found.\n"
"Initialize a 'build.zig' template file with `zig build --init`,\n"
"or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
"See: `zig build --help` or `zig help` for more options.\n"
);
return EXIT_FAILURE;
}
PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),

View File

@ -40,6 +40,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
return l.items[0..l.len];
}
pub fn at(l: &const Self, n: usize) T {
return l.toSliceConst()[n];
}
/// ArrayList takes ownership of the passed in slice. The slice must have been
/// allocated with `allocator`.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
@ -59,6 +63,22 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
return result;
}
pub fn insert(l: &Self, n: usize, item: &const T) !void {
try l.ensureCapacity(l.len + 1);
l.len += 1;
mem.copy(T, l.items[n+1..l.len], l.items[n..l.len-1]);
l.items[n] = *item;
}
pub fn insertSlice(l: &Self, n: usize, items: []align(A) const T) !void {
try l.ensureCapacity(l.len + items.len);
l.len += items.len;
mem.copy(T, l.items[n+items.len..l.len], l.items[n..l.len-items.len]);
mem.copy(T, l.items[n..n+items.len], items);
}
pub fn append(l: &Self, item: &const T) !void {
const new_item_ptr = try l.addOne();
*new_item_ptr = *item;
@ -136,3 +156,22 @@ test "basic ArrayList test" {
list.appendSlice([]const i32 {}) catch unreachable;
assert(list.len == 9);
}
test "insert ArrayList test" {
var list = ArrayList(i32).init(debug.global_allocator);
defer list.deinit();
try list.append(1);
try list.insert(0, 5);
assert(list.items[0] == 5);
assert(list.items[1] == 1);
try list.insertSlice(1, []const i32 { 9, 8 });
assert(list.items[0] == 5);
assert(list.items[1] == 9);
assert(list.items[2] == 8);
const items = []const i32 { 1 };
try list.insertSlice(0, items[0..0]);
assert(list.items[0] == 5);
}

View File

@ -1,4 +1,4 @@
pub use @import("../os/linux_errno.zig");
pub use @import("../os/linux/errno.zig");
pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) c_int;
extern "c" fn __errno_location() &c_int;

View File

@ -228,7 +228,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@
if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) {
return output(context, (*value)[0..]);
} else {
@compileError("Unable to format type '" ++ @typeName(T) ++ "'");
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
}
},
else => if (@canImplicitCast([]const u8, value)) {
@ -550,6 +550,12 @@ test "parse unsigned comptime" {
}
}
// Dummy field because of https://github.com/zig-lang/zig/issues/557.
// At top level because of https://github.com/zig-lang/zig/issues/675.
const Struct = struct {
unused: u8,
};
test "fmt.format" {
{
var buf1: [32]u8 = undefined;
@ -581,6 +587,14 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "u3: {}\n", value);
assert(mem.eql(u8, result, "u3: 5\n"));
}
{
var buf1: [32]u8 = undefined;
const value = Struct {
.unused = 42,
};
const result = try bufPrint(buf1[0..], "pointer: {}\n", &value);
assert(mem.startsWith(u8, result, "pointer: Struct@"));
}
// TODO get these tests passing in release modes
// https://github.com/zig-lang/zig/issues/564

View File

@ -2,7 +2,7 @@ const std = @import("index.zig");
const builtin = @import("builtin");
const Os = builtin.Os;
const system = switch(builtin.os) {
Os.linux => @import("os/linux.zig"),
Os.linux => @import("os/linux/index.zig"),
Os.macosx, Os.ios => @import("os/darwin.zig"),
Os.windows => @import("os/windows/index.zig"),
else => @compileError("Unsupported OS"),

View File

@ -6,7 +6,7 @@ const os = this;
pub const windows = @import("windows/index.zig");
pub const darwin = @import("darwin.zig");
pub const linux = @import("linux.zig");
pub const linux = @import("linux/index.zig");
pub const zen = @import("zen.zig");
pub const posix = switch(builtin.os) {
Os.linux => linux,
@ -70,18 +70,24 @@ pub fn getRandomBytes(buf: []u8) !void {
// See #397
const err = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
if (err > 0) {
return switch (err) {
switch (err) {
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
posix.EINTR => continue,
else => unexpectedErrorPosix(err),
};
posix.ENOSYS => {
const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);
defer close(fd);
try posixRead(fd, buf);
return;
},
else => return unexpectedErrorPosix(err),
}
}
return;
},
Os.macosx, Os.ios => {
const fd = try posixOpen("/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC,
0, null);
const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);
defer close(fd);
try posixRead(fd, buf);
@ -171,10 +177,15 @@ pub fn close(handle: FileHandle) void {
/// Calls POSIX read, and keeps trying if it gets interrupted.
pub fn posixRead(fd: i32, buf: []u8) !void {
// Linux can return EINVAL when read amount is > 0x7ffff000
// See https://github.com/zig-lang/zig/pull/743#issuecomment-363158274
const max_buf_len = 0x7ffff000;
var index: usize = 0;
while (index < buf.len) {
const amt_written = posix.read(fd, &buf[index], buf.len - index);
const err = posix.getErrno(amt_written);
const want_to_read = math.min(buf.len - index, usize(max_buf_len));
const rc = posix.read(fd, &buf[index], want_to_read);
const err = posix.getErrno(rc);
if (err > 0) {
return switch (err) {
posix.EINTR => continue,
@ -187,7 +198,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
else => unexpectedErrorPosix(err),
};
}
index += amt_written;
index += rc;
}
}
@ -205,10 +216,16 @@ pub const PosixWriteError = error {
};
/// Calls POSIX write, and keeps trying if it gets interrupted.
pub fn posixWrite(fd: i32, bytes: []const u8) PosixWriteError!void {
while (true) {
const write_ret = posix.write(fd, bytes.ptr, bytes.len);
const write_err = posix.getErrno(write_ret);
pub fn posixWrite(fd: i32, bytes: []const u8) !void {
// Linux can return EINVAL when write amount is > 0x7ffff000
// See https://github.com/zig-lang/zig/pull/743#issuecomment-363165856
const max_bytes_len = 0x7ffff000;
var index: usize = 0;
while (index < bytes.len) {
const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
const rc = posix.write(fd, &bytes[index], amt_to_write);
const write_err = posix.getErrno(rc);
if (write_err > 0) {
return switch (write_err) {
posix.EINTR => continue,
@ -225,7 +242,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) PosixWriteError!void {
else => unexpectedErrorPosix(write_err),
};
}
return;
index += rc;
}
}
@ -272,8 +289,12 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
mem.copy(u8, path0, file_path);
path0[file_path.len] = 0;
return posixOpenC(path0.ptr, flags, perm);
}
pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) !i32 {
while (true) {
const result = posix.open(path0.ptr, flags, perm);
const result = posix.open(file_path, flags, perm);
const err = posix.getErrno(result);
if (err > 0) {
return switch (err) {
@ -1562,10 +1583,10 @@ test "std.os" {
_ = @import("darwin_errno.zig");
_ = @import("darwin.zig");
_ = @import("get_user_id.zig");
_ = @import("linux_errno.zig");
_ = @import("linux/errno.zig");
//_ = @import("linux_i386.zig");
_ = @import("linux_x86_64.zig");
_ = @import("linux.zig");
_ = @import("linux/x86_64.zig");
_ = @import("linux/index.zig");
_ = @import("path.zig");
_ = @import("windows/index.zig");
}
@ -1600,12 +1621,22 @@ pub fn openSelfExe() !io.File {
return io.File.openRead("/proc/self/exe", null);
},
Os.macosx, Os.ios => {
@panic("TODO: openSelfExe on Darwin");
var fixed_buffer_mem: [darwin.PATH_MAX]u8 = undefined;
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
const self_exe_path = try selfExePath(&fixed_allocator.allocator);
return io.File.openRead(self_exe_path, null);
},
else => @compileError("Unsupported OS"),
}
}
test "openSelfExe" {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios => (try openSelfExe()).close(),
else => return, // Unsupported OS.
}
}
/// Get the path to the current executable.
/// If you only need the directory, use selfExeDirPath.
/// If you only want an open file handle, use openSelfExe.

View File

@ -1,4 +1,5 @@
const linux = @import("linux.zig");
const std = @import("../../index.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;

View File

@ -1,12 +1,12 @@
const std = @import("../index.zig");
const std = @import("../../index.zig");
const assert = std.debug.assert;
const builtin = @import("builtin");
const arch = switch (builtin.arch) {
builtin.Arch.x86_64 => @import("linux_x86_64.zig"),
builtin.Arch.i386 => @import("linux_i386.zig"),
builtin.Arch.x86_64 => @import("x86_64.zig"),
builtin.Arch.i386 => @import("i386.zig"),
else => @compileError("unsupported arch"),
};
pub use @import("linux_errno.zig");
pub use @import("errno.zig");
pub const PATH_MAX = 4096;
@ -787,10 +787,10 @@ pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_va
return arch.syscall4(arch.SYS_timerfd_settime, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value));
}
test "import linux_test" {
test "import linux test" {
// TODO lazy analysis should prevent this test from being compiled on windows, but
// it is still compiled on windows
if (builtin.os == builtin.Os.linux) {
_ = @import("linux_test.zig");
_ = @import("test.zig");
}
}

View File

@ -1,4 +1,4 @@
const std = @import("std");
const std = @import("../../index.zig");
const linux = std.os.linux;
const assert = std.debug.assert;

View File

@ -1,4 +1,5 @@
const linux = @import("linux.zig");
const std = @import("../../index.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;

View File

@ -156,6 +156,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: var) !void {
\\
\\General Options:
\\ --help Print this help and exit
\\ --init Generate a build.zig template
\\ --verbose Print commands before executing them
\\ --prefix [path] Override default install prefix
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers

View File

@ -20,6 +20,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
".tmp_source.zig:3:5: error: duplicate error: 'Bar'",
".tmp_source.zig:2:5: note: other error here");
cases.add("cast negative integer literal to usize",
\\export fn entry() void {
\\ const x = usize(-10);
\\}
, ".tmp_source.zig:2:21: error: cannot cast negative value -10 to unsigned integer type 'usize'");
cases.add("use invalid number literal as array index",
\\var v = 25;
\\export fn entry() void {
\\ var arr: [v]u8 = undefined;
\\}
, ".tmp_source.zig:1:1: error: unable to infer variable type");
cases.add("duplicate struct field",
\\const Foo = struct {
\\ Bar: i32,