|
Packit Service |
f36a15 |
/*
|
|
Packit Service |
f36a15 |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
f36a15 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
f36a15 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
f36a15 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit Service |
f36a15 |
*
|
|
Packit Service |
f36a15 |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
f36a15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f36a15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
f36a15 |
* Lesser General Public License for more details.
|
|
Packit Service |
f36a15 |
*
|
|
Packit Service |
f36a15 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
f36a15 |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
f36a15 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit Service |
f36a15 |
*
|
|
Packit Service |
f36a15 |
* Support for the verb/device/modifier core logic and API,
|
|
Packit Service |
f36a15 |
* command line tool and file parser was kindly sponsored by
|
|
Packit Service |
f36a15 |
* Texas Instruments Inc.
|
|
Packit Service |
f36a15 |
* Support for multiple active modifiers and devices,
|
|
Packit Service |
f36a15 |
* transition sequences, multiple client access and user defined use
|
|
Packit Service |
f36a15 |
* cases was kindly sponsored by Wolfson Microelectronics PLC.
|
|
Packit Service |
f36a15 |
*
|
|
Packit Service |
f36a15 |
* Copyright (C) 2020 Red Hat Inc.
|
|
Packit Service |
f36a15 |
* Authors: Jaroslav Kysela <perex@perex.cz>
|
|
Packit Service |
f36a15 |
*/
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
#include "ucm_local.h"
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static int get_string(snd_config_t *compound, const char *key, const char **str)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
snd_config_t *node;
|
|
Packit Service |
f36a15 |
int err;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = snd_config_search(compound, key, &node);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
return snd_config_get_string(node, str);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static int include_eval_one(snd_use_case_mgr_t *uc_mgr,
|
|
Packit Service |
f36a15 |
snd_config_t *inc,
|
|
Packit Service |
f36a15 |
snd_config_t **result,
|
|
Packit Service |
f36a15 |
snd_config_t **before,
|
|
Packit Service |
f36a15 |
snd_config_t **after)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
const char *file;
|
|
Packit Service |
f36a15 |
char *s;
|
|
Packit Service |
f36a15 |
int err;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
*result = NULL;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (snd_config_get_type(inc) != SND_CONFIG_TYPE_COMPOUND) {
|
|
Packit Service |
f36a15 |
uc_error("compound type expected for Include.1");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = get_string(inc, "File", &file;;
|
|
Packit Service |
f36a15 |
if (err < 0) {
|
|
Packit Service |
f36a15 |
uc_error("file expected (Include)");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = snd_config_search(inc, "Before", before);
|
|
Packit Service |
f36a15 |
if (err < 0 && err != -ENOENT) {
|
|
Packit Service |
f36a15 |
uc_error("before block identifier error");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = snd_config_search(inc, "After", after);
|
|
Packit Service |
f36a15 |
if (err < 0 && err != -ENOENT) {
|
|
Packit Service |
f36a15 |
uc_error("before block identifier error");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = uc_mgr_get_substituted_value(uc_mgr, &s, file);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
err = uc_mgr_config_load_file(uc_mgr, s, result);
|
|
Packit Service |
f36a15 |
free(s);
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
#if 0
|
|
Packit Service |
f36a15 |
static void config_dump(snd_config_t *cfg)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
snd_output_t *out;
|
|
Packit Service |
f36a15 |
snd_output_stdio_attach(&out, stderr, 0);
|
|
Packit Service |
f36a15 |
snd_output_printf(out, "-----\n");
|
|
Packit Service |
f36a15 |
snd_config_save(cfg, out);
|
|
Packit Service |
f36a15 |
snd_output_close(out);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
#endif
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static int find_position_node(snd_config_t **res, snd_config_t *dst,
|
|
Packit Service |
f36a15 |
const char *id, snd_config_t *pos)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
const char *s;
|
|
Packit Service |
f36a15 |
int err;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
err = get_string(pos, id, &s);
|
|
Packit Service |
f36a15 |
if (err < 0 && err != -ENOENT)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
if (err == 0) {
|
|
Packit Service |
f36a15 |
err = snd_config_search(dst, s, res);
|
|
Packit Service |
f36a15 |
if (err < 0 && err != -ENOENT)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
return 0;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static int compound_merge(const char *id,
|
|
Packit Service |
f36a15 |
snd_config_t *dst, snd_config_t *src,
|
|
Packit Service |
f36a15 |
snd_config_t *before, snd_config_t *after)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
snd_config_iterator_t i, next;
|
|
Packit Service |
f36a15 |
snd_config_t *n, *_before = NULL, *_after = NULL;
|
|
Packit Service |
f36a15 |
char tmpid[32];
|
|
Packit Service |
f36a15 |
int err, array, idx;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) {
|
|
Packit Service |
f36a15 |
uc_error("compound type expected for the merged block");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (before) {
|
|
Packit Service |
f36a15 |
err = find_position_node(&_before, dst, id, before);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
if (after) {
|
|
Packit Service |
f36a15 |
err = find_position_node(&_after, dst, id, after);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (_before && _after) {
|
|
Packit Service |
f36a15 |
uc_error("defined both before and after identifiers in the If or Include block");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
array = snd_config_is_array(dst);
|
|
Packit Service |
f36a15 |
if (array < 0) {
|
|
Packit Service |
f36a15 |
uc_error("destination configuration node is not a compound");
|
|
Packit Service |
f36a15 |
return array;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
if (array && snd_config_is_array(src) <= 0) {
|
|
Packit Service |
f36a15 |
uc_error("source configuration node is not an array");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
idx = 0;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
/* for array, use a temporary non-clashing identifier */
|
|
Packit Service |
f36a15 |
if (array > 0) {
|
|
Packit Service |
f36a15 |
snd_config_for_each(i, next, dst) {
|
|
Packit Service |
f36a15 |
n = snd_config_iterator_entry(i);
|
|
Packit Service |
f36a15 |
snprintf(tmpid, sizeof(tmpid), "_tmp_%d", idx++);
|
|
Packit Service |
f36a15 |
err = snd_config_set_id(n, tmpid);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
snd_config_for_each(i, next, src) {
|
|
Packit Service |
f36a15 |
n = snd_config_iterator_entry(i);
|
|
Packit Service |
f36a15 |
err = snd_config_remove(n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
/* for array, use a temporary non-clashing identifier */
|
|
Packit Service |
f36a15 |
if (array > 0) {
|
|
Packit Service |
f36a15 |
snprintf(tmpid, sizeof(tmpid), "_tmp_%d", idx++);
|
|
Packit Service |
f36a15 |
err = snd_config_set_id(n, tmpid);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
if (_before) {
|
|
Packit Service |
f36a15 |
err = snd_config_add_before(_before, n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
_before = NULL;
|
|
Packit Service |
f36a15 |
_after = n;
|
|
Packit Service |
f36a15 |
} else if (_after) {
|
|
Packit Service |
f36a15 |
err = snd_config_add_after(_after, n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
_after = n;
|
|
Packit Service |
f36a15 |
} else {
|
|
Packit Service |
f36a15 |
err = snd_config_add(dst, n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
/* set new indexes for the final array */
|
|
Packit Service |
f36a15 |
if (array > 0) {
|
|
Packit Service |
f36a15 |
idx = 0;
|
|
Packit Service |
f36a15 |
snd_config_for_each(i, next, dst) {
|
|
Packit Service |
f36a15 |
n = snd_config_iterator_entry(i);
|
|
Packit Service |
f36a15 |
snprintf(tmpid, sizeof(tmpid), "%d", idx++);
|
|
Packit Service |
f36a15 |
err = snd_config_set_id(n, tmpid);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
return 0;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx,
|
|
Packit Service |
f36a15 |
snd_config_t *before, snd_config_t *after)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
snd_config_iterator_t i, next;
|
|
Packit Service |
f36a15 |
snd_config_t *n, *parent2;
|
|
Packit Service |
f36a15 |
const char *id;
|
|
Packit Service |
f36a15 |
int err;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
snd_config_for_each(i, next, new_ctx) {
|
|
Packit Service |
f36a15 |
n = snd_config_iterator_entry(i);
|
|
Packit Service |
f36a15 |
err = snd_config_remove(n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
err = snd_config_get_id(n, &id;;
|
|
Packit Service |
f36a15 |
if (err < 0) {
|
|
Packit Service |
f36a15 |
__add:
|
|
Packit Service |
f36a15 |
err = snd_config_add(parent, n);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
continue;
|
|
Packit Service |
f36a15 |
} else {
|
|
Packit Service |
f36a15 |
err = snd_config_search(parent, id, &parent2);
|
|
Packit Service |
f36a15 |
if (err == -ENOENT)
|
|
Packit Service |
f36a15 |
goto __add;
|
|
Packit Service |
f36a15 |
err = compound_merge(id, parent2, n, before, after);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
snd_config_delete(n);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
return 0;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
/*
|
|
Packit Service |
f36a15 |
* put back the included configuration to the parent
|
|
Packit Service |
f36a15 |
*/
|
|
Packit Service |
f36a15 |
int uc_mgr_evaluate_include(snd_use_case_mgr_t *uc_mgr,
|
|
Packit Service |
f36a15 |
snd_config_t *parent,
|
|
Packit Service |
f36a15 |
snd_config_t *inc)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
snd_config_iterator_t i, next;
|
|
Packit Service |
f36a15 |
snd_config_t *a, *n, *before, *after;
|
|
Packit Service |
f36a15 |
int err;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3) {
|
|
Packit Service |
f36a15 |
uc_error("in-place include is supported in v3+ syntax");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (snd_config_get_type(inc) != SND_CONFIG_TYPE_COMPOUND) {
|
|
Packit Service |
f36a15 |
uc_error("compound type expected for Include");
|
|
Packit Service |
f36a15 |
return -EINVAL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
snd_config_for_each(i, next, inc) {
|
|
Packit Service |
f36a15 |
n = snd_config_iterator_entry(i);
|
|
Packit Service |
f36a15 |
before = after = NULL;
|
|
Packit Service |
f36a15 |
err = include_eval_one(uc_mgr, n, &a, &before, &after);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
if (a == NULL)
|
|
Packit Service |
f36a15 |
continue;
|
|
Packit Service |
f36a15 |
err = uc_mgr_evaluate_inplace(uc_mgr, a);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
err = uc_mgr_config_tree_merge(parent, a, before, after);
|
|
Packit Service |
f36a15 |
if (err < 0)
|
|
Packit Service |
f36a15 |
return err;
|
|
Packit Service |
f36a15 |
snd_config_delete(a);
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
return 0;
|
|
Packit Service |
f36a15 |
}
|