authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-09 12:12:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-09 12:12:37-04:00
log05f1ea33d2d2f4ffa2bb6686a6a938d1b7983074
tree4c756014c37eb0299914b155193b6b2ba04dc652
parent2ee67b7642cfeef36d8ebbc08080202b5b1d1958

ZIG_DEBUG_COLOR=1 overrides tty detection for runtime stack traces


3 files changed, 36 insertions(+), 18 deletions(-)

doc/docgen.zig+16-13
......@@ -689,7 +689,10 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
689689fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
690690 var code_progress_index: usize = 0;
691691
692 const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, zig_exe));
692 var env_map = try os.getEnvMap(allocator);
693 try env_map.set("ZIG_DEBUG_COLOR", "1");
694
695 const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, &env_map, zig_exe));
693696
694697 for (toc.nodes) |node| {
695698 switch (node) {
......@@ -778,12 +781,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
778781 try build_args.append("c");
779782 try out.print(" --library c");
780783 }
781 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
784 _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
782785
783786 const run_args = [][]const u8{tmp_bin_file_name};
784787
785788 const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
786 const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size);
789 const result = try os.ChildProcess.exec(allocator, run_args, null, &env_map, max_doc_file_size);
787790 switch (result.term) {
788791 os.ChildProcess.Term.Exited => |exit_code| {
789792 if (exit_code == 0) {
......@@ -799,7 +802,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
799802 }
800803 break :blk result;
801804 } else blk: {
802 break :blk exec(allocator, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
805 break :blk exec(allocator, &env_map, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
803806 };
804807
805808 const escaped_stderr = try escapeHtml(allocator, result.stderr);
......@@ -845,7 +848,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
845848 "msvc",
846849 });
847850 }
848 const result = exec(allocator, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
851 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
849852 const escaped_stderr = try escapeHtml(allocator, result.stderr);
850853 const escaped_stdout = try escapeHtml(allocator, result.stdout);
851854 try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout);
......@@ -877,7 +880,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
877880 try out.print(" --release-small");
878881 },
879882 }
880 const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size);
883 const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, &env_map, max_doc_file_size);
881884 switch (result.term) {
882885 os.ChildProcess.Term.Exited => |exit_code| {
883886 if (exit_code == 0) {
......@@ -923,7 +926,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
923926 builtin.Mode.ReleaseSmall => try test_args.append("--release-small"),
924927 }
925928
926 const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size);
929 const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, &env_map, max_doc_file_size);
927930 switch (result.term) {
928931 os.ChildProcess.Term.Exited => |exit_code| {
929932 if (exit_code == 0) {
......@@ -1000,7 +1003,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10001003 }
10011004
10021005 if (maybe_error_match) |error_match| {
1003 const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, null, max_doc_file_size);
1006 const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size);
10041007 switch (result.term) {
10051008 os.ChildProcess.Term.Exited => |exit_code| {
10061009 if (exit_code == 0) {
......@@ -1032,7 +1035,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10321035 try out.print("</code></pre>\n");
10331036 }
10341037 } else {
1035 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
1038 _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
10361039 }
10371040 if (!code.is_inline) {
10381041 try out.print("</code></pre>\n");
......@@ -1045,8 +1048,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10451048 }
10461049}
10471050
1048fn exec(allocator: *mem.Allocator, args: []const []const u8) !os.ChildProcess.ExecResult {
1049 const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
1051fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u8) !os.ChildProcess.ExecResult {
1052 const result = try os.ChildProcess.exec(allocator, args, null, env_map, max_doc_file_size);
10501053 switch (result.term) {
10511054 os.ChildProcess.Term.Exited => |exit_code| {
10521055 if (exit_code != 0) {
......@@ -1070,8 +1073,8 @@ fn exec(allocator: *mem.Allocator, args: []const []const u8) !os.ChildProcess.Ex
10701073 return result;
10711074}
10721075
1073fn getBuiltinCode(allocator: *mem.Allocator, zig_exe: []const u8) ![]const u8 {
1074 const result = try exec(allocator, []const []const u8{
1076fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
1077 const result = try exec(allocator, env_map, []const []const u8{
10751078 zig_exe,
10761079 "builtin",
10771080 });
std/debug/index.zig+9-2
......@@ -10,6 +10,7 @@ const ArrayList = std.ArrayList;
1010const builtin = @import("builtin");
1111
1212pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
13pub const failing_allocator = FailingAllocator.init(global_allocator, 0);
1314
1415/// Tries to write to stderr, unbuffered, and ignores any error returned.
1516/// Does not append a newline.
......@@ -44,6 +45,12 @@ pub fn getSelfDebugInfo() !*ElfStackTrace {
4445 }
4546}
4647
48fn wantTtyColor() bool {
49 var bytes: [128]u8 = undefined;
50 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
51 return if (std.os.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| true else |_| stderr_file.isTty();
52}
53
4754/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
4855pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
4956 const stderr = getStderrStream() catch return;
......@@ -51,7 +58,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
5158 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
5259 return;
5360 };
54 writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty(), start_addr) catch |err| {
61 writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, wantTtyColor(), start_addr) catch |err| {
5562 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
5663 return;
5764 };
......@@ -64,7 +71,7 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {
6471 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
6572 return;
6673 };
67 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty()) catch |err| {
74 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, wantTtyColor()) catch |err| {
6875 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
6976 return;
7077 };
std/os/index.zig+11-3
......@@ -544,8 +544,13 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
544544 return null;
545545}
546546
547pub const GetEnvVarOwnedError = error{
548 OutOfMemory,
549 EnvironmentVariableNotFound,
550};
551
547552/// Caller must free returned memory.
548pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) ![]u8 {
553pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
549554 if (is_windows) {
550555 const key_with_null = try cstr.addNullByte(allocator, key);
551556 defer allocator.free(key_with_null);
......@@ -554,14 +559,17 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) ![]u8 {
554559 errdefer allocator.free(buf);
555560
556561 while (true) {
557 const windows_buf_len = try math.cast(windows.DWORD, buf.len);
562 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
558563 const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);
559564
560565 if (result == 0) {
561566 const err = windows.GetLastError();
562567 return switch (err) {
563568 windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound,
564 else => unexpectedErrorWindows(err),
569 else => {
570 _ = unexpectedErrorWindows(err);
571 return error.EnvironmentVariableNotFound;
572 },
565573 };
566574 }
567575