/**************************************************************/ /* treebnf: a tree oriented bnf library */ /* Copyright (C) 2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ /**************************************************************/ #include #include #include #include #include #include #include "treebnf_driver_impl.h" #include "treebnf_errinfo_impl.h" #include "treebnf_tmpfile_impl.h" static int tbnf_free_unit_ctx_impl(struct tbnf_unit_ctx_impl * ctx, int ret) { if (ctx) { tbnf_lib_unmap_raw_input(&ctx->map); free(ctx); } return ret; } static int tbnf_stdin_to_tmp(const struct tbnf_driver_ctx * dctx) { struct tbnf_driver_ctx_impl * ictx; int fdtmp; ssize_t ret; ssize_t cnt; char * ch; char buf[4096]; ictx = tbnf_get_driver_ictx(dctx); if (ictx->fdtmpin >= 0) return dup(ictx->fdtmpin); if ((fdtmp = tbnf_tmpfile()) < 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; 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; } } } } int tbnf_lib_get_unit_ctx( const struct tbnf_driver_ctx * dctx, const char * path, struct tbnf_unit_ctx ** pctx) { struct tbnf_unit_ctx_impl * ctx; int prot; int fd; if (!dctx) return TBNF_CUSTOM_ERROR( dctx,TBNF_ERR_NULL_CONTEXT); else if (!(ctx = calloc(1,sizeof(*ctx)))) return TBNF_BUFFER_ERROR(dctx); tbnf_driver_set_ectx( dctx,0,path); prot = PROT_READ; if (strcmp(path,"-")) fd = -1; else if ((fd = tbnf_stdin_to_tmp(dctx)) < 0) return tbnf_free_unit_ctx_impl( ctx,TBNF_FILE_ERROR(dctx)); if (tbnf_lib_map_raw_input(dctx,fd,path,prot,&ctx->map)) return tbnf_free_unit_ctx_impl( ctx,TBNF_NESTED_ERROR(dctx)); if (fd >= 0) close(fd); ctx->path = path; ctx->uctx.path = &ctx->path; ctx->uctx.map = &ctx->map; *pctx = &ctx->uctx; return 0; } void tbnf_lib_free_unit_ctx(struct tbnf_unit_ctx * ctx) { struct tbnf_unit_ctx_impl * ictx; uintptr_t addr; if (ctx) { addr = (uintptr_t)ctx - offsetof(struct tbnf_unit_ctx_impl,uctx); ictx = (struct tbnf_unit_ctx_impl *)addr; tbnf_free_unit_ctx_impl(ictx,0); } }