Blame src/driver/amgc_unit_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
0c8cc0
#include <stdio.h>
383aa6
#include <stdint.h>
383aa6
#include <stddef.h>
383aa6
#include <stdlib.h>
383aa6
#include <string.h>
389acb
#include <unistd.h>
389acb
#include <errno.h>
383aa6
#include <sys/mman.h>
383aa6
43c8c9
43c8c9
#include <cparser/driver/driver.h>
43c8c9
#include <cparser/driver/c_driver.h>
43c8c9
383aa6
#include <apimagic/apimagic.h>
383aa6
#include "apimagic_driver_impl.h"
4671ad
#include "apimagic_errinfo_impl.h"
383aa6
4671ad
static int amgc_free_unit_ctx_impl(struct amgc_unit_ctx_impl * ctx, int ret)
383aa6
{
383aa6
	if (ctx) {
7a622c
		if (ctx->entities)
7a622c
			amgc_free_unit_entities(ctx->entities);
7a622c
383aa6
		amgc_unmap_input(&ctx->map);
383aa6
		free(ctx);
383aa6
	}
383aa6
4671ad
	return ret;
383aa6
}
383aa6
389acb
static FILE * amgc_stdin_to_tmp(const struct amgc_driver_ctx * dctx)
389acb
{
389acb
	struct amgc_driver_ctx_impl *	ictx;
389acb
	uintptr_t			addr;
389acb
	int				fdtmp;
389acb
389acb
	FILE *	ftmp;
389acb
	char	buf[4096];
389acb
	ssize_t	nread;
389acb
	int	ret;
389acb
389acb
	addr = (uintptr_t)dctx - offsetof(struct amgc_driver_ctx_impl,ctx);
389acb
	ictx = (struct amgc_driver_ctx_impl *)addr;
389acb
389acb
	if (ictx->fdtmpin >= 0) {
389acb
		if ((fdtmp = dup(ictx->fdtmpin)) < 0)
389acb
			return 0;
389acb
389acb
		if (!(ftmp = fdopen(fdtmp,"r")))
389acb
			close(fdtmp);
389acb
389acb
		return ftmp;
389acb
	}
389acb
389acb
	if (!(ftmp = tmpfile()))
389acb
		return 0;
389acb
389acb
	if ((ictx->fdtmpin = dup(fileno(ftmp))) < 0) {
389acb
		fclose(ftmp);
389acb
		return 0;
389acb
	}
389acb
389acb
	nread = read(0,buf,sizeof(buf)-1);
389acb
389acb
	while (nread) {
389acb
		if (nread > 0) {
389acb
			buf[nread] = '\0';
389acb
			ret = fputs(buf,ftmp);
389acb
		} else
389acb
			ret = (errno == EINTR) ? 0 : -1;
389acb
389acb
		if (ret < 0) {
389acb
			fclose(ftmp);
389acb
			return 0;
389acb
		}
389acb
389acb
		nread = read(0,buf,sizeof(buf)-1);
389acb
	}
389acb
0c8cc0
	if (fflush(ftmp)) {
0c8cc0
		fclose(ftmp);
0c8cc0
		return 0;
0c8cc0
	}
0c8cc0
389acb
	return ftmp;
389acb
}
389acb
43c8c9
static bool amgc_cparser_no_op(
43c8c9
	compilation_env_t *	env,
43c8c9
	compilation_unit_t *	unit)
43c8c9
{
3a51d2
	(void)env;
3a51d2
	(void)unit;
43c8c9
	return true;
43c8c9
}
43c8c9
43c8c9
static void amgc_init_cparser_unit(void)
43c8c9
{
43c8c9
	set_default_handlers();
43c8c9
43c8c9
	/* parse only */
43c8c9
	set_unit_handler(COMPILATION_UNIT_AST,
43c8c9
			build_firm_ir,true);
43c8c9
43c8c9
	/* assign no-op handler */
43c8c9
	set_unit_handler(COMPILATION_UNIT_PREPROCESSED_ASSEMBLER,
43c8c9
			amgc_cparser_no_op,true);
43c8c9
43c8c9
	set_unit_handler(COMPILATION_UNIT_OBJECT,
43c8c9
			amgc_cparser_no_op,true);
43c8c9
}
43c8c9
383aa6
int amgc_get_unit_ctx(
383aa6
	const struct amgc_driver_ctx *	dctx,
383aa6
	const char *			path,
383aa6
	struct amgc_unit_ctx **		pctx)
