From 1ed0177f9a16f6da5d6d0c89bc0d8c522a9a848f Mon Sep 17 00:00:00 2001 From: midipix Date: Fri, 9 Feb 2024 19:51:11 +0000 Subject: driver: move slbt_split_argv() to its own translation unit. --- src/driver/slbt_split_argv.c | 509 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 src/driver/slbt_split_argv.c (limited to 'src/driver/slbt_split_argv.c') diff --git a/src/driver/slbt_split_argv.c b/src/driver/slbt_split_argv.c new file mode 100644 index 0000000..8ec189b --- /dev/null +++ b/src/driver/slbt_split_argv.c @@ -0,0 +1,509 @@ +/*******************************************************************/ +/* slibtool: a skinny libtool implementation, written in C */ +/* Copyright (C) 2016--2021 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include +#include +#include +#include +#include + +#define ARGV_DRIVER + +#include +#include "slibtool_version.h" +#include "slibtool_driver_impl.h" +#include "slibtool_objlist_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_ar_impl.h" +#include "argv/argv.h" + +static char * slbt_default_cargv[] = {"cc",0}; + +int slbt_split_argv( + char ** argv, + uint64_t flags, + struct slbt_split_vector * sargv, + struct slbt_obj_list ** aobjlistv, + int fderr, + int fdcwd) +{ + int i; + int argc; + int objc; + const char * program; + char * compiler; + char * csysroot; + char ** dargv; + char ** targv; + char ** cargv; + char ** objp; + struct slbt_obj_list * objlistv; + struct slbt_obj_list * objlistp; + char * dst; + bool flast; + bool fcopy; + bool altmode; + size_t size; + const char * base; + struct argv_meta * meta; + struct argv_entry * entry; + struct argv_entry * mode; + struct argv_entry * help; + struct argv_entry * version; + struct argv_entry * config; + struct argv_entry * finish; + 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]; + struct argv_ctx ctx = {ARGV_VERBOSITY_NONE, + ARGV_MODE_SCAN, + 0,0,0,0,0,0,0}; + + program = argv_program_name(argv[0]); + + /* missing arguments? */ + 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] && !altmode && (flags & SLBT_DRIVER_VERBOSITY_USAGE)) + return slbt_driver_usage( + fderr,program, + 0,optv,0,sargv,0, + !!getenv("NO_COLOR")); + + /* initial argv scan: ... --mode=xxx ... ... */ + argv_scan(argv,optv,&ctx,0); + + /* invalid slibtool arguments? */ + if (ctx.erridx && !ctx.unitidx && altmode) { + if (flags & SLBT_DRIVER_VERBOSITY_ERRORS) + argv_get( + argv,optv, + slbt_argv_flags(flags), + fderr); + 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]; + argv[ctx.unitidx] = 0; + + meta = argv_get(argv,optv,ARGV_VERBOSITY_NONE,fderr); + argv[ctx.unitidx] = compiler; + } else { + meta = argv_get(argv,optv,ARGV_VERBOSITY_NONE,fderr); + } + + if (!meta) { + if (flags & SLBT_DRIVER_VERBOSITY_ERRORS) + argv_get( + argv,optv, + slbt_argv_flags(flags), + fderr); + return -1; + } + + /* missing all of --mode, --help, --version, --config, --dumpmachine, --features, and --finish? */ + mode = help = version = config = finish = features = ccwrap = dumpmachine = aropt = 0; + + for (entry=meta->entries; entry->fopt; entry++) + if (entry->tag == TAG_MODE) + mode = entry; + else if (entry->tag == TAG_HELP) + help = entry; + else if (entry->tag == TAG_VERSION) + version = entry; + else if (entry->tag == TAG_CONFIG) + config = entry; + else if (entry->tag == TAG_FINISH) + finish = entry; + else if (entry->tag == TAG_FEATURES) + features = entry; + else if (entry->tag == TAG_CCWRAP) + ccwrap = entry; + 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); + + /* 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); + return -1; + } + + /* missing compiler? */ + if (!ctx.unitidx && !help && !version && !finish && !features && !dumpmachine && !altmode && !aropt) { + if (flags & SLBT_DRIVER_VERBOSITY_ERRORS) + slbt_dprintf(fderr, + "%s: error: is missing.\n", + program); + return -1; + } + + /* clone and normalize the argv vector (-l, --library) */ + for (argc=0,size=0,dargv=argv; *dargv; argc++,dargv++) + size += strlen(*dargv) + 1; + + if (!(sargv->dargv = calloc(argc+1,sizeof(char *)))) + return -1; + + else if (!(sargv->dargs = calloc(1,size+1))) + return -1; + + else if (!(*aobjlistv = calloc(argc,sizeof(**aobjlistv)))) { + free(sargv->dargv); + free(sargv->dargs); + return -1; + } + + objlistv = *aobjlistv; + objlistp = objlistv; + csysroot = 0; + + for (i=0,flast=false,dargv=sargv->dargv,dst=sargv->dargs; iname = dst; + objlistp++; + fcopy = true; + + } else { + fcopy = true; + } + + if (fcopy) { + *dargv++ = dst; + strcpy(dst,argv[i]); + dst += strlen(dst)+1; + } + } + + /* update argc,argv */ + argc = dargv - sargv->dargv; + argv = sargv->dargv; + + /* iterate through the object list vector: map, parse, store */ + for (objlistp=objlistv; objlistp->name; objlistp++) + if (slbt_objlist_read(fdcwd,objlistp) < 0) + return -1; + + for (objc=0,objlistp=objlistv; objlistp->name; objlistp++) + objc += objlistp->objc; + + /* allocate split vectors, account for cargv's added sysroot */ + if ((sargv->targv = calloc(objc + 2*(argc+3),sizeof(char *)))) + sargv->cargv = sargv->targv + argc + 2; + else + return -1; + + /* --features and no ? */ + if (ctx.unitidx) { + (void)0; + + } else if (help || version || features || dumpmachine || altmode) { + for (i=0; itargv[i] = argv[i]; + + 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; itargv[i] = argv[i]; + + /* split vector marks */ + targv = sargv->targv + i; + cargv = sargv->cargv; + + /* known wrappers */ + if (ctx.unitidx && !ccwrap && !aropt) { + if ((base = strrchr(argv[i],'/'))) + base++; + else if ((base = strrchr(argv[i],'\\'))) + base++; + else + base = argv[i]; + + if (!strcmp(base,"ccache") + || !strcmp(base,"distcc") + || !strcmp(base,"compiler") + || !strcmp(base,"purify")) { + *targv++ = "--ccwrap"; + *targv++ = argv[i++]; + } + } + + /* split vectors: legacy mixture */ + for (optout=optv; optout[0] && (optout[0]->tag != TAG_OUTPUT); optout++) + (void)0; + + /* compiler, archiver, etc. */ + if (altmode) { + i = 0; + } else if (aropt) { + *cargv++ = argv[0]; + } else { + *cargv++ = argv[i++]; + } + + /* sysroot */ + if (csysroot) + *cargv++ = csysroot; + + /* remaining vector */ + for (objlistp=objlistv; 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) + && !(strrchr(argv[i],'.'))) + /* libfoo_la_LDFLAGS += -Wl,.... */ + i++; + else + *cargv++ = argv[i]; + + /* must capture -objectlist prior to -o */ + } else if (!(strcmp("objectlist",&argv[i][1]))) { + for (objp=objlistp->objv; *objp; objp++) + *cargv++ = *objp; + + i++; + objlistp++; + + } else if (argv[i][1] == 'o') { + *targv++ = argv[i]; + + if (argv[i][2] == 0) + *targv++ = argv[++i]; + } else if ((argv[i][1] == 'W') && (argv[i][2] == 'c')) { + *cargv++ = argv[i]; + + } else if (!(strcmp("Xcompiler",&argv[i][1]))) { + *cargv++ = argv[++i]; + + } else if (!(strcmp("XCClinker",&argv[i][1]))) { + *cargv++ = argv[++i]; + + } else if ((argv[i][1] == 'R') && (argv[i][2] == 0)) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (argv[i][1] == 'R') { + *targv++ = argv[i]; + + } else if (!(strncmp("-target=",&argv[i][1],8))) { + *cargv++ = argv[i]; + *targv++ = argv[i]; + + } else if (!(strcmp("-target",&argv[i][1]))) { + *cargv++ = argv[i]; + *targv++ = argv[i++]; + + *cargv++ = argv[i]; + *targv++ = argv[i]; + + } else if (!(strcmp("target",&argv[i][1]))) { + *cargv++ = argv[i]; + *targv++ = argv[i++]; + + *cargv++ = argv[i]; + *targv++ = argv[i]; + + } else if (!(strncmp("-sysroot=",&argv[i][1],9))) { + *cargv++ = argv[i]; + *targv++ = argv[i]; + + } else if (!(strcmp("-sysroot",&argv[i][1]))) { + *cargv++ = argv[i]; + *targv++ = argv[i++]; + + *cargv++ = argv[i]; + *targv++ = argv[i]; + + } else if (!(strcmp("bindir",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("shrext",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("rpath",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("release",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("dlopen",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("weak",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("static-libtool-libs",&argv[i][1]))) { + *targv++ = argv[i]; + + } else if (!(strcmp("export-dynamic",&argv[i][1]))) { + *targv++ = argv[i]; + + } else if (!(strcmp("export-symbols",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("export-symbols-regex",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("version-info",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("version-number",&argv[i][1]))) { + *targv++ = argv[i++]; + *targv++ = argv[i]; + + } else if (!(strcmp("dlpreopen",&argv[i][1]))) { + (void)0; + + } else { + for (popt=optout; popt[0] && popt[0]->long_name; popt++) + if (!(strcmp(popt[0]->long_name,&argv[i][1]))) + break; + + if (popt[0] && popt[0]->long_name) + *targv++ = argv[i]; + else + *cargv++ = argv[i]; + } + } + + return 0; +} -- cgit v1.2.3