/* ** OSSP cfg - Configuration Parsing ** Copyright (c) 2002-2006 Ralf S. Engelschall ** Copyright (c) 2002-2006 The OSSP Project (http://www.ossp.org/) ** ** This file is part of OSSP cfg, a configuration parsing ** library which can be found at http://www.ossp.org/pkg/lib/cfg/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** 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. ** ** cfg_main.c: main API */ #include #include #include #include #include "cfg.h" #include "cfg_fmt.h" #include "cfg_main.h" #include "cfg_data.h" #include "cfg_node.h" #include "cfg_syn.h" #include "cfg_global.h" #define _CFG_VERS_C_AS_HEADER_ #include "cfg_vers.c" #undef _CFG_VERS_C_AS_HEADER_ long cfg_version(void) { return __cfg_version.v_hex; } cfg_rc_t cfg_create(cfg_t **cfg) { cfg_rc_t rc; if (cfg == NULL) return CFG_ERR_ARG; if ((*cfg = malloc(sizeof(cfg_t))) == NULL) return CFG_ERR_SYS; (*cfg)->root = NULL; (*cfg)->szError[0] = '\0'; (*cfg)->szErrorInfo[0] = '\0'; (*cfg)->rcErrorInfo = CFG_OK; if ((rc = cfg_grid_create(&((*cfg)->grid_nodes), sizeof(cfg_node_t), 512)) != CFG_OK) { free(*cfg); return rc; } if ((rc = cfg_grid_create(&((*cfg)->grid_tokens), 8192, 1)) != CFG_OK) { free(*cfg); cfg_grid_destroy((*cfg)->grid_nodes); return rc; } return CFG_OK; } static cfg_rc_t cfg_destroy_node(cfg_t *cfg, cfg_node_t *node, void *ctx) { cfg_node_destroy(cfg, node); return CFG_OK; } cfg_rc_t cfg_destroy(cfg_t *cfg) { if (cfg == NULL) return CFG_ERR_ARG; if (cfg->root != NULL) cfg_node_apply(cfg, cfg->root, NULL, NULL, cfg_destroy_node, NULL); cfg_grid_destroy(cfg->grid_nodes); cfg_grid_destroy(cfg->grid_tokens); free(cfg); return CFG_OK; } cfg_rc_t cfg_error_info(cfg_t *cfg, cfg_rc_t rv, const char *fmt, ...) { va_list ap; /* argument sanity check */ if (cfg == NULL || rv == CFG_OK || fmt == NULL) return CFG_ERR_ARG; /* remember error information */ va_start(ap, fmt); cfg_fmt_vsprintf(cfg->szErrorInfo, sizeof(cfg->szErrorInfo), fmt, ap); cfg->rcErrorInfo = rv; va_end(ap); return CFG_OK; } cfg_rc_t cfg_error(cfg_t *cfg, cfg_rc_t rv, char **error) { char *sz; char *cpBuf; int nBuf; int n; /* argument sanity check */ if (cfg == NULL || error == NULL) return CFG_ERR_ARG; /* start at begin of buffer */ cpBuf = cfg->szError; nBuf = sizeof(cfg->szError); /* translate result value into corresponding string */ if (rv == CFG_OK) sz = "everything ok"; else if (rv == CFG_ERR_ARG) sz = "invalid argument"; else if (rv == CFG_ERR_USE) sz = "invalid use"; else if (rv == CFG_ERR_MEM) sz = "no more memory available"; else if (rv == CFG_ERR_SYS) sz = "operating system error"; else if (rv == CFG_ERR_FMT) sz = "formatting error"; else if (rv == CFG_ERR_INT) sz = "internal error"; else if (rv == CFG_ERR_SYN) sz = "syntax error"; else if (rv == CFG_ERR_NDE) sz = "node reference error"; else sz = "unknown error"; n = cfg_fmt_sprintf(cpBuf, nBuf, "%s", sz); cpBuf += n; nBuf -= n; /* optionally annotate with error information */ if (rv == cfg->rcErrorInfo && cfg->szErrorInfo[0] != '\0') { n = cfg_fmt_sprintf(cpBuf, nBuf, "; %s", cfg->szErrorInfo); cpBuf += n; nBuf -= n; } /* optionally annotate with operating system error information */ if (rv == CFG_ERR_SYS) { n = cfg_fmt_sprintf(cpBuf, nBuf, "; %s (%d)", strerror(errno), errno); cpBuf += n; nBuf -= n; } /* return pointer to internal buffer */ *error = cfg->szError; return CFG_OK; } cfg_rc_t cfg_import(cfg_t *cfg, cfg_node_t *node, cfg_fmt_t fmt, const char *in_ptr, size_t in_len) { cfg_rc_t rv; char error[1024]; cfg_node_t *root; if (cfg == NULL || in_ptr == NULL) return CFG_ERR_ARG; if (node == NULL) node = cfg->root; if (fmt == CFG_FMT_CFG) { if ((rv = cfg_syn_import(cfg, &root, in_ptr, in_len, error, sizeof(error))) != CFG_OK) { cfg_error_info(cfg, rv, "%s", error); return rv; } } /* FIXME: CFG_FMT_XML */ else return CFG_ERR_INT; /* FIXME: merge: cfg->root[node] := cfg->root[node] + root */ cfg->root = root; return CFG_OK; } cfg_rc_t cfg_export(cfg_t *cfg, cfg_node_t *node, cfg_fmt_t fmt, char **ex_ptr, size_t ex_len) { cfg_rc_t rv; char *output; size_t n; if (cfg == NULL || ex_ptr == NULL) return CFG_ERR_ARG; if (node == NULL) node = cfg->root; if (fmt == CFG_FMT_CFG) { if ((rv = cfg_syn_export(cfg, node, &output)) != CFG_OK) return rv; } /* FIXME: CFG_FMT_XML */ else return CFG_ERR_INT; /* provide output */ if (ex_len == 0) *ex_ptr = output; else { n = strlen(output); if (n >= ex_len) return CFG_ERR_MEM; memmove(*ex_ptr, output, n+1); free(output); } return CFG_OK; }