rename to readarg

This commit is contained in:
Lukas Wurzinger 2022-10-12 21:49:23 +02:00
parent b4b72a51d5
commit 5e200ea4f8
3 changed files with 161 additions and 161 deletions

View file

@ -1,4 +1,4 @@
# readopt # readarg
## Features ## Features
@ -20,11 +20,11 @@ it into your project directory and including it. Alternatively, you could choose
to use a Git submodule. In any case, attribution is not required. to use a Git submodule. In any case, attribution is not required.
It is required that one file in your project defines the It is required that one file in your project defines the
`READOPT_IMPLEMENTATION` macro before including the `readopt.h` header file, `READARG_IMPLEMENTATION` macro before including the `readarg.h` header file,
as with any other single-header library. as with any other single-header library.
An example for how to use readopt can be found in `test/test.c`. If you want to An example for how to use readarg can be found in `test/test.c`. If you want to
see how readopt represents options and operands, execute `test.sh` in the same see how readarg represents options and operands, execute `test.sh` in the same
directory. directory.
## Terminology ## Terminology
@ -35,11 +35,11 @@ an argument is, you can skim this document to get a better idea:
## Internals ## Internals
readopt permutes `argv` to handle multiple values for each option and to assign readarg permutes `argv` to handle multiple values for each option and to assign
values to operands. The advantage of this approach is as follows: values to operands. The advantage of this approach is as follows:
* Allocations are not needed because the memory provided by `argv` is reused * Allocations are not needed because the memory provided by `argv` is reused
* It's fairly simple to represent all of this data in an intuitive data * It's fairly simple to represent all of this data in an intuitive data
structure (in my opinion anyway) structure (in my opinion anyway)
* For example, looping through operands is as simple as incrementing * For example, looping through operands is as simple as incrementing
`parser.oper` until `readopt_validate_oper` returns `0`. `parser.oper` until `readarg_validate_oper` returns `0`.

View file

