Blame src/driver/amgc_driver_ctx.c

383aa6
/**********************************************************/
383aa6
/*  apimagic: cparser-based API normalization utility     */
383aa6
/*  Copyright (C) 2015--2016  Z. Gilboa                   */
383aa6
/*  Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
383aa6
/**********************************************************/
383aa6
383aa6
#include <stdint.h>
383aa6
#include <unistd.h>
383aa6
#include <fcntl.h>
383aa6
383aa6
#define ARGV_DRIVER
383aa6
383aa6
#include <apimagic/apimagic.h>
383aa6
#include "apimagic_driver_impl.h"
383aa6
#include "argv/argv.h"
383aa6
383aa6
extern const struct argv_option amgc_default_options[];
383aa6
383aa6
struct amgc_driver_ctx_alloc {
383aa6
	struct argv_meta *		meta;
383aa6
	struct amgc_driver_ctx_impl	ctx;
383aa6
	uint64_t			guard;
383aa6
	const char *			units[];
383aa6
};
383aa6
383aa6
static uint32_t amgc_argv_flags(uint32_t flags)
383aa6
{
383aa6
	uint32_t ret = 0;
383aa6
383aa6
	if (flags & AMGC_DRIVER_VERBOSITY_NONE)
383aa6
		ret |= ARGV_VERBOSITY_NONE;
383aa6
383aa6
	if (flags & AMGC_DRIVER_VERBOSITY_ERRORS)
383aa6
		ret |= ARGV_VERBOSITY_ERRORS;
383aa6
383aa6
	if (flags & AMGC_DRIVER_VERBOSITY_STATUS)
383aa6
		ret |= ARGV_VERBOSITY_STATUS;
383aa6
383aa6
	return ret;
383aa6
}
383aa6
383aa6
static int amgc_driver_usage(
383aa6
	const char *			program,
383aa6
	const char *			arg,
383aa6
	const struct argv_option *	options,
383aa6
	struct argv_meta *		meta)
383aa6
{
383aa6
	char header[512];
383aa6
383aa6
	snprintf(header,sizeof(header),
383aa6
		"Usage: %s [options] <file>...\n" "Options:\n",
383aa6
		program);
383aa6
383aa6
	argv_usage(stdout,header,options,arg);
383aa6
	argv_free(meta);
383aa6
383aa6
	return AMGC_USAGE;
383aa6
}
383aa6
383aa6
static struct amgc_driver_ctx_impl * amgc_driver_ctx_alloc(
383aa6
	struct argv_meta *		meta,
383aa6
	const struct amgc_common_ctx *	cctx,
383aa6
	size_t				nunits)
383aa6
{
383aa6
	struct amgc_driver_ctx_alloc *	ictx;
383aa6
	size_t				size;
383aa6
	struct argv_entry *		entry;
383aa6
	const char **			units;
383aa6
383aa6
	size =  sizeof(struct amgc_driver_ctx_alloc);
383aa6
	size += (nunits+1)*sizeof(const char *);
383aa6
383aa6
	if (!(ictx = calloc(size,1)))
383aa6
		return 0;
383aa6
383aa6
	if (cctx)
383aa6
		memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
383aa6
383aa6
	for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
383aa6
		if (!entry->fopt)
383aa6
			*units++ = entry->arg;
383aa6
383aa6
	ictx->meta = meta;
383aa6
	ictx->ctx.ctx.units = ictx->units;
383aa6
	return &ictx->ctx;
383aa6
}
383aa6
383aa6
static int amgc_get_driver_ctx_fail(struct argv_meta * meta)
383aa6
{
383aa6
	argv_free(meta);
383aa6
	return -1;
383aa6
}
383aa6
383aa6
int amgc_get_driver_ctx(
383aa6
	const char **			argv,
383aa6
	const char **			envp,
383aa6
	uint32_t			flags,
383aa6
	struct amgc_driver_ctx **	pctx)
