]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: add ${eval:EXPR} substitution (Syntax 5)
authorJaroslav Kysela <perex@perex.cz>
Tue, 30 Nov 2021 13:19:58 +0000 (14:19 +0100)
committerJaroslav Kysela <perex@perex.cz>
Tue, 30 Nov 2021 13:22:39 +0000 (14:22 +0100)
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 <perex@perex.cz>
src/confeval.c
src/ucm/ucm_local.h
src/ucm/ucm_subs.c

index 62d88697ffd1bff384135f66672d05a061e19034..c8d36f1ef35952f260ef862156ac47b75d4ee721 100644 (file)
@@ -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 {
index 44791b3223b526d01046cecf2a8529b9ba90974c..e6ebe0f314c2bab291d26136a2a48a2234bb5061 100644 (file)
@@ -40,7 +40,7 @@
 #include <pthread.h>
 #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
index 20905c3fb31838d33610479d2a3efabfb01fe032..b6fc7be44516199e57be54ceaa9e047d9fe1ce73 100644 (file)
@@ -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);