Index: ossp-pkg/cfg/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/cfg/ChangeLog,v co -q -kk -p'1.21' '/v/ossp/cvs/ossp-pkg/cfg/ChangeLog,v' | diff -u /dev/null - -L'ossp-pkg/cfg/ChangeLog' 2>/dev/null --- ossp-pkg/cfg/ChangeLog +++ - 2025-04-11 21:41:25.037457607 +0200 @@ -0,0 +1,88 @@ + _ ___ ____ ____ ____ __ + |_|_ _ / _ \/ ___/ ___|| _ \ ___ / _| __ _ + _|_||_| | | | \___ \___ \| |_) | / __| |_ / _` | + |_||_|_| | |_| |___) |__) | __/ | (__| _| (_| | + |_|_|_| \___/|____/____/|_| \___|_| \__, | + |___/ + OSSP cfg - Configuration Parsing + + CHANGELOG + + Changes between 0.9.4 and 0.9.5 (31-Oct-2004 to xx-Nov-2004): + + *) Add OSSP:::cfg::simple Perl convenience API which is an + ultra high-level API allowing especially the bi-directional + conversion between the C API node tree representation and a + simplified Perl data structure representation. + [Ralf S. Engelschall ] + + *) Change cfg_node_root() API function to be able to both + set and/or get the root node. + [Ralf S. Engelschall ] + + *) Fixed cfg_test program by correctly passing the used number of + bytes in the buffer instead of the size of the buffer. + [Ralf S. Engelschall ] + + *) Accept zero-length strings for parsing. Correctly handle + end-of-file during plain text token scanning. + [Ralf S. Engelschall ] + + *) Do not let Flex generate the unused yyunput() and yy_top_state() + functions in order to shut up compilation warnings. + [Ralf S. Engelschall ] + + *) Return an empty string instead of NULL from internal + cfg_buf_content() function to not make visible to the caller the + implementation special case of an initial buffer. + [Ralf S. Engelschall ] + + *) Added initial cut for Perl bindings. + [Ralf S. Engelschall ] + + Changes between 0.9.3 and 0.9.4 (23-Apr-2003 to 31-Oct-2004): + + *) Upgrade to GNU bison 1.875d and GNU flex 2.5.31 + [Ralf S. Engelschall ] + + *) Fixed warnings under GCC 3.4/3.5. + [Ralf S. Engelschall ] + + *) Adjust copyright messages for new year 2004. + [Ralf S. Engelschall ] + + *) Upgraded build environment to GNU libtool 1.5.10 + and GNU shtool 2.0.1 + [Ralf S. Engelschall ] + + Changes between 0.9.2 and 0.9.3 (10-Nov-2003 to 23-Apr-2004): + + *) Import change introduced in OSSP l2 0.9.7: + Replace modf(3) calls in cfg_fmt.c with a hand-crafted + inlined cfg_fmt_modf() function to avoid dependency to external + libm on systems where modf(3) is not part of libc, i.e. Tru64 and + QNX. Reported by Karl Vogel. + [Thomas Lotterer ] + + Changes between 0.9.1 and 0.9.2 (10-Nov-2003 to 10-Nov-2003) + + *) Upgraded build environment to GNU libtool 1.5 and + GNU autoconf 2.58. + [Ralf S. Engelschall ] + + Changes between 0.9.0 and 0.9.1 (01-Jul-2002 to 10-Nov-2003) + + *) Added Bison-locations option to scanner, fixing the missing + reentrant "yylloc" with flex 2.5.31. Taken over from OSSP l2. + [Thomas Lotterer ] + + *) Enhanced test suite by comparing against previously saved output + [Ralf S. Engelschall ] + + *) Switch from text-based VERSION file to C-based cfg_vers.c + and use this to provide a cfg_version(3) API function. + [Ralf S. Engelschall ] + + *) Source tree cleanups. + [Ralf S. Engelschall ] + Index: ossp-pkg/cfg/perl/cfg.pm RCS File: /v/ossp/cvs/ossp-pkg/cfg/perl/cfg.pm,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/cfg/perl/cfg.pm,v' 2>/dev/null --- cfg.pm 2004/11/20 16:51:52 1.6 +++ cfg.pm 2004/11/20 17:09:35 1.7 @@ -326,5 +326,187 @@ # static-loading functions XSLoader::load('OSSP::cfg', $VERSION); +## +## Highest-Level Perl Convenience API +## (based on OSSP::cfg Perl API above) +## + +package OSSP::cfg::simple; + +use 5.008; +use strict; +use warnings; +use Carp; +use IO::File; + +# object constructor +sub new ($;$) { + my ($proto, $input) = @_; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + $self->{-cfg} = new OSSP::cfg + or croak "failed to create OSSP::cfg object"; + $self->parse($input) if (defined($input)); + return $self; +} + +# object destructor +sub DESTROY ($) { + my ($self) = @_; + undef $self->{-cfg}; + return; +} + +# parse textual syntax into node tree +sub parse ($$) { + my ($self, $input) = @_; + my $cfg = $self->{-cfg}; + if (length($input) < 1024 and $input !~ m|[{}&\n\s]|s) { + if (-f $input) { + my $io = new IO::File "<" . $input + or croak "unable to read from configuration file \"".$input."\""; + { local $/; $input = <$io>; } + $io->close(); + } + } + $cfg->import(\0, $cfg->CFG_FMT_CFG, $input) + or die "failed to parse configuration: " . $cfg->error(); + return $self; +} + +# format textual syntax from node tree +sub format ($$) { + my ($self) = @_; + my $cfg = $self->{-cfg}; + my $root = $cfg->node_root(); + my $str = $cfg->export($root, $cfg->CFG_FMT_CFG) + or die "failed to format configuration: " . $cfg->error(); + return $str; +} + +# pack Perl complex data structure into node tree +sub pack ($$) { + my ($self, $tree) = @_; + + # destroy old and create new OSSP::cfg object + undef $self->{-cfg}; + my $cfg = new OSSP::cfg + or croak "failed to create OSSP::cfg object"; + $self->{-cfg} = $cfg; + + # start parsing with a sequence + my $node = &parse_seq($cfg, $tree); + + # parse a sequence (reference) scalar + sub parse_seq { + my ($cfg, $seq) = @_; + my $node = undef; + if (ref($seq) eq 'ARRAY') { + $node = $cfg->node_create(); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_SEQ); + if (@{$seq} > 0) { + my $child = &parse_dir($cfg, $seq->[0]); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_CHILD1, $child); + my $sibling = $child; + foreach my $dir (@{$seq}[1..$#{$seq}]) { + $child = &parse_dir($cfg, $dir); + $cfg->node_set($sibling, $cfg->CFG_NODE_ATTR_RBROTH, $child); + $sibling = $child; + } + } + } + return $node; + } + + # parse a directive (reference) scalar + sub parse_dir { + my ($cfg, $dir) = @_; + my $node = undef; + if (ref($dir) eq 'ARRAY') { + $node = $cfg->node_create(); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_DIR); + if (@{$dir} > 0) { + my $child = &parse_tok($cfg, $dir->[0]); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_CHILD1, $child); + my $sibling = $child; + foreach my $tok (@{$dir}[1..$#{$dir}]) { + $child = &parse_tok($cfg, $tok); + $cfg->node_set($sibling, $cfg->CFG_NODE_ATTR_RBROTH, $child); + $sibling = $child; + } + } + } + return $node; + } + + # parse a token scalar + sub parse_tok { + my ($cfg, $tok) = @_; + my $node; + if (ref($tok) eq 'ARRAY') { + # token is actually a sub-sequence + $node = &parse_seq($cfg, $tok); # recursion + } + else { + # token is a plain one + $node = $cfg->node_create(); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_ARG); + $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TOKEN, $tok); + } + return $node; + } + + # set generated node tree into OSSP::cfg object + $cfg->node_root($node); + + return $self; +} + +# unpack Perl complex data structure from node tree +sub unpack ($) { + my ($self) = @_; + my $cfg = $self->{-cfg}; + + # start traversing the node tree from the root node + my $root = $cfg->node_root(); + my $tree = &traverse($cfg, $root); + + # node processing function + sub traverse { + my ($cfg, $node) = @_; + return if (not(ref($node) and $$node != 0)); + my $type = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_TYPE); + if ($type == $cfg->CFG_NODE_TYPE_SEQ) { + # node is a sequence + my $seq = []; + $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_CHILD1); + while (ref($node) and $$node != 0) { + my $tree = &traverse($cfg, $node); # recursion + push(@{$seq}, $tree) if (defined($tree)); + $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_RBROTH); + } + return $seq; + } + elsif ($type == $cfg->CFG_NODE_TYPE_DIR) { + # node is a directive + my $dir = []; + $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_CHILD1); + while (ref($node) and $$node != 0) { + my $tree = &traverse($cfg, $node); # recursion + push(@{$dir}, $tree) if (defined($tree)); + $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_RBROTH); + } + return $dir; + } + else { + # node is a token + my $token = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_TOKEN); + return $token; + } + } + return $tree; +} + 1; Index: ossp-pkg/cfg/perl/cfg.pod RCS File: /v/ossp/cvs/ossp-pkg/cfg/perl/cfg.pod,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/cfg/perl/cfg.pod,v' 2>/dev/null --- cfg.pod 2004/11/17 13:15:35 1.2 +++ cfg.pod 2004/11/20 17:09:35 1.3 @@ -40,18 +40,41 @@ B is ... -B provides two Perl APIs: +B provides three Perl APIs: + +=head2 SIMPLE API + +The simple API is a wrapper around the OO-style API and intended +for working with configurations the really simple but less flexible way: + +=over 4 + +=item C + +=item C<$cfg = >BC< OSSP::cfg::simple;> + +=item C<$cfg-E>BC<($txt);> + +=item C<$cfg-E>BC<($tree);> + +=item C<$txt = $cfg-E>BC<();> + +=item C<$tree = $cfg-E>BC<();> + +=item C + +=back =head2 OO-STYLE API The OO-style API is a wrapper around the C-style API and intended for -high-level and regular programming. +high-level and flexible programming. =over 4 =item C -=item CBC< OSSP::cfg;> +=item C<$cfg = >BC< OSSP::cfg;> =item C