Skip to content
Snippets Groups Projects
Commit 2f8e586d authored by Anton Khirnov's avatar Anton Khirnov
Browse files

cmdutils: split per-option code out of parse_options().

This allows options like -target, which are just shortcuts for other
options, to work without dummy function for all options they invoke.
parent 7cc8d638
No related branches found
No related tags found
No related merge requests found
...@@ -203,12 +203,66 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) ...@@ -203,12 +203,66 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
} }
#endif /* WIN32 && !__MINGW32CE__ */ #endif /* WIN32 && !__MINGW32CE__ */
int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options)
{
const OptionDef *po;
int bool_val = 1;
void *dst;
po = find_option(options, opt);
if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
/* handle 'no' bool option */
po = find_option(options, opt + 2);
if (!(po->name && (po->flags & OPT_BOOL)))
goto unknown_opt;
bool_val = 0;
}
if (!po->name)
po = find_option(options, "default");
if (!po->name) {
unknown_opt:
av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
return AVERROR(EINVAL);
}
if (po->flags & HAS_ARG && !arg) {
av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt);
return AVERROR(EINVAL);
}
/* new-style options contain an offset into optctx, old-style address of
* a global var*/
dst = po->flags & (OPT_OFFSET) ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr;
if (po->flags & OPT_STRING) {
char *str;
str = av_strdup(arg);
*(char**)dst = str;
} else if (po->flags & OPT_BOOL) {
*(int*)dst = bool_val;
} else if (po->flags & OPT_INT) {
*(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
} else if (po->flags & OPT_INT64) {
*(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
} else if (po->flags & OPT_FLOAT) {
*(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
} else if (po->u.func_arg) {
int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) :
po->u.func_arg(opt, arg);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to set value '%s' for option '%s'\n", arg, opt);
return ret;
}
}
if (po->flags & OPT_EXIT)
exit_program(0);
return !!(po->flags & HAS_ARG);
}
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(void *, const char*)) void (* parse_arg_function)(void *, const char*))
{ {
const char *opt, *arg; const char *opt;
int optindex, handleoptions=1; int optindex, handleoptions = 1, ret;
const OptionDef *po;
/* perform system-dependent conversions for arguments list */ /* perform system-dependent conversions for arguments list */
prepare_app_arguments(&argc, &argv); prepare_app_arguments(&argc, &argv);
...@@ -216,64 +270,18 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options ...@@ -216,64 +270,18 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options
/* parse options */ /* parse options */
optindex = 1; optindex = 1;
while (optindex < argc) { while (optindex < argc) {
void *dst;
opt = argv[optindex++]; opt = argv[optindex++];
if (handleoptions && opt[0] == '-' && opt[1] != '\0') { if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
int bool_val = 1;
if (opt[1] == '-' && opt[2] == '\0') { if (opt[1] == '-' && opt[2] == '\0') {
handleoptions = 0; handleoptions = 0;
continue; continue;
} }
opt++; opt++;
po= find_option(options, opt);
if (!po->name && opt[0] == 'n' && opt[1] == 'o') { if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
/* handle 'no' bool option */
po = find_option(options, opt + 2);
if (!(po->name && (po->flags & OPT_BOOL)))
goto unknown_opt;
bool_val = 0;
}
if (!po->name)
po= find_option(options, "default");
if (!po->name) {
unknown_opt:
fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
exit_program(1); exit_program(1);
} optindex += ret;
arg = NULL;
if (po->flags & HAS_ARG) {
arg = argv[optindex++];
if (!arg) {
fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
exit_program(1);
}
}
/* new-style options contain an offset into optctx, old-style address of
* a global var*/
dst = po->flags & OPT_OFFSET ? (uint8_t*)optctx + po->u.off : po->u.dst_ptr;
if (po->flags & OPT_STRING) {
char *str;
str = av_strdup(arg);
*(char**)dst = str;
} else if (po->flags & OPT_BOOL) {
*(int*)dst = bool_val;
} else if (po->flags & OPT_INT) {
*(int*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
} else if (po->flags & OPT_INT64) {
*(int64_t*)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
} else if (po->flags & OPT_FLOAT) {
*(float*)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
} else if (po->u.func_arg) {
int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) :
po->u.func_arg(opt, arg);
if (ret < 0) {
fprintf(stderr, "%s: failed to set value '%s' for option '%s'\n", argv[0], arg, opt);
exit_program(1);
}
}
if(po->flags & OPT_EXIT)
exit_program(0);
} else { } else {
if (parse_arg_function) if (parse_arg_function)
parse_arg_function(optctx, opt); parse_arg_function(optctx, opt);
......
...@@ -151,6 +151,13 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int ...@@ -151,6 +151,13 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(void *optctx, const char*)); void (* parse_arg_function)(void *optctx, const char*));
/**
* Parse one given option.
*
* @return on success 1 if arg was consumed, 0 otherwise; negative number on error
*/
int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options);
/** /**
* Check if the given stream matches a stream specifier. * Check if the given stream matches a stream specifier.
* *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment