firasuke / cross / slibtool

Forked from cross/slibtool a month ago
Clone

Blame src/logic/slbt_exec_ctx.c

528799
/*******************************************************************/
528799
/*  slibtool: a skinny libtool implementation, written in C        */
528799
/*  Copyright (C) 2016  Z. Gilboa                                  */
528799
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
528799
/*******************************************************************/
528799
528799
#include <stdint.h>
528799
#include <unistd.h>
528799
#include <stdlib.h>
528799
#include <string.h>
528799
528799
#include <slibtool/slibtool.h>
528799
528799
#define SLBT_ARGV_SPARE_PTRS	16
528799
528799
struct slbt_exec_ctx_impl {
528799
	int			argc;
528799
	char *			args;
528799
	struct slbt_exec_ctx	ctx;
528799
	char *			buffer[];
528799
};
528799
528799
528799
static size_t slbt_parse_comma_separated_flags(
528799
	const char *	str,
528799
	int *		argc)
528799
{
528799
	const char * ch;
528799
528799
	for (ch=str; *ch; ch++)
528799
		if (*ch == ',')
528799
			(*argc)++;
528799
528799
	return ch - str;
528799
}
528799
528799
df088e
static char * slbt_source_file(char ** argv)
df088e
{
df088e
	char **	parg;
df088e
	char *	ch;
df088e
df088e
	for (parg=argv; *parg; parg++)
df088e
		if ((ch = strrchr(*parg,'.')))
df088e
			if ((!(strcmp(++ch,"s")))
df088e
					|| (!(strcmp(ch,"S")))
df088e
					|| (!(strcmp(ch,"c")))
df088e
					|| (!(strcmp(ch,"cc")))
df088e
					|| (!(strcmp(ch,"cxx"))))
df088e
				return *parg;
df088e
	return 0;
df088e
}
df088e
df088e
528799
static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc(
528799
	const struct slbt_driver_ctx *	dctx)
528799
{
528799
	struct slbt_exec_ctx_impl *	ictx;
528799
	size_t				size;
528799
	int				argc;
528799
	char *				args;
df088e
	char *				csrc;
528799
	char **				parg;
528799
df088e
	argc = 0;
df088e
	csrc = 0;
df088e
df088e
	/* clerical buffer size (guard, suffix, version) */
df088e
	size  = strlen(".lo") + strlen(".libs/") + 2*sizeof('\0');
df088e
	size += 36*strlen(".0000") + 36*sizeof('\0');
528799
528799
	/* buffer size (cargv, -Wc) */
528799
	for (parg=dctx->cctx->cargv; *parg; parg++, argc++)
528799
		if (!(strncmp("-Wc,",*parg,4)))
528799
			size += sizeof('\0') + slbt_parse_comma_separated_flags(
528799
					parg[4],&argc);
528799
		else
528799
			size += sizeof('\0') + strlen(*parg);
528799
df088e
	/* buffer size (ldirname, lbasename, lobjname) */
df088e
	if (dctx->cctx->output)
df088e
		size += 3*strlen(dctx->cctx->output);
df088e
	else if ((csrc = slbt_source_file(dctx->cctx->cargv)))
df088e
		size += 3*strlen(csrc);
df088e
528799
	/* alloc */
df088e
	if (!(args = malloc(size)))
528799
		return 0;
528799
528799
	size = sizeof(*ictx) + (argc+SLBT_ARGV_SPARE_PTRS)*sizeof(char *);
528799
528799
	if (!(ictx = calloc(1,size))) {
528799
		free(args);
528799
		return 0;
528799
	}
528799
528799
	ictx->args = args;
528799
	ictx->argc = argc;
528799
df088e
	ictx->ctx.csrc = csrc;
df088e
528799
	return ictx;
528799
}
528799
528799
528799
int  slbt_get_exec_ctx(
528799
	const struct slbt_driver_ctx *	dctx,
528799
	struct slbt_exec_ctx **		ectx)
