#ifndef KIcli #define KIcli #include #include #include #include /* input types */ typedef struct kcli_opt { codepoint id; const char* name; enum kcli_opt_kind { kcli_opt_none /* flag is disabled and hidden */, kcli_opt_string /* flag takes a string argument */, kcli_opt_flag /* on if present, off if absent */, kcli_opt_toggle /* off by default, value toggles * for each occurrence */, kcli_opt_accumulate /* u8, value increases for each * occurrence, saturates at 255 */, kcli_opt_enum /* matched against a table of string * values to retrieve the corresponding * integer ID */, kcli_opt_int = 0x40, /* kcli_opt_int takes a default base parameter. * for instance, to take a decimal number, you * might write `kcli_opt_int | 10.` if the * argument takes a base prefix, the default * base will be disregarded. */ kcli_opt_oct = kcli_opt_int | 8, kcli_opt_dec = kcli_opt_int | 10, kcli_opt_hex = kcli_opt_int | 16, } kind; void* val; const char* desc; } kcli_opt; typedef struct kcli_param { const char* name; enum kcli_param_kind { kcli_param_none, kcli_param_string, kcli_param_enum, kcli_param_int = 0x40, kcli_param_oct = kcli_param_int | 8, kcli_param_dec = kcli_param_int | 10, kcli_param_hex = kcli_param_int | 16, } kind; enum kcli_rule { kcli_rule_forbidden, kcli_rule_optional, kcli_rule_required, } rule; } kcli_param; typedef struct kcli_set { const char* name; const char* version; const char** args; sz argc; const char* desc; const kcli_param* params; sz paramc; const kcli_opt* opts; sz optc; } kcli_set; /* output types */ typedef enum kcli_cond { kcli_cond_ok = kcli_cond_id, kcli_cond_extra /* parse succeded, but arguments or flags were left over */, kcli_cond_fail /* unspecified error */, kcli_cond_parse /* bad syntax, parse failed */, } kcli_cond; typedef enum kcli_flag { kcli_flag_off = 0, kcli_flag_on = 1, } kcli_flag; /* functions */ kcond kcli_usage(kcli_set, kiochan); kcli_cond kcli_parse(kcli_set); /* macros */ #define Kcli_param(field,kind,rule,description) \ {#field, kcli_param_##kind, kcli_rule_##rule, &field, description} #define Kcli_opt(long,short,kind,description) \ {short, #long, kcli_opt_##kind, &long, description} #endif