Repository: lucy-clownfish Updated Branches: refs/heads/master cbbee7aa5 -> 86113b3c9
Regen charmonizer for CLI changes. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/86113b3c Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/86113b3c Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/86113b3c Branch: refs/heads/master Commit: 86113b3c9e92cc47b2c102536fdea2f81a635541 Parents: 9119e9c Author: Marvin Humphrey <[email protected]> Authored: Fri Oct 10 19:32:12 2014 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Sun Nov 2 17:48:27 2014 -0800 ---------------------------------------------------------------------- compiler/common/charmonizer.c | 627 +++++++++++++++++++++++++++++------- runtime/common/charmonizer.c | 628 ++++++++++++++++++++++++++++++------- 2 files changed, 1037 insertions(+), 218 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/86113b3c/compiler/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/compiler/common/charmonizer.c b/compiler/common/charmonizer.c index 7b3e900..f346714 100644 --- a/compiler/common/charmonizer.c +++ b/compiler/common/charmonizer.c @@ -179,6 +179,97 @@ chaz_CFlags_enable_code_coverage(chaz_CFlags *flags); /***************************************************************************/ +#line 21 "src/Charmonizer/Core/CLI.h" +#ifndef H_CHAZ_CLI +#define H_CHAZ_CLI 1 + +#define CHAZ_CLI_NO_ARG 0 +#define CHAZ_CLI_ARG_REQUIRED (1 << 0) +#define CHAZ_CLI_ARG_OPTIONAL (1 << 1) + +/* The CLI module provides argument parsing for a command line interface. + */ + +typedef struct chaz_CLI chaz_CLI; + +/* Constructor. + * + * @param name The name of the application. + * @param description A description of the application. + */ +chaz_CLI* +chaz_CLI_new(const char *name, const char *description); + +/* Destructor. + */ +void +chaz_CLI_destroy(chaz_CLI *self); + +/* Return a string combining usage header with documentation of options. + */ +const char* +chaz_CLI_help(chaz_CLI *self); + +/* Override the generated usage header. + */ +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage); + +/* Register an option. Updates the "help" string, invalidating previous + * values. Returns true on success, or reports an error and returns false if + * the option was already registered. + */ +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags); + +/* Set an option. The specified option must have been registered previously. + * The supplied `value` is optional and will be copied. + * + * Returns true on success. Reports an error and returns false on failure. + */ +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value); + +/* Returns true if the option has been set, false otherwise. + */ +int +chaz_CLI_defined(chaz_CLI *self, const char *name); + +/* Return the value of a given option converted to a long int. Defaults to 0. + * Reports an error if the named option has not been registered. + */ +long +chaz_CLI_longval(chaz_CLI *self, const char *name); + +/* Return the value of an option as a C string. Defaults to NULL. Reports an + * error if the named option has not been registered. + */ +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name); + +/* Unset an option, making subsequent calls to `get` return false and making + * it possible to call `set` again. + * + * Returns true if the option exists and was able to be unset. + */ +int +chaz_CLI_unset(chaz_CLI *self, const char *name); + +/* Parse `argc` and `argv`, setting options as appropriate. Returns true on + * success. Reports an error and returns false if either an unexpected option + * was encountered or an option which requires an argument was supplied + * without one. + */ +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]); + +#endif /* H_CHAZ_CLI */ + + + +/***************************************************************************/ + #line 21 "src/Charmonizer/Core/Compiler.h" /* Charmonizer/Core/Compiler.h */ @@ -924,20 +1015,7 @@ chaz_Util_can_open_file(const char *file_path); #include <stddef.h> #include <stdio.h> -#define CHAZ_PROBE_MAX_CC_LEN 100 -#define CHAZ_PROBE_MAX_CFLAGS_LEN 2000 - -struct chaz_CLIArgs { - char cc[CHAZ_PROBE_MAX_CC_LEN + 1]; - char cflags[CHAZ_PROBE_MAX_CFLAGS_LEN + 1]; - int charmony_h; - int charmony_pm; - int charmony_py; - int charmony_rb; - int verbosity; - int write_makefile; - int code_coverage; -}; +struct chaz_CLI; /* Parse command line arguments, initializing and filling in the supplied * `args` struct. @@ -954,7 +1032,7 @@ struct chaz_CLIArgs { */ int chaz_Probe_parse_cli_args(int argc, const char *argv[], - struct chaz_CLIArgs *args); + struct chaz_CLI *cli); /* Exit after printing usage instructions to stderr. */ @@ -971,7 +1049,7 @@ chaz_Probe_die_usage(void); * 2 - debugging */ void -chaz_Probe_init(struct chaz_CLIArgs *args); +chaz_Probe_init(struct chaz_CLI *cli); /* Clean up the Charmonizer environment -- deleting tempfiles, etc. This * should be called only after everything else finishes. @@ -2099,6 +2177,351 @@ chaz_CFlags_enable_code_coverage(chaz_CFlags *flags) { /***************************************************************************/ +#line 17 "src/Charmonizer/Core/CLI.c" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +/* #include "Charmonizer/Core/CLI.h" */ +/* #include "Charmonizer/Core/Util.h" */ + +typedef struct chaz_CLIOption { + char *name; + char *help; + char *value; + int defined; + int flags; +} chaz_CLIOption; + +struct chaz_CLI { + char *name; + char *desc; + char *usage; + char *help; + chaz_CLIOption *opts; + int num_opts; +}; + +static void +S_chaz_CLI_error(chaz_CLI *self, const char *pattern, ...) { + va_list ap; + if (chaz_Util_verbosity > 0) { + va_start(ap, pattern); + vfprintf(stderr, pattern, ap); + va_end(ap); + fprintf(stderr, "\n"); + } +} + +static void +S_chaz_CLI_rebuild_help(chaz_CLI *self) { + int i; + size_t amount = 200; // Length of section headers. + + // Allocate space. + if (self->usage) { + amount += strlen(self->usage); + } + else { + amount += strlen(self->name); + } + if (self->desc) { + amount += strlen(self->desc); + } + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + amount += 24 + 2 * strlen(opt->name); + if (opt->flags) { + amount += strlen(opt->name); + } + if (opt->help) { + amount += strlen(opt->help); + } + } + free(self->help); + self->help = (char*)malloc(amount); + self->help[0] = '\0'; + + // Accumulate "help" string. + if (self->usage) { + strcat(self->help, self->usage); + } + else { + strcat(self->help, "Usage: "); + strcat(self->help, self->name); + if (self->num_opts) { + strcat(self->help, " [OPTIONS]"); + } + } + if (self->desc) { + strcat(self->help, "\n\n"); + strcat(self->help, self->desc); + } + strcat(self->help, "\n"); + if (self->num_opts) { + strcat(self->help, "\nOptional arguments:\n"); + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + size_t line_start = strlen(self->help); + size_t current_len; + + strcat(self->help, " --"); + strcat(self->help, opt->name); + current_len = strlen(self->help); + if (opt->flags) { + int j; + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + self->help[current_len++] = '['; + } + self->help[current_len++] = '='; + for (j = 0; opt->name[j]; j++) { + self->help[current_len++] = toupper(opt->name[j]); + } + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + strcat(self->help, "]"); + } + self->help[current_len] = '\0'; + } + if (opt->help) { + self->help[current_len++] = ' '; + while (current_len - line_start < 25) { + self->help[current_len++] = ' '; + } + self->help[current_len] = '\0'; + strcpy(self->help + current_len, opt->help); + } + strcat(self->help, "\n"); + } + } + strcat(self->help, "\n"); +} + +chaz_CLI* +chaz_CLI_new(const char *name, const char *description) { + chaz_CLI *self = calloc(1, sizeof(chaz_CLI)); + self->name = chaz_Util_strdup(name ? name : "PROGRAM"); + self->desc = description ? chaz_Util_strdup(description) : NULL; + self->help = NULL; + self->opts = NULL; + self->num_opts = 0; + S_chaz_CLI_rebuild_help(self); + return self; +} + +void +chaz_CLI_destroy(chaz_CLI *self) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + free(opt->name); + free(opt->help); + free(opt->value); + } + free(self->name); + free(self->desc); + free(self->opts); + free(self->usage); + free(self->help); +} + +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage) { + free(self->usage); + self->usage = chaz_Util_strdup(usage); +} + +const char* +chaz_CLI_help(chaz_CLI *self) { + return self->help; +} + +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags) { + int rank; + int i; + int arg_required = !!(flags & CHAZ_CLI_ARG_REQUIRED); + int arg_optional = !!(flags & CHAZ_CLI_ARG_OPTIONAL); + + // Validate flags + if (arg_required && arg_optional) { + S_chaz_CLI_error(self, "Conflicting flags: value both optional " + "and required"); + return 0; + } + + // Insert new option. Keep options sorted by name. + for (rank = self->num_opts; rank > 0; rank--) { + int comparison = strcmp(name, self->opts[rank - 1].name); + if (comparison == 0) { + S_chaz_CLI_error(self, "Option '%s' already registered", name); + return 0; + } + else if (comparison > 0) { + break; + } + } + self->num_opts += 1; + self->opts = realloc(self->opts, self->num_opts * sizeof(chaz_CLIOption)); + for (i = self->num_opts - 1; i > rank; i--) { + self->opts[i] = self->opts[i - 1]; + } + self->opts[rank].name = chaz_Util_strdup(name); + self->opts[rank].help = help ? chaz_Util_strdup(help) : NULL; + self->opts[rank].flags = flags; + self->opts[rank].defined = 0; + self->opts[rank].value = NULL; + + // Update `help` with new option. + S_chaz_CLI_rebuild_help(self); + + return 1; +} + +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (opt->defined) { + S_chaz_CLI_error(self, "'%s' specified multiple times", name); + return 0; + } + opt->defined = 1; + if (value != NULL) { + opt->value = chaz_Util_strdup(value); + } + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to set unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_unset(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + free(opt->value); + opt->value = NULL; + opt->defined = 0; + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to unset unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_defined(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->defined; + } + } + S_chaz_CLI_error(self, "Inquiry for unknown option: '%s'", name); + return 0; +} + +long +chaz_CLI_longval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (!opt->defined || !opt->value) { + return 0; + } + return strtol(opt->value, NULL, 10); + } + } + S_chaz_CLI_error(self, "Longval request for unknown option: '%s'", name); + return 0; +} + +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->value; + } + } + S_chaz_CLI_error(self, "Strval request for unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]) { + int i; + char *name = NULL; + size_t name_cap = 0; + + /* Parse most args. */ + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + size_t name_len = 0; + int has_equals = 0; + const char *value = NULL; + + /* Stop processing if we see `-` or `--`. */ + if (strcmp(arg, "--") == 0 || strcmp(arg, "-") == 0) { + break; + } + + if (strncmp(arg, "--", 2) != 0) { + S_chaz_CLI_error(self, "Unexpected argument: '%s'", arg); + free(name); + return 0; + } + + /* Extract the name of the argument, look for a potential value. */ + while (1) { + char c = arg[name_len + 2]; + if (isalnum(c) || c == '-' || c == '_') { + name_len++; + } + else if (c == '\0') { + break; + } + else if (c == '=') { + /* The rest of the arg is the value. */ + value = arg + 2 + name_len + 1; + break; + } + else { + free(name); + S_chaz_CLI_error(self, "Malformed argument: '%s'", arg); + return 0; + } + } + if (name_len + 1 > name_cap) { + name_cap = name_len + 1; + name = (char*)realloc(name, name_cap); + } + memcpy(name, arg + 2, name_len); + name[name_len] = '\0'; + + /* Attempt to set the option. */ + if (!chaz_CLI_set(self, name, value)) { + free(name); + return 0; + } + } + + return 1; +} + + +/***************************************************************************/ + #line 17 "src/Charmonizer/Core/Compiler.c" #include <string.h> #include <stdlib.h> @@ -5110,99 +5533,82 @@ chaz_Util_can_open_file(const char *file_path) { /* #include "Charmonizer/Core/ConfWriterPython.h" */ /* #include "Charmonizer/Core/ConfWriterRuby.h" */ /* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/CLI.h" */ /* #include "Charmonizer/Core/Compiler.h" */ /* #include "Charmonizer/Core/Make.h" */ /* #include "Charmonizer/Core/OperatingSystem.h" */ int -chaz_Probe_parse_cli_args(int argc, const char *argv[], - struct chaz_CLIArgs *args) { +chaz_Probe_parse_cli_args(int argc, const char *argv[], chaz_CLI *cli) { int i; int output_enabled = 0; - /* Zero out args struct. */ - memset(args, 0, sizeof(struct chaz_CLIArgs)); + /* Register Charmonizer-specific options. */ + chaz_CLI_register(cli, "enable-c", "generate charmony.h", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-perl", "generate Charmony.pm", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-python", "generate charmony.py", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-ruby", "generate charmony.rb", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-makefile", NULL, CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-coverage", NULL, CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "cc", "compiler command", CHAZ_CLI_ARG_REQUIRED); + chaz_CLI_register(cli, "cflags", NULL, CHAZ_CLI_ARG_REQUIRED); + + /* Parse options, exiting on failure. */ + if (!chaz_CLI_parse(cli, argc, argv)) { + fprintf(stderr, "%s", chaz_CLI_help(cli)); + exit(1); + } - /* Parse most args. */ - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (strcmp(arg, "--") == 0) { - /* From here on out, everything will be a compiler flag. */ - i++; - break; - } - if (strcmp(arg, "--enable-c") == 0) { - args->charmony_h = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-perl") == 0) { - args->charmony_pm = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-python") == 0) { - args->charmony_py = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-ruby") == 0) { - args->charmony_rb = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-makefile") == 0) { - args->write_makefile = 1; + /* Accumulate compiler flags. */ + { + char *cflags = chaz_Util_strdup(""); + size_t cflags_len = 0; + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "--") == 0) { + i++; + break; + } } - else if (strcmp(arg, "--enable-coverage") == 0) { - args->code_coverage = 1; + for (; i < argc; i++) { + const char *arg = argv[i]; + cflags_len += strlen(arg) + 2; + cflags = (char*)realloc(cflags, cflags_len); + strcat(cflags, " "); + strcat(cflags, arg); } - else if (memcmp(arg, "--cc=", 5) == 0) { - size_t len = strlen(arg); - size_t l = 5; - size_t r = len; - size_t trimmed_len; - - if (len > CHAZ_PROBE_MAX_CC_LEN - 5) { - fprintf(stderr, "Exceeded max length for compiler command"); - exit(1); - } + chaz_CLI_set(cli, "cflags", cflags); + free(cflags); + } - /* - * Some Perl setups have a 'cc' config value with leading - * whitespace. - */ - while (isspace(arg[l])) { - ++l; - } - while (r > l && isspace(arg[r-1])) { - --r; - } + /* Some Perl setups have a 'cc' config value with leading whitespace. */ + if (chaz_CLI_defined(cli, "cc")) { + const char *arg = chaz_CLI_strval(cli, "cc"); + char *cc; + size_t len = strlen(arg); + size_t l = 0; + size_t r = len; + size_t trimmed_len; - trimmed_len = r - l; - memcpy(args->cc, arg + l, trimmed_len); - args->cc[trimmed_len] = '\0'; + while (isspace(arg[l])) { + ++l; } - } /* preserve value of i */ - - /* Accumulate compiler flags. */ - for (; i < argc; i++) { - const char *arg = argv[i]; - size_t new_len = strlen(arg) + strlen(args->cflags) + 2; - if (new_len >= CHAZ_PROBE_MAX_CFLAGS_LEN) { - fprintf(stderr, "Exceeded max length for compiler flags"); - exit(1); + while (r > l && isspace(arg[r-1])) { + --r; } - strcat(args->cflags, " "); - strcat(args->cflags, arg); - } - /* Process CHARM_VERBOSITY environment variable. */ - { - const char *verbosity_env = getenv("CHARM_VERBOSITY"); - if (verbosity_env && strlen(verbosity_env)) { - args->verbosity = strtol(verbosity_env, NULL, 10); - } + trimmed_len = r - l; + cc = (char*)malloc(trimmed_len + 1); + memcpy(cc, arg + l, trimmed_len); + cc[trimmed_len] = '\0'; + chaz_CLI_unset(cli, "cc"); + chaz_CLI_set(cli, "cc", cc); + free(cc); } /* Validate. */ - if (!strlen(args->cc) || !output_enabled) { + if (!chaz_CLI_defined(cli, "cc") + || !strlen(chaz_CLI_strval(cli, "cc")) + ) { return false; } @@ -5218,7 +5624,7 @@ chaz_Probe_die_usage(void) { } void -chaz_Probe_init(struct chaz_CLIArgs *args) { +chaz_Probe_init(struct chaz_CLI *cli) { int output_enabled = 0; { @@ -5231,25 +5637,25 @@ chaz_Probe_init(struct chaz_CLIArgs *args) { /* Dispatch other initializers. */ chaz_OS_init(); - chaz_CC_init(args->cc, args->cflags); + chaz_CC_init(chaz_CLI_strval(cli, "cc"), chaz_CLI_strval(cli, "cflags")); chaz_ConfWriter_init(); chaz_HeadCheck_init(); chaz_Make_init(); /* Enable output. */ - if (args->charmony_h) { + if (chaz_CLI_defined(cli, "enable-c")) { chaz_ConfWriterC_enable(); output_enabled = true; } - if (args->charmony_pm) { + if (chaz_CLI_defined(cli, "enable-perl")) { chaz_ConfWriterPerl_enable(); output_enabled = true; } - if (args->charmony_py) { + if (chaz_CLI_defined(cli, "enable-python")) { chaz_ConfWriterPython_enable(); output_enabled = true; } - if (args->charmony_rb) { + if (chaz_CLI_defined(cli, "enable-ruby")) { chaz_ConfWriterRuby_enable(); output_enabled = true; } @@ -7296,7 +7702,7 @@ typedef struct SourceFileContext { } SourceFileContext; static void -S_add_compiler_flags(struct chaz_CLIArgs *args) { +S_add_compiler_flags(struct chaz_CLI *cli) { chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags(); if (chaz_Probe_gcc_version_num()) { @@ -7308,7 +7714,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { "-DLUCY_DEBUG -pedantic -Wall -Wextra -Wno-variadic-macros" ); } - if (args->charmony_pm) { + if (chaz_CLI_defined(cli, "enable-perl")) { chaz_CFlags_append(extra_cflags, "-DPERL_GCC_PEDANTIC"); } @@ -7359,7 +7765,7 @@ S_source_file_callback(const char *dir, char *file, void *context) { } static void -S_write_makefile(struct chaz_CLIArgs *args) { +S_write_makefile(struct chaz_CLI *cli) { SourceFileContext sfc; const char *base_dir = ".."; @@ -7407,7 +7813,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { chaz_CFlags_add_include_dir(makefile_cflags, "."); chaz_CFlags_add_include_dir(makefile_cflags, include_dir); chaz_CFlags_add_include_dir(makefile_cflags, src_dir); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_CFlags_enable_code_coverage(makefile_cflags); } @@ -7456,7 +7862,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { if (chaz_CC_msvc_version_num()) { chaz_CFlags_append(link_flags, "/nologo"); } - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_CFlags_enable_code_coverage(link_flags); } chaz_MakeFile_add_exe(makefile, cfc_exe, "$(COMMON_OBJS) $(CFC_OBJS)", @@ -7468,7 +7874,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { rule = chaz_MakeFile_add_rule(makefile, "test", test_cfc_exe); chaz_MakeRule_add_command(rule, test_cfc_exe); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { rule = chaz_MakeFile_add_rule(makefile, "coverage", test_cfc_exe); chaz_MakeRule_add_command(rule, "lcov" @@ -7495,7 +7901,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { chaz_MakeRule_add_rm_command(clean_rule, "$(CFC_OBJS)"); chaz_MakeRule_add_rm_command(clean_rule, "$(TEST_CFC_OBJS)"); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_MakeRule_add_rm_command(clean_rule, "cfc.info"); chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage"); } @@ -7517,14 +7923,16 @@ S_write_makefile(struct chaz_CLIArgs *args) { int main(int argc, const char **argv) { /* Initialize. */ - struct chaz_CLIArgs args; + chaz_CLI *cli + = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment"); + chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]"); { - int result = chaz_Probe_parse_cli_args(argc, argv, &args); + int result = chaz_Probe_parse_cli_args(argc, argv, cli); if (!result) { chaz_Probe_die_usage(); } - chaz_Probe_init(&args); - S_add_compiler_flags(&args); + chaz_Probe_init(cli); + S_add_compiler_flags(cli); } /* Define stdint types in charmony.h. */ @@ -7545,11 +7953,12 @@ int main(int argc, const char **argv) { chaz_UnusedVars_run(); chaz_VariadicMacros_run(); - if (args.write_makefile) { - S_write_makefile(&args); + if (chaz_CLI_defined(cli, "enable-makefile")) { + S_write_makefile(cli); } /* Clean up. */ + chaz_CLI_destroy(cli); chaz_Probe_clean_up(); return 0; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/86113b3c/runtime/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c index 0b1444a..e6a39bd 100644 --- a/runtime/common/charmonizer.c +++ b/runtime/common/charmonizer.c @@ -179,6 +179,97 @@ chaz_CFlags_enable_code_coverage(chaz_CFlags *flags); /***************************************************************************/ +#line 21 "src/Charmonizer/Core/CLI.h" +#ifndef H_CHAZ_CLI +#define H_CHAZ_CLI 1 + +#define CHAZ_CLI_NO_ARG 0 +#define CHAZ_CLI_ARG_REQUIRED (1 << 0) +#define CHAZ_CLI_ARG_OPTIONAL (1 << 1) + +/* The CLI module provides argument parsing for a command line interface. + */ + +typedef struct chaz_CLI chaz_CLI; + +/* Constructor. + * + * @param name The name of the application. + * @param description A description of the application. + */ +chaz_CLI* +chaz_CLI_new(const char *name, const char *description); + +/* Destructor. + */ +void +chaz_CLI_destroy(chaz_CLI *self); + +/* Return a string combining usage header with documentation of options. + */ +const char* +chaz_CLI_help(chaz_CLI *self); + +/* Override the generated usage header. + */ +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage); + +/* Register an option. Updates the "help" string, invalidating previous + * values. Returns true on success, or reports an error and returns false if + * the option was already registered. + */ +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags); + +/* Set an option. The specified option must have been registered previously. + * The supplied `value` is optional and will be copied. + * + * Returns true on success. Reports an error and returns false on failure. + */ +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value); + +/* Returns true if the option has been set, false otherwise. + */ +int +chaz_CLI_defined(chaz_CLI *self, const char *name); + +/* Return the value of a given option converted to a long int. Defaults to 0. + * Reports an error if the named option has not been registered. + */ +long +chaz_CLI_longval(chaz_CLI *self, const char *name); + +/* Return the value of an option as a C string. Defaults to NULL. Reports an + * error if the named option has not been registered. + */ +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name); + +/* Unset an option, making subsequent calls to `get` return false and making + * it possible to call `set` again. + * + * Returns true if the option exists and was able to be unset. + */ +int +chaz_CLI_unset(chaz_CLI *self, const char *name); + +/* Parse `argc` and `argv`, setting options as appropriate. Returns true on + * success. Reports an error and returns false if either an unexpected option + * was encountered or an option which requires an argument was supplied + * without one. + */ +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]); + +#endif /* H_CHAZ_CLI */ + + + +/***************************************************************************/ + #line 21 "src/Charmonizer/Core/Compiler.h" /* Charmonizer/Core/Compiler.h */ @@ -924,20 +1015,7 @@ chaz_Util_can_open_file(const char *file_path); #include <stddef.h> #include <stdio.h> -#define CHAZ_PROBE_MAX_CC_LEN 100 -#define CHAZ_PROBE_MAX_CFLAGS_LEN 2000 - -struct chaz_CLIArgs { - char cc[CHAZ_PROBE_MAX_CC_LEN + 1]; - char cflags[CHAZ_PROBE_MAX_CFLAGS_LEN + 1]; - int charmony_h; - int charmony_pm; - int charmony_py; - int charmony_rb; - int verbosity; - int write_makefile; - int code_coverage; -}; +struct chaz_CLI; /* Parse command line arguments, initializing and filling in the supplied * `args` struct. @@ -954,7 +1032,7 @@ struct chaz_CLIArgs { */ int chaz_Probe_parse_cli_args(int argc, const char *argv[], - struct chaz_CLIArgs *args); + struct chaz_CLI *cli); /* Exit after printing usage instructions to stderr. */ @@ -971,7 +1049,7 @@ chaz_Probe_die_usage(void); * 2 - debugging */ void -chaz_Probe_init(struct chaz_CLIArgs *args); +chaz_Probe_init(struct chaz_CLI *cli); /* Clean up the Charmonizer environment -- deleting tempfiles, etc. This * should be called only after everything else finishes. @@ -2099,6 +2177,351 @@ chaz_CFlags_enable_code_coverage(chaz_CFlags *flags) { /***************************************************************************/ +#line 17 "src/Charmonizer/Core/CLI.c" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +/* #include "Charmonizer/Core/CLI.h" */ +/* #include "Charmonizer/Core/Util.h" */ + +typedef struct chaz_CLIOption { + char *name; + char *help; + char *value; + int defined; + int flags; +} chaz_CLIOption; + +struct chaz_CLI { + char *name; + char *desc; + char *usage; + char *help; + chaz_CLIOption *opts; + int num_opts; +}; + +static void +S_chaz_CLI_error(chaz_CLI *self, const char *pattern, ...) { + va_list ap; + if (chaz_Util_verbosity > 0) { + va_start(ap, pattern); + vfprintf(stderr, pattern, ap); + va_end(ap); + fprintf(stderr, "\n"); + } +} + +static void +S_chaz_CLI_rebuild_help(chaz_CLI *self) { + int i; + size_t amount = 200; // Length of section headers. + + // Allocate space. + if (self->usage) { + amount += strlen(self->usage); + } + else { + amount += strlen(self->name); + } + if (self->desc) { + amount += strlen(self->desc); + } + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + amount += 24 + 2 * strlen(opt->name); + if (opt->flags) { + amount += strlen(opt->name); + } + if (opt->help) { + amount += strlen(opt->help); + } + } + free(self->help); + self->help = (char*)malloc(amount); + self->help[0] = '\0'; + + // Accumulate "help" string. + if (self->usage) { + strcat(self->help, self->usage); + } + else { + strcat(self->help, "Usage: "); + strcat(self->help, self->name); + if (self->num_opts) { + strcat(self->help, " [OPTIONS]"); + } + } + if (self->desc) { + strcat(self->help, "\n\n"); + strcat(self->help, self->desc); + } + strcat(self->help, "\n"); + if (self->num_opts) { + strcat(self->help, "\nOptional arguments:\n"); + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + size_t line_start = strlen(self->help); + size_t current_len; + + strcat(self->help, " --"); + strcat(self->help, opt->name); + current_len = strlen(self->help); + if (opt->flags) { + int j; + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + self->help[current_len++] = '['; + } + self->help[current_len++] = '='; + for (j = 0; opt->name[j]; j++) { + self->help[current_len++] = toupper(opt->name[j]); + } + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + strcat(self->help, "]"); + } + self->help[current_len] = '\0'; + } + if (opt->help) { + self->help[current_len++] = ' '; + while (current_len - line_start < 25) { + self->help[current_len++] = ' '; + } + self->help[current_len] = '\0'; + strcpy(self->help + current_len, opt->help); + } + strcat(self->help, "\n"); + } + } + strcat(self->help, "\n"); +} + +chaz_CLI* +chaz_CLI_new(const char *name, const char *description) { + chaz_CLI *self = calloc(1, sizeof(chaz_CLI)); + self->name = chaz_Util_strdup(name ? name : "PROGRAM"); + self->desc = description ? chaz_Util_strdup(description) : NULL; + self->help = NULL; + self->opts = NULL; + self->num_opts = 0; + S_chaz_CLI_rebuild_help(self); + return self; +} + +void +chaz_CLI_destroy(chaz_CLI *self) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + free(opt->name); + free(opt->help); + free(opt->value); + } + free(self->name); + free(self->desc); + free(self->opts); + free(self->usage); + free(self->help); +} + +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage) { + free(self->usage); + self->usage = chaz_Util_strdup(usage); +} + +const char* +chaz_CLI_help(chaz_CLI *self) { + return self->help; +} + +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags) { + int rank; + int i; + int arg_required = !!(flags & CHAZ_CLI_ARG_REQUIRED); + int arg_optional = !!(flags & CHAZ_CLI_ARG_OPTIONAL); + + // Validate flags + if (arg_required && arg_optional) { + S_chaz_CLI_error(self, "Conflicting flags: value both optional " + "and required"); + return 0; + } + + // Insert new option. Keep options sorted by name. + for (rank = self->num_opts; rank > 0; rank--) { + int comparison = strcmp(name, self->opts[rank - 1].name); + if (comparison == 0) { + S_chaz_CLI_error(self, "Option '%s' already registered", name); + return 0; + } + else if (comparison > 0) { + break; + } + } + self->num_opts += 1; + self->opts = realloc(self->opts, self->num_opts * sizeof(chaz_CLIOption)); + for (i = self->num_opts - 1; i > rank; i--) { + self->opts[i] = self->opts[i - 1]; + } + self->opts[rank].name = chaz_Util_strdup(name); + self->opts[rank].help = help ? chaz_Util_strdup(help) : NULL; + self->opts[rank].flags = flags; + self->opts[rank].defined = 0; + self->opts[rank].value = NULL; + + // Update `help` with new option. + S_chaz_CLI_rebuild_help(self); + + return 1; +} + +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (opt->defined) { + S_chaz_CLI_error(self, "'%s' specified multiple times", name); + return 0; + } + opt->defined = 1; + if (value != NULL) { + opt->value = chaz_Util_strdup(value); + } + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to set unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_unset(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + free(opt->value); + opt->value = NULL; + opt->defined = 0; + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to unset unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_defined(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->defined; + } + } + S_chaz_CLI_error(self, "Inquiry for unknown option: '%s'", name); + return 0; +} + +long +chaz_CLI_longval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (!opt->defined || !opt->value) { + return 0; + } + return strtol(opt->value, NULL, 10); + } + } + S_chaz_CLI_error(self, "Longval request for unknown option: '%s'", name); + return 0; +} + +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->value; + } + } + S_chaz_CLI_error(self, "Strval request for unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]) { + int i; + char *name = NULL; + size_t name_cap = 0; + + /* Parse most args. */ + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + size_t name_len = 0; + int has_equals = 0; + const char *value = NULL; + + /* Stop processing if we see `-` or `--`. */ + if (strcmp(arg, "--") == 0 || strcmp(arg, "-") == 0) { + break; + } + + if (strncmp(arg, "--", 2) != 0) { + S_chaz_CLI_error(self, "Unexpected argument: '%s'", arg); + free(name); + return 0; + } + + /* Extract the name of the argument, look for a potential value. */ + while (1) { + char c = arg[name_len + 2]; + if (isalnum(c) || c == '-' || c == '_') { + name_len++; + } + else if (c == '\0') { + break; + } + else if (c == '=') { + /* The rest of the arg is the value. */ + value = arg + 2 + name_len + 1; + break; + } + else { + free(name); + S_chaz_CLI_error(self, "Malformed argument: '%s'", arg); + return 0; + } + } + if (name_len + 1 > name_cap) { + name_cap = name_len + 1; + name = (char*)realloc(name, name_cap); + } + memcpy(name, arg + 2, name_len); + name[name_len] = '\0'; + + /* Attempt to set the option. */ + if (!chaz_CLI_set(self, name, value)) { + free(name); + return 0; + } + } + + return 1; +} + + +/***************************************************************************/ + #line 17 "src/Charmonizer/Core/Compiler.c" #include <string.h> #include <stdlib.h> @@ -5110,99 +5533,82 @@ chaz_Util_can_open_file(const char *file_path) { /* #include "Charmonizer/Core/ConfWriterPython.h" */ /* #include "Charmonizer/Core/ConfWriterRuby.h" */ /* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/CLI.h" */ /* #include "Charmonizer/Core/Compiler.h" */ /* #include "Charmonizer/Core/Make.h" */ /* #include "Charmonizer/Core/OperatingSystem.h" */ int -chaz_Probe_parse_cli_args(int argc, const char *argv[], - struct chaz_CLIArgs *args) { +chaz_Probe_parse_cli_args(int argc, const char *argv[], chaz_CLI *cli) { int i; int output_enabled = 0; - /* Zero out args struct. */ - memset(args, 0, sizeof(struct chaz_CLIArgs)); + /* Register Charmonizer-specific options. */ + chaz_CLI_register(cli, "enable-c", "generate charmony.h", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-perl", "generate Charmony.pm", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-python", "generate charmony.py", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-ruby", "generate charmony.rb", CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-makefile", NULL, CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "enable-coverage", NULL, CHAZ_CLI_NO_ARG); + chaz_CLI_register(cli, "cc", "compiler command", CHAZ_CLI_ARG_REQUIRED); + chaz_CLI_register(cli, "cflags", NULL, CHAZ_CLI_ARG_REQUIRED); + + /* Parse options, exiting on failure. */ + if (!chaz_CLI_parse(cli, argc, argv)) { + fprintf(stderr, "%s", chaz_CLI_help(cli)); + exit(1); + } - /* Parse most args. */ - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (strcmp(arg, "--") == 0) { - /* From here on out, everything will be a compiler flag. */ - i++; - break; - } - if (strcmp(arg, "--enable-c") == 0) { - args->charmony_h = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-perl") == 0) { - args->charmony_pm = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-python") == 0) { - args->charmony_py = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-ruby") == 0) { - args->charmony_rb = 1; - output_enabled = 1; - } - else if (strcmp(arg, "--enable-makefile") == 0) { - args->write_makefile = 1; + /* Accumulate compiler flags. */ + { + char *cflags = chaz_Util_strdup(""); + size_t cflags_len = 0; + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "--") == 0) { + i++; + break; + } } - else if (strcmp(arg, "--enable-coverage") == 0) { - args->code_coverage = 1; + for (; i < argc; i++) { + const char *arg = argv[i]; + cflags_len += strlen(arg) + 2; + cflags = (char*)realloc(cflags, cflags_len); + strcat(cflags, " "); + strcat(cflags, arg); } - else if (memcmp(arg, "--cc=", 5) == 0) { - size_t len = strlen(arg); - size_t l = 5; - size_t r = len; - size_t trimmed_len; - - if (len > CHAZ_PROBE_MAX_CC_LEN - 5) { - fprintf(stderr, "Exceeded max length for compiler command"); - exit(1); - } + chaz_CLI_set(cli, "cflags", cflags); + free(cflags); + } - /* - * Some Perl setups have a 'cc' config value with leading - * whitespace. - */ - while (isspace(arg[l])) { - ++l; - } - while (r > l && isspace(arg[r-1])) { - --r; - } + /* Some Perl setups have a 'cc' config value with leading whitespace. */ + if (chaz_CLI_defined(cli, "cc")) { + const char *arg = chaz_CLI_strval(cli, "cc"); + char *cc; + size_t len = strlen(arg); + size_t l = 0; + size_t r = len; + size_t trimmed_len; - trimmed_len = r - l; - memcpy(args->cc, arg + l, trimmed_len); - args->cc[trimmed_len] = '\0'; + while (isspace(arg[l])) { + ++l; } - } /* preserve value of i */ - - /* Accumulate compiler flags. */ - for (; i < argc; i++) { - const char *arg = argv[i]; - size_t new_len = strlen(arg) + strlen(args->cflags) + 2; - if (new_len >= CHAZ_PROBE_MAX_CFLAGS_LEN) { - fprintf(stderr, "Exceeded max length for compiler flags"); - exit(1); + while (r > l && isspace(arg[r-1])) { + --r; } - strcat(args->cflags, " "); - strcat(args->cflags, arg); - } - /* Process CHARM_VERBOSITY environment variable. */ - { - const char *verbosity_env = getenv("CHARM_VERBOSITY"); - if (verbosity_env && strlen(verbosity_env)) { - args->verbosity = strtol(verbosity_env, NULL, 10); - } + trimmed_len = r - l; + cc = (char*)malloc(trimmed_len + 1); + memcpy(cc, arg + l, trimmed_len); + cc[trimmed_len] = '\0'; + chaz_CLI_unset(cli, "cc"); + chaz_CLI_set(cli, "cc", cc); + free(cc); } /* Validate. */ - if (!strlen(args->cc) || !output_enabled) { + if (!chaz_CLI_defined(cli, "cc") + || !strlen(chaz_CLI_strval(cli, "cc")) + ) { return false; } @@ -5218,7 +5624,7 @@ chaz_Probe_die_usage(void) { } void -chaz_Probe_init(struct chaz_CLIArgs *args) { +chaz_Probe_init(struct chaz_CLI *cli) { int output_enabled = 0; { @@ -5231,25 +5637,25 @@ chaz_Probe_init(struct chaz_CLIArgs *args) { /* Dispatch other initializers. */ chaz_OS_init(); - chaz_CC_init(args->cc, args->cflags); + chaz_CC_init(chaz_CLI_strval(cli, "cc"), chaz_CLI_strval(cli, "cflags")); chaz_ConfWriter_init(); chaz_HeadCheck_init(); chaz_Make_init(); /* Enable output. */ - if (args->charmony_h) { + if (chaz_CLI_defined(cli, "enable-c")) { chaz_ConfWriterC_enable(); output_enabled = true; } - if (args->charmony_pm) { + if (chaz_CLI_defined(cli, "enable-perl")) { chaz_ConfWriterPerl_enable(); output_enabled = true; } - if (args->charmony_py) { + if (chaz_CLI_defined(cli, "enable-python")) { chaz_ConfWriterPython_enable(); output_enabled = true; } - if (args->charmony_rb) { + if (chaz_CLI_defined(cli, "enable-ruby")) { chaz_ConfWriterRuby_enable(); output_enabled = true; } @@ -7300,6 +7706,7 @@ chaz_VariadicMacros_run(void) { /* #include "Charmonizer/Probe/SymbolVisibility.h" */ /* #include "Charmonizer/Probe/VariadicMacros.h" */ /* #include "Charmonizer/Core/HeaderChecker.h" */ +/* #include "Charmonizer/Core/CLI.h" */ /* #include "Charmonizer/Core/ConfWriter.h" */ /* #include "Charmonizer/Core/ConfWriterC.h" */ /* #include "Charmonizer/Core/ConfWriterPerl.h" */ @@ -7313,7 +7720,7 @@ static const char cfish_version[] = "0.4.0"; static const char cfish_major_version[] = "0.4"; static void -S_add_compiler_flags(struct chaz_CLIArgs *args) { +S_add_compiler_flags(struct chaz_CLI *cli) { chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags(); if (chaz_Probe_gcc_version_num()) { @@ -7324,7 +7731,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { else if (getenv("LUCY_DEBUG")) { chaz_CFlags_append(extra_cflags, "-DLUCY_DEBUG -pedantic -Wall -Wextra -Wno-variadic-macros"); - if (args->charmony_pm) { + if (chaz_CLI_defined(cli, "enable-perl")) { chaz_CFlags_append(extra_cflags, "-DPERL_GCC_PEDANTIC"); } } @@ -7398,7 +7805,7 @@ S_cfh_file_callback(const char *dir, char *file, void *context) { } static void -S_write_makefile(struct chaz_CLIArgs *args) { +S_write_makefile(struct chaz_CLI *cli) { SourceFileContext sfc; const char *base_dir = ".."; @@ -7455,7 +7862,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { chaz_CFlags_enable_debugging(makefile_cflags); chaz_CFlags_disable_strict_aliasing(makefile_cflags); chaz_CFlags_compile_shared_library(makefile_cflags); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_CFlags_enable_code_coverage(makefile_cflags); } @@ -7532,7 +7939,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { if (math_library) { chaz_CFlags_add_external_library(link_flags, math_library); } - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_CFlags_enable_code_coverage(link_flags); } chaz_MakeFile_add_shared_lib(makefile, shared_lib, "$(CLOWNFISH_OBJS)", @@ -7561,7 +7968,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { } chaz_MakeRule_add_command(rule, test_command); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { rule = chaz_MakeFile_add_rule(makefile, "coverage", test_cfish_exe); chaz_MakeRule_add_command(rule, "lcov" @@ -7586,7 +7993,7 @@ S_write_makefile(struct chaz_CLIArgs *args) { chaz_MakeRule_add_rm_command(clean_rule, "$(CLOWNFISH_OBJS)"); chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen"); - if (args->code_coverage) { + if (chaz_CLI_defined(cli, "enable-coverage")) { chaz_MakeRule_add_rm_command(clean_rule, "clownfish.info"); chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage"); } @@ -7618,14 +8025,16 @@ S_write_makefile(struct chaz_CLIArgs *args) { int main(int argc, const char **argv) { /* Initialize. */ - struct chaz_CLIArgs args; + chaz_CLI *cli + = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment"); + chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]"); { - int result = chaz_Probe_parse_cli_args(argc, argv, &args); + int result = chaz_Probe_parse_cli_args(argc, argv, cli); if (!result) { chaz_Probe_die_usage(); } - chaz_Probe_init(&args); - S_add_compiler_flags(&args); + chaz_Probe_init(cli); + S_add_compiler_flags(cli); } { int i; @@ -7687,11 +8096,12 @@ int main(int argc, const char **argv) { "#endif\n\n" ); - if (args.write_makefile) { - S_write_makefile(&args); + if (chaz_CLI_defined(cli, "enable-makefile")) { + S_write_makefile(cli); } /* Clean up. */ + chaz_CLI_destroy(cli); chaz_Probe_clean_up(); return 0;
