diff options
| -rw-r--r-- | lib/std/meta/trait.zig | 13 | ||||
| -rw-r--r-- | src-self-hosted/arg.zig | 293 | ||||
| -rw-r--r-- | src-self-hosted/codegen.zig | 2 | ||||
| -rw-r--r-- | src-self-hosted/compilation.zig | 17 | ||||
| -rw-r--r-- | src-self-hosted/link.zig | 176 | ||||
| -rw-r--r-- | src-self-hosted/main.zig | 549 | ||||
| -rw-r--r-- | src-self-hosted/stage1.zig | 82 |
7 files changed, 372 insertions, 760 deletions
diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index f36f3e15f0..d17f2dedaf 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -14,7 +14,6 @@ fn traitFnWorkaround(comptime T: type) bool { } pub const TraitFn = @TypeOf(traitFnWorkaround); -/// //////Trait generators @@ -55,7 +54,6 @@ test "std.meta.trait.multiTrait" { testing.expect(!isVector(u8)); } -/// pub fn hasFn(comptime name: []const u8) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { @@ -79,7 +77,6 @@ test "std.meta.trait.hasFn" { testing.expect(!hasFn("useless")(u8)); } -/// pub fn hasField(comptime name: []const u8) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { @@ -113,7 +110,6 @@ test "std.meta.trait.hasField" { testing.expect(!hasField("value")(u8)); } -/// pub fn is(comptime id: builtin.TypeId) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { @@ -131,7 +127,6 @@ test "std.meta.trait.is" { testing.expect(!is(builtin.TypeId.Optional)(anyerror)); } -/// pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { @@ -173,7 +168,6 @@ test "std.meta.trait.isExtern" { testing.expect(!isExtern(u8)); } -/// pub fn isPacked(comptime T: type) bool { const Packed = builtin.TypeInfo.ContainerLayout.Packed; const info = @typeInfo(T); @@ -194,7 +188,6 @@ test "std.meta.trait.isPacked" { testing.expect(!isPacked(u8)); } -/// pub fn isUnsignedInt(comptime T: type) bool { return switch (@typeId(T)) { builtin.TypeId.Int => !@typeInfo(T).Int.is_signed, @@ -209,7 +202,6 @@ test "isUnsignedInt" { testing.expect(isUnsignedInt(f64) == false); } -/// pub fn isSignedInt(comptime T: type) bool { return switch (@typeId(T)) { builtin.TypeId.ComptimeInt => true, @@ -225,7 +217,6 @@ test "isSignedInt" { testing.expect(isSignedInt(f64) == false); } -/// pub fn isSingleItemPtr(comptime T: type) bool { if (comptime is(builtin.TypeId.Pointer)(T)) { const info = @typeInfo(T); @@ -241,7 +232,6 @@ test "std.meta.trait.isSingleItemPtr" { testing.expect(!isSingleItemPtr(@TypeOf(array[0..1]))); } -/// pub fn isManyItemPtr(comptime T: type) bool { if (comptime is(builtin.TypeId.Pointer)(T)) { const info = @typeInfo(T); @@ -258,7 +248,6 @@ test "std.meta.trait.isManyItemPtr" { testing.expect(!isManyItemPtr(@TypeOf(array[0..1]))); } -/// pub fn isSlice(comptime T: type) bool { if (comptime is(builtin.TypeId.Pointer)(T)) { const info = @typeInfo(T); @@ -274,7 +263,6 @@ test "std.meta.trait.isSlice" { testing.expect(!isSlice(@TypeOf(&array[0]))); } -/// pub fn isIndexable(comptime T: type) bool { if (comptime is(builtin.TypeId.Pointer)(T)) { const info = @typeInfo(T); @@ -297,7 +285,6 @@ test "std.meta.trait.isIndexable" { testing.expect(!isIndexable(meta.Child(@TypeOf(slice)))); } -/// pub fn isNumber(comptime T: type) bool { return switch (@typeId(T)) { builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true, diff --git a/src-self-hosted/arg.zig b/src-self-hosted/arg.zig deleted file mode 100644 index 066080f9ef..0000000000 --- a/src-self-hosted/arg.zig +++ /dev/null @@ -1,293 +0,0 @@ -const std = @import("std"); -const debug = std.debug; -const testing = std.testing; -const mem = std.mem; - -const Allocator = mem.Allocator; -const ArrayList = std.ArrayList; -const StringHashMap = std.StringHashMap; - -fn trimStart(slice: []const u8, ch: u8) []const u8 { - var i: usize = 0; - for (slice) |b| { - if (b != '-') break; - i += 1; - } - - return slice[i..]; -} - -fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool { - if (maybe_set) |set| { - for (set) |possible| { - if (mem.eql(u8, arg, possible)) { - return true; - } - } - return false; - } else { - return true; - } -} - -// Modifies the current argument index during iteration -fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: *usize) !FlagArg { - switch (required) { - 0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value? - 1 => { - if (index.* + 1 >= args.len) { - return error.MissingFlagArguments; - } - - index.* += 1; - const arg = args[index.*]; - - if (!argInAllowedSet(allowed_set, arg)) { - return error.ArgumentNotInAllowedSet; - } - - return FlagArg{ .Single = arg }; - }, - else => |needed| { - var extra = ArrayList([]const u8).init(allocator); - errdefer extra.deinit(); - - var j: usize = 0; - while (j < needed) : (j += 1) { - if (index.* + 1 >= args.len) { - return error.MissingFlagArguments; - } - - index.* += 1; - const arg = args[index.*]; - - if (!argInAllowedSet(allowed_set, arg)) { - return error.ArgumentNotInAllowedSet; - } - - try extra.append(arg); - } - - return FlagArg{ .Many = extra }; - }, - } -} - -const HashMapFlags = StringHashMap(FlagArg); - -// A store for querying found flags and positional arguments. -pub const Args = struct { - flags: HashMapFlags, - positionals: ArrayList([]const u8), - - pub fn parse(allocator: *Allocator, comptime spec: []const Flag, args: []const []const u8) !Args { - var parsed = Args{ - .flags = HashMapFlags.init(allocator), - .positionals = ArrayList([]const u8).init(allocator), - }; - - var i: usize = 0; - next: while (i < args.len) : (i += 1) { - const arg = args[i]; - - if (arg.len != 0 and arg[0] == '-') { - // TODO: hashmap, although the linear scan is okay for small argument sets as is - for (spec) |flag| { - if (mem.eql(u8, arg, flag.name)) { - const flag_name_trimmed = trimStart(flag.name, '-'); - const flag_args = readFlagArguments(allocator, args, flag.required, flag.allowed_set, &i) catch |err| { - switch (err) { - error.ArgumentNotInAllowedSet => { - std.debug.warn("argument '{}' is invalid for flag '{}'\n", .{ args[i], arg }); - std.debug.warn("allowed options are ", .{}); - for (flag.allowed_set.?) |possible| { - std.debug.warn("'{}' ", .{possible}); - } - std.debug.warn("\n", .{}); - }, - error.MissingFlagArguments => { - std.debug.warn("missing argument for flag: {}\n", .{arg}); - }, - else => {}, - } - - return err; - }; - - if (flag.mergable) { - var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator); - - // MergeN creation disallows 0 length flag entry (doesn't make sense) - switch (flag_args) { - .None => unreachable, - .Single => |inner| try prev.append(inner), - .Many => |inner| try prev.appendSlice(inner.toSliceConst()), - } - - _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); - } else { - _ = try parsed.flags.put(flag_name_trimmed, flag_args); - } - - continue :next; - } - } - - // TODO: Better errors with context, global error state and return is sufficient. - std.debug.warn("could not match flag: {}\n", .{arg}); - return error.UnknownFlag; - } else { - try parsed.positionals.append(arg); - } - } - - return parsed; - } - - pub fn deinit(self: *Args) void { - self.flags.deinit(); - self.positionals.deinit(); - } - - // e.g. --help - pub fn present(self: *const Args, name: []const u8) bool { - return self.flags.contains(name); - } - - // e.g. --name value - pub fn single(self: *Args, name: []const u8) ?[]const u8 { - if (self.flags.get(name)) |entry| { - switch (entry.value) { - .Single => |inner| { - return inner; - }, - else => @panic("attempted to retrieve flag with wrong type"), - } - } else { - return null; - } - } - - // e.g. --names value1 value2 value3 - pub fn many(self: *Args, name: []const u8) []const []const u8 { - if (self.flags.get(name)) |entry| { - switch (entry.value) { - .Many => |inner| { - return inner.toSliceConst(); - }, - else => @panic("attempted to retrieve flag with wrong type"), - } - } else { - return &[_][]const u8{}; - } - } -}; - -// Arguments for a flag. e.g. arg1, arg2 in `--command arg1 arg2`. -const FlagArg = union(enum) { - None, - Single: []const u8, - Many: ArrayList([]const u8), -}; - -// Specification for how a flag should be parsed. -pub const Flag = struct { - name: []const u8, - required: usize, - mergable: bool, - allowed_set: ?[]const []const u8, - - pub fn Bool(comptime name: []const u8) Flag { - return ArgN(name, 0); - } - - pub fn Arg1(comptime name: []const u8) Flag { - return ArgN(name, 1); - } - - pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag { - return Flag{ - .name = name, - .required = n, - .mergable = false, - .allowed_set = null, - }; - } - - pub fn ArgMergeN(comptime name: []const u8, comptime n: usize) Flag { - if (n == 0) { - @compileError("n must be greater than 0"); - } - - return Flag{ - .name = name, - .required = n, - .mergable = true, - .allowed_set = null, - }; - } - - pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag { - return Flag{ - .name = name, - .required = 1, - .mergable = false, - .allowed_set = set, - }; - } -}; - -test "parse arguments" { - const spec1 = comptime [_]Flag{ - Flag.Bool("--help"), - Flag.Bool("--init"), - Flag.Arg1("--build-file"), - Flag.Option("--color", [_][]const u8{ - "on", - "off", - "auto", - }), - Flag.ArgN("--pkg-begin", 2), - Flag.ArgMergeN("--object", 1), - Flag.ArgN("--library", 1), - }; - - const cliargs = [_][]const u8{ - "build", - "--help", - "pos1", - "--build-file", - "build.zig", - "--object", - "obj1", - "--object", - "obj2", - "--library", - "lib1", - "--library", - "lib2", - "--color", - "on", - "pos2", - }; - - var args = try Args.parse(std.debug.global_allocator, spec1, cliargs); - - testing.expect(args.present("help")); - testing.expect(!args.present("help2")); - testing.expect(!args.present("init")); - - testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig")); - testing.expect(mem.eql(u8, args.single("color").?, "on")); - - const objects = args.many("object").?; - testing.expect(mem.eql(u8, objects[0], "obj1")); - testing.expect(mem.eql(u8, objects[1], "obj2")); - - testing.expect(mem.eql(u8, args.single("library").?, "lib2")); - - const pos = args.positionals.toSliceConst(); - testing.expect(mem.eql(u8, pos[0], "build")); - testing.expect(mem.eql(u8, pos[1], "pos1")); - testing.expect(mem.eql(u8, pos[2], "pos2")); -} diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 702f2c2883..11bb83ae11 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -101,8 +101,6 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr); } - assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types - const is_small = comp.build_mode == .ReleaseSmall; const is_debug = comp.build_mode == .Debug; diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index 74a6c4fe46..a7ba07342e 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -135,22 +135,17 @@ pub const Compilation = struct { /// lazily created when we need it tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(), - version_major: u32 = 0, - version_minor: u32 = 0, - version_patch: u32 = 0, + version: builtin.Version = builtin.Version{ .major = 0, .minor = 0, .patch = 0 }, linker_script: ?[]const u8 = null, out_h_path: ?[]const u8 = null, is_test: bool = false, - each_lib_rpath: bool = false, strip: bool = false, is_static: bool, linker_rdynamic: bool = false, clang_argv: []const []const u8 = &[_][]const u8{}, - lib_dirs: []const []const u8 = &[_][]const u8{}, - rpath_list: []const []const u8 = &[_][]const u8{}, assembly_files: []const []const u8 = &[_][]const u8{}, /// paths that are explicitly provided by the user to link against @@ -162,9 +157,6 @@ pub const Compilation = struct { pub const FnLinkSet = std.TailQueue(?*Value.Fn); - windows_subsystem_windows: bool = false, - windows_subsystem_console: bool = false, - link_libs_list: ArrayList(*LinkLib), libc_link_lib: ?*LinkLib = null, @@ -178,17 +170,18 @@ pub const Compilation = struct { verbose_llvm_ir: bool = false, verbose_link: bool = false, - darwin_frameworks: []const []const u8 = &[_][]const u8{}, darwin_version_min: DarwinVersionMin = .None, test_filters: []const []const u8 = &[_][]const u8{}, test_name_prefix: ?[]const u8 = null, - emit_file_type: Emit = .Binary, + emit_bin: bool = true, + emit_asm: bool = false, + emit_llvm_ir: bool = false, + emit_h: bool = false, kind: Kind, - link_out_file: ?[]const u8 = null, events: *event.Channel(Event), exported_symbol_names: event.Locked(Decl.Table), diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 935b2f2937..38c4ce14a1 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -36,21 +36,17 @@ pub fn link(comp: *Compilation) !void { ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator); ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator); - if (comp.link_out_file) |out_file| { - ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file); - } else { - ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); - switch (comp.kind) { - .Exe => { - try ctx.out_file_path.append(comp.target.exeFileExt()); - }, - .Lib => { - try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix()); - }, - .Obj => { - try ctx.out_file_path.append(comp.target.oFileExt()); - }, - } + ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); + switch (comp.kind) { + .Exe => { + try ctx.out_file_path.append(comp.target.exeFileExt()); + }, + .Lib => { + try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix()); + }, + .Obj => { + try ctx.out_file_path.append(comp.target.oFileExt()); + }, } // even though we're calling LLD as a library it thinks the first @@ -183,37 +179,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void { try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino); } - //for (size_t i = 0; i < g->rpath_list.length; i += 1) { - // Buf *rpath = g->rpath_list.at(i); - // add_rpath(lj, rpath); - //} - //if (g->each_lib_rpath) { - // for (size_t i = 0; i < g->lib_dirs.length; i += 1) { - // const char *lib_dir = g->lib_dirs.at(i); - // for (size_t i = 0; i < g->link_libs_list.length; i += 1) { - // LinkLib *link_lib = g->link_libs_list.at(i); - // if (buf_eql_str(link_lib->name, "c")) { - // continue; - // } - // bool does_exist; - // Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib->name)); - // if (os_file_exists(test_path, &does_exist) != ErrorNone) { - // zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path)); - // } - // if (does_exist) { - // add_rpath(lj, buf_create_from_str(lib_dir)); - // break; - // } - // } - // } - //} - - //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { - // const char *lib_dir = g->lib_dirs.at(i); - // lj->args.append("-L"); - // lj->args.append(lib_dir); - //} - if (ctx.comp.haveLibC()) { try ctx.args.append("-L"); // TODO addNullByte should probably return [:0]u8 @@ -326,12 +291,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { else => return error.UnsupportedLinkArchitecture, } - if (ctx.comp.windows_subsystem_windows) { - try ctx.args.append("/SUBSYSTEM:windows"); - } else if (ctx.comp.windows_subsystem_console) { - try ctx.args.append("/SUBSYSTEM:console"); - } - const is_library = ctx.comp.kind == .Lib; const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()}); @@ -374,12 +333,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { try ctx.args.append("-NODEFAULTLIB"); if (!is_library) { try ctx.args.append("-ENTRY:WinMainCRTStartup"); - // TODO - //if (g->have_winmain) { - // lj->args.append("-ENTRY:WinMain"); - //} else { - // lj->args.append("-ENTRY:WinMainCRTStartup"); - //} } } @@ -387,11 +340,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { try ctx.args.append("-DLL"); } - //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { - // const char *lib_dir = g->lib_dirs.at(i); - // lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); - //} - for (ctx.comp.link_objects) |link_object| { const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object); try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr)); @@ -402,63 +350,10 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { .Exe, .Lib => { if (!ctx.comp.haveLibC()) { @panic("TODO"); - //Buf *builtin_o_path = build_o(g, "builtin"); - //lj->args.append(buf_ptr(builtin_o_path)); } - - // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage - // TODO - //Buf *compiler_rt_o_path = build_compiler_rt(g); - //lj->args.append(buf_ptr(compiler_rt_o_path)); }, .Obj => {}, } - - //Buf *def_contents = buf_alloc(); - //ZigList<const char *> gen_lib_args = {0}; - //for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) { - // LinkLib *link_lib = g->link_libs_list.at(lib_i); - // if (buf_eql_str(link_lib->name, "c")) { - // continue; - // } - // if (link_lib->provided_explicitly) { - // if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) { - // Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); - // lj->args.append(buf_ptr(arg)); - // } - // else { - // lj->args.append(buf_ptr(link_lib->name)); - // } - // } else { - // buf_resize(def_contents, 0); - // buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name)); - // for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) { - // Buf *symbol_name = link_lib->symbols.at(exp_i); - // buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name)); - // } - // buf_appendf(def_contents, "\n"); - - // Buf *def_path = buf_alloc(); - // os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); - // os_write_file(def_path, def_contents); - - // Buf *generated_lib_path = buf_alloc(); - // os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); - - // gen_lib_args.resize(0); - // gen_lib_args.append("link"); - - // coff_append_machine_arg(g, &gen_lib_args); - // gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); - // gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); - // Buf diag = BUF_INIT; - // if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { - // fprintf(stderr, "%s\n", buf_ptr(&diag)); - // exit(1); - // } - // lj->args.append(buf_ptr(generated_lib_path)); - // } - //} } fn constructLinkerArgsMachO(ctx: *Context) !void { @@ -476,32 +371,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append("-dynamic"); } - //if (is_lib) { - // if (!g->is_static) { - // lj->args.append("-dylib"); - - // Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major); - // lj->args.append("-compatibility_version"); - // lj->args.append(buf_ptr(compat_vers)); - - // Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, - // g->version_major, g->version_minor, g->version_patch); - // lj->args.append("-current_version"); - // lj->args.append(buf_ptr(cur_vers)); - - // // TODO getting an error when running an executable when doing this rpath thing - // //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib", - // // buf_ptr(g->root_out_name), g->version_major); - // //lj->args.append("-install_name"); - // //lj->args.append(buf_ptr(dylib_install_name)); - - // if (buf_len(&lj->out_file) == 0) { - // buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", - // buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); - // } - // } - //} - try ctx.args.append("-arch"); try ctx.args.append(util.getDarwinArchString(ctx.comp.target)); @@ -529,12 +398,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append("-o"); try ctx.args.append(ctx.out_file_path.toSliceConst()); - //for (size_t i = 0; i < g->rpath_list.length; i += 1) { - // Buf *rpath = g->rpath_list.at(i); - // add_rpath(lj, rpath); - //} - //add_rpath(lj, &lj->out_file); - if (shared) { try ctx.args.append("-headerpad_max_install_names"); } else if (ctx.comp.is_static) { @@ -563,24 +426,12 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { } } - //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { - // const char *lib_dir = g->lib_dirs.at(i); - // lj->args.append("-L"); - // lj->args.append(lib_dir); - //} - for (ctx.comp.link_objects) |link_object| { const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object); try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr)); } try addFnObjects(ctx); - //// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce - //if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) { - // Buf *compiler_rt_o_path = build_compiler_rt(g); - // lj->args.append(buf_ptr(compiler_rt_o_path)); - //} - if (ctx.comp.target == Target.Native) { for (ctx.comp.link_libs_list.toSliceConst()) |lib| { if (mem.eql(u8, lib.name, "c")) { @@ -613,11 +464,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { } else { @panic("TODO"); } - - //for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { - // lj->args.append("-framework"); - // lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); - //} } fn constructLinkerArgsWasm(ctx: *Context) void { diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 0fd034479b..5224375e46 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -11,11 +11,8 @@ const Allocator = mem.Allocator; const ArrayList = std.ArrayList; const Buffer = std.Buffer; -const arg = @import("arg.zig"); const c = @import("c.zig"); const introspect = @import("introspect.zig"); -const Args = arg.Args; -const Flag = arg.Flag; const ZigCompiler = @import("compilation.zig").ZigCompiler; const Compilation = @import("compilation.zig").Compilation; const Target = std.Target; @@ -53,11 +50,7 @@ const Command = struct { }; pub fn main() !void { - // This allocator needs to be thread-safe because we use it for the event.Loop - // which multiplexes async functions onto kernel threads. - // libc allocator is guaranteed to have this property. - // TODO https://github.com/ziglang/zig/issues/3783 - const allocator = std.heap.page_allocator; + const allocator = std.heap.c_allocator; stdout = &std.io.getStdOut().outStream().stream; @@ -65,7 +58,7 @@ pub fn main() !void { stderr = &stderr_file.outStream().stream; const args = try process.argsAlloc(allocator); - // TODO I'm getting unreachable code here, which shouldn't happen + // TODO I'm getting unreachable code here, which shouldn't happen //defer process.argsFree(allocator, args); if (args.len <= 1) { @@ -182,8 +175,6 @@ const usage_build_generic = \\ --object [obj] Add object file to build \\ -rdynamic Add all symbols to the dynamic symbol table \\ -rpath [path] Add directory to the runtime library search path - \\ -mconsole (windows) --subsystem console to the linker - \\ -mwindows (windows) --subsystem windows to the linker \\ -framework [name] (darwin) link against framework \\ -mios-version-min [ver] (darwin) set iOS deployment target \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target @@ -194,143 +185,244 @@ const usage_build_generic = \\ ; -const args_build_generic = [_]Flag{ - Flag.Bool("--help"), - Flag.Option("--color", &[_][]const u8{ - "auto", - "off", - "on", - }), - Flag.Option("--mode", &[_][]const u8{ - "debug", - "release-fast", - "release-safe", - "release-small", - }), - - Flag.ArgMergeN("--assembly", 1), - Flag.Option("--emit", &[_][]const u8{ - "asm", - "bin", - "llvm-ir", - }), - Flag.Bool("--enable-timing-info"), - Flag.Arg1("--libc"), - Flag.Arg1("--name"), - Flag.Arg1("--output"), - Flag.Arg1("--output-h"), - // NOTE: Parsed manually after initial check - Flag.ArgN("--pkg-begin", 2), - Flag.Bool("--pkg-end"), - Flag.Bool("--static"), - Flag.Bool("--strip"), - Flag.Arg1("-target"), - Flag.Bool("--verbose-tokenize"), - Flag.Bool("--verbose-ast-tree"), - Flag.Bool("--verbose-ast-fmt"), - Flag.Bool("--verbose-link"), - Flag.Bool("--verbose-ir"), - Flag.Bool("--verbose-llvm-ir"), - Flag.Bool("--verbose-cimport"), - Flag.Arg1("-dirafter"), - Flag.ArgMergeN("-isystem", 1), - Flag.Arg1("-mllvm"), - - Flag.Arg1("--ar-path"), - Flag.Bool("--each-lib-rpath"), - Flag.ArgMergeN("--library", 1), - Flag.ArgMergeN("--forbid-library", 1), - Flag.ArgMergeN("--library-path", 1), - Flag.Arg1("--linker-script"), - Flag.ArgMergeN("--object", 1), - // NOTE: Removed -L since it would need to be special-cased and we have an alias in library-path - Flag.Bool("-rdynamic"), - Flag.Arg1("-rpath"), - Flag.Bool("-mconsole"), - Flag.Bool("-mwindows"), - Flag.ArgMergeN("-framework", 1), - Flag.Arg1("-mios-version-min"), - Flag.Arg1("-mmacosx-version-min"), - Flag.Arg1("--ver-major"), - Flag.Arg1("--ver-minor"), - Flag.Arg1("--ver-patch"), -}; - fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void { - var flags = try Args.parse(allocator, &args_build_generic, args); - defer flags.deinit(); - - if (flags.present("help")) { - try stdout.write(usage_build_generic); - process.exit(0); - } + var color: errmsg.Color = .Auto; + var build_mode: std.builtin.Mode = .Debug; + var emit_bin = true; + var emit_asm = false; + var emit_llvm_ir = false; + var emit_h = false; + var provided_name: ?[]const u8 = null; + var is_dynamic = false; + var root_src_file: ?[]const u8 = null; + var libc_arg: ?[]const u8 = null; + var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; + var linker_script: ?[]const u8 = null; + var strip = false; + var verbose_tokenize = false; + var verbose_ast_tree = false; + var verbose_ast_fmt = false; + var verbose_link = false; + var verbose_ir = false; + var verbose_llvm_ir = false; + var verbose_cimport = false; + var linker_rdynamic = false; + var macosx_version_min: ?[]const u8 = null; + var ios_version_min: ?[]const u8 = null; + + var assembly_files = ArrayList([]const u8).init(allocator); + defer assembly_files.deinit(); + + var link_objects = ArrayList([]const u8).init(allocator); + defer link_objects.deinit(); - const build_mode: std.builtin.Mode = blk: { - if (flags.single("mode")) |mode_flag| { - if (mem.eql(u8, mode_flag, "debug")) { - break :blk .Debug; - } else if (mem.eql(u8, mode_flag, "release-fast")) { - break :blk .ReleaseFast; - } else if (mem.eql(u8, mode_flag, "release-safe")) { - break :blk .ReleaseSafe; - } else if (mem.eql(u8, mode_flag, "release-small")) { - break :blk .ReleaseSmall; - } else unreachable; - } else { - break :blk .Debug; - } - }; + var clang_argv_buf = ArrayList([]const u8).init(allocator); + defer clang_argv_buf.deinit(); - const color: errmsg.Color = blk: { - if (flags.single("color")) |color_flag| { - if (mem.eql(u8, color_flag, "auto")) { - break :blk .Auto; - } else if (mem.eql(u8, color_flag, "on")) { - break :blk .On; - } else if (mem.eql(u8, color_flag, "off")) { - break :blk .Off; - } else unreachable; - } else { - break :blk .Auto; - } - }; - - const emit_type: Compilation.Emit = blk: { - if (flags.single("emit")) |emit_flag| { - if (mem.eql(u8, emit_flag, "asm")) { - break :blk .Assembly; - } else if (mem.eql(u8, emit_flag, "bin")) { - break :blk .Binary; - } else if (mem.eql(u8, emit_flag, "llvm-ir")) { - break :blk .LlvmIr; - } else unreachable; - } else { - break :blk .Binary; - } - }; + var mllvm_flags = ArrayList([]const u8).init(allocator); + defer mllvm_flags.deinit(); var cur_pkg = try CliPkg.init(allocator, "", "", null); defer cur_pkg.deinit(); - var i: usize = 0; - while (i < args.len) : (i += 1) { - const arg_name = args[i]; - if (mem.eql(u8, "--pkg-begin", arg_name)) { - // following two arguments guaranteed to exist due to arg parsing - i += 1; - const new_pkg_name = args[i]; - i += 1; - const new_pkg_path = args[i]; - - var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); - try cur_pkg.children.append(new_cur_pkg); - cur_pkg = new_cur_pkg; - } else if (mem.eql(u8, "--pkg-end", arg_name)) { - if (cur_pkg.parent) |parent| { - cur_pkg = parent; + var system_libs = ArrayList([]const u8).init(allocator); + defer system_libs.deinit(); + + var c_src_files = ArrayList([]const u8).init(allocator); + defer c_src_files.deinit(); + + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "--help")) { + try stdout.write(usage_build_generic); + process.exit(0); + } else if (mem.eql(u8, arg, "--color")) { + if (i + 1 >= args.len) { + try stderr.write("expected [auto|on|off] after --color\n"); + process.exit(1); + } + i += 1; + const next_arg = args[i]; + if (mem.eql(u8, next_arg, "auto")) { + color = .Auto; + } else if (mem.eql(u8, next_arg, "on")) { + color = .On; + } else if (mem.eql(u8, next_arg, "off")) { + color = .Off; + } else { + try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); + process.exit(1); + } + } else if (mem.eql(u8, arg, "--mode")) { + if (i + 1 >= args.len) { + try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n"); + process.exit(1); + } + i += 1; + const next_arg = args[i]; + if (mem.eql(u8, next_arg, "Debug")) { + build_mode = .Debug; + } else if (mem.eql(u8, next_arg, "ReleaseSafe")) { + build_mode = .ReleaseSafe; + } else if (mem.eql(u8, next_arg, "ReleaseFast")) { + build_mode = .ReleaseFast; + } else if (mem.eql(u8, next_arg, "ReleaseSmall")) { + build_mode = .ReleaseSmall; + } else { + try stderr.print("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'\n", .{next_arg}); + process.exit(1); + } + } else if (mem.eql(u8, arg, "--name")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --name\n"); + process.exit(1); + } + i += 1; + provided_name = args[i]; + } else if (mem.eql(u8, arg, "--ver-major")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --ver-major\n"); + process.exit(1); + } + i += 1; + version.major = try std.fmt.parseInt(u32, args[i], 10); + } else if (mem.eql(u8, arg, "--ver-minor")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --ver-minor\n"); + process.exit(1); + } + i += 1; + version.minor = try std.fmt.parseInt(u32, args[i], 10); + } else if (mem.eql(u8, arg, "--ver-patch")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --ver-patch\n"); + process.exit(1); + } + i += 1; + version.patch = try std.fmt.parseInt(u32, args[i], 10); + } else if (mem.eql(u8, arg, "--linker-script")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --linker-script\n"); + process.exit(1); + } + i += 1; + linker_script = args[i]; + } else if (mem.eql(u8, arg, "--libc")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after --libc\n"); + process.exit(1); + } + i += 1; + libc_arg = args[i]; + } else if (mem.eql(u8, arg, "-mllvm")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after -mllvm\n"); + process.exit(1); + } + i += 1; + try clang_argv_buf.append("-mllvm"); + try clang_argv_buf.append(args[i]); + + try mllvm_flags.append(args[i]); + } else if (mem.eql(u8, arg, "-mmacosx-version-min")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after -mmacosx-version-min\n"); + process.exit(1); + } + i += 1; + macosx_version_min = args[i]; + } else if (mem.eql(u8, arg, "-mios-version-min")) { + if (i + 1 >= args.len) { + try stderr.write("expected parameter after -mios-version-min\n"); + process.exit(1); + } + i += 1; + ios_version_min = args[i]; + } else if (mem.eql(u8, arg, "-femit-bin")) { + emit_bin = true; + } else if (mem.eql(u8, arg, "-fno-emit-bin")) { + emit_bin = false; + } else if (mem.eql(u8, arg, "-femit-asm")) { + emit_asm = true; + } else if (mem.eql(u8, arg, "-fno-emit-asm")) { + emit_asm = false; + } else if (mem.eql(u8, arg, "-femit-llvm-ir")) { + emit_llvm_ir = true; + } else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) { + emit_llvm_ir = false; + } else if (mem.eql(u8, arg, "-dynamic")) { + is_dynamic = true; + } else if (mem.eql(u8, arg, "--strip")) { + strip = true; + } else if (mem.eql(u8, arg, "--verbose-tokenize")) { + verbose_tokenize = true; + } else if (mem.eql(u8, arg, "--verbose-ast-tree")) { + verbose_ast_tree = true; + } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) { + verbose_ast_fmt = true; + } else if (mem.eql(u8, arg, "--verbose-link")) { + verbose_link = true; + } else if (mem.eql(u8, arg, "--verbose-ir")) { + verbose_ir = true; + } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { + verbose_llvm_ir = true; + } else if (mem.eql(u8, arg, "--verbose-cimport")) { + verbose_cimport = true; + } else if (mem.eql(u8, arg, "-rdynamic")) { + linker_rdynamic = true; + } else if (mem.eql(u8, arg, "--pkg-begin")) { + if (i + 2 >= args.len) { + try stderr.write("expected [name] [path] after --pkg-begin\n"); + process.exit(1); + } + i += 1; + const new_pkg_name = args[i]; + i += 1; + const new_pkg_path = args[i]; + + var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); + try cur_pkg.children.append(new_cur_pkg); + cur_pkg = new_cur_pkg; + } else if (mem.eql(u8, arg, "--pkg-end")) { + if (cur_pkg.parent) |parent| { + cur_pkg = parent; + } else { + try stderr.write("encountered --pkg-end with no matching --pkg-begin\n"); + process.exit(1); + } + } else if (mem.startsWith(u8, arg, "-l")) { + try system_libs.append(arg[2..]); + } else { + try stderr.print("unrecognized parameter: '{}'", .{arg}); + process.exit(1); + } + } else if (mem.endsWith(u8, arg, ".s")) { + try assembly_files.append(arg); + } else if (mem.endsWith(u8, arg, ".o") or + mem.endsWith(u8, arg, ".obj") or + mem.endsWith(u8, arg, ".a") or + mem.endsWith(u8, arg, ".lib")) + { + try link_objects.append(arg); + } else if (mem.endsWith(u8, arg, ".c") or + mem.endsWith(u8, arg, ".cpp")) + { + try c_src_files.append(arg); + } else if (mem.endsWith(u8, arg, ".zig")) { + if (root_src_file) |other| { + try stderr.print("found another zig file '{}' after root source file '{}'", .{ + arg, + other, + }); + process.exit(1); + } else { + root_src_file = arg; + } } else { - try stderr.print("encountered --pkg-end with no matching --pkg-begin\n", .{}); - process.exit(1); + try stderr.print("unrecognized file extension of parameter '{}'", .{arg}); } } } @@ -340,18 +432,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co process.exit(1); } - const provided_name = flags.single("name"); - const root_source_file = switch (flags.positionals.len) { - 0 => null, - 1 => flags.positionals.at(0), - else => { - try stderr.print("unexpected extra parameter: {}\n", .{flags.positionals.at(1)}); - process.exit(1); - }, - }; - const root_name = if (provided_name) |n| n else blk: { - if (root_source_file) |file| { + if (root_src_file) |file| { const basename = fs.path.basename(file); var it = mem.separate(basename, "."); break :blk it.next() orelse basename; @@ -361,11 +443,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co } }; - const is_static = flags.present("static"); - - const assembly_files = flags.many("assembly"); - const link_objects = flags.many("object"); - if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) { + if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) { try stderr.write("Expected source file argument or at least one --object or --assembly argument\n"); process.exit(1); } @@ -375,15 +453,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co process.exit(1); } - var clang_argv_buf = ArrayList([]const u8).init(allocator); - defer clang_argv_buf.deinit(); - - const mllvm_flags = flags.many("mllvm"); - for (mllvm_flags) |mllvm| { - try clang_argv_buf.append("-mllvm"); - try clang_argv_buf.append(mllvm); - } - try ZigCompiler.setLlvmArgv(allocator, mllvm_flags); + try ZigCompiler.setLlvmArgv(allocator, mllvm_flags.toSliceConst()); const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1); defer allocator.free(zig_lib_dir); @@ -396,74 +466,60 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co var comp = try Compilation.create( &zig_compiler, root_name, - root_source_file, + root_src_file, Target.Native, out_type, build_mode, - is_static, + !is_dynamic, zig_lib_dir, ); defer comp.destroy(); - if (flags.single("libc")) |libc_path| { + if (libc_arg) |libc_path| { parseLibcPaths(allocator, &override_libc, libc_path); comp.override_libc = &override_libc; } - for (flags.many("library")) |lib| { + for (system_libs.toSliceConst()) |lib| { _ = try comp.addLinkLib(lib, true); } - comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10); - comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10); - comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10); - + comp.version = version; comp.is_test = false; - - comp.linker_script = flags.single("linker-script"); - comp.each_lib_rpath = flags.present("each-lib-rpath"); - + comp.linker_script = linker_script; comp.clang_argv = clang_argv_buf.toSliceConst(); + comp.strip = strip; - comp.strip = flags.present("strip"); - - comp.verbose_tokenize = flags.present("verbose-tokenize"); - comp.verbose_ast_tree = flags.present("verbose-ast-tree"); - comp.verbose_ast_fmt = flags.present("verbose-ast-fmt"); - comp.verbose_link = flags.present("verbose-link"); - comp.verbose_ir = flags.present("verbose-ir"); - comp.verbose_llvm_ir = flags.present("verbose-llvm-ir"); - comp.verbose_cimport = flags.present("verbose-cimport"); + comp.verbose_tokenize = verbose_tokenize; + comp.verbose_ast_tree = verbose_ast_tree; + comp.verbose_ast_fmt = verbose_ast_fmt; + comp.verbose_link = verbose_link; + comp.verbose_ir = verbose_ir; + comp.verbose_llvm_ir = verbose_llvm_ir; + comp.verbose_cimport = verbose_cimport; comp.err_color = color; - comp.lib_dirs = flags.many("library-path"); - comp.darwin_frameworks = flags.many("framework"); - comp.rpath_list = flags.many("rpath"); - if (flags.single("output-h")) |output_h| { - comp.out_h_path = output_h; - } - - comp.windows_subsystem_windows = flags.present("mwindows"); - comp.windows_subsystem_console = flags.present("mconsole"); - comp.linker_rdynamic = flags.present("rdynamic"); + comp.linker_rdynamic = linker_rdynamic; - if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) { + if (macosx_version_min != null and ios_version_min != null) { try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n"); process.exit(1); } - if (flags.single("mmacosx-version-min")) |ver| { + if (macosx_version_min) |ver| { comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver }; } - if (flags.single("mios-version-min")) |ver| { + if (ios_version_min) |ver| { comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver }; } - comp.emit_file_type = emit_type; - comp.assembly_files = assembly_files; - comp.link_out_file = flags.single("output"); - comp.link_objects = link_objects; + comp.emit_bin = emit_bin; + comp.emit_asm = emit_asm; + comp.emit_llvm_ir = emit_llvm_ir; + comp.emit_h = emit_h; + comp.assembly_files = assembly_files.toSliceConst(); + comp.link_objects = link_objects.toSliceConst(); comp.start(); processBuildEvents(comp, color); @@ -522,17 +578,6 @@ pub const usage_fmt = \\ ; -pub const args_fmt_spec = [_]Flag{ - Flag.Bool("--help"), - Flag.Bool("--check"), - Flag.Option("--color", &[_][]const u8{ - "auto", - "off", - "on", - }), - Flag.Bool("--stdin"), -}; - const Fmt = struct { seen: event.Locked(SeenMap), any_error: bool, @@ -578,30 +623,52 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void { } fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { - var flags = try Args.parse(allocator, &args_fmt_spec, args); - defer flags.deinit(); - - if (flags.present("help")) { - try stdout.write(usage_fmt); - process.exit(0); - } + var color: errmsg.Color = .Auto; + var stdin_flag: bool = false; + var check_flag: bool = false; + var input_files = ArrayList([]const u8).init(allocator); - const color: errmsg.Color = blk: { - if (flags.single("color")) |color_flag| { - if (mem.eql(u8, color_flag, "auto")) { - break :blk .Auto; - } else if (mem.eql(u8, color_flag, "on")) { - break :blk .On; - } else if (mem.eql(u8, color_flag, "off")) { - break :blk .Off; - } else unreachable; - } else { - break :blk .Auto; + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "--help")) { + try stdout.write(usage_fmt); + process.exit(0); + } else if (mem.eql(u8, arg, "--color")) { + if (i + 1 >= args.len) { + try stderr.write("expected [auto|on|off] after --color\n"); + process.exit(1); + } + i += 1; + const next_arg = args[i]; + if (mem.eql(u8, next_arg, "auto")) { + color = .Auto; + } else if (mem.eql(u8, next_arg, "on")) { + color = .On; + } else if (mem.eql(u8, next_arg, "off")) { + color = .Off; + } else { + try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); + process.exit(1); + } + } else if (mem.eql(u8, arg, "--stdin")) { + stdin_flag = true; + } else if (mem.eql(u8, arg, "--check")) { + check_flag = true; + } else { + try stderr.print("unrecognized parameter: '{}'", .{arg}); + process.exit(1); + } + } else { + try input_files.append(arg); + } } - }; + } - if (flags.present("stdin")) { - if (flags.positionals.len != 0) { + if (stdin_flag) { + if (input_files.len != 0) { try stderr.write("cannot use --stdin with positional arguments\n"); process.exit(1); } @@ -628,7 +695,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { if (tree.errors.len != 0) { process.exit(1); } - if (flags.present("check")) { + if (check_flag) { const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); const code: u8 = if (anything_changed) 1 else 0; process.exit(code); @@ -638,7 +705,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { return; } - if (flags.positionals.len == 0) { + if (input_files.len == 0) { try stderr.write("expected at least one source file argument\n"); process.exit(1); } @@ -650,11 +717,9 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { .color = color, }; - const check_mode = flags.present("check"); - var group = event.Group(FmtError!void).init(allocator); - for (flags.positionals.toSliceConst()) |file_path| { - try group.call(fmtPath, .{ &fmt, file_path, check_mode }); + for (input_files.toSliceConst()) |file_path| { + try group.call(fmtPath, .{ &fmt, file_path, check_flag }); } try group.wait(); if (fmt.any_error) { @@ -808,8 +873,6 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)}); } -const args_test_spec = [_]Flag{Flag.Bool("--help")}; - fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { try stdout.write(usage); } diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 59719a0c7d..1747e049da 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -9,10 +9,7 @@ const process = std.process; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; const Buffer = std.Buffer; -const arg = @import("arg.zig"); const self_hosted_main = @import("main.zig"); -const Args = arg.Args; -const Flag = arg.Flag; const errmsg = @import("errmsg.zig"); const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; @@ -169,31 +166,54 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { stderr_file = std.io.getStdErr(); stderr = &stderr_file.outStream().stream; - const args = args_list.toSliceConst(); - var flags = try Args.parse(allocator, &self_hosted_main.args_fmt_spec, args[2..]); - defer flags.deinit(); - - if (flags.present("help")) { - try stdout.write(self_hosted_main.usage_fmt); - process.exit(0); - } - - const color = blk: { - if (flags.single("color")) |color_flag| { - if (mem.eql(u8, color_flag, "auto")) { - break :blk errmsg.Color.Auto; - } else if (mem.eql(u8, color_flag, "on")) { - break :blk errmsg.Color.On; - } else if (mem.eql(u8, color_flag, "off")) { - break :blk errmsg.Color.Off; - } else unreachable; - } else { - break :blk errmsg.Color.Auto; + const args = args_list.toSliceConst()[2..]; + + var color: errmsg.Color = .Auto; + var stdin_flag: bool = false; + var check_flag: bool = false; + var input_files = ArrayList([]const u8).init(allocator); + + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "--help")) { + try stdout.write(self_hosted_main.usage_fmt); + process.exit(0); + } else if (mem.eql(u8, arg, "--color")) { + if (i + 1 >= args.len) { + try stderr.write("expected [auto|on|off] after --color\n"); + process.exit(1); + } + i += 1; + const next_arg = args[i]; + if (mem.eql(u8, next_arg, "auto")) { + color = .Auto; + } else if (mem.eql(u8, next_arg, "on")) { + color = .On; + } else if (mem.eql(u8, next_arg, "off")) { + color = .Off; + } else { + try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); + process.exit(1); + } + } else if (mem.eql(u8, arg, "--stdin")) { + stdin_flag = true; + } else if (mem.eql(u8, arg, "--check")) { + check_flag = true; + } else { + try stderr.print("unrecognized parameter: '{}'", .{arg}); + process.exit(1); + } + } else { + try input_files.append(arg); + } } - }; + } - if (flags.present("stdin")) { - if (flags.positionals.len != 0) { + if (stdin_flag) { + if (input_files.len != 0) { try stderr.write("cannot use --stdin with positional arguments\n"); process.exit(1); } @@ -217,7 +237,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { if (tree.errors.len != 0) { process.exit(1); } - if (flags.present("check")) { + if (check_flag) { const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); process.exit(code); @@ -227,7 +247,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { return; } - if (flags.positionals.len == 0) { + if (input_files.len == 0) { try stderr.write("expected at least one source file argument\n"); process.exit(1); } @@ -239,10 +259,8 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { .allocator = allocator, }; - const check_mode = flags.present("check"); - - for (flags.positionals.toSliceConst()) |file_path| { - try fmtPath(&fmt, file_path, check_mode); + for (input_files.toSliceConst()) |file_path| { + try fmtPath(&fmt, file_path, check_flag); } if (fmt.any_error) { process.exit(1); |
