AI-FANN

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for Perl extension AI::FANN.

0.10 Mar 10, 2009
    - syntax error in Makefile.PL (bug report by Michael Stevens)
    - backport OpenBSD patch for Makefile.PL

0.09 Oct 16, 2008
    - AI::FANN::TrainData->new_from_file was nos working (bug reported
      by Renata Camargo)
    - constructors were not reporting errors via exceptions as
      documented
    - compiler warnings cleaned

0.08 Jul 5, 2007
    - use doubles instead of floats on accessors
    - MSE is a float (bug and patch by Alex Lang)
    - add support for FANN_SIN_SYMMETRIC, FANN_COS_SYMMETRIC,
      FANN_SIN and FANN_COS constants.

0.07 Nov 22, 2006
    - move to FANN 2.1

0.06 Sep 18, 2006
    - add support for FANN_LIB and FANN_INCLUDE to MAkefile.PL

0.05 May 4, 2006
    - ppport.h regenerated with latest version of Devel::PPPort to
      make it work on perls older than 5.8.8 (bug reported by bodyn).

0.04 May 1, 2006
    - corrected bug on accessor generators with indexes
    - better accessor generation using default arguments XS feature

0.03 Apr 14, 2006
    - improved docs.

0.02 Apr 14, 2006
    - improved docs.

0.01 Apr 7, 2006
    - original version; created by h2xs 1.23 with options
        -An AI::FANN /usr/local/include/fann.h

FANN.xs  view on Meta::CPAN

#include "constants.h"

#define WANT_MORTAL 1

typedef fann_type *fta; /* fta: fann_type array */
typedef fta fta_input;
typedef fta fta_output;

static SV *
_obj2sv(pTHX_ void *ptr, SV * klass, char * ctype) {
    if (ptr) {
	SV *rv;
	SV *sv = newSVpvf("%s(0x%p)", ctype, ptr);
	SV *mgobj = sv_2mortal(newSViv(PTR2IV(ptr)));
	SvREADONLY_on(mgobj);
	sv_magic(sv, mgobj, '~', ctype, 0);
	/* SvREADONLY_on(sv); */
	rv = newRV_noinc(sv);
	if (SvOK(klass)) {
	    HV *stash;
	    if (SvROK(klass))
		stash = SvSTASH(klass);
	    else
		stash = gv_stashsv(klass, 1);
	    
	    sv_bless(rv, stash);
	}
	return rv;
    }
    return &PL_sv_undef;
}

static void *
_sv2obj(pTHX_ SV* self, char * ctype, int required) {
    SV *sv = SvRV(self);
    if (sv) {
        if (SvTYPE(sv) == SVt_PVMG) {
            MAGIC *mg = mg_find(sv, '~');
            if (mg) {
                if (strcmp(ctype, mg->mg_ptr) == 0 && mg->mg_obj) {
                    return INT2PTR(void *, SvIV(mg->mg_obj));
                }
            }
        }
    }
    if (required) {
        Perl_croak(aTHX_ "object of class %s expected", ctype);
    }
    return NULL;
}

static SV *
_fta2sv(pTHX_ fann_type *fta, unsigned int len) {
    unsigned int i;
    AV *av = newAV();
    av_extend(av, len - 1);
    for (i = 0; i < len; i++) {
        SV *sv = newSVnv(fta[i]);
        av_store(av, i, sv);
    }
    return newRV_noinc((SV*)av);
}

static AV*
_srv2av(pTHX_ SV* sv, unsigned int len, char * const name) {
    if (SvROK(sv)) {
        AV *av = (AV*)SvRV(sv);
        if (SvTYPE((SV*)av)==SVt_PVAV) {
            if (av_len(av)+1 == len) {
                return av;
            }
            else {
                Perl_croak(aTHX_ "wrong number of elements in %s array, %d found when %d were required",
                           name, (unsigned int)(av_len(av)+1), len);
            }
        }
    }
    Perl_croak(aTHX_ "wrong type for %s argument, array reference expected", name);
}

static fann_type*
_sv2fta(pTHX_ SV *sv, unsigned int len, int flags, char * const name) {
    unsigned int i;
    fann_type *fta;
    AV *av = _srv2av(aTHX_ sv, len, name);

    Newx(fta, len, fann_type);
    if (flags & WANT_MORTAL) SAVEFREEPV(fta);

    for (i = 0; i < len; i++) {
        SV ** svp = av_fetch(av, i, 0);
        fta[i] = SvNV(svp ? *svp : &PL_sv_undef);
    }
    return fta;
}

static void
_check_error(pTHX_ struct fann_error *self) {
    if (self) {
        if (fann_get_errno(self) != FANN_E_NO_ERROR) {
            ERRSV = newSVpv(self->errstr, strlen(self->errstr) - 2);
            fann_get_errstr(self);
            Perl_croak(aTHX_ Nullch);
        }
    }
    else {
        Perl_croak(aTHX_ "Constructor failed");
    }
}

static unsigned int
_sv2enum(pTHX_ SV *sv, unsigned int top, char * const name) {
	unsigned int value = SvUV(sv);
	if (value > top) {
		Perl_croak(aTHX_ "value %d is out of range for %s", value, name);
	}
	return value;
}

static SV *
_enum2sv(pTHX_ unsigned int value, char const * const * const names, unsigned int top, char const * const name) {
    SV *sv;
    if (value > top) {
        Perl_croak(aTHX_ "internal error: value %d out of range for %s", value, name);
    }
    sv = newSVpv(names[value], 0);
    SvUPGRADE(sv, SVt_PVIV);
    SvUV_set(sv, value);
    SvIOK_on(sv);
    SvIsUV_on(sv);
    return sv;
}

#define _sv2fann_train_enum(sv) _sv2enum(aTHX_ sv, FANN_TRAIN_QUICKPROP, "fann_train_enum")
#define _sv2fann_activationfunc_enum(sv) _sv2enum(aTHX_ sv, FANN_LINEAR_PIECE_SYMMETRIC, "fann_activationfunc_enum")
#define _sv2fann_errorfunc_enum(sv) _sv2enum(aTHX_ sv, FANN_ERRORFUNC_TANH, "fann_errorfunc_enum")
#define _sv2fann_stopfunc_enum(sv) _sv2enum(aTHX_ sv, FANN_STOPFUNC_BIT, "fann_stopfunc_enum")

#define _fann_train_enum2sv(sv) _enum2sv(aTHX_ sv, FANN_TRAIN_NAMES, FANN_TRAIN_QUICKPROP, "fann_train_enum")
#define _fann_activationfunc_enum2sv(sv) _enum2sv(aTHX_ sv, FANN_ACTIVATIONFUNC_NAMES, FANN_LINEAR_PIECE_SYMMETRIC, "fann_activationfunc_enum")
#define _fann_errorfunc_enum2sv(sv) _enum2sv(aTHX_ sv, FANN_ERRORFUNC_NAMES, FANN_ERRORFUNC_TANH, "fann_errorfunc_enum")

FANN.xs  view on Meta::CPAN

#define fann_train_data_length fann_length_train_data
#define fann_train_data_num_input fann_num_input_train_data
#define fann_train_data_num_output fann_num_output_train_data
#define fann_train_data_save fann_save_train

MODULE = AI::FANN		PACKAGE = AI::FANN		PREFIX = fann_

PROTOTYPES: DISABLE

BOOT:
    fann_set_error_log(0, 0);

void
_constants()
  PREINIT:
    unsigned int i;
  PPCODE:
    for (i = 0; my_constant_names[i]; i++) {
        SV *sv = sv_2mortal(newSVpv(my_constant_names[i], 0));
        SvUPGRADE(sv, SVt_PVIV);
        SvUV_set(sv, my_constant_values[i]);
        SvIOK_on(sv);
        SvIsUV_on(sv);
		XPUSHs(sv);
	}
    XSRETURN(i);

struct fann *
fann_new_standard(klass, ...)
    SV *klass;
  PREINIT:
    unsigned int *layers;
    unsigned int i;
    unsigned int num_layers;
  CODE:
    num_layers = items - 1;
    Newx(layers, num_layers, unsigned int);
    SAVEFREEPV(layers);
    for (i = 0; i < num_layers; i++) {
		layers[i] = SvIV(ST(i+1));
    }
    RETVAL = fann_create_standard_array(num_layers, layers);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

struct fann *
fann_new_sparse(klass, connection_rate, ...)
    SV *klass;
    double connection_rate;
  PREINIT:
    unsigned int *layers;
    unsigned int i;
    unsigned int num_layers;
  CODE:
    num_layers = items - 2;
    Newx(layers, num_layers, unsigned int);
    SAVEFREEPV(layers);
    for (i = 0; i < num_layers; i++) {
		layers[i] = SvIV(ST(i+2));
    }
    RETVAL = fann_create_sparse_array(connection_rate, num_layers, layers);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

struct fann *
fann_new_shortcut(klass, ...)
    SV *klass;
  PREINIT:
    unsigned int *layers;
    unsigned int i;
    unsigned int num_layers;
  CODE:
    num_layers = items - 1;
    Newx(layers, num_layers, unsigned int);
    SAVEFREEPV(layers);
    for (i = 0; i < num_layers; i++) {
		layers[i] = SvIV(ST(i+1));
    }
    RETVAL = fann_create_shortcut_array(num_layers, layers);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

struct fann *
fann_new_from_file(klass, filename)
    SV *klass;
    char *filename;
  CODE:
    RETVAL = fann_create_from_file(filename);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

void
fann_DESTROY(self)
    struct fann * self;
  CODE:
    fann_destroy(self);
    sv_unmagic(SvRV(ST(0)), '~');

int
fann_save(self, filename)
    struct fann *self;
    char * filename;
  CODE:
    RETVAL = !fann_save(self, filename);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

fta_output
fann_run(self, input)
    struct fann *self;
    fta_input input;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_randomize_weights(self, min_weight, max_weight)
    struct fann *self;
    fann_type min_weight;
    fann_type max_weight;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train(self, input, desired_output)
    struct fann *self;
    fta_input input;
    fta_output desired_output;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

fta_output
fann_test(self, input, desired_output)
    struct fann *self;
    fta_input input;
    fta_output desired_output;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_reset_MSE(self)
    struct fann * self;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train_on_file(self, filename, max_epochs, epochs_between_reports, desired_error) 
    struct fann *self;
    const char *filename;
    unsigned int max_epochs;
    unsigned int epochs_between_reports;
    double desired_error;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train_on_data(self, data, max_epochs, epochs_between_reports, desired_error)
    struct fann *self;
    struct fann_train_data *data;
    unsigned int max_epochs;
    unsigned int epochs_between_reports;
    double desired_error;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);
    _check_error(aTHX_ (struct fann_error *)data);

void
fann_cascadetrain_on_file(self, filename, max_neurons, neurons_between_reports, desired_error)
    struct fann *self;
	const char *filename;
    unsigned int max_neurons;
    unsigned int neurons_between_reports;
    double desired_error;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_cascadetrain_on_data(self, data, max_neurons, neurons_between_reports, desired_error)
    struct fann *self;
    struct fann_train_data *data;
    unsigned int max_neurons;
    unsigned int neurons_between_reports;
    double desired_error;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);
    _check_error(aTHX_ (struct fann_error *)data);

double
fann_train_epoch(self, data)
    struct fann *self;
    struct fann_train_data *data;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);
    _check_error(aTHX_ (struct fann_error *)data);

void
fann_print_connections(self)
    struct fann * self;

void
fann_print_parameters(self)
    struct fann * self;

void
fann_cascade_activation_functions(self, ...)
    struct fann *self;
  PREINIT:
    unsigned int count;
  PPCODE:
    if (items > 1) {
        unsigned int i;
        enum fann_activationfunc_enum * funcs;
        count = items - 1;
        Newx(funcs, items - 1, enum fann_activationfunc_enum);
        SAVEFREEPV(funcs);
        for (i = 0; i < count; i++) {
            funcs[i] = _sv2fann_activationfunc_enum(ST(i+1));
        }
        fann_set_cascade_activation_functions(self, funcs, count);
    }
    count = fann_get_cascade_activation_functions_count(self);
    if (GIMME_V == G_ARRAY) {
        unsigned int i;
        enum fann_activationfunc_enum * funcs = fann_get_cascade_activation_functions(self);
        EXTEND(SP, count);
        for (i = 0; i < count; i++) {
            ST(i) = sv_2mortal(_fann_activationfunc_enum2sv(funcs[i]));
        }
        XSRETURN(count);
    }
    else {
        ST(0) = sv_2mortal(newSVuv(count));
        XSRETURN(1);
    }

void
fann_cascade_activation_steepnesses(self, ...)
    struct fann *self;
  PREINIT:
    unsigned int count;
  PPCODE:
    if (items > 1) {
        unsigned int i;
        fann_type * steepnesses;
        count = items - 1;
        Newx(steepnesses, items - 1, fann_type);
        SAVEFREEPV(steepnesses);
        for (i = 0; i < count; i++) {
            steepnesses[i] = SvNV(ST(i+1));
        }
        fann_set_cascade_activation_steepnesses(self, steepnesses, count);
    }
    count = fann_get_cascade_activation_steepnesses_count(self);
    if (GIMME_V == G_ARRAY) {
        unsigned int i;
        fann_type * steepnesses = fann_get_cascade_activation_steepnesses(self);
        EXTEND(SP, count);
        for (i = 0; i < count; i++) {
            ST(i) = sv_2mortal(newSVuv(steepnesses[i]));
        }
        XSRETURN(count);
    }
    else {
        ST(0) = sv_2mortal(newSVuv(count));
        XSRETURN(1);
    }


MODULE = AI::FANN		PACKAGE = AI::FANN::TrainData		PREFIX = fann_train_data_

struct fann_train_data *
fann_train_data_new_from_file(klass, filename)
    SV *klass;
    const char *filename;
  CODE:
    RETVAL = fann_train_data_create_from_file(filename);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

struct fann_train_data *
fann_train_data_new_empty(klass, num_data, num_input, num_output)
    SV *klass;
    unsigned int num_data;
    unsigned int num_input;
    unsigned int num_output;
  CODE:
    RETVAL = fann_train_data_create(num_data, num_input, num_output);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);

void
fann_train_data_data(self, index, ...)
    struct fann_train_data *self;
    unsigned int index;
  PREINIT:
    AV *input;
    AV *output;
    unsigned int i;
  PPCODE:
    if (index >= self->num_data)
        Perl_croak(aTHX_"index %d is out of range", index);
    switch (items) {
    case 4:
        input = _srv2av(aTHX_ ST(2), self->num_input, "input");
        for (i = 0; i < self->num_input; i++) {
            SV **svp = av_fetch(input, i, 0);
            self->input[index][i] = SvNV(svp ? *svp : &PL_sv_undef);
        }
        output = _srv2av(aTHX_ ST(3), self->num_output, "output");
        for (i = 0; i < self->num_output; i++) {
            SV **svp = av_fetch(output, i, 0);
            self->output[index][i] = SvNV(svp ? *svp : &PL_sv_undef);
        }
    case 2:
        if (GIMME_V == G_ARRAY) {
            input = newAV();
            output = newAV();
            av_extend(input, self->num_input - 1);
            av_extend(output, self->num_output - 1);
            for (i = 0; i < self->num_input; i++) {
                SV *sv = newSVnv(self->input[index][i]);
                av_store(input, i, sv);
            }
            for (i = 0; i < self->num_output; i++) {
                SV *sv = newSVnv(self->output[index][i]);
                av_store(output, i, sv);
            }
            ST(0) = sv_2mortal(newRV_inc((SV*)input));
            ST(1) = sv_2mortal(newRV_inc((SV*)output));
            XSRETURN(2);
        }
        else {
            ST(0) = &PL_sv_yes;
            XSRETURN(1);
        }
        break;
    default:
        Perl_croak(aTHX_ "Usage: AI::FANN::TrainData::data(self, index [, input, output])");
    }

