| author | |
| committer | |
| log | 8ab5313043dad325488d4491a30642696dc7bbcf |
| tree | 462f0b9d7cae35f0bf6277da49b5d0784ab618a2 |
| parent | 55e8bbd1671f9c8e2f195f8f27a4cbe32665253e |
6 files changed, 135 insertions(+), 20 deletions(-)
std/build.zig+13-3| ... | @@ -308,7 +308,7 @@ pub const Builder = struct { | ... | @@ -308,7 +308,7 @@ pub const Builder = struct { |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | fn processNixOSEnvVars(self: &Builder) { | 310 | fn processNixOSEnvVars(self: &Builder) { |
| 311 | if (os.getEnv("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { | 311 | if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { |
| 312 | var it = mem.split(nix_cflags_compile, " "); | 312 | var it = mem.split(nix_cflags_compile, " "); |
| 313 | while (true) { | 313 | while (true) { |
| 314 | const word = it.next() ?? break; | 314 | const word = it.next() ?? break; |
| ... | @@ -323,8 +323,10 @@ pub const Builder = struct { | ... | @@ -323,8 +323,10 @@ pub const Builder = struct { |
| 323 | break; | 323 | break; |
| 324 | } | 324 | } |
| 325 | } | 325 | } |
| 326 | } else |err| { | ||
| 327 | assert(err == error.EnvironmentVariableNotFound); | ||
| 326 | } | 328 | } |
| 327 | if (os.getEnv("NIX_LDFLAGS")) |nix_ldflags| { | 329 | if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| { |
| 328 | var it = mem.split(nix_ldflags, " "); | 330 | var it = mem.split(nix_ldflags, " "); |
| 329 | while (true) { | 331 | while (true) { |
| 330 | const word = it.next() ?? break; | 332 | const word = it.next() ?? break; |
| ... | @@ -342,6 +344,8 @@ pub const Builder = struct { | ... | @@ -342,6 +344,8 @@ pub const Builder = struct { |
| 342 | break; | 344 | break; |
| 343 | } | 345 | } |
| 344 | } | 346 | } |
| 347 | } else |err| { | ||
| 348 | assert(err == error.EnvironmentVariableNotFound); | ||
| 345 | } | 349 | } |
| 346 | } | 350 | } |
| 347 | 351 | ||
| ... | @@ -1248,7 +1252,13 @@ pub const LibExeObjStep = struct { | ... | @@ -1248,7 +1252,13 @@ pub const LibExeObjStep = struct { |
| 1248 | } | 1252 | } |
| 1249 | 1253 | ||
| 1250 | fn makeC(self: &LibExeObjStep) -> %void { | 1254 | fn makeC(self: &LibExeObjStep) -> %void { |
| 1251 | const cc = os.getEnv("CC") ?? "cc"; | 1255 | const cc = os.getEnvVarOwned(self.builder.allocator, "CC") %% |err| { |
| 1256 | if (err == error.EnvironmentVariableNotFound) { | ||
| 1257 | ([]const u8)("cc") | ||
| 1258 | } else { | ||
| 1259 | return err | ||
| 1260 | } | ||
| 1261 | }; | ||
| 1252 | const builder = self.builder; | 1262 | const builder = self.builder; |
| 1253 | 1263 | ||
| 1254 | assert(!self.is_zig); | 1264 | assert(!self.is_zig); |
std/os/child_process.zig+2-1| ... | @@ -564,7 +564,7 @@ pub const ChildProcess = struct { | ... | @@ -564,7 +564,7 @@ pub const ChildProcess = struct { |
| 564 | const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; | 564 | const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; |
| 565 | 565 | ||
| 566 | const maybe_envp_buf = if (self.env_map) |env_map| { | 566 | const maybe_envp_buf = if (self.env_map) |env_map| { |
| 567 | %return os.createNullDelimitedEnvMap(self.allocator, env_map) | 567 | %return os.createWindowsEnvBlock(self.allocator, env_map) |
| 568 | } else { | 568 | } else { |
| 569 | null | 569 | null |
| 570 | }; | 570 | }; |
| ... | @@ -578,6 +578,7 @@ pub const ChildProcess = struct { | ... | @@ -578,6 +578,7 @@ pub const ChildProcess = struct { |
| 578 | const err = windows.GetLastError(); | 578 | const err = windows.GetLastError(); |
| 579 | return switch (err) { | 579 | return switch (err) { |
| 580 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, | 580 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, |
| 581 | windows.ERROR.INVALID_PARAMETER => unreachable, | ||
| 581 | else => error.Unexpected, | 582 | else => error.Unexpected, |
| 582 | }; | 583 | }; |
| 583 | } | 584 | } |
std/os/index.zig+77-13| ... | @@ -32,6 +32,7 @@ pub const windowsWrite = windows_util.windowsWrite; | ... | @@ -32,6 +32,7 @@ pub const windowsWrite = windows_util.windowsWrite; |
| 32 | pub const windowsIsTty = windows_util.windowsIsTty; | 32 | pub const windowsIsTty = windows_util.windowsIsTty; |
| 33 | pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; | 33 | pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; |
| 34 | pub const windowsOpen = windows_util.windowsOpen; | 34 | pub const windowsOpen = windows_util.windowsOpen; |
| 35 | pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock; | ||
| 35 | 36 | ||
| 36 | const debug = @import("../debug.zig"); | 37 | const debug = @import("../debug.zig"); |
| 37 | const assert = debug.assert; | 38 | const assert = debug.assert; |
| ... | @@ -48,6 +49,7 @@ const io = @import("../io.zig"); | ... | @@ -48,6 +49,7 @@ const io = @import("../io.zig"); |
| 48 | const base64 = @import("../base64.zig"); | 49 | const base64 = @import("../base64.zig"); |
| 49 | const ArrayList = @import("../array_list.zig").ArrayList; | 50 | const ArrayList = @import("../array_list.zig").ArrayList; |
| 50 | const Buffer = @import("../buffer.zig").Buffer; | 51 | const Buffer = @import("../buffer.zig").Buffer; |
| 52 | const math = @import("../index.zig").math; | ||
| 51 | 53 | ||
| 52 | error Unexpected; | 54 | error Unexpected; |
| 53 | error SystemResources; | 55 | error SystemResources; |
| ... | @@ -362,7 +364,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, | ... | @@ -362,7 +364,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, |
| 362 | return posixExecveErrnoToErr(posix.getErrno(posix.execve(??argv_buf[0], argv_buf.ptr, envp_buf.ptr))); | 364 | return posixExecveErrnoToErr(posix.getErrno(posix.execve(??argv_buf[0], argv_buf.ptr, envp_buf.ptr))); |
| 363 | } | 365 | } |
| 364 | 366 | ||
| 365 | const PATH = getEnv("PATH") ?? "/usr/local/bin:/bin/:/usr/bin"; | 367 | const PATH = getEnvPosix("PATH") ?? "/usr/local/bin:/bin/:/usr/bin"; |
| 366 | // PATH.len because it is >= the largest search_path | 368 | // PATH.len because it is >= the largest search_path |
| 367 | // +1 for the / to join the search path and exe_path | 369 | // +1 for the / to join the search path and exe_path |
| 368 | // +1 for the null terminating byte | 370 | // +1 for the null terminating byte |
| ... | @@ -406,29 +408,55 @@ fn posixExecveErrnoToErr(err: usize) -> error { | ... | @@ -406,29 +408,55 @@ fn posixExecveErrnoToErr(err: usize) -> error { |
| 406 | }; | 408 | }; |
| 407 | } | 409 | } |
| 408 | 410 | ||
| 409 | pub var environ_raw: []&u8 = undefined; | 411 | pub var posix_environ_raw: []&u8 = undefined; |
| 410 | 412 | ||
| 411 | /// Caller must free result when done. | 413 | /// Caller must free result when done. |
| 412 | pub fn getEnvMap(allocator: &Allocator) -> %BufMap { | 414 | pub fn getEnvMap(allocator: &Allocator) -> %BufMap { |
| 413 | var result = BufMap.init(allocator); | 415 | var result = BufMap.init(allocator); |
| 414 | %defer result.deinit(); | 416 | %defer result.deinit(); |
| 415 | 417 | ||
| 416 | for (environ_raw) |ptr| { | 418 | if (is_windows) { |
| 417 | var line_i: usize = 0; | 419 | const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory; |
| 418 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 420 | defer assert(windows.FreeEnvironmentStringsA(ptr)); |
| 419 | const key = ptr[0..line_i]; | ||
| 420 | 421 | ||
| 421 | var end_i: usize = line_i; | 422 | var i: usize = 0; |
| 422 | while (ptr[end_i] != 0) : (end_i += 1) {} | 423 | while (true) { |
| 423 | const value = ptr[line_i + 1..end_i]; | 424 | if (ptr[i] == 0) |
| 425 | return result; | ||
| 426 | |||
| 427 | const key_start = i; | ||
| 428 | |||
| 429 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | ||
| 430 | const key = ptr[key_start..i]; | ||
| 424 | 431 | ||
| 425 | %return result.set(key, value); | 432 | if (ptr[i] == '=') i += 1; |
| 433 | |||
| 434 | const value_start = i; | ||
| 435 | while (ptr[i] != 0) : (i += 1) {} | ||
| 436 | const value = ptr[value_start..i]; | ||
| 437 | |||
| 438 | i += 1; // skip over null byte | ||
| 439 | |||
| 440 | %return result.set(key, value); | ||
| 441 | } | ||
| 442 | } else { | ||
| 443 | for (posix_environ_raw) |ptr| { | ||
| 444 | var line_i: usize = 0; | ||
| 445 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | ||
| 446 | const key = ptr[0..line_i]; | ||
| 447 | |||
| 448 | var end_i: usize = line_i; | ||
| 449 | while (ptr[end_i] != 0) : (end_i += 1) {} | ||
| 450 | const value = ptr[line_i + 1..end_i]; | ||
| 451 | |||
| 452 | %return result.set(key, value); | ||
| 453 | } | ||
| 454 | return result; | ||
| 426 | } | 455 | } |
| 427 | return result; | ||
| 428 | } | 456 | } |
| 429 | 457 | ||
| 430 | pub fn getEnv(key: []const u8) -> ?[]const u8 { | 458 | pub fn getEnvPosix(key: []const u8) -> ?[]const u8 { |
| 431 | for (environ_raw) |ptr| { | 459 | for (posix_environ_raw) |ptr| { |
| 432 | var line_i: usize = 0; | 460 | var line_i: usize = 0; |
| 433 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 461 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| 434 | const this_key = ptr[0..line_i]; | 462 | const this_key = ptr[0..line_i]; |
| ... | @@ -444,6 +472,42 @@ pub fn getEnv(key: []const u8) -> ?[]const u8 { | ... | @@ -444,6 +472,42 @@ pub fn getEnv(key: []const u8) -> ?[]const u8 { |
| 444 | return null; | 472 | return null; |
| 445 | } | 473 | } |
| 446 | 474 | ||
| 475 | error EnvironmentVariableNotFound; | ||
| 476 | |||
| 477 | /// Caller must free returned memory. | ||
| 478 | pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 { | ||
| 479 | if (is_windows) { | ||
| 480 | const key_with_null = %return cstr.addNullByte(allocator, key); | ||
| 481 | defer allocator.free(key_with_null); | ||
| 482 | |||
| 483 | var buf = %return allocator.alloc(u8, 256); | ||
| 484 | %defer allocator.free(buf); | ||
| 485 | |||
| 486 | while (true) { | ||
| 487 | const windows_buf_len = %return math.cast(windows.DWORD, buf.len); | ||
| 488 | const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len); | ||
| 489 | |||
| 490 | if (result == 0) { | ||
| 491 | const err = windows.GetLastError(); | ||
| 492 | return switch (err) { | ||
| 493 | windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound, | ||
| 494 | else => error.Unexpected, | ||
| 495 | }; | ||
| 496 | } | ||
| 497 | |||
| 498 | if (result > buf.len) { | ||
| 499 | buf = %return allocator.realloc(u8, buf, result); | ||
| 500 | continue; | ||
| 501 | } | ||
| 502 | |||
| 503 | return allocator.shrink(u8, buf, result); | ||
| 504 | } | ||
| 505 | } else { | ||
| 506 | const result = getEnvPosix(key) ?? return error.EnvironmentVariableNotFound; | ||
| 507 | return mem.dupe(u8, allocator, result); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 447 | /// Caller must free the returned memory. | 511 | /// Caller must free the returned memory. |
| 448 | pub fn getCwd(allocator: &Allocator) -> %[]u8 { | 512 | pub fn getCwd(allocator: &Allocator) -> %[]u8 { |
| 449 | switch (builtin.os) { | 513 | switch (builtin.os) { |
std/os/windows/index.zig+9-2| ... | @@ -32,12 +32,18 @@ pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) -> bool; | ... | @@ -32,12 +32,18 @@ pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) -> bool; |
| 32 | 32 | ||
| 33 | pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) -> noreturn; | 33 | pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) -> noreturn; |
| 34 | 34 | ||
| 35 | pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPCH) -> BOOL; | ||
| 36 | |||
| 35 | pub extern "kernel32" stdcallcc fn GetCommandLineA() -> LPSTR; | 37 | pub extern "kernel32" stdcallcc fn GetCommandLineA() -> LPSTR; |
| 36 | 38 | ||
| 37 | pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool; | 39 | pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool; |
| 38 | 40 | ||
| 39 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) -> DWORD; | 41 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) -> DWORD; |
| 40 | 42 | ||
| 43 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() -> ?LPCH; | ||
| 44 | |||
| 45 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) -> DWORD; | ||
| 46 | |||
| 41 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL; | 47 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL; |
| 42 | 48 | ||
| 43 | pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; | 49 | pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; |
| ... | @@ -49,11 +55,11 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE | ... | @@ -49,11 +55,11 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE |
| 49 | pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR, | 55 | pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR, |
| 50 | cchFilePath: DWORD, dwFlags: DWORD) -> DWORD; | 56 | cchFilePath: DWORD, dwFlags: DWORD) -> DWORD; |
| 51 | 57 | ||
| 52 | pub extern "kernel32" stdcallcc fn GetProcessHeap() -> HANDLE; | 58 | pub extern "kernel32" stdcallcc fn GetProcessHeap() -> ?HANDLE; |
| 53 | 59 | ||
| 54 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE; | 60 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE; |
| 55 | 61 | ||
| 56 | pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; | 62 | pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> ?LPVOID; |
| 57 | 63 | ||
| 58 | pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; | 64 | pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; |
| 59 | 65 | ||
| ... | @@ -91,6 +97,7 @@ pub const HCRYPTPROV = ULONG_PTR; | ... | @@ -91,6 +97,7 @@ pub const HCRYPTPROV = ULONG_PTR; |
| 91 | pub const HINSTANCE = &@OpaqueType(); | 97 | pub const HINSTANCE = &@OpaqueType(); |
| 92 | pub const INT = c_int; | 98 | pub const INT = c_int; |
| 93 | pub const LPBYTE = &BYTE; | 99 | pub const LPBYTE = &BYTE; |
| 100 | pub const LPCH = &CHAR; | ||
| 94 | pub const LPCSTR = &const CHAR; | 101 | pub const LPCSTR = &const CHAR; |
| 95 | pub const LPCTSTR = &const TCHAR; | 102 | pub const LPCTSTR = &const TCHAR; |
| 96 | pub const LPCVOID = &const c_void; | 103 | pub const LPCVOID = &const c_void; |
std/os/windows/util.zig+33| ... | @@ -3,6 +3,7 @@ const os = std.os; | ... | @@ -3,6 +3,7 @@ const os = std.os; |
| 3 | const windows = std.os.windows; | 3 | const windows = std.os.windows; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const BufMap = std.BufMap; | ||
| 6 | 7 | ||
| 7 | error WaitAbandoned; | 8 | error WaitAbandoned; |
| 8 | error WaitTimeOut; | 9 | error WaitTimeOut; |
| ... | @@ -111,3 +112,35 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m | ... | @@ -111,3 +112,35 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m |
| 111 | 112 | ||
| 112 | return result; | 113 | return result; |
| 113 | } | 114 | } |
| 115 | |||
| 116 | /// Caller must free result. | ||
| 117 | pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) -> %[]u8 { | ||
| 118 | // count bytes needed | ||
| 119 | const bytes_needed = { | ||
| 120 | var bytes_needed: usize = 1; // 1 for the final null byte | ||
| 121 | var it = env_map.iterator(); | ||
| 122 | while (it.next()) |pair| { | ||
| 123 | // +1 for '=' | ||
| 124 | // +1 for null byte | ||
| 125 | bytes_needed += pair.key.len + pair.value.len + 2; | ||
| 126 | } | ||
| 127 | bytes_needed | ||
| 128 | }; | ||
| 129 | const result = %return allocator.alloc(u8, bytes_needed); | ||
| 130 | %defer allocator.free(result); | ||
| 131 | |||
| 132 | var it = env_map.iterator(); | ||
| 133 | var i: usize = 0; | ||
| 134 | while (it.next()) |pair| { | ||
| 135 | mem.copy(u8, result[i..], pair.key); | ||
| 136 | i += pair.key.len; | ||
| 137 | result[i] = '='; | ||
| 138 | i += 1; | ||
| 139 | mem.copy(u8, result[i..], pair.value); | ||
| 140 | i += pair.value.len; | ||
| 141 | result[i] = 0; | ||
| 142 | i += 1; | ||
| 143 | } | ||
| 144 | result[i] = 0; | ||
| 145 | return result; | ||
| 146 | } |
std/special/bootstrap.zig+1-1| ... | @@ -56,7 +56,7 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { | ... | @@ -56,7 +56,7 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { |
| 56 | 56 | ||
| 57 | var env_count: usize = 0; | 57 | var env_count: usize = 0; |
| 58 | while (envp[env_count] != null) : (env_count += 1) {} | 58 | while (envp[env_count] != null) : (env_count += 1) {} |
| 59 | std.os.environ_raw = @ptrCast(&&u8, envp)[0..env_count]; | 59 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; |
| 60 | 60 | ||
| 61 | std.debug.user_main_fn = root.main; | 61 | std.debug.user_main_fn = root.main; |
| 62 | 62 |