diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c index 40be65f..0abbf85 100644 --- a/src/driver/slbt_driver_ctx.c +++ b/src/driver/slbt_driver_ctx.c @@ -128,7 +128,7 @@ static uint32_t slbt_argv_flags(uint32_t flags) static int slbt_driver_usage( const char * program, const char * arg, - const struct argv_option * options, + const struct argv_option ** optv, struct argv_meta * meta) { char header[512]; @@ -137,7 +137,7 @@ static int slbt_driver_usage( "Usage: %s [options] ...\n" "Options:\n", program); - argv_usage(stdout,header,options,arg); + argv_usage(stdout,header,optv,arg); argv_free(meta); return SLBT_USAGE; @@ -191,8 +191,9 @@ static int slbt_split_argv( struct argv_entry * mode; struct argv_entry * config; struct argv_entry * finish; - const struct argv_option * option; - const struct argv_option * options = slbt_default_options; + 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}; @@ -200,17 +201,19 @@ static int slbt_split_argv( program = argv_program_name(argv[0]); /* missing arguments? */ + argv_optv_init(slbt_default_options,optv); + if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE)) - return slbt_driver_usage(program,0,options,0); + return slbt_driver_usage(program,0,optv,0); /* initial argv scan: ... --mode=xxx ... ... */ - argv_scan(argv,options,&ctx,0); + argv_scan(argv,optv,&ctx,0); /* invalid slibtool arguments? */ if (ctx.erridx && !ctx.unitidx) { if (flags & SLBT_DRIVER_VERBOSITY_ERRORS) argv_get( - argv,options, + argv,optv, slbt_argv_flags(flags)); return -1; } @@ -219,7 +222,7 @@ static int slbt_split_argv( compiler = argv[ctx.unitidx]; argv[ctx.unitidx] = 0; - meta = argv_get(argv,options,ARGV_VERBOSITY_NONE); + meta = argv_get(argv,optv,ARGV_VERBOSITY_NONE); argv[ctx.unitidx] = compiler; /* missing all of --mode, --config, and --finish? */ @@ -263,9 +266,8 @@ static int slbt_split_argv( sargv->targv[i] = argv[i]; /* split vectors: legacy mixture */ - options = option_from_tag( - slbt_default_options, - TAG_OUTPUT); + for (optout=optv; optout[0]->tag != TAG_OUTPUT; optout++) + (void)0; targv = sargv->targv + i; cargv = sargv->cargv; @@ -345,11 +347,11 @@ static int slbt_split_argv( *targv++ = argv[i]; } else { - for (option=options; option->long_name; option++) - if (!(strcmp(option->long_name,&argv[i][1]))) + for (popt=optout; popt[0] && popt[0]->long_name; popt++) + if (!(strcmp(popt[0]->long_name,&argv[i][1]))) break; - if (option->long_name) + if (popt[0] && popt[0]->long_name) *targv++ = argv[i]; else *cargv++ = argv[i]; @@ -797,17 +799,17 @@ int slbt_get_driver_ctx( struct slbt_split_vector sargv; struct slbt_driver_ctx_impl * ctx; struct slbt_common_ctx cctx; - const struct argv_option * options; + const struct argv_option * optv[SLBT_OPTV_ELEMENTS]; struct argv_meta * meta; struct argv_entry * entry; const char * program; - options = slbt_default_options; + argv_optv_init(slbt_default_options,optv); if (slbt_split_argv(argv,flags,&sargv)) return -1; - if (!(meta = argv_get(sargv.targv,options,slbt_argv_flags(flags)))) + if (!(meta = argv_get(sargv.targv,optv,slbt_argv_flags(flags)))) return -1; program = argv_program_name(argv[0]); @@ -826,7 +828,7 @@ int slbt_get_driver_ctx( case TAG_HELP: case TAG_HELP_ALL: if (flags & SLBT_DRIVER_VERBOSITY_USAGE) - return slbt_driver_usage(program,entry->arg,options,meta); + return slbt_driver_usage(program,entry->arg,optv,meta); case TAG_VERSION: cctx.drvflags |= SLBT_DRIVER_VERSION; @@ -1122,11 +1124,14 @@ int slbt_create_driver_ctx( const struct slbt_common_ctx * cctx, struct slbt_driver_ctx ** pctx) { + const struct argv_option * optv[SLBT_OPTV_ELEMENTS]; struct argv_meta * meta; struct slbt_driver_ctx_impl * ctx; char * argv[] = {"slibtool_driver",0}; - if (!(meta = argv_get(argv,slbt_default_options,0))) + argv_optv_init(slbt_default_options,optv); + + if (!(meta = argv_get(argv,optv,0))) return -1; if (!(ctx = slbt_driver_ctx_alloc(meta,cctx))) diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h index ca1ceba..60806a2 100644 --- a/src/internal/argv/argv.h +++ b/src/internal/argv/argv.h @@ -139,17 +139,21 @@ struct argv_ctx { #ifdef ARGV_DRIVER +static int argv_optv_init( + const struct argv_option[], + const struct argv_option **); + static const char * argv_program_name(const char *); static void argv_usage( FILE *, const char * header, - const struct argv_option[], + const struct argv_option **, const char * mode); static struct argv_meta * argv_get( char **, - const struct argv_option[], + const struct argv_option **, int flags); static void argv_free(struct argv_meta *); @@ -161,14 +165,30 @@ static void argv_free(struct argv_meta *); /* implementation of static functions */ /*------------------------------------*/ +static int argv_optv_init( + const struct argv_option options[], + const struct argv_option ** optv) +{ + const struct argv_option * option; + int i; + + for (option=options,i=0; option->long_name || option->short_name; option++) + optv[i++] = option; + + optv[i] = 0; + return i; +} + static const struct argv_option * argv_short_option( const char * ch, - const struct argv_option options[], + const struct argv_option ** optv, struct argv_entry * entry) { const struct argv_option * option; - for (option=options; option->long_name || option->short_name; option++) { + for (; *optv; optv++) { + option = *optv; + if (option->short_name == *ch) { entry->tag = option->tag; entry->fopt = true; @@ -181,15 +201,16 @@ static const struct argv_option * argv_short_option( static const struct argv_option * argv_long_option( const char * ch, - const struct argv_option options[], + const struct argv_option ** optv, struct argv_entry * entry) { const struct argv_option * option; const char * arg; size_t len; - for (option=options; option->long_name || option->short_name; option++) { - len = option->long_name ? strlen(option->long_name) : 0; + for (; *optv; optv++) { + option = *optv; + len = option->long_name ? strlen(option->long_name) : 0; if (len && !(strncmp(option->long_name,ch,len))) { arg = ch + len; @@ -226,7 +247,7 @@ static inline bool is_last_option(const char * arg) static inline bool is_hybrid_option( const char * arg, - const struct argv_option options[]) + const struct argv_option ** optv) { const struct argv_option * option; struct argv_entry entry; @@ -234,11 +255,11 @@ static inline bool is_hybrid_option( if (!is_short_option(arg)) return false; - if (!(option = argv_long_option(++arg,options,&entry))) + if (!(option = argv_long_option(++arg,optv,&entry))) return false; if (!(option->flags & ARGV_OPTION_HYBRID_SWITCH)) - if (argv_short_option(arg,options,&entry)) + if (argv_short_option(arg,optv,&entry)) return false; return true; @@ -265,20 +286,18 @@ static inline bool is_arg_in_paradigm(const char * arg, const char * paradigm) } static inline const struct argv_option * option_from_tag( - const struct argv_option options[], + const struct argv_option ** optv, int tag) { - const struct argv_option * option; - - for (option=options; option->short_name || option->long_name; option++) - if (option->tag == tag) - return option; + for (; *optv; optv++) + if (optv[0]->tag == tag) + return optv[0]; return 0; } static void argv_scan( char ** argv, - const struct argv_option options[], + const struct argv_option ** optv, struct argv_ctx * ctx, struct argv_meta * meta) { @@ -316,14 +335,14 @@ static void argv_scan( else if (is_last_option(ch)) fnoscan = true; - else if (!fshort && is_hybrid_option(ch,options)) + else if (!fshort && is_hybrid_option(ch,optv)) fhybrid = true; if (!fnoscan && !fhybrid && (fshort || is_short_option(ch))) { if (!fshort) ch++; - if ((option = argv_short_option(ch,options,&entry))) { + if ((option = argv_short_option(ch,optv,&entry))) { if (ch[1]) { ch++; fnext = false; @@ -370,7 +389,7 @@ static void argv_scan( } else if (!fnoscan && (fhybrid || is_long_option(ch))) { ch += (fhybrid ? 1 : 2); - if ((option = argv_long_option(ch,options,&entry))) { + if ((option = argv_long_option(ch,optv,&entry))) { val = ch + strlen(option->long_name); /* val[0] is either '=' (or ',') or '\0' */ @@ -584,7 +603,7 @@ static void argv_show_error(struct argv_ctx * ctx) } static void argv_show_status( - const struct argv_option options[], + const struct argv_option ** optv, struct argv_ctx * ctx, struct argv_meta * meta) { @@ -610,7 +629,7 @@ static void argv_show_status( fputs("\n\nparsed entries:\n",stderr); for (entry=meta->entries; entry->arg || entry->fopt; entry++) if (entry->fopt) { - option = option_from_tag(options,entry->tag); + option = option_from_tag(optv,entry->tag); short_name[0] = option->short_name; if (entry->fval) @@ -683,13 +702,13 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx) static struct argv_meta * argv_get( char * argv[], - const struct argv_option options[], + const struct argv_option ** optv, int flags) { struct argv_meta * meta; struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0}; - argv_scan(argv,options,&ctx,0); + argv_scan(argv,optv,&ctx,0); if (ctx.errcode != ARGV_ERROR_OK) { ctx.program = argv_program_name(argv[0]); @@ -704,7 +723,7 @@ static struct argv_meta * argv_get( return 0; ctx.mode = ARGV_MODE_COPY; - argv_scan(meta->argv,options,&ctx,meta); + argv_scan(meta->argv,optv,&ctx,meta); if (ctx.errcode != ARGV_ERROR_OK) { ctx.program = argv[0]; @@ -716,7 +735,7 @@ static struct argv_meta * argv_get( } if (ctx.flags & ARGV_VERBOSITY_STATUS) - argv_show_status(options,&ctx,meta); + argv_show_status(optv,&ctx,meta); return meta; } @@ -736,9 +755,10 @@ static void argv_free(struct argv_meta * xmeta) static void argv_usage( FILE * file, const char * header, - const struct argv_option options[], + const struct argv_option ** options, const char * mode) { + const struct argv_option ** optv; const struct argv_option * option; bool fshort,flong,fboth; size_t len,optlen,desclen; @@ -771,10 +791,9 @@ static void argv_usage( if (header) fprintf(file,"%s",header); - option = options; - optlen = 0; + for (optlen=0,optv=options; *optv; optv++) { + option = *optv; - for (; option->short_name || option->long_name; option++) { /* indent + comma */ len = fboth ? sizeof(indent) + 1 : sizeof(indent); @@ -805,7 +824,9 @@ static void argv_usage( optlen &= (~(ARGV_TAB_WIDTH-1)); desclen = (optlen < width / 2) ? width - optlen : optlen; - for (option=options; option->short_name || option->long_name; option++) { + for (optv=options; *optv; optv++) { + option = *optv; + /* color */ if (fcolor) { color = (color == ccyan) ? cblue : ccyan; diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index 72f86b0..738f308 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -8,6 +8,8 @@ #include #include "argv/argv.h" +#define SLBT_OPTV_ELEMENTS 64 + extern const struct argv_option slbt_default_options[]; enum app_tags { diff --git a/src/logic/slbt_exec_install.c b/src/logic/slbt_exec_install.c index 7dc2b72..311fc3c 100644 --- a/src/logic/slbt_exec_install.c +++ b/src/logic/slbt_exec_install.c @@ -14,6 +14,7 @@ #define ARGV_DRIVER #include +#include "slibtool_driver_impl.h" #include "slibtool_install_impl.h" #include "slibtool_readlink_impl.h" #include "slibtool_spawn_impl.h" @@ -24,7 +25,7 @@ static int slbt_install_usage( const char * program, const char * arg, - const struct argv_option * options, + const struct argv_option ** optv, struct argv_meta * meta) { char header[512]; @@ -34,7 +35,7 @@ static int slbt_install_usage( "Options:\n", program); - argv_usage(stdout,header,options,arg); + argv_usage(stdout,header,optv,arg); argv_free(meta); return SLBT_USAGE; @@ -545,8 +546,8 @@ int slbt_exec_install( struct argv_entry * copy; struct argv_entry * dest; struct argv_entry * last; + const struct argv_option * optv[SLBT_OPTV_ELEMENTS]; char dstdir[PATH_MAX]; - const struct argv_option * options = slbt_install_options; /* dry run */ if (dctx->cctx->drvflags & SLBT_DRIVER_DRY_RUN) @@ -570,13 +571,15 @@ int slbt_exec_install( iargv++; /* missing arguments? */ + argv_optv_init(slbt_install_options,optv); + if (!iargv[1] && (dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_USAGE)) - return slbt_install_usage(dctx->program,0,options,0); + return slbt_install_usage(dctx->program,0,optv,0); /* argv meta */ if (!(meta = argv_get( iargv, - options, + optv, dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS ? ARGV_VERBOSITY_ERRORS : ARGV_VERBOSITY_NONE))) diff --git a/src/logic/slbt_exec_uninstall.c b/src/logic/slbt_exec_uninstall.c index cc27911..0dafa81 100644 --- a/src/logic/slbt_exec_uninstall.c +++ b/src/logic/slbt_exec_uninstall.c @@ -14,6 +14,7 @@ #define ARGV_DRIVER #include +#include "slibtool_driver_impl.h" #include "slibtool_uninstall_impl.h" #include "slibtool_readlink_impl.h" #include "slibtool_errinfo_impl.h" @@ -22,7 +23,7 @@ static int slbt_uninstall_usage( const char * program, const char * arg, - const struct argv_option * options, + const struct argv_option ** optv, struct argv_meta * meta) { char header[512]; @@ -32,7 +33,7 @@ static int slbt_uninstall_usage( "Options:\n", program); - argv_usage(stdout,header,options,arg); + argv_usage(stdout,header,optv,arg); argv_free(meta); return SLBT_USAGE; @@ -250,7 +251,7 @@ int slbt_exec_uninstall( struct slbt_exec_ctx * actx; struct argv_meta * meta; struct argv_entry * entry; - const struct argv_option * options = slbt_uninstall_options; + const struct argv_option * optv[SLBT_OPTV_ELEMENTS]; /* dry run */ if (dctx->cctx->drvflags & SLBT_DRIVER_DRY_RUN) @@ -274,13 +275,15 @@ int slbt_exec_uninstall( iargv++; /* missing arguments? */ + argv_optv_init(slbt_uninstall_options,optv); + if (!iargv[1] && (dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_USAGE)) - return slbt_uninstall_usage(dctx->program,0,options,0); + return slbt_uninstall_usage(dctx->program,0,optv,0); /* argv meta */ if (!(meta = argv_get( iargv, - options, + optv, dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS ? ARGV_VERBOSITY_ERRORS : ARGV_VERBOSITY_NONE))) @@ -325,7 +328,7 @@ int slbt_exec_uninstall( /* --help */ if (flags & SLBT_UNINSTALL_HELP) { - slbt_uninstall_usage(dctx->program,0,options,meta); + slbt_uninstall_usage(dctx->program,0,optv,meta); return 0; }