A few bug fixes.

diff --git a/tools/winapi/config.pm b/tools/winapi/config.pm
index 3d950e6..26c56f3 100644
--- a/tools/winapi/config.pm
+++ b/tools/winapi/config.pm
@@ -93,9 +93,16 @@
     local $_ = shift;
 
     foreach my $dir (split(m%/%, $current_dir)) {
-	s%^(\.\./)*\.\./$dir/%%;
-	if(defined($1)) {
-	    $_ = "$1$_";
+	if(s%^(\.\./)*\.\./$dir/%%) {
+	    if(defined($1)) {
+		$_ = "$1$_";
+	    }
+	}
+    }
+
+    while(m%^(.*?)([^/\.]+)/\.\./(.*?)$%) {
+	if($2 ne "." && $2 ne "..") {
+	    $_ = "$1$3";
 	}
     }
 
diff --git a/tools/winapi/make_filter b/tools/winapi/make_filter
index 03c6aac..8278270 100755
--- a/tools/winapi/make_filter
+++ b/tools/winapi/make_filter
@@ -7,11 +7,14 @@
     require "$1/winapi/setup.pm";
 }
 
-use config qw($current_dir $wine_dir);
+use config qw(
+    &file_absolutize &file_normalize
+    $current_dir $wine_dir
+);
 use output qw($output);
 use make_filter_options qw($options);
 
