summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c_lib/cgetopt.h130
1 files changed, 75 insertions, 55 deletions
diff --git a/c_lib/cgetopt.h b/c_lib/cgetopt.h
index 58917fc8..08613f62 100644
--- a/c_lib/cgetopt.h
+++ b/c_lib/cgetopt.h
@@ -1,5 +1,27 @@
-#ifndef CGETOPT_H
-#define CGETOPT_H
+// MIT License
+//
+// Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in 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:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// 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
+// AUTHORS OR COPYRIGHT HOLDERS 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 IN THE
+// SOFTWARE.
+
+#ifndef CGETOPT__H__
+#define CGETOPT__H__
#include <string.h>
@@ -25,8 +47,7 @@ typedef struct {
static const c_getopt_t c_getopt_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 c_getopt_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)
@@ -34,87 +55,86 @@ static void c_getopt_permute(char *argv[], int j, int n) /* move argv[j] over n
argv[j - k] = p;
}
-/**
- * Parse command-line options and arguments
- *
- * This fuction has a similar interface to GNU's getopt_long(). Each call
- * parses one option and returns the option name. s->arg points to the option
- * argument if present. The function returns -1 when all command-line arguments
- * are parsed. In this case, s->ind is the index of the first non-option
- * argument.
- *
- * @param s status; shall be initialized to c_getopt_init on the 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 ostr option string
- * @param longopts long options
- *
- * @return ASCII for a short option; c_longopt_t::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 *s, int argc, char *argv[], int permute, const char *ostr, const c_longopt_t *longopts)
-{
+
+// Parse command-line options and arguments
+//
+// This fuction has a similar interface to GNU's getopt_long(). Each call
+// parses one option and returns the option name. s->arg points to the option
+// argument if present. The function returns -1 when all command-line arguments
+// are parsed. In this case, s->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 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
+//
+// @return ASCII for a short option; c_longopt_t::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;
if (permute) {
- while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0'))
- ++s->i, ++s->n_args;
+ while (st->i < argc && (argv[st->i][0] != '-' || argv[st->i][1] == '\0'))
+ ++st->i, ++st->n_args;
}
- s->arg = 0, s->longidx = -1, i0 = s->i;
- if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') {
- s->ind = s->i - s->n_args;
+ 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;
return -1;
}
- if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */
- if (argv[s->i][2] == '\0') { /* a bare "--" */
- c_getopt_permute(argv, s->i, s->n_args);
- ++s->i, s->ind = s->i - s->n_args;
+ 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;
return -1;
}
- s->opt = 0, opt = '?', s->pos = -1;
+ st->opt = 0, opt = '?', st->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[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */
+ for (j = 2; argv[st->i][j] != '\0' && argv[st->i][j] != '='; ++j) {} /* find the end of the option name */
for (k = 0; longopts[k].name != 0; ++k)
- if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) {
+ if (strncmp(&argv[st->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) {
- s->opt = opt = o->val, s->longidx = o - longopts;
- if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1];
- if (o->has_arg == 1 && argv[s->i][j] == '\0') {
- if (s->i < argc - 1) s->arg = argv[++s->i];
+ 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 */
}
}
}
} else { /* a short option */
const char *p;
- if (s->pos == 0) s->pos = 1;
- opt = s->opt = argv[s->i][s->pos++];
- p = strchr((char*)ostr, opt);
+ if (st->pos == 0) st->pos = 1;
+ opt = st->opt = argv[st->i][st->pos++];
+ p = strchr((char*)optstr, opt);
if (p == 0) {
opt = '?'; /* unknown option */
} else if (p[1] == ':') {
- if (argv[s->i][s->pos] == 0) {
- if (s->i < argc - 1) s->arg = argv[++s->i];
+ if (argv[st->i][st->pos] == 0) {
+ if (st->i < argc - 1) st->arg = argv[++st->i];
else opt = ':'; /* missing option argument */
- } else s->arg = &argv[s->i][s->pos];
- s->pos = -1;
+ } else st->arg = &argv[st->i][st->pos];
+ st->pos = -1;
}
}
- if (s->pos < 0 || argv[s->i][s->pos] == 0) {
- ++s->i, s->pos = 0;
- if (s->n_args > 0) /* permute */
- for (j = i0; j < s->i; ++j)
- c_getopt_permute(argv, j, s->n_args);
+ 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);
}
- s->ind = s->i - s->n_args;
+ st->ind = st->i - st->n_args;
return opt;
}