diff options
-rw-r--r-- | command.c | 18 | ||||
-rw-r--r-- | command.h | 2 | ||||
-rw-r--r-- | m_property.c | 137 | ||||
-rw-r--r-- | m_property.h | 18 | ||||
-rw-r--r-- | mplayer.c | 9 | ||||
-rw-r--r-- | screenshot.c | 19 |
6 files changed, 109 insertions, 94 deletions
@@ -1525,7 +1525,7 @@ char *mp_property_print(const char *name, struct MPContext *ctx) return ret; } -char *property_expand_string(MPContext *mpctx, char *str) +char *mp_property_expand_string(struct MPContext *mpctx, char *str) { return m_properties_expand_string(mp_properties, str, mpctx); } @@ -1931,15 +1931,13 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) } case MP_CMD_SHOW_TEXT: { - char *txt = m_properties_expand_string(mp_properties, - cmd->args[0].v.s, - mpctx); - // if no argument supplied use default osd_duration, else <arg> ms. + char *txt = mp_property_expand_string(mpctx, cmd->args[0].v.s); if (txt) { + // if no argument supplied use default osd_duration, else <arg> ms. set_osd_msg(mpctx, OSD_MSG_TEXT, cmd->args[2].v.i, (cmd->args[1].v.i < 0 ? osd_duration : cmd->args[1].v.i), "%s", txt); - free(txt); + talloc_free(txt); } break; } @@ -2198,10 +2196,10 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) case MP_CMD_RUN: #ifndef __MINGW32__ if (!fork()) { - char *exp_cmd = property_expand_string(mpctx, cmd->args[0].v.s); - if (exp_cmd) { - execl("/bin/sh", "sh", "-c", exp_cmd, NULL); - free(exp_cmd); + char *s = mp_property_expand_string(mpctx, cmd->args[0].v.s); + if (s) { + execl("/bin/sh", "sh", "-c", s, NULL); + talloc_free(s); } exit(0); } @@ -23,7 +23,7 @@ struct MPContext; struct mp_cmd; void run_command(struct MPContext *mpctx, struct mp_cmd *cmd); -char *property_expand_string(struct MPContext *mpctx, char *str); +char *mp_property_expand_string(struct MPContext *mpctx, char *str); void property_print_help(void); int mp_property_do(const char* name, int action, void* val, struct MPContext *mpctx); diff --git a/m_property.c b/m_property.c index 68be17c974..acdf91200c 100644 --- a/m_property.c +++ b/m_property.c @@ -27,6 +27,8 @@ #include <inttypes.h> #include <assert.h> +#include <libavutil/common.h> + #include "talloc.h" #include "m_option.h" #include "m_property.h" @@ -140,73 +142,94 @@ int m_property_do(const m_option_t *prop_list, const char *name, } } -char *m_properties_expand_string(const m_option_t *prop_list, char *str, +static int m_property_do_bstr(const m_option_t *prop_list, bstr name, + int action, void *arg, void *ctx) +{ + char name0[64]; + if (name.len >= sizeof(name0)) + return M_PROPERTY_UNKNOWN; + snprintf(name0, sizeof(name0), "%.*s", BSTR_P(name)); + return m_property_do(prop_list, name0, action, arg, ctx); +} + +static void append_str(char **s, int *len, bstr append) +{ + MP_TARRAY_GROW(NULL, *s, *len + append.len); + memcpy(*s + *len, append.start, append.len); + *len = *len + append.len; +} + +char *m_properties_expand_string(const m_option_t *prop_list, char *str0, void *ctx) { - int l, fr = 0, pos = 0, size = strlen(str) + 512; - char *p = NULL, *e, *ret = malloc(size); - int skip = 0, lvl = 0, skip_lvl = 0; + char *ret = NULL; + int ret_len = 0; + bool skip = false; + int level = 0, skip_level = 0; + bstr str = bstr0(str0); + + while (str.len) { + if (level > 0 && bstr_eatstart0(&str, "}")) { + if (skip && level <= skip_level) + skip = false; + level--; + } else if (bstr_startswith0(str, "${") && bstr_find0(str, "}") >= 0) { + str = bstr_cut(str, 2); + level++; + + // Assume ":" and "}" can't be part of the property name + // => if ":" comes before "}", it must be for the fallback + int term_pos = bstrcspn(str, ":}"); + bstr name = bstr_splice(str, 0, term_pos < 0 ? str.len : term_pos); + str = bstr_cut(str, term_pos); + bool have_fallback = bstr_eatstart0(&str, ":"); - while (str[0]) { - if (lvl > 0 && str[0] == ')') { - if (skip && lvl <= skip_lvl) - skip = 0; - lvl--, str++, l = 0; - } else if (str[0] == '$' && str[1] == '{' - && (e = strchr(str + 2, '}'))) { - str += 2; - int method = M_PROPERTY_PRINT; - if (str[0] == '=') { - str += 1; - method = M_PROPERTY_GET_STRING; - } - int pl = e - str; - char pname[pl + 1]; - memcpy(pname, str, pl); - pname[pl] = 0; - if (m_property_do(prop_list, pname, method, &p, ctx) >= 0 && p) - l = strlen(p), fr = 1; - else - l = 0; - str = e + 1; - } else if (str[0] == '?' && str[1] == '(' - && (e = strchr(str + 2, ':'))) { - lvl++; if (!skip) { - int is_not = str[2] == '!'; - int pl = e - str - (is_not ? 3 : 2); - char pname[pl + 1]; - memcpy(pname, str + (is_not ? 3 : 2), pl); - pname[pl] = 0; - struct m_option opt = {0}; - union m_option_value val = {0}; - if (m_property_do(prop_list, pname, M_PROPERTY_GET_TYPE, &opt, ctx) <= 0 && - m_property_do(prop_list, pname, M_PROPERTY_GET, &val, ctx) <= 0) - { - if (!is_not) - skip = 1, skip_lvl = lvl; - m_option_free(&opt, &val); - } else if (is_not) - skip = 1, skip_lvl = lvl; + bool cond_yes = bstr_eatstart0(&name, "?"); + bool cond_no = !cond_yes && bstr_eatstart0(&name, "!"); + bool raw = bstr_eatstart0(&name, "="); + int method = (raw || cond_yes || cond_no) + ? M_PROPERTY_GET_STRING : M_PROPERTY_PRINT; + + char *s = NULL; + int r = m_property_do_bstr(prop_list, name, method, &s, ctx); + if (cond_yes || cond_no) { + skip = (!!s != cond_yes); + } else { + skip = !!s; + char *append = s; + if (!s && !have_fallback && !raw) { + append = r == M_PROPERTY_UNAVAILABLE + ? "(unavailable)" : "(error)"; + } + append_str(&ret, &ret_len, bstr0(append)); + } + talloc_free(s); + if (skip) + skip_level = level; } - str = e + 1, l = 0; - } else - p = str, l = 1, str++; + } else if (level == 0 && bstr_eatstart0(&str, "$>")) { + append_str(&ret, &ret_len, str); + break; + } else { + char c; - if (skip || l <= 0) - continue; + // Other combinations, e.g. "$x", are added verbatim + if (bstr_eatstart0(&str, "$$")) { + c = '$'; + } else if (bstr_eatstart0(&str, "$}")) { + c = '}'; + } else { + c = str.start[0]; + str = bstr_cut(str, 1); + } - if (pos + l + 1 > size) { - size = pos + l + 512; - ret = realloc(ret, size); + if (!skip) + MP_TARRAY_APPEND(NULL, ret, ret_len, c); } - memcpy(ret + pos, p, l); - pos += l; - if (fr) - talloc_free(p), fr = 0; } - ret[pos] = 0; + MP_TARRAY_APPEND(NULL, ret, ret_len, '\0'); return ret; } diff --git a/m_property.h b/m_property.h index b5b8af26ee..94dd36f050 100644 --- a/m_property.h +++ b/m_property.h @@ -110,12 +110,18 @@ int m_property_do(const struct m_option* prop_list, const char* property_name, void m_properties_print_help_list(const struct m_option* list); // Expand a property string. -/* This function allows to print strings containing property values. - * ${NAME} is expanded to the value of property NAME or an empty - * string in case of error. $(NAME:STR) expand STR only if the property - * NAME is available. - */ -char* m_properties_expand_string(const struct m_option* prop_list, char* str, +// This function allows to print strings containing property values. +// ${NAME} is expanded to the value of property NAME. +// If NAME starts with '=', use the raw value of the property. +// ${NAME:STR} expands to the property, or STR if the property is not +// available. +// ${?NAME:STR} expands to STR if the property is available. +// ${!NAME:STR} expands to STR if the property is not available. +// General syntax: "${" ["?" | "!"] ["="] NAME ":" STR "}" +// STR is recursively expanded using the same rules. +// "$$" can be used to escape "$", and "$}" to escape "}". +// "$>" disables parsing of "$" for the rest of the string. +char* m_properties_expand_string(const struct m_option* prop_list, char *str, void *ctx); // Trivial helpers for implementing properties. @@ -2172,10 +2172,9 @@ static void vo_update_window_title(struct MPContext *mpctx) { if (!mpctx->video_out) return; - char *title = property_expand_string(mpctx, mpctx->opts.vo_wintitle); + char *title = mp_property_expand_string(mpctx, mpctx->opts.vo_wintitle); talloc_free(mpctx->video_out->window_title); - mpctx->video_out->window_title = talloc_strdup(mpctx->video_out, title); - free(title); + mpctx->video_out->window_title = talloc_steal(mpctx, title); } int reinit_video_chain(struct MPContext *mpctx) @@ -3876,9 +3875,9 @@ goto_enable_cache: #endif if (opts->playing_msg) { - char *msg = property_expand_string(mpctx, opts->playing_msg); + char *msg = mp_property_expand_string(mpctx, opts->playing_msg); mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", msg); - free(msg); + talloc_free(msg); } // Disable the term OSD in verbose mode diff --git a/screenshot.c b/screenshot.c index 7fb5fd9507..1f2b0694fc 100644 --- a/screenshot.c +++ b/screenshot.c @@ -66,19 +66,6 @@ static char *stripext(void *talloc_ctx, const char *s) return talloc_asprintf(talloc_ctx, "%.*s", end - s, s); } -static char *do_format_property(struct MPContext *mpctx, struct bstr s) { - struct bstr prop_name = s; - int fallbackpos = bstrchr(s, ':'); - if (fallbackpos >= 0) - prop_name = bstr_splice(prop_name, 0, fallbackpos); - char *pn = bstrdup0(NULL, prop_name); - char *res = mp_property_print(pn, mpctx); - talloc_free(pn); - if (!res && fallbackpos >= 0) - res = bstrdup0(NULL, bstr_cut(s, fallbackpos + 1)); - return res; -} - #ifdef _WIN32 #define ILLEGAL_FILENAME_CHARS "?\"/\\<>*|:" #else @@ -186,11 +173,13 @@ static char *create_fname(struct MPContext *mpctx, char *template, if (!end) goto error_exit; struct bstr prop = bstr_splice(bstr0(template), 0, end - template); - template = end + 1; - char *s = do_format_property(mpctx, prop); + char *tmp = talloc_asprintf(NULL, "${%.*s}", BSTR_P(prop)); + char *s = mp_property_expand_string(mpctx, tmp); + talloc_free(tmp); if (s) append_filename(&res, s); talloc_free(s); + template = end + 1; break; } case '%': |