From e14d91b1f48c1144b4af099f505d4c75311d5bac Mon Sep 17 00:00:00 2001 From: Tyge Løvset <60263450+tylo-work@users.noreply.github.com> Date: Mon, 30 Mar 2020 20:16:36 +0200 Subject: Add files via upload --- c_lib/cgetopt.h | 155 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 73 deletions(-) diff --git a/c_lib/cgetopt.h b/c_lib/cgetopt.h index d6ed61d8..fb5e0847 100644 --- a/c_lib/cgetopt.h +++ b/c_lib/cgetopt.h @@ -24,30 +24,30 @@ #define CGETOPT__H__ #include +#include enum { - c_getopt_none = 0, - c_getopt_required = 1, - c_getopt_optional = 2 + copt_no_argument = 0, + copt_required_argument = 1, + copt_optional_argument = 2 }; typedef struct { int ind; /* equivalent to optind */ int opt; /* equivalent to optopt */ char *arg; /* equivalent to optarg */ int longidx; /* index of a long option; or -1 if short */ - /* private variables not intended for external uses */ - int i, pos, n_args; -} c_getopt_t; + int _i, _pos, _nargs; +} copt_t; -typedef struct { +struct copt_option { char *name; int has_arg; int val; -} c_longopt_t; +}; -static const c_getopt_t c_getopt_init = {1, 0, 0, -1, 1, 0, 0}; +static const copt_t copt_init = {1, 0, 0, -1, 1, 0, 0}; -static void _c_getopt_permute(char *argv[], int j, int n) { /* move argv[j] over n elements to the left */ +static void _copt_permute(char *argv[], int j, int n) { /* move argv[j] over n elements to the left */ int k; char *p = argv[j]; for (k = 0; k < n; ++k) @@ -64,105 +64,114 @@ static void _c_getopt_permute(char *argv[], int j, int n) { /* move argv[j] over // are parsed. In this case, st->ind is the index of the first non-option // argument. // -// @param st status; shall be initialized to c_getopt_init on the first call +// @param opt output; must be initialized to copt_init before first call // @param argc length of argv[] // @param argv list of command-line arguments; argv[0] is ignored -// @param permute non-zero to move options ahead of non-option arguments -// @param optstr option string -// @param longopts long options +// @param shortopts short options string +// @param longopts long options struct +// @param permute true: move options ahead of non-option arguments // // @return ASCII val for a short option; longopt.val for a long option; // -1 if argv[] is fully processed; '?' for an unknown option or // an ambiguous long option; ':' if an option argument is missing // -static int c_getopt(c_getopt_t *st, int argc, char *argv[], int permute, const char *optstr, const c_longopt_t *longopts) { - int opt = -1, i0, j; +static int copt_getopt(copt_t *opt, int argc, char *argv[], + const char *shortopts, const struct copt_option *longopts, + bool permute) { + int optc = -1, i0, j; if (permute) { - while (st->i < argc && (argv[st->i][0] != '-' || argv[st->i][1] == '\0')) - ++st->i, ++st->n_args; + while (opt->_i < argc && (argv[opt->_i][0] != '-' || argv[opt->_i][1] == '\0')) + ++opt->_i, ++opt->_nargs; } - st->arg = 0, st->longidx = -1, i0 = st->i; - if (st->i >= argc || argv[st->i][0] != '-' || argv[st->i][1] == '\0') { - st->ind = st->i - st->n_args; + opt->arg = 0, opt->longidx = -1, i0 = opt->_i; + if (opt->_i >= argc || argv[opt->_i][0] != '-' || argv[opt->_i][1] == '\0') { + opt->ind = opt->_i - opt->_nargs; return -1; } - if (argv[st->i][0] == '-' && argv[st->i][1] == '-') { /* "--" or a long option */ - if (argv[st->i][2] == '\0') { /* a bare "--" */ - _c_getopt_permute(argv, st->i, st->n_args); - ++st->i, st->ind = st->i - st->n_args; + if (argv[opt->_i][0] == '-' && argv[opt->_i][1] == '-') { /* "--" or a long option */ + if (argv[opt->_i][2] == '\0') { /* a bare "--" */ + _copt_permute(argv, opt->_i, opt->_nargs); + ++opt->_i, opt->ind = opt->_i - opt->_nargs; return -1; } - st->opt = 0, opt = '?', st->pos = -1; + opt->opt = 0, optc = '?', opt->_pos = -1; if (longopts) { /* parse long options */ int k, n_exact = 0, n_partial = 0; - const c_longopt_t *o = 0, *o_exact = 0, *o_partial = 0; - for (j = 2; argv[st->i][j] != '\0' && argv[st->i][j] != '='; ++j) {} /* find the end of the option name */ + const struct copt_option *o = 0, *o_exact = 0, *o_partial = 0; + for (j = 2; argv[opt->_i][j] != '\0' && argv[opt->_i][j] != '='; ++j) {} /* find the end of the option name */ for (k = 0; longopts[k].name != 0; ++k) - if (strncmp(&argv[st->i][2], longopts[k].name, j - 2) == 0) { + if (strncmp(&argv[opt->_i][2], longopts[k].name, j - 2) == 0) { if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k]; else ++n_partial, o_partial = &longopts[k]; } if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?'; o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0; if (o) { - st->opt = opt = o->val, st->longidx = o - longopts; - if (argv[st->i][j] == '=') st->arg = &argv[st->i][j + 1]; - if (o->has_arg == 1 && argv[st->i][j] == '\0') { - if (st->i < argc - 1) st->arg = argv[++st->i]; - else opt = ':'; /* missing option argument */ + opt->opt = optc = o->val, opt->longidx = o - longopts; + if (o->has_arg != copt_no_argument) { + if (argv[opt->_i][j] == '=') + opt->arg = &argv[opt->_i][j + 1]; + else if (argv[opt->_i][j] == '\0' && opt->_i < argc - 1 && argv[opt->_i + 1][0] != '-') + opt->arg = argv[++opt->_i]; + else if (o->has_arg == copt_required_argument) + optc = ':'; /* missing option argument */ } } } } else { /* a short option */ const char *p; - if (st->pos == 0) st->pos = 1; - opt = st->opt = argv[st->i][st->pos++]; - p = strchr((char*)optstr, opt); + if (opt->_pos == 0) opt->_pos = 1; + optc = opt->opt = argv[opt->_i][opt->_pos++]; + p = strchr((char *) shortopts, optc); if (p == 0) { - opt = '?'; /* unknown option */ + optc = '?'; /* unknown option */ } else if (p[1] == ':') { - if (argv[st->i][st->pos] == 0) { - if (st->i < argc - 1) st->arg = argv[++st->i]; - else opt = ':'; /* missing option argument */ - } else st->arg = &argv[st->i][st->pos]; - st->pos = -1; + if (argv[opt->_i][opt->_pos] != '\0') + opt->arg = &argv[opt->_i][opt->_pos]; + else if (opt->_i < argc - 1 && argv[opt->_i + 1][0] != '-') + opt->arg = argv[++opt->_i]; + else if (p[2] != ':') + optc = ':'; // missing option argument + opt->_pos = -1; } } - if (st->pos < 0 || argv[st->i][st->pos] == 0) { - ++st->i, st->pos = 0; - if (st->n_args > 0) /* permute */ - for (j = i0; j < st->i; ++j) - _c_getopt_permute(argv, j, st->n_args); + if (opt->_pos < 0 || argv[opt->_i][opt->_pos] == 0) { + ++opt->_i, opt->_pos = 0; + if (opt->_nargs > 0) /* permute */ + for (j = i0; j < opt->_i; ++j) + _copt_permute(argv, j, opt->_nargs); } - st->ind = st->i - st->n_args; - return opt; + opt->ind = opt->_i - opt->_nargs; + return optc; } -/* // demo: +/* // demo: int main(int argc, char *argv[]) { - static c_longopt_t longopts[] = { - { "foo", c_getopt_none, 301 }, - { "bar", c_getopt_required, 302 }, - { "opt", c_getopt_optional, 303 }, - { NULL, 0, 0 } - }; - c_getopt_t opt = c_getopt_init; - int i, c; - while ((c = c_getopt(&opt, argc, argv, 1, "xy:", longopts)) >= 0) { - if (c == 'x') printf("-x\n"); - else if (c == 'y') printf("-y %s\n", opt.arg); - else if (c == 301) printf("--foo\n"); - else if (c == 302) printf("--bar %s\n", opt.arg? opt.arg : "(null)"); - else if (c == 303) printf("--opt %s\n", opt.arg? opt.arg : "(null)"); - else if (c == '?') printf("unknown opt: -%c\n", opt.opt? opt.opt : ':'); - else if (c == ':') printf("missing arg: -%c\n", opt.opt? opt.opt : ':'); - } - printf("Non-option arguments:"); - for (i = opt.ind; i < argc; ++i) - printf(" %s", argv[i]); - putchar('\n'); - return 0; + static struct copt_option longopts[] = { + {"foo", copt_no_argument, 'f'}, + {"bar", copt_required_argument, 'b'}, + {"opt", copt_optional_argument, 'o'}, + {NULL} + }; + copt_t opt = copt_init; + int i = 0, c; + const char* optstr = "a:b::c"; + printf("optstr: %s\n", optstr); + while ((c = copt_getopt(&opt, argc, argv, optstr, longopts, true)) != -1) { + if (c == '?') + opt.opt != 0 ? printf("unknown option: %c\n", opt.opt) + : printf("unknown option: %s\n", argv[opt.ind - 1]); + else if (c == ':') + printf("missing argument for %s\n", argv[opt.ind - 1]); + else + printf("option: %c %s\n", c, opt.arg ? opt.arg : ""); + } + printf("\nNon-option arguments:"); + for (i = opt.ind; i < argc; ++i) + printf(" %s", argv[i]); + putchar('\n'); + return 0; } */ -- cgit v1.2.3