|
|
9ca8c4 |
/*******************************************************************/
|
|
|
9ca8c4 |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
9ca8c4 |
/* Copyright (C) 2016 Z. Gilboa */
|
|
|
9ca8c4 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
9ca8c4 |
/*******************************************************************/
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
#include <stdint.h>
|
|
|
9ca8c4 |
#include <unistd.h>
|
|
|
9ca8c4 |
#include <fcntl.h>
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
#define ARGV_DRIVER
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
#include <slibtool/slibtool.h>
|
|
|
9ca8c4 |
#include "slibtool_driver_impl.h"
|
|
|
9ca8c4 |
#include "argv/argv.h"
|
|
|
9ca8c4 |
|
|
|
56cab3 |
struct slbt_split_vector {
|
|
|
56cab3 |
char ** targv;
|
|
|
56cab3 |
char ** cargv;
|
|
|
56cab3 |
};
|
|
|
56cab3 |
|
|
|
9ca8c4 |
struct slbt_driver_ctx_alloc {
|
|
|
9ca8c4 |
struct argv_meta * meta;
|
|
|
9ca8c4 |
struct slbt_driver_ctx_impl ctx;
|
|
|
9ca8c4 |
uint64_t guard;
|
|
|
9ca8c4 |
const char * units[];
|
|
|
9ca8c4 |
};
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
static uint32_t slbt_argv_flags(uint32_t flags)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
uint32_t ret = 0;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (flags & SLBT_DRIVER_VERBOSITY_NONE)
|
|
|
9ca8c4 |
ret |= ARGV_VERBOSITY_NONE;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
|
|
|
9ca8c4 |
ret |= ARGV_VERBOSITY_ERRORS;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (flags & SLBT_DRIVER_VERBOSITY_STATUS)
|
|
|
9ca8c4 |
ret |= ARGV_VERBOSITY_STATUS;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
return ret;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
static int slbt_driver_usage(
|
|
|
9ca8c4 |
const char * program,
|
|
|
9ca8c4 |
const char * arg,
|
|
|
9ca8c4 |
const struct argv_option * options,
|
|
|
9ca8c4 |
struct argv_meta * meta)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
char header[512];
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
snprintf(header,sizeof(header),
|
|
|
9ca8c4 |
"Usage: %s [options] <file>...\n" "Options:\n",
|
|
|
9ca8c4 |
program);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
argv_usage(stdout,header,options,arg);
|
|
|
9ca8c4 |
argv_free(meta);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
return SLBT_USAGE;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
static struct slbt_driver_ctx_impl * slbt_driver_ctx_alloc(
|
|
|
9ca8c4 |
struct argv_meta * meta,
|
|
|
9ca8c4 |
const struct slbt_common_ctx * cctx,
|
|
|
9ca8c4 |
size_t nunits)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
struct slbt_driver_ctx_alloc * ictx;
|
|
|
9ca8c4 |
size_t size;
|
|
|
9ca8c4 |
struct argv_entry * entry;
|
|
|
9ca8c4 |
const char ** units;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
size = sizeof(struct slbt_driver_ctx_alloc);
|
|
|
9ca8c4 |
size += (nunits+1)*sizeof(const char *);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (!(ictx = calloc(1,size)))
|
|
|
9ca8c4 |
return 0;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (cctx)
|
|
|
9ca8c4 |
memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
|
|
|
9ca8c4 |
if (!entry->fopt)
|
|
|
9ca8c4 |
*units++ = entry->arg;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
ictx->meta = meta;
|
|
|
9ca8c4 |
ictx->ctx.ctx.units = ictx->units;
|
|
|
9ca8c4 |
return &ictx->ctx;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
static int slbt_get_driver_ctx_fail(struct argv_meta * meta)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
argv_free(meta);
|
|
|
9ca8c4 |
return -1;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
56cab3 |
static int slbt_split_argv(
|
|
|
56cab3 |
char ** argv,
|
|
|
56cab3 |
uint32_t flags,
|
|
|
56cab3 |
struct slbt_split_vector * sargv)
|
|
|
56cab3 |
{
|
|
|
56cab3 |
int i;
|
|
|
56cab3 |
int argc;
|
|
|
56cab3 |
const char * program;
|
|
|
56cab3 |
char * compiler;
|
|
|
56cab3 |
char ** targv;
|
|
|
56cab3 |
char ** cargv;
|
|
|
56cab3 |
struct argv_meta * meta;
|
|
|
56cab3 |
struct argv_entry * entry;
|
|
|
56cab3 |
struct argv_entry * mode;
|
|
|
56cab3 |
const struct argv_option * option;
|
|
|
56cab3 |
const struct argv_option * options = slbt_default_options;
|
|
|
56cab3 |
struct argv_ctx ctx = {ARGV_VERBOSITY_NONE,
|
|
|
56cab3 |
ARGV_MODE_SCAN,
|
|
|
56cab3 |
0,0,0,0,0,0,0};
|
|
|
56cab3 |
|
|
|
56cab3 |
program = argv_program_name(argv[0]);
|
|
|
56cab3 |
|
|
|
56cab3 |
/* missing arguments? */
|
|
|
56cab3 |
if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
|
|
|
56cab3 |
return slbt_driver_usage(program,0,options,0);
|
|
|
56cab3 |
|
|
|
56cab3 |
/* initial argv scan: ... --mode=xxx ... <compiler> ... */
|
|
|
56cab3 |
argv_scan(argv,options,&ctx,0);
|
|
|
56cab3 |
|
|
|
56cab3 |
/* invalid slibtool arguments? */
|
|
|
56cab3 |
if (ctx.erridx && !ctx.unitidx) {
|
|
|
56cab3 |
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
|
|
|
56cab3 |
argv_get(
|
|
|
56cab3 |
argv,options,
|
|
|
56cab3 |
slbt_argv_flags(flags));
|
|
|
56cab3 |
return -1;
|
|
|
56cab3 |
}
|
|
|
56cab3 |
|
|
|
56cab3 |
/* missing compiler? */
|
|
|
56cab3 |
if (!ctx.unitidx) {
|
|
|
56cab3 |
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
|
|
|
56cab3 |
fprintf(stderr,
|
|
|
56cab3 |
"%s: error: <compiler> is missing.\n",
|
|
|
56cab3 |
program);
|
|
|
56cab3 |
return -1;
|
|
|
56cab3 |
}
|
|
|
56cab3 |
|
|
|
56cab3 |
/* obtain slibtool's own arguments */
|
|
|
56cab3 |
compiler = argv[ctx.unitidx];
|
|
|
56cab3 |
argv[ctx.unitidx] = 0;
|
|
|
56cab3 |
|
|
|
56cab3 |
meta = argv_get(argv,options,ARGV_VERBOSITY_NONE);
|
|
|
56cab3 |
argv[ctx.unitidx] = compiler;
|
|
|
56cab3 |
|
|
|
56cab3 |
/* missing --mode? */
|
|
|
56cab3 |
for (mode=0, entry=meta->entries; entry->fopt; entry++)
|
|
|
56cab3 |
if (entry->tag == TAG_MODE)
|
|
|
56cab3 |
mode = entry;
|
|
|
56cab3 |
|
|
|
56cab3 |
argv_free(meta);
|
|
|
56cab3 |
|
|
|
56cab3 |
if (!mode) {
|
|
|
56cab3 |
fprintf(stderr,
|
|
|
56cab3 |
"%s: error: --mode must be specified.\n",
|
|
|
56cab3 |
program);
|
|
|
56cab3 |
return -1;
|
|
|
56cab3 |
}
|
|
|
56cab3 |
|
|
|
56cab3 |
/* allocate split vectors */
|
|
|
56cab3 |
for (argc=0, targv=argv; *targv; targv++)
|
|
|
56cab3 |
argc++;
|
|
|
56cab3 |
|
|
|
56cab3 |
if ((sargv->targv = calloc(2*(argc+1),sizeof(char *))))
|
|
|
56cab3 |
sargv->cargv = sargv->targv + argc + 1;
|
|
|
56cab3 |
else
|
|
|
56cab3 |
return -1;
|
|
|
56cab3 |
|
|
|
56cab3 |
/* split vectors: slibtool's own options */
|
|
|
56cab3 |
for (i=0; i
|
|
|
56cab3 |
sargv->targv[i] = argv[i];
|
|
|
56cab3 |
|
|
|
56cab3 |
/* split vectors: legacy mixture */
|
|
|
56cab3 |
options = option_from_tag(
|
|
|
56cab3 |
slbt_default_options,
|
|
|
56cab3 |
TAG_OUTPUT);
|
|
|
56cab3 |
|
|
|
56cab3 |
targv = sargv->targv + i;
|
|
|
56cab3 |
cargv = sargv->cargv;
|
|
|
56cab3 |
|
|
|
56cab3 |
for (; i
|
|
|
56cab3 |
if (argv[i][0] != '-')
|
|
|
56cab3 |
*cargv++ = argv[i];
|
|
|
56cab3 |
|
|
|
56cab3 |
else if (argv[i][1] == 'o')
|
|
|
56cab3 |
*targv++ = argv[i];
|
|
|
56cab3 |
|
|
|
56cab3 |
else if ((argv[i][1] == 'W') && (argv[i][2] == 'c'))
|
|
|
56cab3 |
*cargv++ = argv[i];
|
|
|
56cab3 |
|
|
|
56cab3 |
else if (!(strcmp("Xcompiler",&argv[i][1])))
|
|
|
56cab3 |
*cargv++ = argv[++i];
|
|
|
56cab3 |
|
|
|
56cab3 |
else {
|
|
|
56cab3 |
for (option=options; option->long_name; option++)
|
|
|
56cab3 |
if (!(strcmp(option->long_name,&argv[i][1])))
|
|
|
56cab3 |
break;
|
|
|
56cab3 |
|
|
|
56cab3 |
if (option->long_name)
|
|
|
56cab3 |
*targv++ = argv[i];
|
|
|
56cab3 |
else
|
|
|
56cab3 |
*cargv++ = argv[i];
|
|
|
56cab3 |
}
|
|
|
56cab3 |
}
|
|
|
56cab3 |
|
|
|
56cab3 |
return 0;
|
|
|
56cab3 |
}
|
|
|
56cab3 |
|
|
|
9ca8c4 |
int slbt_get_driver_ctx(
|
|
|
9ca8c4 |
char ** argv,
|
|
|
9ca8c4 |
char ** envp,
|
|
|
9ca8c4 |
uint32_t flags,
|
|
|
9ca8c4 |
struct slbt_driver_ctx ** pctx)
|
|
|
9ca8c4 |
{
|
|
|
56cab3 |
struct slbt_split_vector sargv;
|
|
|
9ca8c4 |
struct slbt_driver_ctx_impl * ctx;
|
|
|
9ca8c4 |
struct slbt_common_ctx cctx;
|
|
|
9ca8c4 |
const struct argv_option * options;
|
|
|
9ca8c4 |
struct argv_meta * meta;
|
|
|
9ca8c4 |
struct argv_entry * entry;
|
|
|
9ca8c4 |
size_t nunits;
|
|
|
9ca8c4 |
const char * program;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
options = slbt_default_options;
|
|
|
9ca8c4 |
|
|
|
56cab3 |
if (slbt_split_argv(argv,flags,&sargv))
|
|
|
56cab3 |
return -1;
|
|
|
56cab3 |
|
|
|
56cab3 |
if (!(meta = argv_get(sargv.targv,options,slbt_argv_flags(flags))))
|
|
|
9ca8c4 |
return -1;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
nunits = 0;
|
|
|
9ca8c4 |
program = argv_program_name(argv[0]);
|
|
|
9ca8c4 |
memset(&cctx,0,sizeof(cctx));
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
/* get options, count units */
|
|
|
9ca8c4 |
for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
|
|
|
9ca8c4 |
if (entry->fopt) {
|
|
|
9ca8c4 |
switch (entry->tag) {
|
|
|
9ca8c4 |
case TAG_HELP:
|
|
|
949677 |
case TAG_HELP_ALL:
|
|
|
9ca8c4 |
if (flags & SLBT_DRIVER_VERBOSITY_USAGE)
|
|
|
9ca8c4 |
return slbt_driver_usage(program,entry->arg,options,meta);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
case TAG_VERSION:
|
|
|
9ca8c4 |
cctx.drvflags |= SLBT_DRIVER_VERSION;
|
|
|
9ca8c4 |
break;
|
|
|
667ce2 |
|
|
|
667ce2 |
case TAG_MODE:
|
|
|
667ce2 |
if (!strcmp("clean",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_CLEAN;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("compile",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_COMPILE;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("execute",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_EXECUTE;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("finish",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_FINISH;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("install",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_INSTALL;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("link",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_LINK;
|
|
|
667ce2 |
|
|
|
667ce2 |
else if (!strcmp("uninstall",entry->arg))
|
|
|
667ce2 |
cctx.mode = SLBT_MODE_UNINSTALL;
|
|
|
667ce2 |
break;
|
|
|
071d14 |
|
|
|
071d14 |
case TAG_DRY_RUN:
|
|
|
071d14 |
cctx.drvflags |= SLBT_DRIVER_DRY_RUN;
|
|
|
071d14 |
break;
|
|
|
53f4ec |
|
|
|
53f4ec |
case TAG_TAG:
|
|
|
53f4ec |
if (!strcmp("CC",entry->arg))
|
|
|
53f4ec |
cctx.tag = SLBT_TAG_CC;
|
|
|
53f4ec |
|
|
|
53f4ec |
else if (!strcmp("CXX",entry->arg))
|
|
|
53f4ec |
cctx.tag = SLBT_TAG_CXX;
|
|
|
53f4ec |
break;
|
|
|
173b54 |
|
|
|
173b54 |
case TAG_CONFIG:
|
|
|
173b54 |
cctx.drvflags |= SLBT_DRIVER_CONFIG;
|
|
|
173b54 |
break;
|
|
|
173b54 |
|
|
|
fea1b8 |
case TAG_DEBUG:
|
|
|
fea1b8 |
cctx.drvflags |= SLBT_DRIVER_DEBUG;
|
|
|
fea1b8 |
break;
|
|
|
d03fbc |
|
|
|
d03fbc |
case TAG_FEATURES:
|
|
|
d03fbc |
cctx.drvflags |= SLBT_DRIVER_FEATURES;
|
|
|
d03fbc |
break;
|
|
|
6376f0 |
|
|
|
6376f0 |
case TAG_WARNINGS:
|
|
|
6376f0 |
if (!strcmp("all",entry->arg))
|
|
|
6376f0 |
cctx.tag = SLBT_WARNING_LEVEL_ALL;
|
|
|
6376f0 |
|
|
|
6376f0 |
else if (!strcmp("error",entry->arg))
|
|
|
6376f0 |
cctx.tag = SLBT_WARNING_LEVEL_ERROR;
|
|
|
6376f0 |
|
|
|
6376f0 |
else if (!strcmp("none",entry->arg))
|
|
|
6376f0 |
cctx.tag = SLBT_WARNING_LEVEL_NONE;
|
|
|
6376f0 |
break;
|
|
|
40fabb |
|
|
|
40fabb |
case TAG_DEPS:
|
|
|
40fabb |
cctx.drvflags |= SLBT_DRIVER_DEPS;
|
|
|
40fabb |
break;
|
|
|
40fabb |
|
|
|
398419 |
case TAG_SILENT:
|
|
|
398419 |
cctx.drvflags |= SLBT_DRIVER_SILENT;
|
|
|
398419 |
break;
|
|
|
25956b |
|
|
|
25956b |
case TAG_VERBOSE:
|
|
|
25956b |
cctx.drvflags |= SLBT_DRIVER_VERBOSE;
|
|
|
25956b |
break;
|
|
|
b83b64 |
|
|
|
b83b64 |
case TAG_OUTPUT:
|
|
|
b83b64 |
cctx.output = entry->arg;
|
|
|
b83b64 |
break;
|
|
|
4f1b20 |
|
|
|
4f1b20 |
case TAG_PREFER_PIC:
|
|
|
4f1b20 |
cctx.drvflags |= SLBT_DRIVER_PRO_PIC;
|
|
|
4f1b20 |
break;
|
|
|
4f1b20 |
|
|
|
4f1b20 |
case TAG_PREFER_NON_PIC:
|
|
|
4f1b20 |
cctx.drvflags |= SLBT_DRIVER_ANTI_PIC;
|
|
|
4f1b20 |
break;
|
|
|
9c25c7 |
|
|
|
9c25c7 |
case TAG_SHARED:
|
|
|
9c25c7 |
cctx.drvflags |= SLBT_DRIVER_SHARED;
|
|
|
9c25c7 |
break;
|
|
|
9c25c7 |
|
|
|
9c25c7 |
case TAG_STATIC:
|
|
|
9c25c7 |
cctx.drvflags |= SLBT_DRIVER_STATIC;
|
|
|
9c25c7 |
break;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
} else
|
|
|
9ca8c4 |
nunits++;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (!(ctx = slbt_driver_ctx_alloc(meta,&cctx,nunits)))
|
|
|
9ca8c4 |
return slbt_get_driver_ctx_fail(meta);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
ctx->ctx.program = program;
|
|
|
9ca8c4 |
ctx->ctx.cctx = &ctx->cctx;
|
|
|
56cab3 |
ctx->targv = sargv.targv;
|
|
|
56cab3 |
ctx->cargv = sargv.cargv;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
*pctx = &ctx->ctx;
|
|
|
9ca8c4 |
return SLBT_OK;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
int slbt_create_driver_ctx(
|
|
|
9ca8c4 |
const struct slbt_common_ctx * cctx,
|
|
|
9ca8c4 |
struct slbt_driver_ctx ** pctx)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
struct argv_meta * meta;
|
|
|
9ca8c4 |
struct slbt_driver_ctx_impl * ctx;
|
|
|
9ca8c4 |
char * argv[] = {"slibtool_driver",0};
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (!(meta = argv_get(argv,slbt_default_options,0)))
|
|
|
9ca8c4 |
return -1;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (!(ctx = slbt_driver_ctx_alloc(meta,cctx,0)))
|
|
|
9ca8c4 |
return slbt_get_driver_ctx_fail(0);
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
ctx->ctx.cctx = &ctx->cctx;
|
|
|
9ca8c4 |
memcpy(&ctx->cctx,cctx,sizeof(*cctx));
|
|
|
9ca8c4 |
*pctx = &ctx->ctx;
|
|
|
9ca8c4 |
return SLBT_OK;
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
static void slbt_free_driver_ctx_impl(struct slbt_driver_ctx_alloc * ictx)
|
|
|
9ca8c4 |
{
|
|
|
56cab3 |
if (ictx->ctx.targv)
|
|
|
56cab3 |
free(ictx->ctx.targv);
|
|
|
56cab3 |
|
|
|
9ca8c4 |
argv_free(ictx->meta);
|
|
|
9ca8c4 |
free(ictx);
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
void slbt_free_driver_ctx(struct slbt_driver_ctx * ctx)
|
|
|
9ca8c4 |
{
|
|
|
9ca8c4 |
struct slbt_driver_ctx_alloc * ictx;
|
|
|
9ca8c4 |
uintptr_t addr;
|
|
|
9ca8c4 |
|
|
|
9ca8c4 |
if (ctx) {
|
|
|
9ca8c4 |
addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
|
|
|
9ca8c4 |
addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
|
|
|
9ca8c4 |
ictx = (struct slbt_driver_ctx_alloc *)addr;
|
|
|
9ca8c4 |
slbt_free_driver_ctx_impl(ictx);
|
|
|
9ca8c4 |
}
|
|
|
9ca8c4 |
}
|