Author | Jamozed <[email protected]> |
Date | 2020-10-25 23:53:02 |
Commit | eb8174b7e31dbb41b6c37282370c2a0dcbe85f5e |
Parent | 7ea17c572021175c70357acae87dd86bd4b5cc55 |
optget: Add optget
Diffstat
A | src/lib/optget.c | | | 122 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/lib/optget.h | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 177 insertions, 0 deletions
diff --git a/src/lib/optget.c b/src/lib/optget.c new file mode 100644 index 0000000..da61ebd --- /dev/null +++ b/src/lib/optget.c @@ -0,0 +1,122 @@ +// optget.h, version 1.6.0 +// optget source file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "error.h" +#include "optget.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#define cur av[opt->ind] + +const struct opt OPTGET_INIT = { 1, 0, 1, 0, NULL, NULL, NULL, NULL }; + +static inline void permute(char **av, int i, int n); + +int optget(struct opt *opt, char *av[], int flags) { + if (flags & 1) { + for (; cur && (cur[0] != '-' || cur[1] == 0); ++opt->ind, ++opt->nop); + if (!cur) { opt->ind -= opt->nop; opt->nop = 0; return -1; } + } + else if (!cur || (cur[0] != '-' || cur[1] == 0)) { return -1; } + + int optind = opt->ind, optret; + + if (cur[1] == '-') { + if (cur[2] == 0) { if (opt->nop) { + permute(av, opt->ind++, opt->nop); + opt->ind -= opt->nop; opt->nop = 0; + } else { ++opt->ind; } return -1; + } + + int optend, lop; optret = '?'; opt->opt = 0; opt->lop = cur; + if (!opt->lops) { goto nol; } + for (optend = 2; cur[optend] != '=' && cur[optend] != 0; ++optend); + + for (lop = 0; opt->lops[lop].str; ++lop) { + if (strncmp(&cur[2], opt->lops[lop].str, (size_t)optend - 2) == 0) { + if (!opt->lops[lop].str[optend - 2]) { + optret = opt->opt = opt->lops[lop].val; break; + } + } + } + + if (opt->lops[lop].arg > ARG_NUL) { + if (cur[optend]) { opt->arg = &cur[optend + 1]; } + else if (av[opt->ind + 1]) { opt->arg = av[++opt->ind]; } + else { + if (opt->lops[lop].arg == ARG_REQ) { optret = ':'; } + opt->arg = NULL; + } + } + else { opt->arg = NULL; } + +nol: opt->pos = 0; + } + else { + optret = opt->opt = cur[opt->pos++]; opt->lop = NULL; + const char *optchr = strchr(opt->str, opt->opt); + + if (!optchr) { optret = '?'; } + else if (optchr[1] == ':') { + if (cur[opt->pos]) { opt->arg = &cur[opt->pos]; } + else if (av[opt->ind + 1]) { opt->arg = av[++opt->ind]; } + else { opt->arg = NULL; optret = ':'; } + opt->pos = 0; + } + else { opt->arg = NULL; } + } + + if (!opt->pos || !cur[opt->pos]) { + ++opt->ind; opt->pos = 1; + if (opt->nop) for (; optind < opt->ind; ++optind) { + permute(av, optind, opt->nop); + } + } + + if (optret == '?' && opt->str[0] != ':') { + if (opt->opt) { warn("%c: invalid option", opt->opt); } + else if (opt->lop) { warn("%s: invalid option", opt->lop); } + } + if (optret == ':' && opt->str[0] != ':') { + if (opt->opt) { warn("%c: option requires argument", opt->opt); } + else if (opt->lop) { warn("%s: option requires argument", opt->lop); } + } + + return optret; +} + +static inline void permute(char **av, int i, int n) { + char *a = av[i]; memmove(&av[i - n + 1], &av[i - n], n * sizeof (av)); + av[i - n] = a; return; +} diff --git a/src/lib/optget.h b/src/lib/optget.h new file mode 100644 index 0000000..f83d132 --- /dev/null +++ b/src/lib/optget.h @@ -0,0 +1,55 @@ +// optget.h, version 1.6.0 +// optget header file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OMKOV_LIB_OPTGET_H_W3LIZK1S +#define OMKOV_LIB_OPTGET_H_W3LIZK1S + +#define ARG_NUL 0 +#define ARG_REQ 1 +#define ARG_OPT 2 + +struct lop { + char *str; + int arg, val; +}; + +struct opt { + int ind, opt, pos, nop; + char *arg, *lop, *str; + struct lop *lops; +}; + +extern const struct opt OPTGET_INIT; + +extern int optget(struct opt *opt, char *av[], int flags); + +#endif // OMKOV_LIB_OPTGET_H_W3LIZK1S