struct fann_train_data *
fann_train_data_new(klass, input, output, ...)
    SV *klass;
    AV *input;
    AV *output;
  PREINIT:
    unsigned int num_data;
    unsigned int num_input;
    unsigned int num_output;
    unsigned int i;
  CODE:
    if (!(items & 1)) {
		Perl_croak(aTHX_ "wrong number of arguments in constructor");
    }
    num_data = items >> 1;
    num_input = av_len(input) + 1;
    if (!num_input)
        Perl_croak(aTHX_ "input array is empty");
    num_output = av_len(output) + 1;
    if (!num_output)
        Perl_croak(aTHX_ "output array is empty");
    RETVAL = fann_train_data_create(num_data, num_input, num_output);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)RETVAL);
    /* we do that at cleanup to ensure that the just created object is
     * freed if we croak */
    if (RETVAL) {
        for (i = 0; i < num_data; i++) {
            unsigned int j;
            input = _srv2av(aTHX_ ST(1 + i * 2), num_input, "input");
            for (j = 0; j < num_input; j++) {
                SV **svp = av_fetch(input, j, 0);
                RETVAL->input[i][j] = SvNV(svp ? *svp : &PL_sv_undef);
            }
            output = _srv2av(aTHX_ ST(2 + i * 2), num_output, "output");
            for (j = 0; j < num_output; j++) {
                SV **svp = av_fetch(output, j, 0);
                RETVAL->output[i][j] = SvNV(svp ? *svp : &PL_sv_undef);
            }
        }
    }

void
fann_train_data_DESTROY(self)
    struct fann_train_data * self;
  CODE:
    fann_destroy_train(self);
    sv_unmagic(SvRV(ST(0)), '~');

void
fann_train_data_shuffle(self)
    struct fann_train_data *self;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train_data_scale_input(self, new_min, new_max)
    struct fann_train_data *self;
    fann_type new_min;
    fann_type new_max;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train_data_scale_output(self, new_min, new_max)
    struct fann_train_data *self;
    fann_type new_min;
    fann_type new_max;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

void
fann_train_data_scale(self, new_min, new_max)
    struct fann_train_data *self;
    fann_type new_min;
    fann_type new_max;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

struct fann_train_data*
fann_train_data_subset(self, pos, length)
    struct fann_train_data *self;
    unsigned int pos;
    unsigned int length;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);
    _check_error(aTHX_ (struct fann_error *)RETVAL);


INCLUDE: accessors.xsh

META.yml  view on Meta::CPAN

--- #YAML:1.0
name:                AI-FANN
version:             0.10
abstract:            Perl wrapper for the Fast Artificial Neural Network library
license:             ~
author:              
    - Salvador Fandiño <sfandino@yahoo.com>
generated_by:        ExtUtils::MakeMaker version 6.42
distribution_type:   module
requires:     
meta-spec:
    url:     http://module-build.sourceforge.net/META-spec-v1.3.html
    version: 1.3

Makefile.PL  view on Meta::CPAN

use ExtUtils::MakeMaker;

use strict;
use warnings;

my $fann_lib = '';
my $fann_inc = '';
my $prefix;

@ARGV = map {
    if (/^FANN_LIB=(.*)/) {
        $fann_lib = "-L$1 ";
        ()
    }
    elsif (/^FANN_INCLUDE=(.*)/) {
        $fann_inc = "-I$1 ";
        ()
    }
    else {
	$prefix = $1 if /^PREFIX=(.*)/;
	$_
    }
} @ARGV;

if (defined $prefix) {
    $fann_lib = "-L$prefix/lib " unless length $fann_lib;
    $fann_inc = "-I$prefix/include " unless length $fann_inc;
}

WriteMakefile( NAME => 'AI::FANN',
               VERSION_FROM => 'lib/AI/FANN.pm',
               PREREQ_PM => {},
               ABSTRACT_FROM => 'lib/AI/FANN.pm',
               AUTHOR => 'Salvador Fandiño <sfandino@yahoo.com>',
               LIBS => ["${fann_lib}-ldoublefann"],
               DEFINE => '',
               INC => "${fann_inc}-I.",
               OBJECT => '$(BASEEXT)$(OBJ_EXT) morefann$(OBJ_EXT)',
               #OPTIMIZE => '-g -O0',
               depend => { '$(BASEEXT).c' => 'constants.h accessors.xsh' }
             );

sub MY::postamble {
    return <<MAKE_FRAG

constants.h: genconstants
\t\$(PERL) genconstants > constants.h

accessors.xsh: genaccessors
\t\$(PERL) genaccessors > accessors.xsh

MAKE_FRAG

}

README  view on Meta::CPAN

This module requires the FANN library version 2.1.0beta or later
compiled to use doubles internally.

The module Test::More is also required for testing.


INSTALLATION

To install this module type the following:

   perl Makefile.PL
   make
   make test
   make install

You may need to add two extra parameters to the Makefile.PL script to
indicate where to find the FANN library and include files if they are
not installed on some standard locations. For instance:

   perl Makefile.PL                            \
       FANN_LIB=/usr/local/fann/lib            \
       FANN_INCLUDE=/usr/local/fann/include


COPYRIGHT AND LICENCE

Copyright (C) 2006 by Salvador Fandino (sfandino@yahoo.com).

This Perl module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself, either Perl version
5.8.8 or, at your option, any later version of Perl 5 you may have
available.

accessors.xsh  view on Meta::CPAN


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

