- A few more bug fixes
- Reorganization continues
- New tool (make_filter) for filtering make output added

diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm
index 077ce10..5aa3b3a 100644
--- a/tools/winapi_check/winapi_parser.pm
+++ b/tools/winapi_check/winapi_parser.pm
@@ -3,93 +3,131 @@
 use strict;
 
 use output qw($output);
-use winapi_function;
+use options qw($options);
 
 sub parse_c_file {
-    my $options = shift;
     my $file = shift;
+    my $function_create_callback = shift;
     my $function_found_callback = shift;
+    my $type_create_callback = shift;
+    my $type_found_callback = shift;
     my $preprocessor_found_callback = shift;
 
     # global
     my $debug_channels = [];
 
-    # local
-    my $documentation_line;
-    my $documentation;
-    my $function_line;
-    my $linkage;
-    my $return_type;
-    my $calling_convention;
-    my $internal_name = "";
-    my $argument_types;
-    my $argument_names;
-    my $argument_documentations;
-    my $statements;
-
-    my $function_begin = sub {
-	$documentation_line = shift;
-	$documentation = shift;
-	$function_line = shift;
-	$linkage = shift;
-	$return_type= shift;
-	$calling_convention = shift;
-	$internal_name = shift;
-	$argument_types = shift;
-	$argument_names = shift;
-	$argument_documentations = shift;
-
-	if(defined($argument_names) && defined($argument_types) &&
-	   $#$argument_names == -1)
-	{
-	    foreach my $n (0..$#$argument_types) {
-		push @$argument_names, "";
+    my $in_function = 0;
+    my $function_begin;
+    my $function_end;
+    {
+	my $documentation_line;
+	my $documentation;
+	my $function_line;
+	my $linkage;
+	my $return_type;
+	my $calling_convention;
+	my $internal_name = "";
+	my $argument_types;
+	my $argument_names;
+	my $argument_documentations;
+	my $statements;
+	
+	$function_begin = sub {
+	    $documentation_line = shift;
+	    $documentation = shift;
+	    $function_line = shift;
+	    $linkage = shift;
+	    $return_type= shift;
+	    $calling_convention = shift;
+	    $internal_name = shift;
+	    $argument_types = shift;
+	    $argument_names = shift;
+	    $argument_documentations = shift;
+	    
+	    if(defined($argument_names) && defined($argument_types) &&
+	       $#$argument_names == -1)
+	    {
+		foreach my $n (0..$#$argument_types) {
+		    push @$argument_names, "";
+		}
 	    }
-	}
-
-	if(defined($argument_documentations) &&
-	   $#$argument_documentations == -1)
-	{
-	    foreach my $n (0..$#$argument_documentations) {
-		push @$argument_documentations, "";
+	    
+	    if(defined($argument_documentations) &&
+	       $#$argument_documentations == -1)
+	    {
+		foreach my $n (0..$#$argument_documentations) {
+		    push @$argument_documentations, "";
+		}
 	    }
-	}
+	    
+	    $in_function = 1;
+	};
 
-	$statements = undef;
-    };
-    my $function_end = sub {
-	my $function = 'winapi_function'->new;
+	$function_end = sub {
+	    $statements = shift;
 
-	if(!defined($documentation_line)) {
-	    $documentation_line = 0;
-	}
+	    my $function = &$function_create_callback();
+	    
+	    if(!defined($documentation_line)) {
+		$documentation_line = 0;
+	    }
+	    
+	    $function->file($file);
+	    $function->debug_channels([@$debug_channels]);
+	    $function->documentation_line($documentation_line);
+	    $function->documentation($documentation);
+	    $function->function_line($function_line);
+	    $function->linkage($linkage);
+	    $function->return_type($return_type); 
+	    $function->calling_convention($calling_convention);
+	    $function->internal_name($internal_name);
+	    if(defined($argument_types)) {
+		$function->argument_types([@$argument_types]);
+	    }
+	    if(defined($argument_names)) {
+		$function->argument_names([@$argument_names]);
+	    }
+	    if(defined($argument_documentations)) {
+		$function->argument_documentations([@$argument_documentations]);
+	    }
+	    $function->statements($statements);
+	    
+	    &$function_found_callback($function);
 
-	$function->file($file);
-	$function->debug_channels([@$debug_channels]);
-	$function->documentation_line($documentation_line);
-	$function->documentation($documentation);
-	$function->function_line($function_line);
-	$function->linkage($linkage);
-	$function->return_type($return_type); 
-	$function->calling_convention($calling_convention);
-	$function->internal_name($internal_name);
-	if(defined($argument_types)) {
-	    $function->argument_types([@$argument_types]);
-	}
-	if(defined($argument_names)) {
-	    $function->argument_names([@$argument_names]);
-	}
-	if(defined($argument_documentations)) {
-	    $function->argument_documentations([@$argument_documentations]);
-	}
-	$function->statements($statements);
+	    $in_function = 0;
+	};
+    }
 
-	&$function_found_callback($function);
-	$internal_name = "";
-    };
+    my $in_type = 0;
+    my $type_begin;
+    my $type_end;
+    {
+	my $type;
+
+	$type_begin = sub {
+	    $type = shift;
+	    $in_type = 1;
+	};
+
+	$type_end = sub {
+	    my $names = shift;
+
+	    foreach my $name (@$names) {
+		if($type =~ /^(?:struct|enum)/) {
+		    # $output->write("typedef $type {\n");
+		    # $output->write("} $name;\n");
+		} else {
+		    # $output->write("typedef $type $name;\n");
+		}
+	    }
+	    $in_type = 0;
+	};
+    }
+
     my %regs_entrypoints;
     my @comment_lines = ();
     my @comments = ();
+    my $statements;
     my $level = 0;
     my $extern_c = 0;
     my $again = 0;
@@ -263,8 +301,20 @@
 		$statements .= "$line\n";
 	    }
 
-	    if($internal_name && $level == 0) {
-		&$function_end;
+	    if($level == 0) {
+		if($in_function) {
+		    &$function_end($statements);
+		    $statements = undef;
+		} elsif($in_type) {
+		    if(/^\s*(?:WINE_PACKED\s+)?((?:\*\s*)?\w+\s*(?:\s*,\s*(?:\*+\s*)?\w+)*\s*);/s) {
+			my @parts = split(/\s*,\s*/, $1);
+			&$type_end([@parts]);
+		    } elsif(/;/s) {
+			die "$file: $.: syntax error: '$_'\n";
+		    } else {
+			$lookahead = 1;
+		    }
+		}
 	    }
 	    next;
 	} elsif(/(extern\s+|static\s+)?((struct\s+|union\s+|enum\s+|signed\s+|unsigned\s+)?\w+((\s*\*)+\s*|\s+))
@@ -358,7 +408,8 @@
 			     $function_line, $linkage, $return_type, $calling_convention, $name,
 			     \@argument_types,\@argument_names,\@argument_documentations);
 	    if($level == 0) {
-		&$function_end;
+		&$function_end($statements);
+		$statements = undef;
 	    }
 	} elsif(/__ASM_GLOBAL_FUNC\(\s*(.*?)\s*,/s) {
 	    my @lines = split(/\n/, $&);
@@ -368,95 +419,20 @@
 
 	    &$function_begin($documentation_line, $documentation,
 			     $function_line, "", "void", "__asm", $1);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(GET_X_Y_16|GET_VAL_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s){ 
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my $return16 = $2 . "16";
-	    my $name16 = $3 . "16";
-
-	    $return16 =~ s/^(COLORREF|DWORD)16$/$1/;
-
-	    my @arguments = ("HDC16");
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", $return16, "WINAPI", $name16, \@arguments);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(GET_VAL_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,.*?\)/s) {
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my $return32 = $2;
-	    my $name32 = $3;
-	    my @arguments32 = ("HDC");
-
-	    &$function_end;
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", $return32, "WINAPI", $name32, \@arguments32);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(GET_VAL_EX_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my @arguments16 = ("HDC16", "LP" . $5 . "16");
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", "BOOL16", "WINAPI", $2 . "16", \@arguments16);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(GET_VAL_EX_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my @arguments32 = ("HDC", "LP" . $5);
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", "BOOL", "WINAPI", $2, \@arguments32);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(SET_MODE_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my @arguments16 = ("HDC16", "INT16");
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", "INT16", "WINAPI", $2 . "16", \@arguments16);
-	    $statements = "";
-	    &$function_end;
-	} elsif(/DC_(SET_MODE_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
-	    my @lines = split(/\n/, $&);
-	    my $function_line = $. - scalar(@lines) + 1;
-
-	    $_ = $'; $again = 1;
-
-	    my @arguments32 = ("HDC", "INT");
-	    &$function_begin($documentation_line, $documentation,
-			     $function_line, "", "INT", "WINAPI", $2, \@arguments32);
-	    $statements = "";
-	    &$function_end;
+	    &$function_end("");
 	} elsif(/WAVEIN_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
+	    my @lines = split(/\n/, $&);
+	    my $function_line = $. - scalar(@lines) + 1;
+
 	    $_ = $'; $again = 1;
 	    my @arguments16 = ("HWAVEIN16");
 	    my @arguments32 = ("HWAVEIN");
 	    &$function_begin($documentation_line, $documentation,
 			     $function_line,  "", "UINT16", "WINAPI", "waveIn" . $1 . "16", \@arguments16);
-	    $statements = "";
-	    &$function_end;
+	    &$function_end("");
 	    &$function_begin($documentation_line, $documentation,
 			     $function_line, "", "UINT", "WINAPI", "waveIn" . $1, \@arguments32);
-	    $statements = "";
-	    &$function_end;	    
+	    &$function_end("");
 	} elsif(/WAVEOUT_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
 	    my @lines = split(/\n/, $&);
 	    my $function_line = $. - scalar(@lines) + 1;
@@ -467,11 +443,10 @@
 	    my @arguments32 = ("HWAVEOUT");
 	    &$function_begin($documentation_line, $documentation,
 			     $function_line, "", "UINT16", "WINAPI", "waveOut" . $1 . "16", \@arguments16);
-	    $statements = "";
-	    &$function_end;
+	    &$function_end("");
 	    &$function_begin($documentation_line, $documentation,
 			     $function_line, "", "UINT", "WINAPI", "waveOut" . $1, \@arguments32);	    
-	    &$function_end;
+	    &$function_end("");
 	} elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
 	    my @lines = split(/\n/, $&);
 	    my $function_line = $. - scalar(@lines) + 1;
@@ -483,21 +458,19 @@
 		my @arguments32 = ("HWAVEOUT", $4);
 		&$function_begin($documentation_line, $documentation,
 				 $function_line, "", "UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16);
-		$statements = "";
-		&$function_end;
+		&$function_end("");
 		&$function_begin($documentation_line, $documentation,
 				 $function_line, "", "UINT", "WINAPI", "waveOut" . $2, \@arguments32);
-		&$function_end;
+		&$function_end("");
 	    } elsif($1 eq 2) {
 		my @arguments16 = ("UINT16", $4);
 		my @arguments32 = ("UINT", $4);
 		&$function_begin($documentation_line, $documentation,
 				 $function_line, "", "UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16);
-		$statements = "";
-		&$function_end;
+		&$function_end("");
 		&$function_begin($documentation_line, $documentation, 
 				 $function_line, "", "UINT", "WINAPI", "waveOut" . $2, \@arguments32);
-		&$function_end;
+		&$function_end("");
 	    }
         } elsif(/DEFINE_REGS_ENTRYPOINT_\d+\(\s*(\S*)\s*,\s*([^\s,\)]*).*?\)/s) {
 	    $_ = $'; $again = 1;
@@ -508,6 +481,74 @@
 	} elsif(/(DEFAULT|DECLARE)_DEBUG_CHANNEL\s*\((\S+)\)/s) {
 	    $_ = $'; $again = 1;
 	    push @$debug_channels, $1;
+	} elsif(/typedef\s+(enum|struct|union)(?:\s+(\w+))?\s*\{/s) {
+	    $_ = $'; $again = 1;
+	    $level++;
+	    my $type = $1;
+	    if(defined($2)) {
+	       $type .= " $2";
+	    }
+	    &$type_begin($type);
+	} elsif(/typedef\s+
+		((?:const\s+|enum\s+|long\s+|signed\s+|short\s+|struct\s+|union\s+|unsigned\s+)*?)
+		(\w+)
+		(?:\s+const)?
+		((?:\s*\*+\s*|\s+)\w+\s*(?:\[[^\]]*\])?
+		(?:\s*,\s*(?:\s*\*+\s*|\s+)\w+\s*(?:\[[^\]]*\])?)*)
+		\s*;/sx) 
+	{
+	    $_ = $'; $again = 1;
+
+	    my $type = "$1 $2";
+
+	    my @names;
+	    my @parts = split(/\s*,\s*/, $2);
+	    foreach my $part (@parts) {
+		if($part =~ /(?:\s*(\*+)\s*|\s+)(\w+)\s*(\[[^\]]*\])?/) {
+		    my $name = $2;
+		    if(defined($1)) {
+			$name = "$1$2";
+		    }
+		    if(defined($3)) {
+			$name .= $3;
+		    }
+		    push @names, $name;
+		}
+	    }
+	    &$type_begin($type);
+	    &$type_end([@names]);
+	} elsif(/typedef\s+
+		(?:(?:const\s+|enum\s+|long\s+|signed\s+|short\s+|struct\s+|union\s+|unsigned\s+)*?)
+		(\w+)\s+
+		(?:(\w+)\s*)?
+		\((?:(\w+)\s+)?\s*\*\s*(\w+)\s*\)\s*
+		(?:\(([^\)]*)\)|\[([^\]]*)\])\s*;/sx) 
+	{
+	    $_ = $'; $again = 1;	   
+	    my $type;
+	    if(defined($2) || defined($3)) {
+		my $cc = $2 || $3;
+		if(defined($5)) {
+		    $type = "$1 ($cc *)($5)";
+		} else {
+		    $type = "$1 ($cc *)[$6]";
+		}
+	    } else {
+		if(defined($5)) {
+		    $type = "$1 (*)($5)";
+		} else {
+		    $type = "$1 (*)[$6]";
+		}
+	    }
+	    my $name = $4;
+	    &$type_begin($type);
+	    &$type_end([$name]);
+	} elsif(/typedef[^\{;]*;/s) {
+	    $_ = $'; $again = 1;
+	    $output->write("$file: $.: can't parse: '$&'\n");
+	} elsif(/typedef[^\{]*\{[^\}]*\}[^;];/s) {
+	    $_ = $'; $again = 1;
+	    $output->write("$file: $.: can't parse: '$&'\n");
 	} elsif(/\'[^\']*\'/s) {
 	    $_ = $'; $again = 1;
 	} elsif(/\"[^\"]*\"/s) {