| |
| |
| |
| |
| |
| |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <sys/mman.h> |
| |
| |
| #include <cparser/driver/driver.h> |
| #include <cparser/driver/c_driver.h> |
| |
| #include <apimagic/apimagic.h> |
| #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); |
| |
| amgc_unmap_input(&ctx->map); |
| free(ctx); |
| } |
| |
| return ret; |
| } |
| |
| static FILE * amgc_stdin_to_tmp(const struct amgc_driver_ctx * dctx) |
| { |
| struct amgc_driver_ctx_impl * ictx; |
| uintptr_t addr; |
| int fdtmp; |
| |
| FILE * ftmp; |
| char buf[4096]; |
| ssize_t nread; |
| int ret; |
| |
| addr = (uintptr_t)dctx - offsetof(struct amgc_driver_ctx_impl,ctx); |
| ictx = (struct amgc_driver_ctx_impl *)addr; |
| |
| if (ictx->fdtmpin >= 0) { |
| if ((fdtmp = dup(ictx->fdtmpin)) < 0) |
| return 0; |
| |
| if (!(ftmp = fdopen(fdtmp,"r"))) |
| close(fdtmp); |
| |
| return ftmp; |
| } |
| |
| if (!(ftmp = tmpfile())) |
| return 0; |
| |
| if ((ictx->fdtmpin = dup(fileno(ftmp))) < 0) { |
| fclose(ftmp); |
| return 0; |
| } |
| |
| nread = read(0,buf,sizeof(buf)-1); |
| |
| while (nread) { |
| if (nread > 0) { |
| buf[nread] = '\0'; |
| ret = fputs(buf,ftmp); |
| } else |
| ret = (errno == EINTR) ? 0 : -1; |
| |
| if (ret < 0) { |
| fclose(ftmp); |
| return 0; |
| } |
| |
| nread = read(0,buf,sizeof(buf)-1); |
| } |
| |
| if (fflush(ftmp)) { |
| fclose(ftmp); |
| return 0; |
| } |
| |
| return ftmp; |
| } |
| |
| 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(); |
| |
| |
| set_unit_handler(COMPILATION_UNIT_AST, |
| build_firm_ir,true); |
| |
| |
| 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; |
| FILE * ftmp; |
| 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 (!(ftmp = amgc_stdin_to_tmp(dctx))) |
| return amgc_free_unit_ctx_impl( |
| ctx,AMGC_SYSTEM_ERROR(dctx)); |
| |
| else if ((fd = dup(fileno(ftmp))) < 0) |
| return amgc_free_unit_ctx_impl( |
| ctx,AMGC_SYSTEM_ERROR(dctx)); |
| |
| else |
| ctx->ccunit.input = ftmp; |
| |
| if (amgc_map_input(dctx,fd,path,PROT_READ,&ctx->map)) |
| return amgc_free_unit_ctx_impl( |
| ctx,AMGC_NESTED_ERROR(dctx)); |
| |
| if (fd > 0) |
| close(fd); |
| |
| |
| ctx->ccunit.name = path; |
| ctx->ccunit.original_name = path; |
| ctx->ccunit.type = COMPILATION_UNIT_C; |
| ctx->ccunit.standard = dctx->cctx->std; |
| |
| |
| 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.map = &ctx->map; |
| 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); |
| } |
| } |