@@ -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