-----Original Message-----
From: fred [mailto:[EMAIL PROTECTED] 
Sent: 20 March 2007 09:23
To: 'Stipe Tolj'
Subject: RE: [REQ] generic config struct for parameter value lists

I needed such a feature, here is an example:

Here the LHS is a list of reg expressions, match and the substitution expression

mt-dest-addr-regex-subst = "^1([1-9][0-9]{9})$" "$1"
                         = "^0([2-9][0-9]{9})$" "$1"

mo-source-addr-regex-subst = "(^[2-9][0-9]{9})$" "1$1"
                        = "^0([2-9][0-9]{9})$" "1$1" 


All the stuff is in cfg.c, so I'll simply attach my version....


-----Original Message-----
From: Stipe Tolj [mailto:[EMAIL PROTECTED]
Sent: 20 March 2007 03:27
To: Kannel Development list
Subject: [REQ] generic config struct for parameter value lists

Hi list,

I have some good input on extending Kannel's config handling abilities:

Currently we have several needs for a config value list, some examples:

   group = smsc
   ...
   accepted-smsc-id = "A;B;C"

   group = sms-service
   ...
   aliases = "key2;key3;key4"

   group = smsbox-route
   ...
   shortcode = "1111;2222;3333"

so, all of these are either of type word-list or id-list, semantically it's a
semicolon seperated list. For some parts we have defined foobar-regex config
directives to handle PCRE/regex for a more simple definition.

The idea now is to create a more generic construct for this, which handles 3
(maybe more?) different ways for any "list-type":

   foobar = "A;B;C"
   foobar-url = "http://somewhere/foobar-list";
   foobar-regex = "<the regex expression>"

so users can *CHOOSE* which way they prefer. And we handle the processing of the
list "transparently" to the logic that requires the list from the config
sections.

I like this concept of abstraction here. Since we would encapsulate the plain,
-url and -regex handling to the scope of gwlib/cfg.{ch] and the other calling
modules simply pull for the list.

Thoughts?

-------------------------------------------------------------------
Kölner Landstrasse 419
40589 Düsseldorf, NRW, Germany

tolj.org system architecture      Kannel Software Foundation (KSF)
http://www.tolj.org/              http://www.kannel.org/

mailto:st_{at}_tolj.org           mailto:stolj_{at}_kannel.org
-------------------------------------------------------------------


/* ==================================================================== 
 * The Kannel Software License, Version 1.0 
 * 
 * Copyright (c) 2001-2005 Kannel Group  
 * Copyright (c) 1998-2001 WapIT Ltd.   
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution. 
 * 
 * 3. The end-user documentation included with the redistribution, 
 *    if any, must include the following acknowledgment: 
 *       "This product includes software developed by the 
 *        Kannel Group (http://www.kannel.org/)." 
 *    Alternately, this acknowledgment may appear in the software itself, 
 *    if and wherever such third-party acknowledgments normally appear. 
 * 
 * 4. The names "Kannel" and "Kannel Group" must not be used to 
 *    endorse or promote products derived from this software without 
 *    prior written permission. For written permission, please  
 *    contact [EMAIL PROTECTED] 
 * 
 * 5. Products derived from this software may not be called "Kannel", 
 *    nor may "Kannel" appear in their name, without prior written 
 *    permission of the Kannel Group. 
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 * ==================================================================== 
 * 
 * This software consists of voluntary contributions made by many 
 * individuals on behalf of the Kannel Group.  For more information on  
 * the Kannel Group, please see <http://www.kannel.org/>. 
 * 
 * Portions of this software are based upon software originally written at  
 * WapIT Ltd., Helsinki, Finland for the Kannel project.  
 */ 

/*
 * cfg.c - configuration file handling
 *
 * Lars Wirzenius
 */


#include "gwlib/gwlib.h"

/* for include dir */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

struct CfgGroup {
    Octstr *name;
    Dict *vars;
    Octstr *configfile; 
    long line; 
};


static CfgGroup *create_group(void)
{
    CfgGroup *grp;
    
    grp = gw_malloc(sizeof(*grp));
    grp->name = NULL;
    grp->vars = dict_create(64, octstr_destroy_item);
    grp->configfile = NULL; 
    grp->line = 0; 
    return grp;
}

static void destroy_group(void *arg)
{
    CfgGroup *grp;
    List *names;
    Octstr *name=0;
   
    if (arg != NULL) 
        {
                grp = arg;
                names = dict_keys(grp->vars);
                while ((name = gwlist_extract_first(names)) != NULL) 
                {
                        if(cfg_type_(name)==TYP_OCTSTRARY)
                        {
                                cfg_destroy_list(grp,name);
                        }
            octstr_destroy(name); 
                }
                octstr_destroy(grp->name);
                octstr_destroy(grp->configfile);

                
                dict_destroy(grp->vars);
                gw_free(grp);
    }
}


struct CfgLoc { 
    Octstr *filename; 
    long line_no; 
    Octstr *line; 
}; 


static CfgLoc *cfgloc_create(Octstr *filename) 
{ 
    CfgLoc *cfgloc; 
     
    cfgloc = gw_malloc(sizeof(*cfgloc)); 
    cfgloc->filename = octstr_duplicate(filename); 
    cfgloc->line_no = 0; 
    cfgloc->line = NULL; 
    return cfgloc; 
} 
 
 
static void cfgloc_destroy(CfgLoc *cfgloc) 
{ 
    if (cfgloc != NULL) { 
                octstr_destroy(cfgloc->filename); 
                octstr_destroy(cfgloc->line); 
                gw_free(cfgloc); 
    } 
} 

 
static void destroy_group_list(void *arg)
{
    gwlist_destroy(arg, destroy_group);
}


static void set_group_name(CfgGroup *grp, Octstr *name)
{
    octstr_destroy(grp->name);
    grp->name = octstr_duplicate(name);
}


struct Cfg {
    Octstr *filename;
    Dict *single_groups;
    Dict *multi_groups;
};


static int is_allowed_in_group(Octstr *group, Octstr *variable)
{
    Octstr *groupstr;
    
    groupstr = octstr_imm("group");

    #define OCTSTR(name) \
        if (octstr_compare(octstr_imm(#name), variable) == 0) \
            return 1;
    #define OCTSTRARY(name) \
        if (octstr_compare(octstr_imm(#name), variable) == 0) \
            return 1;
    #define SINGLE_GROUP(name, fields) \
        if (octstr_compare(octstr_imm(#name), group) == 0) { \
            if (octstr_compare(groupstr, variable) == 0) \
                return 1; \
            fields \
            return 0; \
        }
    #define MULTI_GROUP(name, fields) \
        if (octstr_compare(octstr_imm(#name), group) == 0) { \
            if (octstr_compare(groupstr, variable) == 0) \
                return 1; \
            fields \
            return 0; \
        }
    #include "cfg.def"

    return 0;
}


static int is_single_group(Octstr *query)
{
    #define OCTSTR(name)
    #define OCTSTRARY(name) 
    #define SINGLE_GROUP(name, fields) \
        if (octstr_compare(octstr_imm(#name), query) == 0) \
            return 1;
    #define MULTI_GROUP(name, fields) \
        if (octstr_compare(octstr_imm(#name), query) == 0) \
            return 0;
    #include "cfg.def"
    return 0;
}


static int add_group(Cfg *cfg, CfgGroup *grp)
{
    Octstr *groupname;
    Octstr *name;
    List *names;
    List *list;
    
    groupname = cfg_get(grp, octstr_imm("group"));
    if (groupname == NULL) {
                error(0, "Group does not contain variable 'group'.");
        return -1;
    }
    set_group_name(grp, groupname);

    names = dict_keys(grp->vars);
    while ((name = gwlist_extract_first(names)) != NULL) 
        {
                if (!is_allowed_in_group(groupname, name)) 
                {
                        error(0, "Group '%s' may not contain field '%s'.",
                        octstr_get_cstr(groupname), octstr_get_cstr(name));
                        octstr_destroy(name);
                        octstr_destroy(groupname);
                        gwlist_destroy(names, octstr_destroy_item);
                        return -1;
                }
                octstr_destroy(name);
    }
    gwlist_destroy(names, NULL);

    if (is_single_group(groupname))
        dict_put(cfg->single_groups, groupname, grp);
    else {
        list = dict_get(cfg->multi_groups, groupname);
        if (list == NULL) {
            list = gwlist_create();
            dict_put(cfg->multi_groups, groupname, list);
        }
        gwlist_append(list, grp);
    }

    octstr_destroy(groupname);
    return 0;
}


Cfg *cfg_create(Octstr *filename)
{
    Cfg *cfg;
    
    cfg = gw_malloc(sizeof(*cfg));
    cfg->filename = octstr_duplicate(filename);
    cfg->single_groups = dict_create(64, destroy_group);
    cfg->multi_groups = dict_create(64, destroy_group_list);
    return cfg;
}


void cfg_destroy(Cfg *cfg)
{

    if (cfg != NULL) {
                octstr_destroy(cfg->filename);

                dict_destroy(cfg->single_groups);
                dict_destroy(cfg->multi_groups);
                gw_free(cfg);
    }
}


static void parse_value(Octstr *value)
{
    Octstr *temp;
    long len;
    int c;
    
    octstr_strip_blanks(value);

    len = octstr_len(value);
    if (octstr_get_char(value, 0) != '"' || 
        octstr_get_char(value, len - 1) != '"')
        return;

    octstr_delete(value, len - 1, 1);
    octstr_delete(value, 0, 1);

    temp = octstr_duplicate(value);
    octstr_truncate(value, 0);
    
    while (octstr_len(temp) > 0) {
        c = octstr_get_char(temp, 0);
        octstr_delete(temp, 0, 1);
        
        if (c != '\\' || octstr_len(temp) == 0)
            octstr_append_char(value, c);
        else {
            c = octstr_get_char(temp, 0);
            octstr_delete(temp, 0, 1);

            switch (c) {
            case '\\':
            case '"':
                octstr_append_char(value, c);
                break;
                
            default:
                octstr_append_char(value, '\\');
                octstr_append_char(value, c);
                break;
            }
        }
    }
    
    octstr_destroy(temp);
}


static List *expand_file(Octstr *file, int forward) 
{
    Octstr *os;
    Octstr *line;
    List *lines; 
    List *expand; 
    long lineno; 
    CfgLoc *loc; 
 
    os = octstr_read_file(octstr_get_cstr(file)); 
    if (os == NULL) 
        return NULL; 
 
    lines = octstr_split(os, octstr_imm("\n")); 
    lineno = 0; 
    expand = gwlist_create(); 
              
    while ((line = gwlist_extract_first(lines)) != NULL) { 
        ++lineno; 
        loc = cfgloc_create(file); 
        loc->line_no = lineno; 
        loc->line = line; 
        if (forward) 
            gwlist_append(expand, loc); 
        else 
            gwlist_insert(expand, 0, loc); 
    } 
    
    /* 
     * add newline at each end of included files to avoid 
     * concatenating different groups by mistake
     */
    if (lineno > 0) {
        loc = cfgloc_create(file); 
        loc->line_no = lineno;
        loc->line = octstr_create("\n");
        if (forward) 
            gwlist_append(expand, loc); 
        else 
            gwlist_insert(expand, 0, loc); 
    }
         
    gwlist_destroy(lines, octstr_destroy_item); 
    octstr_destroy(os); 
 
    return expand; 
} 
 
 
int cfg_read(Cfg *cfg) 
{ 
    CfgLoc *loc; 
    CfgLoc *loc_inc; 
    List *lines;
    List *expand; 
    List *stack; 
    Octstr *name;
    Octstr *value;
    Octstr *filename; 
    CfgGroup *grp;
        List *valuelist=0;
    long equals;
    long lineno;
    long error_lineno;
    
    loc = loc_inc = NULL;

    /* 
     * expand initial main config file and add it to the recursion 
     * stack to protect against cycling 
     */ 
    if ((lines = expand_file(cfg->filename, 1)) == NULL) { 
        panic(0, "Failed to load main configuration file `%s'. Aborting!", 
              octstr_get_cstr(cfg->filename)); 
    } 
    stack = gwlist_create(); 
    gwlist_insert(stack, 0, octstr_duplicate(cfg->filename)); 

    grp = NULL;
    lineno = 0;
    error_lineno = 0;
    while (error_lineno == 0 && (loc = gwlist_extract_first(lines)) != NULL) 
        { 
        octstr_strip_blanks(loc->line); 
        if (octstr_len(loc->line) == 0) 
                { 
            if (grp != NULL && add_group(cfg, grp) == -1) { 
                error_lineno = loc->line_no; 
                destroy_group(grp); 
            } 
            grp = NULL; 
        } 
                else if (octstr_get_char(loc->line, 0) != '#') 
                { 
            equals = octstr_search_char(loc->line, '=', 0); 
            if (equals == -1) { 
                error(0, "An equals sign ('=') is missing on line %ld of file 
%s.", 
                      loc->line_no, octstr_get_cstr(loc->filename)); 
                error_lineno = loc->line_no; 
            } 
                        else  
             
            /* 
             * check for special config directives, like include or conditional 
             * directives here 
             */ 
            if (octstr_search(loc->line, octstr_imm("include"), 0) != -1) 
                        { 
                filename = octstr_copy(loc->line, equals + 1, 
octstr_len(loc->line)); 
                parse_value(filename); 
 
                /* check if we are cycling */ 
                if (gwlist_search(stack, filename, octstr_item_match) != NULL) 
{ 
                    panic(0, "Recursive include for config file `%s' detected " 
                             "(on line %ld of file %s).", 
                          octstr_get_cstr(filename), loc->line_no,  
                          octstr_get_cstr(loc->filename)); 
                } else {     
                    List *files = gwlist_create();
                    Octstr *file;
                    struct stat filestat;

                    /* check if included file is a directory */
                    lstat(octstr_get_cstr(filename), &filestat);

                    /* 
                     * is a directory, create a list with files of
                     * this directory and load all as part of the
                     * whole configuration.
                     */
                    if (S_ISDIR(filestat.st_mode)) {
                        DIR *dh;
                        struct dirent *diritem;

                        debug("gwlib.cfg", 0, "Loading include dir `%s' "
                              "(on line %ld of file %s).",  
                              octstr_get_cstr(filename), loc->line_no,  
                              octstr_get_cstr(loc->filename)); 

                        dh = opendir(octstr_get_cstr(filename));
                        while ((diritem = readdir(dh))) {
                            Octstr *fileitem;

                            fileitem = octstr_duplicate(filename);
                            octstr_append(fileitem, octstr_create("/"));
                            octstr_append(fileitem, 
octstr_create(diritem->d_name));

                            lstat(octstr_get_cstr(fileitem), &filestat);
                            if (!S_ISDIR(filestat.st_mode)) {
                                gwlist_insert(files, 0, fileitem);
                            }
                        }
                        closedir(dh);
                    } 
                    
                    /* is a file, create a list with it */
                    else {
                        gwlist_insert(files, 0, octstr_duplicate(filename));
                    }

                    /* include files */
                    while ((file = gwlist_extract_first(files)) != NULL) 
                                        {

                        gwlist_insert(stack, 0, octstr_duplicate(file)); 
                        debug("gwlib.cfg", 0, "Loading include file `%s' (on 
line %ld of file %s).",  
                              octstr_get_cstr(file), loc->line_no,  
                              octstr_get_cstr(loc->filename)); 

                        /*  
                         * expand the given include file and add it to the 
current 
                         * processed main while loop 
                         */ 
                        if ((expand = expand_file(file, 0)) != NULL) {
                            while ((loc_inc = gwlist_extract_first(expand)) != 
NULL) 
                                gwlist_insert(lines, 0, loc_inc); 
                        } else { 
                            panic(0, "Failed to load whole configuration. 
Aborting!"); 
                        } 
                 
                        gwlist_destroy(expand, NULL); 
                        cfgloc_destroy(loc_inc);
                        octstr_destroy(file);
                    }
                    gwlist_destroy(files, octstr_destroy_item);
                } 
                octstr_destroy(filename); 
            }  
             
            /* 
             * this is a "normal" line, so process it accodingly 
             */ 
            else  
                        { 
                                int cfg_type;
                                if (grp == NULL)
                    grp = create_group(); 

                if (grp->configfile != NULL) 
                                {
                    octstr_destroy(grp->configfile); grp->configfile=NULL;
                }
                grp->configfile = octstr_duplicate(cfg->filename); 

                name = octstr_copy(loc->line, 0, equals); 
                octstr_strip_blanks(name); 
                value = octstr_copy(loc->line, equals + 1, 
octstr_len(loc->line)); 
                                
                                cfg_type = cfg_type_(name);

                                if(octstr_len(name) > 0 )               // a 
line starting with a name stops/starts an array
                                {
                                        if(cfg_type == TYP_OCTSTRARY )  // 
consecutive lines starting with '=' are part of this list
                                        {
                                                valuelist = gwlist_create(); 
                                                cfg_set_list(grp, name, 
valuelist); 
                                        }
                                        else if(valuelist) 
                                        {
                                                valuelist=0;
                                        }
                                }

                                if(valuelist)
                                {
                                        gwlist_insert(valuelist, 0, 
octstr_duplicate(value)); 
                                }
                                else
                                {
                                        if(octstr_len(name) ==0)
                                        {
                                error(0, "line is not an array setting: line 
%ld file %s.", 
                                                                loc->line_no, 
octstr_get_cstr(loc->filename)); 
                                                error_lineno = loc->line_no; 
                                                break;
                                        }

                                        parse_value(value); 
                                        cfg_set(grp, name, value); 
                                }
                                
                octstr_destroy(name); 
                octstr_destroy(value); 
                        } 
                } 

        cfgloc_destroy(loc); 
    }

    if (grp != NULL && add_group(cfg, grp) == -1) {
        error_lineno = 1; 
        destroy_group(grp); 
    }

    gwlist_destroy(lines, NULL); 
    gwlist_destroy(stack, octstr_destroy_item); 

    if (error_lineno != 0) {
        error(0, "Error found on line %ld of file `%s'.",  
                  error_lineno, octstr_get_cstr(cfg->filename)); 
        return -1; 
    }

    return 0;
}


CfgGroup *cfg_get_single_group(Cfg *cfg, Octstr *name)
{
    return dict_get(cfg->single_groups, name);
}


List *cfg_get_multi_group(Cfg *cfg, Octstr *name)
{
    List *list, *copy;
    long i;
    
    list = dict_get(cfg->multi_groups, name);
    if (list == NULL)
        return NULL;

    copy = gwlist_create();
    for (i = 0; i < gwlist_len(list); ++i)
        gwlist_append(copy, gwlist_get(list, i));
    return copy;
}


Octstr *cfg_get_group_name(CfgGroup *grp)
{
    return octstr_duplicate(grp->name);
}

Octstr *cfg_get_configfile(CfgGroup *grp)
{
    return octstr_duplicate(grp->configfile);
}


Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file, 
                     long line, const char *func)
{
    Octstr *os;

    if(grp == NULL) 
        panic(0, "Trying to fetch variable `%s' in non-existing group",
              octstr_get_cstr(varname));

    if (grp->name != NULL && !is_allowed_in_group(grp->name, varname))
        panic(0, "Trying to fetch variable `%s' in group `%s', not allowed.",
              octstr_get_cstr(varname), octstr_get_cstr(grp->name));

    os = dict_get(grp->vars, varname);
    if (os == NULL)
        return NULL;
    return gw_claim_area_for(octstr_duplicate(os), file, line, func);
}


int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
{
    Octstr *os;
    int ret;
    
    os = cfg_get(grp, varname);
    if (os == NULL)
        return -1;
    if (octstr_parse_long(n, os, 0, 0) == -1)
        ret = -1;
    else
        ret = 0;
    octstr_destroy(os);
    return ret;
}


int cfg_get_longlong(longlong_t *n, CfgGroup *grp, Octstr *varname)
{
    Octstr *os;
    int ret=0;
    
    os = cfg_get(grp, varname);
    if (os == NULL)
        return -1;
    if (octstr_parse_longlongnumber(n, os, 0) == -1)
                if(errno == EINVAL || errno == ERANGE)
                ret = -1;
    
    octstr_destroy(os);
    return ret;
}


int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
{
    Octstr *os;

    os = cfg_get(grp, varname);
    if (os == NULL) {
                *n = 0;
        return -1;
    }
    if (octstr_case_compare(os, octstr_imm("true")) == 0
        || octstr_case_compare(os, octstr_imm("yes")) == 0
        || octstr_case_compare(os, octstr_imm("on")) == 0
        || octstr_case_compare(os, octstr_imm("1")) == 0)
    {       
        *n = 1;
    } else if (octstr_case_compare(os, octstr_imm("false")) == 0
        || octstr_case_compare(os, octstr_imm("no")) == 0
        || octstr_case_compare(os, octstr_imm("off")) == 0
        || octstr_case_compare(os, octstr_imm("0")) == 0)
    {
                *n = 0;
    }
    else {
                *n = 1;
                warning(0, "bool variable set to strange value, assuming 
'true'");
    }
    octstr_destroy(os);
    return 0;
}


List *cfg_get_list(CfgGroup *grp, Octstr *varname)
{
    List *list;
    
    if(grp == NULL) 
        panic(0, "Trying to fetch variable `%s' in non-existing group",
              octstr_get_cstr(varname));

    if (grp->name != NULL && !is_allowed_in_group(grp->name, varname))
        panic(0, "Trying to fetch variable `%s' in group `%s', not allowed.",
              octstr_get_cstr(varname), octstr_get_cstr(grp->name));

    list = dict_get(grp->vars, varname);
    if (list == NULL)
        return NULL;


    return list;
}


/**
 * read config lines like
 * source-addr-regex-subst = "(^[2-9][0-9]{9})" "1$1"
 *                                                 = "(^0[2-9][0-9]{9})" "1$1"
 *
 *
 */
List *cfg_get_lineslist(CfgGroup *grp, Octstr *varname)
{
    Octstr *os;
    List *list;
    
    os = cfg_get(grp, varname);
    if (os == NULL)
        return NULL;

    list = octstr_split_words(os);
    octstr_destroy(os);
    return list;
}



void cfg_set(CfgGroup *grp, Octstr *varname, Octstr *value)
{
    dict_put(grp->vars, varname, octstr_duplicate(value));
}


void cfg_set_list(CfgGroup *grp, Octstr *varname, List *value)
{
    List *list;
    list = dict_get(grp->vars, varname);
        if(list)
        {
                gwlist_destroy(list,octstr_destroy_item);
                dict_remove(grp->vars, varname);
        }
    dict_put(grp->vars, varname, value);
}

void cfg_destroy_list(CfgGroup *grp, Octstr *name)
{
        List *valuelist=0;
        valuelist = cfg_get_list(grp, name);
        gwlist_destroy(valuelist,octstr_destroy_item);
        dict_remove(grp->vars, name);
}


void grp_dump(CfgGroup *grp)
{
    List *names;
    Octstr *name;
    Octstr *value;
        List *valuelist=0;
        long listlen;
        long i;

    if (grp->name == NULL)
        debug("gwlib.cfg", 0, "  dumping group (name not set):");
    else
        debug("gwlib.cfg", 0, "  dumping group (%s):",
              octstr_get_cstr(grp->name));
    names = dict_keys(grp->vars);
    while ((name = gwlist_extract_first(names)) != NULL) 
        {
                if(cfg_type_(name)==TYP_OCTSTRARY)
                {
                        valuelist = cfg_get_list(grp, name);
                        listlen = gwlist_len(valuelist);
                        for(i=0;i<listlen;i++)
                        {
                                value = gwlist_get(valuelist,i);
                                debug("gwlib.cfg", 0, "    <%s> = <%s>", 
                                        octstr_get_cstr(name), 
octstr_get_cstr(value));
                        }

                octstr_destroy(name);

                }
                else
                {
                        value = cfg_get(grp, name);
                        debug("gwlib.cfg", 0, "    <%s> = <%s>", 
                                octstr_get_cstr(name), octstr_get_cstr(value));
                octstr_destroy(value);
                octstr_destroy(name);
                }
    }
    gwlist_destroy(names, NULL);
}


void cfg_dump(Cfg *cfg)
{
    CfgGroup *grp;
    List *list;
    List *names;
    Octstr *name;

    debug("gwlib.cfg", 0, "Dumping Cfg %p", (void *) cfg);
    debug("gwlib.cfg", 0, "  filename = <%s>", 
          octstr_get_cstr(cfg->filename));

    names = dict_keys(cfg->single_groups);
    while ((name = gwlist_extract_first(names)) != NULL)
        {
                grp = cfg_get_single_group(cfg, name);
                if (grp != NULL)
                        grp_dump(grp);
        octstr_destroy(name);
    }
    gwlist_destroy(names, NULL);

    names = dict_keys(cfg->multi_groups);
    while ((name = gwlist_extract_first(names)) != NULL) 
        {
                list = cfg_get_multi_group(cfg, name);
                while ((grp = gwlist_extract_first(list)) != NULL)
                        grp_dump(grp);

                gwlist_destroy(list, NULL);
        octstr_destroy(name);
    }
    gwlist_destroy(names, NULL);

    debug("gwlib.cfg", 0, "Dump ends.");
}

void cfg_dump_all(void)
{
    #define OCTSTR(name) \
        printf("%s = <please consult user doc>\n", #name);

    #define OCTSTRARY(name) \
                printf("OCTSTRARY %s <please consult user doc>\n", #name);

    #define SINGLE_GROUP(name, fields) \
        printf("#\n#  Single Group\n#\n"); \
        printf("group = %s\n", #name); \
        fields; \
        printf("\n\n");

    #define MULTI_GROUP(name, fields) \
        printf("#\n#  Multi Group\n#\n"); \
        printf("group = %s\n", #name); \
        fields; \
        printf("\n\n");

    #include "cfg.def"
}

int cfg_type_(Octstr *configname)
{
        #define OCTSTR(name) \
        if (octstr_compare(octstr_imm(#name), configname) == 0) \
            return TYP_OCTSTR;
                
        #define OCTSTRARY(name) \
        if (octstr_compare(octstr_imm(#name), configname) == 0) \
            return TYP_OCTSTRARY;

    #define SINGLE_GROUP(name, fields) fields

    #define MULTI_GROUP(name, fields)  fields

    #include "cfg.def"

        return TYP_NONE;
}

Reply via email to