.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "xsbuilder.osc2002 3" .TH xsbuilder.osc2002 3 2024-07-13 "perl v5.38.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "XSBuilder \- Autogenerating XS-glue Code" .IX Header "XSBuilder - Autogenerating XS-glue Code" O'Reilly OpenSource Convention 2002 .PP Gerald Richter .PP ecos gmbh .PP http://www.ecos.de .SH "XSBuilder \- What is it?" .IX Header "XSBuilder - What is it?" .SS "It's purpose is to automaticly generate a Perl interface to C Code" .IX Subsection "It's purpose is to automaticly generate a Perl interface to C Code" .SS "Solves the problem, that the Perl interface is not always uptodate with the C interface" .IX Subsection "Solves the problem, that the Perl interface is not always uptodate with the C interface" .SS "Saves a lot of Copy&Paste work" .IX Subsection "Saves a lot of Copy&Paste work" .SS "Systematical changes have to be done only once" .IX Subsection "Systematical changes have to be done only once" For example changes in the memory management of strings. .SS "Is part of mod_perl 2.0 build system" .IX Subsection "Is part of mod_perl 2.0 build system" Most code is developed by Doug MacEachern. Additionaly I have .IP "abstracted the code from mod_perl so it's useable for any C code" 4 .IX Item "abstracted the code from mod_perl so it's useable for any C code" .PD 0 .IP "added new features like callbacks and the ability to parse comments" 4 .IX Item "added new features like callbacks and the ability to parse comments" .IP "Replaced C::Scan with a Parse::RecDescent to be platform and compiler independend" 4 .IX Item "Replaced C::Scan with a Parse::RecDescent to be platform and compiler independend" .PD .PP Goal is to replace the current mod_perl XS generation code with XSBuilder .SS "Inline versus XSBuilder" .IX Subsection "Inline versus XSBuilder" .IP "Inline: embed C\-Code into Perl" 4 .IX Item "Inline: embed C-Code into Perl" .PD 0 .IP "XSBuilder: Create interface for existing C\-libraries/applicationen" 4 .IX Item "XSBuilder: Create interface for existing C-libraries/applicationen" .PD .SH "XSBuilder \- What does it do?" .IX Header "XSBuilder - What does it do?" .SS "Create Perl functions/methods for every C function" .IX Subsection "Create Perl functions/methods for every C function" The function can be assigned to different packages, also automaticly by inspecting the first parameter .SS "Create a Perl class for every C structure" .IX Subsection "Create a Perl class for every C structure" Every element of structure becomes a Perl method to get/set it's value. The object can be either a scalar reference (used by mod_perl) or a reference to a hash (use by Embperl), which allows to store extra data by the Perl code into this hash. .SS "Create glue code to handle callbacks" .IX Subsection "Create glue code to handle callbacks" There several sorts of callback, not all are implemented right now .SS "Create Perl constant subs" .IX Subsection "Create Perl constant subs" Coming soon... .SH "XSBuilder \- How does it work?" .IX Header "XSBuilder - How does it work?" .SS "Parse the C header files" .IX Subsection "Parse the C header files" Extract .IP "Functions, their arguments and return types" 4 .IX Item "Functions, their arguments and return types" .PD 0 .IP "Structures and it's members" 4 .IX Item "Structures and it's members" .IP Constants 4 .IX Item "Constants" .IP Callbacks 4 .IX Item "Callbacks" .PD .PP and create four tables which contains the results .SS "Create the XS code" .IX Subsection "Create the XS code" Input is .IP "The source tables" 4 .IX Item "The source tables" .PD 0 .IP "Mapfiles which contains the mapping from C to Perl" 4 .IX Item "Mapfiles which contains the mapping from C to Perl" .IP "Addtional C and Perl code that can be used to customize the interface" 4 .IX Item "Addtional C and Perl code that can be used to customize the interface" .PD .PP Output is .IP "The XS files (one form every generated class)" 4 .IX Item "The XS files (one form every generated class)" .PD 0 .IP "Makefile.PL for every class" 4 .IX Item "Makefile.PL for every class" .IP "pm files" 4 .IX Item "pm files" .PD .SH "Parse the source" .IX Header "Parse the source" .SS "Create your own ParseSource class and override methods..." .IX Subsection "Create your own ParseSource class and override methods..." .Vb 1 \& package Apache::DAV::ParseSource; \& \& use strict; \& use vars qw{@ISA $VERSION} ; \& use ExtUtils::XSBuilder::ParseSource ; \& \& @ISA = (\*(AqExtUtils::XSBuilder::ParseSource\*(Aq) ; \& $VERSION = \*(Aq0.01\*(Aq; \& \& my $dav_dir = \*(AqC:\eperl\emsrc\ecvs\emod_dav\*(Aq ; \& my $ap_dir = \*(Aqc:\eprogramme\eapache group\eapache\*(Aq ; \& \& # ============================================================================ \& sub find_includes { \& my $self = shift; \& return $self\->{includes} if $self\->{includes}; \& my @includes = ("$ap_dir/include/ap_alloc.h", "$dav_dir/mod_dav.h") ; \& return $self\->{includes} = $self \-> sort_includes (\e@includes) ; \& } \& \& # ============================================================================ \& sub package { \*(AqApache::DAV\*(Aq } \& \& # ============================================================================ \& sub preprocess { \& my $self = shift ; \& $_[0] =~ s/(?:API_EXPORT)(?:_NONSTD)?\es*\e(\es*(.*?)\es*\e)/$1/g ; \& } \& \& \& 1; .Ve .SS "...run it" .IX Subsection "...run it" .Vb 2 \& use FindBin ; \& use lib ($FindBin::Bin) ; \& \& require ParseSource ; \& \& Apache::DAV::ParseSource \-> run ; .Ve .SS "...and you get" .IX Subsection "...and you get" .Vb 10 \& C:\eperl\emsrc\edavint>perl xsbuilder\esource_scan.pl \& Will use mod_dav in C:\eperl\emsrc\ecvs\emod_dav \& Will use Apache in c:\eprogramme\eapache group\eapache \& Initialize parser \& scan c:\eprogramme\eapache group\eapache/include/ap_alloc.h ... \& constant: APACHE_ALLOC_H \& func: ap_init_alloc \& func: ap_cleanup_alloc \& func: ap_make_sub_pool \& func: ap_destroy_pool \& constant: ap_pool_join \& func: ap_pool_join \& func: ap_find_pool \& func: ap_pool_is_ancestor \& func: ap_clear_pool \& func: ap_cleanup_for_exec \& func: ap_palloc \& func: ap_pcalloc \& func: ap_pstrdup \& func: ap_pstrndup \& func: ap_pstrcat \& func: ap_pvsprintf \& valuefield: ap_pool * : pool \& valuefield: int : elt_size \& valuefield: int : nelts \& valuefield: int : nalloc \& valuefield: char * : elts \& struct: (type=array_header) \& ... .Ve .SS "The result is stored in four tables" .IX Subsection "The result is stored in four tables" .IP xsbuilder/tables/Apache/DAV/FuntionTable.pm 4 .IX Item "xsbuilder/tables/Apache/DAV/FuntionTable.pm" Contains all function, it arguments and comments .IP xsbuilder/tables/Apache/DAV/ConstantTable.pm 4 .IX Item "xsbuilder/tables/Apache/DAV/ConstantTable.pm" Contains all constants .IP xsbuilder/tables/Apache/DAV/StructureTable.pm 4 .IX Item "xsbuilder/tables/Apache/DAV/StructureTable.pm" Contains all structures, it's members and their comments .IP xsbuilder/tables/Apache/DAV/CallbackTable.pm 4 .IX Item "xsbuilder/tables/Apache/DAV/CallbackTable.pm" Contains all callback function definitions .SH "Create the map files" .IX Header "Create the map files" .SS "Mapfiles are used to tell XSBuilder how C datatypes, structures and function aruments should be mapped into Perl ones." .IX Subsection "Mapfiles are used to tell XSBuilder how C datatypes, structures and function aruments should be mapped into Perl ones." .SS "Create your own WrapXS class and override methods" .IX Subsection "Create your own WrapXS class and override methods" .Vb 3 \& package Apache::DAV::WrapXS ; \& use strict; \& use vars qw{@ISA $VERSION} ; \& \& use ExtUtils::XSBuilder::WrapXS ; \& \& @ISA = (\*(AqExtUtils::XSBuilder::WrapXS\*(Aq) ; \& $VERSION = \*(Aq0.01\*(Aq; \& \& # ============================================================================ \& sub new_parsesource { [ Apache::DAV::ParseSource\->new ] } \& \& # ============================================================================ \& sub my_xs_prefix { \*(Aqdavxs_\*(Aq } \& \& # ============================================================================ \& sub h_filename_prefix { \*(Aqmoddav_xs_\*(Aq } \& \& # ============================================================================ \& sub xs_includes { \& my $self = shift ; \& my $i = $self \-> SUPER::xs_includes ; \& my @i = grep (!/ap_alloc/, @$i) ; \& return \e@i ; \& } .Ve .SS "XSBuilder can create/update initial maps for you" .IX Subsection "XSBuilder can create/update initial maps for you" .Vb 2 \& use FindBin ; \& use lib ($FindBin::Bin) ; \& \& require ParseSource ; \& require WrapXS ; \& \& Apache::DAV::WrapXS\->checkmaps (\*(Aq \*(Aq); .Ve .SS "run it" .IX Subsection "run it" .Vb 11 \& C:\eperl\emsrc\edavint>perl xsbuilder\exs_check.pl \& Will use mod_dav in C:\eperl\emsrc\ecvs\emod_dav \& Will use Apache in c:\eprogramme\eapache group\eapache \& Parse xsbuilder\emaps/_types.map... \& WARNING: No *_function.map file found in xsbuilder\emaps \& WARNING: No *_callback.map file found in xsbuilder\emaps \& WARNING: No *_structure.map file found in xsbuilder\emaps \& Write xsbuilder\emaps/new_function.map... \& Write xsbuilder\emaps/new_callback.map... \& Write xsbuilder\emaps/new_structure.map... \& Write xsbuilder\emaps/new_type.map... .Ve .SS "Now we have four map files" .IX Subsection "Now we have four map files" .IP new_types.map 4 .IX Item "new_types.map" Contains the mapping from C type to Perl classes .IP new_functions.map 4 .IX Item "new_functions.map" Contains the mapping form C functions to Perl functions. Can be used to reorder arguments, tell XSBuilder which arguments are actualy return values and in which Perl package the function will be created. .IP new_structures.map 4 .IX Item "new_structures.map" Contains the mapping from C structures to Perl classes and defines for which members a access methods should be created. You can also specify if you want a \&\f(CW\*(C`new\*(C'\fR method for the class. .IP new_callbacks.map 4 .IX Item "new_callbacks.map" Contains the mapping form C callback functions to Perl callback functions. Can be used to reorder arguments, tell XSBuilder which arguments are actualy return values and in which Perl package the function will be created. .PP It's a good idea to rename the prefix from \f(CW\*(C`new_\*(C'\fR to something unique, here we use \f(CW\*(C`dav\*(C'\fR .PP Everytime you rerun checkmaps, XSBuilder will create new_* files with the items that are not already part of the other maps. .SS "Next step is to customize the maps..." .IX Subsection "Next step is to customize the maps..." .SH "type map" .IX Header "type map" .SS "autogenerated dav_type.map" .IX Subsection "autogenerated dav_type.map" .Vb 10 \& DIR | \& FILE | \& HANDLE | \& array_header | \& dav_buffer | \& dav_dyn_context | \& dav_dyn_hooks | \& dav_dyn_module | \& dav_dyn_provider | \& dav_error | \& dav_get_props_result | \& dav_hooks_liveprop | \& dav_hooks_locks | \& dav_hooks_repository | \& dav_if_header | \& dav_if_state_type | \& ... .Ve .SS "Add Perl classes" .IX Subsection "Add Perl classes" .Vb 10 \& struct array_header | Apache::Array \& struct dav_buffer | \& struct dav_datum | Apache::DAV::Datum \& struct dav_dyn_context | Apache::DAV::DynContext \& struct dav_dyn_hooks | Apache::DAV::DynHooks \& struct dav_dyn_module | Apache::DAV::DynModule \& struct dav_dyn_provider | Apache::DAV::DynProvider \& struct dav_error | Apache::DAV::Error \& struct dav_get_props_result | Apache::DAV::PropsResult \& struct dav_hooks_db | Apache::DAV::HooksDb \& struct dav_hooks_liveprop | Apache::DAV::HooksLiveprop \& struct dav_hooks_locks | Apache::DAV::HooksLocks \& struct dav_hooks_repository | Apache::DAV::HooksRepository \& struct dav_hooks_vsn | \& struct dav_if_header | Apache::DAV::IfHeader \& struct dav_if_state_list | Apache::DAV::StateList \& ... \& struct pool | Apache::Pool \& struct request_rec | Apache:: \& struct server_rec | Apache::Server \& ... .Ve .PP Defines the mapping from C datatypes to Perl datatypes and classes and tells XSBuilder which datatype are (like) structures .SH "function map" .IX Header "function map" Function map defines the mapping from C functions arguments to Perl arguments .IP "Tell XSBuilder where to place functions and which prefix to strip" 4 .IX Item "Tell XSBuilder where to place functions and which prefix to strip" .Vb 1 \& MODULE=Apache::DAV PACKAGE=guess PREFIX=dav_ .Ve .IP "Simple entries in the function map will be mapped 1:1 from C to Perl" 4 .IX Item "Simple entries in the function map will be mapped 1:1 from C to Perl" .Vb 11 \& dav_add_response \& dav_buffer_append \& dav_buffer_init \& dav_buffer_place \& dav_buffer_place_mem \& dav_check_bufsize \& dav_close_propdb \& dav_collect_liveprop_uris \& dav_dyn_module_add \& dav_empty_elem \& ... .Ve .ie n .IP "The following map file entry tells XSBuilder that the value of ""res_p"" should be returned" 4 .el .IP "The following map file entry tells XSBuilder that the value of \f(CWres_p\fR should be returned" 4 .IX Item "The following map file entry tells XSBuilder that the value of res_p should be returned" .Vb 1 \& dav_get_resource | | r, lookup_uri($uri); \& \& # get a mod_dav resource object \& my ($err, $resource) = $subr\->get_resource; .Ve .IP "You can let XSBuilder insert your custom code, for the interface" 4 .IX Item "You can let XSBuilder insert your custom code, for the interface" If you call \f(CW\*(C`get_props\*(C'\fR from Perl \f(CW\*(C`glue_dav_get_props\*(C'\fR will be called, which can adjust the arguments and return types as necessary. The actual code for \f(CW\*(C`glue_dav_get_props\*(C'\fR will be taken from separate include file. .Sp .Vb 2 \& dav_get_props | glue_ \& dav_get_allprops | glue_ .Ve .Sp xsinclude\eApache\eDAV\ePropResult\eApache_\|_DAV_\|_PropResults.h .Sp .Vb 6 \& dav_get_props_result * dav_glue_get_props(dav_propdb * db, dav_xml_doc *doc) \& { \& dav_get_props_result * result = (dav_get_props_result *)ap_palloc (db \-> p, sizeof (dav_get_props_result)) ; \& *result = dav_get_props(db, doc) ; \& return result ; \& } .Ve .IP "Arguments can be replaced" 4 .IX Item "Arguments can be replaced" .Vb 1 \& MODULE=Apache::Array PACKAGE=Apache::Array PREFIX=ap_ \& \& ap_make_array | ap_make_array(r\->pool, nelts, elt_size) | request_rec *:r, nelts, elt_size .Ve .Sp ap_make_array requires a pool a it's first parameter, we pass the request_rec from Perl and XSBuilder will take the pool from the request_rec. .SH "structure map" .IX Header "structure map" .Vb 2 \& MALLOC=strdup:$dest = ($type)strdup($src) \& FREE=strdup:free($src) \& \& \& name \& ns \& lang \& first_cdata \& following_cdata \& parent \& next \& first_child \& attr \& last_child \& ns_scope \& propid \& provider \& ns_map \& new \& \& \& MALLOC=strdup:$dest = ($type)ap_pstrdup(obj \-> pool, $src) \& \& \& pool \& elt_size \& nelts \& nalloc \& elts \& private \& .Ve .SS "Create a accessor functions for every element and, if requested, a new method" .IX Subsection "Create a accessor functions for every element and, if requested, a new method" .Vb 4 \& $setprop = Apache::DAV::XMLElem \-> new ({name => \*(Aqprop\*(Aq}) ; \& $elem = Apache::DAV::XMLElem \-> new ({name => $name, ns => $namespaces}) ; \& $setprop \-> first_child($elem) ; \& $first = $setprop \-> first_child ; .Ve .SS "some datatypes, like strings, requires dynamic allocated memory" .IX Subsection "some datatypes, like strings, requires dynamic allocated memory" From _types.map,which conatins a set of standard types .PP .Vb 8 \& int | IV \& int * | UNDEFINED \& unsigned int | UV \& signed int | IV \& long | IV \& long int | IV \& unsigned long | UV \& unsigned | UV \& \& char * | PV | | | strdup \& const char * | PV | | | strdup \& const char ** | UNDEFINED \& char const * | PV | | | strdup \& unsigned char * | PV | | | strdup \& const unsigned char * | PV | | | strdup \& ... .Ve .SH "callback maps" .IX Header "callback maps" Callback maps have the same options a function maps .PP .Vb 1 \& # dav_hooks_db \-> open \& \& dav_error *(*)(pool * p,const dav_resource * resource,int ro,dav_db * * pdb) | p, resource, ro=0, has_locks \& \& dav_error *(*)(dav_lockdb * lockdb,const dav_resource * resource,int * locks_present) .Ve .SH "Generate the XS files" .IX Header "Generate the XS files" .Vb 2 \& use FindBin ; \& use lib ($FindBin::Bin) ; \& \& require ParseSource ; \& require WrapXS ; \& \& Apache::DAV::WrapXS\->run; .Ve .SS "...and run..." .IX Subsection "...and run..." .Vb 10 \& C:\eperl\emsrc\edavint>perl xsbuilder\exs_generate.pl \& Will use mod_dav in C:\eperl\emsrc\ecvs\emod_dav \& Will use Apache in c:\eprogramme\eapache group\eapache \& Parse xsbuilder\emaps/_types.map... \& Parse xsbuilder\emaps/dav_type.map... \& mkdir xs \& writing...xs//typemap \& Parse xsbuilder\emaps/dav_functions.map... \& WARNING: Cannot map type int(*)(void * ,const char * ,const char * ) for function ap_table_do \& WARNING: Cannot map type dav_buffer * for function dav_buffer_append \& WARNING: Cannot map type dav_buffer * for function dav_buffer_init \& WARNING: Cannot map type dav_buffer * for function dav_buffer_place \& WARNING: Cannot map type dav_buffer * for function dav_buffer_place_mem \& WARNING: Cannot map type dav_buffer * for function dav_check_bufsize \& WARNING: Cannot map return type int * for function dav_collect_liveprop_uris \& WARNING: Cannot map type dav_resource * * for function dav_ensure_resource_writable \& WARNING: Cannot map type dav_buffer * for function dav_lock_get_activelock \& WARNING: Cannot map type dav_buffer * for function dav_set_bufsize \& WARNING: Cannot map type int * for function dav_xml2text \& struct array_header... \& Parse xsbuilder\emaps/dav_structure.map... \& elt_size... \& nelts... \& nalloc... \& elts... \& struct dav_buffer... \& struct dav_datum... \& dptr... \& dsize... \& struct dav_dyn_context... .Ve .SH Makefile.PL .IX Header "Makefile.PL" .SS "We need create a top level Makefile.PL" .IX Subsection "We need create a top level Makefile.PL" .Vb 1 \& use ExtUtils::MakeMaker (); \& \& my $apdir = \*(Aq/path/to/apache\*(Aq; \& my $davdir = \*(Aq/path/to/moddav\*(Aq; \& \& %MMARGS = ( \& \*(AqINC\*(Aq => "\-I\e"$davdir\e" \-I\e"$apdir/include\e" \-I\e"$apdir/os/unix\e" \-I\e"$dir/xs\e" \-I\e"$dir/xsinclude\e"", \& ) ; \& \& \& open FH, ">xs/mmargs.pl" or die "Cannot open xs/mmargs.pl ($!)" ; \& print FH Data::Dumper \-> Dump ([\e%MMARGS], [\*(AqMMARGS\*(Aq]) ; \& close FH ; \& \& \& ExtUtils::MakeMaker::WriteMakefile( \& \*(AqNAME\*(Aq => \*(AqApache::DAV\*(Aq, \& \*(AqVERSION\*(Aq => \*(Aq0.13\*(Aq, \& %MMARGS, \& ); .Ve .SS "Makefile.PL's for all class are generated automaticly" .IX Subsection "Makefile.PL's for all class are generated automaticly" .Vb 10 \& C:\eperl\emsrc\edavint>perl Makefile.PL \& Will use Apache in c:\eprogramme\eapache group\eapache \& Will use mod_dav in C:\eperl\emsrc\ecvs\emod_dav \& Checking if your kit is complete... \& Looks good \& Writing Makefile for Apache::Array \& Writing Makefile for Apache::DAV::Datum \& Writing Makefile for Apache::DAV::DynContext \& Writing Makefile for Apache::DAV::DynHooks \& Writing Makefile for Apache::DAV::DynModule \& Writing Makefile for Apache::DAV::DynProvider \& Writing Makefile for Apache::DAV::Error \& Writing Makefile for Apache::DAV::HooksDb \& Writing Makefile for Apache::DAV::HooksLiveprop \& Writing Makefile for Apache::DAV::HooksLocks \& Writing Makefile for Apache::DAV::HooksRepository \& Writing Makefile for Apache::DAV::IfHeader \& Writing Makefile for Apache::DAV::Lock \& Writing Makefile for Apache::DAV::LockDB \& Writing Makefile for Apache::DAV::LockTokenList \& Writing Makefile for Apache::DAV::LockupResult \& Writing Makefile for Apache::DAV::PropCtx \& Writing Makefile for Apache::DAV::PropsResult \& Writing Makefile for Apache::DAV::Resource \& Writing Makefile for Apache::DAV::Response \& Writing Makefile for Apache::DAV::StateList \& Writing Makefile for Apache::DAV::Text \& Writing Makefile for Apache::DAV::TextHeader \& Writing Makefile for Apache::DAV::WalkerCtx \& Writing Makefile for Apache::DAV::XMLAttr \& Writing Makefile for Apache::DAV::XMLDoc \& Writing Makefile for Apache::DAV::XMLElem \& Writing Makefile for Apache::DAV \& Writing Makefile for Apache::TableEntry \& Writing Makefile for Apache \& Writing Makefile for WrapXS \& Writing Makefile for Apache::DAV .Ve .SS "and now compile..." .IX Subsection "and now compile..." .SH "How does it go on..." .IX Header "How does it go on..." .SS "Generating documentation" .IX Subsection "Generating documentation" XSBuilder already extracts source comments for functions and structures. It also parses doxygen comments, which are used in Apache 2.0. Lyle Brooks has started on automaticly createing POD files from this information. .SS "Improving callbacks" .IX Subsection "Improving callbacks" Callbacks are the main area that needs improvement. .SS "Bring it back to mod_perl 2.0" .IX Subsection "Bring it back to mod_perl 2.0" .SS "First version will be released just after the conference to CPAN" .IX Subsection "First version will be released just after the conference to CPAN" .SS "Any feedback and help appreciated" .IX Subsection "Any feedback and help appreciated" .SS Questions? .IX Subsection "Questions?"