#include #include #include "cli.h" #include "log.h" #include "serval.h" #include "rhizome.h" #include "strbuf_helpers.h" int cli_usage(const struct cli_schema *commands, XPRINTF xpf) { return cli_usage_args(0, NULL, commands, xpf); } int cli_usage_parsed(const struct cli_parsed *parsed, XPRINTF xpf) { if (parsed->varargi == -1) return cli_usage(parsed->commands, xpf); return cli_usage_args(parsed->argc - parsed->varargi, &parsed->args[parsed->varargi], parsed->commands, xpf); } int cli_usage_args(const int argc, const char *const *args, const struct cli_schema *commands, XPRINTF xpf) { unsigned cmd; int matched_any = 0; for (cmd = 0; commands[cmd].function; ++cmd) { unsigned opt; const char *word; int matched = 1; for (opt = 0; matched && opt < argc && (word = commands[cmd].words[opt]); ++opt) if (strncmp(word, args[opt], strlen(args[opt])) != 0) matched = 0; if (matched) { matched_any = 1; for (opt = 0; (word = commands[cmd].words[opt]); ++opt) { if (word[0] == '\\') ++word; xprintf(xpf, " %s", word); } xputc('\n', xpf); if (commands[cmd].description && commands[cmd].description[0]) xprintf(xpf, " %s\n", commands[cmd].description); } } if (!matched_any && argc) { strbuf b = strbuf_alloca(160); strbuf_append_argv(b, argc, args); xprintf(xpf, " No commands matching %s\n", strbuf_str(b)); } return 0; } int cli_parse(const int argc, const char *const *args, const struct cli_schema *commands, struct cli_parsed *parsed) { int ambiguous = 0; int matched_cmd = -1; int cmd; for (cmd = 0; commands[cmd].function; ++cmd) { struct cli_parsed cmdpa; memset(&cmdpa, 0, sizeof cmdpa); cmdpa.commands = commands; cmdpa.cmdi = cmd; cmdpa.args = args; cmdpa.argc = argc; cmdpa.labelc = 0; cmdpa.varargi = -1; const char *word = NULL; unsigned arg = 0; unsigned opt = 0; while ((word = commands[cmd].words[opt])) { //DEBUGF("cmd=%d opt=%d word='%s' args[arg=%d]='%s'", cmd, opt, word, arg, arg < argc ? args[arg] : ""); unsigned wordlen = strlen(word); if (cmdpa.varargi != -1) return WHYF("Internal error: commands[%d].word[%d]=\"%s\" - more words not allowed after \"...\"", cmd, opt, word); /* These are the argument matching rules: * * "..." consumes all remaining arguments * * "word" consumes one argument that exactly matches "word", does not label it * * "\word" consumes one argument that exactly matches "word" and labels it "word" * * "[word]" consumes one argument if it exactly matches "word", records it with label * "word" * * "