Home > Blockchain >  Cannot parse flag with argument in argp.h
Cannot parse flag with argument in argp.h

Time:10-06

I'm learning C, and got stuck doing cli parsing with <argp.h>. I want to specify path with -p, --path flags, so I did this:

#include "treesome.h"
#include <argp.h>
#include <stdio.h>

const char *argp_program_version =
    "treesome-build 0.2";


static char doc[] =
    "Treesome -- filesystem tree-like output\
\v Tree will show easy to eyeball directory structure";

static char args_doc[] = "";

static struct argp_option options[] = {
{0,0,0,0, "Output view" },
{"all", 'a', 0, 0, "produce verbose output with all the content"},
{"dereference", 'd', 0, 0, "dereferences soft links"},
{"path", 'p', 0, OPTION_ARG_OPTIONAL, "specify path for tree root"},
{ 0 }
};

struct arguments {
    int all, derefence, is_path;
    char *path;
};

static error_t parse_opts(int key, char *arg, struct argp_state *state) {
    struct arguments *arguments = state->input;

    switch (key) {
        case 'a':
            arguments->all = 1;
            break;
        case 'd':
            arguments->derefence = 1;
            break;
        case 'p':
            arguments->is_path = 1;
            break;
        case ARGP_KEY_ARG:
            if (state->arg_num == 0)
                break;
            if (arguments->is_path == 1)
                arguments->path = arg;
            break;
        default:
            return ARGP_ERR_UNKNOWN;
    }
    return 0;
};

static struct argp argp = {
options,
parse_opts,
args_doc,
doc
};

int main(int argc, char **argv) {
    struct arguments arguments;

    arguments.all = 0;
    arguments.derefence = 0;
    arguments.path = ".";

    argp_parse(&argp, argc, argv, 0, 0, &arguments);
    printf("Called with args: \n");
    printf("%d for all\n", arguments.all);
    printf("%d for dereference\n", arguments.derefence);
    printf("%s for path\n\n", arguments.path);
    return treesome(arguments.path);
};

and typing ./tree -p /home/floatfoo/ I got that path is always default. What might be a problem? I dont quite understand what for ARGP_KEY_ARG and ARGP_KEY_ARGS are used for

CodePudding user response:

After removing treesome your option does not take an argument:

{"path", 'p', 0, OPTION_ARG_OPTIONAL, "specify path for tree root"},
             ^^^

./a.out --help
     -p, --path                 specify path for tree root

You have to take the option:

 {"path", 'p', "path", OPTION_ARG_OPTIONAL, "specify path for tree root"},

 ./a.out --help
     -p, --path[=path]          specify path for tree root

In which case only the long form takes the option.

./a.out -p smth      -> too many arguments
./a.out --path=smth  -> ok

Remove OPTION_ARG_OPTIONAL if you want -p to take arg. And also set your path and remove the KEY_ARG case. It's just:

static error_t parse_opts(int key, char *arg, struct argp_state *state) {
    struct arguments *arguments = state->input;

    switch (key) {
        case 'a':
            arguments->all = 1;
            break;
        case 'd':
            arguments->derefence = 1;
            break;
        case 'p':
            arguments->path = arg;
            break;
        default:
            return ARGP_ERR_UNKNOWN;
    }
    return 0;
};
  • Related