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
f2e43d
#include <cparser/ast/type_t.h>
fd0662
#include <cparser/driver/c_driver.h>
1fd161
#include <cparser/driver/driver.h>
1fd161
#include <cparser/driver/driver_t.h>
43c8c9
#include <cparser/driver/target.h>
1fd161
#include <cparser/driver/tempfile.h>
1fd161
#include <cparser/firm/ast2firm.h>
1fd161
#include <cparser/firm/firm_opt.h>
1fd161
#include <cparser/parser/parser.h>
1fd161
#include <cparser/parser/preprocessor.h>
1fd161
383aa6
#define ARGV_DRIVER
383aa6
383aa6
#include <apimagic/apimagic.h>
f83623
#include "apimagic_version.h"
383aa6
#include "apimagic_driver_impl.h"
383aa6
#include "argv/argv.h"
383aa6
f83623
/* package info */
f83623
static const struct amgc_source_version amgc_src_version = {
f83623
	AMGC_TAG_VER_MAJOR,
f83623
	AMGC_TAG_VER_MINOR,
f83623
	AMGC_TAG_VER_PATCH,
f83623
	APIMAGIC_GIT_VERSION
f83623
};
f83623
383aa6
struct amgc_driver_ctx_alloc {
383aa6
	struct argv_meta *		meta;
6adb90
	struct amgc_action *		actions;
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
{
c805ee
	uint32_t ret = ARGV_CLONE_VECTOR;
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(
abf923
	int				fdout,
383aa6
	const char *			program,
383aa6
	const char *			arg,
a6ad51
	const struct argv_option **	optv,
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
abf923
	argv_usage(fdout,header,optv,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,
abf923
	const struct amgc_fd_ctx *	fdctx,
383aa6
	const struct amgc_common_ctx *	cctx,
6adb90
	size_t				nunits,
6adb90
	size_t				nactions)
383aa6
{
383aa6
	struct amgc_driver_ctx_alloc *	ictx;
6adb90
	struct amgc_action *		actions;
383aa6
	size_t				size;
383aa6
	struct argv_entry *		entry;
4d825e
	const char **			aunits;
5334b1
	int				elements;
383aa6
383aa6
	size =  sizeof(struct amgc_driver_ctx_alloc);
383aa6
	size += (nunits+1)*sizeof(const char *);
383aa6
890152
	if (!(ictx = calloc(1,size)))
383aa6
		return 0;
383aa6
6adb90
	if (!(actions = calloc(nactions+1,sizeof(*ictx->actions)))) {
6adb90
		free(ictx);
6adb90
		return 0;
6adb90
	}
6adb90
abf923
	memcpy(&ictx->ctx.fdctx,fdctx,sizeof(*fdctx));
abf923
	memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
383aa6
4d825e
	for (entry=meta->entries,aunits=ictx->units; entry->fopt || entry->arg; entry++)
383aa6
		if (!entry->fopt)
4d825e
			*aunits++ = entry->arg;
383aa6
5334b1
	elements = sizeof(ictx->ctx.erribuf) / sizeof(*ictx->ctx.erribuf);
5334b1
5334b1
	ictx->ctx.errinfp  = &ictx->ctx.erriptr[0];
5334b1
	ictx->ctx.erricap  = &ictx->ctx.erriptr[--elements];
5334b1
383aa6
	ictx->meta = meta;
389acb
	ictx->ctx.fdtmpin = -1;
6adb90
	ictx->actions = actions;
6adb90
	ictx->ctx.actions = actions;
383aa6
	ictx->ctx.ctx.units = ictx->units;
5334b1
	ictx->ctx.ctx.errv  = ictx->ctx.errinfp;
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
1fd161
static int amgc_init_cparser(void)
1fd161
{
1fd161
	init_temp_files();
1fd161
	init_default_driver();
1fd161
	init_driver();
1fd161
	init_preprocessor();
1fd161
	init_parser();
1fd161
	init_ast();
b8fd4d
	init_firm_opt();
b8fd4d
	init_firm_target();
1fd161
43c8c9
	target_setup();
43c8c9
1fd161
	return 0;
1fd161
}
1fd161
383aa6
int amgc_get_driver_ctx(
10a518
	char **				argv,
10a518
	char **				envp,
383aa6
	uint32_t			flags,
abf923
	const struct amgc_fd_ctx *	fdctx,
383aa6
	struct amgc_driver_ctx **	pctx)
383aa6
{
383aa6
	struct amgc_driver_ctx_impl *	ctx;
383aa6
	struct amgc_common_ctx		cctx;
a6ad51
	const struct argv_option *	optv[AMGC_OPTV_ELEMENTS];
383aa6
	struct argv_meta *		meta;
383aa6
	struct argv_entry *		entry;
383aa6
	size_t				nunits;
6adb90
	size_t				nactions;
383aa6
	const char *			program;
383aa6
3a51d2
	(void)envp;
3a51d2
abf923
	if (!fdctx) {
abf923
		fdctx = &(const struct amgc_fd_ctx) {
abf923
			.fdin  = STDIN_FILENO,
abf923
			.fdout = STDOUT_FILENO,
abf923
			.fderr = STDERR_FILENO,
abf923
			.fdlog = (-1),
abf923
			.fdcwd = AT_FDCWD,
abf923
			.fddst = AT_FDCWD,
abf923
		};
abf923
	}
abf923
a6ad51
	argv_optv_init(amgc_default_options,optv);
383aa6
9c9e94
	if (!(meta = argv_get(
9c9e94
			argv,optv,
9c9e94
			amgc_argv_flags(flags),
abf923
			fdctx->fderr)))
383aa6
		return -1;
383aa6
383aa6
	nunits	= 0;
6adb90
	nactions= 0;
383aa6
	program = argv_program_name(argv[0]);
383aa6
	memset(&cctx,0,sizeof(cctx));
d3730a
	cctx.drvflags = flags;
383aa6
383aa6
	if (!argv[1] && (flags & AMGC_DRIVER_VERBOSITY_USAGE))
abf923
		return amgc_driver_usage(
abf923
			fdctx->fderr,
abf923
			program,0,
abf923
			optv,meta);
383aa6
fd0662
	/* compiler defaults */
fd0662
	cctx.std = STANDARD_C99;
fd0662
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)
abf923
						return amgc_driver_usage(
abf923
							fdctx->fderr,
abf923
							program,entry->arg,
abf923
							optv,meta);
383aa6
383aa6
				case TAG_VERSION:
383aa6
					cctx.drvflags |= AMGC_DRIVER_VERSION;
383aa6
					break;
fd0662
fd0662
				case TAG_LANG_STD:
fd0662
					cctx.std = amgc_lang_std_from_string(entry->arg);
fd0662
					break;
6adb90
6adb90
				default:
6adb90
					nactions++;
6adb90
					break;
383aa6
			}
383aa6
		} else
383aa6
			nunits++;
383aa6
	}
383aa6
1fd161
	if (amgc_init_cparser())
1fd161
		return amgc_get_driver_ctx_fail(meta);
1fd161
abf923
	if (!(ctx = amgc_driver_ctx_alloc(meta,fdctx,&cctx,nunits,nactions)))
383aa6
		return amgc_get_driver_ctx_fail(meta);
383aa6
6adb90
	/* create action vector */
6adb90
	for (entry=meta->entries,nactions=0; entry->fopt || entry->arg; entry++)
6adb90
		if (entry->fopt)
6adb90
			switch (entry->tag) {
6adb90
				case TAG_PRINT_ENUMS:
6adb90
					ctx->actions[nactions].type = AMGC_ACTION_OUTPUT;
6adb90
					ctx->actions[nactions++].action = AMGC_OUTPUT_ENUM;
6adb90
					break;
2e879c
2e879c
				case TAG_LIST_ENUMS:
2e879c
					ctx->actions[nactions].type = AMGC_ACTION_OUTPUT;
2e879c
					ctx->actions[nactions++].action = AMGC_LIST_ENUM;
2e879c
					break;
f2e43d
f2e43d
				case TAG_PRINT_TYPEDEFS:
f2e43d
					ctx->actions[nactions].type = AMGC_ACTION_OUTPUT;
f2e43d
					ctx->actions[nactions].action = AMGC_OUTPUT_TYPEDEF;
f2e43d
f2e43d
					if (!strcmp("primary",entry->arg))
f2e43d
						ctx->actions[nactions++].subset = TYPE_ATOMIC;
f2e43d
					break;
0c91ec
0c91ec
				case TAG_PRINT_STRUCTS:
0c91ec
					ctx->actions[nactions].type = AMGC_ACTION_OUTPUT;
0c91ec
					ctx->actions[nactions++].action = AMGC_OUTPUT_STRUCT;
0c91ec
					break;
0c91ec
0c91ec
				case TAG_PRINT_UNIONS:
0c91ec
					ctx->actions[nactions].type = AMGC_ACTION_OUTPUT;
0c91ec
					ctx->actions[nactions++].action = AMGC_OUTPUT_UNION;
0c91ec
					break;
6adb90
			}
6adb90
383aa6
	ctx->ctx.program	= program;
383aa6
	ctx->ctx.cctx		= &ctx->cctx;
6adb90
	ctx->cctx.actions	= ctx->actions;
43c8c9
	ctx->cctx.ccenv		= &ctx->ccenv;
383aa6
383aa6
	*pctx = &ctx->ctx;
383aa6
	return AMGC_OK;
383aa6
}
383aa6
1fd161
static void amgc_exit_cparser(void)
1fd161
{
b8fd4d
	exit_firm_opt();
1fd161
	exit_ast2firm();
1fd161
	exit_ast();
1fd161
	exit_parser();
1fd161
	exit_preprocessor();
1fd161
	exit_driver();
1fd161
	exit_default_driver();
1fd161
	exit_temp_files();
1fd161
}
1fd161
383aa6
static void amgc_free_driver_ctx_impl(struct amgc_driver_ctx_alloc * ictx)
383aa6
{
383aa6
	argv_free(ictx->meta);
6adb90
	free(ictx->actions);
383aa6
	free(ictx);
1fd161
	amgc_exit_cparser();
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) {
1d72ca
		addr = (uintptr_t)ctx - offsetof(struct amgc_driver_ctx_impl,ctx);
1d72ca
		addr = addr - offsetof(struct amgc_driver_ctx_alloc,ctx);
383aa6
		ictx = (struct amgc_driver_ctx_alloc *)addr;
383aa6
		amgc_free_driver_ctx_impl(ictx);
383aa6
	}
