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