// util/optget.h, version 1.6.2 // optget source file from libutil // Copyright (C) 2020, Jakob Wakeling // MIT Licence #include "error.h" #include "optget.h" #include #include #include #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; }