2021-02-08 16:07:25 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#define READOPT_ALLOC_STRINGS(...) ((char *[]){__VA_ARGS__, NULL})
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
enum readopt_error
|
|
|
|
{
|
|
|
|
READOPT_ERROR_SUCCESS,
|
|
|
|
READOPT_ERROR_NOVAL,
|
|
|
|
READOPT_ERROR_NOTREQ,
|
|
|
|
READOPT_ERROR_NOTOPT,
|
|
|
|
READOPT_ERROR_RANGEOPT,
|
|
|
|
READOPT_ERROR_RANGEOPER
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
enum readopt_form
|
|
|
|
{
|
|
|
|
READOPT_FORM_SHORT,
|
|
|
|
READOPT_FORM_LONG
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
enum readopt_format
|
|
|
|
{
|
|
|
|
READOPT_FORMAT_PLAIN,
|
|
|
|
READOPT_FORMAT_MDOC,
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct readopt_view_strings
|
|
|
|
{
|
|
|
|
const char **strings;
|
|
|
|
size_t len;
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct readopt_bounds
|
|
|
|
{
|
|
|
|
/* The upper value will be ignored if inf is non-zero. */
|
|
|
|
size_t val[2];
|
|
|
|
int inf;
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct readopt_oper
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
struct readopt_bounds bounds;
|
|
|
|
struct readopt_view_strings val;
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct readopt_opt
|
|
|
|
{
|
|
|
|
/* Two null-terminated arrays of either long or short option names. */
|
|
|
|
char **names[2];
|
2021-02-08 16:07:25 +00:00
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
int req;
|
2021-02-08 16:07:25 +00:00
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
/* oper.name is the name of the value itself (not the option). */
|
|
|
|
struct readopt_oper oper;
|
|
|
|
} cont;
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
struct readopt_parser
|
|
|
|
{
|
|
|
|
struct readopt_opt *opts;
|
|
|
|
struct readopt_oper *opers;
|
|
|
|
struct readopt_view_strings args;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int pending;
|
|
|
|
const char *grppos;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
struct readopt_opt *opt;
|
|
|
|
/* Reference to the current argument being parsed. */
|
|
|
|
const char **arg;
|
|
|
|
/* Reference to the last element of the option/operand value view. */
|
|
|
|
const char **eoval;
|
|
|
|
/* Intermediate operands which have not yet been assigned. */
|
|
|
|
struct readopt_view_strings ioper;
|
|
|
|
} curr;
|
|
|
|
} state;
|
|
|
|
enum readopt_error error;
|
2021-02-08 16:07:25 +00:00
|
|
|
};
|
|
|
|
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Iteratively parse the arguments. */
|
2021-03-02 17:25:50 +00:00
|
|
|
int readopt_parse(struct readopt_parser *rp);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* args should always exclude the first element. */
|
2021-02-08 16:07:25 +00:00
|
|
|
void readopt_parser_init(struct readopt_parser *rp, struct readopt_opt *opts, struct readopt_oper *opers, struct readopt_view_strings args);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Check whether the argument is a valid option (can be used to check for the end of an array of options). */
|
2021-02-08 16:07:25 +00:00
|
|
|
int readopt_validate_opt(struct readopt_opt *opt);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Check whether the argument is a valid operand (can be used to check for the end of an array of operands). */
|
2021-02-08 16:07:25 +00:00
|
|
|
int readopt_validate_oper(struct readopt_oper *oper);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Check whether the operand's values are within the defined limits. */
|
2021-02-08 16:07:25 +00:00
|
|
|
int readopt_validate_within(struct readopt_oper *oper);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Get the upper limit. */
|
2021-02-08 16:07:25 +00:00
|
|
|
size_t readopt_select_upper(struct readopt_bounds bounds);
|
2022-09-25 10:08:56 +00:00
|
|
|
/* Get the lower limit. This does not always return the minimum. */
|
2021-02-08 16:07:25 +00:00
|
|
|
size_t readopt_select_lower(struct readopt_bounds bounds);
|