aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README8
-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
diff --git a/README b/README
index 2feb1ba..c946ff6 100644
--- a/README
+++ b/README
@@ -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,