Made a new improved version of winapi-check in perl.

diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm
new file mode 100644
index 0000000..efadd5b
--- /dev/null
+++ b/tools/winapi_check/winapi_options.pm
@@ -0,0 +1,272 @@
+package winapi_options;
+
+use strict;
+
+
+sub parser_comma_list {
+    my $prefix = shift;
+    my $value = shift;
+    if(defined($prefix) && $prefix eq "no") {
+	return { active => 0, filter => 0, hash => {} };
+    } elsif(defined($value)) {
+	my %names;
+	for my $name (split /,/, $value) {
+	    $names{$name} = 1;
+	}
+	return { active => 1, filter => 1, hash => \%names };
+    } else {
+	return { active => 1, filter => 0, hash => {} };
+    }
+}
+
+my %options = (
+    "debug" => { default => 0, description => "debug mode" },
+    "help" => { default => 0, description => "help mode" },
+    "verbose" => { default => 0, description => "verbose mode" },
+
+    "win16" => { default => 1, description => "Win16 checking" },
+    "win32" => { default => 1, description => "Win32 checking" },
+
+    "shared" =>  { default => 0, description => "show shared functions between Win16 and Win32" },
+    "shared-segmented" =>  { default => 0, description => "segmented shared functions between Win16 and Win32 checking" },
+
+    "local" =>  { default => 1, description => "local checking" },
+    "module" => { 
+	default => { active => 1, filter => 0, hash => {} },
+	parent => "local",
+	parser => \&parser_comma_list,
+	description => "module filter"
+    },
+
+    "argument" => { default => 1, parent => "local", description => "argument checking" },
+    "argument-count" => { default => 1, parent => "argument", description => "argument count checking" },
+    "argument-forbidden" => {
+	default => { active => 0, filter => 0, hash => {} },
+	parent => "argument",
+	parser => \&parser_comma_list,
+	description => "argument forbidden checking"
+    },
+    "argument-kind" => {
+	default => { active => 0, filter => 0, hash => {} },
+	parent => "argument",
+	parser => \&parser_comma_list,
+	description => "argument kind checking"
+    },
+    "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" },
+    "misplaced" => { default => 0, parent => "local", description => "checking for misplaced functions" },
+             
+    "global" => { default => 1, description => "global checking" }, 
+    "declared" => { default => 1, parent => "global", description => "declared checking" }, 
+    "implemented" => { default => 0, parent => "global", description => "implemented checking" }
+
+);
+
+my %short_options = (
+    "d" => "debug",
+    "?" => "help",
+    "v" => "verbose"
+);
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = {};
+    bless ($self, $class);
+
+    my $refarguments = shift;
+    my @ARGV = @$refarguments;
+
+    for my $name (sort(keys(%options))) {
+        my $option = $options{$name};
+	my $key = uc($name);
+	$key =~ tr/-/_/;
+	$$option{key} = $key;
+	my $refvalue = \${$self->{$key}};
+	$$refvalue = $$option{default};
+    }
+
+    my $files = \@{$self->{FILES}};
+    my $module = \${$self->{MODULE}};
+    my $global = \${$self->{GLOBAL}};
+
+    while(defined($_ = shift @ARGV)) {
+	if(/^-([^=]*)(=(.*))?$/) {
+	    my $name;
+	    my $value;
+	    if(defined($2)) {
+		$name = $1;
+		$value = $3;
+            } else {
+		$name = $1;
+	    }
+	    
+	    if($name =~ /^([^-].*)$/) {
+		$name = $short_options{$1};
+	    } else {
+		$name =~ s/^-(.*)$/$1/;
+	    }
+	    	   
+	    my $prefix;
+	    if($name =~ /^no-(.*)$/) {
+		$name = $1;
+		$prefix = "no";
+		if(defined($value)) {
+		    print STDERR "<internal>: options with prefix 'no' can't take parameters\n";
+		    exit 1;
+		}
+	    }
+
+	    my $option = $options{$name};
+	    if(defined($option)) {
+		my $key = $$option{key};
+		my $parser = $$option{parser};
+		my $refvalue = \${$self->{$key}};
+	      	       
+		if(defined($parser)) { 
+		    $$refvalue = &$parser($prefix,$value);
+		} else {
+		    if(defined($value)) {
+			$$refvalue = $value;
+		    } elsif(!defined($prefix)) {
+			$$refvalue = 1;
+		    } else {
+			$$refvalue = 0;
+		    }
+		}
+		next;
+	    }	 
+	}
+	
+	if(/^--module-dlls$/) {
+	    my @dirs = `cd dlls && find ./ -type d ! -name CVS`;
+	    my %names;
+	    for my $dir (@dirs) {
+		chomp $dir;
+		$dir =~ s/^\.\/(.*)$/$1/;
+		next if $dir eq "";
+		$names{$dir} = 1;
+	    }
+	    $$module = { active => 1, filter => 1, hash => \%names };
+	}	
+	elsif(/^-(.*)$/) {
+	    print STDERR "<internal>: unknown option: $&\n"; 
+	    print STDERR "<internal>: usage: winapi-check [--help] [<files>]\n";
+	    exit 1;
+	} else {
+	    push @$files, $_;
+	}
+    }
+
+    if($#$files == -1) {
+	@$files = map {
+	    s/^.\/(.*)$/$1/;
+	    $_; 
+	} split(/\n/, `find . -name \\*.c`);
+    } else {
+	$$global = 0
+    }
+ 
+    return $self;
+}
+
+sub show_help {
+    my $self = shift;
+
+    my $maxname = 0;
+    for my $name (sort(keys(%options))) {
+	if(length($name) > $maxname) {
+	    $maxname = length($name);
+	}
+    }
+
+    print "usage: winapi-check [--help] [<files>]\n";
+    print "\n";
+    for my $name (sort(keys(%options))) {
+	my $option = $options{$name};
+        my $description = $$option{description};
+	my $default = $$option{default};
+	
+	my $output;
+	if(ref($default) ne "HASH") {
+	    if($default) {
+		$output = "--no-$name";
+	    } else {
+		$output = "--$name";
+	    }
+	} else {
+	    if($default->{active}) {
+		$output = "--[no-]$name\[=<value>]";
+	    } else {
+		$output = "--$name\[=<value>]";
+	    }
+	}
+
+	print "$output";
+	for (0..(($maxname - length($name) + 14) - (length($output) - length($name) + 1))) { print " "; }
+	if(ref($default) ne "HASH") {
+	    if($default) {
+		print "Disable $description\n";
+	    } else {
+		print "Enable $description\n";
+	    }    
+	} else {
+	    if($default->{active}) {
+		print "(Disable) $description\n";
+	    } else {
+		print "Enable $description\n";
+	    }
+
+
+	}
+    }
+}
+
+sub AUTOLOAD {
+    my $self = shift;
+
+    my $name = $winapi_options::AUTOLOAD;
+    $name =~ s/^.*::(.[^:]*)$/\U$1/;
+
+    my $refvalue = $self->{$name};
+    if(!defined($refvalue)) {
+	die "<internal>: winapi_options.pm: member $name does not exists\n"; 
+    }
+    return $$refvalue;
+}
+
+sub files { my $self = shift; return @{$self->{FILES}}; }
+
+sub report_module {
+    my $self = shift;
+    my $module = $self->module;
+    
+    my $name = shift;
+
+    if(defined($name)) {
+	return $module->{active} && (!$module->{filter} || $module->{hash}->{$name}); 
+    } else {
+	return 0;
+    } 
+}
+
+sub report_argument_forbidden {
+    my $self = shift;   
+    my $argument_forbidden = $self->argument_forbidden;
+
+    my $type = shift;
+
+    return $argument_forbidden->{active} && (!$argument_forbidden->{filter} || $argument_forbidden->{hash}->{$type}); 
+}
+
+sub report_argument_kind {
+    my $self = shift;
+    my $argument_kind = $self->argument_kind;
+
+    my $kind = shift;
+
+    return $argument_kind->{active} && (!$argument_kind->{filter} || $argument_kind->{hash}->{$kind}); 
+
+}
+
+1;
+