Blame src/driver/ntux_driver_ctx.c

26e14f
/***********************************************************/
26e14f
/*  ntux: native translation und extension                 */
db57dd
/*  Copyright (C) 2016--2018  Z. Gilboa                    */
26e14f
/*  Released under GPLv2 and GPLv3; see COPYING.NTUX.      */
26e14f
/***********************************************************/
26e14f
26e14f
#include <ntapi/ntapi.h>
26e14f
#include <psxscl/psxscl.h>
26e14f
#include <stdint.h>
26e14f
26e14f
#include <ntux/ntux.h>
26e14f
#include "ntux_init_impl.h"
26e14f
#include "ntux_nolibc_impl.h"
26e14f
26e14f
#define ARGV_DRIVER
26e14f
26e14f
#include "ntux_version.h"
26e14f
#include "ntux_driver_impl.h"
26e14f
#include "argv/argv.h"
26e14f
26e14f
/* framework integration */
26e14f
#include <psxtypes/section/midipix.h>
26e14f
26e14f
__attr_section_decl__(".midipix")
26e14f
static const nt_tty_affiliation tty_affiliation
26e14f
	__attr_section__(".midipix")
26e14f
	= NT_TTY_AFFILIATION_DEFAULT;
26e14f
26e14f
/* ntapi accessor table */
26e14f
const ntapi_vtbl * ntux_ntapi;
26e14f
26e14f
/* package info */
26e14f
static const struct ntux_source_version ntux_src_version = {
26e14f
	NTUX_TAG_VER_MAJOR,
26e14f
	NTUX_TAG_VER_MINOR,
26e14f
	NTUX_TAG_VER_PATCH,
26e14f
	NTUX_GIT_VERSION
26e14f
};
26e14f
26e14f
struct ntux_driver_ctx_alloc {
26e14f
	struct argv_meta *		meta;
26e14f
	struct ntux_driver_ctx_impl	ctx;
26e14f
	uint64_t			guard;
26e14f
	const char *			units[];
26e14f
};
26e14f
26e14f
static uint32_t ntux_argv_flags(uint32_t flags)
26e14f
{
26e14f
	uint32_t ret = 0;
26e14f
26e14f
	if (flags & NTUX_DRIVER_VERBOSITY_NONE)
26e14f
		ret |= ARGV_VERBOSITY_NONE;
26e14f
26e14f
	if (flags & NTUX_DRIVER_VERBOSITY_ERRORS)
26e14f
		ret |= ARGV_VERBOSITY_ERRORS;
26e14f
26e14f
	if (flags & NTUX_DRIVER_VERBOSITY_STATUS)
26e14f
		ret |= ARGV_VERBOSITY_STATUS;
26e14f
26e14f
	return ret;
26e14f
}
26e14f
26e14f
static int ntux_driver_usage(
26e14f
	const char *			program,
26e14f
	const char *			arg,
2404cd
	const struct argv_option **	optv,
26e14f
	struct argv_meta *		meta)
26e14f
{
26e14f
	char header[512];
26e14f
26e14f
	snprintf(header,sizeof(header),
6a7c02
		"Usage: %s [options] ...\n"
6a7c02
		"Usage: %s [options] --cmd=<command> <arg> <arg> ...\n" "Options:\n",
6a7c02
		program,program);
26e14f
2404cd
	argv_usage(stdout,header,optv,arg);
26e14f
	argv_free(meta);
26e14f
26e14f
	return NTUX_USAGE;
26e14f
}
26e14f
26e14f
static struct ntux_driver_ctx_impl * ntux_driver_ctx_alloc(
26e14f
	struct argv_meta *		meta,
26e14f
	const struct ntux_common_ctx *	cctx,
26e14f
	size_t				nunits)
26e14f
{
26e14f
	struct ntux_driver_ctx_alloc *	ictx;
26e14f
	size_t				size;
26e14f
	struct argv_entry *		entry;
26e14f
	const char **			units;
26e14f
	int				elements;
26e14f
26e14f
	(void)tty_affiliation;
26e14f
26e14f
	size =  sizeof(struct ntux_driver_ctx_alloc);
26e14f
	size += (nunits+1)*sizeof(const char *);
26e14f
26e14f
	if (!(ictx = calloc(1,size)))
26e14f
		return 0;
26e14f
26e14f
	elements = sizeof(ictx->ctx.erribuf) / sizeof(*ictx->ctx.erribuf);
26e14f
26e14f
	ictx->ctx.errinfp  = &ictx->ctx.erriptr[0];
26e14f
	ictx->ctx.erricap  = &ictx->ctx.erriptr[--elements];
26e14f
26e14f
	if (cctx)
26e14f
		memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
26e14f
26e14f
	for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
26e14f
		if (!entry->fopt)
26e14f
			*units++ = entry->arg;
26e14f
26e14f
	ictx->meta = meta;
26e14f
	ictx->ctx.ctx.units = ictx->units;
26e14f
	ictx->ctx.ctx.errv  = ictx->ctx.errinfp;
26e14f
	return &ictx->ctx;
26e14f
}
26e14f
26e14f
static int ntux_get_driver_ctx_fail(struct argv_meta * meta)
26e14f
{
26e14f
	argv_free(meta);
26e14f
	return -1;
26e14f
}
26e14f
26e14f
int ntux_get_driver_ctx(
26e14f
	char **				argv,
26e14f
	char **				envp,
26e14f
	uint32_t			flags,
26e14f
	struct ntux_driver_ctx **	pctx)
