summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/driver/slbt_amain.c7
-rw-r--r--src/driver/slbt_driver_ctx.c80
-rw-r--r--src/internal/slibtool_ar_impl.h12
-rw-r--r--src/logic/slbt_exec_ar.c173
-rw-r--r--src/skin/slbt_skin_ar.c9
-rw-r--r--src/skin/slbt_skin_default.c2
6 files changed, 267 insertions, 16 deletions
diff --git a/src/driver/slbt_amain.c b/src/driver/slbt_amain.c
index eff2b45..1cc1c07 100644
--- a/src/driver/slbt_amain.c
+++ b/src/driver/slbt_amain.c
@@ -79,6 +79,9 @@ static void slbt_perform_driver_actions(struct slbt_driver_ctx * dctx)
if (dctx->cctx->mode == SLBT_MODE_UNINSTALL)
slbt_exec_uninstall(dctx,0);
+
+ if (dctx->cctx->mode == SLBT_MODE_AR)
+ slbt_exec_ar(dctx,0);
}
static int slbt_exit(struct slbt_driver_ctx * dctx, int ret)
@@ -122,6 +125,10 @@ int slbt_main(char ** argv, char ** envp, const struct slbt_fd_ctx * fdctx)
else if (!(strcmp(dash,"static")))
flags = SLBT_DRIVER_FLAGS | SLBT_DRIVER_DISABLE_SHARED;
+ /* internal ar mode */
+ else if (!(strcmp(dash,"ar")))
+ flags |= SLBT_DRIVER_MODE_AR;
+
/* debug */
if (!(strcmp(program,"dlibtool")))
flags |= SLBT_DRIVER_DEBUG;
diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c
index cd89a00..458f9c8 100644
--- a/src/driver/slbt_driver_ctx.c
+++ b/src/driver/slbt_driver_ctx.c
@@ -21,6 +21,7 @@
#include "slibtool_objlist_impl.h"
#include "slibtool_errinfo_impl.h"
#include "slibtool_lconf_impl.h"
+#include "slibtool_ar_impl.h"
#include "argv/argv.h"
extern char ** environ;
@@ -309,6 +310,7 @@ static int slbt_split_argv(
char * dst;
bool flast;
bool fcopy;
+ bool altmode;
size_t size;
const char * base;
struct argv_meta * meta;
@@ -321,6 +323,7 @@ static int slbt_split_argv(
struct argv_entry * features;
struct argv_entry * ccwrap;
struct argv_entry * dumpmachine;
+ struct argv_entry * aropt;
const struct argv_option ** popt;
const struct argv_option ** optout;
const struct argv_option * optv[SLBT_OPTV_ELEMENTS];
@@ -331,9 +334,14 @@ static int slbt_split_argv(
program = argv_program_name(argv[0]);
/* missing arguments? */
- argv_optv_init(slbt_default_options,optv);
+ if ((altmode = (flags & SLBT_DRIVER_MODE_AR))) {
+ argv_optv_init(slbt_ar_options,optv);
+ } else {
+ argv_optv_init(slbt_default_options,optv);
+ }
+
- if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
+ if (!argv[1] && !altmode && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
return slbt_driver_usage(
fderr,program,
0,optv,0,sargv,0,
@@ -343,7 +351,7 @@ static int slbt_split_argv(
argv_scan(argv,optv,&ctx,0);
/* invalid slibtool arguments? */
- if (ctx.erridx && !ctx.unitidx) {
+ if (ctx.erridx && !ctx.unitidx && altmode) {
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
argv_get(
argv,optv,
@@ -352,6 +360,10 @@ static int slbt_split_argv(
return -1;
}
+ /* error possibly due to an altmode argument? */
+ if (ctx.erridx && !ctx.unitidx)
+ ctx.unitidx = ctx.erridx;
+
/* obtain slibtool's own arguments */
if (ctx.unitidx) {
compiler = argv[ctx.unitidx];
@@ -364,7 +376,7 @@ static int slbt_split_argv(
}
/* missing all of --mode, --help, --version, --config, --dumpmachine, --features, and --finish? */
- mode = help = version = config = finish = features = ccwrap = dumpmachine = 0;
+ mode = help = version = config = finish = features = ccwrap = dumpmachine = aropt = 0;
for (entry=meta->entries; entry->fopt; entry++)
if (entry->tag == TAG_MODE)
@@ -384,9 +396,24 @@ static int slbt_split_argv(
else if (entry->tag == TAG_DUMPMACHINE)
dumpmachine = entry;
+ /* alternate execusion mode? */
+ if (!altmode && mode && !strcmp(mode->arg,"ar"))
+ aropt = mode;
+
+ /* release temporary argv meta context */
argv_free(meta);
- if (!mode && !help && !version && !config && !finish && !features && !dumpmachine) {
+ /* error not due to an altmode argument? */
+ if (!aropt && ctx.erridx && (ctx.erridx == ctx.unitidx)) {
+ if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
+ argv_get(
+ argv,optv,
+ slbt_argv_flags(flags),
+ fderr);
+ return -1;
+ }
+
+ if (!mode && !help && !version && !config && !finish && !features && !dumpmachine && !altmode) {
slbt_dprintf(fderr,
"%s: error: --mode must be specified.\n",
program);
@@ -394,7 +421,7 @@ static int slbt_split_argv(
}
/* missing compiler? */
- if (!ctx.unitidx && !help && !version && !finish && !features && !dumpmachine) {
+ if (!ctx.unitidx && !help && !version && !finish && !features && !dumpmachine && !altmode && !aropt) {
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
slbt_dprintf(fderr,
"%s: error: <compiler> is missing.\n",
@@ -423,7 +450,7 @@ static int slbt_split_argv(
csysroot = 0;
for (i=0,flast=false,dargv=sargv->dargv,dst=sargv->dargs; i<argc; i++) {
- if ((fcopy = flast)) {
+ if ((fcopy = (flast || altmode || aropt))) {
(void)0;
} else if (!strcmp(argv[i],"--")) {
@@ -544,15 +571,19 @@ static int slbt_split_argv(
if (ctx.unitidx) {
(void)0;
- } else if (help || version || features || dumpmachine) {
+ } else if (help || version || features || dumpmachine || altmode) {
for (i=0; i<argc; i++)
sargv->targv[i] = argv[i];
- sargv->cargv = slbt_default_cargv;
+ sargv->cargv = altmode ? sargv->targv : slbt_default_cargv;
return 0;
}
+ /* --mode=ar and no ar-specific arguments? */
+ if (aropt && !ctx.unitidx)
+ ctx.unitidx = argc;
+
/* split vectors: slibtool's own options */
for (i=0; i<ctx.unitidx; i++)
sargv->targv[i] = argv[i];
@@ -562,7 +593,7 @@ static int slbt_split_argv(
cargv = sargv->cargv;
/* known wrappers */
- if (ctx.unitidx && !ccwrap) {
+ if (ctx.unitidx && !ccwrap && !aropt) {
if ((base = strrchr(argv[i],'/')))
base++;
else if ((base = strrchr(argv[i],'\\')))
@@ -580,11 +611,17 @@ static int slbt_split_argv(
}
/* split vectors: legacy mixture */
- for (optout=optv; optout[0]->tag != TAG_OUTPUT; optout++)
+ for (optout=optv; optout[0] && (optout[0]->tag != TAG_OUTPUT); optout++)
(void)0;
- /* compiler */
- *cargv++ = argv[i++];
+ /* compiler, archiver, etc. */
+ if (altmode) {
+ i = 0;
+ } else if (aropt) {
+ *cargv++ = argv[0];
+ } else {
+ *cargv++ = argv[i++];
+ }
/* sysroot */
if (csysroot)
@@ -592,7 +629,10 @@ static int slbt_split_argv(
/* remaining vector */
for (objlistp=objlistv; i<argc; i++) {
- if (argv[i][0] != '-') {
+ if (aropt && (i >= ctx.unitidx)) {
+ *cargv++ = argv[i];
+
+ } else if (argv[i][0] != '-') {
if (argv[i+1] && (argv[i+1][0] == '+')
&& (argv[i+1][1] == '=')
&& (argv[i+1][2] == 0)
@@ -1433,7 +1473,10 @@ int slbt_get_driver_ctx(
const char * lconf;
uint64_t lflags;
- argv_optv_init(slbt_default_options,optv);
+ if (flags & SLBT_DRIVER_MODE_AR)
+ argv_optv_init(slbt_ar_options,optv);
+ else
+ argv_optv_init(slbt_default_options,optv);
if (!fdctx)
fdctx = &slbt_default_fdctx;
@@ -1466,6 +1509,9 @@ int slbt_get_driver_ctx(
memset(&cctx,0,sizeof(cctx));
+ if (flags & SLBT_DRIVER_MODE_AR)
+ cctx.mode = SLBT_MODE_AR;
+
/* shared and static objects: enable by default, disable by ~switch */
cctx.drvflags = flags | SLBT_DRIVER_SHARED | SLBT_DRIVER_STATIC;
@@ -1488,6 +1534,7 @@ int slbt_get_driver_ctx(
switch (cctx.mode) {
case SLBT_MODE_INSTALL:
case SLBT_MODE_UNINSTALL:
+ case SLBT_MODE_AR:
break;
default:
@@ -1532,6 +1579,9 @@ int slbt_get_driver_ctx(
else if (!strcmp("uninstall",entry->arg))
cctx.mode = SLBT_MODE_UNINSTALL;
+
+ else if (!strcmp("ar",entry->arg))
+ cctx.mode = SLBT_MODE_AR;
break;
case TAG_FINISH:
diff --git a/src/internal/slibtool_ar_impl.h b/src/internal/slibtool_ar_impl.h
new file mode 100644
index 0000000..3dfabe7
--- /dev/null
+++ b/src/internal/slibtool_ar_impl.h
@@ -0,0 +1,12 @@
+#ifndef SLIBTOOL_AR_IMPL_H
+#define SLIBTOOL_AR_IMPL_H
+
+#include "argv/argv.h"
+
+extern const struct argv_option slbt_ar_options[];
+
+enum ar_tags {
+ TAG_AR_HELP,
+};
+
+#endif
diff --git a/src/logic/slbt_exec_ar.c b/src/logic/slbt_exec_ar.c
new file mode 100644
index 0000000..7c15d8b
--- /dev/null
+++ b/src/logic/slbt_exec_ar.c
@@ -0,0 +1,173 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#define ARGV_DRIVER
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+#include "slibtool_ar_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "argv/argv.h"
+
+struct slbt_archive_ctx;
+
+static int slbt_ar_usage(
+ int fdout,
+ const char * program,
+ const char * arg,
+ const struct argv_option ** optv,
+ struct argv_meta * meta,
+ struct slbt_exec_ctx * ectx,
+ int noclr)
+{
+ char header[512];
+ bool armode;
+ const char * dash;
+
+ armode = (dash = strrchr(program,'-'))
+ && !strcmp(++dash,"ar");
+
+ snprintf(header,sizeof(header),
+ "Usage: %s%s [options] [ARCHIVE-FILE] [ARCHIVE_FILE] ...\n"
+ "Options:\n",
+ program,
+ armode ? "" : " --mode=ar");
+
+ switch (noclr) {
+ case 0:
+ argv_usage(fdout,header,optv,arg);
+ break;
+
+ default:
+ argv_usage_plain(fdout,header,optv,arg);
+ break;
+ }
+
+ if (ectx)
+ slbt_free_exec_ctx(ectx);
+
+ argv_free(meta);
+
+ return SLBT_USAGE;
+}
+
+static int slbt_exec_ar_fail(
+ struct slbt_exec_ctx * actx,
+ struct argv_meta * meta,
+ int ret)
+{
+ argv_free(meta);
+ slbt_free_exec_ctx(actx);
+ return ret;
+}
+
+int slbt_exec_ar(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx)
+{
+ int ret;
+ int fdout;
+ char ** argv;
+ char ** iargv;
+ struct slbt_archive_ctx ** arctxv;
+ const char ** unitv;
+ const char ** unitp;
+ size_t nunits;
+ struct slbt_exec_ctx * actx;
+ struct argv_meta * meta;
+ struct argv_entry * entry;
+ const struct argv_option * optv[SLBT_OPTV_ELEMENTS];
+
+ /* context */
+ if (ectx)
+ actx = 0;
+ else if ((ret = slbt_get_exec_ctx(dctx,&ectx)))
+ return ret;
+ else
+ actx = ectx;
+
+ /* initial state, ar mode skin */
+ slbt_reset_arguments(ectx);
+ slbt_disable_placeholders(ectx);
+ iargv = ectx->cargv;
+ fdout = slbt_driver_fdout(dctx);
+
+ /* missing arguments? */
+ argv_optv_init(slbt_ar_options,optv);
+
+ if (!iargv[1] && (dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_USAGE))
+ return slbt_ar_usage(
+ fdout,
+ dctx->program,
+ 0,optv,0,actx,
+ dctx->cctx->drvflags & SLBT_DRIVER_ANNOTATE_NEVER);
+
+ /* <ar> argv meta */
+ if (!(meta = argv_get(
+ iargv,optv,
+ dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS
+ ? ARGV_VERBOSITY_ERRORS
+ : ARGV_VERBOSITY_NONE,
+ fdout)))
+ return slbt_exec_ar_fail(
+ actx,meta,
+ SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_AR_FAIL));
+
+ /* dest, alternate argument vector options */
+ argv = ectx->altv;
+ *argv++ = iargv[0];
+ nunits = 0;
+
+ for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
+ if (entry->fopt) {
+ switch (entry->tag) {
+ case TAG_AR_HELP:
+ slbt_ar_usage(
+ fdout,
+ dctx->program,
+ 0,optv,0,ectx,
+ dctx->cctx->drvflags
+ & SLBT_DRIVER_ANNOTATE_NEVER);
+ return 0;
+ }
+
+ if (entry->fval) {
+ *argv++ = (char *)entry->arg;
+ }
+ } else {
+ nunits++;
+ };
+ }
+
+ /* archive vector allocation */
+ if (!(arctxv = calloc(nunits+1,sizeof(struct slbt_archive_ctx *))))
+ return slbt_exec_ar_fail(
+ actx,meta,
+ SLBT_SYSTEM_ERROR(dctx,0));
+
+ /* unit vector allocation */
+ if (!(unitv = calloc(nunits+1,sizeof(const char *)))) {
+ free (arctxv);
+
+ return slbt_exec_ar_fail(
+ actx,meta,
+ SLBT_SYSTEM_ERROR(dctx,0));
+ }
+
+ /* unit vector initialization */
+ for (entry=meta->entries,unitp=unitv; entry->fopt || entry->arg; entry++)
+ if (!entry->fopt)
+ *unitp++ = entry->arg;
+
+ /* all done */
+ free(unitv);
+ free(arctxv);
+
+ argv_free(meta);
+ slbt_free_exec_ctx(actx);
+
+ return 0;
+}
diff --git a/src/skin/slbt_skin_ar.c b/src/skin/slbt_skin_ar.c
new file mode 100644
index 0000000..4376421
--- /dev/null
+++ b/src/skin/slbt_skin_ar.c
@@ -0,0 +1,9 @@
+#include "slibtool_ar_impl.h"
+#include "argv/argv.h"
+
+const struct argv_option slbt_ar_options[] = {
+ {"help", 'h',TAG_AR_HELP,ARGV_OPTARG_NONE,0,0,0,
+ "display ar mode help"},
+
+ {0,0,0,0,0,0,0,0}
+};
diff --git a/src/skin/slbt_skin_default.c b/src/skin/slbt_skin_default.c
index 5c4d67d..9dd372e 100644
--- a/src/skin/slbt_skin_default.c
+++ b/src/skin/slbt_skin_default.c
@@ -19,7 +19,7 @@ const struct argv_option slbt_default_options[] = {
{"mode", 0,TAG_MODE,ARGV_OPTARG_REQUIRED,0,
"clean|compile|execute|finish"
- "|install|link|uninstall",0,
+ "|install|link|uninstall|ar",0,
"set the execution mode, where <mode> "
"is one of {%s}. of the above modes, "
"'finish' is not needed and is therefore "