/**********************************************************/ /* apimagic: cparser-based API normalization utility */ /* Copyright (C) 2015--2016 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */ /**********************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "apimagic_driver_impl.h" #include "apimagic_errinfo_impl.h" static int amgc_free_unit_ctx_impl(struct amgc_unit_ctx_impl * ctx, int ret) { if (ctx) { if (ctx->entities) amgc_free_unit_entities(ctx->entities); free(ctx); } return ret; } static int amgc_stdin_to_tmp(const struct amgc_driver_ctx * dctx) { struct amgc_driver_ctx_impl * ictx; uintptr_t addr; int fdtmp; ssize_t ret; ssize_t cnt; char * ch; char buf[4096]; char template[] = "/tmp/amgc_stdin_to_tmp_XXXXXX"; addr = (uintptr_t)dctx - offsetof(struct amgc_driver_ctx_impl,ctx); ictx = (struct amgc_driver_ctx_impl *)addr; if (ictx->fdtmpin >= 0) return dup(ictx->fdtmpin); if ((fdtmp = mkstemp(template)) < 0) return -1; if ((ictx->fdtmpin = dup(fdtmp)) < 0) { close(fdtmp); return -1; } for (;;) { ret = read(0,buf,sizeof(buf)-1); while ((ret < 0) && (errno == EINTR)) ret = read(0,buf,sizeof(buf)-1); if (ret < 0) { close(fdtmp); return -1; } else if (ret == 0) { return fdtmp; } else { ch = buf; cnt = ret; ret = 0; for (; cnt; ) { ret = write(fdtmp,ch,cnt); while ((ret < 0) && (errno == EINTR)) ret = write(fdtmp,ch,cnt); if (ret < 0) { close(fdtmp); return -1; } ch += ret; cnt -= ret; } } } } static bool amgc_cparser_no_op( compilation_env_t * env, compilation_unit_t * unit) { (void)env; (void)unit; return true; } static void amgc_init_cparser_unit(void) { set_default_handlers(); /* parse only */ set_unit_handler(COMPILATION_UNIT_AST, build_firm_ir,true); /* assign no-op handler */ set_unit_handler(COMPILATION_UNIT_PREPROCESSED_ASSEMBLER, amgc_cparser_no_op,true); set_unit_handler(COMPILATION_UNIT_OBJECT, amgc_cparser_no_op,true); } int amgc_get_unit_ctx( const struct amgc_driver_ctx * dctx, const char * path, struct amgc_unit_ctx ** pctx) { struct amgc_unit_ctx_impl * ctx; int fd; amgc_init_cparser_unit(); if (!dctx) return AMGC_CUSTOM_ERROR( dctx,AMGC_ERR_NULL_CONTEXT); else if (!(ctx = calloc(1,sizeof(*ctx)))) return AMGC_SYSTEM_ERROR(dctx); amgc_driver_set_ectx( dctx,0,path); if (strcmp(path,"-")) fd = -1; else if ((fd = amgc_stdin_to_tmp(dctx)) < 0) return amgc_free_unit_ctx_impl( ctx,AMGC_SYSTEM_ERROR(dctx)); else if (lseek(fd,0,SEEK_SET < 0)) return amgc_free_unit_ctx_impl( ctx,AMGC_NESTED_ERROR(dctx)); else if (!(ctx->ccunit.input = fdopen(fd,"r"))) return amgc_free_unit_ctx_impl( ctx,AMGC_FILE_ERROR(dctx)); /* compilation unit */ ctx->ccunit.name = path; ctx->ccunit.original_name = path; ctx->ccunit.type = COMPILATION_UNIT_C; ctx->ccunit.standard = dctx->cctx->std; /* parse, generate ast, generate ir */ if ((process_unit(ctx->cctx.ccenv,&ctx->ccunit)) == false) { if (ctx->ccunit.input) fclose(ctx->ccunit.input); return amgc_free_unit_ctx_impl( ctx,AMGC_CUSTOM_ERROR(dctx,AMGC_ERR_FLOW_ERROR)); } memcpy(&ctx->cctx,dctx->cctx, sizeof(ctx->cctx)); ctx->dctx = dctx; ctx->path = path; ctx->uctx.path = &ctx->path; ctx->uctx.cctx = &ctx->cctx; ctx->uctx.meta = &ctx->meta; ctx->uctx.ccunit = &ctx->ccunit; if (amgc_get_unit_entities(&ctx->uctx,&ctx->meta,&ctx->entities)) return amgc_free_unit_ctx_impl( ctx,AMGC_CUSTOM_ERROR(dctx,AMGC_ERR_FLOW_ERROR)); ctx->uctx.entities = ctx->entities; *pctx = &ctx->uctx; return 0; } void amgc_free_unit_ctx(struct amgc_unit_ctx * ctx) { struct amgc_unit_ctx_impl * ictx; uintptr_t addr; if (ctx) { addr = (uintptr_t)ctx - offsetof(struct amgc_unit_ctx_impl,uctx); ictx = (struct amgc_unit_ctx_impl *)addr; amgc_free_unit_ctx_impl(ictx,0); } }