-use make_parser;
+use make_parser qw($directory $tool $file $line $message);
 
 if($options->progress) {
     $output->enable_progress;
@@ -23,7 +26,7 @@
 # main
 ########################################################################
 
-my $command = join(" ", $options->arguments);
+my $command = $options->make . " " . join(" ", $options->arguments);
 open(IN, "($command) 2>&1 |");
 
 while(<IN>) {    
@@ -33,35 +36,32 @@
 	next;
     }
 
-    my $directory = &make_parser::directory();
-    my $file = &make_parser::file_name();
-    my $line = &make_parser::file_line();
-    my $message = &make_parser::message();
-
-    if(&make_parser::tool() eq "make") {
-	if($directory && $directory ne ".") {
-	    $output->progress("$directory: make");
-	}
-    } elsif($message) {
+    if($message) {
 	if($file && $line) {
-	    if($directory) {
-		$output->write("$directory/$file:$line: $message\n");
+	    if($directory && $directory ne ".") {
+		$output->write(&file_normalize("$directory/$file") . ":$line: $message\n");
 	    } else {
 		$output->write("$file:$line: $message\n");
 	    }
 	} elsif($file) {
-	    if($directory) {
-		$output->write("$directory/$file: $message\n");
+	    if($directory && $directory ne ".") {
+		$output->write(&file_normalize("$directory/$file") . ": $message\n");
 	    } else {
 		$output->write("$file: $message\n");
 	    }
 	} else {
-	    if($directory) {
-		$output->write("$directory: " . &make_parser::tool() . ": $message\n");
+	    if($directory && $directory ne ".") {
+		$output->write("$directory: $tool: $message\n");
+	    } elsif($tool) {
+		$output->write("$tool: $message\n");
 	    } else {
-		$output->write(".: " . &make_parser::tool() . ": $message\n");
+		$output->write("$message\n");
 	    }
 	}
+    } elsif($tool eq "make") {
+	if($directory && $directory ne ".") {
+	    $output->progress("$directory: make");
+	}
     }
 }
 
diff --git a/tools/winapi/make_filter_options.pm b/tools/winapi/make_filter_options.pm
index ceecd77..98f3bec 100644
--- a/tools/winapi/make_filter_options.pm
+++ b/tools/winapi/make_filter_options.pm
@@ -10,7 +10,7 @@
 @EXPORT = qw();
 @EXPORT_OK = qw($options);
 
-use options qw($options &parse_comma_list);
+use options qw($options &parse_comma_list &parse_value);
 
 my %options_long = (
     "debug" => { default => 0, description => "debug mode" },
@@ -19,6 +19,9 @@
 
     "progress" => { default => 1, description => "show progress" },
 
+    "make" => { default => "make",
+		parser => \&parse_value,
+		description => "use which make" },
     "pedantic" => { default => 0, description => "be pedantic" },
 );
 
diff --git a/tools/winapi/make_parser.pm b/tools/winapi/make_parser.pm
index 63037d9..124f539 100644
--- a/tools/winapi/make_parser.pm
+++ b/tools/winapi/make_parser.pm
@@ -2,32 +2,39 @@
 
 use strict;
 
+use strict;
+
+use setup qw($current_dir $wine_dir $winapi_dir $winapi_check_dir);
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT = qw();
+@EXPORT_OK = qw($directory $tool $file $line $message);
+
+use vars qw($directory $tool $file $line $message);
+
 use output qw($output);
+use options qw($options);
 
 ########################################################################
 # global
 ########################################################################
 
 my $current; 
-my $tool;
-my $directory;
-my $file;
-my $line;
 my $function;
-my $message;
-
-sub directory { return $directory; }
-sub tool { return $tool; }
-sub file_name { return $file; }
-sub file_line { return $line; }
-sub message { return $message; }
 
 ########################################################################
 # error
 ########################################################################
 
 sub error {
-    $output->write("make_filter: $tool: can't parse output: '$current'\n");
+    if(defined($tool)) {
+	$output->write("make_filter: $tool: can't parse output: '$current'\n");
+    } else {
+	$output->write("make_filter: <>: can't parse output: '$current'\n");
+    }
     exit 1;
 }
 
@@ -50,40 +57,52 @@
 
 	$function = "";
 
-	my $progress = "$directory: $tool: ";
-	if($#$read_files >= 0) {
-	    $progress .= "read[" . join(" ", @{$read_files}) . "]";
-	}
-	if($#$write_files >= 0) {
-	    if($#$read_files >= 0) {
-		$progress .= ", ";
-	    }	       
-	    $progress .= "write[" . join(" ", @{$write_files}) . "]";
-	}
-	if($#$remove_files >= 0) {
-	    if($#$read_files >= 0 || $#$write_files >= 0) {
-		$progress .= ", ";
-	    }	       
-	    $progress .= "remove[" . join(" ", @{$remove_files}) . "]";
-	}
-
 	if($tool =~ /^cd|make$/) {
 	    # Nothing
 	} elsif($tool =~ /^ld$/) {
-	    $progress =~ s/read\[.*?\]/read[*.o]/; # FIXME: Kludge
-	    $output->progress($progress)
+	    foreach my $file (@{$read_files}) {
+		$output->lazy_progress("$directory: ld: reading '$file'");
+	    }
+	    my $file = $$write_files[0];
+	    $output->progress("$directory: ld: writing '$file'");
+	} elsif($tool =~ /^rm$/) {
+	    foreach my $file (@{$remove_files}) {
+		$output->lazy_progress("$directory: rm: removing '$file'");
+	    }
 	} else {
-	    $output->progress($progress)
+	    my $progress = "$directory: $tool: ";
+	    if($#$read_files >= 0) {
+		$progress .= "read[" . join(" ", @{$read_files}) . "]";
+	    }
+	    if($#$write_files >= 0) {
+		if($#$read_files >= 0) {
+		    $progress .= ", ";
+		}	       
+		$progress .= "write[" . join(" ", @{$write_files}) . "]";
+	    }
+	    if($#$remove_files >= 0) {
+		if($#$read_files >= 0 || $#$write_files >= 0) {
+		    $progress .= ", ";
+		}	       
+		$progress .= "remove[" . join(" ", @{$remove_files}) . "]";
+	    }
+	    
+	    $output->progress($progress);
 	}
-
 	return 0;
     }
 
     if(/^Wine build complete\.$/) {
 	# Nothing
-    } elsif(s/^make\[(\d+)\]:\s*//) {
+    } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
+	$message = "$_";
+    } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
+	$message = "$_";
+    } elsif(s/^make(?:\[(\d+)\])?:\s*//) {
 	$tool = "make";
 	make_output($1, $_);
+    } elsif(!defined($tool)) {
+	error();
     } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
 	# Nothing
     } elsif($tool eq "gcc" && /^In file included from (.+?):(\d+):$/) {
@@ -101,7 +120,7 @@
     } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
 	parse_cd_output($_);
     } else {
-	error($_)
+	error();
     }
     
     $file =~ s/^\.\///;
