|
|
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 |
|
|
|
ef1e6e |
/* clerical [worst-case] buffer size (guard, .libs, version) */
|
|
|
ef1e6e |
size = strlen(".lo") + sizeof('\0');
|
|
|
ef1e6e |
size += 6 * (strlen(".libs/") + sizeof('\0'));
|
|
|
ef1e6e |
size += 36 * (strlen(".0000") + 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 |
|
|
|
e88a39 |
/* buffer size (ldirname, lbasename, lobjname, aobjname, ltobjname) */
|
|
|
df088e |
if (dctx->cctx->output)
|
|
|
e02305 |
size += 4*strlen(dctx->cctx->output);
|
|
|
df088e |
else if ((csrc = slbt_source_file(dctx->cctx->cargv)))
|
|
|
e02305 |
size += 4*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 |
|
|
|
5aae4b |
/* placeholders for -DPIC, -fPIC, -c, -o, <output> */
|
|
|
5aae4b |
ictx->ctx.dpic = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.fpic = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.cass = &ictx->ctx.argv[i++];
|
|
|
528799 |
|
|
|
5aae4b |
ictx->ctx.lout[0] = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.lout[1] = &ictx->ctx.argv[i++];
|
|
|
df088e |
|
|
|
df088e |
/* output file name */
|
|
|
df088e |
if (ref) {
|
|
|
5aae4b |
*ictx->ctx.lout[0] = "-o";
|
|
|
5aae4b |
*ictx->ctx.lout[1] = ch;
|
|
|
5aae4b |
ictx->ctx.lobjname = ch;
|
|
|
528799 |
|
|
|
e02305 |
ch += sprintf(ch,"%s%s",
|
|
|
df088e |
ictx->ctx.ldirname,
|
|
|
e02305 |
ictx->ctx.lbasename)
|
|
|
e02305 |
+ sizeof('\0');
|
|
|
e02305 |
|
|
|
e02305 |
ictx->ctx.aobjname = ch;
|
|
|
e02305 |
|
|
|
e02305 |
ch += sprintf(ch,"%s",ictx->ctx.ldirname);
|
|
|
e02305 |
ch -= strlen(".libs/");
|
|
|
e88a39 |
ch += sprintf(ch,"%s",
|
|
|
e88a39 |
ictx->ctx.lbasename)
|
|
|
e88a39 |
+ sizeof('\0');
|
|
|
e88a39 |
|
|
|
e88a39 |
ictx->ctx.ltobjname = ch;
|
|
|
e88a39 |
strcpy(ch,ictx->ctx.aobjname);
|
|
|
e88a39 |
|
|
|
e88a39 |
if ((ch = strrchr(ch,'.')))
|
|
|
e88a39 |
ch += sprintf(ch,"%s",
|
|
|
e88a39 |
(dctx->cctx->mode == SLBT_MODE_COMPILE)
|
|
|
e88a39 |
? ".lo"
|
|
|
e88a39 |
: ".la")
|
|
|
e88a39 |
+ sizeof('\0');
|
|
|
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 |
}
|
|
|
5aae4b |
|
|
|
5aae4b |
|
|
|
5aae4b |
void slbt_reset_placeholders(struct slbt_exec_ctx * ectx)
|
|
|
5aae4b |
{
|
|
|
5aae4b |
*ectx->dpic = "-DSLIBTOOL_PLACEHOLDER_DPIC";
|
|
|
5aae4b |
*ectx->fpic = "-DSLIBTOOL_PLACEHOLDER_FPIC";
|
|
|
5aae4b |
*ectx->cass = "-DSLIBTOOL_PLACEHOLDER_COMPILE_ASSEMBLE";
|
|
|
5aae4b |
|
|
|
5aae4b |
*ectx->lout[0] = "-DSLIBTOOL_PLACEHOLDER_OUTPUT_SWITCH";
|
|
|
5aae4b |
*ectx->lout[1] = "-DSLIBTOOL_PLACEHOLDER_OUTPUT_FILE";
|
|
|
5aae4b |
}
|