From 7b6da9ee6d14cbba2360716f1e48922add5c1556 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 30 Nov 2021 14:19:58 +0100 Subject: [PATCH] ucm: add ${eval:EXPR} substitution (Syntax 5) It is useful to do simple integer math in UCM configurations, too. Use snd_config_evaluate_string() string for this job. Example: ${eval:1+1} ${eval:100*$var1} ${eval:$[$var2+1]/5} Signed-off-by: Jaroslav Kysela --- src/confeval.c | 8 ++++---- src/ucm/ucm_local.h | 2 +- src/ucm/ucm_subs.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/confeval.c b/src/confeval.c index 62d88697..c8d36f1e 100644 --- a/src/confeval.c +++ b/src/confeval.c @@ -119,8 +119,8 @@ static int _to_integer(value_type_t *val, snd_config_t *c) return 0; } -static int _eval_string(snd_config_t **dst, const char *s, - snd_config_expand_fcn_t fcn, void *private_data) +int _snd_eval_string(snd_config_t **dst, const char *s, + snd_config_expand_fcn_t fcn, void *private_data) { snd_config_t *tmp; const char *save, *e; @@ -174,7 +174,7 @@ static int _eval_string(snd_config_t **dst, const char *s, return -ENOMEM; memcpy(m, s + 2, e - s - 2); m[e - s - 3] = '\0'; - err = _eval_string(&tmp, m, fcn, private_data); + err = _snd_eval_string(&tmp, m, fcn, private_data); free(m); if (err < 0) return err; @@ -250,7 +250,7 @@ int snd_config_evaluate_string(snd_config_t **dst, const char *s, if (*s != '$') return -EINVAL; if (s[1] == '[') { - err = _eval_string(dst, s, fcn, private_data); + err = _snd_eval_string(dst, s, fcn, private_data); if (err < 0) SNDERR("wrong expression '%s'", s); } else { diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h index 44791b32..e6ebe0f3 100644 --- a/src/ucm/ucm_local.h +++ b/src/ucm/ucm_local.h @@ -40,7 +40,7 @@ #include #include "use-case.h" -#define SYNTAX_VERSION_MAX 4 +#define SYNTAX_VERSION_MAX 5 #define MAX_CARD_SHORT_NAME 32 #define MAX_CARD_LONG_NAME 80 diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c index 20905c3f..b6fc7be4 100644 --- a/src/ucm/ucm_subs.c +++ b/src/ucm/ucm_subs.c @@ -585,6 +585,42 @@ static char *rval_var(snd_use_case_mgr_t *uc_mgr, const char *id) return NULL; } +int _snd_eval_string(snd_config_t **dst, const char *s, + snd_config_expand_fcn_t fcn, void *private_data); + +static int rval_eval_var_cb(snd_config_t **dst, const char *s, void *private_data) +{ + snd_use_case_mgr_t *uc_mgr = private_data; + const char *v; + + v = uc_mgr_get_variable(uc_mgr, s); + if (v == NULL) + return -ENOENT; + return snd_config_imake_string(dst, NULL, v); +} + +static char *rval_eval(snd_use_case_mgr_t *uc_mgr, const char *e) +{ + snd_config_t *dst; + char *r; + int err; + + if (uc_mgr->conf_format < 5) { + uc_error("variable substitution is supported in v5+ syntax"); + return NULL; + } + err = _snd_eval_string(&dst, e, rval_eval_var_cb, uc_mgr); + if (err < 0) { + uc_error("unable to evaluate '%s'", e); + return NULL; + } + err = snd_config_get_ascii(dst, &r); + snd_config_delete(dst); + if (err < 0) + return NULL; + return r; +} + #define MATCH_VARIABLE(name, id, fcn, empty_ok) \ if (strncmp((name), (id), sizeof(id) - 1) == 0) { \ rval = fcn(uc_mgr); \ @@ -688,6 +724,7 @@ __std: MATCH_VARIABLE2(value, "${env:", rval_env, false); MATCH_VARIABLE2(value, "${sys:", rval_sysfs, false); MATCH_VARIABLE2(value, "${var:", rval_var, true); + MATCH_VARIABLE2(value, "${eval:", rval_eval, false); MATCH_VARIABLE2(value, "${find-card:", rval_card_lookup, false); MATCH_VARIABLE2(value, "${find-device:", rval_device_lookup, false); MATCH_VARIABLE2(value, "${CardNumberByName:", rval_card_number_by_name, false); -- 2.47.1