Blame src/driver/slbt_driver_ctx.c

9ca8c4
/*******************************************************************/
9ca8c4
/*  slibtool: a skinny libtool implementation, written in C        */
9ca8c4
/*  Copyright (C) 2016  Z. Gilboa                                  */
9ca8c4
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
9ca8c4
/*******************************************************************/
9ca8c4
9ca8c4
#include <stdint.h>
9ca8c4
#include <unistd.h>
9ca8c4
#include <fcntl.h>
9ca8c4
9ca8c4
#define ARGV_DRIVER
9ca8c4
9ca8c4
#include <slibtool/slibtool.h>
9ca8c4
#include "slibtool_driver_impl.h"
9ca8c4
#include "argv/argv.h"
9ca8c4
9ca8c4
struct slbt_driver_ctx_alloc {
9ca8c4
	struct argv_meta *		meta;
9ca8c4
	struct slbt_driver_ctx_impl	ctx;
9ca8c4
	uint64_t			guard;
9ca8c4
	const char *			units[];
9ca8c4
};
9ca8c4
9ca8c4
static uint32_t slbt_argv_flags(uint32_t flags)
9ca8c4
{
9ca8c4
	uint32_t ret = 0;
9ca8c4
9ca8c4
	if (flags & SLBT_DRIVER_VERBOSITY_NONE)
9ca8c4
		ret |= ARGV_VERBOSITY_NONE;
9ca8c4
9ca8c4
	if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
9ca8c4
		ret |= ARGV_VERBOSITY_ERRORS;
9ca8c4
9ca8c4
	if (flags & SLBT_DRIVER_VERBOSITY_STATUS)
9ca8c4
		ret |= ARGV_VERBOSITY_STATUS;
9ca8c4
9ca8c4
	return ret;
9ca8c4
}
9ca8c4
9ca8c4
static int slbt_driver_usage(
9ca8c4
	const char *			program,
9ca8c4
	const char *			arg,
9ca8c4
	const struct argv_option *	options,
9ca8c4
	struct argv_meta *		meta)
9ca8c4
{
9ca8c4
	char header[512];
9ca8c4
9ca8c4
	snprintf(header,sizeof(header),
9ca8c4
		"Usage: %s [options] <file>...\n" "Options:\n",
9ca8c4
		program);
9ca8c4
9ca8c4
	argv_usage(stdout,header,options,arg);
9ca8c4
	argv_free(meta);
9ca8c4
9ca8c4
	return SLBT_USAGE;
9ca8c4
}
9ca8c4
9ca8c4
static struct slbt_driver_ctx_impl * slbt_driver_ctx_alloc(
9ca8c4
	struct argv_meta *		meta,
9ca8c4
	const struct slbt_common_ctx *	cctx,
9ca8c4
	size_t				nunits)
9ca8c4
{
9ca8c4
	struct slbt_driver_ctx_alloc *	ictx;
9ca8c4
	size_t				size;
9ca8c4
	struct argv_entry *		entry;
9ca8c4
	const char **			units;
9ca8c4
9ca8c4
	size =  sizeof(struct slbt_driver_ctx_alloc);
9ca8c4
	size += (nunits+1)*sizeof(const char *);
9ca8c4
9ca8c4
	if (!(ictx = calloc(1,size)))
9ca8c4
		return 0;
9ca8c4
9ca8c4
	if (cctx)
9ca8c4
		memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
9ca8c4
9ca8c4
	for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
9ca8c4
		if (!entry->fopt)
9ca8c4
			*units++ = entry->arg;
9ca8c4
9ca8c4
	ictx->meta = meta;
9ca8c4
	ictx->ctx.ctx.units = ictx->units;
9ca8c4
	return &ictx->ctx;
9ca8c4
}
9ca8c4
9ca8c4
static int slbt_get_driver_ctx_fail(struct argv_meta * meta)
9ca8c4
{
9ca8c4
	argv_free(meta);
9ca8c4
	return -1;
9ca8c4
}
9ca8c4
9ca8c4
int slbt_get_driver_ctx(
9ca8c4
	char **				argv,
9ca8c4
	char **				envp,
9ca8c4
	uint32_t			flags,
9ca8c4
	struct slbt_driver_ctx **	pctx)
