aboutsummaryrefslogtreecommitdiff
path: root/src/getlopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/getlopt.c')
-rw-r--r--src/getlopt.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/getlopt.c b/src/getlopt.c
new file mode 100644
index 0000000..2296886
--- /dev/null
+++ b/src/getlopt.c
@@ -0,0 +1,148 @@
+/*
+ getlopt: command line option/parameter parsing
+
+ copyright ?-2008 by the mpg123 project - free software under the terms of the LGPL 2.1
+ see COPYING and AUTHORS files in distribution or http://mpg123.org
+ initially written Oliver Fromme
+ old timestamp: Tue Apr 8 07:15:13 MET DST 1997
+*/
+
+#include <stdio.h>
+#include "config.h"
+#include "getlopt.h"
+#include "compat.h"
+#include "debug.h"
+
+int loptind = 1; /* index in argv[] */
+int loptchr = 0; /* index in argv[loptind] */
+char *loptarg; /* points to argument if present, else to option */
+
+topt *findopt (int islong, char *opt, topt *opts)
+{
+ if (!opts)
+ return (0);
+ while (opts->lname) {
+ if (islong) {
+ if (!strcmp(opts->lname, opt))
+ return (opts);
+ }
+ else
+ if (opts->sname == *opt)
+ return (opts);
+ opts++;
+ }
+ return (0);
+}
+
+int performoption (int argc, char *argv[], topt *opt)
+{
+ int result = GLO_CONTINUE;
+ /* this really is not supposed to happen, so the exit may be justified to create asap ficing pressure */
+ #define prog_error() \
+ { \
+ fprintf(stderr, __FILE__ ":%i Option without type flag! This is a programming error! Developer: fix this ASAP to regain your honor.\n", __LINE__); \
+ exit(1); \
+ }
+
+ if (!(opt->flags & GLO_ARG)) { /* doesn't take argument */
+ if (opt->var) {
+ if (opt->flags & GLO_CHAR) /* var is *char */
+ {
+ debug1("char at %p", opt->var);
+ *((char *) opt->var) = (char) opt->value;\
+ }
+ else if(opt->flags & GLO_LONG)
+ {
+ debug1("long at %p", opt->var);
+ *( (long *) opt->var ) = opt->value;
+ }
+ else if(opt->flags & GLO_INT)
+ {
+ debug1("int at %p", opt->var);
+ *( (int *) opt->var ) = (int) opt->value;
+ }
+ /* GLO_DOUBLE is not supported here */
+ else prog_error();
+
+ debug("casting assignment done");
+ }
+ else
+ result = opt->value ? opt->value : opt->sname;
+ }
+ else { /* requires argument */
+ if (loptind >= argc)
+ return (GLO_NOARG);
+ loptarg = argv[loptind++]+loptchr;
+ loptchr = 0;
+ if (opt->var) {
+ if (opt->flags & GLO_CHAR) /* var is *char */
+ *((char **) opt->var) = strdup(loptarg); /* valgrind claims lost memory here */
+ else if(opt->flags & GLO_LONG)
+ *((long *) opt->var) = atol(loptarg);
+ else if(opt->flags & GLO_INT)
+ *((int *) opt->var) = atoi(loptarg);
+ else if(opt->flags & GLO_DOUBLE)
+ *((double *) opt->var) = atof(loptarg);
+ else prog_error();
+ }
+ else
+ result = opt->value ? opt->value : opt->sname;
+ }
+ if (opt->func)
+ opt->func(loptarg);
+ return (result);
+}
+
+int getsingleopt (int argc, char *argv[], topt *opts)
+{
+ char *thisopt;
+ topt *opt;
+ static char shortopt[2] = {0, 0};
+
+ if (loptind >= argc)
+ return (GLO_END);
+ thisopt = argv[loptind];
+ debug1("getsingleopt: %s", thisopt);
+ if (!loptchr) { /* start new option string */
+ if (thisopt[0] != '-' || !thisopt[1]) /* no more options */
+ return (GLO_END);
+ if (thisopt[1] == '-') { /* "--" */
+ if (thisopt[2]) { /* long option */
+ loptarg = thisopt+2;
+ loptind++;
+ if (!(opt = findopt(1, thisopt+2, opts)))
+ return (GLO_UNKNOWN);
+ else
+ return (performoption(argc, argv, opt));
+ }
+ else { /* "--" == end of options */
+ loptind++;
+ return (GLO_END);
+ }
+ }
+ else /* start short option(s) */
+ loptchr = 1;
+ }
+ shortopt[0] = thisopt[loptchr];
+ loptarg = shortopt;
+ opt = findopt(0, thisopt+(loptchr++), opts);
+ if (!thisopt[loptchr]) {
+ loptind++;
+ loptchr = 0;
+ }
+ if (!opt)
+ return (GLO_UNKNOWN);
+ else
+ return (performoption(argc, argv, opt));
+}
+
+int getlopt (int argc, char *argv[], topt *opts)
+{
+
+ int result;
+
+ while ((result = getsingleopt(argc, argv, opts)) == GLO_CONTINUE);
+ return (result);
+}
+
+/* EOF */