authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-04 22:18:04-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-04 22:45:20-04:00
log2bf1b6840d33a27614630ddb34f53a859fc87345
tree270c9d4b21eb27a8511530938b02f88456b4c94b
parent869167fc6d1f672f2bb827404b0e704223edab41
signaturelock-open Commit is signed but in an unrecognized format.

port std.os.path.resolve to stage1


10 files changed, 601 insertions(+), 55 deletions(-)

src/all_types.hpp+1-1
......@@ -1763,7 +1763,7 @@ struct CodeGen {
17631763
17641764 ZigList<TimeEvent> timing_events;
17651765
1766 Buf *cache_dir;
1766 Buf cache_dir;
17671767 Buf *out_h_path;
17681768
17691769 ZigList<FnTableEntry *> inline_fns;
src/buffer.hpp+5
......@@ -173,4 +173,9 @@ static inline void buf_upcase(Buf *buf) {
173173 }
174174}
175175
176static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
177 return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
178}
179
180
176181#endif
src/codegen.cpp+5-5
......@@ -243,7 +243,7 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
243243 g->root_out_name = out_name;
244244}
245245
246void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir) {
246void codegen_set_cache_dir(CodeGen *g, Buf cache_dir) {
247247 g->cache_dir = cache_dir;
248248}
249249
......@@ -5730,7 +5730,7 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c
57305730
57315731static void ensure_cache_dir(CodeGen *g) {
57325732 int err;
5733 if ((err = os_make_path(g->cache_dir))) {
5733 if ((err = os_make_path(&g->cache_dir))) {
57345734 zig_panic("unable to make cache dir: %s", err_str(err));
57355735 }
57365736}
......@@ -6098,7 +6098,7 @@ static void do_code_gen(CodeGen *g) {
60986098 }
60996099
61006100 Buf *output_path = buf_alloc();
6101 os_path_join(g->cache_dir, o_basename, output_path);
6101 os_path_join(&g->cache_dir, o_basename, output_path);
61026102 ensure_cache_dir(g);
61036103
61046104 bool is_small = g->build_mode == BuildModeSmallRelease;
......@@ -6860,7 +6860,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
68606860
68616861 const char *builtin_zig_basename = "builtin.zig";
68626862 Buf *builtin_zig_path = buf_alloc();
6863 os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
6863 os_path_join(&g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
68646864
68656865 Buf *contents = codegen_generate_builtin_source(g);
68666866 ensure_cache_dir(g);
......@@ -6875,7 +6875,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
68756875
68766876 assert(g->root_package);
68776877 assert(g->std_package);
6878 g->compile_var_package = new_package(buf_ptr(g->cache_dir), builtin_zig_basename);
6878 g->compile_var_package = new_package(buf_ptr(&g->cache_dir), builtin_zig_basename);
68796879 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
68806880 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
68816881 g->compile_var_import = add_source_file(g, g->compile_var_package, abs_full_path, contents);
src/codegen.hpp+1-1
......@@ -47,7 +47,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
4747void codegen_set_test_filter(CodeGen *g, Buf *filter);
4848void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
4949void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
50void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir);
50void codegen_set_cache_dir(CodeGen *g, Buf cache_dir);
5151void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
5252void codegen_add_time_event(CodeGen *g, const char *name);
5353void codegen_print_timing_report(CodeGen *g, FILE *f);
src/ir.cpp+5-2
......@@ -17974,8 +17974,11 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr
1797417974 Buf source_dir_path = BUF_INIT;
1797517975 os_path_dirname(import->path, &source_dir_path);
1797617976
17977 Buf file_path = BUF_INIT;
17978 os_path_resolve(&source_dir_path, rel_file_path, &file_path);
17977 Buf *resolve_paths[] = {
17978 &source_dir_path,
17979 rel_file_path,
17980 };
17981 Buf file_path = os_path_resolve(resolve_paths, 2);
1797917982
1798017983 // load from file system into const expr
1798117984 Buf *file_contents = buf_alloc();
src/link.cpp+3-3
......@@ -66,7 +66,7 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
6666 const char *o_ext = target_o_file_ext(&child_gen->zig_target);
6767 Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);
6868 Buf *output_path = buf_alloc();
69 os_path_join(parent_gen->cache_dir, o_out_name, output_path);
69 os_path_join(&parent_gen->cache_dir, o_out_name, output_path);
7070 codegen_link(child_gen, buf_ptr(output_path));
7171
7272 codegen_destroy(child_gen);
......@@ -587,11 +587,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
587587 buf_appendf(def_contents, "\n");
588588
589589 Buf *def_path = buf_alloc();
590 os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
590 os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
591591 os_write_file(def_path, def_contents);
592592
593593 Buf *generated_lib_path = buf_alloc();
594 os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
594 os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
595595
596596 gen_lib_args.resize(0);
597597 gen_lib_args.append("link");
src/main.cpp+13-13
......@@ -374,25 +374,26 @@ int main(int argc, char **argv) {
374374 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
375375 codegen_set_out_name(g, buf_create_from_str("build"));
376376
377 Buf build_file_abs = BUF_INIT;
378 os_path_resolve(buf_create_from_str("."), buf_create_from_str(build_file), &build_file_abs);
377 Buf *build_file_buf = buf_create_from_str(build_file);
378 Buf build_file_abs = os_path_resolve(&build_file_buf, 1);
379379 Buf build_file_basename = BUF_INIT;
380380 Buf build_file_dirname = BUF_INIT;
381381 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
382382
383 Buf *full_cache_dir = buf_alloc();
383 Buf full_cache_dir = BUF_INIT;
384384 if (cache_dir == nullptr) {
385 os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), full_cache_dir);
385 os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
386386 } else {
387 os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);
387 Buf *cache_dir_buf = buf_create_from_str(cache_dir);
388 full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
388389 }
389390
390391 Buf *path_to_build_exe = buf_alloc();
391 os_path_join(full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
392 os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
392393 codegen_set_cache_dir(g, full_cache_dir);
393394
394395 args.items[1] = buf_ptr(&build_file_dirname);
395 args.items[2] = buf_ptr(full_cache_dir);
396 args.items[2] = buf_ptr(&full_cache_dir);
396397
397398 bool build_file_exists;
398399 if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
......@@ -789,7 +790,7 @@ int main(int argc, char **argv) {
789790
790791 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
791792
792 Buf *full_cache_dir = buf_alloc();
793 Buf full_cache_dir = BUF_INIT;
793794 Buf *run_exec_path = buf_alloc();
794795 if (cmd == CmdRun) {
795796 if (buf_out_name == nullptr) {
......@@ -799,13 +800,12 @@ int main(int argc, char **argv) {
799800 Buf *global_cache_dir = buf_alloc();
800801 os_get_global_cache_directory(global_cache_dir);
801802 os_path_join(global_cache_dir, buf_out_name, run_exec_path);
802 os_path_resolve(buf_create_from_str("."), global_cache_dir, full_cache_dir);
803 full_cache_dir = os_path_resolve(&global_cache_dir, 1);
803804
804805 out_file = buf_ptr(run_exec_path);
805806 } else {
806 os_path_resolve(buf_create_from_str("."),
807 buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
808 full_cache_dir);
807 Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir);
808 full_cache_dir = os_path_resolve(&resolve_paths, 1);
809809 }
810810
811811 Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
......@@ -937,7 +937,7 @@ int main(int argc, char **argv) {
937937
938938 Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));
939939 Buf *test_exe_path = buf_alloc();
940 os_path_join(full_cache_dir, test_exe_name, test_exe_path);
940 os_path_join(&full_cache_dir, test_exe_name, test_exe_path);
941941
942942 for (size_t i = 0; i < test_exec_args.length; i += 1) {
943943 if (test_exec_args.items[i] == nullptr) {
src/os.cpp+499-29
......@@ -57,6 +57,54 @@ static clock_serv_t cclock;
5757#include <errno.h>
5858#include <time.h>
5959
60// Ported from std/mem.zig.
61// Coordinate struct fields with memSplit function
62struct SplitIterator {
63 size_t index;
64 Slice<uint8_t> buffer;
65 Slice<uint8_t> split_bytes;
66};
67
68// Ported from std/mem.zig.
69static bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
70 for (size_t i = 0; i < self->split_bytes.len; i += 1) {
71 if (byte == self->split_bytes.ptr[i]) {
72 return true;
73 }
74 }
75 return false;
76}
77
78// Ported from std/mem.zig.
79static Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
80 // move to beginning of token
81 while (self->index < self->buffer.len &&
82 SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
83 {
84 self->index += 1;
85 }
86 size_t start = self->index;
87 if (start == self->buffer.len) {
88 return {};
89 }
90
91 // move to end of token
92 while (self->index < self->buffer.len &&
93 !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
94 {
95 self->index += 1;
96 }
97 size_t end = self->index;
98
99 return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
100}
101
102// Ported from std/mem.zig
103static SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
104 return SplitIterator{0, buffer, split_bytes};
105}
106
107
60108#if defined(ZIG_OS_POSIX)
61109static void populate_termination(Termination *term, int status) {
62110 if (WIFEXITED(status)) {
......@@ -266,15 +314,31 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path) {
266314#endif
267315}
268316
269bool os_path_is_absolute(Buf *path) {
270317#if defined(ZIG_OS_WINDOWS)
271 if (buf_starts_with_str(path, "/") || buf_starts_with_str(path, "\\"))
318// Ported from std/os/path.zig
319static bool isAbsoluteWindows(Slice<uint8_t> path) {
320 if (path.ptr[0] == '/')
272321 return true;
273322
274 if (buf_len(path) >= 3 && buf_ptr(path)[1] == ':')
323 if (path.ptr[0] == '\\') {
275324 return true;
276
325 }
326 if (path.len < 3) {
327 return false;
328 }
329 if (path.ptr[1] == ':') {
330 if (path.ptr[2] == '/')
331 return true;
332 if (path.ptr[2] == '\\')
333 return true;
334 }
277335 return false;
336}
337#endif
338
339bool os_path_is_absolute(Buf *path) {
340#if defined(ZIG_OS_WINDOWS)
341 return isAbsoluteWindows(buf_to_slice(path));
278342#elif defined(ZIG_OS_POSIX)
279343 return buf_ptr(path)[0] == '/';
280344#else
......@@ -282,14 +346,423 @@ bool os_path_is_absolute(Buf *path) {
282346#endif
283347}
284348
285void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path) {
286 if (os_path_is_absolute(target_path)) {
287 buf_init_from_buf(out_abs_path, target_path);
288 return;
349#if defined(ZIG_OS_WINDOWS)
350
351enum WindowsPathKind {
352 WindowsPathKindNone,
353 WindowsPathKindDrive,
354 WindowsPathKindNetworkShare,
355};
356
357struct WindowsPath {
358 Slice<uint8_t> disk_designator;
359 WindowsPathKind kind;
360 bool is_abs;
361};
362
363
364// Ported from std/os/path.zig
365static WindowsPath windowsParsePath(Slice<uint8_t> path) {
366 if (path.len >= 2 && path.ptr[1] == ':') {
367 return WindowsPath{
368 path.slice(0, 2),
369 WindowsPathKindDrive,
370 isAbsoluteWindows(path),
371 };
372 }
373 if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') &&
374 (path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\')))
375 {
376 return WindowsPath{
377 path.slice(0, 0),
378 WindowsPathKindNone,
379 true,
380 };
381 }
382 WindowsPath relative_path = {
383 str(""),
384 WindowsPathKindNone,
385 false,
386 };
387 if (path.len < strlen("//a/b")) {
388 return relative_path;
289389 }
290390
291 os_path_join(ref_path, target_path, out_abs_path);
292 return;
391 {
392 if (memStartsWith(path, str("//"))) {
393 if (path.ptr[2] == '/') {
394 return relative_path;
395 }
396
397 SplitIterator it = memSplit(path, str("/"));
398 {
399 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
400 if (!opt_component.is_some) return relative_path;
401 }
402 {
403 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
404 if (!opt_component.is_some) return relative_path;
405 }
406 return WindowsPath{
407 path.slice(0, it.index),
408 WindowsPathKindNetworkShare,
409 isAbsoluteWindows(path),
410 };
411 }
412 }
413 {
414 if (memStartsWith(path, str("\\\\"))) {
415 if (path.ptr[2] == '\\') {
416 return relative_path;
417 }
418
419 SplitIterator it = memSplit(path, str("\\"));
420 {
421 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
422 if (!opt_component.is_some) return relative_path;
423 }
424 {
425 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
426 if (!opt_component.is_some) return relative_path;
427 }
428 return WindowsPath{
429 path.slice(0, it.index),
430 WindowsPathKindNetworkShare,
431 isAbsoluteWindows(path),
432 };
433 }
434 }
435 return relative_path;
436}
437
438// Ported from std/os/path.zig
439static uint8_t asciiUpper(uint8_t byte) {
440 if (byte >= 'a' && byte <= 'z') {
441 return 'A' + (byte - 'a');
442 }
443 return byte;
444}
445
446// Ported from std/os/path.zig
447static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) {
448 if (s1.len != s2.len)
449 return false;
450 for (size_t i = 0; i < s1.len; i += 1) {
451 if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i]))
452 return false;
453 }
454 return true;
455}
456
457// Ported from std/os/path.zig
458static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) {
459 switch (kind) {
460 case WindowsPathKindNone:
461 assert(p1.len == 0);
462 assert(p2.len == 0);
463 return true;
464 case WindowsPathKindDrive:
465 return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]);
466 case WindowsPathKindNetworkShare:
467 uint8_t sep1 = p1.ptr[0];
468 uint8_t sep2 = p2.ptr[0];
469
470 SplitIterator it1 = memSplit(p1, {&sep1, 1});
471 SplitIterator it2 = memSplit(p2, {&sep2, 1});
472
473 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
474 return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) &&
475 asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value);
476 }
477 zig_unreachable();
478}
479
480// Ported from std/os/path.zig
481static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) {
482 if (paths_len == 0) {
483 Buf cwd = BUF_INIT;
484 int err;
485 if ((err = os_get_cwd(&cwd))) {
486 zig_panic("get cwd failed");
487 }
488 return cwd;
489 }
490
491 // determine which disk designator we will result with, if any
492 char result_drive_buf[2] = {'_', ':'};
493 Slice<uint8_t> result_disk_designator = str("");
494 WindowsPathKind have_drive_kind = WindowsPathKindNone;
495 bool have_abs_path = false;
496 size_t first_index = 0;
497 size_t max_size = 0;
498 for (size_t i = 0; i < paths_len; i += 1) {
499 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
500 WindowsPath parsed = windowsParsePath(p);
501 if (parsed.is_abs) {
502 have_abs_path = true;
503 first_index = i;
504 max_size = result_disk_designator.len;
505 }
506 switch (parsed.kind) {
507 case WindowsPathKindDrive:
508 result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]);
509 result_disk_designator = str(result_drive_buf);
510 have_drive_kind = WindowsPathKindDrive;
511 break;
512 case WindowsPathKindNetworkShare:
513 result_disk_designator = parsed.disk_designator;
514 have_drive_kind = WindowsPathKindNetworkShare;
515 break;
516 case WindowsPathKindNone:
517 break;
518 }
519 max_size += p.len + 1;
520 }
521
522 // if we will result with a disk designator, loop again to determine
523 // which is the last time the disk designator is absolutely specified, if any
524 // and count up the max bytes for paths related to this disk designator
525 if (have_drive_kind != WindowsPathKindNone) {
526 have_abs_path = false;
527 first_index = 0;
528 max_size = result_disk_designator.len;
529 bool correct_disk_designator = false;
530
531 for (size_t i = 0; i < paths_len; i += 1) {
532 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
533 WindowsPath parsed = windowsParsePath(p);
534 if (parsed.kind != WindowsPathKindNone) {
535 if (parsed.kind == have_drive_kind) {
536 correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
537 } else {
538 continue;
539 }
540 }
541 if (!correct_disk_designator) {
542 continue;
543 }
544 if (parsed.is_abs) {
545 first_index = i;
546 max_size = result_disk_designator.len;
547 have_abs_path = true;
548 }
549 max_size += p.len + 1;
550 }
551 }
552
553 // Allocate result and fill in the disk designator, calling getCwd if we have to.
554 Slice<uint8_t> result;
555 size_t result_index = 0;
556
557 if (have_abs_path) {
558 switch (have_drive_kind) {
559 case WindowsPathKindDrive: {
560 result = Slice<uint8_t>::alloc(max_size);
561
562 memCopy(result, result_disk_designator);
563 result_index += result_disk_designator.len;
564 break;
565 }
566 case WindowsPathKindNetworkShare: {
567 result = Slice<uint8_t>::alloc(max_size);
568 SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\"));
569 Slice<uint8_t> server_name = SplitIterator_next(&it).value;
570 Slice<uint8_t> other_name = SplitIterator_next(&it).value;
571
572 result.ptr[result_index] = '\\';
573 result_index += 1;
574 result.ptr[result_index] = '\\';
575 result_index += 1;
576 memCopy(result.sliceFrom(result_index), server_name);
577 result_index += server_name.len;
578 result.ptr[result_index] = '\\';
579 result_index += 1;
580 memCopy(result.sliceFrom(result_index), other_name);
581 result_index += other_name.len;
582
583 result_disk_designator = result.slice(0, result_index);
584 break;
585 }
586 case WindowsPathKindNone: {
587 Buf cwd = BUF_INIT;
588 int err;
589 if ((err = os_get_cwd(&cwd))) {
590 zig_panic("get cwd failed");
591 }
592 WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd));
593 result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1);
594 memCopy(result, parsed_cwd.disk_designator);
595 result_index += parsed_cwd.disk_designator.len;
596 result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len);
597 if (parsed_cwd.kind == WindowsPathKindDrive) {
598 result.ptr[0] = asciiUpper(result.ptr[0]);
599 }
600 have_drive_kind = parsed_cwd.kind;
601 break;
602 }
603 }
604 } else {
605 // TODO call get cwd for the result_disk_designator instead of the global one
606 Buf cwd = BUF_INIT;
607 int err;
608 if ((err = os_get_cwd(&cwd))) {
609 zig_panic("get cwd failed");
610 }
611 result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1);
612
613 memCopy(result, buf_to_slice(&cwd));
614 result_index += buf_len(&cwd);
615 WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index));
616 result_disk_designator = parsed_cwd.disk_designator;
617 if (parsed_cwd.kind == WindowsPathKindDrive) {
618 result.ptr[0] = asciiUpper(result.ptr[0]);
619 }
620 have_drive_kind = parsed_cwd.kind;
621 }
622
623 // Now we know the disk designator to use, if any, and what kind it is. And our result
624 // is big enough to append all the paths to.
625 bool correct_disk_designator = true;
626 for (size_t i = 0; i < paths_len; i += 1) {
627 Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
628 WindowsPath parsed = windowsParsePath(p);
629
630 if (parsed.kind != WindowsPathKindNone) {
631 if (parsed.kind == have_drive_kind) {
632 correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
633 } else {
634 continue;
635 }
636 }
637 if (!correct_disk_designator) {
638 continue;
639 }
640 SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\"));
641 while (true) {
642 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
643 if (!opt_component.is_some) break;
644 Slice<uint8_t> component = opt_component.value;
645 if (memEql(component, str("."))) {
646 continue;
647 } else if (memEql(component, str(".."))) {
648 while (true) {
649 if (result_index == 0 || result_index == result_disk_designator.len)
650 break;
651 result_index -= 1;
652 if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/')
653 break;
654 }
655 } else {
656 result.ptr[result_index] = '\\';
657 result_index += 1;
658 memCopy(result.sliceFrom(result_index), component);
659 result_index += component.len;
660 }
661 }
662 }
663
664 if (result_index == result_disk_designator.len) {
665 result.ptr[result_index] = '\\';
666 result_index += 1;
667 }
668
669 Buf return_value = BUF_INIT;
670 buf_init_from_mem(&return_value, (char *)result.ptr, result_index);
671 return return_value;
672}
673#endif
674
675#if defined(ZIG_OS_POSIX)
676// Ported from std/os/path.zig
677static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
678 if (paths_len == 0) {
679 Buf cwd = BUF_INIT;
680 int err;
681 if ((err = os_get_cwd(&cwd))) {
682 zig_panic("get cwd failed");
683 }
684 return cwd;
685 }
686
687 size_t first_index = 0;
688 bool have_abs = false;
689 size_t max_size = 0;
690 for (size_t i = 0; i < paths_len; i += 1) {
691 Buf *p = paths_ptr[i];
692 if (os_path_is_absolute(p)) {
693 first_index = i;
694 have_abs = true;
695 max_size = 0;
696 }
697 max_size += buf_len(p) + 1;
698 }
699
700 uint8_t *result_ptr;
701 size_t result_len;
702 size_t result_index = 0;
703
704 if (have_abs) {
705 result_len = max_size;
706 result_ptr = allocate_nonzero<uint8_t>(result_len);
707 } else {
708 Buf cwd = BUF_INIT;
709 int err;
710 if ((err = os_get_cwd(&cwd))) {
711 zig_panic("get cwd failed");
712 }
713 result_len = max_size + buf_len(&cwd) + 1;
714 result_ptr = allocate_nonzero<uint8_t>(result_len);
715 memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd));
716 result_index += buf_len(&cwd);
717 }
718
719 for (size_t i = first_index; i < paths_len; i += 1) {
720 Buf *p = paths_ptr[i];
721 SplitIterator it = memSplit(buf_to_slice(p), str("/"));
722 while (true) {
723 Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
724 if (!opt_component.is_some) break;
725 Slice<uint8_t> component = opt_component.value;
726
727 if (memEql<uint8_t>(component, str("."))) {
728 continue;
729 } else if (memEql<uint8_t>(component, str(".."))) {
730 while (true) {
731 if (result_index == 0)
732 break;
733 result_index -= 1;
734 if (result_ptr[result_index] == '/')
735 break;
736 }
737 } else {
738 result_ptr[result_index] = '/';
739 result_index += 1;
740 memcpy(result_ptr + result_index, component.ptr, component.len);
741 result_index += component.len;
742 }
743 }
744 }
745
746 if (result_index == 0) {
747 result_ptr[0] = '/';
748 result_index += 1;
749 }
750
751 Buf return_value = BUF_INIT;
752 buf_init_from_mem(&return_value, (char *)result_ptr, result_index);
753 return return_value;
754}
755#endif
756
757// Ported from std/os/path.zig
758Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
759#if defined(ZIG_OS_WINDOWS)
760 return os_path_resolve_windows(paths_ptr, paths_len);
761#elif defined(ZIG_OS_POSIX)
762 return os_path_resolve_posix(paths_ptr, paths_len);
763#else
764#error "missing os_path_resolve implementation"
765#endif
293766}
294767
295768int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
......@@ -558,7 +1031,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args,
5581031void os_write_file(Buf *full_path, Buf *contents) {
5591032 FILE *f = fopen(buf_ptr(full_path), "wb");
5601033 if (!f) {
561 zig_panic("open failed");
1034 zig_panic("os_write_file failed for %s", buf_ptr(full_path));
5621035 }
5631036 size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
5641037 if (amt_written != (size_t)buf_len(contents))
......@@ -645,21 +1118,19 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
6451118
6461119int os_get_cwd(Buf *out_cwd) {
6471120#if defined(ZIG_OS_WINDOWS)
648 buf_resize(out_cwd, 4096);
649 if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) {
1121 char buf[4096];
1122 if (GetCurrentDirectory(4096, buf) == 0) {
6501123 zig_panic("GetCurrentDirectory failed");
6511124 }
1125 buf_init_from_str(out_cwd, buf);
6521126 return 0;
6531127#elif defined(ZIG_OS_POSIX)
654 int err = ERANGE;
655 buf_resize(out_cwd, 512);
656 while (err == ERANGE) {
657 buf_resize(out_cwd, buf_len(out_cwd) * 2);
658 err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno;
1128 char buf[PATH_MAX];
1129 char *res = getcwd(buf, PATH_MAX);
1130 if (res == nullptr) {
1131 zig_panic("unable to get cwd: %s", strerror(errno));
6591132 }
660 if (err)
661 zig_panic("unable to get cwd: %s", strerror(err));
662
1133 buf_init_from_str(out_cwd, res);
6631134 return 0;
6641135#else
6651136#error "missing os_get_cwd implementation"
......@@ -898,21 +1369,20 @@ double os_get_time(void) {
8981369}
8991370
9001371int os_make_path(Buf *path) {
901 Buf *resolved_path = buf_alloc();
902 os_path_resolve(buf_create_from_str("."), path, resolved_path);
1372 Buf resolved_path = os_path_resolve(&path, 1);
9031373
904 size_t end_index = buf_len(resolved_path);
1374 size_t end_index = buf_len(&resolved_path);
9051375 int err;
9061376 while (true) {
907 if ((err = os_make_dir(buf_slice(resolved_path, 0, end_index)))) {
1377 if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
9081378 if (err == ErrorPathAlreadyExists) {
909 if (end_index == buf_len(resolved_path))
1379 if (end_index == buf_len(&resolved_path))
9101380 return 0;
9111381 } else if (err == ErrorFileNotFound) {
9121382 // march end_index backward until next path component
9131383 while (true) {
9141384 end_index -= 1;
915 if (os_is_sep(buf_ptr(resolved_path)[end_index]))
1385 if (os_is_sep(buf_ptr(&resolved_path)[end_index]))
9161386 break;
9171387 }
9181388 continue;
......@@ -920,12 +1390,12 @@ int os_make_path(Buf *path) {
9201390 return err;
9211391 }
9221392 }
923 if (end_index == buf_len(resolved_path))
1393 if (end_index == buf_len(&resolved_path))
9241394 return 0;
9251395 // march end_index forward until next path component
9261396 while (true) {
9271397 end_index += 1;
928 if (end_index == buf_len(resolved_path) || os_is_sep(buf_ptr(resolved_path)[end_index]))
1398 if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index]))
9291399 break;
9301400 }
9311401 }
src/os.hpp+1-1
......@@ -49,7 +49,7 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
4949void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
5050void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
5151int os_path_real(Buf *rel_path, Buf *out_abs_path);
52void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path);
52Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
5353bool os_path_is_absolute(Buf *path);
5454
5555int os_get_global_cache_directory(Buf *out_tmp_path);
src/util.hpp+68
......@@ -186,4 +186,72 @@ static inline double zig_f16_to_double(float16_t x) {
186186 return z;
187187}
188188
189template<typename T>
190struct Optional {
191 T value;
192 bool is_some;
193
194 static inline Optional<T> some(T x) {
195 return {x, true};
196 }
197};
198
199template<typename T>
200struct Slice {
201 T *ptr;
202 size_t len;
203
204 inline Slice<T> slice(size_t start, size_t end) {
205 assert(end <= len);
206 assert(end >= start);
207 return {
208 ptr + start,
209 end - start,
210 };
211 }
212
213 inline Slice<T> sliceFrom(size_t start) {
214 assert(start <= len);
215 return {
216 ptr + start,
217 len - start,
218 };
219 }
220
221 static inline Slice<T> alloc(size_t n) {
222 return {allocate_nonzero<T>(n), n};
223 }
224};
225
226static inline Slice<uint8_t> str(const char *literal) {
227 return {(uint8_t*)(literal), strlen(literal)};
228}
229
230// Ported from std/mem.zig
231template<typename T>
232static inline bool memEql(Slice<T> a, Slice<T> b) {
233 if (a.len != b.len)
234 return false;
235 for (size_t i = 0; i < a.len; i += 1) {
236 if (a.ptr[i] != b.ptr[i])
237 return false;
238 }
239 return true;
240}
241
242// Ported from std/mem.zig
243template<typename T>
244static inline bool memStartsWith(Slice<T> haystack, Slice<T> needle) {
245 if (needle.len > haystack.len)
246 return false;
247 return memEql(haystack.slice(0, needle.len), needle);
248}
249
250// Ported from std/mem.zig
251template<typename T>
252static inline void memCopy(Slice<T> dest, Slice<T> src) {
253 assert(dest.len >= src.len);
254 memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
255}
256
189257#endif