ALPM
view release on metacpan or search on metacpan
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <alpm.h>
#include "types.h"
#include "cb.h"
#define alpm_croak(HND)\
croak("ALPM Error: %s", alpm_strerror(alpm_errno(HND)));
MODULE = ALPM PACKAGE = ALPM
PROTOTYPES: DISABLE
# ALPM::PackageFree is a subclass of ALPM::Package.
negative_is_error
unregister_all(self)
ALPM_Handle self
CODE:
RETVAL = alpm_unregister_all_syncdbs(self);
OUTPUT:
RETVAL
# Packages created with load_pkgfile must be freed by the caller.
# Hence we use ALPM_PackageFree. NULL pointers are converted
# into undef by the typemap.
ALPM_PackageFree
load_pkgfile(self, filename, full, siglevel)
ALPM_Handle self
const char *filename
int full
ALPM_SigLevel siglevel
CODE:
RETVAL = NULL;
alpm_pkg_load(self, filename, full, siglevel, &RETVAL);
* lib/ALPM/LoadConfig.pm: Fix bug where config file repos could
not have hyphens ("-"). Reported by knotty.
2010-11-21 Justin Davis <juster@cpan.org>
* lib/ALPM/Package.pm (attribs): Fix attribs to return a list and
not an array reference.
2010-06-22 Justin Davis <juster@cpan.org>
* lib/ALPM.pm (transaction): Removed type parameter from
transaction method.
* ALPM.xs: Renamed ALPM::DB method set_server to add_url.
2010-05-29 Justin Davis <juster@cpan.org>
* RELEASE (0.08): Uploaded to CPAN.
* typemap (find_group): Fix a bug with group type conversion.
This caused ALPM::DB::find_group() to croak instead of (properly)
returning undef when given a group name that didn't exist.
Reported by Andre Schmidt. Thanks!
2010-05-24 Justin Davis <juster@cpan.org>
* ALPM.xs (ALPM::Package): Renamed compute_requiredby method to
requiredby.
2010-05-02 Justin Davis <juster@cpan.org>
of fakeroot.
2009-10-29 Justin Davis <jrcd83@gmail.com>
* 0.4: Released version 0.4
2009-10-08 Justin Davis <jrcd83@gmail.com>
* lib/ALPM.pm (transaction): 'flags' are now passed as a string
of flag names separated by spaces. Added the sysupgrade
transaction 'type'.
* ALPM.xs: Added conv and progress callbacks for transactions.
2009-09-03 Justin Davis <jrcd83@gmail.com>
* ALPM.xs: s/alpm_pkg_get_/alpm_pkg_/;
* lib/ALPM/DB.pm: Renamed get_pkg_cache() to packages().
* lib/ALPM.pm: Changed methods local_db to localdb, get_sync_dbs
Changes
Makefile.PL
MANIFEST
MANIFEST.SKIP
README
ppport.h
ALPM.xs
alpm_xs.h
cb.c
cb.h
typemap
types.c
types.h
t/00-ALPM.t
t/01-Conf.t
t/02-DB.t
t/03-Package.t
t/04-Misc.t
t/05-Callbacks.t
t/repos/build/simpletest/bar/.PKGINFO
t/repos/build/simpletest/bar/usr/foo/bar/bar
t/repos/build/simpletest/foo/.PKGINFO
t/repos/build/simpletest/foo/usr/foo/foo
Makefile.PL view on Meta::CPAN
'VERSION_FROM' => 'lib/ALPM.pm',
'LICENSE' => 'perl',
'ABSTRACT_FROM' => 'lib/ALPM.pod',
'AUTHOR' => [
'Andrew Gregory <apg@cpan.org>',
'Justin Davis <juster at cpan dot org>'
],
'LIBS' => [ '-lalpm' ],
'META_MERGE' => \%meta,
'clean' => { 'FILES' => 't/root t/repos/share const-*.inc' },
'OBJECT' => 'ALPM.o types.o cb.o',
'XS' => { 'ALPM.xs' => 'ALPM.c' },
);
If you really need transactions why not call pacman with "system" or
backticks? In contrast, complicated queries becomes ugly and convoluted
when calling pacman in shell scripts. With the aid of this module, queries
should instead be possible in the quintessential ugly and succinct perl form.
Small utility scripts, like the examples, can also be quickly drawn up. This
is the new goal of the module.
INSTALLATION
To install this module type the following:
perl Makefile.PL
make
make test
make install
DEPENDENCIES
This module requires the alpm C library that is included with pacman.
libalpm 9.0.0 included with pacman version 4.2.0 was the latest version
? &PL_sv_undef : cb_ ## CBTYPE ## _sub );
void cb_log_wrapper ( alpm_loglevel_t level, const char * format, va_list args );
void cb_dl_wrapper ( const char *filename, off_t xfered, off_t total );
void cb_totaldl_wrapper ( off_t total );
int cb_fetch_wrapper ( const char *url, const char *localpath, int force );
/* TRANSACTIONS ************************************************************/
/* This macro is used inside alpm_trans_init.
CB_NAME is one of the transaction callback types (event, conv, progress).
* [CB_NAME]_sub is the argument to the trans_init XSUB.
* [CB_NAME]_func is a variable to hold the function pointer to pass
to the real C ALPM function.
* cb_trans_[CB_NAME]_wrapper is the name of the C wrapper function which
calls the perl sub stored in the global variable:
* cb_trans_[CB_NAME]_sub.
*/
#define UPDATE_TRANS_CALLBACK( CB_NAME ) \
if ( SvOK( CB_NAME ## _sub ) ) { \
} \
else if ( cb_trans_ ## CB_NAME ## _sub != NULL ) { \
/* If no event callback was provided for this new transaction, \
and an event callback is active, then remove the old callback. */ \
SvREFCNT_dec( cb_trans_ ## CB_NAME ## _sub ); \
cb_trans_ ## CB_NAME ## _sub = NULL; \
}
void cb_trans_event_wrapper ( alpm_transevt_t event,
void *arg_one, void *arg_two );
void cb_trans_conv_wrapper ( alpm_transconv_t type,
void *arg_one, void *arg_two, void *arg_three,
int *result );
void cb_trans_progress_wrapper ( alpm_transprog_t type,
const char * desc,
int item_progress,
size_t total_count,
size_t total_pos );
SV * convert_packagelist ( alpm_list_t * package_list );
SV * convert_depend ( alpm_depend_t * depend );
SV * convert_depmissing ( alpm_depissing_t * depmiss );
SV * convert_conflict (alpm_conflict_t * conflict );
SV * convert_fileconflict ( alpm_fileconflict_t * fileconflict );
lib/ALPM.pod view on Meta::CPAN
This is one of the following strings: error, warning, debug, function, or unknown.
=item 2. message
This is the message itself.
=back
=head1 DATA TYPES
Several libalpm data types have been converted into hash references. The
alternative is to turn them into full-blown objects, which seems pointless
considering the only methods are data accessors.
=head2 Dependency
Dependencies specify constraints on a set of packages. Only certain packages
satisfy a dependency. These can be used in places other than dependencies,
such as conflicts. Dependencies have the following keys:
=over 4
lib/ALPM.pod view on Meta::CPAN
=item reason
A hashref that is identical to a dependency. See L</Dependency>.
=back
=head2 Signature Level
Signature levels describe the level of security which is required for packages files
and by databases files. Different degrees of signature checking can be used for
either type of file. The signature checking is performed after the file is downloaded
in order to verify the original packager. B<When gpg is not available an invalid argument
error will be raised from libalpm if you try to set the siglevel.>
A "siglvl" can either be the string C<"default"> or a hash reference. A value of C<"default">
can be used when registering a database to instruct libalpm to use the default siglevel
that is set by I<set_defsiglvl>. A siglvl hashref must contain a C<"pkg"> key
and a C<"db"> key. Other keys are ignored.
Possible hash values include:
lib/ALPM/Conf.pm view on Meta::CPAN
my $SECTION_MATCH = qr/ \A \s* \[ ([^\]]+) \] \s* \z /xms;
my $FIELD_MATCH = qr/ \A \s* ([^=\s]+) (?: \s* = \s* ([^\n]*))? /xms;
sub _mkparser
{
my($path, $hooks) = @_;
sub {
local $_ = shift;
s/^\s+//; s/\s+$//; # trim whitespace
return unless(length);
# Call the appropriate hook for each type of token...
if(/$COMMENT_MATCH/){
;
}elsif(/$SECTION_MATCH/){
$hooks->{'section'}->($1);
}elsif(/$FIELD_MATCH/){
my($name, $val) = ($1, $2);
if(length $val){
my $apply = $hooks->{'field'}{$name};
$apply->($val) if($apply);
}
lib/ALPM/Conf.pm view on Meta::CPAN
return;
}
sub _parse_siglvl
{
my($str) = @_;
my $siglvl;
my $opt;
for(split /\s+/, $str){
my @types = qw/pkg db/;
if(s/^Package//){
@types = qw/pkg/;
}elsif(s/^Database//){
@types = qw/db/;
}
if(/^Never$/){
$opt->{$_} = 'never' for(@types);
}elsif(/^Optional$/){
$opt->{$_} = 'optional' for(@types);
}elsif(/^Required$/){
$opt->{$_} = 'required' for(@types);
}elsif(/^TrustedOnly$/){
;
}elsif(/^TrustAll$/){
for my $t (@types){
$opt->{$t} = 'optional' unless(defined $opt->{$t});
$opt->{$t} .= ' trustall';
}
}else{
die "Unknown SigLevel option: $_\n";
}
}
# Check for a blank SigLevel
unless(defined $opt){
lib/ALPM/Conf.pm view on Meta::CPAN
unless($dbpath){
$dbpath = "$root/var/lib/pacman";
$dbpath =~ tr{/}{/}s;
}
}
my $alpm = ALPM->new($root, $dbpath);
_setarch($opts);
while(my ($opt, $val) = each %$opts){
# The SetOption type in typemap croaks on error, no need to check.
_setopt($alpm, $opt, $val);
}
my $usesl = grep { /signatures/ } $alpm->caps;
for my $db (@$dbs){
my($r, $sl, $mirs) = @{$db}{'name', 'siglvl', 'mirrors'};
next if(!@$mirs);
_expurls($mirs, $opts->{'arch'}, $r);
$sl = 'default' if(!$usesl);
av_len|||
av_make|||
av_pop|||
av_push|||
av_reify|||
av_shift|||
av_store|||
av_undef|||
av_unshift|||
ax|||n
bad_type|||
bind_match|||
block_end|||
block_gimme||5.004000|
block_start|||
boolSV|5.004000||p
boot_core_PerlIO|||
boot_core_UNIVERSAL|||
boot_core_mro|||
boot_core_xsutils|||
bytes_from_utf8||5.007001|
call_list||5.004000|
call_method|5.006000||p
call_pv|5.006000||p
call_sv|5.006000||p
calloc||5.007002|n
cando|||
cast_i32||5.006000|
cast_iv||5.006000|
cast_ulong||5.006000|
cast_uv||5.006000|
check_type_and_open|||
check_uni|||
checkcomma|||
checkposixcc|||
ckWARN|5.006000||p
ck_anoncode|||
ck_bitop|||
ck_concat|||
ck_defined|||
ck_delete|||
ck_die|||
newPVOP|||
newRANGE|||
newRV_inc|5.004000||p
newRV_noinc|5.004000||p
newRV|||
newSLICEOP|||
newSTATEOP|||
newSUB|||
newSVOP|||
newSVREF|||
newSV_type||5.009005|
newSVhek||5.009003|
newSViv|||
newSVnv|||
newSVpvf_nocontext|||vn
newSVpvf||5.004000|v
newSVpvn_flags|5.011000||p
newSVpvn_share|5.007001||p
newSVpvn_utf8|5.011000||p
newSVpvn|5.004050||p
newSVpvs_flags|5.011000||p
newSV|||
newTOKEN|||
newUNOP|||
newWHENOP||5.009003|
newWHILEOP||5.009003|
newXS_flags||5.009004|
newXSproto||5.006000|
newXS||5.006000|
new_collate||5.006000|
new_constant|||
new_ctype||5.006000|
new_he|||
new_logop|||
new_numeric||5.006000|
new_stackinfo||5.005000|
new_version||5.009000|
new_warnings_bitfield|||
next_symbol|||
nextargv|||
nextchar|||
ninstr|||
packWARN|5.007003||p
pack_cat||5.007003|
pack_rec|||
package|||
packlist||5.008001|
pad_add_anon|||
pad_add_name|||
pad_alloc|||
pad_block_start|||
pad_check_dup|||
pad_compname_type|||
pad_findlex|||
pad_findmy|||
pad_fixup_inner_anons|||
pad_free|||
pad_leavemy|||
pad_new|||
pad_peg|||n
pad_push|||
pad_reset|||
pad_setsv|||
save_vptr||5.006000|
savepvn|||
savepvs||5.009003|
savepv|||
savesharedpvn||5.009005|
savesharedpv||5.007003|
savestack_grow_cnt||5.008001|
savestack_grow|||
savesvpv||5.009002|
sawparens|||
scalar_mod_type|||n
scalarboolean|||
scalarkids|||
scalarseq|||
scalarvoid|||
scalar|||
scan_bin||5.006000|
scan_commit|||
scan_const|||
scan_formline|||
scan_heredoc|||
sv_pvbyte||5.006000|
sv_pvn_force_flags|5.007002||p
sv_pvn_force|||
sv_pvn_nomg|5.007003|5.005000|p
sv_pvn||5.005000|
sv_pvutf8n_force||5.006000|
sv_pvutf8n||5.006000|
sv_pvutf8||5.006000|
sv_pv||5.006000|
sv_recode_to_utf8||5.007003|
sv_reftype|||
sv_release_COW|||
sv_replace|||
sv_report_used|||
sv_reset|||
sv_rvweaken||5.006000|
sv_setiv_mg|5.004050||p
sv_setiv|||
sv_setnv_mg|5.006000||p
sv_setnv|||
sv_setpv_mg|5.004050||p
sv_utf8_upgrade_nomg||5.007002|
sv_utf8_upgrade||5.007001|
sv_uv|5.005000||p
sv_vcatpvf_mg|5.006000|5.004000|p
sv_vcatpvfn||5.004000|
sv_vcatpvf|5.006000|5.004000|p
sv_vsetpvf_mg|5.006000|5.004000|p
sv_vsetpvfn||5.004000|
sv_vsetpvf|5.006000|5.004000|p
sv_xmlpeek|||
svtype|||
swallow_bom|||
swap_match_buff|||
swash_fetch||5.007002|
swash_get|||
swash_init||5.006000|
sys_init3||5.010000|n
sys_init||5.010000|n
sys_intern_clear|||
sys_intern_dup|||
sys_intern_init|||
$file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg);
}
}
$file{needs_inc_ppport} = keys %{$file{uses}};
if ($file{needs_inc_ppport}) {
my $pp = '';
for $func (sort keys %{$file{needs}}) {
my $type = $file{needs}{$func};
next if $type eq 'extern';
my $suffix = $type eq 'global' ? '_GLOBAL' : '';
unless (exists $file{"needed_$type"}{$func}) {
if ($type eq 'global') {
diag("Files [@{$global{needs}{$func}}] need $func, adding global request");
}
else {
diag("File needs $func, adding static request");
}
$pp .= "#define NEED_$func$suffix\n";
}
}
if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) {
#ifndef dNOOP
# define dNOOP extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL
#endif
#ifndef NVTYPE
# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
# define NVTYPE long double
# else
# define NVTYPE double
# endif
typedef NVTYPE NV;
#endif
#ifndef INT2PTR
# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
# define PTRV UV
# define INT2PTR(any,d) (any)(d)
# else
# if PTRSIZE == LONGSIZE
# define PTRV unsigned long
# else
#ifndef PERLIO_FUNCS_DECL
# ifdef PERLIO_FUNCS_CONST
# define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs
# define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs)
# else
# define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs
# define PERLIO_FUNCS_CAST(funcs) (funcs)
# endif
#endif
/* provide these typedefs for older perls */
#if (PERL_BCDVERSION < 0x5009003)
# ifdef ARGSproto
typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto);
# else
typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX);
# endif
typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*);
#endif
#ifndef isPSXSPC
# define isPSXSPC(c) (isSPACE(c) || (c) == '\v')
#endif
#ifndef isBLANK
# define isBLANK(c) ((c) == ' ' || (c) == '\t')
#endif
#endif
/*
* Boilerplate macros for initializing and accessing interpreter-local
* data from C. All statics in extensions should be reworked to use
* this, if you want to make the extension thread-safe. See ext/re/re.xs
* for an example of the use of these macros.
*
* Code that uses these macros is responsible for the following:
* 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
* 2. Declare a typedef named my_cxt_t that is a structure that contains
* all the data that needs to be interpreter-local.
* 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
* 4. Use the MY_CXT_INIT macro such that it is called exactly once
* (typically put in the BOOT: section).
* 5. Use the members of the my_cxt_t structure everywhere as
* MY_CXT.member.
* 6. Use the dMY_CXT macro (a declaration) in all the functions that
* access MY_CXT.
*/
#define Perl_grok_number DPPP_(my_grok_number)
#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL)
int
DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep)
{
const char *s = pv;
const char *send = pv + len;
const UV max_div_10 = UV_MAX / 10;
const char max_mod_10 = UV_MAX % 10;
int numtype = 0;
int sawinf = 0;
int sawnan = 0;
while (s < send && isSPACE(*s))
s++;
if (s == send) {
return 0;
} else if (*s == '-') {
s++;
numtype = IS_NUMBER_NEG;
}
else if (*s == '+')
s++;
if (s == send)
return 0;
/* next must be digit or the radix separator or beginning of infinity */
if (isDIGIT(*s)) {
/* UVs are at least 32 bits, so the first 9 decimal digits cannot
break;
}
if (digit >= 0 && digit <= 9
&& (s < send)) {
/* value overflowed.
skip the remaining digits, don't
worry about setting *valuep. */
do {
s++;
} while (s < send && isDIGIT(*s));
numtype |=
IS_NUMBER_GREATER_THAN_UV_MAX;
goto skip_value;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
numtype |= IS_NUMBER_IN_UV;
if (valuep)
*valuep = value;
skip_value:
if (GROK_NUMERIC_RADIX(&s, send)) {
numtype |= IS_NUMBER_NOT_INT;
while (s < send && isDIGIT(*s)) /* optional digits after the radix */
s++;
}
}
else if (GROK_NUMERIC_RADIX(&s, send)) {
numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */
/* no digits before the radix means we need digits after it */
if (s < send && isDIGIT(*s)) {
do {
s++;
} while (s < send && isDIGIT(*s));
if (valuep) {
/* integer approximation is valid - it's 0. */
*valuep = 0;
}
}
} else if (*s == 'N' || *s == 'n') {
/* XXX TODO: There are signaling NaNs and quiet NaNs. */
s++; if (s == send || (*s != 'A' && *s != 'a')) return 0;
s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
s++;
sawnan = 1;
} else
return 0;
if (sawinf) {
numtype &= IS_NUMBER_NEG; /* Keep track of sign */
numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
} else if (sawnan) {
numtype &= IS_NUMBER_NEG; /* Keep track of sign */
numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
} else if (s < send) {
/* we can have an optional exponent part */
if (*s == 'e' || *s == 'E') {
/* The only flag we keep is sign. Blow away any "it's UV" */
numtype &= IS_NUMBER_NEG;
numtype |= IS_NUMBER_NOT_INT;
s++;
if (s < send && (*s == '-' || *s == '+'))
s++;
if (s < send && isDIGIT(*s)) {
do {
s++;
} while (s < send && isDIGIT(*s));
}
else
return 0;
}
}
while (s < send && isSPACE(*s))
s++;
if (s >= send)
return numtype;
if (len == 10 && memEQ(pv, "0 but true", 10)) {
if (valuep)
*valuep = 0;
return IS_NUMBER_IN_UV;
}
return 0;
}
#endif
#endif
off_t T_INT
#--------------------
# INPUT # Perl ==> C
#--------------------
INPUT
T_ALPM_HANDLE
if(sv_derived_from($arg, \"ALPM\")){
$var = INT2PTR($type, SvIV((SV *)SvRV($arg)));
}else{
croak(\"error: expected an ALPM object\");
}
T_ALPM_DB
if(sv_derived_from($arg, \"ALPM::DB\")){
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type, tmp);
}else{
croak(\"error: expected an ALPM::DB object\");
}
T_ALPM_LOCALDB
if(sv_derived_from($arg, \"ALPM::DB::Local\")){
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type, tmp);
}else{
croak(\"error: expected an ALPM::DB::Local object\");
}
T_ALPM_SYNCDB
if(sv_derived_from($arg, \"ALPM::DB::Sync\")){
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type, tmp);
}else{
croak(\"error: expected an ALPM::DB::Sync object\");
}
T_ALPM_PACKAGE
if(sv_derived_from($arg, \"ALPM::Package\")){
$var = INT2PTR($type, SvIV((SV *)SvRV($arg)));
}else{
croak(\"error: expected an ALPM::Package object\");
}
T_ALPM_PACKAGEFREE
if(sv_derived_from($arg, \"ALPM::PackageFree\")){
IV tmp = SvIV((SV*)SvRV($arg));
$var = INT2PTR($type,tmp);
}else{
croak(\"error: expected an ALPM::PackageFree object\");
}
T_SIGLEVEL
$var = p2c_siglevel($arg);
T_DEPEND
$var = p2c_depend($arg);
#include <stdlib.h>
#include <string.h>
#include <alpm.h>
/* Perl API headers. */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "types.h"
/* SCALAR CONVERSIONS */
SV*
c2p_str(void *str)
{
return newSVpv(str, 0);
}
const char*
#ifndef _ALPMXS_TYPES
#define _ALPMXS_TYPES
/* TYPEDEFS */
/* Used in typemap and xs/Options.xs. */
typedef int SetOption;
typedef int IntOption;
typedef char * StringOption;
typedef int negative_is_error;
typedef alpm_handle_t * ALPM_Handle;
typedef alpm_db_t * ALPM_DB;
typedef alpm_db_t * ALPM_LocalDB;
typedef alpm_db_t * ALPM_SyncDB;
typedef alpm_pkg_t * ALPM_Package;
typedef alpm_pkg_t * ALPM_PackageFree;
typedef alpm_siglevel_t ALPM_SigLevel;
typedef alpm_pkgfrom_t ALPM_Origin;
typedef alpm_pkgvalidation_t ALPM_Validity;
typedef alpm_depend_t * ALPM_Depend;
typedef alpm_conflict_t * ConflictArray;
typedef alpm_list_t * StringListFree;
typedef alpm_list_t * StringList;
typedef alpm_list_t * PackageListNoFree;
typedef alpm_list_t * DependList;
typedef alpm_list_t * ListAutoFree;
typedef alpm_filelist_t * ALPM_FileList;
/* these are for list converter functions */
typedef SV* (*scalarmap)(void*);
typedef void* (*listmap)(SV*);
/* CONVERTER FUNC PROTOS */
SV* c2p_str(void*);
const char* p2c_str(SV*);
SV* c2p_pkg(void*);
ALPM_Package p2c_pkg(SV*);
ALPM_DB p2c_db(SV*);
( run in 1.156 second using v1.01-cache-2.11-cpan-df04353d9ac )