enum fann_train_enum
accessor_training_algorithm(self, value = NO_INIT)
    struct fann * self;
    enum fann_train_enum value
  CODE:
    if (items > 1) {
        fann_set_training_algorithm(self, value);
    }
    RETVAL = fann_get_training_algorithm(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

enum fann_errorfunc_enum
accessor_train_error_function(self, value = NO_INIT)
    struct fann * self;
    enum fann_errorfunc_enum value
  CODE:
    if (items > 1) {
        fann_set_train_error_function(self, value);
    }
    RETVAL = fann_get_train_error_function(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

enum fann_stopfunc_enum
accessor_train_stop_function(self, value = NO_INIT)
    struct fann * self;
    enum fann_stopfunc_enum value
  CODE:
    if (items > 1) {
        fann_set_train_stop_function(self, value);
    }
    RETVAL = fann_get_train_stop_function(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_learning_rate(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_learning_rate(self, value);
    }
    RETVAL = fann_get_learning_rate(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_learning_momentum(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_learning_momentum(self, value);
    }
    RETVAL = fann_get_learning_momentum(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

fann_type
accessor_bit_fail_limit(self, value = NO_INIT)
    struct fann * self;
    fann_type value
  CODE:
    if (items > 1) {
        fann_set_bit_fail_limit(self, value);
    }
    RETVAL = fann_get_bit_fail_limit(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_quickprop_decay(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_quickprop_decay(self, value);
    }
    RETVAL = fann_get_quickprop_decay(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_quickprop_mu(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_quickprop_mu(self, value);
    }
    RETVAL = fann_get_quickprop_mu(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_rprop_increase_factor(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_rprop_increase_factor(self, value);
    }
    RETVAL = fann_get_rprop_increase_factor(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_rprop_decrease_factor(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_rprop_decrease_factor(self, value);
    }
    RETVAL = fann_get_rprop_decrease_factor(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_rprop_delta_min(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_rprop_delta_min(self, value);
    }
    RETVAL = fann_get_rprop_delta_min(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_rprop_delta_max(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_rprop_delta_max(self, value);
    }
    RETVAL = fann_get_rprop_delta_max(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_num_inputs(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_num_input(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_num_outputs(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_num_output(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_total_neurons(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_total_neurons(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_total_connections(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_total_connections(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_connection_rate(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_connection_rate(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_MSE(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_MSE(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_bit_fail(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_bit_fail(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_cascade_output_change_fraction(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_cascade_output_change_fraction(self, value);
    }
    RETVAL = fann_get_cascade_output_change_fraction(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_cascade_output_stagnation_epochs(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_cascade_output_stagnation_epochs(self, value);
    }
    RETVAL = fann_get_cascade_output_stagnation_epochs(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

double
accessor_cascade_candidate_change_fraction(self, value = NO_INIT)
    struct fann * self;
    double value
  CODE:
    if (items > 1) {
        fann_set_cascade_candidate_change_fraction(self, value);
    }
    RETVAL = fann_get_cascade_candidate_change_fraction(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_cascade_candidate_stagnation_epochs(self, value = NO_INIT)
    struct fann * self;
    unsigned int value
  CODE:
    if (items > 1) {
        fann_set_cascade_candidate_stagnation_epochs(self, value);
    }
    RETVAL = fann_get_cascade_candidate_stagnation_epochs(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

fann_type
accessor_cascade_weight_multiplier(self, value = NO_INIT)
    struct fann * self;
    fann_type value
  CODE:
    if (items > 1) {
        fann_set_cascade_weight_multiplier(self, value);
    }
    RETVAL = fann_get_cascade_weight_multiplier(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

fann_type
accessor_cascade_candidate_limit(self, value = NO_INIT)
    struct fann * self;
    fann_type value
  CODE:
    if (items > 1) {
        fann_set_cascade_candidate_limit(self, value);
    }
    RETVAL = fann_get_cascade_candidate_limit(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_cascade_max_out_epochs(self, value = NO_INIT)
    struct fann * self;
    unsigned int value
  CODE:
    if (items > 1) {
        fann_set_cascade_max_out_epochs(self, value);
    }
    RETVAL = fann_get_cascade_max_out_epochs(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_cascade_max_cand_epochs(self, value = NO_INIT)
    struct fann * self;
    unsigned int value
  CODE:
    if (items > 1) {
        fann_set_cascade_max_cand_epochs(self, value);
    }
    RETVAL = fann_get_cascade_max_cand_epochs(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_cascade_num_candidates(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_cascade_num_candidates(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_cascade_num_candidate_groups(self, value = NO_INIT)
    struct fann * self;
    unsigned int value
  CODE:
    if (items > 1) {
        fann_set_cascade_num_candidate_groups(self, value);
    }
    RETVAL = fann_get_cascade_num_candidate_groups(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

enum fann_activationfunc_enum
accessor_neuron_activation_function(self, layer, neuron_index, value = NO_INIT)
    struct fann * self;
    unsigned int layer;
    unsigned int neuron_index;
    enum fann_activationfunc_enum value
  CODE:
    if (items > 3) {
        fann_set_activation_function(self, value, layer, neuron_index);
    }
    RETVAL = fann_get_activation_function(self, layer, neuron_index);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_layer_activation_function(self, layer, value)
    struct fann * self;
    unsigned int layer;
    enum fann_activationfunc_enum value;
  CODE:
    fann_set_activation_function_layer(self, value, layer);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_hidden_activation_function(self, value)
    struct fann * self;
    enum fann_activationfunc_enum value;
  CODE:
    fann_set_activation_function_hidden(self, value);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_output_activation_function(self, value)
    struct fann * self;
    enum fann_activationfunc_enum value;
  CODE:
    fann_set_activation_function_output(self, value);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

fann_type
accessor_neuron_activation_steepness(self, layer, neuron, value = NO_INIT)
    struct fann * self;
    unsigned int layer;
    unsigned int neuron;
    fann_type value
  CODE:
    if (items > 3) {
        fann_set_activation_steepness(self, value, layer, neuron);
    }
    RETVAL = fann_get_activation_steepness(self, layer, neuron);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_layer_activation_steepness(self, layer, value)
    struct fann * self;
    unsigned int layer;
    fann_type value;
  CODE:
    fann_set_activation_steepness_layer(self, value, layer);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_hidden_activation_steepness(self, value)
    struct fann * self;
    fann_type value;
  CODE:
    fann_set_activation_steepness_hidden(self, value);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_
void
accessor_output_activation_steepness(self, value)
    struct fann * self;
    fann_type value;
  CODE:
    fann_set_activation_steepness_output(self, value);
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_layer_num_neurons(self, layer)
	struct fann * self;
    unsigned int layer;
  CODE:
    RETVAL = fann_get_num_neurons(self, layer);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN    PREFIX = accessor_

unsigned int
accessor_num_layers(self)
	struct fann * self;
  CODE:
    RETVAL = fann_get_num_layers(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN::TrainData    PREFIX = accessor_

unsigned int
accessor_num_inputs(self)
	struct fann_train_data * self;
  CODE:
    RETVAL = fann_train_data_num_input(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN::TrainData    PREFIX = accessor_

unsigned int
accessor_num_outputs(self)
	struct fann_train_data * self;
  CODE:
    RETVAL = fann_train_data_num_output(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);


MODULE = AI::FANN    PACKAGE = AI::FANN::TrainData    PREFIX = accessor_

unsigned int
accessor_length(self)
	struct fann_train_data * self;
  CODE:
    RETVAL = fann_train_data_length(self);
  OUTPUT:
    RETVAL
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

constants.h  view on Meta::CPAN

static char * const my_constant_names[] = {
    "FANN_TRAIN_INCREMENTAL",
    "FANN_TRAIN_BATCH",
    "FANN_TRAIN_RPROP",
    "FANN_TRAIN_QUICKPROP",
    "FANN_LINEAR",
    "FANN_THRESHOLD",
    "FANN_THRESHOLD_SYMMETRIC",
    "FANN_SIGMOID",
    "FANN_SIGMOID_STEPWISE",
    "FANN_SIGMOID_SYMMETRIC",
    "FANN_SIGMOID_SYMMETRIC_STEPWISE",
    "FANN_GAUSSIAN",
    "FANN_GAUSSIAN_SYMMETRIC",
    "FANN_GAUSSIAN_STEPWISE",
    "FANN_ELLIOT",
    "FANN_ELLIOT_SYMMETRIC",
    "FANN_LINEAR_PIECE",
    "FANN_LINEAR_PIECE_SYMMETRIC",
    "FANN_SIN_SYMMETRIC",
    "FANN_COS_SYMMETRIC",
    "FANN_SIN",
    "FANN_COS",
    "FANN_ERRORFUNC_LINEAR",
    "FANN_ERRORFUNC_TANH",
    "FANN_STOPFUNC_MSE",
    "FANN_STOPFUNC_BIT",
    0,
};
static const unsigned int my_constant_values[] = {
    FANN_TRAIN_INCREMENTAL,
    FANN_TRAIN_BATCH,
    FANN_TRAIN_RPROP,
    FANN_TRAIN_QUICKPROP,
    FANN_LINEAR,
    FANN_THRESHOLD,
    FANN_THRESHOLD_SYMMETRIC,
    FANN_SIGMOID,
    FANN_SIGMOID_STEPWISE,
    FANN_SIGMOID_SYMMETRIC,
    FANN_SIGMOID_SYMMETRIC_STEPWISE,
    FANN_GAUSSIAN,
    FANN_GAUSSIAN_SYMMETRIC,
    FANN_GAUSSIAN_STEPWISE,
    FANN_ELLIOT,
    FANN_ELLIOT_SYMMETRIC,
    FANN_LINEAR_PIECE,
    FANN_LINEAR_PIECE_SYMMETRIC,
    FANN_SIN_SYMMETRIC,
    FANN_COS_SYMMETRIC,
    FANN_SIN,
    FANN_COS,
    FANN_ERRORFUNC_LINEAR,
    FANN_ERRORFUNC_TANH,
    FANN_STOPFUNC_MSE,
    FANN_STOPFUNC_BIT,
};

genaccessors  view on Meta::CPAN

#!/usr/bin/perl

use strict;
use warnings;

$| = 1;

my %struct = ( 'AI::FANN' => 'struct fann *',
               'AI::FANN::TrainData' => 'struct fann_train_data *' );

sub accessor {
    my ($name, $type, $getter, $setter, @ixs) = @_;
	
    my ($package, $method) = $name =~ /^(?:(.*)::)?(.*)$/
        or die "wrong accessor name $name";

    $package = $package ? "AI::FANN::$package" : 'AI::FANN';
    my $struct = $struct{$package}
        or die "wrong package name $package";

    push @ixs, 'value' unless grep /^value$/, @ixs;
    my @ixs1 =  grep !/^value$/, @ixs;

    my $nixs = @ixs;

    my $types = join("\n    ", "$struct self;", map "unsigned int $_;", @ixs1);
    my $args = join(', ', 'self', @ixs1);
    my $setargs = join(', ', 'self', @ixs);

    if ($getter) {
        if ($getter =~ /^->/) {
            $getter = "self->$getter"
        }
        else {
            $getter = "$getter($args)"
        }
    }

    if ($setter) {
        if ($setter =~ /^->/) {
            $setter = "self->$setter = value"
        }
        else {
            $setter = "$setter($setargs)"
        }
    }


    print <<HEAD;

MODULE = AI::FANN    PACKAGE = $package    PREFIX = accessor_
HEAD

    if ($setter and $getter) {
        print <<EOA

$type
accessor_$method($args, value = NO_INIT)
    $types
    $type value
  CODE:
    if (items > $nixs) {
        $setter;
    }
    RETVAL = $getter;
  OUTPUT:
    RETVAL
EOA

    }
    elsif ($getter) {
        print <<EOA;

$type
accessor_$method($args)
	$types
  CODE:
    RETVAL = $getter;
  OUTPUT:
    RETVAL
EOA

    }
    elsif ($setter) {
        print <<EOA;
void
accessor_$method($args, value)
    $types
    $type value;
  CODE:
    $setter;
EOA

    }
    else {
        die "both setter and getter are null"
    }

    print <<EOA;
  CLEANUP:
    _check_error(aTHX_ (struct fann_error *)self);

EOA
}


while(<DATA>) {
	chomp;
	next if /^\s*(?:#.*)?$/;
	my (@args) = split /\s*,\s*/;
	@args > 2 or die "wrong number of arguments: $_";

	accessor(@args);
}

__DATA__

training_algorithm, enum fann_train_enum, fann_get_training_algorithm, fann_set_training_algorithm
train_error_function, enum fann_errorfunc_enum, fann_get_train_error_function, fann_set_train_error_function
train_stop_function, enum fann_stopfunc_enum, fann_get_train_stop_function, fann_set_train_stop_function
learning_rate, double, fann_get_learning_rate, fann_set_learning_rate
learning_momentum, double, fann_get_learning_momentum, fann_set_learning_momentum
bit_fail_limit, fann_type, fann_get_bit_fail_limit, fann_set_bit_fail_limit

genconstants  view on Meta::CPAN

#!/usr/bin/perl

my @names;
while(<DATA>) {
	chomp;
	next if /^\s*(?:#.*)?$/;
	push @names, $_
}

my $n = @names;
my $n2 = $n*2;

print "static char * const my_constant_names[] = {\n";
for (@names) {
	print qq(    "$_",\n)
}
print qq(    0,\n);
print "};\n";
print "static const unsigned int my_constant_values[] = {\n";
for (@names) {
	print qq(    $_,\n)
}
print "};\n";

__DATA__

# enum fann_train_enum:
FANN_TRAIN_INCREMENTAL
FANN_TRAIN_BATCH
FANN_TRAIN_RPROP
FANN_TRAIN_QUICKPROP

lib/AI/FANN.pm  view on Meta::CPAN

use strict;
use warnings;
use Carp;

require XSLoader;
XSLoader::load('AI::FANN', $VERSION);

use Exporter qw(import);

{
    my @constants = _constants();

    our %EXPORT_TAGS = ( 'all' => [ @constants ] );
    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

    require constant;
    for my $constant (@constants) {
        constant->import($constant, $constant);
    }
}

sub num_neurons {

    @_ == 1 or croak "Usage: AI::FANN::get_neurons(self)";

    my $self = shift;
    if (wantarray) {
        map { $self->layer_num_neurons($_) } (0 .. $self->num_layers - 1);
    }
    else {
        $self->total_neurons;
    }
}

1;
__END__

=head1 NAME

AI::FANN - Perl wrapper for the Fast Artificial Neural Network library

=head1 SYNOPSIS

Train...

  use AI::FANN qw(:all);

  # create an ANN with 2 inputs, a hidden layer with 3 neurons and an
  # output layer with 1 neuron:
  my $ann = AI::FANN->new_standard(2, 3, 1);

  $ann->hidden_activation_function(FANN_SIGMOID_SYMMETRIC);
  $ann->output_activation_function(FANN_SIGMOID_SYMMETRIC);

  # create the training data for a XOR operator:
  my $xor_train = AI::FANN::TrainData->new( [-1, -1], [-1],
                                            [-1, 1], [1],
                                            [1, -1], [1],
                                            [1, 1], [-1] );

  $ann->train_on_data($xor_train, 500000, 1000, 0.001);

  $ann->save("xor.ann");

Run...

  use AI::FANN;

  my $ann = AI::FANN->new_from_file("xor.ann");

  for my $a (-1, 1) {
    for my $b (-1, 1) {
      my $out = $ann->run([$a, $b]);
      printf "xor(%f, %f) = %f\n", $a, $b, $out->[0];
    }
  }

=head1 DESCRIPTION


  WARNING:  THIS IS A VERY EARLY RELEASE,
            MAY CONTAIN CRITICAL BUGS!!!

AI::FANN is a Perl wrapper for the Fast Artificial Neural Network
(FANN) Library available from L<http://fann.sourceforge.net>:

  Fast Artificial Neural Network Library is a free open source neural
  network library, which implements multilayer artificial neural
  networks in C with support for both fully connected and sparsely
  connected networks. Cross-platform execution in both fixed and
  floating point are supported. It includes a framework for easy
  handling of training data sets. It is easy to use, versatile, well
  documented, and fast. PHP, C++, .NET, Python, Delphi, Octave, Ruby,
  Pure Data and Mathematica bindings are available. A reference manual
  accompanies the library with examples and recommendations on how to
  use the library. A graphical user interface is also available for
  the library.

AI::FANN object oriented interface provides an almost direct map to
the C library API. Some differences have been introduced to make it
more perlish:

=over 4

=item *

Two classes are used: C<AI::FANN> that wraps the C C<struct fann> type
and C<AI::FANN::TrainData> that wraps C<struct fann_train_data>.

=item *

Prefixes and common parts on the C function names referring to those
structures have been removed. For instance C
C<fann_train_data_shuffle> becomes C<AI::FANN::TrainData::shuffle> that
will be usually called as...

  $train_data->shuffle;

=item *

Pairs of C get/set functions are wrapped in Perl with dual accessor
methods named as the attribute (and without any C<set_>/C<get_>
prefix). For instance:

  $ann->bit_fail_limit($limit); # sets the bit_fail_limit

  $bfl = $ann->bit_fail_limit;  # gets the bit_fail_limit


Pairs of get/set functions requiring additional indexing arguments are
also wrapped inside dual accessors:

  # sets:
  $ann->neuron_activation_function($layer_ix, $neuron_ix, $actfunc);

  # gets:
  $af = $ann->neuron_activation_function($layer_ix, $neuron_ix);

Important: note that on the Perl version, the optional value argument
is moved to the last position (on the C version of the C<set_> method
it is usually the second argument).

=item *

Some functions have been renamed to make the naming more consistent
and to follow Perl conventions:

  C                                      Perl
  -----------------------------------------------------------
  fann_create_from_file               => new_from_file
  fann_create_standard                => new_standard
  fann_get_num_input                  => num_inputs
  fann_get_activation_function        => neuron_activation_function
  fann_set_activation_function        => ^^^
  fann_set_activation_function_layer  => layer_activation_function
  fann_set_activation_function_hidden => hidden_activation_function
  fann_set_activation_function_output => output_activation_function

=item *

Boolean methods return true on success and undef on failure.

=item *

Any error reported from the C side is automaticaly converter to a Perl
exception. No manual error checking is required after calling FANN
functions.

lib/AI/FANN.pm  view on Meta::CPAN


Doubles are used for computations (using floats or fixed
point types is not supported).

=back

=head1 CONSTANTS

All the constants defined in the C documentation are exported from the module:

  # import all...
  use AI::FANN ':all';

  # or individual constants...
  use AI::FANN qw(FANN_TRAIN_INCREMENTAL FANN_GAUSSIAN);

The values returned from this constant subs yield the integer value on
numerical context and the constant name when used as strings.

The constants available are:

  # enum fann_train_enum:
  FANN_TRAIN_INCREMENTAL
  FANN_TRAIN_BATCH
  FANN_TRAIN_RPROP
  FANN_TRAIN_QUICKPROP

  # enum fann_activationfunc_enum:
  FANN_LINEAR
  FANN_THRESHOLD
  FANN_THRESHOLD_SYMMETRIC
  FANN_SIGMOID
  FANN_SIGMOID_STEPWISE
  FANN_SIGMOID_SYMMETRIC
  FANN_SIGMOID_SYMMETRIC_STEPWISE
  FANN_GAUSSIAN
  FANN_GAUSSIAN_SYMMETRIC
  FANN_GAUSSIAN_STEPWISE
  FANN_ELLIOT
  FANN_ELLIOT_SYMMETRIC
  FANN_LINEAR_PIECE
  FANN_LINEAR_PIECE_SYMMETRIC
  FANN_SIN_SYMMETRIC
  FANN_COS_SYMMETRIC
  FANN_SIN
  FANN_COS

  # enum fann_errorfunc_enum:
  FANN_ERRORFUNC_LINEAR
  FANN_ERRORFUNC_TANH

  # enum fann_stopfunc_enum:
  FANN_STOPFUNC_MSE
  FANN_STOPFUNC_BIT

=head1 CLASSES

The classes defined by this package are:

=head2 AI::FANN

Wraps C C<struct fann> types and provides the following methods
(consult the C documentation for a full description of their usage):

lib/AI/FANN.pm  view on Meta::CPAN

=item $ann->save($filename)

-

=item $ann->run($input)

C<input> is an array with the input values.

returns an array with the values on the output layer.

  $out = $ann->run([1, 0.6]);
  print "@$out\n";

=item $ann->randomize_weights($min_weight, $max_weight)

=item $ann->train($input, $desired_output)

C<$input> and C<$desired_output> are arrays.

=item $ann->test($input, $desired_output)

C<$input> and C<$desired_output> are arrays.

morefann.c  view on Meta::CPAN


#include "morefann.h"
#include <string.h>

static fann_type **allocvv(unsigned int n1, unsigned int n2) {
	fann_type **ptr = (fann_type **)malloc(n1 * sizeof(fann_type *));
	fann_type *v = (fann_type *)malloc(n1 * n2 * sizeof(fann_type));
	if (ptr && v) {
		unsigned int i;
		for (i = 0; i < n1; i++) {
			ptr[i] = v + i * n2;
		}
		return ptr;
	}
	return 0;
}

struct fann_train_data *
fann_train_data_create(unsigned int num_data, unsigned int num_input, unsigned int num_output) {
	struct fann_train_data *data = (struct fann_train_data *)calloc(1, sizeof(*data));
	if (data) {
		fann_init_error_data((struct fann_error *)data);
		data->input = allocvv(num_data, num_input);
		data->output = allocvv(num_data, num_output);
		if (data->input && data->output) {
			data->num_data = num_data;
			data->num_input = num_input;
			data->num_output = num_output;
			return data;
		}
	}
	return 0;
}

void
fann_train_data_set(struct fann_train_data *data, unsigned int ix,
					fann_type *input, fann_type *output ) {
	if (ix < data->num_data) {
		memcpy(data->input[ix], input, data->num_input * sizeof(fann_type));
		memcpy(data->output[ix], output, data->num_output * sizeof(fann_type));
	}
	else {
		fann_error((struct fann_error *)data, FANN_E_INDEX_OUT_OF_BOUND, ix);
	}
}

/*
enum fann_activationfunc_enum
fann_get_activation_function(struct fann *ann, unsigned int layer, int neuron_index) {
    struct fann_neuron *neuron = fann_get_neuron(ann, layer, neuron_index);
    if (neuron) {
        return neuron->activation_function;
    }
    return 0;
}
*/

/*
fann_type
fann_get_activation_steepness(struct fann *ann, unsigned int layer, int neuron_index) {
    struct fann_neuron *neuron = fann_get_neuron(ann, layer, neuron_index);
    if (neuron) {
        return neuron->activation_steepness;
    }
    return 0;
}
*/

/*
unsigned int
fann_get_num_layers(struct fann *ann) {
    return ann->last_layer - ann->first_layer;
}
*/

unsigned int
fann_get_num_neurons(struct fann *ann, unsigned int layer_index) {
    struct fann_layer * layer = fann_get_layer(ann, layer_index);
    if (layer) {
        return layer->last_neuron - layer->first_neuron;
    }
    return 0;
}

morefann.h  view on Meta::CPAN


#include <doublefann.h>

void
fann_train_data_set(struct fann_train_data *data, unsigned int ix,
					fann_type *input, fann_type *output );

struct fann_train_data *
fann_train_data_create(unsigned int num_data,
					   unsigned int num_input, unsigned int num_output);


struct fann_layer*
fann_get_layer(struct fann *ann, int layer);

struct fann_neuron*
fann_get_neuron_layer(struct fann *ann, struct fann_layer* layer, int neuron);

struct fann_neuron*
fann_get_neuron(struct fann *ann, unsigned int layer, int neuron);

ppport.h  view on Meta::CPAN

#if 0
<<'SKIP';
#endif
/*
----------------------------------------------------------------------

    ppport.h -- Perl/Pollution/Portability Version 3.13

    Automatically created by Devel::PPPort running under perl 5.010000.

    Do NOT edit this file directly! -- Edit PPPort_pm.PL and the
    includes in parts/inc/ instead.

    Use 'perldoc ppport.h' to view the documentation below.

----------------------------------------------------------------------

SKIP

=pod

=head1 NAME

ppport.h - Perl/Pollution/Portability version 3.13

=head1 SYNOPSIS

  perl ppport.h [options] [source files]

  Searches current directory for files if no [source files] are given

  --help                      show short help

  --version                   show version

  --patch=file                write one patch file with changes
  --copy=suffix               write changed copies with suffix
  --diff=program              use diff program and options

  --compat-version=version    provide compatibility with Perl version
  --cplusplus                 accept C++ comments

  --quiet                     don't output anything except fatal errors
  --nodiag                    don't show diagnostics
  --nohints                   don't show hints
  --nochanges                 don't suggest changes
  --nofilter                  don't filter input files

  --strip                     strip all script and doc functionality from
                              ppport.h

  --list-provided             list provided API
  --list-unsupported          list unsupported API
  --api-info=name             show Perl API portability information

=head1 COMPATIBILITY

This version of F<ppport.h> is designed to support operation with Perl
installations back to 5.003, and has been tested up to 5.10.0.

=head1 OPTIONS

=head2 --help

ppport.h  view on Meta::CPAN

across differing versions of Perl itself, certain steps need to be taken.

=over 4

=item *

Including this header is the first major one. This alone will give you
access to a large part of the Perl API that hasn't been available in
earlier Perl releases. Use

    perl ppport.h --list-provided

to see which API elements are provided by ppport.h.

=item *

You should avoid using deprecated parts of the API. For example, using
global Perl variables without the C<PL_> prefix is deprecated. Also,
some API functions used to have a C<perl_> prefix. Using this form is
also deprecated. You can safely use the supported API, as F<ppport.h>
will provide wrappers for older Perl versions.

ppport.h  view on Meta::CPAN

These functions or variables will be marked C<explicit> in the list shown
by C<--list-provided>.

Depending on whether you module has a single or multiple files that
use such functions or variables, you want either C<static> or global
variants.

For a C<static> function or variable (used only in a single source
file), use:

    #define NEED_function
    #define NEED_variable

For a global function or variable (used in multiple source files),
use:

    #define NEED_function_GLOBAL
    #define NEED_variable_GLOBAL

Note that you mustn't have more than one global request for the
same function or variable in your project.

    Function / Variable       Static Request               Global Request
    -----------------------------------------------------------------------------------------
    PL_signals                NEED_PL_signals              NEED_PL_signals_GLOBAL
    eval_pv()                 NEED_eval_pv                 NEED_eval_pv_GLOBAL
    grok_bin()                NEED_grok_bin                NEED_grok_bin_GLOBAL
    grok_hex()                NEED_grok_hex                NEED_grok_hex_GLOBAL
    grok_number()             NEED_grok_number             NEED_grok_number_GLOBAL
    grok_numeric_radix()      NEED_grok_numeric_radix      NEED_grok_numeric_radix_GLOBAL
    grok_oct()                NEED_grok_oct                NEED_grok_oct_GLOBAL
    load_module()             NEED_load_module             NEED_load_module_GLOBAL
    my_snprintf()             NEED_my_snprintf             NEED_my_snprintf_GLOBAL
    my_strlcat()              NEED_my_strlcat              NEED_my_strlcat_GLOBAL
    my_strlcpy()              NEED_my_strlcpy              NEED_my_strlcpy_GLOBAL
    newCONSTSUB()             NEED_newCONSTSUB             NEED_newCONSTSUB_GLOBAL
    newRV_noinc()             NEED_newRV_noinc             NEED_newRV_noinc_GLOBAL
    newSVpvn_share()          NEED_newSVpvn_share          NEED_newSVpvn_share_GLOBAL
    sv_2pv_flags()            NEED_sv_2pv_flags            NEED_sv_2pv_flags_GLOBAL
    sv_2pvbyte()              NEED_sv_2pvbyte              NEED_sv_2pvbyte_GLOBAL
    sv_catpvf_mg()            NEED_sv_catpvf_mg            NEED_sv_catpvf_mg_GLOBAL
    sv_catpvf_mg_nocontext()  NEED_sv_catpvf_mg_nocontext  NEED_sv_catpvf_mg_nocontext_GLOBAL
    sv_pvn_force_flags()      NEED_sv_pvn_force_flags      NEED_sv_pvn_force_flags_GLOBAL
    sv_setpvf_mg()            NEED_sv_setpvf_mg            NEED_sv_setpvf_mg_GLOBAL
    sv_setpvf_mg_nocontext()  NEED_sv_setpvf_mg_nocontext  NEED_sv_setpvf_mg_nocontext_GLOBAL
    vload_module()            NEED_vload_module            NEED_vload_module_GLOBAL
    vnewSVpvf()               NEED_vnewSVpvf               NEED_vnewSVpvf_GLOBAL
    warner()                  NEED_warner                  NEED_warner_GLOBAL

To avoid namespace conflicts, you can change the namespace of the
explicitly exported functions / variables using the C<DPPP_NAMESPACE>
macro. Just C<#define> the macro before including C<ppport.h>:

    #define DPPP_NAMESPACE MyOwnNamespace_
    #include "ppport.h"

The default namespace is C<DPPP_>.

=back

The good thing is that most of the above can be checked by running
F<ppport.h> on your source code. See the next section for
details.

=head1 EXAMPLES

To verify whether F<ppport.h> is needed for your module, whether you
should make any changes to your code, and whether any special defines
should be used, F<ppport.h> can be run as a Perl script to check your
source code. Simply say:

    perl ppport.h

The result will usually be a list of patches suggesting changes
that should at least be acceptable, if not necessarily the most
efficient solution, or a fix for all possible problems.

If you know that your XS module uses features only available in
newer Perl releases, if you're aware that it uses C++ comments,
and if you want all suggestions as a single patch file, you could
use something like this:

    perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff

If you only want your code to be scanned without any suggestions
for changes, use:

    perl ppport.h --nochanges

You can specify a different C<diff> program or options, using
the C<--diff> option:

    perl ppport.h --diff='diff -C 10'

This would output context diffs with 10 lines of context.

If you want to create patched copies of your files instead, use:

    perl ppport.h --copy=.new

To display portability information for the C<newSVpvn> function,
use:

    perl ppport.h --api-info=newSVpvn

Since the argument to C<--api-info> can be a regular expression,
you can use

    perl ppport.h --api-info=/_nomg$/

to display portability information for all C<_nomg> functions or

    perl ppport.h --api-info=/./

to display information for all known API elements.

=head1 BUGS

If this version of F<ppport.h> is causing failure during
the compilation of this module, please check if newer versions
of either this module or C<Devel::PPPort> are available on CPAN
before sending a bug report.

ppport.h  view on Meta::CPAN

=cut

use strict;

# Disable broken TRIE-optimization
BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 }

my $VERSION = 3.13;

my %opt = (
  quiet     => 0,
  diag      => 1,
  hints     => 1,
  changes   => 1,
  cplusplus => 0,
  filter    => 1,
  strip     => 0,
  version   => 0,
);

my($ppport) = $0 =~ /([\w.]+)$/;
my $LF = '(?:\r\n|[\r\n])';   # line feed
my $HS = "[ \t]";             # horizontal whitespace

# Never use C comments in this file!
my $ccs  = '/'.'*';
my $cce  = '*'.'/';
my $rccs = quotemeta $ccs;
my $rcce = quotemeta $cce;

eval {
  require Getopt::Long;
  Getopt::Long::GetOptions(\%opt, qw(
    help quiet diag! filter! hints! changes! cplusplus strip version
    patch=s copy=s diff=s compat-version=s
    list-provided list-unsupported api-info=s
  )) or usage();
};

if ($@ and grep /^-/, @ARGV) {
  usage() if "@ARGV" =~ /^--?h(?:elp)?$/;
  die "Getopt::Long not found. Please don't use any options.\n";
}

if ($opt{version}) {
  print "This is $0 $VERSION.\n";
  exit 0;
}

usage() if $opt{help};
strip() if $opt{strip};

if (exists $opt{'compat-version'}) {
  my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) };
  if ($@) {
    die "Invalid version number format: '$opt{'compat-version'}'\n";
  }
  die "Only Perl 5 is supported\n" if $r != 5;
  die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000;
  $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s;
}
else {
  $opt{'compat-version'} = 5;
}

my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/
                ? ( $1 => {
                      ($2                  ? ( base     => $2 ) : ()),
                      ($3                  ? ( todo     => $3 ) : ()),
                      (index($4, 'v') >= 0 ? ( varargs  => 1  ) : ()),
                      (index($4, 'p') >= 0 ? ( provided => 1  ) : ()),
                      (index($4, 'n') >= 0 ? ( nothxarg => 1  ) : ()),
                    } )
                : die "invalid spec: $_" } qw(
AvFILLp|5.004050||p
AvFILL|||
CLASS|||n
CX_CURPAD_SAVE|||
CX_CURPAD_SV|||
CopFILEAV|5.006000||p
CopFILEGV_set|5.006000||p
CopFILEGV|5.006000||p
CopFILESV|5.006000||p
CopFILE_set|5.006000||p

ppport.h  view on Meta::CPAN

xmldump_packsubs|||
xmldump_sub|||
xmldump_vindent|||
yyerror|||
yylex|||
yyparse|||
yywarn|||
);

if (exists $opt{'list-unsupported'}) {
  my $f;
  for $f (sort { lc $a cmp lc $b } keys %API) {
    next unless $API{$f}{todo};
    print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n";
  }
  exit 0;
}

# Scan for possible replacement candidates

my(%replace, %need, %hints, %warnings, %depends);
my $replace = 0;
my($hint, $define, $function);

sub find_api
{
  my $code = shift;
  $code =~ s{
    / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
  | "[^"\\]*(?:\\.[^"\\]*)*"
  | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx;
  grep { exists $API{$_} } $code =~ /(\w+)/mg;
}

while (<DATA>) {
  if ($hint) {
    my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings;
    if (m{^\s*\*\s(.*?)\s*$}) {
      for (@{$hint->[1]}) {
        $h->{$_} ||= '';  # suppress warning with older perls
        $h->{$_} .= "$1\n";
      }
    }
    else { undef $hint }
  }

  $hint = [$1, [split /,?\s+/, $2]]
      if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$};

  if ($define) {
    if ($define->[1] =~ /\\$/) {
      $define->[1] .= $_;
    }
    else {
      if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) {
        my @n = find_api($define->[1]);
        push @{$depends{$define->[0]}}, @n if @n
      }
      undef $define;
    }
  }

  $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)};

  if ($function) {
    if (/^}/) {
      if (exists $API{$function->[0]}) {
        my @n = find_api($function->[1]);
        push @{$depends{$function->[0]}}, @n if @n
      }
      undef $define;
    }
    else {
      $function->[1] .= $_;
    }
  }

  $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)};

  $replace     = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$};
  $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)};
  $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce};
  $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$};

  if (m{^\s*$rccs\s+(\w+)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) {
    push @{$depends{$1}}, map { s/\s+//g; $_ } split /,/, $2;
  }

  $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)};
}

for (values %depends) {
  my %s;
  $_ = [sort grep !$s{$_}++, @$_];
}

if (exists $opt{'api-info'}) {
  my $f;
  my $count = 0;
  my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$";
  for $f (sort { lc $a cmp lc $b } keys %API) {
    next unless $f =~ /$match/;
    print "\n=== $f ===\n\n";
    my $info = 0;
    if ($API{$f}{base} || $API{$f}{todo}) {
      my $base = format_version($API{$f}{base} || $API{$f}{todo});
      print "Supported at least starting from perl-$base.\n";
      $info++;
    }
    if ($API{$f}{provided}) {
      my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003";
      print "Support by $ppport provided back to perl-$todo.\n";
      print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f};
      print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f};
      print "\n$hints{$f}" if exists $hints{$f};
      print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f};
      $info++;
    }
    print "No portability information available.\n" unless $info;
    $count++;
  }
  $count or print "Found no API matching '$opt{'api-info'}'.";
  print "\n";
  exit 0;
}

if (exists $opt{'list-provided'}) {
  my $f;
  for $f (sort { lc $a cmp lc $b } keys %API) {
    next unless $API{$f}{provided};
    my @flags;
    push @flags, 'explicit' if exists $need{$f};
    push @flags, 'depend'   if exists $depends{$f};
    push @flags, 'hint'     if exists $hints{$f};
    push @flags, 'warning'  if exists $warnings{$f};
    my $flags = @flags ? '  ['.join(', ', @flags).']' : '';
    print "$f$flags\n";
  }
  exit 0;
}

my @files;
my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc );
my $srcext = join '|', map { quotemeta $_ } @srcext;

if (@ARGV) {
  my %seen;
  for (@ARGV) {
    if (-e) {
      if (-f) {
        push @files, $_ unless $seen{$_}++;
      }
      else { warn "'$_' is not a file.\n" }
    }
    else {
      my @new = grep { -f } glob $_
          or warn "'$_' does not exist.\n";
      push @files, grep { !$seen{$_}++ } @new;
    }
  }
}
else {
  eval {
    require File::Find;
    File::Find::find(sub {
      $File::Find::name =~ /($srcext)$/i
          and push @files, $File::Find::name;
    }, '.');
  };
  if ($@) {
    @files = map { glob "*$_" } @srcext;
  }
}

if (!@ARGV || $opt{filter}) {
  my(@in, @out);
  my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files;
  for (@files) {
    my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i;
    push @{ $out ? \@out : \@in }, $_;
  }
  if (@ARGV && @out) {
    warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out);
  }
  @files = @in;
}

die "No input files given!\n" unless @files;

my(%files, %global, %revreplace);
%revreplace = reverse %replace;
my $filename;
my $patch_opened = 0;

for $filename (@files) {
  unless (open IN, "<$filename") {
    warn "Unable to read from $filename: $!\n";
    next;
  }

  info("Scanning $filename ...");

  my $c = do { local $/; <IN> };
  close IN;

  my %file = (orig => $c, changes => 0);

  # Temporarily remove C/XS comments and strings from the code
  my @ccom;

  $c =~ s{
    ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]*
    | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* )
  | ( ^$HS*\#[^\r\n]*
    | "[^"\\]*(?:\\.[^"\\]*)*"
    | '[^'\\]*(?:\\.[^'\\]*)*'
    | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) )
  }{ defined $2 and push @ccom, $2;
     defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex;

  $file{ccom} = \@ccom;
  $file{code} = $c;
  $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m;

  my $func;

  for $func (keys %API) {
    my $match = $func;
    $match .= "|$revreplace{$func}" if exists $revreplace{$func};
    if ($c =~ /\b(?:Perl_)?($match)\b/) {
      $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func};
      $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/;
      if (exists $API{$func}{provided}) {
        $file{uses_provided}{$func}++;
        if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) {
          $file{uses}{$func}++;
          my @deps = rec_depend($func);
          if (@deps) {
            $file{uses_deps}{$func} = \@deps;
            for (@deps) {
              $file{uses}{$_} = 0 unless exists $file{uses}{$_};
            }
          }
          for ($func, @deps) {
            $file{needs}{$_} = 'static' if exists $need{$_};
          }
        }
      }
      if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) {
        if ($c =~ /\b$func\b/) {
          $file{uses_todo}{$func}++;
        }
      }
    }
  }

  while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) {
    if (exists $need{$2}) {
      $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++;
    }
    else { warning("Possibly wrong #define $1 in $filename") }
  }

  for (qw(uses needs uses_todo needed_global needed_static)) {
    for $func (keys %{$file{$_}}) {
      push @{$global{$_}{$func}}, $filename;
    }
  }

  $files{$filename} = \%file;
}

# Globally resolve NEED_'s
my $need;
for $need (keys %{$global{needs}}) {
  if (@{$global{needs}{$need}} > 1) {
    my @targets = @{$global{needs}{$need}};
    my @t = grep $files{$_}{needed_global}{$need}, @targets;
    @targets = @t if @t;
    @t = grep /\.xs$/i, @targets;
    @targets = @t if @t;
    my $target = shift @targets;
    $files{$target}{needs}{$need} = 'global';
    for (@{$global{needs}{$need}}) {
      $files{$_}{needs}{$need} = 'extern' if $_ ne $target;
    }
  }
}

for $filename (@files) {
  exists $files{$filename} or next;

  info("=== Analyzing $filename ===");

  my %file = %{$files{$filename}};
  my $func;
  my $c = $file{code};
  my $warnings = 0;

  for $func (sort keys %{$file{uses_Perl}}) {
    if ($API{$func}{varargs}) {
      unless ($API{$func}{nothxarg}) {
        my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))}
                              { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge);
        if ($changes) {
          warning("Doesn't pass interpreter argument aTHX to Perl_$func");
          $file{changes} += $changes;
        }
      }
    }
    else {
      warning("Uses Perl_$func instead of $func");
      $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*}
                                {$func$1(}g);
    }
  }

  for $func (sort keys %{$file{uses_replace}}) {
    warning("Uses $func instead of $replace{$func}");
    $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g);
  }

  for $func (sort keys %{$file{uses_provided}}) {
    if ($file{uses}{$func}) {
      if (exists $file{uses_deps}{$func}) {
        diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}}));
      }
      else {
        diag("Uses $func");
      }
    }
    $warnings += hint($func);
  }

  unless ($opt{quiet}) {
    for $func (sort keys %{$file{uses_todo}}) {
      print "*** WARNING: Uses $func, which may not be portable below perl ",
            format_version($API{$func}{todo}), ", even with '$ppport'\n";
      $warnings++;
    }
  }

  for $func (sort keys %{$file{needed_static}}) {
    my $message = '';
    if (not exists $file{uses}{$func}) {
      $message = "No need to define NEED_$func if $func is never used";
    }
    elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') {
      $message = "No need to define NEED_$func when already needed globally";
    }
    if ($message) {
      diag($message);
      $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg);
    }
  }

  for $func (sort keys %{$file{needed_global}}) {
    my $message = '';
    if (not exists $global{uses}{$func}) {
      $message = "No need to define NEED_${func}_GLOBAL if $func is never used";
    }
    elsif (exists $file{needs}{$func}) {
      if ($file{needs}{$func} eq 'extern') {
        $message = "No need to define NEED_${func}_GLOBAL when already needed globally";
      }
      elsif ($file{needs}{$func} eq 'static') {
        $message = "No need to define NEED_${func}_GLOBAL when only used in this file";
      }
    }
    if ($message) {
      diag($message);
      $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)) {
      $pp = '';
      $file{changes}++;
    }

    unless ($file{has_inc_ppport}) {
      diag("Needs to include '$ppport'");
      $pp .= qq(#include "$ppport"\n)
    }

    if ($pp) {
      $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms)
                     || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m)
                     || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m)
                     || ($c =~ s/^/$pp/);
    }
  }
  else {
    if ($file{has_inc_ppport}) {
      diag("No need to include '$ppport'");
      $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m);
    }
  }

  # put back in our C comments
  my $ix;
  my $cppc = 0;
  my @ccom = @{$file{ccom}};
  for $ix (0 .. $#ccom) {
    if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) {
      $cppc++;
      $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/;
    }
    else {
      $c =~ s/$rccs$ix$rcce/$ccom[$ix]/;
    }
  }

  if ($cppc) {
    my $s = $cppc != 1 ? 's' : '';
    warning("Uses $cppc C++ style comment$s, which is not portable");
  }

  my $s = $warnings != 1 ? 's' : '';
  my $warn = $warnings ? " ($warnings warning$s)" : '';
  info("Analysis completed$warn");

  if ($file{changes}) {
    if (exists $opt{copy}) {
      my $newfile = "$filename$opt{copy}";
      if (-e $newfile) {
        error("'$newfile' already exists, refusing to write copy of '$filename'");
      }
      else {
        local *F;
        if (open F, ">$newfile") {
          info("Writing copy of '$filename' with changes to '$newfile'");
          print F $c;
          close F;
        }
        else {
          error("Cannot open '$newfile' for writing: $!");
        }
      }
    }
    elsif (exists $opt{patch} || $opt{changes}) {
      if (exists $opt{patch}) {
        unless ($patch_opened) {
          if (open PATCH, ">$opt{patch}") {
            $patch_opened = 1;
          }
          else {
            error("Cannot open '$opt{patch}' for writing: $!");
            delete $opt{patch};
            $opt{changes} = 1;
            goto fallback;
          }
        }
        mydiff(\*PATCH, $filename, $c);
      }
      else {
fallback:
        info("Suggested changes:");
        mydiff(\*STDOUT, $filename, $c);
      }
    }
    else {
      my $s = $file{changes} == 1 ? '' : 's';
      info("$file{changes} potentially required change$s detected");
    }
  }
  else {
    info("Looks good");
  }
}

close PATCH if $patch_opened;

exit 0;


sub try_use { eval "use @_;"; return $@ eq '' }

sub mydiff
{
  local *F = shift;
  my($file, $str) = @_;
  my $diff;

  if (exists $opt{diff}) {
    $diff = run_diff($opt{diff}, $file, $str);
  }

  if (!defined $diff and try_use('Text::Diff')) {
    $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' });
    $diff = <<HEADER . $diff;
--- $file
+++ $file.patched
HEADER
  }

  if (!defined $diff) {
    $diff = run_diff('diff -u', $file, $str);
  }

  if (!defined $diff) {
    $diff = run_diff('diff', $file, $str);
  }

  if (!defined $diff) {
    error("Cannot generate a diff. Please install Text::Diff or use --copy.");
    return;
  }

  print F $diff;
}

sub run_diff
{
  my($prog, $file, $str) = @_;
  my $tmp = 'dppptemp';
  my $suf = 'aaa';
  my $diff = '';
  local *F;

  while (-e "$tmp.$suf") { $suf++ }
  $tmp = "$tmp.$suf";

  if (open F, ">$tmp") {
    print F $str;
    close F;

    if (open F, "$prog $file $tmp |") {
      while (<F>) {
        s/\Q$tmp\E/$file.patched/;
        $diff .= $_;
      }
      close F;
      unlink $tmp;
      return $diff;
    }

    unlink $tmp;
  }
  else {
    error("Cannot open '$tmp' for writing: $!");
  }

  return undef;
}

sub rec_depend
{
  my($func, $seen) = @_;
  return () unless exists $depends{$func};
  $seen = {%{$seen||{}}};
  return () if $seen->{$func}++;
  my %s;
  grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}};
}

sub parse_version
{
  my $ver = shift;

  if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) {
    return ($1, $2, $3);
  }
  elsif ($ver !~ /^\d+\.[\d_]+$/) {
    die "cannot parse version '$ver'\n";
  }

  $ver =~ s/_//g;
  $ver =~ s/$/000000/;

  my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;

  $v = int $v;
  $s = int $s;

  if ($r < 5 || ($r == 5 && $v < 6)) {
    if ($s % 10) {
      die "cannot parse version '$ver'\n";
    }
  }

  return ($r, $v, $s);
}

sub format_version
{
  my $ver = shift;

  $ver =~ s/$/000000/;
  my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;

  $v = int $v;
  $s = int $s;

  if ($r < 5 || ($r == 5 && $v < 6)) {
    if ($s % 10) {
      die "invalid version '$ver'\n";
    }
    $s /= 10;

    $ver = sprintf "%d.%03d", $r, $v;
    $s > 0 and $ver .= sprintf "_%02d", $s;

    return $ver;
  }

  return sprintf "%d.%d.%d", $r, $v, $s;
}

sub info
{
  $opt{quiet} and return;
  print @_, "\n";
}

sub diag
{
  $opt{quiet} and return;
  $opt{diag} and print @_, "\n";
}

sub warning
{
  $opt{quiet} and return;
  print "*** ", @_, "\n";
}

sub error
{
  print "*** ERROR: ", @_, "\n";
}

my %given_hints;
my %given_warnings;
sub hint
{
  $opt{quiet} and return;
  my $func = shift;
  my $rv = 0;
  if (exists $warnings{$func} && !$given_warnings{$func}++) {
    my $warn = $warnings{$func};
    $warn =~ s!^!*** !mg;
    print "*** WARNING: $func\n", $warn;
    $rv++;
  }
  if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) {
    my $hint = $hints{$func};
    $hint =~ s/^/   /mg;
    print "   --- hint for $func ---\n", $hint;
  }
  $rv;
}

sub usage
{
  my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms;
  my %M = ( 'I' => '*' );
  $usage =~ s/^\s*perl\s+\S+/$^X $0/;
  $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g;

  print <<ENDUSAGE;

Usage: $usage

See perldoc $0 for details.

ENDUSAGE

  exit 2;
}

sub strip
{
  my $self = do { local(@ARGV,$/)=($0); <> };
  my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms;
  $copy =~ s/^(?=\S+)/    /gms;
  $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms;
  $self =~ s/^SKIP.*(?=^__DATA__)/SKIP
if (\@ARGV && \$ARGV[0] eq '--unstrip') {
  eval { require Devel::PPPort };
  \$@ and die "Cannot require Devel::PPPort, please install.\\n";
  if (\$Devel::PPPort::VERSION < $VERSION) {
    die "$0 was originally generated with Devel::PPPort $VERSION.\\n"
      . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n"
      . "Please install a newer version, or --unstrip will not work.\\n";
  }
  Devel::PPPort::WriteFile(\$0);
  exit 0;
}
print <<END;

Sorry, but this is a stripped version of \$0.

To be able to use its original script and doc functionality,
please try to regenerate this file using:

  \$^X \$0 --unstrip

END
/ms;
  my($pl, $c) = $self =~ /(.*^__DATA__)(.*)/ms;
  $c =~ s{
    / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
  | ( "[^"\\]*(?:\\.[^"\\]*)*"
    | '[^'\\]*(?:\\.[^'\\]*)*' )
  | ($HS+) }{ defined $2 ? ' ' : ($1 || '') }gsex;
  $c =~ s!\s+$!!mg;
  $c =~ s!^$LF!!mg;
  $c =~ s!^\s*#\s*!#!mg;
  $c =~ s!^\s+!!mg;

  open OUT, ">$0" or die "cannot strip $0: $!\n";
  print OUT "$pl$c\n";

  exit 0;
}

__DATA__
*/

#ifndef _P_P_PORTABILITY_H_
#define _P_P_PORTABILITY_H_

#ifndef DPPP_NAMESPACE
#  define DPPP_NAMESPACE DPPP_

ppport.h  view on Meta::CPAN

#ifndef PERL_REVISION
#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
#    define PERL_PATCHLEVEL_H_IMPLICIT
#    include <patchlevel.h>
#  endif
#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
#    include <could_not_find_Perl_patchlevel.h>
#  endif
#  ifndef PERL_REVISION
#    define PERL_REVISION       (5)
     /* Replace: 1 */
#    define PERL_VERSION        PATCHLEVEL
#    define PERL_SUBVERSION     SUBVERSION
     /* Replace PERL_PATCHLEVEL with PERL_VERSION */
     /* Replace: 0 */
#  endif
#endif

#define _dpppDEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10))
#define PERL_BCDVERSION ((_dpppDEC2BCD(PERL_REVISION)<<24)|(_dpppDEC2BCD(PERL_VERSION)<<12)|_dpppDEC2BCD(PERL_SUBVERSION))

/* It is very unlikely that anyone will try to use this with Perl 6
   (or greater), but who knows.
 */
#if PERL_REVISION != 5
#  error ppport.h only works with Perl version 5
#endif /* PERL_REVISION != 5 */

#ifdef I_LIMITS
#  include <limits.h>
#endif

#ifndef PERL_UCHAR_MIN
#  define PERL_UCHAR_MIN ((unsigned char)0)

ppport.h  view on Meta::CPAN

#endif
#ifndef UVTYPE
#  define UVTYPE                         unsigned IVTYPE
#endif

#ifndef UVSIZE
#  define UVSIZE                         IVSIZE
#endif
#ifndef sv_setuv
#  define sv_setuv(sv, uv)               \
               STMT_START {                         \
                 UV TeMpUv = uv;                    \
                 if (TeMpUv <= IV_MAX)              \
                   sv_setiv(sv, TeMpUv);            \
                 else                               \
                   sv_setnv(sv, (double)TeMpUv);    \
               } STMT_END
#endif
#ifndef newSVuv
#  define newSVuv(uv)                    ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv))
#endif
#ifndef sv_2uv
#  define sv_2uv(sv)                     ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv)))
#endif

#ifndef SvUVX
#  define SvUVX(sv)                      ((UV)SvIVX(sv))

ppport.h  view on Meta::CPAN


#ifndef SvUV
#  define SvUV(sv)                       (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv))
#endif

#ifndef SvUVx
#  define SvUVx(sv)                      ((PL_Sv = (sv)), SvUV(PL_Sv))
#endif

/* Hint: sv_uv
 * Always use the SvUVx() macro instead of sv_uv().
 */
#ifndef sv_uv
#  define sv_uv(sv)                      SvUVx(sv)
#endif

#if !defined(SvUOK) && defined(SvIOK_UV)
#  define SvUOK(sv) SvIOK_UV(sv)
#endif
#ifndef XST_mUV
#  define XST_mUV(i,v)                   (ST(i) = sv_2mortal(newSVuv(v))  )
#endif

ppport.h  view on Meta::CPAN


/* Older perls (<=5.003) lack AvFILLp */
#ifndef AvFILLp
#  define AvFILLp                        AvFILL
#endif
#ifndef ERRSV
#  define ERRSV                          get_sv("@",FALSE)
#endif
#ifndef newSVpvn
#  define newSVpvn(data,len)             ((data)                                              \
                                    ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \
                                    : newSV(0))
#endif

/* Hint: gv_stashpvn
 * This function's backport doesn't support the length parameter, but
 * rather ignores it. Portability can only be ensured if the length
 * parameter is used for speed reasons, but the length can always be
 * correctly computed from the string argument.
 */
#ifndef gv_stashpvn
#  define gv_stashpvn(str,len,create)    gv_stashpv(str,create)
#endif

/* Replace: 1 */
#ifndef get_cv
#  define get_cv                         perl_get_cv
#endif

#ifndef get_sv

ppport.h  view on Meta::CPAN

#endif

#ifndef dITEMS
#  define dITEMS                         I32 items = SP - MARK
#endif
#ifndef dXSTARG
#  define dXSTARG                        SV * targ = sv_newmortal()
#endif
#ifndef dAXMARK
#  define dAXMARK                        I32 ax = POPMARK; \
                               register SV ** const mark = PL_stack_base + ax++
#endif
#ifndef XSprePUSH
#  define XSprePUSH                      (sp = PL_stack_base + ax - 1)
#endif

#if (PERL_BCDVERSION < 0x5005000)
#  undef XSRETURN
#  define XSRETURN(off)                                   \
      STMT_START {                                        \
          PL_stack_sp = PL_stack_base + ax + ((off) - 1); \
          return;                                         \
      } STMT_END
#endif
#ifndef PERL_ABS
#  define PERL_ABS(x)                    ((x) < 0 ? -(x) : (x))
#endif
#ifndef dVAR
#  define dVAR                           dNOOP
#endif
#ifndef SVf
#  define SVf                            "_"
#endif
#ifndef UTF8_MAXBYTES
#  define UTF8_MAXBYTES                  UTF8_MAXLEN
#endif
#ifndef PERL_HASH
#  define PERL_HASH(hash,str,len)        \
     STMT_START	{ \
	const char *s_PeRlHaSh = str; \
	I32 i_PeRlHaSh = len; \
	U32 hash_PeRlHaSh = 0; \
	while (i_PeRlHaSh--) \
	    hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \
	(hash) = hash_PeRlHaSh; \
    } STMT_END
#endif

#ifndef PERL_SIGNALS_UNSAFE_FLAG

#define PERL_SIGNALS_UNSAFE_FLAG 0x0001

#if (PERL_BCDVERSION < 0x5008000)
#  define D_PPP_PERL_SIGNALS_INIT   PERL_SIGNALS_UNSAFE_FLAG
#else
#  define D_PPP_PERL_SIGNALS_INIT   0

ppport.h  view on Meta::CPAN

#elif defined(NEED_PL_signals_GLOBAL)
U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT;
#else
extern U32 DPPP_(my_PL_signals);
#endif
#define PL_signals DPPP_(my_PL_signals)

#endif

/* Hint: PL_ppaddr
 * Calling an op via PL_ppaddr requires passing a context argument
 * for threaded builds. Since the context argument is different for
 * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will
 * automatically be defined as the correct argument.
 */

#if (PERL_BCDVERSION <= 0x5005005)
/* Replace: 1 */
#  define PL_ppaddr                 ppaddr
#  define PL_no_modify              no_modify
/* Replace: 0 */
#endif

#if (PERL_BCDVERSION <= 0x5004005)
/* Replace: 1 */

ppport.h  view on Meta::CPAN

#  define PL_sv_arenaroot           sv_arenaroot
#  define PL_sv_no                  sv_no
#  define PL_sv_undef               sv_undef
#  define PL_sv_yes                 sv_yes
#  define PL_tainted                tainted
#  define PL_tainting               tainting
/* Replace: 0 */
#endif

/* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters
 * Do not use this variable. It is internal to the perl parser
 * and may change or even be removed in the future. Note that
 * as of perl 5.9.5 you cannot assign to this variable anymore.
 */

/* TODO: cannot assign to these vars; is it worth fixing? */
#if (PERL_BCDVERSION >= 0x5009005)
#  define PL_expect         (PL_parser ? PL_parser->expect : 0)
#  define PL_copline        (PL_parser ? PL_parser->copline : 0)
#  define PL_rsfp           (PL_parser ? PL_parser->rsfp : (PerlIO *) 0)
#  define PL_rsfp_filters   (PL_parser ? PL_parser->rsfp_filters : (AV *) 0)
#endif
#ifndef dTHR
#  define dTHR                           dNOOP

ppport.h  view on Meta::CPAN

#  undef eval_pv
#endif
#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b)
#define Perl_eval_pv DPPP_(my_eval_pv)

#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL)

SV*
DPPP_(my_eval_pv)(char *p, I32 croak_on_error)
{
    dSP;
    SV* sv = newSVpv(p, 0);

    PUSHMARK(sp);
    eval_sv(sv, G_SCALAR);
    SvREFCNT_dec(sv);

    SPAGAIN;
    sv = POPs;
    PUTBACK;

    if (croak_on_error && SvTRUE(GvSV(errgv)))
	croak(SvPVx(GvSV(errgv), na));

    return sv;
}

#endif
#endif

#ifndef vload_module
#if defined(NEED_vload_module)
static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args);
static
#else

ppport.h  view on Meta::CPAN

#  undef vload_module
#endif
#define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d)
#define Perl_vload_module DPPP_(my_vload_module)

#if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL)

void
DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args)
{
    dTHR;
    dVAR;
    OP *veop, *imop;

    OP * const modname = newSVOP(OP_CONST, 0, name);
    /* 5.005 has a somewhat hacky force_normal that doesn't croak on
       SvREADONLY() if PL_compling is true. Current perls take care in
       ck_require() to correctly turn off SvREADONLY before calling
       force_normal_flags(). This seems a better fix than fudging PL_compling
     */
    SvREADONLY_off(((SVOP*)modname)->op_sv);
    modname->op_private |= OPpCONST_BARE;
    if (ver) {
	veop = newSVOP(OP_CONST, 0, ver);
    }
    else
	veop = NULL;
    if (flags & PERL_LOADMOD_NOIMPORT) {
	imop = sawparens(newNULLLIST());
    }
    else if (flags & PERL_LOADMOD_IMPORT_OPS) {
	imop = va_arg(*args, OP*);
    }
    else {
	SV *sv;
	imop = NULL;
	sv = va_arg(*args, SV*);
	while (sv) {
	    imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv));
	    sv = va_arg(*args, SV*);
	}
    }
    {
	const line_t ocopline = PL_copline;
	COP * const ocurcop = PL_curcop;
	const int oexpect = PL_expect;

#if (PERL_BCDVERSION >= 0x5004000)
	utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
		veop, modname, imop);
#else
	utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(),
		modname, imop);
#endif
	PL_expect = oexpect;
	PL_copline = ocopline;
	PL_curcop = ocurcop;
    }
}

#endif
#endif

#ifndef load_module
#if defined(NEED_load_module)
static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...);
static
#else

ppport.h  view on Meta::CPAN

#  undef load_module
#endif
#define load_module DPPP_(my_load_module)
#define Perl_load_module DPPP_(my_load_module)

#if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL)

void
DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...)
{
    va_list args;
    va_start(args, ver);
    vload_module(flags, name, ver, &args);
    va_end(args);
}

#endif
#endif
#ifndef newRV_inc
#  define newRV_inc(sv)                  newRV(sv)   /* Replace */
#endif

#ifndef newRV_noinc
#if defined(NEED_newRV_noinc)

ppport.h  view on Meta::CPAN

#ifdef newRV_noinc
#  undef newRV_noinc
#endif
#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a)
#define Perl_newRV_noinc DPPP_(my_newRV_noinc)

#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL)
SV *
DPPP_(my_newRV_noinc)(SV *sv)
{
  SV *rv = (SV *)newRV(sv);
  SvREFCNT_dec(sv);
  return rv;
}
#endif
#endif

/* Hint: newCONSTSUB
 * Returns a CV* as of perl-5.7.1. This return value is not supported
 * by Devel::PPPort.
 */

/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
#if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005)
#if defined(NEED_newCONSTSUB)
static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv);
static
#else
extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv);
#endif

ppport.h  view on Meta::CPAN

#  undef newCONSTSUB
#endif
#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c)
#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB)

#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)

void
DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv)
{
	U32 oldhints = PL_hints;
	HV *old_cop_stash = PL_curcop->cop_stash;
	HV *old_curstash = PL_curstash;
	line_t oldline = PL_curcop->cop_line;
	PL_curcop->cop_line = PL_copline;

	PL_hints &= ~HINT_BLOCK_SCOPE;
	if (stash)
		PL_curstash = PL_curcop->cop_stash = stash;

	newSUB(

#if   (PERL_BCDVERSION < 0x5003022)
		start_subparse(),
#elif (PERL_BCDVERSION == 0x5003022)
     		start_subparse(0),
#else  /* 5.003_23  onwards */
     		start_subparse(FALSE, 0),
#endif

		newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)),
		newSVOP(OP_CONST, 0, &PL_sv_no),   /* SvPV(&PL_sv_no) == "" -- GMB */
		newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
	);

	PL_hints = oldhints;
	PL_curcop->cop_stash = old_cop_stash;
	PL_curstash = old_curstash;
	PL_curcop->cop_line = oldline;
}
#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.
 */

#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
    defined(PERL_CAPI)    || defined(PERL_IMPLICIT_CONTEXT)

#ifndef START_MY_CXT

/* This must appear in all extensions that define a my_cxt_t structure,
 * right after the definition (i.e. at file scope).  The non-threads
 * case below uses it to declare the data as static. */
#define START_MY_CXT

#if (PERL_BCDVERSION < 0x5004068)
/* Fetches the SV that keeps the per-interpreter data. */
#define dMY_CXT_SV \
	SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE)
#else /* >= perl5.004_68 */
#define dMY_CXT_SV \
	SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY,		\
				  sizeof(MY_CXT_KEY)-1, TRUE)
#endif /* < perl5.004_68 */

/* This declaration should be used within all functions that use the
 * interpreter-local data. */
#define dMY_CXT	\
	dMY_CXT_SV;							\
	my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))

/* Creates and zeroes the per-interpreter data.
 * (We allocate my_cxtp in a Perl SV so that it will be released when
 * the interpreter goes away.) */
#define MY_CXT_INIT \
	dMY_CXT_SV;							\
	/* newSV() allocates one more than needed */			\
	my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
	Zero(my_cxtp, 1, my_cxt_t);					\
	sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))

/* This macro must be used to access members of the my_cxt_t structure.
 * e.g. MYCXT.some_data */
#define MY_CXT		(*my_cxtp)

/* Judicious use of these macros can reduce the number of times dMY_CXT
 * is used.  Use is similar to pTHX, aTHX etc. */
#define pMY_CXT		my_cxt_t *my_cxtp
#define pMY_CXT_	pMY_CXT,
#define _pMY_CXT	,pMY_CXT
#define aMY_CXT		my_cxtp
#define aMY_CXT_	aMY_CXT,
#define _aMY_CXT	,aMY_CXT

#endif /* START_MY_CXT */

#ifndef MY_CXT_CLONE
/* Clones the per-interpreter data. */
#define MY_CXT_CLONE \
	dMY_CXT_SV;							\
	my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
	Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\
	sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
#endif

#else /* single interpreter */

#ifndef START_MY_CXT

#define START_MY_CXT	static my_cxt_t my_cxt;
#define dMY_CXT_SV	dNOOP
#define dMY_CXT		dNOOP
#define MY_CXT_INIT	NOOP

ppport.h  view on Meta::CPAN

#      define	UVuf      "u"
#      define	UVof      "o"
#      define	UVxf      "x"
#      define	UVXf      "X"
#    endif
#  endif
#endif

#ifndef NVef
#  if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
      defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */
#    define NVef          PERL_PRIeldbl
#    define NVff          PERL_PRIfldbl
#    define NVgf          PERL_PRIgldbl
#  else
#    define NVef          "e"
#    define NVff          "f"
#    define NVgf          "g"
#  endif
#endif

#ifndef SvREFCNT_inc
#  ifdef PERL_USE_GCC_BRACE_GROUPS
#    define SvREFCNT_inc(sv)		\
      ({				\
          SV * const _sv = (SV*)(sv);	\
          if (_sv)			\
               (SvREFCNT(_sv))++;	\
          _sv;				\
      })
#  else
#    define SvREFCNT_inc(sv)	\
          ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
#  endif
#endif

#ifndef SvREFCNT_inc_simple
#  ifdef PERL_USE_GCC_BRACE_GROUPS
#    define SvREFCNT_inc_simple(sv)	\
      ({					\
          if (sv)				\
               (SvREFCNT(sv))++;		\
          (SV *)(sv);				\
      })
#  else
#    define SvREFCNT_inc_simple(sv) \
          ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL)
#  endif
#endif

#ifndef SvREFCNT_inc_NN
#  ifdef PERL_USE_GCC_BRACE_GROUPS
#    define SvREFCNT_inc_NN(sv)		\
      ({					\
          SV * const _sv = (SV*)(sv);	\
          SvREFCNT(_sv)++;		\
          _sv;				\
      })
#  else
#    define SvREFCNT_inc_NN(sv) \
          (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
#  endif
#endif

#ifndef SvREFCNT_inc_void
#  ifdef PERL_USE_GCC_BRACE_GROUPS
#    define SvREFCNT_inc_void(sv)		\
      ({					\
          SV * const _sv = (SV*)(sv);	\
          if (_sv)			\
              (void)(SvREFCNT(_sv)++);	\
      })
#  else
#    define SvREFCNT_inc_void(sv) \
          (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
#  endif
#endif
#ifndef SvREFCNT_inc_simple_void
#  define SvREFCNT_inc_simple_void(sv)   STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END
#endif

#ifndef SvREFCNT_inc_simple_NN
#  define SvREFCNT_inc_simple_NN(sv)     (++SvREFCNT(sv), (SV*)(sv))
#endif

ppport.h  view on Meta::CPAN


/* Backwards compatibility stuff... :-( */
#if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen)
#  define NEED_sv_2pv_flags
#endif
#if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL)
#  define NEED_sv_2pv_flags_GLOBAL
#endif

/* Hint: sv_2pv_nolen
 * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen().
 */
#ifndef sv_2pv_nolen
#  define sv_2pv_nolen(sv)               SvPV_nolen(sv)
#endif

#ifdef SvPVbyte

/* Hint: SvPVbyte
 * Does not work in perl-5.6.1, ppport.h implements a version
 * borrowed from perl-5.7.3.
 */

#if (PERL_BCDVERSION < 0x5007000)

#if defined(NEED_sv_2pvbyte)
static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV * sv, STRLEN * lp);
static
#else
extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV * sv, STRLEN * lp);
#endif

ppport.h  view on Meta::CPAN

#  undef sv_2pvbyte
#endif
#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b)
#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte)

#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL)

char *
DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp)
{
  sv_utf8_downgrade(sv,0);
  return SvPV(sv,*lp);
}

#endif

/* Hint: sv_2pvbyte
 * Use the SvPVbyte() macro instead of sv_2pvbyte().
 */

#undef SvPVbyte

#define SvPVbyte(sv, lp)                                                \
        ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK)                \
         ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp))

#endif

#else

#  define SvPVbyte          SvPV
#  define sv_2pvbyte        sv_2pv

#endif
#ifndef sv_2pvbyte_nolen
#  define sv_2pvbyte_nolen(sv)           sv_2pv_nolen(sv)
#endif

/* Hint: sv_pvn
 * Always use the SvPV() macro instead of sv_pvn().
 */

/* Hint: sv_pvn_force
 * Always use the SvPV_force() macro instead of sv_pvn_force().
 */

/* If these are undefined, they're not handled by the core anyway */
#ifndef SV_IMMEDIATE_UNREF
#  define SV_IMMEDIATE_UNREF             0
#endif

#ifndef SV_GMAGIC
#  define SV_GMAGIC                      0
#endif

ppport.h  view on Meta::CPAN

#  undef sv_2pv_flags
#endif
#define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c)
#define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags)

#if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL)

char *
DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags)
{
  STRLEN n_a = (STRLEN) flags;
  return sv_2pv(sv, lp ? lp : &n_a);
}

#endif

#if defined(NEED_sv_pvn_force_flags)
static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV * sv, STRLEN * lp, I32 flags);
static
#else
extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV * sv, STRLEN * lp, I32 flags);
#endif

ppport.h  view on Meta::CPAN

#  undef sv_pvn_force_flags
#endif
#define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c)
#define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags)

#if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL)

char *
DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags)
{
  STRLEN n_a = (STRLEN) flags;
  return sv_pvn_force(sv, lp ? lp : &n_a);
}

#endif

#endif
#ifndef SvPV_const
#  define SvPV_const(sv, lp)             SvPV_flags_const(sv, lp, SV_GMAGIC)
#endif

#ifndef SvPV_mutable
#  define SvPV_mutable(sv, lp)           SvPV_flags_mutable(sv, lp, SV_GMAGIC)
#endif
#ifndef SvPV_flags
#  define SvPV_flags(sv, lp, flags)      \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags))
#endif
#ifndef SvPV_flags_const
#  define SvPV_flags_const(sv, lp, flags) \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \
                  (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN))
#endif
#ifndef SvPV_flags_const_nolen
#  define SvPV_flags_const_nolen(sv, flags) \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? SvPVX_const(sv) : \
                  (const char*) sv_2pv_flags(sv, 0, flags|SV_CONST_RETURN))
#endif
#ifndef SvPV_flags_mutable
#  define SvPV_flags_mutable(sv, lp, flags) \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \
                  sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN))
#endif
#ifndef SvPV_force
#  define SvPV_force(sv, lp)             SvPV_force_flags(sv, lp, SV_GMAGIC)
#endif

#ifndef SvPV_force_nolen
#  define SvPV_force_nolen(sv)           SvPV_force_flags_nolen(sv, SV_GMAGIC)
#endif

#ifndef SvPV_force_mutable

ppport.h  view on Meta::CPAN


#ifndef SvPV_force_nomg
#  define SvPV_force_nomg(sv, lp)        SvPV_force_flags(sv, lp, 0)
#endif

#ifndef SvPV_force_nomg_nolen
#  define SvPV_force_nomg_nolen(sv)      SvPV_force_flags_nolen(sv, 0)
#endif
#ifndef SvPV_force_flags
#  define SvPV_force_flags(sv, lp, flags) \
                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
                 ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags))
#endif
#ifndef SvPV_force_flags_nolen
#  define SvPV_force_flags_nolen(sv, flags) \
                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
                 ? SvPVX(sv) : sv_pvn_force_flags(sv, 0, flags))
#endif
#ifndef SvPV_force_flags_mutable
#  define SvPV_force_flags_mutable(sv, lp, flags) \
                 ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
                 ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \
                  : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN))
#endif
#ifndef SvPV_nolen
#  define SvPV_nolen(sv)                 \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? SvPVX(sv) : sv_2pv_flags(sv, 0, SV_GMAGIC))
#endif
#ifndef SvPV_nolen_const
#  define SvPV_nolen_const(sv)           \
                 ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
                  ? SvPVX_const(sv) : sv_2pv_flags(sv, 0, SV_GMAGIC|SV_CONST_RETURN))
#endif
#ifndef SvPV_nomg
#  define SvPV_nomg(sv, lp)              SvPV_flags(sv, lp, 0)
#endif

#ifndef SvPV_nomg_const
#  define SvPV_nomg_const(sv, lp)        SvPV_flags_const(sv, lp, 0)
#endif

#ifndef SvPV_nomg_const_nolen
#  define SvPV_nomg_const_nolen(sv)      SvPV_flags_const_nolen(sv, 0)
#endif
#ifndef SvMAGIC_set
#  define SvMAGIC_set(sv, val)           \
                STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
                (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END
#endif

#if (PERL_BCDVERSION < 0x5009003)
#ifndef SvPVX_const
#  define SvPVX_const(sv)                ((const char*) (0 + SvPVX(sv)))
#endif

#ifndef SvPVX_mutable
#  define SvPVX_mutable(sv)              (0 + SvPVX(sv))
#endif
#ifndef SvRV_set
#  define SvRV_set(sv, val)              \
                STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
                (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END
#endif

#else
#ifndef SvPVX_const
#  define SvPVX_const(sv)                ((const char*)((sv)->sv_u.svu_pv))
#endif

#ifndef SvPVX_mutable
#  define SvPVX_mutable(sv)              ((sv)->sv_u.svu_pv)
#endif
#ifndef SvRV_set
#  define SvRV_set(sv, val)              \
                STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
                ((sv)->sv_u.svu_rv = (val)); } STMT_END
#endif

#endif
#ifndef SvSTASH_set
#  define SvSTASH_set(sv, val)           \
                STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
                (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END
#endif

#if (PERL_BCDVERSION < 0x5004000)
#ifndef SvUV_set
#  define SvUV_set(sv, val)              \
                STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END
#endif

#else
#ifndef SvUV_set
#  define SvUV_set(sv, val)              \
                STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END
#endif

#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf)
#if defined(NEED_vnewSVpvf)
static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char * pat, va_list * args);
static
#else
extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char * pat, va_list * args);

ppport.h  view on Meta::CPAN

#  undef vnewSVpvf
#endif
#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b)
#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf)

#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL)

SV *
DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args)
{
  register SV *sv = newSV(0);
  sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
  return sv;
}

#endif
#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf)
#  define sv_vcatpvf(sv, pat, args)  sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*))
#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf)

ppport.h  view on Meta::CPAN

extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
#endif

#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg)

#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL)

void
DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
{
  va_list args;
  va_start(args, pat);
  sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
  SvSETMAGIC(sv);
  va_end(args);
}

#endif
#endif

#ifdef PERL_IMPLICIT_CONTEXT
#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext)
#if defined(NEED_sv_catpvf_mg_nocontext)
static void DPPP_(my_sv_catpvf_mg_nocontext)(SV * sv, const char * pat, ...);
static

ppport.h  view on Meta::CPAN

#endif

#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)
#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)

#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL)

void
DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...)
{
  dTHX;
  va_list args;
  va_start(args, pat);
  sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
  SvSETMAGIC(sv);
  va_end(args);
}

#endif
#endif
#endif

/* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */
#ifndef sv_catpvf_mg
#  ifdef PERL_IMPLICIT_CONTEXT
#    define sv_catpvf_mg   Perl_sv_catpvf_mg_nocontext
#  else
#    define sv_catpvf_mg   Perl_sv_catpvf_mg
#  endif
#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg)
#  define sv_vcatpvf_mg(sv, pat, args)                                     \
   STMT_START {                                                            \
     sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));  \
     SvSETMAGIC(sv);                                                       \
   } STMT_END
#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg)
#if defined(NEED_sv_setpvf_mg)
static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
static
#else
extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
#endif

#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg)

#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL)

void
DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
{
  va_list args;
  va_start(args, pat);
  sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
  SvSETMAGIC(sv);
  va_end(args);
}

#endif
#endif

#ifdef PERL_IMPLICIT_CONTEXT
#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext)
#if defined(NEED_sv_setpvf_mg_nocontext)
static void DPPP_(my_sv_setpvf_mg_nocontext)(SV * sv, const char * pat, ...);
static

ppport.h  view on Meta::CPAN

#endif

#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)
#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)

#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL)

void
DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...)
{
  dTHX;
  va_list args;
  va_start(args, pat);
  sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
  SvSETMAGIC(sv);
  va_end(args);
}

#endif
#endif
#endif

/* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */
#ifndef sv_setpvf_mg
#  ifdef PERL_IMPLICIT_CONTEXT
#    define sv_setpvf_mg   Perl_sv_setpvf_mg_nocontext
#  else
#    define sv_setpvf_mg   Perl_sv_setpvf_mg
#  endif
#endif

#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg)
#  define sv_vsetpvf_mg(sv, pat, args)                                     \
   STMT_START {                                                            \
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));  \
     SvSETMAGIC(sv);                                                       \
   } STMT_END
#endif

#ifndef newSVpvn_share

#if defined(NEED_newSVpvn_share)
static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash);
static
#else
extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash);
#endif

ppport.h  view on Meta::CPAN

#  undef newSVpvn_share
#endif
#define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c)
#define Perl_newSVpvn_share DPPP_(my_newSVpvn_share)

#if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL)

SV *
DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash)
{
  SV *sv;
  if (len < 0)
    len = -len;
  if (!hash)
    PERL_HASH(hash, (char*) src, len);
  sv = newSVpvn((char *) src, len);
  sv_upgrade(sv, SVt_PVIV);
  SvIVX(sv) = hash;
  SvREADONLY_on(sv);
  SvPOK_on(sv);
  return sv;
}

#endif

