diff options
Diffstat (limited to 'src/getlopt.c')
-rw-r--r-- | src/getlopt.c | 148 |
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 */ |