/*******************************************************************/ /* slibtool: a strong libtool implementation, written in C */ /* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ #include #include #include #include #include #include #include #include "slibtool_driver_impl.h" #include "slibtool_errinfo_impl.h" #include "slibtool_visibility_impl.h" /********************************************************/ /* Read a text file, and create an in-memory vecotr of */ /* normalized text lines, stripped of both leading and */ /* trailing white space. */ /********************************************************/ static int slbt_lib_free_txtfile_ctx_impl( struct slbt_txtfile_ctx_impl * ctx, struct slbt_input * mapinfo, int ret) { if (mapinfo) slbt_fs_unmap_input(mapinfo); if (ctx) { if (ctx->pathbuf) free(ctx->pathbuf); if (ctx->txtlines) free(ctx->txtlines); if (ctx->txtlinev) free(ctx->txtlinev); free(ctx); } return ret; } static int slbt_lib_get_txtfile_ctx_impl( const struct slbt_driver_ctx * dctx, const char * path, int fdsrc, struct slbt_txtfile_ctx ** pctx) { struct slbt_txtfile_ctx_impl * ctx; struct slbt_input mapinfo; size_t nlines; char * ch; char * cap; char * src; char * mark; const char ** pline; char dummy; int cint; /* map txtfile file temporarily */ if (slbt_fs_map_input(dctx,fdsrc,path,PROT_READ,&mapinfo) < 0) return SLBT_NESTED_ERROR(dctx); /* alloc context */ if (!(ctx = calloc(1,sizeof(*ctx)))) return slbt_lib_free_txtfile_ctx_impl( ctx,&mapinfo, SLBT_BUFFER_ERROR(dctx)); /* count lines */ src = mapinfo.size ? mapinfo.addr : &dummy; cap = &src[mapinfo.size]; for (; (srcpathbuf = strdup(path))) return slbt_lib_free_txtfile_ctx_impl( ctx,&mapinfo, SLBT_SYSTEM_ERROR(dctx,0)); if (!(ctx->txtlines = calloc(mapinfo.size+1,1))) return slbt_lib_free_txtfile_ctx_impl( ctx,&mapinfo, SLBT_SYSTEM_ERROR(dctx,0)); if (!(ctx->txtlinev = calloc(nlines+1,sizeof(char *)))) return slbt_lib_free_txtfile_ctx_impl( ctx,&mapinfo, SLBT_SYSTEM_ERROR(dctx,0)); /* copy the source to the allocated string buffer */ memcpy(ctx->txtlines,mapinfo.addr,mapinfo.size); slbt_fs_unmap_input(&mapinfo); /* populate the line vector, handle whitespace */ src = ctx->txtlines; cap = &src[mapinfo.size]; for (; (srctxtlinev; ch *pline) && isspace((cint = *ch)); ch--) *ch = '\0'; if ((ch = mark) < cap) *ch++ = '\0'; } /* all done */ ctx->dctx = dctx; ctx->path = ctx->pathbuf; ctx->tctx.path = &ctx->path; ctx->tctx.txtlinev = ctx->txtlinev; *pctx = &ctx->tctx; return 0; } slbt_hidden int slbt_impl_get_txtfile_ctx( const struct slbt_driver_ctx * dctx, const char * path, int fdsrc, struct slbt_txtfile_ctx ** pctx) { return slbt_lib_get_txtfile_ctx_impl(dctx,path,fdsrc,pctx); } int slbt_lib_get_txtfile_ctx( const struct slbt_driver_ctx * dctx, const char * path, struct slbt_txtfile_ctx ** pctx) { return slbt_lib_get_txtfile_ctx_impl(dctx,path,(-1),pctx); } void slbt_lib_free_txtfile_ctx(struct slbt_txtfile_ctx * ctx) { struct slbt_txtfile_ctx_impl * ictx; uintptr_t addr; if (ctx) { addr = (uintptr_t)ctx - offsetof(struct slbt_txtfile_ctx_impl,tctx); ictx = (struct slbt_txtfile_ctx_impl *)addr; slbt_lib_free_txtfile_ctx_impl(ictx,0,0); } }