528799
{
528799
	struct slbt_exec_ctx_impl *	ictx;
528799
	char **				parg;
528799
	char *				ch;
528799
	char *				slash;
df088e
	const char *			ref;
528799
	int				i;
528799
528799
	/* alloc */
528799
	if (!(ictx = slbt_exec_ctx_alloc(dctx)))
528799
		return -1;
528799
528799
	/* init with guard for later .lo check */
528799
	ch                = ictx->args + strlen(".lo");
528799
	ictx->ctx.argv    = ictx->buffer;
528799
528799
	/* <compiler> */
528799
	ictx->ctx.program = dctx->cctx->cargv[0];
528799
df088e
	/* ldirname, lbasename */
df088e
	ref = (dctx->cctx->output)
df088e
		? dctx->cctx->output
df088e
		: ictx->ctx.csrc;
df088e
df088e
	if (ref && !ictx->ctx.csrc && (slash = strrchr(ref,'/'))) {
df088e
		ictx->ctx.ldirname = ch;
df088e
		strcpy(ch,ref);
df088e
		ch += slash - ref;
df088e
		ch += sprintf(ch,"%s","/.libs/");
df088e
		ch++;
df088e
df088e
		ictx->ctx.lbasename = ch;
df088e
		ch += sprintf(ch,"%s",++slash);
df088e
		ch++;
df088e
	} else if (ref) {
df088e
		ictx->ctx.ldirname = ch;
df088e
		ch += sprintf(ch,"%s",".libs/");
df088e
		ch++;
df088e
df088e
		ictx->ctx.lbasename = ch;
df088e
		slash = strrchr(ref,'/');
df088e
		ch += sprintf(ch,"%s",slash ? ++slash : ref);
df088e
		ch++;
df088e
	}
df088e
df088e
	/* lbasename suffix */
df088e
	if (ref && (dctx->cctx->mode == SLBT_MODE_COMPILE)) {
df088e
		if ((ch[-4] == '.') && (ch[-3] == 'l') && (ch[-2] == 'o')) {
df088e
			ch[-3] = 'o';
df088e
			ch[-2] = '\0';
df088e
			ch--;
df088e
		} else if (ictx->ctx.csrc) {
df088e
			if ((ch = strrchr(ictx->ctx.lbasename,'.'))) {
df088e
				*++ch = 'o';
df088e
				*++ch = '\0';
df088e
				ch++;
df088e
			}
df088e
		}
df088e
	}
df088e
528799
	/* cargv, -Wc */
528799
	for (i=0, parg=dctx->cctx->cargv; *parg; parg++, ch++) {
528799
		if (!(strncmp("-Wc,",*parg,4))) {
528799
			strcpy(ch,parg[4]);
528799
			ictx->ctx.argv[i++] = ch;
528799
528799
			for (; *ch; ch++)
528799
				if (*ch == ',') {
528799
					*ch = '\0';
528799
					ictx->ctx.argv[i++] = ch+1;
528799
				}
528799
		} else {
528799
			ictx->ctx.argv[i++] = ch;
528799
			ch += sprintf(ch,"%s",*parg);
528799
		}
528799
	}
528799
528799
	if (dctx->cctx->mode == SLBT_MODE_COMPILE) {
528799
		if (dctx->cctx->drvflags & SLBT_DRIVER_SHARED) {
528799
			ictx->ctx.argv[i++] = "-DPIC";
528799
			ictx->ctx.argv[i++] = "-fPIC";
528799
		}
528799
528799
		ictx->ctx.argv[i++] = "-c";
df088e
	}
df088e
df088e
	/* output file name */
df088e
	if (ref) {
528799
		ictx->ctx.argv[i++] = "-o";
528799
		ictx->ctx.argv[i++] = ch;
df088e
		ictx->ctx.lobjname  = ch;
528799
df088e
		sprintf(ch,"%s%s",
df088e
			ictx->ctx.ldirname,
df088e
			ictx->ctx.lbasename);
528799
	}
528799
528799
	*ectx = &ictx->ctx;
528799
	return 0;
528799
}
528799
528799
528799
static int slbt_free_exec_ctx_impl(
528799
	struct slbt_exec_ctx_impl *	ictx,
528799
	int				status)
528799
{
528799
	free(ictx->args);
528799
	free (ictx);
528799
	return status;
528799
}
528799
528799
528799
void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx)
528799
{
528799
	struct slbt_exec_ctx_impl *	ictx;
528799
	uintptr_t			addr;
528799
528799
	if (ctx) {
528799
		addr = (uintptr_t)ctx - offsetof(struct slbt_exec_ctx_impl,ctx);
528799
		ictx = (struct slbt_exec_ctx_impl *)addr;
528799
		slbt_free_exec_ctx_impl(ictx,0);
528799
	}
528799
}