@@ -123,7 +142,7 @@
     if(0) {
 	# Nothing
     } elsif(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
-	# Nothing
+	$message = "$_";
     } elsif(/^\*\*\* Warning:\s+/) { # 
 	if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
 	    # Nothing
@@ -150,7 +169,9 @@
 	    }
 	}
 	$directory = join("/", @components);
-    } elsif(/^Nothing to be done for \`(.*?)\'.$/) {
+    } elsif(/^(.*?) is older than (.*?), please rerun (.*?)\$/) {
+	# Nothing
+    } elsif(/^Nothing to be done for \`(.*?)\'\.$/) {
 	# Nothing
     } elsif(s/^warning:\s+//) {
 	if(/^Clock skew detected.  Your build may be incomplete.$/) {
@@ -378,6 +399,8 @@
 
 	    if(0) {
 		# Nothing
+	    } elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
+		$supress = 0;
 	    } elsif(/^\(near initialization for \`(.*?)\'\)$/) {
 		$supress = 0;
 	    } elsif(/^\`(.*?)\' defined but not used$/) {
@@ -386,10 +409,16 @@
 		$supress = 0;
 	    } elsif(/^\`%x\' yields only last 2 digits of year in some locales$/) {
 		$supress = 1;
-	    } elsif(/^(.*?) format, different type arg \(arg (\d+)\)$/) {
+	    } elsif(/^assignment makes integer from pointer without a cast$/) {
+		$supress = 0;
+	    } elsif(/^assignment makes pointer from integer without a cast$/) {
 		$supress = 0;
 	    } elsif(/^assignment from incompatible pointer type$/) {
 		$supress = 0;
+	    } elsif(/^cast from pointer to integer of different size$/) {
+		$supress = 0;
+	    } elsif(/^comparison between pointer and integer$/) {
+		$supress = 0;
 	    } elsif(/^comparison between signed and unsigned$/) {
 		$supress = 0;
 	    } elsif(/^comparison of unsigned expression < 0 is always false$/) {
@@ -406,18 +435,28 @@
 		$supress = 0;
 	    } elsif(/^initialization from incompatible pointer type$/) {
 		$supress = 0;
+	    } elsif(/^initialization makes pointer from integer without a cast$/) {
+		$supress = 0;
 	    } elsif(/^missing initializer$/) {
 		$supress = 0;
 	    } elsif(/^ordered comparison of pointer with integer zero$/) {
 		$supress = 0;
-	    } elsif(/^passing arg (\d+) of pointer to function from incompatible pointer type$/) {
+	    } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') from incompatible pointer type$/) {
 		$supress = 0;
-	    } elsif(/^passing arg (\d+) of \`(\S+)\' from incompatible pointer type$/) {
+	    } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes integer from pointer without a cast$/) {
 		$supress = 0;
-	    } elsif(/^passing arg (\d+) of \`(\S+)\' makes integer from pointer without a cast$/) {
+	    } elsif(/^passing arg (\d+) of (?:pointer to function|\`(\S+)\') makes pointer from integer without a cast$/) {
+		$supress = 0;
+	    } elsif(/^return makes integer from pointer without a cast$/) {
+		$supress = 0;
+	    } elsif(/^return makes pointer from integer without a cast$/) {
 		$supress = 0;
 	    } elsif(/^type of \`(.*?)\' defaults to \`(.*?)\'$/) {
 		$supress = 0;
+	    } elsif(/^unused variable \`(.*?)\'$/) {
+		$supress = 0;
+	    } elsif(!$options->pedantic) {
+		$supress = 0;
 	    } else {
 		error();
 	    }
@@ -435,11 +474,17 @@
 	    $message = "$_";
 	} elsif(/^\(Each undeclared identifier is reported only once$/) {
 	    $message = "$_";
+	} elsif(/^conflicting types for \`(.*?)\'$/) {
+	    $message = "$_";
 	} elsif(/^for each function it appears in.\)$/) {
 	    $message = "$_";
+	} elsif(/^too many arguments to function$/) {
+	    $message = "$_";
+        } elsif(/^previous declaration of \`(.*?)\'$/) {
+	    $message = "$_";
 	} elsif(/^parse error before `(.*?)'$/) {
 	    $message = "$_";
-	} elsif(/^$/) {
+	} elsif(!$options->pedantic) {
 	    $message = "$_";
 	} else {
 	    error();
diff --git a/tools/winapi/options.pm b/tools/winapi/options.pm
index ac6d061..b0fdd4d 100644
--- a/tools/winapi/options.pm
+++ b/tools/winapi/options.pm
@@ -7,13 +7,16 @@
 
 @ISA = qw(Exporter);
 @EXPORT = qw();
-@EXPORT_OK = qw($options &parse_comma_list);
+@EXPORT_OK = qw($options &parse_comma_list &parse_value);
 
 use vars qw($options);
 
+use output qw($output);
+
 sub parse_comma_list {
     my $prefix = shift;
     my $value = shift;
+
     if(defined($prefix) && $prefix eq "no") {
 	return { active => 0, filter => 0, hash => {} };
     } elsif(defined($value)) {
@@ -27,6 +30,13 @@
     }
 }
 
+sub parse_value {
+    my $prefix = shift;
+    my $value = shift;
+
+    return $value;
+}
+
 package _options;
 
 use strict;
diff --git a/tools/winapi/setup.pm b/tools/winapi/setup.pm
index 9c0961f..e123a7c 100644
--- a/tools/winapi/setup.pm
+++ b/tools/winapi/setup.pm
@@ -12,24 +12,27 @@
 
     use vars qw($current_dir $wine_dir $winapi_dir $winapi_check_dir);
 
-    my $dir;
-    my $tool;
+    my $tool = $0; 
+    $tool =~ s%^(?:.*?/)?([^/]+)$%$1%;
 
-    if($0 =~ m%^((.*?)/?tools/([^/]+))/([^/]+)$%)
+    if(defined($current_dir) && defined($wine_dir) &&
+       defined($winapi_dir) && defined($winapi_check_dir))
     {
-	$winapi_dir = $1;
-	$winapi_check_dir = $1;
-	$dir = $3;
-	$tool = $4;
-	
-	if(defined($2) && $2 ne "")
+	# Nothing
+    } elsif($0 =~ m%^(.*?)/?tools/([^/]+)/[^/]+$%) {
+	my $dir = $2;
+
+	if(defined($1) && $1 ne "")
 	{
-	    $wine_dir = $2;
+	    $wine_dir = $1;
 	} else {
 	    $wine_dir = ".";
 	    
 	} 
-	
+
+	require Cwd;
+	my $cwd = Cwd::cwd();
+
 	if($wine_dir =~ /^\./) {
 	    $current_dir = ".";
 	    my $pwd; chomp($pwd = `pwd`);
@@ -38,19 +41,32 @@
 		$current_dir = "$1/$current_dir";
 	    }
 	    $current_dir =~ s%/\.$%%;
+	} elsif($wine_dir eq $cwd) {
+	    $wine_dir = ".";
+	    $current_dir = ".";
+	} elsif($cwd =~ m%^$wine_dir/(.*?)?$%) {
+	    $current_dir = $1;
+	    $wine_dir = ".";
+	    foreach my $dir (split(m%/%, $current_dir)) {
+		$wine_dir = "../$wine_dir";
+	    }
+	    $wine_dir =~ s%/\.$%%;
+	} else {
+	    print STDERR "$tool: You must run this tool in the main Wine directory or a sub directory\n";
+	    exit 1;
 	}
-	
+
+	$winapi_dir = "$wine_dir/tools/winapi";
 	$winapi_dir =~ s%^\./%%;
-	$winapi_dir =~ s/$dir/winapi/g;
-	
+
+	$winapi_check_dir = "$wine_dir/tools/winapi_check";
 	$winapi_check_dir =~ s%^\./%%;
-	$winapi_check_dir =~ s/$dir/winapi_check/g; 
+
+	push @INC, ($winapi_dir, $winapi_check_dir);
     } else {
 	print STDERR "$tool: You must run this tool in the main Wine directory or a sub directory\n";
 	exit 1;
     }
-
-    push @INC, ($winapi_dir, $winapi_check_dir);
 }
 
 1;