struct ast_category {
char name[80];
- int ignored; /*!< do not let user of the config see this category -- set by (!) after the category decl; a template */
+ int ignored:1; /*!< do not let user of the config see this category -- set by (!) after the category decl; a template */
+ int loaded:1; /*!< 0 = created in memory, 1 = loaded from disk */
int include_level;
/*!
* \brief The file name from whence this declaration was read
if (!newcat) {
return -1;
}
+ (*cat)->loaded = 1;
(*cat)->lineno = lineno;
/* add comments */
var = cat->root;
while (var) {
struct ast_category_template_instance *x;
- int found = 0;
+ struct ast_variable *parent = NULL; /* last occurrence matching variable name */
+
+ /*
+ * When saving the configuration we have the option to preserve
+ * the effective category contents. If enabled, the template
+ * variables are materialized into the leaf categories. Here,
+ * we check to see if a variable is also present in the leaf
+ * and, if so, we do not keep just the leaf value (no point in
+ * duplicate "var = value" lines in the .conf.
+ */
+ if ((flags & CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT) && cat->loaded) {
+ if (var->inherited) {
+ struct ast_variable *v;
+ int skip = 0;
+
+ for (v = var->next; v; v = v->next) {
+ if (!strcasecmp(var->name, v->name)) {
+ /* skip earlier inherited duplicate */
+ skip = 1;
+ break;
+ }
+ }
+ if (skip) {
+ var = var->next;
+ continue;
+ }
+ }
+ }
+ /*
+ * Walk every template instance in the order Asterisk applies
+ * them, letting later templates override earlier ones.
+ */
AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
struct ast_variable *v;
- for (v = x->inst->root; v; v = v->next) {
+ struct ast_variable *last = NULL;
- if (flags & CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT) {
- if (!strcasecmp(var->name, v->name) && !strcmp(var->value, v->value)) {
- found = 1;
- break;
- }
- } else {
- if (var->inherited) {
- found = 1;
- break;
- } else {
- if (!strcasecmp(var->name, v->name) && !strcmp(var->value, v->value)) {
- found = 1;
- break;
- }
- }
+ /* Within a template, capture the last occurrence of the key. */
+ for (v = x->inst->root; v; v = v->next) {
+ if (!strcasecmp(var->name, v->name)) {
+ last = v;
}
}
- if (found) {
- break;
+
+ if (last) {
+ parent = last;
}
}
- if (found) {
- var = var->next;
- continue;
+
+ /* decide whether to write the variable */
+ if ((flags & CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT) && cat->loaded) {
+ /* materialize inherited vars; suppress only explicit exact dups */
+ if (!var->inherited && parent && !strcmp(var->value, parent->value)) {
+ var = var->next;
+ continue;
+ }
+ } else {
+ /* skip inherited, explicit exact dups */
+ if (var->inherited || (parent && !strcmp(var->value, parent->value))) {
+ var = var->next;
+ continue;
+ }
}
+
fi = set_fn(fn, sizeof(fn), var->file, configfile, fileset);
f = fopen(fn, "a");
if (!f) {