SOOT
view release on metacpan or search on metacpan
inc/inc_ExtUtils-XSpp/ExtUtils/XSpp/Node/Function.pm view on Meta::CPAN
# /* anything */
#
# Or: (style=ansi)
#
# return_type
# class_name::function_name( type arg1 = def, type arg2 = def, ... )
# PREINIT:
# (rest as above)
sub print {
my $this = shift;
my $state = shift;
my $out = '';
my $fname = $this->perl_function_name;
my $args = $this->arguments;
my $ret_type = $this->ret_type;
my $ret_typemap = $this->{TYPEMAPS}{RET_TYPE};
$out .= '#if ' . $this->emit_condition . "\n" if $this->emit_condition;
my( $init, $arg_list, $call_arg_list, $code, $output, $cleanup,
$postcall, $precall ) =
( '', '', '', '', '', '', '', '' );
# compute the precall code, XS argument list and C++ argument list using
# the typemap information
if( $args && @$args ) {
my $has_self = $this->is_method ? 1 : 0;
my( @arg_list, @call_arg_list );
foreach my $i ( 0 .. $#$args ) {
my $arg = ${$args}[$i];
my $t = $this->{TYPEMAPS}{ARGUMENTS}[$i];
my $pc = $t->precall_code( sprintf( 'ST(%d)', $i + $has_self ),
$arg->name );
push @arg_list, $t->cpp_type . ' ' . $arg->name .
( $arg->has_default ? ' = ' . $arg->default : '' );
my $call_code = $t->call_parameter_code( $arg->name );
push @call_arg_list, defined( $call_code ) ? $call_code : $arg->name;
$precall .= $pc . ";\n" if $pc
}
$arg_list = ' ' . join( ', ', @arg_list ) . ' ';
$call_arg_list = ' ' . join( ', ', @call_arg_list ) . ' ';
}
my $retstr = $ret_typemap ? $ret_typemap->cpp_type : 'void';
# special case: constructors with name different from 'new'
# need to be declared 'static' in XS
if( $this->isa( 'ExtUtils::XSpp::Node::Constructor' ) &&
$this->perl_name ne $this->cpp_name ) {
$retstr = "static $retstr";
}
my $has_ret = $ret_typemap && !$ret_typemap->type->is_void;
my $ppcode = $has_ret && $ret_typemap->output_list( '' ) ? 1 : 0;
my $code_type = $ppcode ? "PPCODE" : "CODE";
my $ccode = $this->_call_code( $call_arg_list );
if ($this->isa('ExtUtils::XSpp::Node::Destructor')) {
$ccode = 'delete THIS';
$has_ret = 0;
} elsif( $has_ret && defined $ret_typemap->call_function_code( '', '' ) ) {
$ccode = $ret_typemap->call_function_code( $ccode, 'RETVAL' );
} elsif( $has_ret ) {
$ccode = "RETVAL = $ccode";
}
$code .= " $code_type:\n";
$code .= " try {\n";
if ($precall) {
$code .= ' ' . $precall;
}
$code .= ' ' . $ccode . ";\n";
if( $has_ret && defined $ret_typemap->output_code( '', '' ) ) {
my $retcode = $ret_typemap->output_code( 'ST(0)', 'RETVAL' );
$code .= ' ' . $retcode . ";\n";
}
if( $has_ret && defined $ret_typemap->output_list( '' ) ) {
my $retcode = $ret_typemap->output_list( 'RETVAL' );
$code .= ' ' . $retcode . ";\n";
}
$code .= " }\n";
my @catchers = @{$this->{EXCEPTIONS}};
foreach my $exception_handler (@catchers) {
my $handler_code = $exception_handler->handler_code;
$code .= $handler_code;
}
$output = " OUTPUT: RETVAL\n" if $has_ret;
if( $has_ret && defined $ret_typemap->cleanup_code( '', '' ) ) {
$cleanup .= " CLEANUP:\n";
my $cleanupcode = $ret_typemap->cleanup_code( 'ST(0)', 'RETVAL' );
$cleanup .= ' ' . $cleanupcode . ";\n";
}
if( $this->code ) {
$code = " $code_type:\n " . join( "\n", @{$this->code} ) . "\n";
# cleanup potential multiple newlines because they break XSUBs
$code =~ s/^\s*\z//m;
$output = " OUTPUT: RETVAL\n" if $code =~ m/\bRETVAL\b/;
}
if( $this->postcall ) {
$postcall = " POSTCALL:\n " . join( "\n", @{$this->postcall} ) . "\n";
$output ||= " OUTPUT: RETVAL\n" if $has_ret;
}
if( $this->cleanup ) {
$cleanup ||= " CLEANUP:\n";
my $clcode = join( "\n", @{$this->cleanup} );
$cleanup .= " $clcode\n";
}
if( $ppcode ) {
$output = '';
}
if( !$this->is_method && $fname =~ /^(.*)::(\w+)$/ ) {
my $pcname = $1;
( run in 0.540 second using v1.01-cache-2.11-cpan-4e7a2411597 )