Blame src/driver/mdso_driver_ctx.c

cde03b
/****************************************************************/
cde03b
/*  mdso: midipix dso scavenger                                 */
cde03b
/*  Copyright (C) 2015  Z. Gilboa                               */
cde03b
/*  Released under GPLv2 and GPLv3; see COPYING.MDSO.           */
cde03b
/****************************************************************/
cde03b
cde03b
#include <stdint.h>
cde03b
#include <unistd.h>
cde03b
#include <fcntl.h>
cde03b
cde03b
#define ARGV_DRIVER
cde03b
cde03b
#include <mdso/mdso.h>
cde03b
#include "mdso_driver_impl.h"
cde03b
#include "argv/argv.h"
cde03b
cde03b
extern const struct argv_option mdso_default_options[];
cde03b
cde03b
struct mdso_driver_ctx_alloc {
cde03b
	struct argv_meta *		meta;
cde03b
	struct mdso_driver_ctx_impl	ctx;
cde03b
	uint64_t			guard;
cde03b
	const char *			units[];
cde03b
};
cde03b
cde03b
static uint32_t mdso_argv_flags(uint32_t flags)
cde03b
{
cde03b
	uint32_t ret = 0;
cde03b
cde03b
	if (flags & MDSO_DRIVER_VERBOSITY_NONE)
cde03b
		ret |= ARGV_VERBOSITY_NONE;
cde03b
cde03b
	if (flags & MDSO_DRIVER_VERBOSITY_ERRORS)
cde03b
		ret |= ARGV_VERBOSITY_ERRORS;
cde03b
cde03b
	if (flags & MDSO_DRIVER_VERBOSITY_STATUS)
cde03b
		ret |= ARGV_VERBOSITY_STATUS;
cde03b
cde03b
	return ret;
cde03b
}
cde03b
cde03b
static int mdso_driver_usage(
cde03b
	const char *			program,
cde03b
	const char *			arg,
cde03b
	const struct argv_option *	options,
cde03b
	struct argv_meta *		meta)
cde03b
{
cde03b
	char header[512];
cde03b
cde03b
	snprintf(header,sizeof(header),
cde03b
		"Usage: %s [options] <file>...\n" "Options:\n",
cde03b
		program);
cde03b
cde03b
	argv_usage(stdout,header,options,arg);
cde03b
	argv_free(meta);
cde03b
cde03b
	return MDSO_USAGE;
cde03b
}
cde03b
cde03b
static struct mdso_driver_ctx_impl * mdso_driver_ctx_alloc(struct argv_meta * meta, size_t nunits)
cde03b
{
cde03b
	struct mdso_driver_ctx_alloc *	ictx;
cde03b
	size_t				size;
cde03b
	struct argv_entry *		entry;
cde03b
	const char **			units;
cde03b
cde03b
	size =  sizeof(struct mdso_driver_ctx_alloc);
cde03b
	size += (nunits+1)*sizeof(const char *);
cde03b
cde03b
	if (!(ictx = calloc(size,1)))
cde03b
		return 0;
cde03b
cde03b
	for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
cde03b
		if (!entry->fopt)
cde03b
			*units++ = entry->arg;
cde03b
cde03b
	ictx->ctx.ctx.units = ictx->units;
cde03b
	return &ictx->ctx;
cde03b
}
cde03b
cde03b
int mdso_get_driver_ctx_fail(struct argv_meta * meta)
cde03b
{
cde03b
	argv_free(meta);
cde03b
	return -1;
cde03b
}
cde03b
cde03b
int mdso_get_driver_ctx(
cde03b
	const char **		argv,
cde03b
	const char **		envp,
cde03b
	uint32_t		flags,
cde03b
	struct mdso_driver_ctx ** pctx)
cde03b
{
cde03b
	struct mdso_driver_ctx_impl *	ctx;
cde03b
	struct mdso_common_ctx		cctx;
cde03b
	const struct argv_option *	options;
cde03b
	struct argv_meta *		meta;
cde03b
	struct argv_entry *		entry;
cde03b
	size_t				nunits;
cde03b
	const char *			program;
cde03b
cde03b
	options = mdso_default_options;
cde03b
cde03b
	if (!(meta = argv_get(argv,options,mdso_argv_flags(flags))))
cde03b
		return -1;
cde03b
cde03b
	nunits	= 0;
cde03b
	program = argv_program_name(argv[0]);
cde03b
	memset(&cctx,0,sizeof(cctx));
cde03b
cde03b
	if (!argv[1] && (flags & MDSO_DRIVER_VERBOSITY_USAGE))
cde03b
		return mdso_driver_usage(program,0,options,meta);
cde03b
cde03b
	/* get options, count units */
cde03b
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
cde03b
		if (entry->fopt) {
cde03b
			switch (entry->tag) {
cde03b
				case TAG_HELP:
cde03b
					if (flags & MDSO_DRIVER_VERBOSITY_USAGE)
cde03b
						return mdso_driver_usage(program,entry->arg,options,meta);
cde03b
cde03b
				case TAG_VERSION:
cde03b
					cctx.drvflags |= MDSO_DRIVER_VERSION;
cde03b
					break;
cde03b
			}
cde03b
		} else
cde03b
			nunits++;
cde03b
	}
cde03b
cde03b
	if (!(ctx = mdso_driver_ctx_alloc(meta,nunits)))
cde03b
		return mdso_get_driver_ctx_fail(meta);
cde03b
cde03b
	ctx->ctx.program	= program;
cde03b
	ctx->ctx.cctx		= &ctx->cctx;
cde03b
cde03b
	memcpy(&ctx->cctx,&cctx,sizeof(cctx));
cde03b
	*pctx = &ctx->ctx;
cde03b
	return MDSO_OK;
cde03b
}
cde03b
cde03b
int mdso_create_driver_ctx(
cde03b
	const struct mdso_common_ctx *	cctx,
cde03b
	struct mdso_driver_ctx **	pctx)
cde03b
{
cde03b
	struct argv_meta *		meta;
cde03b
	struct mdso_driver_ctx_impl *	ctx;
cde03b
	const char *			argv[] = {"mdso_driver",0};
cde03b
cde03b
	if (!(meta = argv_get(argv,mdso_default_options,0)))
cde03b
		return -1;
cde03b
cde03b
	if (!(ctx = mdso_driver_ctx_alloc(meta,0)))
cde03b
		return mdso_get_driver_ctx_fail(0);
cde03b
cde03b
	ctx->ctx.cctx = &ctx->cctx;
cde03b
	memcpy(&ctx->cctx,cctx,sizeof(*cctx));
cde03b
	*pctx = &ctx->ctx;
cde03b
	return MDSO_OK;
cde03b
}
cde03b
cde03b
static void mdso_free_driver_ctx_impl(struct mdso_driver_ctx_alloc * ictx)
cde03b
{
cde03b
	argv_free(ictx->meta);
cde03b
	free(ictx);
cde03b
}
cde03b
cde03b
void mdso_free_driver_ctx(struct mdso_driver_ctx * ctx)
cde03b
{
cde03b
	struct mdso_driver_ctx_alloc *	ictx;
cde03b
	uintptr_t			addr;
cde03b
cde03b
	if (ctx) {
cde03b
		addr = (uintptr_t)ctx - offsetof(struct mdso_driver_ctx_alloc,ctx);
cde03b
		addr = addr - offsetof(struct mdso_driver_ctx_impl,ctx);
cde03b
		ictx = (struct mdso_driver_ctx_alloc *)addr;
cde03b
		mdso_free_driver_ctx_impl(ictx);
cde03b
	}
cde03b
}