383aa6
}
f83623
f83623
const struct amgc_source_version * amgc_source_version(void)
f83623
{
f83623
	return &amgc_src_version;
f83623
}
abf923
abf923
int amgc_get_driver_fdctx(
abf923
	const struct amgc_driver_ctx *	dctx,
abf923
	struct amgc_fd_ctx *		fdctx)
abf923
{
abf923
	struct amgc_driver_ctx_impl *	ictx;
abf923
abf923
	ictx = amgc_get_driver_ictx(dctx);
abf923
abf923
	fdctx->fdin  = ictx->fdctx.fdin;
abf923
	fdctx->fdout = ictx->fdctx.fdout;
abf923
	fdctx->fderr = ictx->fdctx.fderr;
abf923
	fdctx->fdlog = ictx->fdctx.fdlog;
abf923
	fdctx->fdcwd = ictx->fdctx.fdcwd;
abf923
	fdctx->fddst = ictx->fdctx.fddst;
abf923
abf923
	return 0;
abf923
}
abf923
abf923
int amgc_set_driver_fdctx(
abf923
	struct amgc_driver_ctx *	dctx,
abf923
	const struct amgc_fd_ctx *	fdctx)
abf923
{
abf923
	struct amgc_driver_ctx_impl *	ictx;
abf923
abf923
	ictx = amgc_get_driver_ictx(dctx);
abf923
abf923
	ictx->fdctx.fdin  = fdctx->fdin;
abf923
	ictx->fdctx.fdout = fdctx->fdout;
abf923
	ictx->fdctx.fderr = fdctx->fderr;
abf923
	ictx->fdctx.fdlog = fdctx->fdlog;
abf923
	ictx->fdctx.fdcwd = fdctx->fdcwd;
abf923
	ictx->fdctx.fddst = fdctx->fddst;
abf923
abf923
	return 0;
abf923
}