383aa6
{
383aa6
	struct amgc_driver_ctx_impl *	ctx;
383aa6
	struct amgc_common_ctx		cctx;
383aa6
	const struct argv_option *	options;
383aa6
	struct argv_meta *		meta;
383aa6
	struct argv_entry *		entry;
383aa6
	size_t				nunits;
383aa6
	const char *			program;
383aa6
383aa6
	options = amgc_default_options;
383aa6
383aa6
	if (!(meta = argv_get(argv,options,amgc_argv_flags(flags))))
383aa6
		return -1;
383aa6
383aa6
	nunits	= 0;
383aa6
	program = argv_program_name(argv[0]);
383aa6
	memset(&cctx,0,sizeof(cctx));
383aa6
383aa6
	if (!argv[1] && (flags & AMGC_DRIVER_VERBOSITY_USAGE))
383aa6
		return amgc_driver_usage(program,0,options,meta);
383aa6
383aa6
	/* get options, count units */
383aa6
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
383aa6
		if (entry->fopt) {
383aa6
			switch (entry->tag) {
383aa6
				case TAG_HELP:
383aa6
					if (flags & AMGC_DRIVER_VERBOSITY_USAGE)
383aa6
						return amgc_driver_usage(program,entry->arg,options,meta);
383aa6
383aa6
				case TAG_VERSION:
383aa6
					cctx.drvflags |= AMGC_DRIVER_VERSION;
383aa6
					break;
383aa6
			}
383aa6
		} else
383aa6
			nunits++;
383aa6
	}
383aa6
383aa6
	if (!(ctx = amgc_driver_ctx_alloc(meta,&cctx,nunits)))
383aa6
		return amgc_get_driver_ctx_fail(meta);
383aa6
383aa6
	ctx->ctx.program	= program;
383aa6
	ctx->ctx.cctx		= &ctx->cctx;
383aa6
383aa6
	*pctx = &ctx->ctx;
383aa6
	return AMGC_OK;
383aa6
}
383aa6
383aa6
int amgc_create_driver_ctx(
383aa6
	const struct amgc_common_ctx *	cctx,
383aa6
	struct amgc_driver_ctx **	pctx)
383aa6
{
383aa6
	struct argv_meta *		meta;
383aa6
	struct amgc_driver_ctx_impl *	ctx;
383aa6
	const char *			argv[] = {"apimagic_driver",0};
383aa6
383aa6
	if (!(meta = argv_get(argv,amgc_default_options,0)))
383aa6
		return -1;
383aa6
383aa6
	if (!(ctx = amgc_driver_ctx_alloc(meta,cctx,0)))
383aa6
		return amgc_get_driver_ctx_fail(0);
383aa6
383aa6
	ctx->ctx.cctx = &ctx->cctx;
383aa6
	memcpy(&ctx->cctx,cctx,sizeof(*cctx));
383aa6
	*pctx = &ctx->ctx;
383aa6
	return AMGC_OK;
383aa6
}
383aa6
383aa6
static void amgc_free_driver_ctx_impl(struct amgc_driver_ctx_alloc * ictx)
383aa6
{
383aa6
	argv_free(ictx->meta);
383aa6
	free(ictx);
383aa6
}
383aa6
383aa6
void amgc_free_driver_ctx(struct amgc_driver_ctx * ctx)
383aa6
{
383aa6
	struct amgc_driver_ctx_alloc *	ictx;
383aa6
	uintptr_t			addr;
383aa6
383aa6
	if (ctx) {
383aa6
		addr = (uintptr_t)ctx - offsetof(struct amgc_driver_ctx_alloc,ctx);
383aa6
		addr = addr - offsetof(struct amgc_driver_ctx_impl,ctx);
383aa6
		ictx = (struct amgc_driver_ctx_alloc *)addr;
383aa6
		amgc_free_driver_ctx_impl(ictx);
383aa6
	}
383aa6
}