summaryrefslogtreecommitdiff
path: root/src/logic
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic')
-rw-r--r--src/logic/slbt_exec_ar.c173
1 files changed, 173 insertions, 0 deletions
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;
+}