Skip to content

ArgParseInit

Description

Create a parser. The name and about pointers are borrowed – they must outlive the parser (string literals are the typical case). The -h / --help flag is registered lazily on the first ArgParseRun / ArgParseHelp call.

Two call shapes, like StrInit / VecInitT: ArgParseInit(name, about) – uses the surrounding Scope’s allocator. ArgParseInit(name, about, alloc) – explicit allocator.

Success

Yields an initialized parser. The specs Vec is empty; add specs with ArgParseAddPositional / etc.

Failure

Cannot fail at construction; first allocator OOM surfaces from later spec-Vec growth.

Usage example (Cross-references)

Usage examples (Cross-references)
            Zstr hostname = NULL;
    
            ArgParse ap = ArgParseInit("resolve", "look up a hostname via /etc/hosts and DNS");
            ArgPositional(&ap, "hostname", &hostname, "name to resolve");
            Zstr upstream_spec = NULL;
    
            ArgParse ap = ArgParseInit("beam", "small reverse-proxy");
            ArgRequired(&ap, "-l", "--listen", &listen_spec, "host:port to listen on");
            ArgRequired(&ap, "-u", "--upstream", &upstream_spec, "upstream host:port");
    static bool test_required_long_space(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_required_long_equals(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_required_short(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_optional_default_preserved(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 timeout = 30;
    static bool test_optional_overrides_default(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 timeout = 30;
    static bool test_flag_presence(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool verbose = false;
    static bool test_flag_absence(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool verbose = false;
    static bool test_count_repeated(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 verbose = 0;
    static bool test_count_bundled(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 verbose = 0;
    static bool test_positional_order(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
    
        Zstr src = NULL;
    static bool test_positional_with_interleaved_flag(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
    
        Zstr src     = NULL;
    static bool test_type_inferred_u32(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 n = 0;
    static bool test_type_inferred_i64_negative(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        i64 v = 0;
    static bool test_type_inferred_f64(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        f64 ratio = 1.0;
    static bool test_type_inferred_str(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Str name = StrInit(&a);
    static bool test_missing_required(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_missing_positional(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
    
        Zstr src = NULL;
    static bool test_unknown_option(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool v = false;
    static bool test_invalid_value_for_type(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 n = 0;
    static bool test_u8_overflow(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u8 v = 0;
    static bool test_too_many_positionals(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr x = NULL;
    static bool run_bool_value(Zstr text, bool *out) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        ArgOptional(&p, NULL, "--enable", out, "toggle");
        char  *argv[] = {(char *)"prog", (char *)"--enable", (char *)text};
        // pre-existing target value must be left untouched.
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        bool             v = true;
        ArgOptional(&p, NULL, "--enable", &v, "toggle");
    static bool test_count_u8_target(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u8               n = 0;
        ArgCount(&p, "-v", "--verbose", &n, "v");
    static bool test_count_u16_target(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u16              n = 0;
        ArgCount(&p, "-v", "--verbose", &n, "v");
    static bool test_count_u64_target(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u64              n = 0;
        ArgCount(&p, "-v", "--verbose", &n, "v");
        // parse must error rather than read past argv.
        DefaultAllocator a      = DefaultAllocatorInit();
        ArgParse         p      = ArgParseInit("prog", NULL, &a);
        Zstr             listen = NULL;
        ArgRequired(&p, "-l", "--listen", &listen, "host:port");
        // A boolean flag takes no value; "--verbose=1" must be rejected.
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        bool             v = false;
        ArgFlag(&p, "-v", "--verbose", &v, "v");
    static bool test_count_rejects_inline_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u32              n = 0;
        ArgCount(&p, "-v", "--verbose", &n, "v");
        // it must error rather than silently treat "lX" as bundled flags.
        DefaultAllocator a      = DefaultAllocatorInit();
        ArgParse         p      = ArgParseInit("prog", NULL, &a);
        Zstr             listen = NULL;
        ArgRequired(&p, "-l", "--listen", &listen, "host:port");
        // fail. Covers the range-check predicate in parse_signed.
        DefaultAllocator a  = DefaultAllocatorInit();
        ArgParse         p  = ArgParseInit("prog", NULL, &a);
        i16              lo = 0;
        i16              hi = 0;
    static bool test_signed_boundary_overflow_rejected(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        i16              v = 5;
        ArgOptional(&p, NULL, "--v", &v, "v");
    static bool test_double_dash_separator(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cat", NULL, &a);
    
        Zstr file = NULL;
    static bool test_help_returns_help_code(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", "test prog", &a);
    
        Zstr required = NULL;
    static bool test_a1_full_layout(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", "test prog", &a);
    
        Zstr src     = NULL;
    static bool test_a1_no_about_no_options(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_a1_positionals_section(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
    
        Zstr from = NULL;
    static bool test_a1_short_only_flag(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool quiet = false;
    static bool test_a1_empty_help_padding(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr mode = NULL;
    static bool test_a1_render_cap_is_64(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool flags[70] = {0};
    static bool run_u32(Zstr text, u32 *out, ArgRun *rc) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        ArgOptional(&p, NULL, "--n", out, "count");
        char *argv[] = {(char *)"prog", (char *)"--n", (char *)text};
    static bool run_u64(Zstr text, u64 *out, ArgRun *rc) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        ArgOptional(&p, NULL, "--n", out, "count");
        char *argv[] = {(char *)"prog", (char *)"--n", (char *)text};
    static bool test_a2_store_u8_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u8               v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u8_boundary(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u8               v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u16_boundary(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u16              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u16_overflow(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u16              v = 9;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u32_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u32              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u32_overflow(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u32              v = 11;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_u64_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u64              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_str_value(void) {
        DefaultAllocator a    = DefaultAllocatorInit();
        ArgParse         p    = ArgParseInit("prog", NULL, &a);
        Str              name = StrInit(&a);
        StrPushBackMany(&name, "stale");
    static bool test_a2_store_zstr_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             s = NULL;
        ArgOptional(&p, NULL, "--name", &s, "n");
    static bool test_a2_store_i16_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        i16              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_i16_rejects_garbage(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        i16              v = 7;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_i32_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        i32              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_i32_rejects_garbage(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        i32              v = 13;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_f32_value(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        f32              v = 0;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_store_f32_rejects_garbage(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        f32              v = 9;
        ArgOptional(&p, NULL, "--v", &v, "");
    static bool test_a2_metavar_uppercased(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, "-l", "--listen", &v, "addr");
    static bool test_a2_metavar_hyphen_to_underscore(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, NULL, "--read-only", &v, "mode");
    static bool test_a2_metavar_skips_double_dash(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, NULL, "--port", &v, "p");
    static bool test_a2_metavar_short_only_fallback(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, "-x", NULL, &v, "x");
    static bool test_a2_metavar_digits_passthrough(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, NULL, "--ip6", &v, "x");
    static bool test_a2_metavar_z_uppercased(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, NULL, "--gzip", &v, "x");
    static bool test_a2_metavar_a_uppercased(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, NULL, "--abc", &v, "x");
    static bool test_a2_left_positional_brackets(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
        Zstr             s = NULL;
        ArgPositional(&p, "source", &s, "from");
    static bool test_a2_left_short_and_long(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, "-l", "--listen", &v, "addr");
    static bool test_a2_left_full_option_line(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        Zstr             v = NULL;
        ArgRequired(&p, "-l", "--listen", &v, "addr");
    static bool test_a2_left_long_only_pads_short(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        u32              t = 0;
        ArgOptional(&p, NULL, "--timeout", &t, "secs");
    static bool test_a2_left_flag_has_no_metavar(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
        bool             f = false;
        ArgFlag(&p, "-v", "--verbose", &f, "v");
    static bool test_a2_left_width_drives_padding(void) {
        DefaultAllocator a  = DefaultAllocatorInit();
        ArgParse         p  = ArgParseInit("prog", NULL, &a);
        bool             aa = false;
        Zstr             bb = NULL;
    static bool test_a3_run_argc_zero_is_ok(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        ArgRun rc = ArgParseRun(&p, 0, NULL);
    static bool test_a3_inline_value_flag_name_terminated(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_a3_find_short_matches_correct_spec(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool aflag = false;
    static bool test_a3_bundle_invalid_char_errors(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 verbose = 0;
    static bool test_a3_bundle_lookup_key_terminated(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32 verbose = 0;
    static bool test_a3_bundle_flag_stores_true(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool f = false;
    static bool test_a3_flag_bundle_accepted(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool f = false;
    static bool test_a3_bundle_then_missing_required(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        u32  verbose = 0;
    static bool test_a3_short_only_option_registers(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool v = false;
    static bool test_a3_option_without_any_name_aborts(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        bool v = false;
    static bool test_mut_help_role_drives_options_tag(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("cp", NULL, &a);
    
        Zstr from = NULL;
    static bool test_blind_too_many_positionals_message(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr x = NULL;
    static bool test_blind_missing_required_message(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        Zstr listen = NULL;
    static bool test_blind_flag_name_too_long_boundary(void) {
        DefaultAllocator a = DefaultAllocatorInit();
        ArgParse         p = ArgParseInit("prog", NULL, &a);
    
        // Build "--" + 126 'a' = 128-char long name, then register it.
        Allocator     *adbg = ALLOCATOR_OF(&dbg);
    
        ArgParse p = ArgParseInit("prog", "an about line", adbg);
    
        Zstr listen   = NULL;
Last updated on