@@ -56,17 +56,20 @@ type Options struct {
5656 const char* output_name;
5757 string_list.List targets;
5858 string_list.List files;
59+ string_list.List features;
5960}
6061
6162fn void Options.init(Options* opts, string_pool.Pool* pool) {
6263 memset(opts, 0, sizeof(Options));
6364 opts.targets.init(pool);
6465 opts.files.init(pool);
66+ opts.features.init(pool);
6567}
6668
6769fn void Options.free(Options *opts) {
6870 opts.targets.free();
6971 opts.files.free();
72+ opts.features.free();
7073}
7174
7275fn void write_file_or_die(const char* filename, string_buffer.Buf* buf) {
@@ -176,6 +179,7 @@ const char[] Usage_help =
176179 " -A print Library ASTs\n"
177180 " -b [file] use specified build file\n"
178181 " -d [dir] change to [dir] first\n"
182+ " -Dfeature define global feature\n"
179183 " -h print this help\n"
180184 " -i use IR backend\n"
181185 " -I use IR backend and print generated IR\n"
@@ -216,8 +220,12 @@ fn void missing_arg(const char* option) {
216220 exit(EXIT_FAILURE);
217221}
218222
219- fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
220- const char* arg = argv[i];
223+ fn void unknown_option(const char* option) {
224+ console.error("c2c: unknown option: '%s'", option);
225+ exit(EXIT_FAILURE);
226+ }
227+
228+ fn i32 parse_long_opt(const char* arg, i32 i, i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
221229 switch (arg+2) {
222230 case "I2":
223231 opts.use_ir_backend = true;
@@ -227,9 +235,8 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
227235 comp_opts.check_only = true;
228236 break;
229237 case "create":
230- if (i==argc-1) missing_arg(arg);
231- i++;
232- create_project(argv[i]);
238+ if (i >= argc) missing_arg(arg);
239+ create_project(argv[i++]);
233240 break;
234241 case "fast":
235242 comp_opts.fast_build = true;
@@ -250,9 +257,8 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
250257 opts.show_plugins = true;
251258 break;
252259 case "target":
253- if (i==argc-1) missing_arg(arg);
254- i++;
255- comp_opts.target_triple = argv[i];
260+ if (i >= argc) missing_arg(arg);
261+ comp_opts.target_triple = argv[i++];
256262 break;
257263 case "targets":
258264 opts.show_targets = true;
@@ -276,22 +282,28 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
276282 print_version();
277283 exit(EXIT_SUCCESS);
278284 default:
279- console.error("c2c: unknown option: %s", arg);
280- exit(EXIT_FAILURE) ;
285+ unknown_option( arg);
286+ break ;
281287 }
282288 return i;
283289}
284290
285291fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
286- for (i32 i= 1; i< argc; i++ ) {
287- const char* arg = argv[i];
292+ for (i32 i = 1; i < argc;) {
293+ const char* arg = argv[i++ ];
288294 if (arg[0] == '-') {
289295 if (arg[1] == '-') {
290- i = parse_long_opt(i, argc, argv, comp_opts, opts);
296+ i = parse_long_opt(arg, i, argc, argv, comp_opts, opts);
291297 } else {
292- if (strlen(arg) != 2) {
293- console.error("c2c: unknown option '%s'", arg);
294- exit(EXIT_FAILURE);
298+ const char *argarg = nil;
299+ if (memchr("Ddbo", arg[1], 4)) { // needs argument
300+ argarg = &arg[2];
301+ if (!*argarg) {
302+ if (i >= argc) missing_arg(arg);
303+ argarg = argv[i++];
304+ }
305+ } else if (strlen(arg) != 2) {
306+ unknown_option(arg);
295307 }
296308 switch (arg[1]) {
297309 case '0': // 'hidden' feature, print AST early after parsing, then quit
@@ -300,6 +312,9 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
300312 case 'A':
301313 comp_opts.print_lib_ast = true;
302314 break;
315+ case 'D':
316+ opts.features.addStr(argarg);
317+ break;
303318 case 'I':
304319 opts.use_ir_backend = true;
305320 comp_opts.print_ir = true;
@@ -314,14 +329,10 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
314329 comp_opts.print_ast = true;
315330 break;
316331 case 'b':
317- if (i==argc-1) missing_arg(arg);
318- i++;
319- opts.build_file = argv[i];
332+ opts.build_file = argarg;
320333 break;
321334 case 'd':
322- if (i==argc-1) missing_arg(arg);
323- i++;
324- opts.other_dir = argv[i];
335+ opts.other_dir = argarg;
325336 break;
326337 case '?':
327338 case 'h':
@@ -334,9 +345,7 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
334345 comp_opts.print_modules = true;
335346 break;
336347 case 'o':
337- if (i==argc-1) missing_arg(arg);
338- i++;
339- opts.output_name = argv[i];
348+ opts.output_name = argarg;
340349 break;
341350 case 'r':
342351 comp_opts.print_reports += 1;
@@ -354,8 +363,7 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
354363 opts.force_warnings = true;
355364 break;
356365 default:
357- console.error("c2c: unknown option '-%c'", arg[1]);
358- exit(EXIT_FAILURE);
366+ unknown_option(arg);
359367 break;
360368 }
361369 }
@@ -593,7 +601,7 @@ fn bool Context.build_target(Context* c,
593601 }
594602 }
595603
596- compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.pluginHandler);
604+ compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.opts.features, &c. pluginHandler);
597605
598606 // TODO unload target-specific plugins?
599607 // TODO fix build_file
0 commit comments