383aa6
{
383aa6
	struct amgc_unit_ctx_impl *	ctx;
389acb
	FILE *				ftmp;
389acb
	int				fd;
383aa6
43c8c9
	amgc_init_cparser_unit();
43c8c9
4671ad
	if (!dctx)
4671ad
		return AMGC_CUSTOM_ERROR(
4671ad
			dctx,AMGC_ERR_NULL_CONTEXT);
4671ad
4671ad
	else if (!(ctx = calloc(1,sizeof(*ctx))))
4671ad
		return AMGC_SYSTEM_ERROR(dctx);
4671ad
4671ad
	amgc_driver_set_ectx(
4671ad
		dctx,0,path);
383aa6
389acb
	if (strcmp(path,"-"))
389acb
		fd = -1;
4671ad
389acb
	else if (!(ftmp = amgc_stdin_to_tmp(dctx)))
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_SYSTEM_ERROR(dctx));
4671ad
389acb
	else if ((fd = dup(fileno(ftmp))) < 0)
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_SYSTEM_ERROR(dctx));
4671ad
389acb
	else
43c8c9
		ctx->ccunit.input = ftmp;
389acb
bb5e47
	if (amgc_map_input(dctx,fd,path,PROT_READ,&ctx->map))
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_NESTED_ERROR(dctx));
389acb
389acb
	if (fd > 0)
389acb
		close(fd);
383aa6
43c8c9
	/* compilation unit */
43c8c9
	ctx->ccunit.name		= path;
43c8c9
	ctx->ccunit.original_name	= path;
43c8c9
	ctx->ccunit.type		= COMPILATION_UNIT_C;
fd0662
	ctx->ccunit.standard		= dctx->cctx->std;
43c8c9
43c8c9
	/* parse, generate ast, generate ir */
43c8c9
	if ((process_unit(ctx->cctx.ccenv,&ctx->ccunit)) == false) {
43c8c9
		if (ctx->ccunit.input)
43c8c9
			fclose(ctx->ccunit.input);
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_CUSTOM_ERROR(dctx,AMGC_ERR_FLOW_ERROR));
43c8c9
	}
43c8c9
383aa6
	memcpy(&ctx->cctx,dctx->cctx,
383aa6
		sizeof(ctx->cctx));
383aa6
8fca74
	ctx->dctx	    = dctx;
f06b53
	ctx->path	    = path;
f06b53
	ctx->uctx.path	    = &ctx->path;
f06b53
	ctx->uctx.map	    = &ctx->map;
f06b53
	ctx->uctx.cctx	    = &ctx->cctx;
f06b53
	ctx->uctx.meta	    = &ctx->meta;
f06b53
	ctx->uctx.ccunit    = &ctx->ccunit;
383aa6
7a622c
	if (amgc_get_unit_entities(&ctx->uctx,&ctx->meta,&ctx->entities))
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_CUSTOM_ERROR(dctx,AMGC_ERR_FLOW_ERROR));
9c2028
75d04a
	ctx->uctx.entities  = ctx->entities;
383aa6
	*pctx = &ctx->uctx;
383aa6
	return 0;
383aa6
}
383aa6
383aa6
void amgc_free_unit_ctx(struct amgc_unit_ctx * ctx)
383aa6
{
383aa6
	struct amgc_unit_ctx_impl *	ictx;
383aa6
	uintptr_t			addr;
383aa6
383aa6
	if (ctx) {
383aa6
		addr = (uintptr_t)ctx - offsetof(struct amgc_unit_ctx_impl,uctx);
383aa6
		ictx = (struct amgc_unit_ctx_impl *)addr;
383aa6
		amgc_free_unit_ctx_impl(ictx,0);
383aa6
	}
383aa6
}