9ca8c4
{
9ca8c4
	struct slbt_driver_ctx_impl *	ctx;
9ca8c4
	struct slbt_common_ctx		cctx;
9ca8c4
	const struct argv_option *	options;
9ca8c4
	struct argv_meta *		meta;
9ca8c4
	struct argv_entry *		entry;
9ca8c4
	size_t				nunits;
9ca8c4
	const char *			program;
9ca8c4
9ca8c4
	options = slbt_default_options;
9ca8c4
9ca8c4
	if (!(meta = argv_get(argv,options,slbt_argv_flags(flags))))
9ca8c4
		return -1;
9ca8c4
9ca8c4
	nunits	= 0;
9ca8c4
	program = argv_program_name(argv[0]);
9ca8c4
	memset(&cctx,0,sizeof(cctx));
9ca8c4
9ca8c4
	if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
9ca8c4
		return slbt_driver_usage(program,0,options,meta);
9ca8c4
9ca8c4
	/* get options, count units */
9ca8c4
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
9ca8c4
		if (entry->fopt) {
9ca8c4
			switch (entry->tag) {
9ca8c4
				case TAG_HELP:
9ca8c4
					if (flags & SLBT_DRIVER_VERBOSITY_USAGE)
9ca8c4
						return slbt_driver_usage(program,entry->arg,options,meta);
9ca8c4
9ca8c4
				case TAG_VERSION:
9ca8c4
					cctx.drvflags |= SLBT_DRIVER_VERSION;
9ca8c4
					break;
9ca8c4
			}
9ca8c4
		} else
9ca8c4
			nunits++;
9ca8c4
	}
9ca8c4
9ca8c4
	if (!(ctx = slbt_driver_ctx_alloc(meta,&cctx,nunits)))
9ca8c4
		return slbt_get_driver_ctx_fail(meta);
9ca8c4
9ca8c4
	ctx->ctx.program	= program;
9ca8c4
	ctx->ctx.cctx		= &ctx->cctx;
9ca8c4
9ca8c4
	*pctx = &ctx->ctx;
9ca8c4
	return SLBT_OK;
9ca8c4
}
9ca8c4
9ca8c4
int slbt_create_driver_ctx(
9ca8c4
	const struct slbt_common_ctx *	cctx,
9ca8c4
	struct slbt_driver_ctx **	pctx)
9ca8c4
{
9ca8c4
	struct argv_meta *		meta;
9ca8c4
	struct slbt_driver_ctx_impl *	ctx;
9ca8c4
	char *				argv[] = {"slibtool_driver",0};
9ca8c4
9ca8c4
	if (!(meta = argv_get(argv,slbt_default_options,0)))
9ca8c4
		return -1;
9ca8c4
9ca8c4
	if (!(ctx = slbt_driver_ctx_alloc(meta,cctx,0)))
9ca8c4
		return slbt_get_driver_ctx_fail(0);
9ca8c4
9ca8c4
	ctx->ctx.cctx = &ctx->cctx;
9ca8c4
	memcpy(&ctx->cctx,cctx,sizeof(*cctx));
9ca8c4
	*pctx = &ctx->ctx;
9ca8c4
	return SLBT_OK;
9ca8c4
}
9ca8c4
9ca8c4
static void slbt_free_driver_ctx_impl(struct slbt_driver_ctx_alloc * ictx)
9ca8c4
{
9ca8c4
	argv_free(ictx->meta);
9ca8c4
	free(ictx);
9ca8c4
}
9ca8c4
9ca8c4
void slbt_free_driver_ctx(struct slbt_driver_ctx * ctx)
9ca8c4
{
9ca8c4
	struct slbt_driver_ctx_alloc *	ictx;
9ca8c4
	uintptr_t			addr;
9ca8c4
9ca8c4
	if (ctx) {
9ca8c4
		addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
9ca8c4
		addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
9ca8c4
		ictx = (struct slbt_driver_ctx_alloc *)addr;
9ca8c4
		slbt_free_driver_ctx_impl(ictx);
9ca8c4
	}
9ca8c4
}