@@ -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) {
@@ -175,6 +178,7 @@ const char[] Usage_help =
175178 " -A print Library ASTs\n"
176179 " -b [file] use specified build file\n"
177180 " -d [dir] change to [dir] first\n"
181+ " -Dfeature define global feature\n"
178182 " -h print this help\n"
179183 " -i use IR backend\n"
180184 " -I use IR backend and print generated IR\n"
@@ -215,8 +219,12 @@ fn void missing_arg(const char* option) {
215219 exit(EXIT_FAILURE);
216220}
217221
218- fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
219- const char* arg = argv[i];
222+ fn void unknown_option(const char* option) {
223+ console.error("c2c: unknown option: '%s'", option);
224+ exit(EXIT_FAILURE);
225+ }
226+
227+ fn i32 parse_long_opt(const char* arg, i32 i, i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
220228 switch (arg+2) {
221229 case "I2":
222230 opts.use_ir_backend = true;
@@ -226,9 +234,8 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
226234 comp_opts.check_only = true;
227235 break;
228236 case "create":
229- if (i==argc-1) missing_arg(arg);
230- i++;
231- create_project(argv[i]);
237+ if (i >= argc) missing_arg(arg);
238+ create_project(argv[i++]);
232239 break;
233240 case "fast":
234241 comp_opts.fast_build = true;
@@ -249,9 +256,8 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
249256 opts.show_plugins = true;
250257 break;
251258 case "target":
252- if (i==argc-1) missing_arg(arg);
253- i++;
254- comp_opts.target_triple = argv[i];
259+ if (i >= argc) missing_arg(arg);
260+ comp_opts.target_triple = argv[i++];
255261 break;
256262 case "targets":
257263 opts.show_targets = true;
@@ -275,22 +281,28 @@ fn i32 parse_long_opt(i32 i, i32 argc, char** argv, compiler.Options* comp_opts,
275281 print_version();
276282 exit(EXIT_SUCCESS);
277283 default:
278- console.error("c2c: unknown option: %s", arg);
279- exit(EXIT_FAILURE) ;
284+ unknown_option( arg);
285+ break ;
280286 }
281287 return i;
282288}
283289
284290fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options* opts) {
285- for (i32 i= 1; i< argc; i++ ) {
286- const char* arg = argv[i];
291+ for (i32 i = 1; i < argc;) {
292+ const char* arg = argv[i++ ];
287293 if (arg[0] == '-') {
288294 if (arg[1] == '-') {
289- i = parse_long_opt(i, argc, argv, comp_opts, opts);
295+ i = parse_long_opt(arg, i, argc, argv, comp_opts, opts);
290296 } else {
291- if (strlen(arg) != 2) {
292- console.error("c2c: unknown option '%s'", arg);
293- exit(EXIT_FAILURE);
297+ const char *argarg = nil;
298+ if (memchr("Ddbo", arg[1], 4)) { // needs argument
299+ argarg = &arg[2];
300+ if (!*argarg) {
301+ if (i >= argc) missing_arg(arg);
302+ argarg = argv[i++];
303+ }
304+ } else if (strlen(arg) != 2) {
305+ unknown_option(arg);
294306 }
295307 switch (arg[1]) {
296308 case '0': // 'hidden' feature, print AST early after parsing, then quit
@@ -299,6 +311,9 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
299311 case 'A':
300312 comp_opts.print_lib_ast = true;
301313 break;
314+ case 'D':
315+ opts.features.addStr(argarg);
316+ break;
302317 case 'I':
303318 opts.use_ir_backend = true;
304319 comp_opts.print_ir = true;
@@ -313,14 +328,10 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
313328 comp_opts.print_ast = true;
314329 break;
315330 case 'b':
316- if (i==argc-1) missing_arg(arg);
317- i++;
318- opts.build_file = argv[i];
331+ opts.build_file = argarg;
319332 break;
320333 case 'd':
321- if (i==argc-1) missing_arg(arg);
322- i++;
323- opts.other_dir = argv[i];
334+ opts.other_dir = argarg;
324335 break;
325336 case '?':
326337 case 'h':
@@ -333,9 +344,7 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
333344 comp_opts.print_modules = true;
334345 break;
335346 case 'o':
336- if (i==argc-1) missing_arg(arg);
337- i++;
338- opts.output_name = argv[i];
347+ opts.output_name = argarg;
339348 break;
340349 case 'r':
341350 comp_opts.print_reports += 1;
@@ -353,8 +362,7 @@ fn void parse_opts(i32 argc, char** argv, compiler.Options* comp_opts, Options*
353362 opts.force_warnings = true;
354363 break;
355364 default:
356- console.error("c2c: unknown option '-%c'", arg[1]);
357- exit(EXIT_FAILURE);
365+ unknown_option(arg);
358366 break;
359367 }
360368 }
@@ -592,7 +600,7 @@ fn bool Context.build_target(Context* c,
592600 }
593601 }
594602
595- compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.pluginHandler);
603+ compiler.build(c.auxPool, c.sm, c.diags, c.build_info, target, &c.comp_opts, &c.opts.features, &c. pluginHandler);
596604
597605 // TODO unload target-specific plugins?
598606 // TODO fix build_file
0 commit comments