Blame src/driver/slbt_txtfile_ctx.c

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