mirror of https://git.ffmpeg.org/ffmpeg.git
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.
This commit is contained in:
parent
7cc8d6385a
commit
2f8e586df1
112
cmdutils.c
112
cmdutils.c
|
@ -203,12 +203,66 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
|
|||
}
|
||||
#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_arg_function)(void *, const char*))
|
||||
{
|
||||
const char *opt, *arg;
|
||||
int optindex, handleoptions=1;
|
||||
const OptionDef *po;
|
||||
const char *opt;
|
||||
int optindex, handleoptions = 1, ret;
|
||||
|
||||
/* perform system-dependent conversions for arguments list */
|
||||
prepare_app_arguments(&argc, &argv);
|
||||
|
@ -216,64 +270,18 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options
|
|||
/* parse options */
|
||||
optindex = 1;
|
||||
while (optindex < argc) {
|
||||
void *dst;
|
||||
opt = argv[optindex++];
|
||||
|
||||
if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
|
||||
int bool_val = 1;
|
||||
if (opt[1] == '-' && opt[2] == '\0') {
|
||||
handleoptions = 0;
|
||||
continue;
|
||||
}
|
||||
opt++;
|
||||
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:
|
||||
fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
|
||||
|
||||
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
|
||||
exit_program(1);
|
||||
}
|
||||
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);
|
||||
optindex += ret;
|
||||
} else {
|
||||
if (parse_arg_function)
|
||||
parse_arg_function(optctx, opt);
|
||||
|
|
|
@ -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_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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue