in native/build/api.pl [125:215]
sub cNativeApi {
# Only check C source files
return if $_ !~ /\.c$/;
my $file = $_;
my ($m, $signature, $type, $args, $ret, $class, $method);
print "Checking C API file $file\n" if $verbose;
open(IN, "<$file") or do {
print "ERROR: Ignoring file '$file', could not open file for read: $!\n";
return;
};
while(<IN>) {
# Example declaration:
#TCN_IMPLEMENT_CALL(jlong, Socket, create)(TCN_STDARGS, jint family,
# jint type, jint protocol,
# jlong pool)
if ($_ =~ /^\s*$C_NATIVE_DECLARATION\s*/o) {
chomp();
$signature = $_;
# Concat next line until signature is complete
while($signature !~ /\([^\)]*\)\s*\([^\)]*\)/ && $signature !~ /;/ && ($_ = <IN>)) {
chomp();
$signature .= $_;
}
# Strip C-style comments. See: "perldoc -q comment"
$signature =~ s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse;
# Save one declaration
if ($signature =~ /^\s*$C_NATIVE_DECLARATION\s*\(([^\)]*)\)\s*\(([^\)]*)\)/) {
($type, $args) = ($1, $2);
# Normalize return type and method name
# Collapse multiple spaces
$type =~ s/\s+/ /g;
# Remove spaces around commas
$type =~ s/, /,/g;
$type =~ s/ ,/,/g;
# Trim spaces at start and end
$type =~ s/^ //;
$type =~ s/ $//;
($ret, $class, $method) = split(/,/, $type);
# Map return type
$ret = mapTypes($ret);
# Normalize argument list
# Collapse multiple spaces
$args =~ s/\s+/ /g;
# Remove spaces around commas
$args =~ s/, /,/g;
$args =~ s/ ,/,/g;
# Remove argument names, only types are needed
$args =~ s/ [^, ]+//g;
# Trim spaces at start and end
$args =~ s/^ //;
$args =~ s/ $//;
# Remove leading JNI arguments macro
$args =~ s/^$C_NATIVE_ARGUMENTS,?//o;
# Map argument list types
$args = mapTypes($args);
$m = $cSignature{$class};
if (!defined($m)) {
$m = $cSignature{$class} = {};
}
if (exists($m->{$method}) && ($m->{$method}->{return} ne $ret || $m->{$method}->{args} ne $args)) {
print "ERROR: C native file $file method $method in class $class will be overwritten!";
print "\tOld signature: '$m->{$method}->{return} $m->{$method}->{method}($m->{$method}->{args})\n";
print "\tNew signature: '$ret $method($args)\n";
}
# XXX Use method plus ret plus args as key instead
$m = $m->{$method} = {};
$m->{method} = $method;
$m->{return} = $ret;
$m->{args} = $args;
print "\tFound C API in $file class $class: '$m->{return} $m->{method}($m->{args})'\n" if $verbose;
} else {
print "ERROR: Incomplete C signature in file $file ignored in '$signature'";
}
}
}
close(IN);
}