#endif
#ifndef SvSHARED_HASH
#  define SvSHARED_HASH(sv)              (0 + SvUVX(sv))
#endif
#ifndef WARN_ALL
#  define WARN_ALL                       0

ppport.h  view on Meta::CPAN

extern void DPPP_(my_warner)(U32 err, const char *pat, ...);
#endif

#define Perl_warner DPPP_(my_warner)

#if defined(NEED_warner) || defined(NEED_warner_GLOBAL)

void
DPPP_(my_warner)(U32 err, const char *pat, ...)
{
  SV *sv;
  va_list args;

  PERL_UNUSED_ARG(err);

  va_start(args, pat);
  sv = vnewSVpvf(pat, &args);
  va_end(args);
  sv_2mortal(sv);
  warn("%s", SvPV_nolen(sv));
}

#define warner  Perl_warner

#define Perl_warner_nocontext  Perl_warner

#endif
#endif

/* concatenating with "" ensures that only literal strings are accepted as argument
 * note that STR_WITH_LEN() can't be used as argument to macros or functions that
 * under some configurations might be macros
 */
#ifndef STR_WITH_LEN
#  define STR_WITH_LEN(s)                (s ""), (sizeof(s)-1)
#endif
#ifndef newSVpvs
#  define newSVpvs(str)                  newSVpvn(str "", sizeof(str) - 1)
#endif

