authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-11 02:08:33-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-11 02:08:33-05:00
log7c1dbfab724291b492be5e64fd93ec14e48b202c
treee109e0fd711ca766ea148b1965b8762f3e24f4ea
parentc3d8b1ffebb94d180c382bd74128d17dc21c1392
signaturelock-open Commit is signed but in an unrecognized format.

self-hosted: manually parse args


7 files changed, 372 insertions(+), 760 deletions(-)

lib/std/meta/trait.zig-13
...@@ -14,7 +14,6 @@ fn traitFnWorkaround(comptime T: type) bool {...@@ -14,7 +14,6 @@ fn traitFnWorkaround(comptime T: type) bool {
14}14}
1515
16pub const TraitFn = @TypeOf(traitFnWorkaround);16pub const TraitFn = @TypeOf(traitFnWorkaround);
17///
1817
19//////Trait generators18//////Trait generators
2019
...@@ -55,7 +54,6 @@ test "std.meta.trait.multiTrait" {...@@ -55,7 +54,6 @@ test "std.meta.trait.multiTrait" {
55 testing.expect(!isVector(u8));54 testing.expect(!isVector(u8));
56}55}
5756
58///
59pub fn hasFn(comptime name: []const u8) TraitFn {57pub fn hasFn(comptime name: []const u8) TraitFn {
60 const Closure = struct {58 const Closure = struct {
61 pub fn trait(comptime T: type) bool {59 pub fn trait(comptime T: type) bool {
...@@ -79,7 +77,6 @@ test "std.meta.trait.hasFn" {...@@ -79,7 +77,6 @@ test "std.meta.trait.hasFn" {
79 testing.expect(!hasFn("useless")(u8));77 testing.expect(!hasFn("useless")(u8));
80}78}
8179
82///
83pub fn hasField(comptime name: []const u8) TraitFn {80pub fn hasField(comptime name: []const u8) TraitFn {
84 const Closure = struct {81 const Closure = struct {
85 pub fn trait(comptime T: type) bool {82 pub fn trait(comptime T: type) bool {
...@@ -113,7 +110,6 @@ test "std.meta.trait.hasField" {...@@ -113,7 +110,6 @@ test "std.meta.trait.hasField" {
113 testing.expect(!hasField("value")(u8));110 testing.expect(!hasField("value")(u8));
114}111}
115112
116///
117pub fn is(comptime id: builtin.TypeId) TraitFn {113pub fn is(comptime id: builtin.TypeId) TraitFn {
118 const Closure = struct {114 const Closure = struct {
119 pub fn trait(comptime T: type) bool {115 pub fn trait(comptime T: type) bool {
...@@ -131,7 +127,6 @@ test "std.meta.trait.is" {...@@ -131,7 +127,6 @@ test "std.meta.trait.is" {
131 testing.expect(!is(builtin.TypeId.Optional)(anyerror));127 testing.expect(!is(builtin.TypeId.Optional)(anyerror));
132}128}
133129
134///
135pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {130pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
136 const Closure = struct {131 const Closure = struct {
137 pub fn trait(comptime T: type) bool {132 pub fn trait(comptime T: type) bool {
...@@ -173,7 +168,6 @@ test "std.meta.trait.isExtern" {...@@ -173,7 +168,6 @@ test "std.meta.trait.isExtern" {
173 testing.expect(!isExtern(u8));168 testing.expect(!isExtern(u8));
174}169}
175170
176///
177pub fn isPacked(comptime T: type) bool {171pub fn isPacked(comptime T: type) bool {
178 const Packed = builtin.TypeInfo.ContainerLayout.Packed;172 const Packed = builtin.TypeInfo.ContainerLayout.Packed;
179 const info = @typeInfo(T);173 const info = @typeInfo(T);
...@@ -194,7 +188,6 @@ test "std.meta.trait.isPacked" {...@@ -194,7 +188,6 @@ test "std.meta.trait.isPacked" {
194 testing.expect(!isPacked(u8));188 testing.expect(!isPacked(u8));
195}189}
196190
197///
198pub fn isUnsignedInt(comptime T: type) bool {191pub fn isUnsignedInt(comptime T: type) bool {
199 return switch (@typeId(T)) {192 return switch (@typeId(T)) {
200 builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,193 builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
...@@ -209,7 +202,6 @@ test "isUnsignedInt" {...@@ -209,7 +202,6 @@ test "isUnsignedInt" {
209 testing.expect(isUnsignedInt(f64) == false);202 testing.expect(isUnsignedInt(f64) == false);
210}203}
211204
212///
213pub fn isSignedInt(comptime T: type) bool {205pub fn isSignedInt(comptime T: type) bool {
214 return switch (@typeId(T)) {206 return switch (@typeId(T)) {
215 builtin.TypeId.ComptimeInt => true,207 builtin.TypeId.ComptimeInt => true,
...@@ -225,7 +217,6 @@ test "isSignedInt" {...@@ -225,7 +217,6 @@ test "isSignedInt" {
225 testing.expect(isSignedInt(f64) == false);217 testing.expect(isSignedInt(f64) == false);
226}218}
227219
228///
229pub fn isSingleItemPtr(comptime T: type) bool {220pub fn isSingleItemPtr(comptime T: type) bool {
230 if (comptime is(builtin.TypeId.Pointer)(T)) {221 if (comptime is(builtin.TypeId.Pointer)(T)) {
231 const info = @typeInfo(T);222 const info = @typeInfo(T);
...@@ -241,7 +232,6 @@ test "std.meta.trait.isSingleItemPtr" {...@@ -241,7 +232,6 @@ test "std.meta.trait.isSingleItemPtr" {
241 testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));232 testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));
242}233}
243234
244///
245pub fn isManyItemPtr(comptime T: type) bool {235pub fn isManyItemPtr(comptime T: type) bool {
246 if (comptime is(builtin.TypeId.Pointer)(T)) {236 if (comptime is(builtin.TypeId.Pointer)(T)) {
247 const info = @typeInfo(T);237 const info = @typeInfo(T);
...@@ -258,7 +248,6 @@ test "std.meta.trait.isManyItemPtr" {...@@ -258,7 +248,6 @@ test "std.meta.trait.isManyItemPtr" {
258 testing.expect(!isManyItemPtr(@TypeOf(array[0..1])));248 testing.expect(!isManyItemPtr(@TypeOf(array[0..1])));
259}249}
260250
261///
262pub fn isSlice(comptime T: type) bool {251pub fn isSlice(comptime T: type) bool {
263 if (comptime is(builtin.TypeId.Pointer)(T)) {252 if (comptime is(builtin.TypeId.Pointer)(T)) {
264 const info = @typeInfo(T);253 const info = @typeInfo(T);
...@@ -274,7 +263,6 @@ test "std.meta.trait.isSlice" {...@@ -274,7 +263,6 @@ test "std.meta.trait.isSlice" {
274 testing.expect(!isSlice(@TypeOf(&array[0])));263 testing.expect(!isSlice(@TypeOf(&array[0])));
275}264}
276265
277///
278pub fn isIndexable(comptime T: type) bool {266pub fn isIndexable(comptime T: type) bool {
279 if (comptime is(builtin.TypeId.Pointer)(T)) {267 if (comptime is(builtin.TypeId.Pointer)(T)) {
280 const info = @typeInfo(T);268 const info = @typeInfo(T);
...@@ -297,7 +285,6 @@ test "std.meta.trait.isIndexable" {...@@ -297,7 +285,6 @@ test "std.meta.trait.isIndexable" {
297 testing.expect(!isIndexable(meta.Child(@TypeOf(slice))));285 testing.expect(!isIndexable(meta.Child(@TypeOf(slice))));
298}286}
299287
300///
301pub fn isNumber(comptime T: type) bool {288pub fn isNumber(comptime T: type) bool {
302 return switch (@typeId(T)) {289 return switch (@typeId(T)) {
303 builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true,290 builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true,
src-self-hosted/arg.zig deleted-293
...@@ -1,293 +0,0 @@
1const std = @import("std");
2const debug = std.debug;
3const testing = std.testing;
4const mem = std.mem;
5
6const Allocator = mem.Allocator;
7const ArrayList = std.ArrayList;
8const StringHashMap = std.StringHashMap;
9
10fn trimStart(slice: []const u8, ch: u8) []const u8 {
11 var i: usize = 0;
12 for (slice) |b| {
13 if (b != '-') break;
14 i += 1;
15 }
16
17 return slice[i..];
18}
19
20fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool {
21 if (maybe_set) |set| {
22 for (set) |possible| {
23 if (mem.eql(u8, arg, possible)) {
24 return true;
25 }
26 }
27 return false;
28 } else {
29 return true;
30 }
31}
32
33// Modifies the current argument index during iteration
34fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: *usize) !FlagArg {
35 switch (required) {
36 0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value?
37 1 => {
38 if (index.* + 1 >= args.len) {
39 return error.MissingFlagArguments;
40 }
41
42 index.* += 1;
43 const arg = args[index.*];
44
45 if (!argInAllowedSet(allowed_set, arg)) {
46 return error.ArgumentNotInAllowedSet;
47 }
48
49 return FlagArg{ .Single = arg };
50 },
51 else => |needed| {
52 var extra = ArrayList([]const u8).init(allocator);
53 errdefer extra.deinit();
54
55 var j: usize = 0;
56 while (j < needed) : (j += 1) {
57 if (index.* + 1 >= args.len) {
58 return error.MissingFlagArguments;
59 }
60
61 index.* += 1;
62 const arg = args[index.*];
63
64 if (!argInAllowedSet(allowed_set, arg)) {
65 return error.ArgumentNotInAllowedSet;
66 }
67
68 try extra.append(arg);
69 }
70
71 return FlagArg{ .Many = extra };
72 },
73 }
74}
75
76const HashMapFlags = StringHashMap(FlagArg);
77
78// A store for querying found flags and positional arguments.
79pub const Args = struct {
80 flags: HashMapFlags,
81 positionals: ArrayList([]const u8),
82
83 pub fn parse(allocator: *Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
84 var parsed = Args{
85 .flags = HashMapFlags.init(allocator),
86 .positionals = ArrayList([]const u8).init(allocator),
87 };
88
89 var i: usize = 0;
90 next: while (i < args.len) : (i += 1) {
91 const arg = args[i];
92
93 if (arg.len != 0 and arg[0] == '-') {
94 // TODO: hashmap, although the linear scan is okay for small argument sets as is
95 for (spec) |flag| {
96 if (mem.eql(u8, arg, flag.name)) {
97 const flag_name_trimmed = trimStart(flag.name, '-');
98 const flag_args = readFlagArguments(allocator, args, flag.required, flag.allowed_set, &i) catch |err| {
99 switch (err) {
100 error.ArgumentNotInAllowedSet => {
101 std.debug.warn("argument '{}' is invalid for flag '{}'\n", .{ args[i], arg });
102 std.debug.warn("allowed options are ", .{});
103 for (flag.allowed_set.?) |possible| {
104 std.debug.warn("'{}' ", .{possible});
105 }
106 std.debug.warn("\n", .{});
107 },
108 error.MissingFlagArguments => {
109 std.debug.warn("missing argument for flag: {}\n", .{arg});
110 },
111 else => {},
112 }
113
114 return err;
115 };
116
117 if (flag.mergable) {
118 var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator);
119
120 // MergeN creation disallows 0 length flag entry (doesn't make sense)
121 switch (flag_args) {
122 .None => unreachable,
123 .Single => |inner| try prev.append(inner),
124 .Many => |inner| try prev.appendSlice(inner.toSliceConst()),
125 }
126
127 _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
128 } else {
129 _ = try parsed.flags.put(flag_name_trimmed, flag_args);
130 }
131
132 continue :next;
133 }
134 }
135
136 // TODO: Better errors with context, global error state and return is sufficient.
137 std.debug.warn("could not match flag: {}\n", .{arg});
138 return error.UnknownFlag;
139 } else {
140 try parsed.positionals.append(arg);
141 }
142 }
143
144 return parsed;
145 }
146
147 pub fn deinit(self: *Args) void {
148 self.flags.deinit();
149 self.positionals.deinit();
150 }
151
152 // e.g. --help
153 pub fn present(self: *const Args, name: []const u8) bool {
154 return self.flags.contains(name);
155 }
156
157 // e.g. --name value
158 pub fn single(self: *Args, name: []const u8) ?[]const u8 {
159 if (self.flags.get(name)) |entry| {
160 switch (entry.value) {
161 .Single => |inner| {
162 return inner;
163 },
164 else => @panic("attempted to retrieve flag with wrong type"),
165 }
166 } else {
167 return null;
168 }
169 }
170
171 // e.g. --names value1 value2 value3
172 pub fn many(self: *Args, name: []const u8) []const []const u8 {
173 if (self.flags.get(name)) |entry| {
174 switch (entry.value) {
175 .Many => |inner| {
176 return inner.toSliceConst();
177 },
178 else => @panic("attempted to retrieve flag with wrong type"),
179 }
180 } else {
181 return &[_][]const u8{};
182 }
183 }
184};
185
186// Arguments for a flag. e.g. arg1, arg2 in `--command arg1 arg2`.
187const FlagArg = union(enum) {
188 None,
189 Single: []const u8,
190 Many: ArrayList([]const u8),
191};
192
193// Specification for how a flag should be parsed.
194pub const Flag = struct {
195 name: []const u8,
196 required: usize,
197 mergable: bool,
198 allowed_set: ?[]const []const u8,
199
200 pub fn Bool(comptime name: []const u8) Flag {
201 return ArgN(name, 0);
202 }
203
204 pub fn Arg1(comptime name: []const u8) Flag {
205 return ArgN(name, 1);
206 }
207
208 pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
209 return Flag{
210 .name = name,
211 .required = n,
212 .mergable = false,
213 .allowed_set = null,
214 };
215 }
216
217 pub fn ArgMergeN(comptime name: []const u8, comptime n: usize) Flag {
218 if (n == 0) {
219 @compileError("n must be greater than 0");
220 }
221
222 return Flag{
223 .name = name,
224 .required = n,
225 .mergable = true,
226 .allowed_set = null,
227 };
228 }
229
230 pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
231 return Flag{
232 .name = name,
233 .required = 1,
234 .mergable = false,
235 .allowed_set = set,
236 };
237 }
238};
239
240test "parse arguments" {
241 const spec1 = comptime [_]Flag{
242 Flag.Bool("--help"),
243 Flag.Bool("--init"),
244 Flag.Arg1("--build-file"),
245 Flag.Option("--color", [_][]const u8{
246 "on",
247 "off",
248 "auto",
249 }),
250 Flag.ArgN("--pkg-begin", 2),
251 Flag.ArgMergeN("--object", 1),
252 Flag.ArgN("--library", 1),
253 };
254
255 const cliargs = [_][]const u8{
256 "build",
257 "--help",
258 "pos1",
259 "--build-file",
260 "build.zig",
261 "--object",
262 "obj1",
263 "--object",
264 "obj2",
265 "--library",
266 "lib1",
267 "--library",
268 "lib2",
269 "--color",
270 "on",
271 "pos2",
272 };
273
274 var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);
275
276 testing.expect(args.present("help"));
277 testing.expect(!args.present("help2"));
278 testing.expect(!args.present("init"));
279
280 testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig"));
281 testing.expect(mem.eql(u8, args.single("color").?, "on"));
282
283 const objects = args.many("object").?;
284 testing.expect(mem.eql(u8, objects[0], "obj1"));
285 testing.expect(mem.eql(u8, objects[1], "obj2"));
286
287 testing.expect(mem.eql(u8, args.single("library").?, "lib2"));
288
289 const pos = args.positionals.toSliceConst();
290 testing.expect(mem.eql(u8, pos[0], "build"));
291 testing.expect(mem.eql(u8, pos[1], "pos1"));
292 testing.expect(mem.eql(u8, pos[2], "pos2"));
293}
src-self-hosted/codegen.zig-2
...@@ -101,8 +101,6 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -101,8 +101,6 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
101 _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);101 _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
102 }102 }
103103
104 assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types
105
106 const is_small = comp.build_mode == .ReleaseSmall;104 const is_small = comp.build_mode == .ReleaseSmall;
107 const is_debug = comp.build_mode == .Debug;105 const is_debug = comp.build_mode == .Debug;
108106
src-self-hosted/compilation.zig+5-12
...@@ -135,22 +135,17 @@ pub const Compilation = struct {...@@ -135,22 +135,17 @@ pub const Compilation = struct {
135 /// lazily created when we need it135 /// lazily created when we need it
136 tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),136 tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),
137137
138 version_major: u32 = 0,138 version: builtin.Version = builtin.Version{ .major = 0, .minor = 0, .patch = 0 },
139 version_minor: u32 = 0,
140 version_patch: u32 = 0,
141139
142 linker_script: ?[]const u8 = null,140 linker_script: ?[]const u8 = null,
143 out_h_path: ?[]const u8 = null,141 out_h_path: ?[]const u8 = null,
144142
145 is_test: bool = false,143 is_test: bool = false,
146 each_lib_rpath: bool = false,
147 strip: bool = false,144 strip: bool = false,
148 is_static: bool,145 is_static: bool,
149 linker_rdynamic: bool = false,146 linker_rdynamic: bool = false,
150147
151 clang_argv: []const []const u8 = &[_][]const u8{},148 clang_argv: []const []const u8 = &[_][]const u8{},
152 lib_dirs: []const []const u8 = &[_][]const u8{},
153 rpath_list: []const []const u8 = &[_][]const u8{},
154 assembly_files: []const []const u8 = &[_][]const u8{},149 assembly_files: []const []const u8 = &[_][]const u8{},
155150
156 /// paths that are explicitly provided by the user to link against151 /// paths that are explicitly provided by the user to link against
...@@ -162,9 +157,6 @@ pub const Compilation = struct {...@@ -162,9 +157,6 @@ pub const Compilation = struct {
162157
163 pub const FnLinkSet = std.TailQueue(?*Value.Fn);158 pub const FnLinkSet = std.TailQueue(?*Value.Fn);
164159
165 windows_subsystem_windows: bool = false,
166 windows_subsystem_console: bool = false,
167
168 link_libs_list: ArrayList(*LinkLib),160 link_libs_list: ArrayList(*LinkLib),
169 libc_link_lib: ?*LinkLib = null,161 libc_link_lib: ?*LinkLib = null,
170162
...@@ -178,17 +170,18 @@ pub const Compilation = struct {...@@ -178,17 +170,18 @@ pub const Compilation = struct {
178 verbose_llvm_ir: bool = false,170 verbose_llvm_ir: bool = false,
179 verbose_link: bool = false,171 verbose_link: bool = false,
180172
181 darwin_frameworks: []const []const u8 = &[_][]const u8{},
182 darwin_version_min: DarwinVersionMin = .None,173 darwin_version_min: DarwinVersionMin = .None,
183174
184 test_filters: []const []const u8 = &[_][]const u8{},175 test_filters: []const []const u8 = &[_][]const u8{},
185 test_name_prefix: ?[]const u8 = null,176 test_name_prefix: ?[]const u8 = null,
186177
187 emit_file_type: Emit = .Binary,178 emit_bin: bool = true,
179 emit_asm: bool = false,
180 emit_llvm_ir: bool = false,
181 emit_h: bool = false,
188182
189 kind: Kind,183 kind: Kind,
190184
191 link_out_file: ?[]const u8 = null,
192 events: *event.Channel(Event),185 events: *event.Channel(Event),
193186
194 exported_symbol_names: event.Locked(Decl.Table),187 exported_symbol_names: event.Locked(Decl.Table),
src-self-hosted/link.zig+11-165
...@@ -36,21 +36,17 @@ pub fn link(comp: *Compilation) !void {...@@ -36,21 +36,17 @@ pub fn link(comp: *Compilation) !void {
36 ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);36 ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
37 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);37 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
3838
39 if (comp.link_out_file) |out_file| {39 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
40 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file);40 switch (comp.kind) {
41 } else {41 .Exe => {
42 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());42 try ctx.out_file_path.append(comp.target.exeFileExt());
43 switch (comp.kind) {43 },
44 .Exe => {44 .Lib => {
45 try ctx.out_file_path.append(comp.target.exeFileExt());45 try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());
46 },46 },
47 .Lib => {47 .Obj => {
48 try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());48 try ctx.out_file_path.append(comp.target.oFileExt());
49 },49 },
50 .Obj => {
51 try ctx.out_file_path.append(comp.target.oFileExt());
52 },
53 }
54 }50 }
5551
56 // even though we're calling LLD as a library it thinks the first52 // even though we're calling LLD as a library it thinks the first
...@@ -183,37 +179,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -183,37 +179,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
183 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);179 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
184 }180 }
185181
186 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
187 // Buf *rpath = g->rpath_list.at(i);
188 // add_rpath(lj, rpath);
189 //}
190 //if (g->each_lib_rpath) {
191 // for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
192 // const char *lib_dir = g->lib_dirs.at(i);
193 // for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
194 // LinkLib *link_lib = g->link_libs_list.at(i);
195 // if (buf_eql_str(link_lib->name, "c")) {
196 // continue;
197 // }
198 // bool does_exist;
199 // Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib->name));
200 // if (os_file_exists(test_path, &does_exist) != ErrorNone) {
201 // zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path));
202 // }
203 // if (does_exist) {
204 // add_rpath(lj, buf_create_from_str(lib_dir));
205 // break;
206 // }
207 // }
208 // }
209 //}
210
211 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
212 // const char *lib_dir = g->lib_dirs.at(i);
213 // lj->args.append("-L");
214 // lj->args.append(lib_dir);
215 //}
216
217 if (ctx.comp.haveLibC()) {182 if (ctx.comp.haveLibC()) {
218 try ctx.args.append("-L");183 try ctx.args.append("-L");
219 // TODO addNullByte should probably return [:0]u8184 // TODO addNullByte should probably return [:0]u8
...@@ -326,12 +291,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -326,12 +291,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
326 else => return error.UnsupportedLinkArchitecture,291 else => return error.UnsupportedLinkArchitecture,
327 }292 }
328293
329 if (ctx.comp.windows_subsystem_windows) {
330 try ctx.args.append("/SUBSYSTEM:windows");
331 } else if (ctx.comp.windows_subsystem_console) {
332 try ctx.args.append("/SUBSYSTEM:console");
333 }
334
335 const is_library = ctx.comp.kind == .Lib;294 const is_library = ctx.comp.kind == .Lib;
336295
337 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});296 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 {...@@ -374,12 +333,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
374 try ctx.args.append("-NODEFAULTLIB");333 try ctx.args.append("-NODEFAULTLIB");
375 if (!is_library) {334 if (!is_library) {
376 try ctx.args.append("-ENTRY:WinMainCRTStartup");335 try ctx.args.append("-ENTRY:WinMainCRTStartup");
377 // TODO
378 //if (g->have_winmain) {
379 // lj->args.append("-ENTRY:WinMain");
380 //} else {
381 // lj->args.append("-ENTRY:WinMainCRTStartup");
382 //}
383 }336 }
384 }337 }
385338
...@@ -387,11 +340,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -387,11 +340,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
387 try ctx.args.append("-DLL");340 try ctx.args.append("-DLL");
388 }341 }
389342
390 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
391 // const char *lib_dir = g->lib_dirs.at(i);
392 // lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
393 //}
394
395 for (ctx.comp.link_objects) |link_object| {343 for (ctx.comp.link_objects) |link_object| {
396 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);344 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
397 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));345 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
...@@ -402,63 +350,10 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -402,63 +350,10 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
402 .Exe, .Lib => {350 .Exe, .Lib => {
403 if (!ctx.comp.haveLibC()) {351 if (!ctx.comp.haveLibC()) {
404 @panic("TODO");352 @panic("TODO");
405 //Buf *builtin_o_path = build_o(g, "builtin");
406 //lj->args.append(buf_ptr(builtin_o_path));
407 }353 }
408
409 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
410 // TODO
411 //Buf *compiler_rt_o_path = build_compiler_rt(g);
412 //lj->args.append(buf_ptr(compiler_rt_o_path));
413 },354 },
414 .Obj => {},355 .Obj => {},
415 }356 }
416
417 //Buf *def_contents = buf_alloc();
418 //ZigList<const char *> gen_lib_args = {0};
419 //for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
420 // LinkLib *link_lib = g->link_libs_list.at(lib_i);
421 // if (buf_eql_str(link_lib->name, "c")) {
422 // continue;
423 // }
424 // if (link_lib->provided_explicitly) {
425 // if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) {
426 // Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
427 // lj->args.append(buf_ptr(arg));
428 // }
429 // else {
430 // lj->args.append(buf_ptr(link_lib->name));
431 // }
432 // } else {
433 // buf_resize(def_contents, 0);
434 // buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
435 // for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
436 // Buf *symbol_name = link_lib->symbols.at(exp_i);
437 // buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
438 // }
439 // buf_appendf(def_contents, "\n");
440
441 // Buf *def_path = buf_alloc();
442 // os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
443 // os_write_file(def_path, def_contents);
444
445 // Buf *generated_lib_path = buf_alloc();
446 // os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
447
448 // gen_lib_args.resize(0);
449 // gen_lib_args.append("link");
450
451 // coff_append_machine_arg(g, &gen_lib_args);
452 // gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
453 // gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
454 // Buf diag = BUF_INIT;
455 // if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
456 // fprintf(stderr, "%s\n", buf_ptr(&diag));
457 // exit(1);
458 // }
459 // lj->args.append(buf_ptr(generated_lib_path));
460 // }
461 //}
462}357}
463358
464fn constructLinkerArgsMachO(ctx: *Context) !void {359fn constructLinkerArgsMachO(ctx: *Context) !void {
...@@ -476,32 +371,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -476,32 +371,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
476 try ctx.args.append("-dynamic");371 try ctx.args.append("-dynamic");
477 }372 }
478373
479 //if (is_lib) {
480 // if (!g->is_static) {
481 // lj->args.append("-dylib");
482
483 // Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major);
484 // lj->args.append("-compatibility_version");
485 // lj->args.append(buf_ptr(compat_vers));
486
487 // Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
488 // g->version_major, g->version_minor, g->version_patch);
489 // lj->args.append("-current_version");
490 // lj->args.append(buf_ptr(cur_vers));
491
492 // // TODO getting an error when running an executable when doing this rpath thing
493 // //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib",
494 // // buf_ptr(g->root_out_name), g->version_major);
495 // //lj->args.append("-install_name");
496 // //lj->args.append(buf_ptr(dylib_install_name));
497
498 // if (buf_len(&lj->out_file) == 0) {
499 // buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
500 // buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
501 // }
502 // }
503 //}
504
505 try ctx.args.append("-arch");374 try ctx.args.append("-arch");
506 try ctx.args.append(util.getDarwinArchString(ctx.comp.target));375 try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
507376
...@@ -529,12 +398,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -529,12 +398,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
529 try ctx.args.append("-o");398 try ctx.args.append("-o");
530 try ctx.args.append(ctx.out_file_path.toSliceConst());399 try ctx.args.append(ctx.out_file_path.toSliceConst());
531400
532 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
533 // Buf *rpath = g->rpath_list.at(i);
534 // add_rpath(lj, rpath);
535 //}
536 //add_rpath(lj, &lj->out_file);
537
538 if (shared) {401 if (shared) {
539 try ctx.args.append("-headerpad_max_install_names");402 try ctx.args.append("-headerpad_max_install_names");
540 } else if (ctx.comp.is_static) {403 } else if (ctx.comp.is_static) {
...@@ -563,24 +426,12 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -563,24 +426,12 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
563 }426 }
564 }427 }
565428
566 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
567 // const char *lib_dir = g->lib_dirs.at(i);
568 // lj->args.append("-L");
569 // lj->args.append(lib_dir);
570 //}
571
572 for (ctx.comp.link_objects) |link_object| {429 for (ctx.comp.link_objects) |link_object| {
573 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);430 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
574 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));431 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
575 }432 }
576 try addFnObjects(ctx);433 try addFnObjects(ctx);
577434
578 //// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
579 //if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
580 // Buf *compiler_rt_o_path = build_compiler_rt(g);
581 // lj->args.append(buf_ptr(compiler_rt_o_path));
582 //}
583
584 if (ctx.comp.target == Target.Native) {435 if (ctx.comp.target == Target.Native) {
585 for (ctx.comp.link_libs_list.toSliceConst()) |lib| {436 for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
586 if (mem.eql(u8, lib.name, "c")) {437 if (mem.eql(u8, lib.name, "c")) {
...@@ -613,11 +464,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -613,11 +464,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
613 } else {464 } else {
614 @panic("TODO");465 @panic("TODO");
615 }466 }
616
617 //for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
618 // lj->args.append("-framework");
619 // lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
620 //}
621}467}
622468
623fn constructLinkerArgsWasm(ctx: *Context) void {469fn constructLinkerArgsWasm(ctx: *Context) void {
src-self-hosted/main.zig+306-243
...@@ -11,11 +11,8 @@ const Allocator = mem.Allocator;...@@ -11,11 +11,8 @@ const Allocator = mem.Allocator;
11const ArrayList = std.ArrayList;11const ArrayList = std.ArrayList;
12const Buffer = std.Buffer;12const Buffer = std.Buffer;
1313
14const arg = @import("arg.zig");
15const c = @import("c.zig");14const c = @import("c.zig");
16const introspect = @import("introspect.zig");15const introspect = @import("introspect.zig");
17const Args = arg.Args;
18const Flag = arg.Flag;
19const ZigCompiler = @import("compilation.zig").ZigCompiler;16const ZigCompiler = @import("compilation.zig").ZigCompiler;
20const Compilation = @import("compilation.zig").Compilation;17const Compilation = @import("compilation.zig").Compilation;
21const Target = std.Target;18const Target = std.Target;
...@@ -53,11 +50,7 @@ const Command = struct {...@@ -53,11 +50,7 @@ const Command = struct {
53};50};
5451
55pub fn main() !void {52pub fn main() !void {
56 // This allocator needs to be thread-safe because we use it for the event.Loop53 const allocator = std.heap.c_allocator;
57 // which multiplexes async functions onto kernel threads.
58 // libc allocator is guaranteed to have this property.
59 // TODO https://github.com/ziglang/zig/issues/3783
60 const allocator = std.heap.page_allocator;
6154
62 stdout = &std.io.getStdOut().outStream().stream;55 stdout = &std.io.getStdOut().outStream().stream;
6356
...@@ -65,7 +58,7 @@ pub fn main() !void {...@@ -65,7 +58,7 @@ pub fn main() !void {
65 stderr = &stderr_file.outStream().stream;58 stderr = &stderr_file.outStream().stream;
6659
67 const args = try process.argsAlloc(allocator);60 const args = try process.argsAlloc(allocator);
68 // TODO I'm getting unreachable code here, which shouldn't happen61 // TODO I'm getting unreachable code here, which shouldn't happen
69 //defer process.argsFree(allocator, args);62 //defer process.argsFree(allocator, args);
7063
71 if (args.len <= 1) {64 if (args.len <= 1) {
...@@ -182,8 +175,6 @@ const usage_build_generic =...@@ -182,8 +175,6 @@ const usage_build_generic =
182 \\ --object [obj] Add object file to build175 \\ --object [obj] Add object file to build
183 \\ -rdynamic Add all symbols to the dynamic symbol table176 \\ -rdynamic Add all symbols to the dynamic symbol table
184 \\ -rpath [path] Add directory to the runtime library search path177 \\ -rpath [path] Add directory to the runtime library search path
185 \\ -mconsole (windows) --subsystem console to the linker
186 \\ -mwindows (windows) --subsystem windows to the linker
187 \\ -framework [name] (darwin) link against framework178 \\ -framework [name] (darwin) link against framework
188 \\ -mios-version-min [ver] (darwin) set iOS deployment target179 \\ -mios-version-min [ver] (darwin) set iOS deployment target
189 \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target180 \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target
...@@ -194,143 +185,244 @@ const usage_build_generic =...@@ -194,143 +185,244 @@ const usage_build_generic =
194 \\185 \\
195;186;
196187
197const args_build_generic = [_]Flag{
198 Flag.Bool("--help"),
199 Flag.Option("--color", &[_][]const u8{
200 "auto",
201 "off",
202 "on",
203 }),
204 Flag.Option("--mode", &[_][]const u8{
205 "debug",
206 "release-fast",
207 "release-safe",
208 "release-small",
209 }),
210
211 Flag.ArgMergeN("--assembly", 1),
212 Flag.Option("--emit", &[_][]const u8{
213 "asm",
214 "bin",
215 "llvm-ir",
216 }),
217 Flag.Bool("--enable-timing-info"),
218 Flag.Arg1("--libc"),
219 Flag.Arg1("--name"),
220 Flag.Arg1("--output"),
221 Flag.Arg1("--output-h"),
222 // NOTE: Parsed manually after initial check
223 Flag.ArgN("--pkg-begin", 2),
224 Flag.Bool("--pkg-end"),
225 Flag.Bool("--static"),
226 Flag.Bool("--strip"),
227 Flag.Arg1("-target"),
228 Flag.Bool("--verbose-tokenize"),
229 Flag.Bool("--verbose-ast-tree"),
230 Flag.Bool("--verbose-ast-fmt"),
231 Flag.Bool("--verbose-link"),
232 Flag.Bool("--verbose-ir"),
233 Flag.Bool("--verbose-llvm-ir"),
234 Flag.Bool("--verbose-cimport"),
235 Flag.Arg1("-dirafter"),
236 Flag.ArgMergeN("-isystem", 1),
237 Flag.Arg1("-mllvm"),
238
239 Flag.Arg1("--ar-path"),
240 Flag.Bool("--each-lib-rpath"),
241 Flag.ArgMergeN("--library", 1),
242 Flag.ArgMergeN("--forbid-library", 1),
243 Flag.ArgMergeN("--library-path", 1),
244 Flag.Arg1("--linker-script"),
245 Flag.ArgMergeN("--object", 1),
246 // NOTE: Removed -L since it would need to be special-cased and we have an alias in library-path
247 Flag.Bool("-rdynamic"),
248 Flag.Arg1("-rpath"),
249 Flag.Bool("-mconsole"),
250 Flag.Bool("-mwindows"),
251 Flag.ArgMergeN("-framework", 1),
252 Flag.Arg1("-mios-version-min"),
253 Flag.Arg1("-mmacosx-version-min"),
254 Flag.Arg1("--ver-major"),
255 Flag.Arg1("--ver-minor"),
256 Flag.Arg1("--ver-patch"),
257};
258
259fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {188fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
260 var flags = try Args.parse(allocator, &args_build_generic, args);189 var color: errmsg.Color = .Auto;
261 defer flags.deinit();190 var build_mode: std.builtin.Mode = .Debug;
262191 var emit_bin = true;
263 if (flags.present("help")) {192 var emit_asm = false;
264 try stdout.write(usage_build_generic);193 var emit_llvm_ir = false;
265 process.exit(0);194 var emit_h = false;
266 }195 var provided_name: ?[]const u8 = null;
196 var is_dynamic = false;
197 var root_src_file: ?[]const u8 = null;
198 var libc_arg: ?[]const u8 = null;
199 var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 };
200 var linker_script: ?[]const u8 = null;
201 var strip = false;
202 var verbose_tokenize = false;
203 var verbose_ast_tree = false;
204 var verbose_ast_fmt = false;
205 var verbose_link = false;
206 var verbose_ir = false;
207 var verbose_llvm_ir = false;
208 var verbose_cimport = false;
209 var linker_rdynamic = false;
210 var macosx_version_min: ?[]const u8 = null;
211 var ios_version_min: ?[]const u8 = null;
212
213 var assembly_files = ArrayList([]const u8).init(allocator);
214 defer assembly_files.deinit();
215
216 var link_objects = ArrayList([]const u8).init(allocator);
217 defer link_objects.deinit();
267218
268 const build_mode: std.builtin.Mode = blk: {219 var clang_argv_buf = ArrayList([]const u8).init(allocator);
269 if (flags.single("mode")) |mode_flag| {220 defer clang_argv_buf.deinit();
270 if (mem.eql(u8, mode_flag, "debug")) {
271 break :blk .Debug;
272 } else if (mem.eql(u8, mode_flag, "release-fast")) {
273 break :blk .ReleaseFast;
274 } else if (mem.eql(u8, mode_flag, "release-safe")) {
275 break :blk .ReleaseSafe;
276 } else if (mem.eql(u8, mode_flag, "release-small")) {
277 break :blk .ReleaseSmall;
278 } else unreachable;
279 } else {
280 break :blk .Debug;
281 }
282 };
283221
284 const color: errmsg.Color = blk: {222 var mllvm_flags = ArrayList([]const u8).init(allocator);
285 if (flags.single("color")) |color_flag| {223 defer mllvm_flags.deinit();
286 if (mem.eql(u8, color_flag, "auto")) {
287 break :blk .Auto;
288 } else if (mem.eql(u8, color_flag, "on")) {
289 break :blk .On;
290 } else if (mem.eql(u8, color_flag, "off")) {
291 break :blk .Off;
292 } else unreachable;
293 } else {
294 break :blk .Auto;
295 }
296 };
297
298 const emit_type: Compilation.Emit = blk: {
299 if (flags.single("emit")) |emit_flag| {
300 if (mem.eql(u8, emit_flag, "asm")) {
301 break :blk .Assembly;
302 } else if (mem.eql(u8, emit_flag, "bin")) {
303 break :blk .Binary;
304 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {
305 break :blk .LlvmIr;
306 } else unreachable;
307 } else {
308 break :blk .Binary;
309 }
310 };
311224
312 var cur_pkg = try CliPkg.init(allocator, "", "", null);225 var cur_pkg = try CliPkg.init(allocator, "", "", null);
313 defer cur_pkg.deinit();226 defer cur_pkg.deinit();
314227
315 var i: usize = 0;228 var system_libs = ArrayList([]const u8).init(allocator);
316 while (i < args.len) : (i += 1) {229 defer system_libs.deinit();
317 const arg_name = args[i];230
318 if (mem.eql(u8, "--pkg-begin", arg_name)) {231 var c_src_files = ArrayList([]const u8).init(allocator);
319 // following two arguments guaranteed to exist due to arg parsing232 defer c_src_files.deinit();
320 i += 1;233
321 const new_pkg_name = args[i];234 {
322 i += 1;235 var i: usize = 0;
323 const new_pkg_path = args[i];236 while (i < args.len) : (i += 1) {
324237 const arg = args[i];
325 var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);238 if (mem.startsWith(u8, arg, "-")) {
326 try cur_pkg.children.append(new_cur_pkg);239 if (mem.eql(u8, arg, "--help")) {
327 cur_pkg = new_cur_pkg;240 try stdout.write(usage_build_generic);
328 } else if (mem.eql(u8, "--pkg-end", arg_name)) {241 process.exit(0);
329 if (cur_pkg.parent) |parent| {242 } else if (mem.eql(u8, arg, "--color")) {
330 cur_pkg = parent;243 if (i + 1 >= args.len) {
244 try stderr.write("expected [auto|on|off] after --color\n");
245 process.exit(1);
246 }
247 i += 1;
248 const next_arg = args[i];
249 if (mem.eql(u8, next_arg, "auto")) {
250 color = .Auto;
251 } else if (mem.eql(u8, next_arg, "on")) {
252 color = .On;
253 } else if (mem.eql(u8, next_arg, "off")) {
254 color = .Off;
255 } else {
256 try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
257 process.exit(1);
258 }
259 } else if (mem.eql(u8, arg, "--mode")) {
260 if (i + 1 >= args.len) {
261 try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
262 process.exit(1);
263 }
264 i += 1;
265 const next_arg = args[i];
266 if (mem.eql(u8, next_arg, "Debug")) {
267 build_mode = .Debug;
268 } else if (mem.eql(u8, next_arg, "ReleaseSafe")) {
269 build_mode = .ReleaseSafe;
270 } else if (mem.eql(u8, next_arg, "ReleaseFast")) {
271 build_mode = .ReleaseFast;
272 } else if (mem.eql(u8, next_arg, "ReleaseSmall")) {
273 build_mode = .ReleaseSmall;
274 } else {
275 try stderr.print("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'\n", .{next_arg});
276 process.exit(1);
277 }
278 } else if (mem.eql(u8, arg, "--name")) {
279 if (i + 1 >= args.len) {
280 try stderr.write("expected parameter after --name\n");
281 process.exit(1);
282 }
283 i += 1;
284 provided_name = args[i];
285 } else if (mem.eql(u8, arg, "--ver-major")) {
286 if (i + 1 >= args.len) {
287 try stderr.write("expected parameter after --ver-major\n");
288 process.exit(1);
289 }
290 i += 1;
291 version.major = try std.fmt.parseInt(u32, args[i], 10);
292 } else if (mem.eql(u8, arg, "--ver-minor")) {
293 if (i + 1 >= args.len) {
294 try stderr.write("expected parameter after --ver-minor\n");
295 process.exit(1);
296 }
297 i += 1;
298 version.minor = try std.fmt.parseInt(u32, args[i], 10);
299 } else if (mem.eql(u8, arg, "--ver-patch")) {
300 if (i + 1 >= args.len) {
301 try stderr.write("expected parameter after --ver-patch\n");
302 process.exit(1);
303 }
304 i += 1;
305 version.patch = try std.fmt.parseInt(u32, args[i], 10);
306 } else if (mem.eql(u8, arg, "--linker-script")) {
307 if (i + 1 >= args.len) {
308 try stderr.write("expected parameter after --linker-script\n");
309 process.exit(1);
310 }
311 i += 1;
312 linker_script = args[i];
313 } else if (mem.eql(u8, arg, "--libc")) {
314 if (i + 1 >= args.len) {
315 try stderr.write("expected parameter after --libc\n");
316 process.exit(1);
317 }
318 i += 1;
319 libc_arg = args[i];
320 } else if (mem.eql(u8, arg, "-mllvm")) {
321 if (i + 1 >= args.len) {
322 try stderr.write("expected parameter after -mllvm\n");
323 process.exit(1);
324 }
325 i += 1;
326 try clang_argv_buf.append("-mllvm");
327 try clang_argv_buf.append(args[i]);
328
329 try mllvm_flags.append(args[i]);
330 } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
331 if (i + 1 >= args.len) {
332 try stderr.write("expected parameter after -mmacosx-version-min\n");
333 process.exit(1);
334 }
335 i += 1;
336 macosx_version_min = args[i];
337 } else if (mem.eql(u8, arg, "-mios-version-min")) {
338 if (i + 1 >= args.len) {
339 try stderr.write("expected parameter after -mios-version-min\n");
340 process.exit(1);
341 }
342 i += 1;
343 ios_version_min = args[i];
344 } else if (mem.eql(u8, arg, "-femit-bin")) {
345 emit_bin = true;
346 } else if (mem.eql(u8, arg, "-fno-emit-bin")) {
347 emit_bin = false;
348 } else if (mem.eql(u8, arg, "-femit-asm")) {
349 emit_asm = true;
350 } else if (mem.eql(u8, arg, "-fno-emit-asm")) {
351 emit_asm = false;
352 } else if (mem.eql(u8, arg, "-femit-llvm-ir")) {
353 emit_llvm_ir = true;
354 } else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) {
355 emit_llvm_ir = false;
356 } else if (mem.eql(u8, arg, "-dynamic")) {
357 is_dynamic = true;
358 } else if (mem.eql(u8, arg, "--strip")) {
359 strip = true;
360 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
361 verbose_tokenize = true;
362 } else if (mem.eql(u8, arg, "--verbose-ast-tree")) {
363 verbose_ast_tree = true;
364 } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) {
365 verbose_ast_fmt = true;
366 } else if (mem.eql(u8, arg, "--verbose-link")) {
367 verbose_link = true;
368 } else if (mem.eql(u8, arg, "--verbose-ir")) {
369 verbose_ir = true;
370 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
371 verbose_llvm_ir = true;
372 } else if (mem.eql(u8, arg, "--verbose-cimport")) {
373 verbose_cimport = true;
374 } else if (mem.eql(u8, arg, "-rdynamic")) {
375 linker_rdynamic = true;
376 } else if (mem.eql(u8, arg, "--pkg-begin")) {
377 if (i + 2 >= args.len) {
378 try stderr.write("expected [name] [path] after --pkg-begin\n");
379 process.exit(1);
380 }
381 i += 1;
382 const new_pkg_name = args[i];
383 i += 1;
384 const new_pkg_path = args[i];
385
386 var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);
387 try cur_pkg.children.append(new_cur_pkg);
388 cur_pkg = new_cur_pkg;
389 } else if (mem.eql(u8, arg, "--pkg-end")) {
390 if (cur_pkg.parent) |parent| {
391 cur_pkg = parent;
392 } else {
393 try stderr.write("encountered --pkg-end with no matching --pkg-begin\n");
394 process.exit(1);
395 }
396 } else if (mem.startsWith(u8, arg, "-l")) {
397 try system_libs.append(arg[2..]);
398 } else {
399 try stderr.print("unrecognized parameter: '{}'", .{arg});
400 process.exit(1);
401 }
402 } else if (mem.endsWith(u8, arg, ".s")) {
403 try assembly_files.append(arg);
404 } else if (mem.endsWith(u8, arg, ".o") or
405 mem.endsWith(u8, arg, ".obj") or
406 mem.endsWith(u8, arg, ".a") or
407 mem.endsWith(u8, arg, ".lib"))
408 {
409 try link_objects.append(arg);
410 } else if (mem.endsWith(u8, arg, ".c") or
411 mem.endsWith(u8, arg, ".cpp"))
412 {
413 try c_src_files.append(arg);
414 } else if (mem.endsWith(u8, arg, ".zig")) {
415 if (root_src_file) |other| {
416 try stderr.print("found another zig file '{}' after root source file '{}'", .{
417 arg,
418 other,
419 });
420 process.exit(1);
421 } else {
422 root_src_file = arg;
423 }
331 } else {424 } else {
332 try stderr.print("encountered --pkg-end with no matching --pkg-begin\n", .{});425 try stderr.print("unrecognized file extension of parameter '{}'", .{arg});
333 process.exit(1);
334 }426 }
335 }427 }
336 }428 }
...@@ -340,18 +432,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -340,18 +432,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
340 process.exit(1);432 process.exit(1);
341 }433 }
342434
343 const provided_name = flags.single("name");
344 const root_source_file = switch (flags.positionals.len) {
345 0 => null,
346 1 => flags.positionals.at(0),
347 else => {
348 try stderr.print("unexpected extra parameter: {}\n", .{flags.positionals.at(1)});
349 process.exit(1);
350 },
351 };
352
353 const root_name = if (provided_name) |n| n else blk: {435 const root_name = if (provided_name) |n| n else blk: {
354 if (root_source_file) |file| {436 if (root_src_file) |file| {
355 const basename = fs.path.basename(file);437 const basename = fs.path.basename(file);
356 var it = mem.separate(basename, ".");438 var it = mem.separate(basename, ".");
357 break :blk it.next() orelse basename;439 break :blk it.next() orelse basename;
...@@ -361,11 +443,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -361,11 +443,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
361 }443 }
362 };444 };
363445
364 const is_static = flags.present("static");446 if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {
365
366 const assembly_files = flags.many("assembly");
367 const link_objects = flags.many("object");
368 if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) {
369 try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");447 try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
370 process.exit(1);448 process.exit(1);
371 }449 }
...@@ -375,15 +453,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -375,15 +453,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
375 process.exit(1);453 process.exit(1);
376 }454 }
377455
378 var clang_argv_buf = ArrayList([]const u8).init(allocator);456 try ZigCompiler.setLlvmArgv(allocator, mllvm_flags.toSliceConst());
379 defer clang_argv_buf.deinit();
380
381 const mllvm_flags = flags.many("mllvm");
382 for (mllvm_flags) |mllvm| {
383 try clang_argv_buf.append("-mllvm");
384 try clang_argv_buf.append(mllvm);
385 }
386 try ZigCompiler.setLlvmArgv(allocator, mllvm_flags);
387457
388 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1);458 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1);
389 defer allocator.free(zig_lib_dir);459 defer allocator.free(zig_lib_dir);
...@@ -396,74 +466,60 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -396,74 +466,60 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
396 var comp = try Compilation.create(466 var comp = try Compilation.create(
397 &zig_compiler,467 &zig_compiler,
398 root_name,468 root_name,
399 root_source_file,469 root_src_file,
400 Target.Native,470 Target.Native,
401 out_type,471 out_type,
402 build_mode,472 build_mode,
403 is_static,473 !is_dynamic,
404 zig_lib_dir,474 zig_lib_dir,
405 );475 );
406 defer comp.destroy();476 defer comp.destroy();
407477
408 if (flags.single("libc")) |libc_path| {478 if (libc_arg) |libc_path| {
409 parseLibcPaths(allocator, &override_libc, libc_path);479 parseLibcPaths(allocator, &override_libc, libc_path);
410 comp.override_libc = &override_libc;480 comp.override_libc = &override_libc;
411 }481 }
412482
413 for (flags.many("library")) |lib| {483 for (system_libs.toSliceConst()) |lib| {
414 _ = try comp.addLinkLib(lib, true);484 _ = try comp.addLinkLib(lib, true);
415 }485 }
416486
417 comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);487 comp.version = version;
418 comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
419 comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
420
421 comp.is_test = false;488 comp.is_test = false;
422489 comp.linker_script = linker_script;
423 comp.linker_script = flags.single("linker-script");
424 comp.each_lib_rpath = flags.present("each-lib-rpath");
425
426 comp.clang_argv = clang_argv_buf.toSliceConst();490 comp.clang_argv = clang_argv_buf.toSliceConst();
491 comp.strip = strip;
427492
428 comp.strip = flags.present("strip");493 comp.verbose_tokenize = verbose_tokenize;
429494 comp.verbose_ast_tree = verbose_ast_tree;
430 comp.verbose_tokenize = flags.present("verbose-tokenize");495 comp.verbose_ast_fmt = verbose_ast_fmt;
431 comp.verbose_ast_tree = flags.present("verbose-ast-tree");496 comp.verbose_link = verbose_link;
432 comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");497 comp.verbose_ir = verbose_ir;
433 comp.verbose_link = flags.present("verbose-link");498 comp.verbose_llvm_ir = verbose_llvm_ir;
434 comp.verbose_ir = flags.present("verbose-ir");499 comp.verbose_cimport = verbose_cimport;
435 comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
436 comp.verbose_cimport = flags.present("verbose-cimport");
437500
438 comp.err_color = color;501 comp.err_color = color;
439 comp.lib_dirs = flags.many("library-path");
440 comp.darwin_frameworks = flags.many("framework");
441 comp.rpath_list = flags.many("rpath");
442502
443 if (flags.single("output-h")) |output_h| {503 comp.linker_rdynamic = linker_rdynamic;
444 comp.out_h_path = output_h;
445 }
446
447 comp.windows_subsystem_windows = flags.present("mwindows");
448 comp.windows_subsystem_console = flags.present("mconsole");
449 comp.linker_rdynamic = flags.present("rdynamic");
450504
451 if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {505 if (macosx_version_min != null and ios_version_min != null) {
452 try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");506 try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
453 process.exit(1);507 process.exit(1);
454 }508 }
455509
456 if (flags.single("mmacosx-version-min")) |ver| {510 if (macosx_version_min) |ver| {
457 comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };511 comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
458 }512 }
459 if (flags.single("mios-version-min")) |ver| {513 if (ios_version_min) |ver| {
460 comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };514 comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
461 }515 }
462516
463 comp.emit_file_type = emit_type;517 comp.emit_bin = emit_bin;
464 comp.assembly_files = assembly_files;518 comp.emit_asm = emit_asm;
465 comp.link_out_file = flags.single("output");519 comp.emit_llvm_ir = emit_llvm_ir;
466 comp.link_objects = link_objects;520 comp.emit_h = emit_h;
521 comp.assembly_files = assembly_files.toSliceConst();
522 comp.link_objects = link_objects.toSliceConst();
467523
468 comp.start();524 comp.start();
469 processBuildEvents(comp, color);525 processBuildEvents(comp, color);
...@@ -522,17 +578,6 @@ pub const usage_fmt =...@@ -522,17 +578,6 @@ pub const usage_fmt =
522 \\578 \\
523;579;
524580
525pub const args_fmt_spec = [_]Flag{
526 Flag.Bool("--help"),
527 Flag.Bool("--check"),
528 Flag.Option("--color", &[_][]const u8{
529 "auto",
530 "off",
531 "on",
532 }),
533 Flag.Bool("--stdin"),
534};
535
536const Fmt = struct {581const Fmt = struct {
537 seen: event.Locked(SeenMap),582 seen: event.Locked(SeenMap),
538 any_error: bool,583 any_error: bool,
...@@ -578,30 +623,52 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {...@@ -578,30 +623,52 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
578}623}
579624
580fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {625fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
581 var flags = try Args.parse(allocator, &args_fmt_spec, args);626 var color: errmsg.Color = .Auto;
582 defer flags.deinit();627 var stdin_flag: bool = false;
583628 var check_flag: bool = false;
584 if (flags.present("help")) {629 var input_files = ArrayList([]const u8).init(allocator);
585 try stdout.write(usage_fmt);
586 process.exit(0);
587 }
588630
589 const color: errmsg.Color = blk: {631 {
590 if (flags.single("color")) |color_flag| {632 var i: usize = 0;
591 if (mem.eql(u8, color_flag, "auto")) {633 while (i < args.len) : (i += 1) {
592 break :blk .Auto;634 const arg = args[i];
593 } else if (mem.eql(u8, color_flag, "on")) {635 if (mem.startsWith(u8, arg, "-")) {
594 break :blk .On;636 if (mem.eql(u8, arg, "--help")) {
595 } else if (mem.eql(u8, color_flag, "off")) {637 try stdout.write(usage_fmt);
596 break :blk .Off;638 process.exit(0);
597 } else unreachable;639 } else if (mem.eql(u8, arg, "--color")) {
598 } else {640 if (i + 1 >= args.len) {
599 break :blk .Auto;641 try stderr.write("expected [auto|on|off] after --color\n");
642 process.exit(1);
643 }
644 i += 1;
645 const next_arg = args[i];
646 if (mem.eql(u8, next_arg, "auto")) {
647 color = .Auto;
648 } else if (mem.eql(u8, next_arg, "on")) {
649 color = .On;
650 } else if (mem.eql(u8, next_arg, "off")) {
651 color = .Off;
652 } else {
653 try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
654 process.exit(1);
655 }
656 } else if (mem.eql(u8, arg, "--stdin")) {
657 stdin_flag = true;
658 } else if (mem.eql(u8, arg, "--check")) {
659 check_flag = true;
660 } else {
661 try stderr.print("unrecognized parameter: '{}'", .{arg});
662 process.exit(1);
663 }
664 } else {
665 try input_files.append(arg);
666 }
600 }667 }
601 };668 }
602669
603 if (flags.present("stdin")) {670 if (stdin_flag) {
604 if (flags.positionals.len != 0) {671 if (input_files.len != 0) {
605 try stderr.write("cannot use --stdin with positional arguments\n");672 try stderr.write("cannot use --stdin with positional arguments\n");
606 process.exit(1);673 process.exit(1);
607 }674 }
...@@ -628,7 +695,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -628,7 +695,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
628 if (tree.errors.len != 0) {695 if (tree.errors.len != 0) {
629 process.exit(1);696 process.exit(1);
630 }697 }
631 if (flags.present("check")) {698 if (check_flag) {
632 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);699 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
633 const code: u8 = if (anything_changed) 1 else 0;700 const code: u8 = if (anything_changed) 1 else 0;
634 process.exit(code);701 process.exit(code);
...@@ -638,7 +705,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -638,7 +705,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
638 return;705 return;
639 }706 }
640707
641 if (flags.positionals.len == 0) {708 if (input_files.len == 0) {
642 try stderr.write("expected at least one source file argument\n");709 try stderr.write("expected at least one source file argument\n");
643 process.exit(1);710 process.exit(1);
644 }711 }
...@@ -650,11 +717,9 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -650,11 +717,9 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
650 .color = color,717 .color = color,
651 };718 };
652719
653 const check_mode = flags.present("check");
654
655 var group = event.Group(FmtError!void).init(allocator);720 var group = event.Group(FmtError!void).init(allocator);
656 for (flags.positionals.toSliceConst()) |file_path| {721 for (input_files.toSliceConst()) |file_path| {
657 try group.call(fmtPath, .{ &fmt, file_path, check_mode });722 try group.call(fmtPath, .{ &fmt, file_path, check_flag });
658 }723 }
659 try group.wait();724 try group.wait();
660 if (fmt.any_error) {725 if (fmt.any_error) {
...@@ -808,8 +873,6 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {...@@ -808,8 +873,6 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
808 try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});873 try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
809}874}
810875
811const args_test_spec = [_]Flag{Flag.Bool("--help")};
812
813fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {876fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
814 try stdout.write(usage);877 try stdout.write(usage);
815}878}
src-self-hosted/stage1.zig+50-32
...@@ -9,10 +9,7 @@ const process = std.process;...@@ -9,10 +9,7 @@ const process = std.process;
9const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
10const ArrayList = std.ArrayList;10const ArrayList = std.ArrayList;
11const Buffer = std.Buffer;11const Buffer = std.Buffer;
12const arg = @import("arg.zig");
13const self_hosted_main = @import("main.zig");12const self_hosted_main = @import("main.zig");
14const Args = arg.Args;
15const Flag = arg.Flag;
16const errmsg = @import("errmsg.zig");13const errmsg = @import("errmsg.zig");
17const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;14const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
1815
...@@ -169,31 +166,54 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {...@@ -169,31 +166,54 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
169 stderr_file = std.io.getStdErr();166 stderr_file = std.io.getStdErr();
170 stderr = &stderr_file.outStream().stream;167 stderr = &stderr_file.outStream().stream;
171168
172 const args = args_list.toSliceConst();169 const args = args_list.toSliceConst()[2..];
173 var flags = try Args.parse(allocator, &self_hosted_main.args_fmt_spec, args[2..]);170
174 defer flags.deinit();171 var color: errmsg.Color = .Auto;
175172 var stdin_flag: bool = false;
176 if (flags.present("help")) {173 var check_flag: bool = false;
177 try stdout.write(self_hosted_main.usage_fmt);174 var input_files = ArrayList([]const u8).init(allocator);
178 process.exit(0);175
179 }176 {
180177 var i: usize = 0;
181 const color = blk: {178 while (i < args.len) : (i += 1) {
182 if (flags.single("color")) |color_flag| {179 const arg = args[i];
183 if (mem.eql(u8, color_flag, "auto")) {180 if (mem.startsWith(u8, arg, "-")) {
184 break :blk errmsg.Color.Auto;181 if (mem.eql(u8, arg, "--help")) {
185 } else if (mem.eql(u8, color_flag, "on")) {182 try stdout.write(self_hosted_main.usage_fmt);
186 break :blk errmsg.Color.On;183 process.exit(0);
187 } else if (mem.eql(u8, color_flag, "off")) {184 } else if (mem.eql(u8, arg, "--color")) {
188 break :blk errmsg.Color.Off;185 if (i + 1 >= args.len) {
189 } else unreachable;186 try stderr.write("expected [auto|on|off] after --color\n");
190 } else {187 process.exit(1);
191 break :blk errmsg.Color.Auto;188 }
189 i += 1;
190 const next_arg = args[i];
191 if (mem.eql(u8, next_arg, "auto")) {
192 color = .Auto;
193 } else if (mem.eql(u8, next_arg, "on")) {
194 color = .On;
195 } else if (mem.eql(u8, next_arg, "off")) {
196 color = .Off;
197 } else {
198 try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
199 process.exit(1);
200 }
201 } else if (mem.eql(u8, arg, "--stdin")) {
202 stdin_flag = true;
203 } else if (mem.eql(u8, arg, "--check")) {
204 check_flag = true;
205 } else {
206 try stderr.print("unrecognized parameter: '{}'", .{arg});
207 process.exit(1);
208 }
209 } else {
210 try input_files.append(arg);
211 }
192 }212 }
193 };213 }
194214
195 if (flags.present("stdin")) {215 if (stdin_flag) {
196 if (flags.positionals.len != 0) {216 if (input_files.len != 0) {
197 try stderr.write("cannot use --stdin with positional arguments\n");217 try stderr.write("cannot use --stdin with positional arguments\n");
198 process.exit(1);218 process.exit(1);
199 }219 }
...@@ -217,7 +237,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {...@@ -217,7 +237,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
217 if (tree.errors.len != 0) {237 if (tree.errors.len != 0) {
218 process.exit(1);238 process.exit(1);
219 }239 }
220 if (flags.present("check")) {240 if (check_flag) {
221 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);241 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
222 const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);242 const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
223 process.exit(code);243 process.exit(code);
...@@ -227,7 +247,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {...@@ -227,7 +247,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
227 return;247 return;
228 }248 }
229249
230 if (flags.positionals.len == 0) {250 if (input_files.len == 0) {
231 try stderr.write("expected at least one source file argument\n");251 try stderr.write("expected at least one source file argument\n");
232 process.exit(1);252 process.exit(1);
233 }253 }
...@@ -239,10 +259,8 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {...@@ -239,10 +259,8 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
239 .allocator = allocator,259 .allocator = allocator,
240 };260 };
241261
242 const check_mode = flags.present("check");262 for (input_files.toSliceConst()) |file_path| {
243263 try fmtPath(&fmt, file_path, check_flag);
244 for (flags.positionals.toSliceConst()) |file_path| {
245 try fmtPath(&fmt, file_path, check_mode);
246 }264 }
247 if (fmt.any_error) {265 if (fmt.any_error) {
248 process.exit(1);266 process.exit(1);