#!/usr/bin/perl -w
use strict;

# 2000/07/09: Fixed an off by one error in the month of the 'last updated' date
# 2005/07/04: Added missing "</p>" (Thanks to the html-checker in dillo)
#             Added "." for Libraries to include "*.drv", "*.ocx" and other
#             Changed Ignore-List

my @ignore_list=qw(winealsa.drv
                   winearts.drv
                   wineaudioio.drv
                   wined3d
                   winedos
                   winejack.drv
                   winemp3.acm
                   winenas.drv
                   wineoss.drv
                   wineps.drv
                   wineps16.drv
                   winex11.drv);

sub print_library_stats($$$$)
{
    my ($name, $api_count, $stub_count, $pseudo_stub_count)=@_;
    return if ($api_count == 0);

    #print "Match: name=$name\n";
    #print " api_count=$api_count\n";
    #print " stub_count=$stub_count\n";
    #print " pseudo_stub_count=$pseudo_stub_count\n";

    print "<tr>\n";
    print "  <td>$name</td>\n";
    print "  <td align=\"center\">$api_count</td>\n";
    printf "  <td align=\"center\"><span class=\"error\">%2.0f%%</span></td>\n",($api_count-$stub_count-$pseudo_stub_count)*100/$api_count;
    printf "  <td><span class=\"error\">%d</span> = <span class=\"warning\">%d</span> + <span class=\"warning\">%d</span></td>\n",$stub_count+$pseudo_stub_count,$stub_count,$pseudo_stub_count;
    print "</tr>\n";
}

my %dlls;
my $api_count=0;
my $stub_count=0;
my $pseudo_stub_count=0;

my %ignored=();
foreach my $ignored_module (@ignore_list)
{
    $ignored{$ignored_module}=1;
}

while (<>)
{
    if (/^\*.c: ([a-zA-Z0-9_.]+): [0-9]+ of ([0-9]+) functions are stubs \(([0-9]+) real, ([0-9]+) pseudo\)/) {
        next if (defined $ignored{$1});
        my @counts=($2,$3,$4);
        $dlls{$1}=\@counts;
        $api_count+=$2;
        $stub_count+=$3;
        $pseudo_stub_count+=$4;
    }
}

my ($day,$month,$year)=(localtime)[3,4,5];
$month+=1;
$year+=1900;

print <<__EOF__
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
<header>
  <!--#include virtual="/share/header.html" -->
  <title>Wine</title>
  <style type="text/css">
<!--
.error { color: #880000; }
.warning { color: #d74000; }
-->
  </style>
</header>
<body bgcolor="white">
<!--#include virtual="/share/bodys-en.shtml" -->

<h1>Wine</h1>
<br><br><br><br>

<h2>Quick API statistics</h2>


<p>Here are the stats I generated out of the new results provided by Patrik
Stridvall's winapi_check. Before anyone jumps to the stats and starts
quoting them I would like to point out that they only tell a small part of
the story and thus should be taken with a big grain of salt. In particular:
<ul>
  <li>Not all applications use all the Windows APIs. In fact one can expect
    that 80% of the applications use only 20% of the APIs (or something
    like this). So it's not because Wine only implements x% of the APIs that
    only x%, with the same x, of the applications will run in Wine. If you
    look well, you'll see that the coverage for gdi, gdi32, kernel,
    kernel32, user and user32 is above average which is logical since these
    are the DLLs that most applications use.
  <li>It's not because a particular API is not implemented that the
    application will not work. First the application may well not call this
    API in most normal circumstances. Then even if it is called and it
    returns an error code (or a fake success result), the application may
    carry on with little or no effect for the user.
  <li>Reciprocally, it's not because an API is implemented that it is
    implemented correctly. Some APIs may be considered implemented although
    they reproduce the function's behavior correctly in only some cases. So
    you cannot point at these figures and say that a specific DLL has been
    reimplemented at 100%. You'll have to look at the code for that.
  <li>This chart does not take the COM aspect of things into account very
    well. Most COM functions are not exported since they are accessed via
    the corresponding interface's method table. So these statistics will
    not tell you which percentage of the COM functionalities is implemented.
</ul>

<p>Finally here's a word about how this is all computed. winapi_check
analyzes the contents of Wine's spec files which list all the entry-point
(APIs) present in a DLL. This gives the per library API count in the second
column. The Spec file also specifies for each API whether there is a
function that implements it. If not we say this entry-point is a 'regular'
stub. Some APIs are implemented but all the implementation does is print a
warning: 'FIXME("stub");' (and returns either a fake success code or an
error which is enough to get some applications to work). winapi_check also
detects these and reports them as pseudo stubs. So the second column is the
percentage of APIs of a dll which have been implemented, i.e. are neither
regular nor pseudo stubs. The last column indicates how many stubs there
are and their repartition between regular and pseudo stubs.

<p>You can download the script right <a href="winapi_stats">here</a>. Then,
to take it for a ride, type:
<pre>
./tools/winapi/winapi_extract --pseudo-stub-statistics --no-verbose --no-progress 2>&1 | tee winapi_stats.txt | winapi_stats >winapi_stats.html
</pre>

<p><i>The <a href="winapi_stats.txt">text file</a> is nice if you decide to
tweak the script as an afterthought or if you want to diff it against an
older version to see what has changed</i>

<p><br>
<center>Last updated: $year/$month/$day
<br>
<table border="1" cellspacing="0" cellpadding="3">
<tr>
  <td>Library</td>
  <td>API Count</td>
  <td>% Implemented</td>
  <td>Stubs (total=regular+pseudo)</td>
</tr>
__EOF__
;

print_library_stats("Total",$api_count,$stub_count,$pseudo_stub_count);

print "<tr>\n";
print "  <td colspan=\"4\" height=\"20\">&nbsp;</td>\n";
print "</tr>\n";

foreach my $dll (sort keys %dlls)
{
    my $counts=$dlls{$dll};
    #print "$dll $counts->[0] $counts->[1] $counts->[2]\n";
    print_library_stats($dll,$counts->[0],$counts->[1],$counts->[2]);
}

print "</table>\n";
print "</center>\n";

print "<p>\n";
print "<!--#include virtual=\"/share/bodye-en.shtml\" -->\n";
print "</p></body>\n";
