sub javaNativeApi()

in native/build/api.pl [218:302]


sub javaNativeApi {

    # Only check Java source files
    return if $_ !~ /\.java$/;

    my $file = $_;
    my ($m, $signature, $type, $args, $ret, $class, $method);

    print "Checking Java API file $file\n" if $verbose;
    open(IN, "<$_") or do {
        print "ERROR: Ignoring file '$file', could not open file for read: $!\n";
        return;
    };

    $class = $file;
    $class =~ s/\.java$//;

    while(<IN>) {

        # Example declaration
        #public static native long uid(String username, long p)
        #       throws Error;
        if ($_ =~ /^\s*((public|protected|private)\s+)?([^\(]*)\(/ && ($type = $3) && $type =~ /\snative\s/) {
            chomp();
            $signature = $_;
            # Concat next line until signature is complete
            while($signature !~ /\([^\)]*\)/ && $signature !~ /;/ && ($_ = <IN>)) {
                chomp();
                $signature .= $_;
            }

            # Save one declaration
            if ($signature =~ /^\s*([^\(]+)\(([^\)]*)\)/) {
                ($type, $args) = ($1, $2);

                # Normalize return type and method name
                # Remove unused specifiers
                $type =~ s/\b(public|protected|private)\b//g;
                $type =~ s/\bnative\b//g;
                $type =~ s/\bstatic\b//g;
                # Collapse multiple spaces
                $type =~ s/\s+/ /g;
                # Trim spaces at start and end
                $type =~ s/^ //;
                $type =~ s/ $//;

                ($ret, $method) = split(/\s+/, $type);

                # Normalize argument list
                # Collapse multiple spaces
                $args =~ s/\s+/ /g;
                # Remove spaces around commas
                $args =~ s/, /,/g;
                $args =~ s/ ,/,/g;
                # Remove spaces in front of array "[]"
                $args =~ s/ \[\]/[]/g;
                # Remove argument names, only types are needed
                $args =~ s/ [^, ]+//g;
                # Trim spaces at start and end
                $args =~ s/^ //;
                $args =~ s/ $//;

                $m = $javaSignature{$class};
                if (!defined($m)) {
                    $m = $javaSignature{$class} = {};
                }
                if (exists($m->{$method})) {
                    print "ERROR: Java 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 native Java API in $file class $class: '$m->{return} $m->{method}($m->{args})'\n" if $verbose;
            } else {
                print "ERROR: Incomplete Java signature in file $file ignored in '$signature'";
            }
        }
    }

    close(IN);
}