#ifndef sv_catpvs
#  define sv_catpvs(sv, str)             sv_catpvn(sv, str "", sizeof(str) - 1)
#endif

ppport.h  view on Meta::CPAN

#ifndef SvIV_nomg
#  define SvIV_nomg                      SvIV
#endif

#ifndef SvUV_nomg
#  define SvUV_nomg                      SvUV
#endif

#ifndef sv_catpv_mg
#  define sv_catpv_mg(sv, ptr)          \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_catpv(TeMpSv,ptr);              \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_catpvn_mg
#  define sv_catpvn_mg(sv, ptr, len)    \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_catpvn(TeMpSv,ptr,len);         \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_catsv_mg
#  define sv_catsv_mg(dsv, ssv)         \
   STMT_START {                         \
     SV *TeMpSv = dsv;                  \
     sv_catsv(TeMpSv,ssv);              \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setiv_mg
#  define sv_setiv_mg(sv, i)            \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_setiv(TeMpSv,i);                \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setnv_mg
#  define sv_setnv_mg(sv, num)          \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_setnv(TeMpSv,num);              \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setpv_mg
#  define sv_setpv_mg(sv, ptr)          \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_setpv(TeMpSv,ptr);              \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setpvn_mg
#  define sv_setpvn_mg(sv, ptr, len)    \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_setpvn(TeMpSv,ptr,len);         \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setsv_mg
#  define sv_setsv_mg(dsv, ssv)         \
   STMT_START {                         \
     SV *TeMpSv = dsv;                  \
     sv_setsv(TeMpSv,ssv);              \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_setuv_mg
#  define sv_setuv_mg(sv, i)            \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_setuv(TeMpSv,i);                \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif

#ifndef sv_usepvn_mg
#  define sv_usepvn_mg(sv, ptr, len)    \
   STMT_START {                         \
     SV *TeMpSv = sv;                   \
     sv_usepvn(TeMpSv,ptr,len);         \
     SvSETMAGIC(TeMpSv);                \
   } STMT_END
#endif
#ifndef SvVSTRING_mg
#  define SvVSTRING_mg(sv)               (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL)
#endif

/* Hint: sv_magic_portable
 * This is a compatibility function that is only available with
 * Devel::PPPort. It is NOT in the perl core.
 * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when
 * it is being passed a name pointer with namlen == 0. In that
 * case, perl 5.8.0 and later store the pointer, not a copy of it.
 * The compatibility can be provided back to perl 5.004. With
 * earlier versions, the code will not compile.
 */

#if (PERL_BCDVERSION < 0x5004000)

  /* code that uses sv_magic_portable will not compile */

#elif (PERL_BCDVERSION < 0x5008000)

#  define sv_magic_portable(sv, obj, how, name, namlen)     \
   STMT_START {                                             \
     SV *SvMp_sv = (sv);                                    \
     char *SvMp_name = (char *) (name);                     \
     I32 SvMp_namlen = (namlen);                            \
     if (SvMp_name && SvMp_namlen == 0)                     \
     {                                                      \
       MAGIC *mg;                                           \
       sv_magic(SvMp_sv, obj, how, 0, 0);                   \
       mg = SvMAGIC(SvMp_sv);                               \
       mg->mg_len = -42; /* XXX: this is the tricky part */ \
       mg->mg_ptr = SvMp_name;                              \
     }                                                      \
     else                                                   \
     {                                                      \
       sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \
     }                                                      \
   } STMT_END

#else

#  define sv_magic_portable(a, b, c, d, e)  sv_magic(a, b, c, d, e)

#endif

#ifdef USE_ITHREADS
#ifndef CopFILE
#  define CopFILE(c)                     ((c)->cop_file)

ppport.h  view on Meta::CPAN

#ifndef CopSTASH
#  define CopSTASH(c)                    (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv)
#endif

#ifndef CopSTASH_set
#  define CopSTASH_set(c,hv)             CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch)
#endif

#ifndef CopSTASH_eq
#  define CopSTASH_eq(c,hv)              ((hv) && (CopSTASHPV(c) == HvNAME(hv) \
					|| (CopSTASHPV(c) && HvNAME(hv) \
					&& strEQ(CopSTASHPV(c), HvNAME(hv)))))
#endif

#else
#ifndef CopFILEGV
#  define CopFILEGV(c)                   ((c)->cop_filegv)
#endif

#ifndef CopFILEGV_set
#  define CopFILEGV_set(c,gv)            ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv))
#endif

ppport.h  view on Meta::CPAN

#endif
#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b)
#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix)

#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL)
bool
DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send)
{
#ifdef USE_LOCALE_NUMERIC
#ifdef PL_numeric_radix_sv
    if (PL_numeric_radix_sv && IN_LOCALE) {
        STRLEN len;
        char* radix = SvPV(PL_numeric_radix_sv, len);
        if (*sp + len <= send && memEQ(*sp, radix, len)) {
            *sp += len;
            return TRUE;
        }
    }
#else
    /* older perls don't have PL_numeric_radix_sv so the radix
     * must manually be requested from locale.h
     */
#include <locale.h>
    dTHR;  /* needed for older threaded perls */
    struct lconv *lc = localeconv();
    char *radix = lc->decimal_point;
    if (radix && IN_LOCALE) {
        STRLEN len = strlen(radix);
        if (*sp + len <= send && memEQ(*sp, radix, len)) {
            *sp += len;
            return TRUE;
        }
    }
#endif
#endif /* USE_LOCALE_NUMERIC */
    /* always try "." if numeric radix didn't match because
     * we may have data from different locales mixed */
    if (*sp < send && **sp == '.') {
        ++*sp;
        return TRUE;
    }
    return FALSE;
}
#endif
#endif

#ifndef grok_number
#if defined(NEED_grok_number)
static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);
static
#else
extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);

ppport.h  view on Meta::CPAN

