#!/usr/bin/perl -w

#
#  This software may be used and distributed according to the terms
#  of the GNU General Public License, incorporated herein by reference.
#
#  Copyright 2004-2007 Michael Stefaniuc
#  - idea and code from Vincent Béron's original wine_crosscalls.pl script


use smatch;
use strict;

my $func_called;

# Hash with ASCII functions to ignore as it is ok to call them. We are
# interested only in the key and not the value.
my %ignore = (
		'lstrcatA' => '1',
		'lstrcpyA' => '1',
		'lstrcpynA' => '1',
		'lstrlenA' => '1',
	     );

sub merge($$$) {
    my ($name, $one, $two) = @_;
    if (($one =~ /^functionW$/) or ($two =~ /^functionW$/)){
	return "functionW";
    }
    return "__none";
}
add_merge_function(\&merge);

sub error_msg($) {
    my $msg = shift;
    print get_filename(), " ", get_lineno(), " ", get_func_pos(),
    		" call to $msg\n";
}

sub false_positive() {
    # We ignore tests for now. They are application code.
    my $filename = get_filename();
    if ($filename =~ m,/tests/,) {
	return 1;
    }
    # Ignore also *AW functions.
    my $funcname = get_cur_func();
    if ($funcname =~ /AW$/) {
	# We could miss here some function like *DRAW but found that
	# only in tests which we exclude anyway.
	return 1;
    }
    if (exists($ignore{$func_called})) {
	return 1;
    }
    return 0;
}


while(my $data = get_data()){
    if (($data =~ /^function_decl/) and (get_cur_func() =~ /W$/)) {
	set_state("functionW");
    }
    elsif (get_state() =~ /^functionW$/) {
	my $tmp = $data;
	while ($tmp =~ /call_expr\(\(addr_expr function_decl\(([^\)]*?)\)(.*)/) {
	    $func_called = $1;
	    $tmp = $2;
	    if ($func_called =~ /(.*?)A$/ and !false_positive()) {
		error_msg($func_called);
	    }
	}
    }
}

