Blame src/getlopt.c

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 */