#ifdef grok_number
#  undef grok_number
#endif
#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c)
#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
       overflow.  */
    UV value = *s - '0';
    /* This construction seems to be more optimiser friendly.
       (without it gcc does the isDIGIT test and the *s - '0' separately)
       With it gcc on arm is managing 6 instructions (6 cycles) per digit.
       In theory the optimiser could deduce how far to unroll the loop
       before checking for overflow.  */
    if (++s < send) {
      int digit = *s - '0';
      if (digit >= 0 && digit <= 9) {
        value = value * 10 + digit;
        if (++s < send) {
          digit = *s - '0';
          if (digit >= 0 && digit <= 9) {
            value = value * 10 + digit;
            if (++s < send) {
              digit = *s - '0';
              if (digit >= 0 && digit <= 9) {
                value = value * 10 + digit;
		if (++s < send) {
                  digit = *s - '0';
                  if (digit >= 0 && digit <= 9) {
                    value = value * 10 + digit;
                    if (++s < send) {
                      digit = *s - '0';
                      if (digit >= 0 && digit <= 9) {
                        value = value * 10 + digit;
                        if (++s < send) {
                          digit = *s - '0';
                          if (digit >= 0 && digit <= 9) {
                            value = value * 10 + digit;
                            if (++s < send) {
                              digit = *s - '0';
                              if (digit >= 0 && digit <= 9) {
                                value = value * 10 + digit;
                                if (++s < send) {
                                  digit = *s - '0';
                                  if (digit >= 0 && digit <= 9) {
                                    value = value * 10 + digit;
                                    if (++s < send) {
                                      /* Now got 9 digits, so need to check
                                         each time for overflow.  */
                                      digit = *s - '0';
                                      while (digit >= 0 && digit <= 9
                                             && (value < max_div_10
                                                 || (value == max_div_10
                                                     && digit <= max_mod_10))) {
                                        value = value * 10 + digit;
                                        if (++s < send)
                                          digit = *s - '0';
                                        else
                                          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
      return 0;
  } else if (*s == 'I' || *s == 'i') {
    s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
    s++; if (s == send || (*s != 'F' && *s != 'f')) return 0;
    s++; if (s < send && (*s == 'I' || *s == 'i')) {
      s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
      s++; if (s == send || (*s != 'I' && *s != 'i')) return 0;
      s++; if (s == send || (*s != 'T' && *s != 't')) return 0;
      s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0;
      s++;
    }
    sawinf = 1;
  } 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

/*
 * The grok_* routines have been modified to use warn() instead of
 * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit,
 * which is why the stack variable has been renamed to 'xdigit'.
 */

#ifndef grok_bin
#if defined(NEED_grok_bin)
static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
static
#else
extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
#endif

#ifdef grok_bin
#  undef grok_bin
#endif
#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d)
#define Perl_grok_bin DPPP_(my_grok_bin)

#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL)
UV
DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
{
    const char *s = start;
    STRLEN len = *len_p;
    UV value = 0;
    NV value_nv = 0;

    const UV max_div_2 = UV_MAX / 2;
    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
    bool overflowed = FALSE;

    if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
        /* strip off leading b or 0b.
           for compatibility silently suffer "b" and "0b" as valid binary
           numbers. */
        if (len >= 1) {
            if (s[0] == 'b') {
                s++;
                len--;
            }
            else if (len >= 2 && s[0] == '0' && s[1] == 'b') {
                s+=2;
                len-=2;
            }
        }
    }

    for (; len-- && *s; s++) {
        char bit = *s;
        if (bit == '0' || bit == '1') {
            /* Write it in this wonky order with a goto to attempt to get the
               compiler to make the common case integer-only loop pretty tight.
               With gcc seems to be much straighter code than old scan_bin.  */
          redo:
            if (!overflowed) {
                if (value <= max_div_2) {
                    value = (value << 1) | (bit - '0');
                    continue;
                }
                /* Bah. We're just overflowed.  */
                warn("Integer overflow in binary number");
                overflowed = TRUE;
                value_nv = (NV) value;
            }
            value_nv *= 2.0;
	    /* If an NV has not enough bits in its mantissa to
	     * represent a UV this summing of small low-order numbers
	     * is a waste of time (because the NV cannot preserve
	     * the low-order bits anyway): we could just remember when
	     * did we overflow and in the end just multiply value_nv by the
	     * right amount. */
            value_nv += (NV)(bit - '0');
            continue;
        }
        if (bit == '_' && len && allow_underscores && (bit = s[1])
            && (bit == '0' || bit == '1'))
	    {
		--len;
		++s;
                goto redo;
	    }
        if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
            warn("Illegal binary digit '%c' ignored", *s);
        break;
    }

    if (   ( overflowed && value_nv > 4294967295.0)
#if UVSIZE > 4
	|| (!overflowed && value > 0xffffffff  )
#endif
	) {
	warn("Binary number > 0b11111111111111111111111111111111 non-portable");
    }
    *len_p = s - start;
    if (!overflowed) {
        *flags = 0;
        return value;
    }
    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
    if (result)
        *result = value_nv;
    return UV_MAX;
}
#endif
#endif

#ifndef grok_hex
#if defined(NEED_grok_hex)
static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
static
#else
extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);

ppport.h  view on Meta::CPAN

#ifdef grok_hex
#  undef grok_hex
#endif
#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d)
#define Perl_grok_hex DPPP_(my_grok_hex)

#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL)
UV
DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
{
    const char *s = start;
    STRLEN len = *len_p;
    UV value = 0;
    NV value_nv = 0;

    const UV max_div_16 = UV_MAX / 16;
    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
    bool overflowed = FALSE;
    const char *xdigit;

    if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
        /* strip off leading x or 0x.
           for compatibility silently suffer "x" and "0x" as valid hex numbers.
        */
        if (len >= 1) {
            if (s[0] == 'x') {
                s++;
                len--;
            }
            else if (len >= 2 && s[0] == '0' && s[1] == 'x') {
                s+=2;
                len-=2;
            }
        }
    }

    for (; len-- && *s; s++) {
	xdigit = strchr((char *) PL_hexdigit, *s);
        if (xdigit) {
            /* Write it in this wonky order with a goto to attempt to get the
               compiler to make the common case integer-only loop pretty tight.
               With gcc seems to be much straighter code than old scan_hex.  */
          redo:
            if (!overflowed) {
                if (value <= max_div_16) {
                    value = (value << 4) | ((xdigit - PL_hexdigit) & 15);
                    continue;
                }
                warn("Integer overflow in hexadecimal number");
                overflowed = TRUE;
                value_nv = (NV) value;
            }
            value_nv *= 16.0;
	    /* If an NV has not enough bits in its mantissa to
	     * represent a UV this summing of small low-order numbers
	     * is a waste of time (because the NV cannot preserve
	     * the low-order bits anyway): we could just remember when
	     * did we overflow and in the end just multiply value_nv by the
	     * right amount of 16-tuples. */
            value_nv += (NV)((xdigit - PL_hexdigit) & 15);
            continue;
        }
        if (*s == '_' && len && allow_underscores && s[1]
		&& (xdigit = strchr((char *) PL_hexdigit, s[1])))
	    {
		--len;
		++s;
                goto redo;
	    }
        if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
            warn("Illegal hexadecimal digit '%c' ignored", *s);
        break;
    }

    if (   ( overflowed && value_nv > 4294967295.0)
#if UVSIZE > 4
	|| (!overflowed && value > 0xffffffff  )
#endif
	) {
	warn("Hexadecimal number > 0xffffffff non-portable");
    }
    *len_p = s - start;
    if (!overflowed) {
        *flags = 0;
        return value;
    }
    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
    if (result)
        *result = value_nv;
    return UV_MAX;
}
#endif
#endif

#ifndef grok_oct
#if defined(NEED_grok_oct)
static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);
static
#else
extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result);

ppport.h  view on Meta::CPAN

#ifdef grok_oct
#  undef grok_oct
#endif
#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d)
#define Perl_grok_oct DPPP_(my_grok_oct)

#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL)
UV
DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
{
    const char *s = start;
    STRLEN len = *len_p;
    UV value = 0;
    NV value_nv = 0;

    const UV max_div_8 = UV_MAX / 8;
    bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
    bool overflowed = FALSE;

    for (; len-- && *s; s++) {
         /* gcc 2.95 optimiser not smart enough to figure that this subtraction
            out front allows slicker code.  */
        int digit = *s - '0';
        if (digit >= 0 && digit <= 7) {
            /* Write it in this wonky order with a goto to attempt to get the
               compiler to make the common case integer-only loop pretty tight.
            */
          redo:
            if (!overflowed) {
                if (value <= max_div_8) {
                    value = (value << 3) | digit;
                    continue;
                }
                /* Bah. We're just overflowed.  */
                warn("Integer overflow in octal number");
                overflowed = TRUE;
                value_nv = (NV) value;
            }
            value_nv *= 8.0;
	    /* If an NV has not enough bits in its mantissa to
	     * represent a UV this summing of small low-order numbers
	     * is a waste of time (because the NV cannot preserve
	     * the low-order bits anyway): we could just remember when
	     * did we overflow and in the end just multiply value_nv by the
	     * right amount of 8-tuples. */
            value_nv += (NV)digit;
            continue;
        }
        if (digit == ('_' - '0') && len && allow_underscores
            && (digit = s[1] - '0') && (digit >= 0 && digit <= 7))
	    {
		--len;
		++s;
                goto redo;
	    }
        /* Allow \octal to work the DWIM way (that is, stop scanning
         * as soon as non-octal characters are seen, complain only iff
         * someone seems to want to use the digits eight and nine). */
        if (digit == 8 || digit == 9) {
            if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
                warn("Illegal octal digit '%c' ignored", *s);
        }
        break;
    }

    if (   ( overflowed && value_nv > 4294967295.0)
#if UVSIZE > 4
	|| (!overflowed && value > 0xffffffff  )
#endif
	) {
	warn("Octal number > 037777777777 non-portable");
    }
    *len_p = s - start;
    if (!overflowed) {
        *flags = 0;
        return value;
    }
    *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
    if (result)
        *result = value_nv;
    return UV_MAX;
}
#endif
#endif

#if !defined(my_snprintf)
#if defined(NEED_my_snprintf)
static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...);
static
#else
extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...);
#endif

#define my_snprintf DPPP_(my_my_snprintf)
#define Perl_my_snprintf DPPP_(my_my_snprintf)

#if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL)

int
DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...)
{
    dTHX;
    int retval;
    va_list ap;
    va_start(ap, format);
#ifdef HAS_VSNPRINTF
    retval = vsnprintf(buffer, len, format, ap);
#else
    retval = vsprintf(buffer, format, ap);
#endif
    va_end(ap);
    if (retval >= (int)len)
	Perl_croak(aTHX_ "panic: my_snprintf buffer overflow");
    return retval;
}

#endif
#endif

#ifdef NO_XSLOCKS
#  ifdef dJMPENV
#    define dXCPT             dJMPENV; int rEtV = 0
#    define XCPT_TRY_START    JMPENV_PUSH(rEtV); if (rEtV == 0)
#    define XCPT_TRY_END      JMPENV_POP;

ppport.h  view on Meta::CPAN

#endif

#define my_strlcat DPPP_(my_my_strlcat)
#define Perl_my_strlcat DPPP_(my_my_strlcat)

#if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL)

Size_t
DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size)
{
    Size_t used, length, copy;

    used = strlen(dst);
    length = strlen(src);
    if (size > 0 && used < size - 1) {
        copy = (length >= size - used) ? size - used - 1 : length;
        memcpy(dst + used, src, copy);
        dst[used + copy] = '\0';
    }
    return used + length;
}
#endif
#endif

#if !defined(my_strlcpy)
#if defined(NEED_my_strlcpy)
static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size);
static
#else
extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size);
#endif

#define my_strlcpy DPPP_(my_my_strlcpy)
#define Perl_my_strlcpy DPPP_(my_my_strlcpy)

#if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL)

Size_t
DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size)
{
    Size_t length, copy;

    length = strlen(src);
    if (size > 0) {
        copy = (length >= size) ? size - 1 : length;
        memcpy(dst, src, copy);
        dst[copy] = '\0';
    }
    return length;
}

#endif
#endif

#endif /* _P_P_PORTABILITY_H_ */

/* End of File ppport.h */

samples/add.pl  view on Meta::CPAN


use strict;
use warnings;

use AI::FANN qw(:all);

my $n = 500;

if ($ARGV[0] eq 'train') {

    # create an ANN with 2 inputs, a hidden layer with 3 neurons and an
    # output layer with 1 neuron:
    my $ann = AI::FANN->new_standard(2, 5, 3, 1);

    $ann->hidden_activation_function(FANN_SIGMOID_SYMMETRIC);
    $ann->output_activation_function(FANN_SIGMOID_SYMMETRIC);

    my $train = AI::FANN::TrainData->new_empty($n, 2, 1);

    for (0..$n-1) {
        my $a = rand(2) - 1;
        my $b = rand(2) - 1;
        my $c = 0.5 * ($a + $b);

        $train->data($_, [$a, $b], [$c]);
    }

    $ann->train_on_data($train, 25000, 250, 0.00001);
    $ann->save("add.ann");
}
elsif ($ARGV[0] eq 'test') {

    my $ann = AI::FANN->new_from_file("add.ann");

    for (1..10) {
        my $a = rand(2) - 1;
        my $b = rand(2) - 1;

        my $c = 0.5 * ($a + $b);

        my $out = $ann->run([$a, $b]);
        printf "%f + %f = %f (good: %f, error: %4.1f%%)\n",
            $a, $b, $out->[0], $c, 50*abs($out->[0] - $c);
    }
}

else {
    die "bad action\n"
}

samples/ox.pl  view on Meta::CPAN


use GD;
use AI::FANN qw(:all);

my $num = 500;
my $size = 16;

$| = 1;

sub draw_o {
    my ($im, $color) = @_;
    my $r = int (0.2 + rand(0.25 * $size));
    my $x0 = $r + int rand($size - 2 * $r);
    my $y0 = $r + int rand($size - 2 * $r);
    $im->arc($x0, $y0, $r, $r, 0, 360, $color);
    return 2*$r/$size
}

sub draw_x {
    my ($im, $color) = @_;
    my $r = int (0.2 + rand(0.25 * $size));
    my $x0 = $r + int rand($size - 2 * $r);
    my $y0 = $r + int rand($size - 2 * $r);
    $im->line($x0-$r, $y0-$r, $x0+$r, $y0+$r, $color);
    $im->line($x0-$r, $y0+$r, $x0+$r, $y0-$r, $color);
    return 2*$r/$size
}

sub image_to_input {
    my ($im, $type) = @_;
    my @data;
    for my $x (0..$size-1) {
        for my $y (0..$size-1) {
            push @data, $im->getPixel($x, $y);
        }
    }
    return \@data;
}

sub make_train {
    my $train = AI::FANN::TrainData->new_empty($num, $size * $size, 2);
    for (0..$num - 1) {
        print ".";
        my $im = GD::Image->new($size, $size);
        my $white = $im->colorAllocate(255,255,255);
        my $black = $im->colorAllocate(0,0,0);
        my $type = (rand > .5);
        my $r = $type ? draw_x($im, $black) : draw_o($im, $black);
        $train->data($_, image_to_input($im), [$type, $r]);
    }
    print "\n";
    my $ann = AI::FANN->new_standard(@_);
    for (1..40) {
        $ann->train_on_data($train, 100, 1, 0.0001);
        # $ann->print_connections;
        $ann->print_parameters;
        $ann->save("ox.ann");
    }
}

sub make_test {
    my $rep = shift;
    my $ann = AI::FANN->new_from_file("ox.ann");
    print "ann read\n";
    for (0..$rep - 1) {
        my $im = GD::Image->new($size, $size);
        my $white = $im->colorAllocate(255,255,255);
        my $black = $im->colorAllocate(0,0,0);
        my $type = (rand > .5);
        my $r = $type ? draw_x($im, $black) : draw_o($im, $black);
        my $out = $ann->run(image_to_input($im));
        printf ("type: %f, r: %4.2f out type: %f, r: %4.2f\n", $type, $r, $out->[0], $out->[1]);
    }
}

if ($ARGV[0] eq 'train') {
    make_train($size * $size, 4 * $size * $size, 240, 200, 60, 20, 2);
}
elsif ($ARGV[0] eq 'test') {
    make_test($ARGV[1] || 10);
}
else {
    die "wrong action"
}

samples/xor.pl  view on Meta::CPAN

#!/usr/bin/perl

use strict;
use warnings;

use AI::FANN qw(:all);

if ($ARGV[0] eq 'train') {

    # create an ANN with 2 inputs, a hidden layer with 3 neurons and an
    # output layer with 1 neuron:
    my $ann = AI::FANN->new_standard(2, 3, 1);

    $ann->hidden_activation_function(FANN_SIGMOID_SYMMETRIC);
    $ann->output_activation_function(FANN_SIGMOID_SYMMETRIC);

    # create the training data for a XOR operator:
    my $xor_train = AI::FANN::TrainData->new( [-1, -1], [-1],
                                              [-1, 1], [1],
                                              [1, -1], [1],
                                              [1, 1], [-1] );

    $ann->train_on_data($xor_train, 500000, 100, 0.0001);

    $ann->save("xor.ann");

}
elsif ($ARGV[0] eq 'test') {

    my $ann = AI::FANN->new_from_file("xor.ann");

    for my $a (-1, 1) {
        for my $b (-1, 1) {
            my $out = $ann->run([$a, $b]);
            printf "xor(%f, %f) = %f\n", $a, $b, $out->[0];
        }
    }

}
else {
    die "bad action\n"
}

t/pods.t  view on Meta::CPAN

#!/usr/bin/perl

use strict;
use Test::More;

plan skip_all => "Only the author needs to check that POD docs are right"
    unless eval "no warnings; getlogin eq 'salva'";

eval "use Test::Pod 1.00";
plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;

all_pod_files_ok( all_pod_files( qw(blib) ) );

typemap  view on Meta::CPAN

enum fann_activationfunc_enum	T_UV

enum fann_train_enum    T_FANN_TRAIN_ENUM
enum fann_activationfunc_enum   T_FANN_ACTIVATIONFUNC_ENUM
enum fann_errorfunc_enum    T_FANN_ERRORFUNC_ENUM
enum fann_stopfunc_enum T_STOPFUNC_ENUM

INPUT

T_PTROBJ_MAGIC
	$var = ($type)_sv2obj(aTHX_ $arg, \"${type}\", 1);

T_FTA_INPUT
	$var = _sv2fta(aTHX_ $arg, self->num_input, WANT_MORTAL, \"${var}\");

T_FTA_OUTPUT
	$var = _sv2fta(aTHX_ $arg, self->num_output, WANT_MORTAL, \"${var}\");

T_FANN_TRAIN_ENUM
    $var = _sv2fann_train_enum($arg)

T_FANN_ACTIVATIONFUNC_ENUM
    $var = _sv2fann_activationfunc_enum($arg)

T_FANN_ERRORFUNC_ENUM
    $var = _sv2fann_errorfunc_enum($arg)

T_STOPFUNC_ENUM
    $var = _sv2fann_stopfunc_enum($arg)


OUTPUT

T_PTROBJ_MAGIC
	$arg = _obj2sv(aTHX_ $var, ST(0), "$type");

T_FTA_OUTPUT
	$arg = _fta2sv(aTHX_ $var, self->num_output);

T_FANN_TRAIN_ENUM
    $arg = _fann_train_enum2sv($var);

T_FANN_ACTIVATIONFUNC_ENUM
    $arg = _fann_activationfunc_enum2sv($var);

T_FANN_ERRORFUNC_ENUM
    $arg = _fann_errorfunc_enum2sv($var);

T_STOPFUNC_ENUM
    $arg = _fann_stopfunc_enum2sv($var);



( run in 1.085 second using v1.01-cache-2.11-cpan-4d50c553e7e )