Blame src/driver/amgc_unit_ctx.c

383aa6
/**********************************************************/
383aa6
/*  apimagic: cparser-based API normalization utility     */
d4e394
/*  Copyright (C) 2015--2021  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
		free(ctx);
383aa6
	}
383aa6
4671ad
	return ret;
383aa6
}
383aa6
27c847
static int 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
27c847
	ssize_t ret;
27c847
	ssize_t cnt;
27c847
	char *	ch;
389acb
	char	buf[4096];
27c847
	char	template[] = "/tmp/amgc_stdin_to_tmp_XXXXXX";
389acb
389acb
	addr = (uintptr_t)dctx - offsetof(struct amgc_driver_ctx_impl,ctx);
389acb
	ictx = (struct amgc_driver_ctx_impl *)addr;
389acb
27c847
	if (ictx->fdtmpin >= 0)
27c847
		return dup(ictx->fdtmpin);
389acb
27c847
	if ((fdtmp = mkstemp(template)) < 0)
27c847
		return -1;
389acb
27c847
	if ((ictx->fdtmpin = dup(fdtmp)) < 0) {
27c847
		close(fdtmp);
27c847
		return -1;
389acb
	}
389acb
27c847
	for (;;) {
27c847
		ret = read(0,buf,sizeof(buf)-1);
389acb
27c847
		while ((ret < 0) && (errno == EINTR))
27c847
			ret = read(0,buf,sizeof(buf)-1);
389acb
27c847
		if (ret < 0) {
27c847
			close(fdtmp);
27c847
			return -1;
389acb
27c847
		} else if (ret == 0) {
27c847
			return fdtmp;
389acb
27c847
		} else {
27c847
			ch  = buf;
27c847
			cnt = ret;
27c847
			ret = 0;
389acb
27c847
			for (; cnt; ) {
27c847
				ret = write(fdtmp,ch,cnt);
389acb
27c847
				while ((ret < 0) && (errno == EINTR))
27c847
					ret = write(fdtmp,ch,cnt);
0c8cc0
27c847
				if (ret < 0) {
27c847
					close(fdtmp);
27c847
					return -1;
27c847
				}
27c847
27c847
				ch  += ret;
27c847
				cnt -= ret;
27c847
			}
27c847
		}
27c847
	}
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
	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
27c847
	else if ((fd = amgc_stdin_to_tmp(dctx)) < 0)
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_SYSTEM_ERROR(dctx));
4671ad
27c847
	else if (lseek(fd,0,SEEK_SET < 0))
4671ad
		return amgc_free_unit_ctx_impl(
4671ad
			ctx,AMGC_NESTED_ERROR(dctx));
389acb
27c847
	else if (!(ctx->ccunit.input = fdopen(fd,"r")))
27c847
		return amgc_free_unit_ctx_impl(
27c847
			ctx,AMGC_FILE_ERROR(dctx));
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.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
}