@ -4,51 +4,51 @@
#include <stdio.h> #include <stdio.h>
#define READOPT_STRINGS(...) ((char *[]){__VA_ARGS__, NULL}) #define READARG_STRINGS(...) ((char *[]){__VA_ARGS__, NULL})
enum readopt_error enum readarg_error
{ {
READOPT_ERROR_SUCCESS, READARG_ERROR_SUCCESS,
READOPT_ERROR_NOVAL, READARG_ERROR_NOVAL,
READOPT_ERROR_NOTREQ, READARG_ERROR_NOTREQ,
READOPT_ERROR_NOTOPT, READARG_ERROR_NOTOPT,
READOPT_ERROR_RANGEOPT, READARG_ERROR_RANGEOPT,
READOPT_ERROR_RANGEOPER READARG_ERROR_RANGEOPER
}; };
enum readopt_form enum readarg_form
{ {
READOPT_FORM_SHORT, READARG_FORM_SHORT,
READOPT_FORM_LONG READARG_FORM_LONG
}; };
enum readopt_format enum readarg_format
{ {
READOPT_FORMAT_PLAIN, READARG_FORMAT_PLAIN,
READOPT_FORMAT_MDOC, READARG_FORMAT_MDOC,
}; };
struct readopt_view_strings struct readarg_view_strings
{ {
const char **strings; const char **strings;
size_t len; size_t len;
}; };
struct readopt_bounds struct readarg_bounds
{ {
/* The upper value will be ignored if inf is non-zero. */ /* The upper value will be ignored if inf is non-zero. */
size_t val[2]; size_t val[2];
int inf; int inf;
}; };
struct readopt_oper struct readarg_oper
{ {
char *name; char *name;
struct readopt_bounds bounds; struct readarg_bounds bounds;
struct readopt_view_strings val; struct readarg_view_strings val;
}; };
struct readopt_opt struct readarg_opt
{ {
/* Two null-terminated arrays of either long or short option names. */ /* Two null-terminated arrays of either long or short option names. */
char **names[2]; char **names[2];
@ -58,76 +58,76 @@ struct readopt_opt
int req; int req;
/* oper.name is the name of the value itself (not the option). */ /* oper.name is the name of the value itself (not the option). */
struct readopt_oper oper; struct readarg_oper oper;
} cont; } cont;
}; };
struct readopt_parser struct readarg_parser
{ {
struct readopt_opt *opts; struct readarg_opt *opts;
struct readopt_oper *opers; struct readarg_oper *opers;
struct readopt_view_strings args; struct readarg_view_strings args;
struct struct
{ {
int pending; int pending;
const char *grppos; const char *grppos;
struct struct
{ {
struct readopt_opt *opt; struct readarg_opt *opt;
/* Reference to the current argument being parsed. */ /* Reference to the current argument being parsed. */
const char **arg; const char **arg;
/* Reference to the last element of the option/operand value view. */ /* Reference to the last element of the option/operand value view. */
const char **eoval; const char **eoval;
/* Intermediate operands which have not yet been assigned. */ /* Intermediate operands which have not yet been assigned. */
struct readopt_view_strings ioper; struct readarg_view_strings ioper;
} curr; } curr;
} state; } state;
enum readopt_error error; enum readarg_error error;
}; };
/* Iteratively parse the arguments. */ /* Iteratively parse the arguments. */
int readopt_parse(struct readopt_parser *rp); int readarg_parse(struct readarg_parser *rp);
/* args should always exclude the first element. */ /* args should always exclude the first element. */
void readopt_parser_init(struct readopt_parser *rp, struct readopt_opt *opts, struct readopt_oper *opers, struct readopt_view_strings args); void readarg_parser_init(struct readarg_parser *rp, struct readarg_opt *opts, struct readarg_oper *opers, struct readarg_view_strings args);
/* Check whether the argument is a valid option (can be used to check for the end of an array of options). */ /* Check whether the argument is a valid option (can be used to check for the end of an array of options). */
int readopt_validate_opt(struct readopt_opt *opt); int readarg_validate_opt(struct readarg_opt *opt);
/* Check whether the argument is a valid operand (can be used to check for the end of an array of operands). */ /* Check whether the argument is a valid operand (can be used to check for the end of an array of operands). */
int readopt_validate_oper(struct readopt_oper *oper); int readarg_validate_oper(struct readarg_oper *oper);
/* Check whether the operand's values are within the defined limits. */ /* Check whether the operand's values are within the defined limits. */
int readopt_validate_within(struct readopt_oper *oper); int readarg_validate_within(struct readarg_oper *oper);
/* Get the upper limit. */ /* Get the upper limit. */
size_t readopt_select_upper(struct readopt_bounds bounds); size_t readarg_select_upper(struct readarg_bounds bounds);
/* Get the lower limit. This does not always return the minimum. */ /* Get the lower limit. This does not always return the minimum. */
size_t readopt_select_lower(struct readopt_bounds bounds); size_t readarg_select_lower(struct readarg_bounds bounds);
#ifdef READOPT_IMPLEMENTATION #ifdef READARG_IMPLEMENTATION
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
static void readopt_parse_arg(struct readopt_parser *rp, const char *arg); static void readarg_parse_arg(struct readarg_parser *rp, const char *arg);
static void readopt_parse_opt(struct readopt_parser *rp, enum readopt_form form, const char **pos); static void readarg_parse_opt(struct readarg_parser *rp, enum readarg_form form, const char **pos);
static struct readopt_opt *readopt_match_opt(struct readopt_parser *rp, enum readopt_form form, const char **needle); static struct readarg_opt *readarg_match_opt(struct readarg_parser *rp, enum readarg_form form, const char **needle);
static struct readopt_opt *readopt_match_finish(struct readopt_parser *rp, const char **needle, const char *adv, struct readopt_opt *opt); static struct readarg_opt *readarg_match_finish(struct readarg_parser *rp, const char **needle, const char *adv, struct readarg_opt *opt);
static void readopt_update_opt(struct readopt_parser *rp, const char *attach, struct readopt_opt *opt); static void readarg_update_opt(struct readarg_parser *rp, const char *attach, struct readarg_opt *opt);
static void readopt_update_oper(struct readopt_parser *rp, struct readopt_view_strings val); static void readarg_update_oper(struct readarg_parser *rp, struct readarg_view_strings val);
static void readopt_assign_opers(struct readopt_parser *rp); static void readarg_assign_opers(struct readarg_parser *rp);
static void readopt_add_val(struct readopt_parser *rp, struct readopt_oper *oper, const char *string, int end); static void readarg_add_val(struct readarg_parser *rp, struct readarg_oper *oper, const char *string, int end);
static const char *readopt_skip_incl(const char *outer, const char *inner); static const char *readarg_skip_incl(const char *outer, const char *inner);
static void readopt_occ_opt(struct readopt_parser *rp, struct readopt_opt *opt); static void readarg_occ_opt(struct readarg_parser *rp, struct readarg_opt *opt);
static void readopt_permute_val(struct readopt_parser *rp, struct readopt_view_strings *target, const char *val, int end); static void readarg_permute_val(struct readarg_parser *rp, struct readarg_view_strings *target, const char *val, int end);
static void readopt_incr_between(const char **start, const char **stop, struct readopt_view_strings *curr, struct readopt_view_strings *exclude); static void readarg_incr_between(const char **start, const char **stop, struct readarg_view_strings *curr, struct readarg_view_strings *exclude);
static void readopt_permute_rest(const char **target, struct readopt_view_strings start); static void readarg_permute_rest(const char **target, struct readarg_view_strings start);
int readopt_parse(struct readopt_parser *rp) int readarg_parse(struct readarg_parser *rp)
{ {
/* Check whether the current offset is at the end of argv. */ /* Check whether the current offset is at the end of argv. */
size_t off = rp->state.curr.arg - rp->args.strings; size_t off = rp->state.curr.arg - rp->args.strings;
@ -136,31 +136,31 @@ int readopt_parse(struct readopt_parser *rp)
if (rp->state.pending) if (rp->state.pending)
{ {
/* The last specified option required an argument, but no argument has been provided. */ /* The last specified option required an argument, but no argument has been provided. */
rp->error = READOPT_ERROR_NOVAL; rp->error = READARG_ERROR_NOVAL;
return 0; return 0;
} }
for (size_t i = 0; readopt_validate_opt(rp->opts + i); i++) for (size_t i = 0; readarg_validate_opt(rp->opts + i); i++)
{ {
if (!readopt_validate_within(&rp->opts[i].cont.oper)) if (!readarg_validate_within(&rp->opts[i].cont.oper))
{ {
rp->error = READOPT_ERROR_RANGEOPT; rp->error = READARG_ERROR_RANGEOPT;
return 0; return 0;
} }
} }
readopt_assign_opers(rp); readarg_assign_opers(rp);
return 0; return 0;
} }
if (rp->state.pending) if (rp->state.pending)
{ {
readopt_add_val(rp, &rp->state.curr.opt->cont.oper, *rp->state.curr.arg, 0); readarg_add_val(rp, &rp->state.curr.opt->cont.oper, *rp->state.curr.arg, 0);
++rp->state.curr.arg; ++rp->state.curr.arg;
return !rp->error; return !rp->error;
} }
readopt_parse_arg(rp, *rp->state.curr.arg); readarg_parse_arg(rp, *rp->state.curr.arg);
/* If grouped options are still being parsed, they should not be discarded. */ /* If grouped options are still being parsed, they should not be discarded. */
if (!rp->state.grppos) if (!rp->state.grppos)
@ -169,12 +169,12 @@ int readopt_parse(struct readopt_parser *rp)
return !rp->error; return !rp->error;
} }
static void readopt_parse_arg(struct readopt_parser *rp, const char *arg) static void readarg_parse_arg(struct readarg_parser *rp, const char *arg)
{ {
/* Parse the next option in the grouped option string, which automatically advances it. */ /* Parse the next option in the grouped option string, which automatically advances it. */
if (rp->state.grppos) if (rp->state.grppos)
{ {
readopt_parse_opt(rp, READOPT_FORM_SHORT, &rp->state.grppos); readarg_parse_opt(rp, READARG_FORM_SHORT, &rp->state.grppos);
if (!*rp->state.grppos) if (!*rp->state.grppos)
{ {
rp->state.grppos = NULL; rp->state.grppos = NULL;
@ -205,37 +205,37 @@ static void readopt_parse_arg(struct readopt_parser *rp, const char *arg)
return; return;
} }
readopt_update_oper(rp, (struct readopt_view_strings){ readarg_update_oper(rp, (struct readarg_view_strings){
.len = off - 1, .len = off - 1,
.strings = rp->state.curr.arg + 1}); .strings = rp->state.curr.arg + 1});
rp->state.curr.arg = rp->args.strings + rp->args.len - 1; rp->state.curr.arg = rp->args.strings + rp->args.len - 1;
return; return;
default: default:
readopt_parse_opt(rp, READOPT_FORM_LONG, &pos); readarg_parse_opt(rp, READARG_FORM_LONG, &pos);
return; return;
} }
case '\0': case '\0':
readopt_update_oper(rp, (struct readopt_view_strings){.len = 1, .strings = (const char *[]){arg}}); readarg_update_oper(rp, (struct readarg_view_strings){.len = 1, .strings = (const char *[]){arg}});
return; return;
default: default:
readopt_parse_opt(rp, READOPT_FORM_SHORT, &pos); readarg_parse_opt(rp, READARG_FORM_SHORT, &pos);
return; return;
} }
default: default:
readopt_update_oper(rp, (struct readopt_view_strings){.len = 1, .strings = (const char *[]){arg}}); readarg_update_oper(rp, (struct readarg_view_strings){.len = 1, .strings = (const char *[]){arg}});
return; return;
} }
} }
static void readopt_parse_opt(struct readopt_parser *rp, enum readopt_form form, const char **pos) static void readarg_parse_opt(struct readarg_parser *rp, enum readarg_form form, const char **pos)
{ {
struct readopt_opt *match; struct readarg_opt *match;
assert(form == READOPT_FORM_SHORT || form == READOPT_FORM_LONG); assert(form == READARG_FORM_SHORT || form == READARG_FORM_LONG);
if (form == READOPT_FORM_SHORT) if (form == READARG_FORM_SHORT)
{ {
match = readopt_match_opt(rp, form, pos); match = readarg_match_opt(rp, form, pos);
if (match) if (match)
{ {
const char *strpos = *pos; const char *strpos = *pos;
@ -243,47 +243,47 @@ static void readopt_parse_opt(struct readopt_parser *rp, enum readopt_form form,
if (!match->cont.req && *strpos) if (!match->cont.req && *strpos)
{ {
rp->state.grppos = strpos; rp->state.grppos = strpos;
readopt_update_opt(rp, NULL, match); readarg_update_opt(rp, NULL, match);
} }
else else
{ {
readopt_update_opt(rp, *strpos ? strpos : NULL, match); readarg_update_opt(rp, *strpos ? strpos : NULL, match);
} }
} }
else else
{ {
rp->error = READOPT_ERROR_NOTOPT; rp->error = READARG_ERROR_NOTOPT;
} }
} }
else else
{ {
/* Match and advance pos to the end of the match. */ /* Match and advance pos to the end of the match. */
match = readopt_match_opt(rp, form, pos); match = readarg_match_opt(rp, form, pos);
if (match) if (match)
{ {
switch (**pos) switch (**pos)
{ {
case '\0': case '\0':
readopt_update_opt(rp, NULL, match); readarg_update_opt(rp, NULL, match);
break; break;
case '=': case '=':
++(*pos); ++(*pos);
readopt_update_opt(rp, *pos, match); readarg_update_opt(rp, *pos, match);
break; break;
default: default:
rp->error = READOPT_ERROR_NOTOPT; rp->error = READARG_ERROR_NOTOPT;
break; break;
} }
} }
else else
{ {
rp->error = READOPT_ERROR_NOTOPT; rp->error = READARG_ERROR_NOTOPT;
} }
} }
} }
static struct readopt_opt *readopt_match_opt(struct readopt_parser *rp, enum readopt_form form, const char **needle) static struct readarg_opt *readarg_match_opt(struct readarg_parser *rp, enum readarg_form form, const char **needle)
{ {
/* This represents the last inexact match. */ /* This represents the last inexact match. */
struct struct
@ -291,11 +291,11 @@ static struct readopt_opt *readopt_match_opt(struct readopt_parser *rp, enum rea
/* The current advanced string. */ /* The current advanced string. */
const char *adv; const char *adv;
/* The current option. */ /* The current option. */
struct readopt_opt *opt; struct readarg_opt *opt;
} loose = {0}; } loose = {0};
struct readopt_opt *haystack = rp->opts; struct readarg_opt *haystack = rp->opts;
for (size_t i = 0; readopt_validate_opt(haystack + i); i++) for (size_t i = 0; readarg_validate_opt(haystack + i); i++)
{ {
/* Iterate through all short or long names of the current option. */ /* Iterate through all short or long names of the current option. */
char **names = haystack[i].names[form]; char **names = haystack[i].names[form];
@ -309,24 +309,24 @@ static struct readopt_opt *readopt_match_opt(struct readopt_parser *rp, enum rea
for (size_t j = 0; names[j]; j++) for (size_t j = 0; names[j]; j++)
{ {
char *name = names[j]; char *name = names[j];
cmp = readopt_skip_incl(*needle, name); cmp = readarg_skip_incl(*needle, name);
if (!cmp) if (!cmp)
continue; continue;
if (!*cmp) if (!*cmp)
/* A guaranteed match. */ /* A guaranteed match. */
return readopt_match_finish(rp, needle, cmp, haystack + i); return readarg_match_finish(rp, needle, cmp, haystack + i);
else if ((cmp - *needle) > (loose.adv - *needle)) else if ((cmp - *needle) > (loose.adv - *needle))
/* Maybe a match, maybe not. */ /* Maybe a match, maybe not. */
loose.adv = cmp, loose.opt = haystack + i; loose.adv = cmp, loose.opt = haystack + i;
} }
} }
return readopt_match_finish(rp, needle, loose.adv, loose.opt); return readarg_match_finish(rp, needle, loose.adv, loose.opt);
} }
static struct readopt_opt *readopt_match_finish(struct readopt_parser *rp, const char **needle, const char *adv, struct readopt_opt *opt) static struct readarg_opt *readarg_match_finish(struct readarg_parser *rp, const char **needle, const char *adv, struct readarg_opt *opt)
{ {
if (adv) if (adv)
*needle = adv; *needle = adv;
@ -337,63 +337,63 @@ static struct readopt_opt *readopt_match_finish(struct readopt_parser *rp, const
return opt; return opt;
} }
static void readopt_update_opt(struct readopt_parser *rp, const char *attach, struct readopt_opt *opt) static void readarg_update_opt(struct readarg_parser *rp, const char *attach, struct readarg_opt *opt)
{ {
if (opt->cont.req) if (opt->cont.req)
{ {
if (attach) if (attach)
{ {
/* --opt=value, --opt=, -ovalue */ /* --opt=value, --opt=, -ovalue */
struct readopt_oper *curr = &rp->state.curr.opt->cont.oper; struct readarg_oper *curr = &rp->state.curr.opt->cont.oper;
readopt_occ_opt(rp, opt); readarg_occ_opt(rp, opt);
readopt_add_val(rp, curr, attach, 0); readarg_add_val(rp, curr, attach, 0);
} }
else else
{ {
/* --opt value, -o value */ /* --opt value, -o value */
rp->state.pending = 1; rp->state.pending = 1;
readopt_occ_opt(rp, opt); readarg_occ_opt(rp, opt);
} }
} }
else else
{ {
readopt_occ_opt(rp, opt); readarg_occ_opt(rp, opt);
if (attach) if (attach)
rp->error = READOPT_ERROR_NOTREQ; rp->error = READARG_ERROR_NOTREQ;
} }
} }
static void readopt_update_oper(struct readopt_parser *rp, struct readopt_view_strings val) static void readarg_update_oper(struct readarg_parser *rp, struct readarg_view_strings val)
{ {
assert(val.len && val.strings); assert(val.len && val.strings);
if (val.len == 1) if (val.len == 1)
{ {
++rp->state.curr.ioper.len; ++rp->state.curr.ioper.len;
readopt_permute_val(rp, &rp->state.curr.ioper, val.strings[0], 1); readarg_permute_val(rp, &rp->state.curr.ioper, val.strings[0], 1);
} }
else else
{ {
readopt_permute_rest(rp->state.curr.eoval, val); readarg_permute_rest(rp->state.curr.eoval, val);
rp->state.curr.ioper.len += val.len; rp->state.curr.ioper.len += val.len;
} }
} }
static void readopt_assign_opers(struct readopt_parser *rp) static void readarg_assign_opers(struct readarg_parser *rp)
{ {
size_t count = rp->state.curr.ioper.len; size_t count = rp->state.curr.ioper.len;
size_t nlower = 0; size_t nlower = 0;
size_t nupper = 0; size_t nupper = 0;
for (size_t i = 0; readopt_validate_oper(rp->opers + i); i++) for (size_t i = 0; readarg_validate_oper(rp->opers + i); i++)
{ {
nlower += readopt_select_lower(rp->opers[i].bounds); nlower += readarg_select_lower(rp->opers[i].bounds);
nupper += readopt_select_upper(rp->opers[i].bounds); nupper += readarg_select_upper(rp->opers[i].bounds);
} }
if (count < nlower) if (count < nlower)
{ {
rp->error = READOPT_ERROR_RANGEOPER; rp->error = READARG_ERROR_RANGEOPER;
return; return;
} }
@ -405,7 +405,7 @@ static void readopt_assign_opers(struct readopt_parser *rp)
count - nlower, count - nlower,
nlower}; nlower};
for (size_t i = 0; readopt_validate_oper(rp->opers + i); i++) for (size_t i = 0; readarg_validate_oper(rp->opers + i); i++)
{ {
if (count == 0 || !rp->opers[i].val.strings) if (count == 0 || !rp->opers[i].val.strings)
{ {
@ -413,8 +413,8 @@ static void readopt_assign_opers(struct readopt_parser *rp)
rp->opers[i].val.strings = rp->state.curr.ioper.strings + off; rp->opers[i].val.strings = rp->state.curr.ioper.strings + off;
} }
size_t lower = readopt_select_lower(rp->opers[i].bounds); size_t lower = readarg_select_lower(rp->opers[i].bounds);
size_t upper = readopt_select_upper(rp->opers[i].bounds); size_t upper = readarg_select_upper(rp->opers[i].bounds);
int inf = rp->opers[i].bounds.inf; int inf = rp->opers[i].bounds.inf;
size_t add; size_t add;
@ -430,20 +430,20 @@ static void readopt_assign_opers(struct readopt_parser *rp)
} }
if (rest.extra || rest.req) if (rest.extra || rest.req)
rp->error = READOPT_ERROR_RANGEOPER; rp->error = READARG_ERROR_RANGEOPER;
} }
static void readopt_add_val(struct readopt_parser *rp, struct readopt_oper *oper, const char *string, int end) static void readarg_add_val(struct readarg_parser *rp, struct readarg_oper *oper, const char *string, int end)
{ {
rp->state.pending = 0; rp->state.pending = 0;
if (!readopt_validate_within(oper)) if (!readarg_validate_within(oper))
rp->error = READOPT_ERROR_RANGEOPT; rp->error = READARG_ERROR_RANGEOPT;
else else
readopt_permute_val(rp, &oper->val, string, end); readarg_permute_val(rp, &oper->val, string, end);
} }
static const char *readopt_skip_incl(const char *outer, const char *inner) static const char *readarg_skip_incl(const char *outer, const char *inner)
{ {
while (*inner == *outer) while (*inner == *outer)
{ {
@ -454,14 +454,14 @@ static const char *readopt_skip_incl(const char *outer, const char *inner)
return !*inner ? outer : NULL; return !*inner ? outer : NULL;
} }
static void readopt_occ_opt(struct readopt_parser *rp, struct readopt_opt *opt) static void readarg_occ_opt(struct readarg_parser *rp, struct readarg_opt *opt)
{ {
assert(opt); assert(opt);
rp->state.curr.opt = opt; rp->state.curr.opt = opt;
++rp->state.curr.opt->cont.oper.val.len; ++rp->state.curr.opt->cont.oper.val.len;
} }
static void readopt_permute_val(struct readopt_parser *rp, struct readopt_view_strings *target, const char *val, int end) static void readarg_permute_val(struct readarg_parser *rp, struct readarg_view_strings *target, const char *val, int end)
{ {
if (!target->strings) if (!target->strings)
/* Fallback position when no value has yet been set. */ /* Fallback position when no value has yet been set. */
@ -479,26 +479,26 @@ static void readopt_permute_val(struct readopt_parser *rp, struct readopt_view_s
const char **start = pos, **stop = rp->state.curr.eoval; const char **start = pos, **stop = rp->state.curr.eoval;
/* Increment all value pointers in the options which are between start and stop (inclusive). */ /* Increment all value pointers in the options which are between start and stop (inclusive). */
for (size_t i = 0; readopt_validate_opt(rp->opts + i); i++) for (size_t i = 0; readarg_validate_opt(rp->opts + i); i++)
readopt_incr_between(start, stop, &rp->opts[i].cont.oper.val, target); readarg_incr_between(start, stop, &rp->opts[i].cont.oper.val, target);
readopt_incr_between(start, stop, &rp->state.curr.ioper, target); readarg_incr_between(start, stop, &rp->state.curr.ioper, target);
} }
static void readopt_incr_between(const char **start, const char **stop, struct readopt_view_strings *curr, struct readopt_view_strings *exclude) static void readarg_incr_between(const char **start, const char **stop, struct readarg_view_strings *curr, struct readarg_view_strings *exclude)
{ {
if (curr->strings >= start && curr->strings <= stop && curr != exclude) if (curr->strings >= start && curr->strings <= stop && curr != exclude)
++curr->strings; ++curr->strings;
} }
static void readopt_permute_rest(const char **target, struct readopt_view_strings start) static void readarg_permute_rest(const char **target, struct readarg_view_strings start)
{ {
memmove(target, start.strings, start.len * sizeof *start.strings); memmove(target, start.strings, start.len * sizeof *start.strings);
} }
void readopt_parser_init(struct readopt_parser *rp, struct readopt_opt *opts, struct readopt_oper *opers, struct readopt_view_strings args) void readarg_parser_init(struct readarg_parser *rp, struct readarg_opt *opts, struct readarg_oper *opers, struct readarg_view_strings args)
{ {
*rp = (struct readopt_parser){ *rp = (struct readarg_parser){
.args = args, .args = args,
.opts = opts, .opts = opts,
.opers = opers, .opers = opers,
@ -507,34 +507,34 @@ void readopt_parser_init(struct readopt_parser *rp, struct readopt_opt *opts, st
.eoval = args.strings}}; .eoval = args.strings}};
} }
int readopt_validate_opt(struct readopt_opt *opt) int readarg_validate_opt(struct readarg_opt *opt)
{ {
assert(opt); assert(opt);
return opt->names[0] || opt->names[1]; return opt->names[0] || opt->names[1];
} }
int readopt_validate_oper(struct readopt_oper *oper) int readarg_validate_oper(struct readarg_oper *oper)
{ {
assert(oper); assert(oper);
return !!oper->name; return !!oper->name;
} }
int readopt_validate_within(struct readopt_oper *oper) int readarg_validate_within(struct readarg_oper *oper)
{ {
size_t occ = oper->val.len; size_t occ = oper->val.len;
size_t upper = readopt_select_upper(oper->bounds); size_t upper = readarg_select_upper(oper->bounds);
size_t lower = readopt_select_lower(oper->bounds); size_t lower = readarg_select_lower(oper->bounds);
return occ >= lower && (occ <= upper || oper->bounds.inf); return occ >= lower && (occ <= upper || oper->bounds.inf);
} }
size_t readopt_select_upper(struct readopt_bounds bounds) size_t readarg_select_upper(struct readarg_bounds bounds)
{ {
return bounds.val[0] > bounds.val[1] ? bounds.val[0] : bounds.val[1]; return bounds.val[0] > bounds.val[1] ? bounds.val[0] : bounds.val[1];
} }
size_t readopt_select_lower(struct readopt_bounds bounds) size_t readarg_select_lower(struct readarg_bounds bounds)
{ {
return bounds.inf ? readopt_select_upper(bounds) : bounds.val[0] < bounds.val[1] ? bounds.val[0] return bounds.inf ? readarg_select_upper(bounds) : bounds.val[0] < bounds.val[1] ? bounds.val[0]
: bounds.val[1]; : bounds.val[1];
} }

View file

@ -1,14 +1,14 @@
#define READOPT_IMPLEMENTATION #define READARG_IMPLEMENTATION
#include "../readopt.h" #include "../readarg.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct readopt_opt opts[] = { struct readarg_opt opts[] = {
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("e", "x"), [READARG_FORM_SHORT] = READARG_STRINGS("e", "x"),
[READOPT_FORM_LONG] = READOPT_STRINGS("expr", "expression"), [READARG_FORM_LONG] = READARG_STRINGS("expr", "expression"),
}, },
.cont = { .cont = {
.req = 1, .req = 1,
@ -20,8 +20,8 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("c"), [READARG_FORM_SHORT] = READARG_STRINGS("c"),
[READOPT_FORM_LONG] = READOPT_STRINGS("config"), [READARG_FORM_LONG] = READARG_STRINGS("config"),
}, },
.cont = { .cont = {
.req = 1, .req = 1,
@ -35,8 +35,8 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("i"), [READARG_FORM_SHORT] = READARG_STRINGS("i"),
[READOPT_FORM_LONG] = READOPT_STRINGS("uri"), [READARG_FORM_LONG] = READARG_STRINGS("uri"),
}, },
.cont = { .cont = {
.req = 1, .req = 1,
@ -45,8 +45,8 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("b"), [READARG_FORM_SHORT] = READARG_STRINGS("b"),
[READOPT_FORM_LONG] = READOPT_STRINGS("backup", "backup-file"), [READARG_FORM_LONG] = READARG_STRINGS("backup", "backup-file"),
}, },
.cont = { .cont = {
.req = 1, .req = 1,
@ -55,8 +55,8 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("v"), [READARG_FORM_SHORT] = READARG_STRINGS("v"),
[READOPT_FORM_LONG] = READOPT_STRINGS("verbose"), [READARG_FORM_LONG] = READARG_STRINGS("verbose"),
}, },
.cont.oper.bounds.val = { .cont.oper.bounds.val = {
3, 3,
@ -64,14 +64,14 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("s"), [READARG_FORM_SHORT] = READARG_STRINGS("s"),
[READOPT_FORM_LONG] = READOPT_STRINGS("sort"), [READARG_FORM_LONG] = READARG_STRINGS("sort"),
}, },
.cont.oper.bounds.inf = 1, .cont.oper.bounds.inf = 1,
}, },
{ {
.names = { .names = {
[READOPT_FORM_LONG] = READOPT_STRINGS("help"), [READARG_FORM_LONG] = READARG_STRINGS("help"),
}, },
.cont.oper.bounds.val = { .cont.oper.bounds.val = {
1, 1,
@ -79,8 +79,8 @@ int main(int argc, char **argv)
}, },
{ {
.names = { .names = {
[READOPT_FORM_SHORT] = READOPT_STRINGS("V"), [READARG_FORM_SHORT] = READARG_STRINGS("V"),
[READOPT_FORM_LONG] = READOPT_STRINGS("version"), [READARG_FORM_LONG] = READARG_STRINGS("version"),
}, },
.cont.oper.bounds.val = { .cont.oper.bounds.val = {
1, 1,
@ -89,7 +89,7 @@ int main(int argc, char **argv)
{0}, {0},
}; };
struct readopt_oper opers[] = { struct readarg_oper opers[] = {
{ {
.name = "pattern", .name = "pattern",
.bounds.inf = 1, .bounds.inf = 1,
@ -117,28 +117,28 @@ int main(int argc, char **argv)
}, },
}; };
struct readopt_parser rp; struct readarg_parser rp;
readopt_parser_init( readarg_parser_init(
&rp, &rp,
opts, opts,
opers, opers,
(struct readopt_view_strings){ (struct readarg_view_strings){
.strings = (const char **)argv + 1, .strings = (const char **)argv + 1,
.len = argc - 1}); .len = argc - 1});
while (readopt_parse(&rp)) while (readarg_parse(&rp))
; ;
fprintf(stderr, "error: %d\n", rp.error); fprintf(stderr, "error: %d\n", rp.error);
if (rp.error != READOPT_ERROR_SUCCESS) if (rp.error != READARG_ERROR_SUCCESS)
{ {
return 1; return 1;
} }
printf("opt:\n"); printf("opt:\n");
{ {
struct readopt_opt *curr = rp.opts; struct readarg_opt *curr = rp.opts;
for (size_t i = 0; readopt_validate_opt(curr + i); i++) for (size_t i = 0; readarg_validate_opt(curr + i); i++)
{ {
for (size_t j = 0; j < sizeof curr[i].names / sizeof *curr[i].names; j++) for (size_t j = 0; j < sizeof curr[i].names / sizeof *curr[i].names; j++)
{ {
@ -153,7 +153,7 @@ int main(int argc, char **argv)
printf("{ [%zu] ", curr[i].cont.oper.val.len); printf("{ [%zu] ", curr[i].cont.oper.val.len);
if (curr[i].cont.req) if (curr[i].cont.req)
{ {
struct readopt_view_strings val = curr[i].cont.oper.val; struct readarg_view_strings val = curr[i].cont.oper.val;
for (size_t j = 0; j < val.len; j++) for (size_t j = 0; j < val.len; j++)
{ {
printf("%s ", val.strings[j]); printf("%s ", val.strings[j]);
@ -165,8 +165,8 @@ int main(int argc, char **argv)
printf("oper:\n"); printf("oper:\n");
{ {
struct readopt_oper *curr = rp.opers; struct readarg_oper *curr = rp.opers;
for (size_t i = 0; readopt_validate_oper(curr + i); i++) for (size_t i = 0; readarg_validate_oper(curr + i); i++)
{ {
printf("%s { [%zu] ", curr[i].name, curr[i].val.len); printf("%s { [%zu] ", curr[i].name, curr[i].val.len);
for (size_t j = 0; j < curr[i].val.len; j++) for (size_t j = 0; j < curr[i].val.len; j++)