Merged revisions 89036 via svnmerge from
authorSteve Murphy <murf@digium.com>
Tue, 6 Nov 2007 21:08:38 +0000 (21:08 +0000)
committerSteve Murphy <murf@digium.com>
Tue, 6 Nov 2007 21:08:38 +0000 (21:08 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r89036 | murf | 2007-11-06 10:52:50 -0700 (Tue, 06 Nov 2007) | 1 line

closes issue #8786 - where the [catname](!) and [catname](othercat1,othercat2,...) notation gets dropped across a ConfigUpdate (or any other thing that would cause a config file to be written). While I was at it, I also cleaned up some of the destroy routines to free up comments, which was not being done. Made sure the new struct I introduced is also cleaned up properly at destruction time. My code handles multiple template inclusions. Many thanks to ssokol for his patch, which, while not literally used in the final merge, served as a foundation for the fix.
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@89062 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/config.c

index e2f0a8d..736c542 100644 (file)
@@ -212,12 +212,19 @@ static struct ast_config_engine *config_engine_list;
 
 #define MAX_INCLUDE_LEVEL 10
 
 
 #define MAX_INCLUDE_LEVEL 10
 
+struct ast_category_template_instance {
+       char name[80]; /* redundant? */
+       const struct ast_category *inst;
+       AST_LIST_ENTRY(ast_category_template_instance) next;
+};
+
 struct ast_category {
        char name[80];
        int ignored;                    /*!< do not let user of the config see this category */
        int include_level;
        char *file;                /*!< the file name from whence this declaration was read */
        int lineno;
 struct ast_category {
        char name[80];
        int ignored;                    /*!< do not let user of the config see this category */
        int include_level;
        char *file;                /*!< the file name from whence this declaration was read */
        int lineno;
+       AST_LIST_HEAD_NOLOCK(template_instance_list, ast_category_template_instance) template_instances;
        struct ast_comment *precomments;
        struct ast_comment *sameline;
        struct ast_comment *trailing; /*!< the last object in the list will get assigned any trailing comments when EOF is hit */
        struct ast_comment *precomments;
        struct ast_comment *sameline;
        struct ast_comment *trailing; /*!< the last object in the list will get assigned any trailing comments when EOF is hit */
@@ -515,12 +522,45 @@ void ast_category_append(struct ast_config *config, struct ast_category *categor
        config->current = category;
 }
 
        config->current = category;
 }
 
+static void ast_destroy_comments(struct ast_category *cat)
+{
+       struct ast_comment *n, *p;
+       for (p=cat->precomments; p; p=n) {
+               n = p->next;
+               free(p);
+       }
+       for (p=cat->sameline; p; p=n) {
+               n = p->next;
+               free(p);
+       }
+       for (p=cat->trailing; p; p=n) {
+               n = p->next;
+               free(p);
+       }
+       cat->precomments = NULL;
+       cat->sameline = NULL;
+       cat->trailing = NULL;
+}
+
+static void ast_destroy_template_list(struct ast_category *cat)
+{
+       struct ast_category_template_instance *x;
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&cat->template_instances, x, next) {
+               AST_LIST_REMOVE_CURRENT(&cat->template_instances, next);
+               free(x);
+       }
+       AST_LIST_TRAVERSE_SAFE_END;
+}
+
 void ast_category_destroy(struct ast_category *cat)
 {
        ast_variables_destroy(cat->root);
 void ast_category_destroy(struct ast_category *cat)
 {
        ast_variables_destroy(cat->root);
-       if (cat->file)
+       if (cat->file) {
                free(cat->file);
                free(cat->file);
-       
+               cat->file = 0;
+       }
+       ast_destroy_comments(cat);
+       ast_destroy_template_list(cat);
        ast_free(cat);
 }
 
        ast_free(cat);
 }
 
@@ -606,7 +646,10 @@ void ast_category_rename(struct ast_category *cat, const char *name)
 static void inherit_category(struct ast_category *new, const struct ast_category *base)
 {
        struct ast_variable *var;
 static void inherit_category(struct ast_category *new, const struct ast_category *base)
 {
        struct ast_variable *var;
-
+       struct ast_category_template_instance *x = ast_calloc(1,sizeof(struct ast_category_template_instance));
+       strcpy(x->name, base->name);
+       x->inst = base;
+       AST_LIST_INSERT_TAIL(&new->template_instances, x, next);
        for (var = base->root; var; var = var->next)
                ast_variable_append(new, variable_clone(var));
 }
        for (var = base->root; var; var = var->next)
                ast_variable_append(new, variable_clone(var));
 }
@@ -711,7 +754,6 @@ int ast_category_delete(struct ast_config *cfg, const char *category)
        cat = cfg->root;
        while (cat) {
                if (cat->name == category) {
        cat = cfg->root;
        while (cat) {
                if (cat->name == category) {
-                       ast_variables_destroy(cat->root);
                        if (prev) {
                                prev->next = cat->next;
                                if (cat == cfg->last)
                        if (prev) {
                                prev->next = cat->next;
                                if (cat == cfg->last)
@@ -721,7 +763,7 @@ int ast_category_delete(struct ast_config *cfg, const char *category)
                                if (cat == cfg->last)
                                        cfg->last = NULL;
                        }
                                if (cat == cfg->last)
                                        cfg->last = NULL;
                        }
-                       ast_free(cat);
+                       ast_category_destroy(cat);
                        return 0;
                }
                prev = cat;
                        return 0;
                }
                prev = cat;
@@ -732,7 +774,6 @@ int ast_category_delete(struct ast_config *cfg, const char *category)
        cat = cfg->root;
        while (cat) {
                if (!strcasecmp(cat->name, category)) {
        cat = cfg->root;
        while (cat) {
                if (!strcasecmp(cat->name, category)) {
-                       ast_variables_destroy(cat->root);
                        if (prev) {
                                prev->next = cat->next;
                                if (cat == cfg->last)
                        if (prev) {
                                prev->next = cat->next;
                                if (cat == cfg->last)
@@ -742,7 +783,7 @@ int ast_category_delete(struct ast_config *cfg, const char *category)
                                if (cat == cfg->last)
                                        cfg->last = NULL;
                        }
                                if (cat == cfg->last)
                                        cfg->last = NULL;
                        }
-                       ast_free(cat);
+                       ast_category_destroy(cat);
                        return 0;
                }
                prev = cat;
                        return 0;
                }
                prev = cat;
@@ -762,11 +803,9 @@ void ast_config_destroy(struct ast_config *cfg)
 
        cat = cfg->root;
        while (cat) {
 
        cat = cfg->root;
        while (cat) {
-               ast_variables_destroy(cat->root);
                catn = cat;
                cat = cat->next;
                catn = cat;
                cat = cat->next;
-               ast_free(catn->file);
-               ast_free(catn);
+               ast_category_destroy(catn);
        }
        ast_free(cfg);
 }
        }
        ast_free(cfg);
 }
@@ -1528,7 +1567,20 @@ int config_text_file_save(const char *configfile, const struct ast_config *cfg,
                        if (!cat->precomments)
                                fprintf(f,"\n");
                        fprintf(f, "[%s]", cat->name);
                        if (!cat->precomments)
                                fprintf(f,"\n");
                        fprintf(f, "[%s]", cat->name);
-                       for (cmt = cat->sameline; cmt; cmt=cmt->next) {
+                       if (cat->ignored)
+                               fprintf(f, "(!)");
+                       if (!AST_LIST_EMPTY(&cat->template_instances)) {
+                               struct ast_category_template_instance *x;
+                               fprintf(f, "(");
+                               AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
+                                       fprintf(f,"%s",x->name);
+                                       if (x != AST_LIST_LAST(&cat->template_instances))
+                                               fprintf(f,",");
+                               }
+                               fprintf(f, ")");
+                       }
+                       for(cmt = cat->sameline; cmt; cmt=cmt->next)
+                       {
                                fprintf(f,"%s", cmt->cmt);
                        }
                        if (!cat->sameline)
                                fprintf(f,"%s", cmt->cmt);
                        }
                        if (!cat->sameline)
@@ -1543,6 +1595,23 @@ int config_text_file_save(const char *configfile, const struct ast_config *cfg,
                        
                        var = cat->root;
                        while (var) {
                        
                        var = cat->root;
                        while (var) {
+                               struct ast_category_template_instance *x;
+                               int found = 0;
+                               AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
+                                       struct ast_variable *v;
+                                       for (v = x->inst->root; v; v = v->next) {
+                                               if (!strcasecmp(var->name, v->name) && !strcmp(var->value, v->value)) {
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (found)
+                                               break;
+                               }
+                               if (found) {
+                                       var = var->next;
+                                       continue;
+                               }
                                set_fn(fn, sizeof(fn), var->file, configfile, fileset, &fi);
                                f = fopen(fn, "a");
                                if (!f)
                                set_fn(fn, sizeof(fn), var->file, configfile, fileset, &fi);
                                f = fopen(fn, "a");
                                if (!f)