diff options
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | include/cli.h (renamed from include/optparse.h) | 27 | ||||
-rw-r--r-- | lib/cli/optparse.c (renamed from lib/optparse/optparse.c) | 48 |
3 files changed, 41 insertions, 42 deletions
@@ -12,12 +12,12 @@ library. It is a C23 library with no plans to support older standards. The headers as of now are: • alloc.h — allocators and memory allocation functions • bitset.h — bitset implementation + • cli.h — CLI-option parsing functions • dynarr.h — dynamic array implementation • errors.h — err.h-inspired diagnostics functions • macros.h — miscellaneous utility macros (MIN/MAX/lengthof/etc.) • mbio.h — multibyte file I/O • mbstring.h — multibyte-strings - • optparse.h — option parsing functions • rune.h — inttypes.h but for runes • unicode/prop.h — unicode character properties • unicode/string.h — unicode string functions @@ -72,6 +72,9 @@ FEATURES: memory-allocating functions • bitset.h • Bitset implementation and operations + • cli.h + • Thread-safe (non-global) UTF-8-aware option parsing with + support for short- and long options • dynarr.h • Dynamic-array implementation and operations • Macro for array iteration @@ -95,9 +98,6 @@ FEATURES: • UTF-8 validation • Various string.h analogues with UTF-8 support • Random utility macros and -constants - • optparse.h - • Thread-safe (non-global) UTF-8-aware option parsing with - support for short- and long options • rune.h • Format string macros for the printf() and scanf() families of functions diff --git a/include/optparse.h b/include/cli.h index 7e2c315..7b5b611 100644 --- a/include/optparse.h +++ b/include/cli.h @@ -1,14 +1,13 @@ -#ifndef MLIB_OPTPARSE_H -#define MLIB_OPTPARSE_H +#ifndef MLIB_CLI_H +#define MLIB_CLI_H #include <stddef.h> #include "_attrs.h" -#include "_charN_t.h" #include "_rune.h" #include "_u8view.h" -struct optparse { +struct optparser { bool _b; int _subopt; char **_argv; @@ -18,29 +17,29 @@ struct optparse { struct u8view optarg; }; -enum op_argkind { - OPT_NONE, - OPT_OPT, - OPT_REQ, +enum cliarg { + CLI_NONE, + CLI_OPT, + CLI_REQ, }; -struct op_option { +struct cli_option { rune shortopt; struct u8view longopt; - enum op_argkind argtype; + enum cliarg argtype; }; -[[nodiscard]] rune optparse(struct optparse *, const struct op_option *, +[[nodiscard]] rune optparse(struct optparser *, const struct cli_option *, size_t); [[_mlib_inline]] -static inline struct optparse +static inline struct optparser mkoptparser(char **argv) { - return (struct optparse){ + return (struct optparser){ ._argv = argv, .optind = argv[0] != nullptr, }; } -#endif /* !MLIB_OPTPARSE_H */ +#endif /* !MLIB_CLI_H */ diff --git a/lib/optparse/optparse.c b/lib/cli/optparse.c index 757dd47..ce688cf 100644 --- a/lib/optparse/optparse.c +++ b/lib/cli/optparse.c @@ -1,27 +1,27 @@ #include <stdio.h> #include <string.h> +#include "cli.h" #include "macros.h" #include "mbstring.h" -#include "optparse.h" -#define OPT_MSG_INVALID "invalid option" -#define OPT_MSG_MISSING "option requires an argument" -#define OPT_MSG_TOOMANY "option takes no arguments" +#define CLI_MSG_INVALID "invalid option" +#define CLI_MSG_MISSING "option requires an argument" +#define CLI_MSG_TOOMANY "option takes no arguments" #define IS_DASHDASH(s) ((s).len == 2 && (s).p[0] == '-' && (s).p[1] == '-') #define IS_LONGOPT(s) ((s).len >= 3 && (s).p[0] == '-' && (s).p[1] == '-') #define IS_SHORTOPT(s) ((s).len >= 2 && (s).p[0] == '-' && (s).p[1] != '-') -#define error(st, msg, x) \ +#define error(st, msg, x) \ _Generic((x), struct u8view: error_s, rune: error_r)((st), (msg), (x)) -static rune error_r(struct optparse *, const char *, rune); -static rune error_s(struct optparse *, const char *, struct u8view); -static rune shortopt(struct optparse *, const struct op_option *, size_t); +static rune error_r(struct optparser *, const char *, rune); +static rune error_s(struct optparser *, const char *, struct u8view); +static rune shortopt(struct optparser *, const struct cli_option *, size_t); rune -optparse(struct optparse *st, const struct op_option *opts, size_t nopts) +optparse(struct optparser *st, const struct cli_option *opts, size_t nopts) { st->errmsg[0] = '\0'; st->optarg = (struct u8view){}; @@ -46,7 +46,7 @@ optparse(struct optparse *st, const struct op_option *opts, size_t nopts) /* Skip ‘--’ */ VSHFT(&opt, 2); - const struct op_option *o = nullptr; + const struct cli_option *o = nullptr; const char8_t *eq_p = u8chr(opt, '='); struct u8view opt_no_eq = { .p = opt.p, @@ -58,19 +58,19 @@ optparse(struct optparse *st, const struct op_option *opts, size_t nopts) if (lo.p == nullptr || !u8haspfx(lo, opt_no_eq)) continue; if (o != nullptr) - return error(st, OPT_MSG_INVALID, opt_no_eq); + return error(st, CLI_MSG_INVALID, opt_no_eq); o = opts + i; } if (o == nullptr) - return error(st, OPT_MSG_INVALID, opt_no_eq); + return error(st, CLI_MSG_INVALID, opt_no_eq); switch (o->argtype) { - case OPT_NONE: + case CLI_NONE: if (eq_p != nullptr) - return error(st, OPT_MSG_TOOMANY, opt); + return error(st, CLI_MSG_TOOMANY, opt); break; - case OPT_OPT: + case CLI_OPT: if (eq_p == nullptr) st->optarg = (struct u8view){}; else { @@ -81,10 +81,10 @@ optparse(struct optparse *st, const struct op_option *opts, size_t nopts) }; } break; - case OPT_REQ: + case CLI_REQ: if (eq_p == nullptr) { if (st->_argv[st->optind] == nullptr) - return error(st, OPT_MSG_MISSING, opt); + return error(st, CLI_MSG_MISSING, opt); st->optarg.p = st->_argv[st->optind++]; st->optarg.len = strlen(st->optarg.p); } else { @@ -101,7 +101,7 @@ optparse(struct optparse *st, const struct op_option *opts, size_t nopts) } rune -shortopt(struct optparse *st, const struct op_option *opts, size_t nopts) +shortopt(struct optparser *st, const struct cli_option *opts, size_t nopts) { rune ch; const char *opt = st->_argv[st->optind]; @@ -114,7 +114,7 @@ shortopt(struct optparse *st, const struct op_option *opts, size_t nopts) for (size_t i = 0; i < nopts; i++) { if (opts[i].shortopt != ch) continue; - if (opts[i].argtype == OPT_NONE) + if (opts[i].argtype == CLI_NONE) goto out; if (opt[st->_subopt + 1] != '\0') { st->optarg.p = opt + st->_subopt + 1; @@ -123,26 +123,26 @@ shortopt(struct optparse *st, const struct op_option *opts, size_t nopts) st->optind++; goto out; } - if (opts[i].argtype == OPT_OPT) { + if (opts[i].argtype == CLI_OPT) { st->optarg = (struct u8view){}; goto out; } if (st->_argv[st->optind + 1] == nullptr) { st->optarg = (struct u8view){}; - return error(st, OPT_MSG_MISSING, ch); + return error(st, CLI_MSG_MISSING, ch); } st->optarg.p = st->_argv[st->optind + 1]; st->optarg.len = strlen(st->optarg.p); st->optind += 2; goto out; } - return error(st, OPT_MSG_INVALID, ch); + return error(st, CLI_MSG_INVALID, ch); out: return ch; } rune -error_s(struct optparse *st, const char *msg, struct u8view s) +error_s(struct optparser *st, const char *msg, struct u8view s) { snprintf(st->errmsg, sizeof(st->errmsg), u8"%s — ‘%.*s’", msg, SV_PRI_ARGS(s)); @@ -150,7 +150,7 @@ error_s(struct optparse *st, const char *msg, struct u8view s) } rune -error_r(struct optparse *st, const char *msg, rune ch) +error_r(struct optparser *st, const char *msg, rune ch) { char buf[U8_LEN_MAX + 1] = {}; snprintf(st->errmsg, sizeof(st->errmsg), u8"%s — ‘%.*s’", msg, |