| author | |
| committer | |
| log | 1c6000d0474a89bbc48897fc2f2f2d7331e2fe4e |
| tree | fa74f0cd662d01d03d0cbd3a1459404796414d79 |
| parent | 72fb2443e0e5dd0c8c3a0265428832796b4ff548 |
* add std.buf_map.BufMap
* add std.buf_set.BufSet
* add std.mem.split
* zig build system improvements (See #204)
- automatically parses NIX_CFLAGS_COMPILE and NIX_LDFLAGS
- add builder.addCIncludePath
- add builder.addRPath
- add builder.addLibPath
- add exe.linkLibrary9 files changed, 297 insertions(+), 91 deletions(-)
CMakeLists.txt+2| ... | ... | @@ -204,6 +204,8 @@ install(TARGETS zig DESTINATION bin) |
| 204 | 204 | |
| 205 | 205 | install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST}) |
| 206 | 206 | |
| 207 | install(FILES "${CMAKE_SOURCE_DIR}/std/buf_map.zig" DESTINATION "${ZIG_STD_DEST}") | |
| 208 | install(FILES "${CMAKE_SOURCE_DIR}/std/buf_set.zig" DESTINATION "${ZIG_STD_DEST}") | |
| 207 | 209 | install(FILES "${CMAKE_SOURCE_DIR}/std/build.zig" DESTINATION "${ZIG_STD_DEST}") |
| 208 | 210 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/darwin.zig" DESTINATION "${ZIG_STD_DEST}/c") |
| 209 | 211 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/index.zig" DESTINATION "${ZIG_STD_DEST}/c") |
src/main.cpp+1-1| ... | ... | @@ -195,7 +195,7 @@ int main(int argc, char **argv) { |
| 195 | 195 | fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n"); |
| 196 | 196 | fprintf(stderr, "./build"); |
| 197 | 197 | for (size_t i = 0; i < args.length; i += 1) { |
| 198 | fprintf(stderr, " \"%s\"", args.at(i)); | |
| 198 | fprintf(stderr, " %s", args.at(i)); | |
| 199 | 199 | } |
| 200 | 200 | fprintf(stderr, "\n"); |
| 201 | 201 | } |
std/buf_map.zig created+71| ... | ... | @@ -0,0 +1,71 @@ |
| 1 | const HashMap = @import("hash_map.zig").HashMap; | |
| 2 | const mem = @import("mem.zig"); | |
| 3 | const Allocator = mem.Allocator; | |
| 4 | ||
| 5 | /// BufMap copies keys and values before they go into the map, and | |
| 6 | /// frees them when they get removed. | |
| 7 | pub const BufMap = struct { | |
| 8 | hash_map: BufMapHashMap, | |
| 9 | ||
| 10 | const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); | |
| 11 | ||
| 12 | pub fn init(allocator: &Allocator) -> BufMap { | |
| 13 | var self = BufMap { | |
| 14 | .hash_map = undefined, | |
| 15 | }; | |
| 16 | self.hash_map.init(allocator); | |
| 17 | return self; | |
| 18 | } | |
| 19 | ||
| 20 | pub fn deinit(self: &BufMap) { | |
| 21 | var it = self.hash_map.entryIterator(); | |
| 22 | while (true) { | |
| 23 | const entry = it.next() ?? break; | |
| 24 | self.free(entry.key); | |
| 25 | self.free(entry.value); | |
| 26 | } | |
| 27 | ||
| 28 | self.hash_map.deinit(); | |
| 29 | } | |
| 30 | ||
| 31 | pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void { | |
| 32 | if (const entry ?= self.hash_map.get(key)) { | |
| 33 | const value_copy = %return self.copy(value); | |
| 34 | %defer self.free(value_copy); | |
| 35 | %return self.hash_map.put(key, value_copy); | |
| 36 | self.free(entry.value); | |
| 37 | } else { | |
| 38 | const key_copy = %return self.copy(key); | |
| 39 | %defer self.free(key_copy); | |
| 40 | const value_copy = %return self.copy(value); | |
| 41 | %defer self.free(value_copy); | |
| 42 | %return self.hash_map.put(key_copy, value_copy); | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 | pub fn delete(self: &BufMap, key: []const u8) { | |
| 47 | const entry = self.hash_map.remove(key) ?? return; | |
| 48 | self.free(entry.key); | |
| 49 | self.free(entry.value); | |
| 50 | } | |
| 51 | ||
| 52 | pub fn count(self: &const BufMap) -> usize { | |
| 53 | return self.hash_map.size; | |
| 54 | } | |
| 55 | ||
| 56 | pub fn iterator(self: &const BufMap) -> BufMapHashMap.Iterator { | |
| 57 | return self.hash_map.entryIterator(); | |
| 58 | } | |
| 59 | ||
| 60 | fn free(self: &BufMap, value: []const u8) { | |
| 61 | // remove the const | |
| 62 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | |
| 63 | self.hash_map.allocator.free(mut_value); | |
| 64 | } | |
| 65 | ||
| 66 | fn copy(self: &BufMap, value: []const u8) -> %[]const u8 { | |
| 67 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | |
| 68 | mem.copy(u8, result, value); | |
| 69 | return result; | |
| 70 | } | |
| 71 | }; |
std/buf_set.zig created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | const HashMap = @import("hash_map.zig").HashMap; | |
| 2 | const mem = @import("mem.zig"); | |
| 3 | const Allocator = mem.Allocator; | |
| 4 | ||
| 5 | pub const BufSet = struct { | |
| 6 | hash_map: BufSetHashMap, | |
| 7 | ||
| 8 | const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | |
| 9 | ||
| 10 | pub fn init(allocator: &Allocator) -> BufSet { | |
| 11 | var self = BufSet { | |
| 12 | .hash_map = undefined, | |
| 13 | }; | |
| 14 | self.hash_map.init(allocator); | |
| 15 | return self; | |
| 16 | } | |
| 17 | ||
| 18 | pub fn deinit(self: &BufSet) { | |
| 19 | var it = self.hash_map.entryIterator(); | |
| 20 | while (true) { | |
| 21 | const entry = it.next() ?? break; | |
| 22 | self.free(entry.key); | |
| 23 | } | |
| 24 | ||
| 25 | self.hash_map.deinit(); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn put(self: &BufSet, key: []const u8) -> %void { | |
| 29 | if (self.hash_map.get(key) == null) { | |
| 30 | const key_copy = %return self.copy(key); | |
| 31 | %defer self.free(key_copy); | |
| 32 | %return self.hash_map.put(key_copy, {}); | |
| 33 | } | |
| 34 | } | |
| 35 | ||
| 36 | pub fn delete(self: &BufSet, key: []const u8) { | |
| 37 | const entry = self.hash_map.remove(key) ?? return; | |
| 38 | self.free(entry.key); | |
| 39 | } | |
| 40 | ||
| 41 | pub fn count(self: &const BufSet) -> usize { | |
| 42 | return self.hash_map.size; | |
| 43 | } | |
| 44 | ||
| 45 | pub fn iterator(self: &const BufSet) -> BufSetHashMap.Iterator { | |
| 46 | return self.hash_map.entryIterator(); | |
| 47 | } | |
| 48 | ||
| 49 | fn free(self: &BufSet, value: []const u8) { | |
| 50 | // remove the const | |
| 51 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | |
| 52 | self.hash_map.allocator.free(mut_value); | |
| 53 | } | |
| 54 | ||
| 55 | fn copy(self: &BufSet, value: []const u8) -> %[]const u8 { | |
| 56 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | |
| 57 | mem.copy(u8, result, value); | |
| 58 | return result; | |
| 59 | } | |
| 60 | }; | |
| 61 |
std/build.zig+110-5| ... | ... | @@ -6,6 +6,7 @@ const Allocator = @import("mem.zig").Allocator; |
| 6 | 6 | const os = @import("os/index.zig"); |
| 7 | 7 | const StdIo = os.ChildProcess.StdIo; |
| 8 | 8 | const Term = os.ChildProcess.Term; |
| 9 | const BufSet = @import("buf_set.zig").BufSet; | |
| 9 | 10 | |
| 10 | 11 | error ExtraArg; |
| 11 | 12 | error UncleanExit; |
| ... | ... | @@ -14,13 +15,28 @@ pub const Builder = struct { |
| 14 | 15 | zig_exe: []const u8, |
| 15 | 16 | allocator: &Allocator, |
| 16 | 17 | exe_list: List(&Exe), |
| 18 | lib_paths: List([]const u8), | |
| 19 | include_paths: List([]const u8), | |
| 20 | rpaths: List([]const u8), | |
| 17 | 21 | |
| 18 | 22 | pub fn init(zig_exe: []const u8, allocator: &Allocator) -> Builder { |
| 19 | Builder { | |
| 23 | var self = Builder { | |
| 20 | 24 | .zig_exe = zig_exe, |
| 21 | 25 | .allocator = allocator, |
| 22 | 26 | .exe_list = List(&Exe).init(allocator), |
| 23 | } | |
| 27 | .lib_paths = List([]const u8).init(allocator), | |
| 28 | .include_paths = List([]const u8).init(allocator), | |
| 29 | .rpaths = List([]const u8).init(allocator), | |
| 30 | }; | |
| 31 | self.processNixOSEnvVars(); | |
| 32 | return self; | |
| 33 | } | |
| 34 | ||
| 35 | pub fn deinit(self: &Builder) { | |
| 36 | self.exe_list.deinit(); | |
| 37 | self.lib_paths.deinit(); | |
| 38 | self.include_paths.deinit(); | |
| 39 | self.rpaths.deinit(); | |
| 24 | 40 | } |
| 25 | 41 | |
| 26 | 42 | pub fn addExe(self: &Builder, root_src: []const u8, name: []const u8) -> &Exe { |
| ... | ... | @@ -34,11 +50,24 @@ pub const Builder = struct { |
| 34 | 50 | .name = name, |
| 35 | 51 | .target = Target.Native, |
| 36 | 52 | .linker_script = LinkerScript.None, |
| 53 | .link_libs = BufSet.init(self.allocator), | |
| 37 | 54 | }; |
| 38 | 55 | %return self.exe_list.append(exe); |
| 39 | 56 | return exe; |
| 40 | 57 | } |
| 41 | 58 | |
| 59 | pub fn addCIncludePath(self: &Builder, path: []const u8) { | |
| 60 | %%self.include_paths.append(path); | |
| 61 | } | |
| 62 | ||
| 63 | pub fn addRPath(self: &Builder, path: []const u8) { | |
| 64 | %%self.rpaths.append(path); | |
| 65 | } | |
| 66 | ||
| 67 | pub fn addLibPath(self: &Builder, path: []const u8) { | |
| 68 | %%self.lib_paths.append(path); | |
| 69 | } | |
| 70 | ||
| 42 | 71 | pub fn make(self: &Builder, leftover_arg_index: usize) -> %void { |
| 43 | 72 | var env_map = %return os.getEnvMap(self.allocator); |
| 44 | 73 | |
| ... | ... | @@ -96,18 +125,85 @@ pub const Builder = struct { |
| 96 | 125 | }, |
| 97 | 126 | } |
| 98 | 127 | |
| 99 | printInvocation(self.zig_exe, zig_args); | |
| 128 | { | |
| 129 | var it = exe.link_libs.iterator(); | |
| 130 | while (true) { | |
| 131 | const entry = it.next() ?? break; | |
| 132 | %return zig_args.append("--library"[0...]); // TODO issue #296 | |
| 133 | %return zig_args.append(entry.key); | |
| 134 | } | |
| 135 | } | |
| 136 | ||
| 137 | for (self.include_paths.toSliceConst()) |include_path| { | |
| 138 | %return zig_args.append("-isystem"[0...]); // TODO issue #296 | |
| 139 | %return zig_args.append(include_path); | |
| 140 | } | |
| 141 | ||
| 142 | for (self.rpaths.toSliceConst()) |rpath| { | |
| 143 | %return zig_args.append("-rpath"[0...]); // TODO issue #296 | |
| 144 | %return zig_args.append(rpath); | |
| 145 | } | |
| 146 | ||
| 147 | for (self.lib_paths.toSliceConst()) |lib_path| { | |
| 148 | %return zig_args.append("--library-path"[0...]); // TODO issue #296 | |
| 149 | %return zig_args.append(lib_path); | |
| 150 | } | |
| 151 | ||
| 100 | 152 | // TODO issue #301 |
| 101 | 153 | var child = %return os.ChildProcess.spawn(self.zig_exe, zig_args.toSliceConst(), &env_map, |
| 102 | 154 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator); |
| 103 | 155 | const term = %return child.wait(); |
| 104 | switch (term) { | |
| 156 | const exe_result = switch (term) { | |
| 105 | 157 | Term.Clean => |code| { |
| 106 | 158 | if (code != 0) { |
| 159 | %%io.stderr.printf("\nCompile failed with code {}. To reproduce:\n", code); | |
| 160 | printInvocation(self.zig_exe, zig_args); | |
| 107 | 161 | return error.UncleanExit; |
| 108 | 162 | } |
| 109 | 163 | }, |
| 110 | else => return error.UncleanExit, | |
| 164 | else => { | |
| 165 | %%io.stderr.printf("\nCompile crashed. To reproduce:\n"); | |
| 166 | printInvocation(self.zig_exe, zig_args); | |
| 167 | return error.UncleanExit; | |
| 168 | }, | |
| 169 | }; | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 173 | fn processNixOSEnvVars(self: &Builder) { | |
| 174 | if (const nix_cflags_compile ?= os.getEnv("NIX_CFLAGS_COMPILE")) { | |
| 175 | var it = mem.split(nix_cflags_compile, ' '); | |
| 176 | while (true) { | |
| 177 | const word = it.next() ?? break; | |
| 178 | if (mem.eql(u8, word, "-isystem")) { | |
| 179 | const include_path = it.next() ?? { | |
| 180 | %%io.stderr.printf("Expected argument after -isystem in NIX_CFLAGS_COMPILE\n"); | |
| 181 | break; | |
| 182 | }; | |
| 183 | self.addCIncludePath(include_path); | |
| 184 | } else { | |
| 185 | %%io.stderr.printf("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}\n", word); | |
| 186 | break; | |
| 187 | } | |
| 188 | } | |
| 189 | } | |
| 190 | if (const nix_ldflags ?= os.getEnv("NIX_LDFLAGS")) { | |
| 191 | var it = mem.split(nix_ldflags, ' '); | |
| 192 | while (true) { | |
| 193 | const word = it.next() ?? break; | |
| 194 | if (mem.eql(u8, word, "-rpath")) { | |
| 195 | const rpath = it.next() ?? { | |
| 196 | %%io.stderr.printf("Expected argument after -rpath in NIX_LDFLAGS\n"); | |
| 197 | break; | |
| 198 | }; | |
| 199 | self.addRPath(rpath); | |
| 200 | } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') { | |
| 201 | const lib_path = word[2...]; | |
| 202 | self.addLibPath(lib_path); | |
| 203 | } else { | |
| 204 | %%io.stderr.printf("Unrecognized C flag from NIX_LDFLAGS: {}\n", word); | |
| 205 | break; | |
| 206 | } | |
| 111 | 207 | } |
| 112 | 208 | } |
| 113 | 209 | } |
| ... | ... | @@ -135,6 +231,11 @@ const Exe = struct { |
| 135 | 231 | name: []const u8, |
| 136 | 232 | target: Target, |
| 137 | 233 | linker_script: LinkerScript, |
| 234 | link_libs: BufSet, | |
| 235 | ||
| 236 | fn deinit(self: &Exe) { | |
| 237 | self.link_libs.deinit(); | |
| 238 | } | |
| 138 | 239 | |
| 139 | 240 | fn setTarget(self: &Exe, target_arch: Arch, target_os: Os, target_environ: Environ) { |
| 140 | 241 | self.target = Target.Cross { |
| ... | ... | @@ -155,6 +256,10 @@ const Exe = struct { |
| 155 | 256 | fn setLinkerScriptPath(self: &Exe, path: []const u8) { |
| 156 | 257 | self.linker_script = LinkerScript.Path { path }; |
| 157 | 258 | } |
| 259 | ||
| 260 | fn linkLibrary(self: &Exe, name: []const u8) { | |
| 261 | %%self.link_libs.put(name); | |
| 262 | } | |
| 158 | 263 | }; |
| 159 | 264 | |
| 160 | 265 | fn handleErr(err: error) -> noreturn { |
std/mem.zig+44| ... | ... | @@ -176,6 +176,49 @@ pub fn writeInt(buf: []u8, value: var, big_endian: bool) { |
| 176 | 176 | assert(bits == 0); |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | ||
| 180 | pub fn hash_slice_u8(k: []const u8) -> u32 { | |
| 181 | // FNV 32-bit hash | |
| 182 | var h: u32 = 2166136261; | |
| 183 | for (k) |b| { | |
| 184 | h = (h ^ b) *% 16777619; | |
| 185 | } | |
| 186 | return h; | |
| 187 | } | |
| 188 | ||
| 189 | pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { | |
| 190 | return eql(u8, a, b); | |
| 191 | } | |
| 192 | ||
| 193 | pub fn split(s: []const u8, c: u8) -> SplitIterator { | |
| 194 | SplitIterator { | |
| 195 | .index = 0, | |
| 196 | .s = s, | |
| 197 | .c = c, | |
| 198 | } | |
| 199 | } | |
| 200 | ||
| 201 | const SplitIterator = struct { | |
| 202 | s: []const u8, | |
| 203 | c: u8, | |
| 204 | index: usize, | |
| 205 | ||
| 206 | pub fn next(self: &SplitIterator) -> ?[]const u8 { | |
| 207 | // move to beginning of token | |
| 208 | while (self.index < self.s.len and self.s[self.index] == self.c; self.index += 1) {} | |
| 209 | const start = self.index; | |
| 210 | if (start == self.s.len) { | |
| 211 | return null; | |
| 212 | } | |
| 213 | ||
| 214 | // move to end of token | |
| 215 | while (self.index < self.s.len and self.s[self.index] != self.c; self.index += 1) {} | |
| 216 | const end = self.index; | |
| 217 | ||
| 218 | return self.s[start...end]; | |
| 219 | } | |
| 220 | }; | |
| 221 | ||
| 179 | 222 | test "testStringEquality" { |
| 180 | 223 | assert(eql(u8, "abcd", "abcd")); |
| 181 | 224 | assert(!eql(u8, "abcdef", "abZdef")); |
| ... | ... | @@ -223,3 +266,4 @@ fn testWriteIntImpl() { |
| 223 | 266 | writeInt(bytes[0...], u16(0x1234), false); |
| 224 | 267 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); |
| 225 | 268 | } |
| 269 |
std/os/child_process.zig+3-2| ... | ... | @@ -6,6 +6,7 @@ const Allocator = mem.Allocator; |
| 6 | 6 | const errno = @import("errno.zig"); |
| 7 | 7 | const debug = @import("../debug.zig"); |
| 8 | 8 | const assert = debug.assert; |
| 9 | const BufMap = @import("../buf_map.zig").BufMap; | |
| 9 | 10 | |
| 10 | 11 | pub const ChildProcess = struct { |
| 11 | 12 | pid: i32, |
| ... | ... | @@ -29,7 +30,7 @@ pub const ChildProcess = struct { |
| 29 | 30 | Close, |
| 30 | 31 | }; |
| 31 | 32 | |
| 32 | pub fn spawn(exe_path: []const u8, args: []const []const u8, env_map: &const os.EnvMap, | |
| 33 | pub fn spawn(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap, | |
| 33 | 34 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess |
| 34 | 35 | { |
| 35 | 36 | switch (@compileVar("os")) { |
| ... | ... | @@ -96,7 +97,7 @@ pub const ChildProcess = struct { |
| 96 | 97 | }; |
| 97 | 98 | } |
| 98 | 99 | |
| 99 | fn spawnPosix(exe_path: []const u8, args: []const []const u8, env_map: &const os.EnvMap, | |
| 100 | fn spawnPosix(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap, | |
| 100 | 101 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess |
| 101 | 102 | { |
| 102 | 103 | // TODO issue #295 |
std/os/index.zig+4-83| ... | ... | @@ -21,7 +21,7 @@ const c = @import("../c/index.zig"); |
| 21 | 21 | const mem = @import("../mem.zig"); |
| 22 | 22 | const Allocator = mem.Allocator; |
| 23 | 23 | |
| 24 | const HashMap = @import("../hash_map.zig").HashMap; | |
| 24 | const BufMap = @import("../buf_map.zig").BufMap; | |
| 25 | 25 | const cstr = @import("../cstr.zig"); |
| 26 | 26 | |
| 27 | 27 | error Unexpected; |
| ... | ... | @@ -204,7 +204,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 204 | 204 | /// It must also convert to KEY=VALUE\0 format for environment variables, and include null |
| 205 | 205 | /// pointers after the args and after the environment variables. |
| 206 | 206 | /// Also make the first arg equal to path. |
| 207 | pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const EnvMap, | |
| 207 | pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const BufMap, | |
| 208 | 208 | allocator: &Allocator) -> %usize |
| 209 | 209 | { |
| 210 | 210 | const path_buf = %return allocator.alloc(u8, path.len + 1); |
| ... | ... | @@ -271,87 +271,8 @@ pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const E |
| 271 | 271 | |
| 272 | 272 | pub var environ_raw: []&u8 = undefined; |
| 273 | 273 | |
| 274 | pub const EnvMap = struct { | |
| 275 | hash_map: EnvHashMap, | |
| 276 | ||
| 277 | const EnvHashMap = HashMap([]const u8, []const u8, hash_slice_u8, eql_slice_u8); | |
| 278 | ||
| 279 | pub fn init(allocator: &Allocator) -> EnvMap { | |
| 280 | var self = EnvMap { | |
| 281 | .hash_map = undefined, | |
| 282 | }; | |
| 283 | self.hash_map.init(allocator); | |
| 284 | return self; | |
| 285 | } | |
| 286 | ||
| 287 | pub fn deinit(self: &EnvMap) { | |
| 288 | var it = self.hash_map.entryIterator(); | |
| 289 | while (true) { | |
| 290 | const entry = it.next() ?? break; | |
| 291 | self.free(entry.key); | |
| 292 | self.free(entry.value); | |
| 293 | } | |
| 294 | ||
| 295 | self.hash_map.deinit(); | |
| 296 | } | |
| 297 | ||
| 298 | pub fn set(self: &EnvMap, key: []const u8, value: []const u8) -> %void { | |
| 299 | if (const entry ?= self.hash_map.get(key)) { | |
| 300 | const value_copy = %return self.copy(value); | |
| 301 | %defer self.free(value_copy); | |
| 302 | %return self.hash_map.put(key, value_copy); | |
| 303 | self.free(entry.value); | |
| 304 | } else { | |
| 305 | const key_copy = %return self.copy(key); | |
| 306 | %defer self.free(key_copy); | |
| 307 | const value_copy = %return self.copy(value); | |
| 308 | %defer self.free(value_copy); | |
| 309 | %return self.hash_map.put(key_copy, value_copy); | |
| 310 | } | |
| 311 | } | |
| 312 | ||
| 313 | pub fn delete(self: &EnvMap, key: []const u8) { | |
| 314 | const entry = self.hash_map.remove(key) ?? return; | |
| 315 | self.free(entry.key); | |
| 316 | self.free(entry.value); | |
| 317 | } | |
| 318 | ||
| 319 | pub fn count(self: &const EnvMap) -> usize { | |
| 320 | return self.hash_map.size; | |
| 321 | } | |
| 322 | ||
| 323 | pub fn iterator(self: &const EnvMap) -> EnvHashMap.Iterator { | |
| 324 | return self.hash_map.entryIterator(); | |
| 325 | } | |
| 326 | ||
| 327 | fn free(self: &EnvMap, value: []const u8) { | |
| 328 | // remove the const | |
| 329 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | |
| 330 | self.hash_map.allocator.free(mut_value); | |
| 331 | } | |
| 332 | ||
| 333 | fn copy(self: &EnvMap, value: []const u8) -> %[]const u8 { | |
| 334 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | |
| 335 | mem.copy(u8, result, value); | |
| 336 | return result; | |
| 337 | } | |
| 338 | ||
| 339 | fn hash_slice_u8(k: []const u8) -> u32 { | |
| 340 | // FNV 32-bit hash | |
| 341 | var h: u32 = 2166136261; | |
| 342 | for (k) |b| { | |
| 343 | h = (h ^ b) *% 16777619; | |
| 344 | } | |
| 345 | return h; | |
| 346 | } | |
| 347 | ||
| 348 | fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { | |
| 349 | return mem.eql(u8, a, b); | |
| 350 | } | |
| 351 | }; | |
| 352 | ||
| 353 | pub fn getEnvMap(allocator: &Allocator) -> %EnvMap { | |
| 354 | var result = EnvMap.init(allocator); | |
| 274 | pub fn getEnvMap(allocator: &Allocator) -> %BufMap { | |
| 275 | var result = BufMap.init(allocator); | |
| 355 | 276 | %defer result.deinit(); |
| 356 | 277 | |
| 357 | 278 | for (environ_raw) |ptr| { |
std/special/build_runner.zig+1| ... | ... | @@ -20,6 +20,7 @@ pub fn main() -> %void { |
| 20 | 20 | defer inc_allocator.deinit(); |
| 21 | 21 | |
| 22 | 22 | var builder = Builder.init(zig_exe, &inc_allocator.allocator); |
| 23 | defer builder.deinit(); | |
| 23 | 24 | root.build(&builder); |
| 24 | 25 | %return builder.make(leftover_arg_index); |
| 25 | 26 | } |