/* ** OSSP cfg - Configuration Parsing ** Copyright (c) 2002-2006 Ralf S. Engelschall ** Copyright (c) 2002-2006 The OSSP Project ** ** 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.xs: Perl Binding (Perl/XS part) */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "cfg.h" /* find/apply callback context */ typedef struct { SV *fct; SV *ctx; } cb_ctx_t; /* find/apply callback wrapper */ static cfg_rc_t cb_fct(cfg_t *cfg, cfg_node_t *node, void *_ctx) { cb_ctx_t *ctx = (cb_ctx_t *)ctx; cfg_rc_t rc; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(PTR2IV(cfg)))); XPUSHs(sv_2mortal(newSViv(PTR2IV(node)))); XPUSHs(ctx->ctx); PUTBACK; if (call_sv(ctx->fct, G_SCALAR) != 1) croak("cfg_node_find: expected single scalar as return value from callback"); SPAGAIN; rc = (cfg_rc_t)SvIV(POPs); FREETMPS; LEAVE; return rc; } MODULE = OSSP::cfg PACKAGE = OSSP::cfg void constant(sv) PREINIT: dXSTARG; STRLEN len; int i; static struct { const char *name; int value; } constant_table[] = { { "CFG_OK", CFG_OK }, { "CFG_ERR_ARG", CFG_ERR_ARG }, { "CFG_ERR_USE", CFG_ERR_USE }, { "CFG_ERR_MEM", CFG_ERR_MEM }, { "CFG_ERR_SYS", CFG_ERR_SYS }, { "CFG_ERR_FMT", CFG_ERR_FMT }, { "CFG_ERR_INT", CFG_ERR_INT }, { "CFG_ERR_SYN", CFG_ERR_SYN }, { "CFG_ERR_NDE", CFG_ERR_NDE }, { "CFG_FMT_CFG", CFG_FMT_CFG }, { "CFG_FMT_XML", CFG_FMT_XML }, { "CFG_NODE_TYPE_SEQ", CFG_NODE_TYPE_SEQ }, { "CFG_NODE_TYPE_DIR", CFG_NODE_TYPE_DIR }, { "CFG_NODE_TYPE_OPT", CFG_NODE_TYPE_OPT }, { "CFG_NODE_TYPE_ARG", CFG_NODE_TYPE_ARG }, { "CFG_NODE_ATTR_PARENT", CFG_NODE_ATTR_PARENT }, { "CFG_NODE_ATTR_LBROTH", CFG_NODE_ATTR_LBROTH }, { "CFG_NODE_ATTR_RBROTH", CFG_NODE_ATTR_RBROTH }, { "CFG_NODE_ATTR_CHILD1", CFG_NODE_ATTR_CHILD1 }, { "CFG_NODE_ATTR_CHILDL", CFG_NODE_ATTR_CHILDL }, { "CFG_NODE_ATTR_CHILDS", CFG_NODE_ATTR_CHILDS }, { "CFG_NODE_ATTR_NODES", CFG_NODE_ATTR_NODES }, { "CFG_NODE_ATTR_DEPTH", CFG_NODE_ATTR_DEPTH }, { "CFG_NODE_ATTR_SRCNAME", CFG_NODE_ATTR_SRCNAME }, { "CFG_NODE_ATTR_SRCPOS", CFG_NODE_ATTR_SRCPOS }, { "CFG_NODE_ATTR_TYPE", CFG_NODE_ATTR_TYPE }, { "CFG_NODE_ATTR_TOKEN", CFG_NODE_ATTR_TOKEN }, { "CFG_NODE_ATTR_DATA", CFG_NODE_ATTR_DATA }, { "CFG_DATA_TYPE_PTR", CFG_DATA_TYPE_PTR }, { "CFG_DATA_TYPE_STR", CFG_DATA_TYPE_STR }, { "CFG_DATA_TYPE_INT", CFG_DATA_TYPE_INT }, { "CFG_DATA_TYPE_FLT", CFG_DATA_TYPE_FLT }, { "CFG_DATA_CTRL_CLONE", CFG_DATA_CTRL_CLONE }, { "CFG_DATA_CTRL_DESTROY", CFG_DATA_CTRL_DESTROY }, { "CFG_DATA_ATTR_TYPE", CFG_DATA_ATTR_TYPE }, { "CFG_DATA_ATTR_VALUE", CFG_DATA_ATTR_VALUE }, { "CFG_DATA_ATTR_CTRL", CFG_DATA_ATTR_CTRL } }; INPUT: SV *sv; const char *s = SvPV(sv, len); PPCODE: for (i = 0; i < sizeof(constant_table)/sizeof(constant_table[0]); i++) { if (strcmp(s, constant_table[i].name) == 0) { EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHi(constant_table[i].value); break; } } if (i == sizeof(constant_table)/sizeof(constant_table[0])) { sv = sv_2mortal(newSVpvf("unknown contant OSSP::cfg::%s", s)); PUSHs(sv); } cfg_rc_t cfg_create(cfg) PROTOTYPE: $ INPUT: cfg_t *&cfg = NO_INIT CODE: RETVAL = cfg_create(&cfg); OUTPUT: cfg RETVAL cfg_rc_t cfg_destroy(cfg) PROTOTYPE: $ INPUT: cfg_t *cfg CODE: RETVAL = cfg_destroy(cfg); OUTPUT: RETVAL cfg_rc_t cfg_error(cfg,rc,error) PROTOTYPE: $$$ INPUT: cfg_t *cfg cfg_rc_t rc char *&error = NO_INIT CODE: RETVAL = cfg_error(cfg, rc, &error); OUTPUT: error RETVAL long cfg_version() PROTOTYPE: INPUT: CODE: RETVAL = cfg_version(); OUTPUT: RETVAL cfg_rc_t cfg_import(cfg,node,fmt,in_ptr,in_len) PROTOTYPE: $$$$$ INPUT: cfg_t *cfg cfg_node_t *node cfg_fmt_t fmt const char *in_ptr size_t in_len CODE: if (ST(4) == &PL_sv_undef) in_len = sv_len(ST(3)); RETVAL = cfg_import(cfg, node, fmt, in_ptr, in_len); OUTPUT: RETVAL cfg_rc_t cfg_export(cfg,node,fmt,ex_ptr,ex_len) PROTOTYPE: $$$$$ INPUT: cfg_t *cfg cfg_node_t *node cfg_fmt_t fmt char *&ex_ptr = NO_INIT size_t ex_len CODE: RETVAL = cfg_export(cfg, node, fmt, &ex_ptr, ex_len); OUTPUT: ex_ptr RETVAL cfg_rc_t cfg_node_create(cfg,node) PROTOTYPE: $$ INPUT: cfg_t *cfg cfg_node_t *&node = NO_INIT CODE: RETVAL = cfg_node_create(cfg, &node); OUTPUT: node RETVAL cfg_rc_t cfg_node_destroy(cfg,node) PROTOTYPE: $$ INPUT: cfg_t *cfg cfg_node_t *node CODE: RETVAL = cfg_node_destroy(cfg, node); OUTPUT: RETVAL cfg_rc_t cfg_node_clone(cfg,node,node2) PROTOTYPE: $$$ INPUT: cfg_t *cfg cfg_node_t *node cfg_node_t *&node2 = NO_INIT CODE: RETVAL = cfg_node_clone(cfg, node, &node2); OUTPUT: node2 RETVAL cfg_rc_t cfg_node_set(cfg,node,attr,va_arg1) CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_PARENT \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_LBROTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_RBROTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILD1 \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDL ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_node_t *va_arg1 CODE: RETVAL = cfg_node_set(cfg, node, attr, va_arg1); OUTPUT: RETVAL CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDS \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_NODES \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DEPTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCPOS ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr int va_arg1 CODE: RETVAL = cfg_node_set(cfg, node, attr, va_arg1); OUTPUT: RETVAL CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCNAME \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TOKEN ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr char *va_arg1 CODE: RETVAL = cfg_node_set(cfg, node, attr|CFG_ATTR_COPY, va_arg1); OUTPUT: RETVAL CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TYPE) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_node_type_t va_arg1 CODE: RETVAL = cfg_node_set(cfg, node, attr, va_arg1); OUTPUT: RETVAL CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DATA) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_data_t *va_arg1 CODE: RETVAL = cfg_node_set(cfg, node, attr, va_arg1); OUTPUT: RETVAL CASE: PROTOTYPE: $$$;$ INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr CODE: RETVAL = cfg_node_set(cfg, node, attr); OUTPUT: RETVAL cfg_rc_t cfg_node_get(cfg,node,attr,va_arg1) CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_PARENT \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_LBROTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_RBROTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILD1 \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDL ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_node_t *&va_arg1 = NO_INIT CODE: RETVAL = cfg_node_get(cfg, node, attr, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDS \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_NODES \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DEPTH \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCPOS ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr int &va_arg1 = NO_INIT CODE: RETVAL = cfg_node_get(cfg, node, attr, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCNAME \ || (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TOKEN ) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr char *&va_arg1 = NO_INIT CODE: RETVAL = cfg_node_get(cfg, node, attr|CFG_ATTR_COPY, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TYPE) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_node_type_t &va_arg1 = NO_INIT CODE: RETVAL = cfg_node_get(cfg, node, attr, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DATA) INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr cfg_data_t *&va_arg1 = NO_INIT CODE: RETVAL = cfg_node_get(cfg, node, attr, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: PROTOTYPE: $$$;$ INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t attr CODE: RETVAL = cfg_node_get(cfg, node, attr); OUTPUT: RETVAL cfg_rc_t cfg_node_root(cfg,node,node_old) PROTOTYPE: $$ INPUT: cfg_t *cfg cfg_node_t *node cfg_node_t *&node_old = NO_INIT CODE: RETVAL = cfg_node_root(cfg, node, &node_old); OUTPUT: node_old RETVAL cfg_rc_t cfg_node_select(cfg,node,result,spec) PROTOTYPE: $$$$ INPUT: cfg_t *cfg cfg_node_t *node SV *&result = NO_INIT const char *spec PREINIT: cfg_node_t **r; CODE: /* FIXME: perhaps use sv_vsetpvfn() to fully emulate C API? */ RETVAL = cfg_node_select(cfg, node, &r, "%s", spec); if (RETVAL == CFG_OK) { /* translate C array into Perl array */ int i; AV *av = newAV(); for (i = 0; r[i] != NULL; i++) av_push(av, newSV(PTR2IV(r[i]))); free(r); result = newRV_noinc((SV *)av); } else result = &PL_sv_undef; OUTPUT: result RETVAL cfg_rc_t cfg_node_find(cfg,node,cb_fct_cmp,cb_ctx_cmp,cont) PROTOTYPE: $$$$$ INPUT: cfg_t *cfg cfg_node_t *node SV *cb_fct_cmp SV *cb_ctx_cmp cfg_node_t *&cont = NO_INIT PREINIT: cb_ctx_t ctx_cmp; CODE: ctx_cmp.fct = cb_fct_cmp; ctx_cmp.ctx = cb_ctx_cmp; RETVAL = cfg_node_find(cfg, node, cb_fct, &ctx_cmp, &cont); OUTPUT: cont RETVAL cfg_rc_t cfg_node_apply(cfg,node,cb_fct_cmp,cb_ctx_cmp,cb_fct_cb,cb_ctx_cb) PROTOTYPE: $$$$$$ INPUT: cfg_t *cfg cfg_node_t *node SV *cb_fct_cmp SV *cb_ctx_cmp SV *cb_fct_cb SV *cb_ctx_cb PREINIT: cb_ctx_t ctx_cmp; cb_ctx_t ctx_cb; CODE: ctx_cmp.fct = cb_fct_cmp; ctx_cmp.ctx = cb_ctx_cmp; ctx_cb.fct = cb_fct_cb; ctx_cb.ctx = cb_ctx_cb; RETVAL = cfg_node_apply(cfg, node, cb_fct, &ctx_cmp, cb_fct, &ctx_cb); OUTPUT: RETVAL cfg_rc_t cfg_node_cmp(cfg,node,token) PROTOTYPE: $$$ INPUT: cfg_t *cfg cfg_node_t *node char *token CODE: RETVAL = cfg_node_cmp(cfg, node, (void *)token); OUTPUT: RETVAL cfg_rc_t cfg_node_link(cfg,node,id,node2) PROTOTYPE: $$$$ INPUT: cfg_t *cfg cfg_node_t *node cfg_node_attr_t id cfg_node_t *node2 CODE: RETVAL = cfg_node_link(cfg, node, id, node2); OUTPUT: RETVAL cfg_rc_t cfg_node_unlink(cfg,node) PROTOTYPE: $$ INPUT: cfg_t *cfg cfg_node_t *node CODE: RETVAL = cfg_node_unlink(cfg, node); OUTPUT: RETVAL cfg_rc_t cfg_data_set(data,attr,va_arg1) CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_TYPE PROTOTYPE: $$$ INPUT: cfg_data_t *data cfg_data_attr_t attr cfg_data_type_t va_arg1 CODE: RETVAL = cfg_data_set(data, attr, va_arg1); OUTPUT: RETVAL CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_VALUE INPUT: cfg_data_t *data cfg_data_attr_t attr PREINIT: cfg_data_type_t type; CODE: if ((RETVAL = cfg_data_get(data, CFG_DATA_ATTR_TYPE, &type)) == CFG_OK) { switch (type) { case CFG_DATA_TYPE_PTR: { void *va_arg1 = INT2PTR(cfg_node_t *, SvIV((SV*)SvRV(ST(2)))); RETVAL = cfg_data_set(data, attr, va_arg1); break; } case CFG_DATA_TYPE_STR: { char *va_arg1 = SvPV_nolen(ST(2)); RETVAL = cfg_data_set(data, attr, va_arg1); break; } case CFG_DATA_TYPE_INT: { int va_arg1 = SvIV(ST(2)); RETVAL = cfg_data_set(data, attr, va_arg1); break; } case CFG_DATA_TYPE_FLT: { double va_arg1 = SvNV(ST(2)); RETVAL = cfg_data_set(data, attr, va_arg1); break; } } } OUTPUT: RETVAL CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_CTRL INPUT: cfg_data_t *data cfg_data_attr_t attr cfg_data_cb_t va_arg1 CODE: RETVAL = cfg_data_set(data, attr, va_arg1); OUTPUT: RETVAL cfg_rc_t cfg_data_get(data,attr,va_arg1) CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_TYPE PROTOTYPE: $$$ INPUT: cfg_data_t *data cfg_data_attr_t attr cfg_data_type_t &va_arg1 = NO_INIT CODE: RETVAL = cfg_data_get(data, attr, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_VALUE INPUT: cfg_data_t *data cfg_data_attr_t attr SV *va_arg1 PREINIT: cfg_data_type_t type; CODE: if ((RETVAL = cfg_data_get(data, CFG_DATA_ATTR_TYPE, &type)) == CFG_OK) { switch (type) { case CFG_DATA_TYPE_PTR: { void *arg; RETVAL = cfg_data_get(data, attr, &arg); sv_setiv(va_arg1, PTR2IV(arg)); break; } case CFG_DATA_TYPE_STR: { char *arg; RETVAL = cfg_data_set(data, attr, &arg); sv_setpv(va_arg1, arg); break; } case CFG_DATA_TYPE_INT: { int arg; RETVAL = cfg_data_set(data, attr, &arg); sv_setiv(va_arg1, arg); break; } case CFG_DATA_TYPE_FLT: { double arg; RETVAL = cfg_data_set(data, attr, &arg); sv_setnv(va_arg1, arg); break; } } } OUTPUT: va_arg1 RETVAL CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_CTRL INPUT: cfg_data_t *data cfg_data_attr_t attr cfg_data_cb_t &va_arg1 = NO_INIT CODE: RETVAL = cfg_data_set(data, attr, &va_arg1); OUTPUT: va_arg1 RETVAL cfg_rc_t cfg_data_ctrl(data,ctrl,va_arg1) CASE: (cfg_data_ctrl_t)SvIV(ST(1)) == CFG_DATA_CTRL_CLONE PROTOTYPE: $$;$ INPUT: cfg_data_t *data cfg_data_ctrl_t ctrl cfg_data_t *&va_arg1 = NO_INIT CODE: RETVAL = cfg_data_ctrl(data, ctrl, &va_arg1); OUTPUT: va_arg1 RETVAL CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_CTRL_DESTROY INPUT: cfg_data_t *data cfg_data_ctrl_t ctrl CODE: RETVAL = cfg_data_ctrl(data, ctrl); OUTPUT: RETVAL CASE: INPUT: cfg_data_t *data cfg_data_ctrl_t ctrl CODE: RETVAL = cfg_data_set(data, ctrl); OUTPUT: RETVAL