summaryrefslogtreecommitdiffstats
path: root/m_option.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /m_option.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'm_option.c')
-rw-r--r--m_option.c2117
1 files changed, 0 insertions, 2117 deletions
diff --git a/m_option.c b/m_option.c
deleted file mode 100644
index 3f300326ca..0000000000
--- a/m_option.c
+++ /dev/null
@@ -1,2117 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/// \file
-/// \ingroup Options
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <libavutil/common.h>
-#include <libavutil/avstring.h>
-
-#include "talloc.h"
-#include "m_option.h"
-#include "mp_msg.h"
-#include "stream/url.h"
-
-char *m_option_strerror(int code)
-{
- switch (code) {
- case M_OPT_UNKNOWN:
- return mp_gtext("Unrecognized option name");
- case M_OPT_MISSING_PARAM:
- return mp_gtext("Required parameter for option missing");
- case M_OPT_INVALID:
- return mp_gtext("Option parameter could not be parsed");
- case M_OPT_OUT_OF_RANGE:
- return mp_gtext("Parameter is outside values allowed for option");
- case M_OPT_PARSER_ERR:
- return mp_gtext("Parser error");
- default:
- return NULL;
- }
-}
-
-static const struct m_option *m_option_list_findb(const struct m_option *list,
- struct bstr name)
-{
- for (int i = 0; list[i].name; i++) {
- struct bstr lname = bstr0(list[i].name);
- if ((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD)
- && bstr_endswith0(lname, "*")) {
- lname.len--;
- if (bstrcasecmp(bstr_splice(name, 0, lname.len), lname) == 0)
- return &list[i];
- } else if (bstrcasecmp(lname, name) == 0)
- return &list[i];
- }
- return NULL;
-}
-
-const m_option_t *m_option_list_find(const m_option_t *list, const char *name)
-{
- return m_option_list_findb(list, bstr0(name));
-}
-
-// Default function that just does a memcpy
-
-static void copy_opt(const m_option_t *opt, void *dst, const void *src)
-{
- if (dst && src)
- memcpy(dst, src, opt->type->size);
-}
-
-// Flag
-
-#define VAL(x) (*(int *)(x))
-
-static int clamp_flag(const m_option_t *opt, void *val)
-{
- if (VAL(val) == opt->min || VAL(val) == opt->max)
- return 0;
- VAL(val) = opt->min;
- return M_OPT_OUT_OF_RANGE;
-}
-
-static int parse_flag(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (param.len) {
- if (!bstrcasecmp0(param, "yes")) {
- if (dst)
- VAL(dst) = opt->max;
- return 1;
- }
- if (!bstrcasecmp0(param, "no")) {
- if (dst)
- VAL(dst) = opt->min;
- return 1;
- }
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Invalid parameter for %.*s flag: %.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
- } else {
- if (dst)
- VAL(dst) = opt->max;
- return 0;
- }
-}
-
-static char *print_flag(const m_option_t *opt, const void *val)
-{
- if (VAL(val) == opt->min)
- return talloc_strdup(NULL, "no");
- else
- return talloc_strdup(NULL, "yes");
-}
-
-static void add_flag(const m_option_t *opt, void *val, double add, bool wrap)
-{
- if (fabs(add) < 0.5)
- return;
- bool state = VAL(val) != opt->min;
- state = wrap ? !state : add > 0;
- VAL(val) = state ? opt->max : opt->min;
-}
-
-const m_option_type_t m_option_type_flag = {
- // need yes or no in config files
- .name = "Flag",
- .size = sizeof(int),
- .flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
- .parse = parse_flag,
- .print = print_flag,
- .copy = copy_opt,
- .add = add_flag,
- .clamp = clamp_flag,
-};
-
-// Integer
-
-#undef VAL
-
-static int clamp_longlong(const m_option_t *opt, void *val)
-{
- long long v = *(long long *)val;
- int r = 0;
- if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
- v = opt->max;
- r = M_OPT_OUT_OF_RANGE;
- }
- if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
- v = opt->min;
- r = M_OPT_OUT_OF_RANGE;
- }
- *(long long *)val = v;
- return r;
-}
-
-static int parse_longlong(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- struct bstr rest;
- long long tmp_int = bstrtoll(param, &rest, 10);
- if (rest.len)
- tmp_int = bstrtoll(param, &rest, 0);
- if (rest.len) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be an integer: %.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
- }
-
- if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be >= %d: %.*s\n",
- BSTR_P(name), (int) opt->min, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be <= %d: %.*s\n",
- BSTR_P(name), (int) opt->max, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (dst)
- *(long long *)dst = tmp_int;
-
- return 1;
-}
-
-static int clamp_int(const m_option_t *opt, void *val)
-{
- long long tmp = *(int *)val;
- int r = clamp_longlong(opt, &tmp);
- *(int *)val = tmp;
- return r;
-}
-
-static int clamp_int64(const m_option_t *opt, void *val)
-{
- long long tmp = *(int64_t *)val;
- int r = clamp_longlong(opt, &tmp);
- *(int64_t *)val = tmp;
- return r;
-}
-
-static int parse_int(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- long long tmp;
- int r = parse_longlong(opt, name, param, &tmp);
- if (r >= 0 && dst)
- *(int *)dst = tmp;
- return r;
-}
-
-static int parse_int64(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- long long tmp;
- int r = parse_longlong(opt, name, param, &tmp);
- if (r >= 0 && dst)
- *(int64_t *)dst = tmp;
- return r;
-}
-
-static char *print_int(const m_option_t *opt, const void *val)
-{
- if (opt->type->size == sizeof(int64_t))
- return talloc_asprintf(NULL, "%"PRId64, *(const int64_t *)val);
- return talloc_asprintf(NULL, "%d", *(const int *)val);
-}
-
-static void add_int64(const m_option_t *opt, void *val, double add, bool wrap)
-{
- int64_t v = *(int64_t *)val;
-
- v = v + add;
-
- bool is64 = opt->type->size == sizeof(int64_t);
- int64_t nmin = is64 ? INT64_MIN : INT_MIN;
- int64_t nmax = is64 ? INT64_MAX : INT_MAX;
-
- int64_t min = (opt->flags & M_OPT_MIN) ? opt->min : nmin;
- int64_t max = (opt->flags & M_OPT_MAX) ? opt->max : nmax;
-
- if (v < min)
- v = wrap ? max : min;
- if (v > max)
- v = wrap ? min : max;
-
- *(int64_t *)val = v;
-}
-
-static void add_int(const m_option_t *opt, void *val, double add, bool wrap)
-{
- int64_t tmp = *(int *)val;
- add_int64(opt, &tmp, add, wrap);
- *(int *)val = tmp;
-}
-
-const m_option_type_t m_option_type_int = {
- .name = "Integer",
- .size = sizeof(int),
- .parse = parse_int,
- .print = print_int,
- .copy = copy_opt,
- .add = add_int,
- .clamp = clamp_int,
-};
-
-const m_option_type_t m_option_type_int64 = {
- .name = "Integer64",
- .size = sizeof(int64_t),
- .parse = parse_int64,
- .print = print_int,
- .copy = copy_opt,
- .add = add_int64,
- .clamp = clamp_int64,
-};
-
-static int parse_intpair(const struct m_option *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- struct bstr s = param;
- int end = -1;
- int start = bstrtoll(s, &s, 10);
- if (s.len == param.len)
- goto bad;
- if (s.len > 0) {
- if (!bstr_startswith0(s, "-"))
- goto bad;
- s = bstr_cut(s, 1);
- }
- if (s.len > 0)
- end = bstrtoll(s, &s, 10);
- if (s.len > 0)
- goto bad;
-
- if (dst) {
- int *p = dst;
- p[0] = start;
- p[1] = end;
- }
-
- return 1;
-
-bad:
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid integer range "
- "specification for option %.*s: %.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
-}
-
-const struct m_option_type m_option_type_intpair = {
- .name = "Int[-Int]",
- .size = sizeof(int[2]),
- .parse = parse_intpair,
- .copy = copy_opt,
-};
-
-static int clamp_choice(const m_option_t *opt, void *val)
-{
- int v = *(int *)val;
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- if (v >= opt->min && v <= opt->max)
- return 0;
- }
- ;
- for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) {
- if (alt->value == v)
- return 0;
- }
- return M_OPT_INVALID;
-}
-
-static int parse_choice(const struct m_option *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- struct m_opt_choice_alternatives *alt = opt->priv;
- for ( ; alt->name; alt++)
- if (!bstrcasecmp0(param, alt->name))
- break;
- if (!alt->name) {
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- long long val;
- if (parse_longlong(opt, name, param, &val) == 1) {
- if (dst)
- *(int *)dst = val;
- return 1;
- }
- }
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Invalid value for option %.*s: %.*s\n",
- BSTR_P(name), BSTR_P(param));
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Valid values are:");
- for (alt = opt->priv; alt->name; alt++)
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s", alt->name);
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n");
- return M_OPT_INVALID;
- }
- if (dst)
- *(int *)dst = alt->value;
-
- return 1;
-}
-
-static char *print_choice(const m_option_t *opt, const void *val)
-{
- int v = *(int *)val;
- struct m_opt_choice_alternatives *alt;
- for (alt = opt->priv; alt->name; alt++)
- if (alt->value == v)
- return talloc_strdup(NULL, alt->name);
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- if (v >= opt->min && v <= opt->max)
- return talloc_asprintf(NULL, "%d", v);
- }
- abort();
-}
-
-static void choice_get_min_max(const struct m_option *opt, int *min, int *max)
-{
- assert(opt->type == &m_option_type_choice);
- *min = INT_MAX;
- *max = INT_MIN;
- for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) {
- *min = FFMIN(*min, alt->value);
- *max = FFMAX(*max, alt->value);
- }
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- *min = FFMIN(*min, opt->min);
- *max = FFMAX(*max, opt->max);
- }
-}
-
-static void check_choice(int dir, int val, bool *found, int *best, int choice)
-{
- if ((dir == -1 && (!(*found) || choice > (*best)) && choice < val) ||
- (dir == +1 && (!(*found) || choice < (*best)) && choice > val))
- {
- *found = true;
- *best = choice;
- }
-}
-
-static void add_choice(const m_option_t *opt, void *val, double add, bool wrap)
-{
- assert(opt->type == &m_option_type_choice);
- int dir = add > 0 ? +1 : -1;
- bool found = false;
- int ival = *(int *)val;
- int best = 0; // init. value unused
-
- if (fabs(add) < 0.5)
- return;
-
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- int newval = ival + add;
- if (ival >= opt->min && ival <= opt->max &&
- newval >= opt->min && newval <= opt->max)
- {
- found = true;
- best = newval;
- } else {
- check_choice(dir, ival, &found, &best, opt->min);
- check_choice(dir, ival, &found, &best, opt->max);
- }
- }
-
- for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++)
- check_choice(dir, ival, &found, &best, alt->value);
-
- if (!found) {
- int min, max;
- choice_get_min_max(opt, &min, &max);
- best = (dir == -1) ^ wrap ? min : max;
- }
-
- *(int *)val = best;
-}
-
-const struct m_option_type m_option_type_choice = {
- .name = "String", // same as arbitrary strings in option list for now
- .size = sizeof(int),
- .parse = parse_choice,
- .print = print_choice,
- .copy = copy_opt,
- .add = add_choice,
- .clamp = clamp_choice,
-};
-
-// Float
-
-#undef VAL
-#define VAL(x) (*(double *)(x))
-
-static int clamp_double(const m_option_t *opt, void *val)
-{
- double v = VAL(val);
- int r = 0;
- if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
- v = opt->max;
- r = M_OPT_OUT_OF_RANGE;
- }
- if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
- v = opt->min;
- r = M_OPT_OUT_OF_RANGE;
- }
- VAL(val) = v;
- return r;
-}
-
-static int parse_double(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- struct bstr rest;
- double tmp_float = bstrtod(param, &rest);
-
- switch (rest.len ? rest.start[0] : 0) {
- case ':':
- case '/':
- tmp_float /= bstrtod(bstr_cut(rest, 1), &rest);
- break;
- case '.':
- case ',':
- /* we also handle floats specified with
- * non-locale decimal point ::atmos
- */
- rest = bstr_cut(rest, 1);
- if (tmp_float < 0)
- tmp_float -= 1.0 / pow(10, rest.len) * bstrtod(rest, &rest);
- else
- tmp_float += 1.0 / pow(10, rest.len) * bstrtod(rest, &rest);
- break;
- }
-
- if (rest.len) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be a floating point number or a "
- "ratio (numerator[:/]denominator): %.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
- }
-
- if (opt->flags & M_OPT_MIN)
- if (tmp_float < opt->min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be >= %f: %.*s\n",
- BSTR_P(name), opt->min, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (opt->flags & M_OPT_MAX)
- if (tmp_float > opt->max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "The %.*s option must be <= %f: %.*s\n",
- BSTR_P(name), opt->max, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (dst)
- VAL(dst) = tmp_float;
- return 1;
-}
-
-static char *print_double(const m_option_t *opt, const void *val)
-{
- return talloc_asprintf(NULL, "%f", VAL(val));
-}
-
-static char *print_double_f2(const m_option_t *opt, const void *val)
-{
- return talloc_asprintf(NULL, "%.2f", VAL(val));
-}
-
-static void add_double(const m_option_t *opt, void *val, double add, bool wrap)
-{
- double v = VAL(val);
-
- v = v + add;
-
- double min = (opt->flags & M_OPT_MIN) ? opt->min : -INFINITY;
- double max = (opt->flags & M_OPT_MAX) ? opt->max : +INFINITY;
-
- if (v < min)
- v = wrap ? max : min;
- if (v > max)
- v = wrap ? min : max;
-
- VAL(val) = v;
-}
-
-const m_option_type_t m_option_type_double = {
- // double precision float or ratio (numerator[:/]denominator)
- .name = "Double",
- .size = sizeof(double),
- .parse = parse_double,
- .print = print_double,
- .pretty_print = print_double_f2,
- .copy = copy_opt,
- .clamp = clamp_double,
-};
-
-#undef VAL
-#define VAL(x) (*(float *)(x))
-
-static int clamp_float(const m_option_t *opt, void *val)
-{
- double tmp = VAL(val);
- int r = clamp_double(opt, &tmp);
- VAL(val) = tmp;
- return r;
-}
-
-static int parse_float(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- double tmp;
- int r = parse_double(opt, name, param, &tmp);
- if (r == 1 && dst)
- VAL(dst) = tmp;
- return r;
-}
-
-static char *print_float(const m_option_t *opt, const void *val)
-{
- return talloc_asprintf(NULL, "%f", VAL(val));
-}
-
-static char *print_float_f2(const m_option_t *opt, const void *val)
-{
- return talloc_asprintf(NULL, "%.2f", VAL(val));
-}
-
-static void add_float(const m_option_t *opt, void *val, double add, bool wrap)
-{
- double tmp = VAL(val);
- add_double(opt, &tmp, add, wrap);
- VAL(val) = tmp;
-}
-
-const m_option_type_t m_option_type_float = {
- // floating point number or ratio (numerator[:/]denominator)
- .name = "Float",
- .size = sizeof(float),
- .parse = parse_float,
- .print = print_float,
- .pretty_print = print_float_f2,
- .copy = copy_opt,
- .add = add_float,
- .clamp = clamp_float,
-};
-
-///////////// String
-
-#undef VAL
-#define VAL(x) (*(char **)(x))
-
-static int clamp_str(const m_option_t *opt, void *val)
-{
- char *v = VAL(val);
- int len = v ? strlen(v) : 0;
- if ((opt->flags & M_OPT_MIN) && (len < opt->min))
- return M_OPT_OUT_OF_RANGE;
- if ((opt->flags & M_OPT_MAX) && (len > opt->max))
- return M_OPT_OUT_OF_RANGE;
- return 0;
-}
-
-static int parse_str(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (param.start == NULL)
- return M_OPT_MISSING_PARAM;
-
- if ((opt->flags & M_OPT_MIN) && (param.len < opt->min)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Parameter must be >= %d chars: %.*s\n",
- (int) opt->min, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if ((opt->flags & M_OPT_MAX) && (param.len > opt->max)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Parameter must be <= %d chars: %.*s\n",
- (int) opt->max, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if (dst) {
- talloc_free(VAL(dst));
- VAL(dst) = bstrdup0(NULL, param);
- }
-
- return 1;
-
-}
-
-static char *print_str(const m_option_t *opt, const void *val)
-{
- return (val && VAL(val)) ? talloc_strdup(NULL, VAL(val)) : NULL;
-}
-
-static void copy_str(const m_option_t *opt, void *dst, const void *src)
-{
- if (dst && src) {
- talloc_free(VAL(dst));
- VAL(dst) = talloc_strdup(NULL, VAL(src));
- }
-}
-
-static void free_str(void *src)
-{
- if (src && VAL(src)) {
- talloc_free(VAL(src));
- VAL(src) = NULL;
- }
-}
-
-const m_option_type_t m_option_type_string = {
- .name = "String",
- .size = sizeof(char *),
- .flags = M_OPT_TYPE_DYNAMIC,
- .parse = parse_str,
- .print = print_str,
- .copy = copy_str,
- .free = free_str,
- .clamp = clamp_str,
-};
-
-//////////// String list
-
-#undef VAL
-#define VAL(x) (*(char ***)(x))
-
-#define OP_NONE 0
-#define OP_ADD 1
-#define OP_PRE 2
-#define OP_DEL 3
-#define OP_CLR 4
-
-static void free_str_list(void *dst)
-{
- char **d;
- int i;
-
- if (!dst || !VAL(dst))
- return;
- d = VAL(dst);
-
- for (i = 0; d[i] != NULL; i++)
- talloc_free(d[i]);
- talloc_free(d);
- VAL(dst) = NULL;
-}
-
-static int str_list_add(char **add, int n, void *dst, int pre)
-{
- if (!dst)
- return M_OPT_PARSER_ERR;
- char **lst = VAL(dst);
-
- int ln;
- for (ln = 0; lst && lst[ln]; ln++)
- /**/;
-
- lst = talloc_realloc(NULL, lst, char *, n + ln + 1);
-
- if (pre) {
- memmove(&lst[n], lst, ln * sizeof(char *));
- memcpy(lst, add, n * sizeof(char *));
- } else
- memcpy(&lst[ln], add, n * sizeof(char *));
- // (re-)add NULL-termination
- lst[ln + n] = NULL;
-
- talloc_free(add);
-
- VAL(dst) = lst;
-
- return 1;
-}
-
-static int str_list_del(char **del, int n, void *dst)
-{
- char **lst, *ep;
- int i, ln, s;
- long idx;
-
- if (!dst)
- return M_OPT_PARSER_ERR;
- lst = VAL(dst);
-
- for (ln = 0; lst && lst[ln]; ln++)
- /**/;
- s = ln;
-
- for (i = 0; del[i] != NULL; i++) {
- idx = strtol(del[i], &ep, 0);
- if (*ep) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n", del[i]);
- talloc_free(del[i]);
- continue;
- }
- talloc_free(del[i]);
- if (idx < 0 || idx >= ln) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Index %ld is out of range.\n", idx);
- continue;
- } else if (!lst[idx])
- continue;
- talloc_free(lst[idx]);
- lst[idx] = NULL;
- s--;
- }
- talloc_free(del);
-
- if (s == 0) {
- talloc_free(lst);
- VAL(dst) = NULL;
- return 1;
- }
-
- // Don't bother shrinking the list allocation
- for (i = 0, n = 0; i < ln; i++) {
- if (!lst[i])
- continue;
- lst[n] = lst[i];
- n++;
- }
- lst[s] = NULL;
-
- return 1;
-}
-
-static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify)
-{
- struct bstr str = *ptr;
- struct bstr orig = str;
- for (;;) {
- int idx = bstrchr(str, sep);
- if (idx > 0 && str.start[idx - 1] == '\\') {
- if (modify) {
- memmove(str.start + idx - 1, str.start + idx, str.len - idx);
- str.len--;
- str = bstr_cut(str, idx);
- } else
- str = bstr_cut(str, idx + 1);
- } else {
- str = bstr_cut(str, idx < 0 ? str.len : idx);
- break;
- }
- }
- *ptr = str;
- return bstr_splice(orig, 0, str.start - orig.start);
-}
-
-static int parse_str_list(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- char **res;
- int op = OP_NONE;
- int len = strlen(opt->name);
- if (opt->name[len - 1] == '*' && (name.len > len - 1)) {
- struct bstr suffix = bstr_cut(name, len - 1);
- if (bstrcasecmp0(suffix, "-add") == 0)
- op = OP_ADD;
- else if (bstrcasecmp0(suffix, "-pre") == 0)
- op = OP_PRE;
- else if (bstrcasecmp0(suffix, "-del") == 0)
- op = OP_DEL;
- else if (bstrcasecmp0(suffix, "-clr") == 0)
- op = OP_CLR;
- else
- return M_OPT_UNKNOWN;
- }
-
- // Clear the list ??
- if (op == OP_CLR) {
- if (dst)
- free_str_list(dst);
- return 0;
- }
-
- // All other ops need a param
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- // custom type for "profile" calls this but uses ->priv for something else
- char separator = opt->type == &m_option_type_string_list && opt->priv ?
- *(char *)opt->priv : OPTION_LIST_SEPARATOR;
- int n = 0;
- struct bstr str = param;
- while (str.len) {
- get_nextsep(&str, separator, 0);
- str = bstr_cut(str, 1);
- n++;
- }
- if (n == 0)
- return M_OPT_INVALID;
- if (((opt->flags & M_OPT_MIN) && (n < opt->min)) ||
- ((opt->flags & M_OPT_MAX) && (n > opt->max)))
- return M_OPT_OUT_OF_RANGE;
-
- if (!dst)
- return 1;
-
- res = talloc_array(NULL, char *, n + 2);
- str = bstrdup(NULL, param);
- char *ptr = str.start;
- n = 0;
-
- while (1) {
- struct bstr el = get_nextsep(&str, separator, 1);
- res[n] = bstrdup0(NULL, el);
- n++;
- if (!str.len)
- break;
- str = bstr_cut(str, 1);
- }
- res[n] = NULL;
- talloc_free(ptr);
-
- switch (op) {
- case OP_ADD:
- return str_list_add(res, n, dst, 0);
- case OP_PRE:
- return str_list_add(res, n, dst, 1);
- case OP_DEL:
- return str_list_del(res, n, dst);
- }
-
- if (VAL(dst))
- free_str_list(dst);
- VAL(dst) = res;
-
- return 1;
-}
-
-static void copy_str_list(const m_option_t *opt, void *dst, const void *src)
-{
- int n;
- char **d, **s;
-
- if (!(dst && src))
- return;
- s = VAL(src);
-
- if (VAL(dst))
- free_str_list(dst);
-
- if (!s) {
- VAL(dst) = NULL;
- return;
- }
-
- for (n = 0; s[n] != NULL; n++)
- /* NOTHING */;
- d = talloc_array(NULL, char *, n + 1);
- for (; n >= 0; n--)
- d[n] = talloc_strdup(NULL, s[n]);
-
- VAL(dst) = d;
-}
-
-static char *print_str_list(const m_option_t *opt, const void *src)
-{
- char **lst = NULL;
- char *ret = NULL;
-
- if (!(src && VAL(src)))
- return NULL;
- lst = VAL(src);
-
- for (int i = 0; lst[i]; i++) {
- if (ret)
- ret = talloc_strdup_append_buffer(ret, ",");
- ret = talloc_strdup_append_buffer(ret, lst[i]);
- }
- return ret;
-}
-
-const m_option_type_t m_option_type_string_list = {
- /* A list of strings separated by ','.
- * Option with a name ending in '*' permits using the following suffixes:
- * -add: Add the given parameters at the end of the list.
- * -pre: Add the given parameters at the beginning of the list.
- * -del: Remove the entry at the given indices.
- * -clr: Clear the list.
- * e.g: -vf-add flip,mirror -vf-del 2,5
- */
- .name = "String list",
- .size = sizeof(char **),
- .flags = M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD,
- .parse = parse_str_list,
- .print = print_str_list,
- .copy = copy_str_list,
- .free = free_str_list,
-};
-
-
-/////////////////// Print
-
-static int parse_print(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- if (opt->type == CONF_TYPE_PRINT) {
- mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", mp_gtext(opt->p));
- } else {
- char *name0 = bstrdup0(NULL, name);
- char *param0 = bstrdup0(NULL, param);
- int r = ((m_opt_func_full_t) opt->p)(opt, name0, param0);
- talloc_free(name0);
- talloc_free(param0);
- return r;
- }
-
- if (opt->priv == NULL)
- return M_OPT_EXIT;
- return 0;
-}
-
-const m_option_type_t m_option_type_print = {
- .name = "Print",
- .flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
- .parse = parse_print,
-};
-
-const m_option_type_t m_option_type_print_func_param = {
- .name = "Print",
- .flags = M_OPT_TYPE_ALLOW_WILDCARD,
- .parse = parse_print,
-};
-
-const m_option_type_t m_option_type_print_func = {
- .name = "Print",
- .flags = M_OPT_TYPE_ALLOW_WILDCARD | M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
- .parse = parse_print,
-};
-
-
-/////////////////////// Subconfig
-#undef VAL
-#define VAL(x) (*(char ***)(x))
-
-static int parse_subconf(const m_option_t *opt, struct bstr name,
- struct bstr param, void *dst)
-{
- int nr = 0;
- char **lst = NULL;
-
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- struct bstr p = param;
-
- while (p.len) {
- int optlen = bstrcspn(p, ":=");
- struct bstr subopt = bstr_splice(p, 0, optlen);
- struct bstr subparam = bstr0(NULL);
- p = bstr_cut(p, optlen);
- if (bstr_startswith0(p, "=")) {
- p = bstr_cut(p, 1);
- if (bstr_startswith0(p, "\"")) {
- p = bstr_cut(p, 1);
- optlen = bstrcspn(p, "\"");
- subparam = bstr_splice(p, 0, optlen);
- p = bstr_cut(p, optlen);
- if (!bstr_startswith0(p, "\"")) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Terminating '\"' missing for '%.*s'\n",
- BSTR_P(subopt));
- return M_OPT_INVALID;
- }
- p = bstr_cut(p, 1);
- } else if (bstr_startswith0(p, "%")) {
- p = bstr_cut(p, 1);
- optlen = bstrtoll(p, &p, 0);
- if (!bstr_startswith0(p, "%") || (optlen > p.len - 1)) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Invalid length %d for '%.*s'\n",
- optlen, BSTR_P(subopt));
- return M_OPT_INVALID;
- }
- subparam = bstr_splice(p, 1, optlen + 1);
- p = bstr_cut(p, optlen + 1);
- } else {
- optlen = bstrcspn(p, ":");
- subparam = bstr_splice(p, 0, optlen);
- p = bstr_cut(p, optlen);
- }
- }
- if (bstr_startswith0(p, ":"))
- p = bstr_cut(p, 1);
- else if (p.len > 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Incorrect termination for '%.*s'\n", BSTR_P(subopt));
- return M_OPT_INVALID;
- }
-
- if (dst) {
- lst = talloc_realloc(NULL, lst, char *, 2 * (nr + 2));
- lst[2 * nr] = bstrdup0(lst, subopt);
- lst[2 * nr + 1] = bstrdup0(lst, subparam);
- memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *));
- nr++;
- }
- }
-
- if (dst)
- VAL(dst) = lst;
-
- return 1;
-}
-
-const m_option_type_t m_option_type_subconfig = {
- // The syntax is -option opt1=foo:flag:opt2=blah
- .name = "Subconfig",
- .flags = M_OPT_TYPE_HAS_CHILD,
- .parse = parse_subconf,
-};
-
-const m_option_