26e14f
{
26e14f
	struct ntux_driver_ctx_impl *	ctx;
26e14f
	struct ntux_common_ctx		cctx;
2404cd
	const struct argv_option *	optv[NTUX_OPTV_ELEMENTS];
26e14f
	struct argv_meta *		meta;
26e14f
	struct argv_entry *		entry;
26e14f
	size_t				nunits;
26e14f
	const char *			program;
26e14f
26e14f
	(void)envp;
26e14f
2404cd
	argv_optv_init(ntux_default_options,optv);
26e14f
26e14f
	if (ntux_init())
26e14f
		return -1;
26e14f
2404cd
	if (!(meta = argv_get(argv,optv,ntux_argv_flags(flags))))
26e14f
		return -1;
26e14f
26e14f
	nunits	= 0;
26e14f
	program = argv_program_name(argv[0]);
26e14f
	memset(&cctx,0,sizeof(cctx));
26e14f
	cctx.drvflags = flags;
26e14f
26e14f
	if (!argv[1] && (flags & NTUX_DRIVER_VERBOSITY_USAGE))
2404cd
		return ntux_driver_usage(program,0,optv,meta);
26e14f
26e14f
	/* get options, count units */
26e14f
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
26e14f
		if (entry->fopt) {
26e14f
			switch (entry->tag) {
26e14f
				case TAG_HELP:
26e14f
					if (flags & NTUX_DRIVER_VERBOSITY_USAGE)
2404cd
						return ntux_driver_usage(program,entry->arg,optv,meta);
26e14f
26e14f
				case TAG_VERSION:
26e14f
					cctx.drvflags |= NTUX_DRIVER_VERSION;
26e14f
					break;
6a7c02
6a7c02
				case TAG_CMD:
6a7c02
					if (!strcmp(entry->arg,"stat"))
6a7c02
						cctx.cmd = NTUX_CMD_STAT;
6a7c02
					break;
26e14f
			}
26e14f
		} else
26e14f
			nunits++;
26e14f
	}
26e14f
c59ae6
	if (nunits && !cctx.cmd)
c59ae6
		return ntux_driver_usage(program,0,optv,meta);
c59ae6
26e14f
	if (!(ctx = ntux_driver_ctx_alloc(meta,&cctx,nunits)))
26e14f
		return ntux_get_driver_ctx_fail(meta);
26e14f
26e14f
	ctx->ctx.program	= program;
26e14f
	ctx->ctx.cctx		= &ctx->cctx;
26e14f
26e14f
	*pctx = &ctx->ctx;
26e14f
	return NTUX_OK;
26e14f
}
26e14f
26e14f
int ntux_create_driver_ctx(
26e14f
	const struct ntux_common_ctx *	cctx,
26e14f
	struct ntux_driver_ctx **	pctx)
26e14f
{
2404cd
	const struct argv_option *	optv[NTUX_OPTV_ELEMENTS];
26e14f
	struct argv_meta *		meta;
26e14f
	struct ntux_driver_ctx_impl *	ctx;
26e14f
	char *				argv[] = {"ntux_driver",0};
26e14f
26e14f
	if (ntux_init())
26e14f
		return -1;
26e14f
2404cd
	argv_optv_init(ntux_default_options,optv);
2404cd
2404cd
	if (!(meta = argv_get(argv,optv,0)))
26e14f
		return -1;
26e14f
26e14f
	if (!(ctx = ntux_driver_ctx_alloc(meta,cctx,0)))
26e14f
		return ntux_get_driver_ctx_fail(0);
26e14f
26e14f
	ctx->ctx.cctx = &ctx->cctx;
26e14f
	memcpy(&ctx->cctx,cctx,sizeof(*cctx));
26e14f
	*pctx = &ctx->ctx;
26e14f
	return NTUX_OK;
26e14f
}
26e14f
26e14f
static void ntux_free_driver_ctx_impl(struct ntux_driver_ctx_alloc * ictx)
26e14f
{
26e14f
	argv_free(ictx->meta);
26e14f
	free(ictx);
26e14f
}
26e14f
26e14f
void ntux_free_driver_ctx(struct ntux_driver_ctx * ctx)
26e14f
{
26e14f
	struct ntux_driver_ctx_alloc *	ictx;
26e14f
	uintptr_t			addr;
26e14f
26e14f
	if (ctx) {
26e14f
		addr = (uintptr_t)ctx - offsetof(struct ntux_driver_ctx_impl,ctx);
26e14f
		addr = addr - offsetof(struct ntux_driver_ctx_alloc,ctx);
26e14f
		ictx = (struct ntux_driver_ctx_alloc *)addr;
26e14f
		ntux_free_driver_ctx_impl(ictx);
26e14f
	}
26e14f
}
26e14f
26e14f
const struct ntux_source_version * ntux_source_version(void)
26e14f
{
26e14f
	return &ntux_src_version;
26e14f
}