- Continued on the new C parser.
- More reorganizations and fixes.
- API files update.
diff --git a/tools/winapi/c_function.pm b/tools/winapi/c_function.pm
new file mode 100644
index 0000000..ee96a91
--- /dev/null
+++ b/tools/winapi/c_function.pm
@@ -0,0 +1,168 @@
+package c_function;
+
+use strict;
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ bless ($self, $class);
+
+ return $self;
+}
+
+sub file {
+ my $self = shift;
+ my $file = \${$self->{FILE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$file = $_; }
+
+ return $$file;
+}
+
+sub begin_line {
+ my $self = shift;
+ my $begin_line = \${$self->{BEGIN_LINE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$begin_line = $_; }
+
+ return $$begin_line;
+}
+
+sub begin_column {
+ my $self = shift;
+ my $begin_column = \${$self->{BEGIN_COLUMN}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$begin_column = $_; }
+
+ return $$begin_column;
+}
+
+sub end_line {
+ my $self = shift;
+ my $end_line = \${$self->{END_LINE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$end_line = $_; }
+
+ return $$end_line;
+}
+
+sub end_column {
+ my $self = shift;
+ my $end_column = \${$self->{END_COLUMN}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$end_column = $_; }
+
+ return $$end_column;
+}
+
+sub linkage {
+ my $self = shift;
+ my $linkage = \${$self->{LINKAGE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$linkage = $_; }
+
+ return $$linkage;
+}
+
+sub return_type {
+ my $self = shift;
+ my $return_type = \${$self->{RETURN_TYPE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$return_type = $_; }
+
+ return $$return_type;
+}
+
+sub calling_convention {
+ my $self = shift;
+ my $calling_convention = \${$self->{CALLING_CONVENTION}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$calling_convention = $_; }
+
+ return $$calling_convention;
+}
+
+sub name {
+ my $self = shift;
+ my $name = \${$self->{NAME}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$name = $_; }
+
+ return $$name;
+}
+
+sub argument_types {
+ my $self = shift;
+ my $argument_types = \${$self->{ARGUMENT_TYPES}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$argument_types = $_; }
+
+ return $$argument_types;
+}
+
+sub argument_names {
+ my $self = shift;
+ my $argument_names = \${$self->{ARGUMENT_NAMES}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$argument_names = $_; }
+
+ return $$argument_names;
+}
+
+sub statements_line {
+ my $self = shift;
+ my $statements_line = \${$self->{STATEMENTS_LINE}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$statements_line = $_; }
+
+ return $$statements_line;
+}
+
+sub statements_column {
+ my $self = shift;
+ my $statements_column = \${$self->{STATEMENTS_COLUMN}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$statements_column = $_; }
+
+ return $$statements_column;
+}
+
+sub statements {
+ my $self = shift;
+ my $statements = \${$self->{STATEMENTS}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$statements = $_; }
+
+ return $$statements;
+}
+
+1;
diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm
index 957723a..87c880c 100644
--- a/tools/winapi/c_parser.pm
+++ b/tools/winapi/c_parser.pm
@@ -2,92 +2,218 @@
use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+
use options qw($options);
use output qw($output);
-sub _update_c_position {
- local $_ = shift;
- my $refline = shift;
- my $refcolumn = shift;
+use c_function;
- my $line = $$refline;
- my $column = $$refcolumn;
+########################################################################
+# new
+#
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ bless ($self, $class);
- while($_) {
- if(s/^[^\n\t\'\"]*//s) {
- $column += length($&);
- }
+ my $file = \${$self->{FILE}};
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+ my $create_function = \${$self->{CREATE_FUNCTION}};
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+ my $found_statement = \${$self->{FOUND_STATEMENT}};
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
- if(s/^\'//) {
- $column++;
- while(/^./ && !s/^\'//) {
- s/^([^\'\\]*)//s;
- $column += length($1);
- if(s/^\\//) {
- $column++;
- if(s/^(.)//s) {
- $column += length($1);
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $column += length($1);
- }
- }
- }
- }
- $column++;
- } elsif(s/^\"//) {
- $column++;
- while(/^./ && !s/^\"//) {
- s/^([^\"\\]*)//s;
- $column += length($1);
- if(s/^\\//) {
- $column++;
- if(s/^(.)//s) {
- $column += length($1);
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $column += length($1);
- }
- }
- }
- }
- $column++;
- } elsif(s/^\n//) {
- $line++;
- $column = 0;
- } elsif(s/^\t//) {
- $column = $column + 8 - $column % 8;
- }
- }
+ $$file = shift;
- $$refline = $line;
- $$refcolumn = $column;
+ $$found_comment = sub { return 1; };
+ $$found_declaration = sub { return 1; };
+ $$create_function = sub { return new c_function; };
+ $$found_function = sub { return 1; };
+ $$found_function_call = sub { return 1; };
+ $$found_preprocessor = sub { return 1; };
+ $$found_statement = sub { return 1; };
+ $$found_variable = sub { return 1; };
+
+ return $self;
}
-sub parse_c {
+########################################################################
+# set_found_comment_callback
+#
+sub set_found_comment_callback {
+ my $self = shift;
+
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+
+ $$found_comment = shift;
+}
+
+########################################################################
+# set_found_declaration_callback
+#
+sub set_found_declaration_callback {
+ my $self = shift;
+
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+
+ $$found_declaration = shift;
+}
+
+########################################################################
+# set_found_function_callback
+#
+sub set_found_function_callback {
+ my $self = shift;
+
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+
+ $$found_function = shift;
+}
+
+########################################################################
+# set_found_function_call_callback
+#
+sub set_found_function_call_callback {
+ my $self = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ $$found_function_call = shift;
+}
+
+########################################################################
+# set_found_preprocessor_callback
+#
+sub set_found_preprocessor_callback {
+ my $self = shift;
+
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+
+ $$found_preprocessor = shift;
+}
+
+########################################################################
+# set_found_statement_callback
+#
+sub set_found_statement_callback {
+ my $self = shift;
+
+ my $found_statement = \${$self->{FOUND_STATEMENT}};
+
+ $$found_statement = shift;
+}
+
+########################################################################
+# set_found_variable_callback
+#
+sub set_found_variable_callback {
+ my $self = shift;
+
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
+
+ $$found_variable = shift;
+}
+
+########################################################################
+# _parse_c
+
+sub _parse_c {
+ my $self = shift;
+
my $pattern = shift;
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
+ my $refmatch = shift;
+
local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- if(s/$pattern//) {
- _update_c_position($&, \$line, \$column);
+ my $match;
+ if(s/^(?:$pattern)//s) {
+ $self->_update_c_position($&, \$line, \$column);
+ $match = $&;
} else {
return 0;
}
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
$$refcurrent = $_;
$$refline = $line;
$$refcolumn = $column;
+ $$refmatch = $match;
+
return 1;
}
-sub parse_c_until_one_of {
+########################################################################
+# _parse_c_error
+
+sub _parse_c_error {
+ my $self = shift;
+
+ my $file = \${$self->{FILE}};
+
+ local $_ = shift;
+ my $line = shift;
+ my $column = shift;
+ my $context = shift;
+
+ my @lines = split(/\n/, $_);
+
+ my $current = "\n";
+ $current .= $lines[0] . "\n" || "";
+ $current .= $lines[1] . "\n" || "";
+
+ if($output->prefix) {
+ $output->write("\n");
+ $output->prefix("");
+ }
+ $output->write("$$file:$line." . ($column + 1) . ": $context: parse error: \\$current");
+
+ exit 1;
+}
+
+########################################################################
+# _parse_c_output
+
+sub _parse_c_output {
+ my $self = shift;
+
+ local $_ = shift;
+ my $line = shift;
+ my $column = shift;
+ my $message = shift;
+
+ my @lines = split(/\n/, $_);
+
+ my $current = "\n";
+ $current .= $lines[0] . "\n" || "";
+ $current .= $lines[1] . "\n" || "";
+
+ $output->write("$line." . ($column + 1) . ": $message: \\$current");
+}
+
+########################################################################
+# _parse_c_until_one_of
+
+sub _parse_c_until_one_of {
+ my $self = shift;
+
my $characters = shift;
my $refcurrent = shift;
my $refline = shift;
@@ -98,11 +224,6 @@
my $line = $$refline;
my $column = $$refcolumn;
- if(!defined($line) || !defined($column)) {
- $output->write("error: \$characters = '$characters' \$_ = '$_'\n");
- exit 1;
- }
-
if(!defined($match)) {
my $blackhole;
$match = \$blackhole;
@@ -179,10 +300,80 @@
return 1;
}
+########################################################################
+# _update_c_position
+
+sub _update_c_position {
+ my $self = shift;
+
+ local $_ = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ while($_) {
+ if(s/^[^\n\t\'\"]*//s) {
+ $column += length($&);
+ }
+
+ if(s/^\'//) {
+ $column++;
+ while(/^./ && !s/^\'//) {
+ s/^([^\'\\]*)//s;
+ $column += length($1);
+ if(s/^\\//) {
+ $column++;
+ if(s/^(.)//s) {
+ $column += length($1);
+ if($1 eq "0") {
+ s/^(\d{0,3})//s;
+ $column += length($1);
+ }
+ }
+ }
+ }
+ $column++;
+ } elsif(s/^\"//) {
+ $column++;
+ while(/^./ && !s/^\"//) {
+ s/^([^\"\\]*)//s;
+ $column += length($1);
+ if(s/^\\//) {
+ $column++;
+ if(s/^(.)//s) {
+ $column += length($1);
+ if($1 eq "0") {
+ s/^(\d{0,3})//s;
+ $column += length($1);
+ }
+ }
+ }
+ }
+ $column++;
+ } elsif(s/^\n//) {
+ $line++;
+ $column = 0;
+ } elsif(s/^\t//) {
+ $column = $column + 8 - $column % 8;
+ }
+ }
+
+ $$refline = $line;
+ $$refcolumn = $column;
+}
+
+########################################################################
+# parse_c_block
+
sub parse_c_block {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
+
my $refstatements = shift;
my $refstatements_line = shift;
my $refstatements_column = shift;
@@ -191,6 +382,8 @@
my $line = $$refline;
my $column = $$refcolumn;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
my $statements;
if(s/^\{//) {
$column++;
@@ -199,7 +392,7 @@
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
my $statements_line = $line;
my $statements_column = $column;
@@ -207,7 +400,7 @@
my $plevel = 1;
while($plevel > 0) {
my $match;
- parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
$column++;
@@ -235,63 +428,161 @@
return 1;
}
-sub parse_c_expression {
+########################################################################
+# parse_c_declaration
+
+sub parse_c_declaration {
+ my $self = shift;
+
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ my $end_line = $begin_line;
+ my $end_column = $begin_column;
+ $self->_update_c_position($_, \$end_line, \$end_column);
+
+ if(!&$$found_declaration($begin_line, $begin_column, $end_line, $end_column, $_)) {
+ return 1;
+ }
+
+ # Function
+ my $function = shift;
+
+ my $linkage = shift;
+ my $calling_convention = shift;
+ my $return_type = shift;
+ my $name = shift;
+ my @arguments = shift;
+ my @argument_lines = shift;
+ my @argument_columns = shift;
+
+ # Variable
+ my $type;
+
+ # $self->_parse_c_output($_, $line, $column, "declaration");
+
+ if(0) {
+ # Nothing
+ } elsif(s/^(?:DEFAULT|DECLARE)_DEBUG_CHANNEL\s*\(\s*(\w+)\s*\)\s*//s) { # FIXME: Wine specific kludge
+ $self->_update_c_position($&, \$line, \$column);
+ } elsif(s/^extern\s*\"(.*?)\"\s*//s) {
+ $self->_update_c_position($&, \$line, \$column);
+ my $declarations;
+ my $declarations_line;
+ my $declarations_column;
+ if(!$self->parse_c_block(\$_, \$line, \$column, \$declarations, \$declarations_line, \$declarations_column)) {
+ return 0;
+ }
+ if(!$self->parse_c_declarations(\$declarations, \$declarations_line, \$declarations_column)) {
+ return 0;
+ }
+ } elsif($self->parse_c_function(\$_, \$line, \$column, \$function)) {
+ if(&$$found_function($function))
+ {
+ my $statements = $function->statements;
+ my $statements_line = $function->statements_line;
+ my $statements_column = $function->statements_column;
+
+ if(defined($statements)) {
+ if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
+ return 0;
+ }
+ }
+ }
+ } elsif($self->parse_c_typedef(\$_, \$line, \$column)) {
+ # Nothing
+ } elsif($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type, \$name)) {
+ # Nothing
+ } else {
+ $self->_parse_c_error($_, $line, $column, "declaration");
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_declarations
+
+sub parse_c_declarations {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_expression
+
+sub parse_c_expression {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(s/^(.*?)(\w+)(\s*)\(//s) {
+ if(s/^(.*?)(\w+\s*\()/$2/s) {
+ $column += length($1);
+
my $begin_line = $line;
- my $begin_column = $column + length($1) + 1;
+ my $begin_column = $column + 1;
- $line = $begin_line;
- $column = $begin_column + length("$2$3") - 1;
-
- my $name = $2;
-
- $_ = "($'";
-
- # $output->write("$name: $line.$column: '$_'\n");
-
+ my $name;
my @arguments;
my @argument_lines;
my @argument_columns;
- if(!parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ if(!$self->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns)) {
return 0;
}
- if($name =~ /^sizeof$/) {
- # Nothing
- } else {
- &$found_function_call_callback($begin_line, $begin_column, $line, $column,
- $name, \@arguments);
- }
-
- while(defined(my $argument = shift @arguments) &&
- defined(my $argument_line = shift @argument_lines) &&
- defined(my $argument_column = shift @argument_columns))
+ if($name =~ /^sizeof$/ ||
+ &$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
{
- parse_c_expression(\$argument, \$argument_line, \$argument_column, $found_function_call_callback);
+ while(defined(my $argument = shift @arguments) &&
+ defined(my $argument_line = shift @argument_lines) &&
+ defined(my $argument_column = shift @argument_columns))
+ {
+ $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
+ }
}
} elsif(s/^return//) {
$column += length($&);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(!parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) {
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ if(!$self->parse_c_expression(\$_, \$line, \$column)) {
return 0;
}
} else {
return 0;
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -300,22 +591,358 @@
return 1;
}
-sub parse_c_statement {
+########################################################################
+# parse_c_file
+
+sub parse_c_file {
+ my $self = shift;
+
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
-
+
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- local $_ = $$refcurrent;
+ my $declaration = "";
+ my $declaration_line = $line;
+ my $declaration_column = $column;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ my $previous_line = 0;
+ my $previous_column = -1;
+
+ my $blevel = 1;
+ my $plevel = 1;
+ while($plevel > 0 || $blevel > 0) {
+ my $match;
+ $self->_parse_c_until_one_of("#/\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
+
+ if($line == $previous_line && $column == $previous_column) {
+ # $self->_parse_c_error($_, $line, $column, "file: no progress");
+ }
+ $previous_line = $line;
+ $previous_column = $column;
+
+ # $self->_parse_c_output($_, $line, $column, "'$match'");
+
+ if(!$declaration && $match =~ s/^\s+//s) {
+ $self->_update_c_position($&, \$declaration_line, \$declaration_column);
+ }
+ $declaration .= $match;
+
+ if(/^[\#\/]/) {
+ my $blank_lines = 0;
+ if(s/^\#\s*//) {
+ my $preprocessor_line = $line;
+ my $preprocessor_column = $column;
+
+ my $preprocessor = $&;
+ while(s/^(.*?)\\\s*\n//) {
+ $blank_lines++;
+ $preprocessor .= "$1\n";
+ }
+ if(s/^(.*?)(\/[\*\/].*)?\n//) {
+ if(defined($2)) {
+ $_ = "$2\n$_";
+ } else {
+ $blank_lines++;
+ }
+ $preprocessor .= $1;
+ }
+
+ if(!$self->parse_c_preprocessor(\$preprocessor, \$preprocessor_line, \$preprocessor_column)) {
+ return 0;
+ }
+ }
+
+ if(s/^\/\*(.*?)\*\///s) {
+ &$$found_comment($line, $column + 1, "/*$1*/");
+ my @lines = split(/\n/, $1);
+ if($#lines > 0) {
+ $blank_lines += $#lines;
+ } else {
+ $column += length($1);
+ }
+ } elsif(s/^\/\/(.*?)\n//) {
+ &$$found_comment($line, $column + 1, "//$1");
+ $blank_lines++;
+ } elsif(s/^\///) {
+ $declaration .= $&;
+ }
+
+ $line += $blank_lines;
+ if($blank_lines > 0) {
+ $column = 0;
+ }
+
+ if(!$declaration) {
+ $declaration_line = $line;
+ $declaration_column = $column;
+ } else {
+ $declaration .= "\n" x $blank_lines;
+ }
+
+ next;
+ }
+
+ $column++;
+ if(s/^[\(\[]//) {
+ $plevel++;
+ $declaration .= $&;
+ } elsif(s/^[\)\]]//) {
+ $plevel--;
+ $declaration .= $&;
+ } elsif(s/^\{//) {
+ $blevel++;
+ $declaration .= $&;
+ } elsif(s/^\}//) {
+ $blevel--;
+ $declaration .= $&;
+ if($plevel == 1 && $blevel == 1 && $declaration !~ /^typedef/) {
+ if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
+ return 0;
+ }
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $declaration = "";
+ $declaration_line = $line;
+ $declaration_column = $column;
+ }
+ } elsif(s/^;//) {
+ if($plevel == 1 && $blevel == 1) {
+ if($declaration && !$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
+ return 0;
+ }
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $declaration = "";
+ $declaration_line = $line;
+ $declaration_column = $column;
+ } else {
+ $declaration .= $&;
+ }
+ } elsif(/^\s*$/ && $declaration =~ /^\s*$/ && $match =~ /^\s*$/) {
+ $plevel = 0;
+ $blevel = 0;
+ } else {
+ $self->_parse_c_error($_, $line, $column, "file");
+ }
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_function
+
+sub parse_c_function {
+ my $self = shift;
+
+ my $file = \${$self->{FILE}};
+ my $create_function = \${$self->{CREATE_FUNCTION}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reffunction = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $linkage = "";
+ my $calling_convention = "";
+ my $return_type;
+ my $name;
+ my @arguments;
+ my @argument_lines;
+ my @argument_columns;
+ my $statements;
+ my $statements_line;
+ my $statements_column;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ $self->_parse_c("inline", \$_, \$line, \$column);
+ $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
+ $self->_parse_c("inline", \$_, \$line, \$column);
+ if(!$self->parse_c_type(\$_, \$line, \$column, \$return_type)) {
+ return 0;
+ }
+
+ $self->_parse_c("__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK",
+ \$_, \$line, \$column, \$calling_convention);
+ if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) {
+ return 0;
+ }
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ return 0;
+ }
+ if($_ && !$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
+ return 0;
+ }
+
+ my $end_line = $line;
+ my $end_column = $column;
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ my $function = &$$create_function;
+
+ $function->file($$file);
+ $function->begin_line($begin_line);
+ $function->begin_column($begin_column);
+ $function->end_line($end_line);
+ $function->end_column($end_column);
+ $function->linkage($linkage);
+ $function->return_type($return_type);
+ $function->calling_convention($calling_convention);
+ $function->name($name);
+ # if(defined($argument_types)) {
+ # $function->argument_types([@$argument_types]);
+ # }
+ # if(defined($argument_names)) {
+ # $function->argument_names([@$argument_names]);
+ # }
+ $function->statements_line($statements_line);
+ $function->statements_column($statements_column);
+ $function->statements($statements);
+
+ $$reffunction = $function;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_function_call
+
+sub parse_c_function_call {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $refname = shift;
+ my $refarguments = shift;
+ my $refargument_lines = shift;
+ my $refargument_columns = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $name;
+ my @arguments;
+ my @argument_lines;
+ my @argument_columns;
+
+ if(s/^(\w+)(\s*)\(/\(/s) {
+ $column += length("$1$2");
+
+ $name = $1;
+
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$refname = $name;
+ @$refarguments = @arguments;
+ @$refargument_lines = @argument_lines;
+ @$refargument_columns = @argument_columns;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_preprocessor
+
+sub parse_c_preprocessor {
+ my $self = shift;
+
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ if(!&$$found_preprocessor($begin_line, $begin_column, "$_")) {
+ return 1;
+ }
+
+ if(0) {
+ # Nothing
+ } elsif(/^\#\s*define\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*else/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*endif/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*(?:if|ifdef|ifndef)?\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*include\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*undef\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } else {
+ $self->_parse_c_error($_, $line, $column, "preprocessor");
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_statement
+
+sub parse_c_statement {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
if(s/^(?:case\s+)?(\w+)\s*://) {
$column += length($&);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
}
# $output->write("$line.$column: '$_'\n");
@@ -326,10 +953,10 @@
my $statements;
my $statements_line;
my $statements_column;
- if(!parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
+ if(!$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
return 0;
}
- if(!parse_c_statements(\$statements, \$statements_line, \$statements_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
return 0;
}
} elsif(/^(for|if|switch|while)(\s*)\(/) {
@@ -341,35 +968,34 @@
my @arguments;
my @argument_lines;
my @argument_columns;
- if(!parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) {
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
while(defined(my $argument = shift @arguments) &&
defined(my $argument_line = shift @argument_lines) &&
defined(my $argument_column = shift @argument_columns))
{
- parse_c_expression(\$argument, \$argument_line, \$argument_column, $found_function_call_callback);
+ $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
}
} elsif(s/^else//) {
$column += length($&);
- if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0;
}
- } elsif(parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) {
+ } elsif($self->parse_c_expression(\$_, \$line, \$column)) {
# Nothing
} else {
- # $output->write("error '$_'\n");
- # exit 1;
+ # $self->_parse_c_error($_, $line, $column, "statement");
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -378,18 +1004,24 @@
return 1;
}
+########################################################################
+# parse_c_statements
+
sub parse_c_statements {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- local $_ = $$refcurrent;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
my $statement = "";
my $statement_line = $line;
my $statement_column = $column;
@@ -398,7 +1030,7 @@
my $plevel = 1;
while($plevel > 0 || $blevel > 0) {
my $match;
- parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
# $output->write("'$match' '$_'\n");
@@ -410,8 +1042,7 @@
} elsif(s/^[\)\]]//) {
$plevel--;
if($plevel <= 0) {
- $output->write("error $plevel: '$statement' '$match' '$_'\n");
- exit 1;
+ $self->_parse_c_error($_, $line, $column, "statements");
}
$statement .= $&;
} elsif(s/^\{//) {
@@ -421,21 +1052,21 @@
$blevel--;
$statement .= $&;
if($blevel == 1) {
- if(!parse_c_statement(\$statement, \$statement_line, \$statement_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = "";
$statement_line = $line;
$statement_column = $column;
}
} elsif(s/^;//) {
if($plevel == 1 && $blevel == 1) {
- if(!parse_c_statement(\$statement, \$statement_line, \$statement_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = "";
$statement_line = $line;
$statement_column = $column;
@@ -446,12 +1077,11 @@
$plevel = 0;
$blevel = 0;
} else {
- $output->write("error $plevel: '$statement' '$match' '$_'\n");
- exit 1;
+ $self->_parse_c_error($_, $line, $column, "statements");
}
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -460,7 +1090,12 @@
return 1;
}
+########################################################################
+# parse_c_tuple
+
sub parse_c_tuple {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
@@ -489,7 +1124,7 @@
my $plevel = 1;
while($plevel > 0) {
my $match;
- parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
$column++;
@@ -512,7 +1147,7 @@
push @$item_lines, $item_line;
push @$item_columns, $item_column;
push @$items, $item;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$item_line = $line;
$item_column = $column + 1;
$item = "";
@@ -531,4 +1166,125 @@
return 1;
}
+########################################################################
+# parse_c_type
+
+sub parse_c_type {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reftype = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $type;
+
+ $self->_parse_c("const", \$_, \$line, \$column);
+
+
+ if(0) {
+ # Nothing
+ } elsif($self->_parse_c('ICOM_VTABLE\(.*?\)', \$_, \$line, \$column, \$type)) {
+ # Nothing
+ } elsif($self->_parse_c('\w+\s*(\*\s*)*', \$_, \$line, \$column, \$type)) {
+ # Nothing
+ } else {
+ return 0;
+ }
+ $type =~ s/\s//g;
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reftype = $type;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_typedef
+
+sub parse_c_typedef {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reftype = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $type;
+
+ if(!$self->_parse_c("typedef", \$_, \$line, \$column)) {
+ return 0;
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reftype = $type;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_variable
+
+sub parse_c_variable {
+ my $self = shift;
+
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reflinkage = shift;
+ my $reftype = shift;
+ my $refname = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ my $linkage = "";
+ my $type;
+ my $name;
+
+ $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
+ if(!$self->parse_c_type(\$_, \$line, \$column, \$type)) { return 0; }
+ if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) { return 0; }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reflinkage = $linkage;
+ $$reftype = $type;
+ $$refname = $name;
+
+ if(&$$found_variable($begin_line, $begin_column, $linkage, $type, $name))
+ {
+ # Nothing
+ }
+
+ return 1;
+}
+
1;
diff --git a/tools/winapi/make_parser.pm b/tools/winapi/make_parser.pm
index ff0b517..1fa6e9d 100644
--- a/tools/winapi/make_parser.pm
+++ b/tools/winapi/make_parser.pm
@@ -51,9 +51,9 @@
}
if(defined($tool)) {
- $output->write("make_filter: $context: can't parse output: '$current'\n");
+ $output->write("$directory: $context: can't parse output: '$current'\n");
} else {
- $output->write("make_filter: $context: can't parse output: '$current'\n");
+ $output->write("$directory: $context: can't parse output: '$current'\n");
}
exit 1;
}
@@ -133,8 +133,12 @@
# Nothing
} elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
# Nothing
- } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.o(?:\(.*?\))?):\s*//) {
- ld_output($1, $_)
+ } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
+ $tool = "ld";
+ ld_output($1, $_);
+ } elsif($tool =~ /^gcc|ld$/ && s/^collect2:\s*//) {
+ $tool = "ld";
+ ld_output("collect2", $_);
} elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
gcc_output($1, $_);
} elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
@@ -427,13 +431,13 @@
# Nothing
} elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
my $type = $2;
- if($type =~ /^
- HACCEL|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|
- HGDIOBJ|HKL|HGLOBAL|HINSTANCE|HKEY|
+ if($type =~ /^(?:
+ HACCEL|HACMDRIVER|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|HDRAWDIB
+ HGDIOBJ|HKL|HGLOBAL|HIMC|HINSTANCE|HKEY|HLOCAL|
HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE|
- HLINE|HPHONE|HPHONEAPP|
- HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|WSAEVENT|
- handle_t|pointer$/x)
+ HLINE|HPEN|HPHONE|HPHONEAPP|
+ HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|
+ SC_HANDLE|WSAEVENT|handle_t|pointer)$/x)
{
$supress = 1;
} else {
@@ -580,8 +584,14 @@
$file = shift;
local $_ = shift;
- if(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
- # nothing
+ if(0) {
+ # Nothing
+ } elsif(/^In function \`(.*?)\':$/) {
+ $function = $1;
+ } elsif(0 && /^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
+ # Nothing
+ } else {
+ $message = "$_";
}
}
diff --git a/tools/winapi/output.pm b/tools/winapi/output.pm
index 018d63f..c6154ed 100644
--- a/tools/winapi/output.pm
+++ b/tools/winapi/output.pm
@@ -162,8 +162,13 @@
my $prefix = \${$self->{PREFIX}};
my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
- $$prefix = shift;
- $$prefix_callback = undef;
+ my $new_prefix = shift;
+ if(defined($new_prefix)) {
+ $$prefix = $new_prefix;
+ $$prefix_callback = undef;
+ } else {
+ return $$prefix;
+ }
}
sub prefix_callback {
diff --git a/tools/winapi/winapi_extract b/tools/winapi/winapi_extract
index 8423836..efae0ed 100755
--- a/tools/winapi/winapi_extract
+++ b/tools/winapi/winapi_extract
@@ -16,6 +16,12 @@
use output qw($output);
use winapi_extract_options qw($options);
+if($options->progress) {
+ $output->enable_progress;
+} else {
+ $output->disable_progress;
+}
+
use function;
use type;
use winapi_function;
@@ -144,9 +150,7 @@
my %functions;
$progress_current++;
- if($options->progress) {
- $output->progress("$file: file $progress_current of $progress_max");
- }
+ $output->progress("$file (file $progress_current of $progress_max)");
my $create_function = sub {
if($options->stub_statistics) {
@@ -159,19 +163,20 @@
my $found_function = sub {
my $function = shift;
+ my $internal_name = $function->internal_name;
+ $functions{$internal_name} = $function;
+
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
+ $output->prefix_callback(sub { return $function->prefix; });
+
my $documentation_line = $function->documentation_line;
my $documentation = $function->documentation;
my $function_line = $function->function_line;
my $linkage = $function->linkage;
my $return_type = $function->return_type;
my $calling_convention = $function->calling_convention;
- my $internal_name = $function->internal_name;
my $statements = $function->statements;
- $functions{$internal_name} = $function;
-
- $output->prefix_callback(sub { return $function->prefix; });
-
if($options->spec_files) {
documentation_specifications($function);
}
diff --git a/tools/winapi/winapi_fixup b/tools/winapi/winapi_fixup
index 3583143..6f79c36 100755
--- a/tools/winapi/winapi_fixup
+++ b/tools/winapi/winapi_fixup
@@ -19,9 +19,14 @@
use output qw($output);
use winapi_fixup_options qw($options);
+if($options->progress) {
+ $output->enable_progress;
+} else {
+ $output->disable_progress;
+}
+
+use c_parser;
use type;
-use winapi_function;
-use winapi_parser;
use winapi_fixup_documentation qw(&fixup_documentation);
use winapi_fixup_editor;
@@ -39,50 +44,109 @@
my $editor = new winapi_fixup_editor($file);
$progress_current++;
- if($options->progress) {
- $output->progress("$file (file $progress_current of $progress_max)");
- }
+ $output->progress("$file (file $progress_current of $progress_max)");
+ $output->prefix("$file:");
- my $create_function = sub {
- return 'winapi_function'->new;
+ {
+ open(IN, "< $file");
+ local $/ = undef;
+ $_ = <IN>;
+ close(IN);
+ }
+
+ my $parser = new c_parser($file);
+
+ my $found_preprocessor = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ my $preprocessor = shift;
+
+ # $output->write("$begin_line.$begin_column: preprocessor: $preprocessor\n");
+
+ return 1;
};
+ $parser->set_found_preprocessor_callback($found_preprocessor);
+
+ my $found_comment = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ my $comment = shift;
+
+ # $output->write("$begin_line.$begin_column: comment: $comment\n");
+
+ return 1;
+ };
+
+ $parser->set_found_comment_callback($found_comment);
+
+ my $found_declaration = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ my $end_line = shift;
+ my $end_column = shift;
+ my $declaration = shift;
+
+ # $output->write("$begin_line.$begin_column-$end_line.$end_column: declaration: \\\n$declaration\n");
+
+ return 1;
+ };
+
+ $parser->set_found_declaration_callback($found_declaration);
+
+ my $function;
+
my $found_function = sub {
- my $function = shift;
-
- my $internal_name = $function->internal_name;
- if($options->progress) {
- $output->progress("$file (file $progress_current of $progress_max): $internal_name");
- }
-
- $output->prefix_callback(sub { return $function->prefix; });
-
+ $function = shift;
+
+ my $name = $function->name;
+ my $begin_line = $function->begin_line;
+ my $begin_column = $function->begin_column;
+
+ $output->progress("$file (file $progress_current of $progress_max): $name");
+ $output->prefix("$file:$begin_line: function $name: ");
+ # $output->prefix_callback(sub { return $function->prefix; });
+
if($options->documentation) {
- fixup_documentation($function, $editor);
+ # fixup_documentation($function, $editor);
}
-
+
if($options->statements) {
fixup_statements($function, $editor);
}
+
+ my $statements = $function->statements;
+ if(!defined($statements)) {
+ $function = undef;
+ $output->prefix("$file: ");
+ }
- $output->prefix("");
+ return 0;
};
+
+ $parser->set_found_function_callback($found_function);
- my $create_type = sub {
- return 'type'->new;
- };
-
- my $found_type = sub {
+ my $found_variable = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ my $linkage = shift;
my $type = shift;
+ my $name = shift;
+
+ # $output->write("$begin_line.$begin_column: $linkage $type $name\n");
+
+ return 1;
};
- my $found_preprocessor = sub {
- my $directive = shift;
- my $argument = shift;
- };
+ $parser->set_found_variable_callback($found_variable);
- &winapi_parser::parse_c_file($file, $create_function, $found_function, $create_type, $found_type, $found_preprocessor);
+ my $line = 1;
+ my $column = 0;
+ if(!$parser->parse_c_file(\$_, \$line, \$column)) {
+ $output->write("can't parse file\n");
+ }
+
+ $output->prefix("");
$editor->flush;
}
-
diff --git a/tools/winapi/winapi_fixup_editor.pm b/tools/winapi/winapi_fixup_editor.pm
index 89331b4..49f0bde 100644
--- a/tools/winapi/winapi_fixup_editor.pm
+++ b/tools/winapi/winapi_fixup_editor.pm
@@ -94,7 +94,7 @@
my $line = $. - $lookahead_count;
foreach my $action (@{$$triggers{$line}}) {
- if($. < $action->{end_line}) {
+ if($. < $action->{end_line}) {
$lookahead = 1;
next LINE;
}
diff --git a/tools/winapi/winapi_fixup_options.pm b/tools/winapi/winapi_fixup_options.pm
index 2acc704..c4a15e5 100644
--- a/tools/winapi/winapi_fixup_options.pm
+++ b/tools/winapi/winapi_fixup_options.pm
@@ -29,7 +29,7 @@
"documentation-ordinal" => { default => 1, parent => "documentation", description => "documentation ordinal fixup" },
"documentation-wrong" => { default => 1, parent => "documentation", description => "documentation wrong fixup" },
"statements" => { default => 1, parent => "local", description => "statements fixup" },
- "statements-windowsx" => { default => 1, parent => "local", description => "statements windowsx fixup" },
+ "statements-windowsx" => { default => 0, parent => "local", description => "statements windowsx fixup" },
"stub" => { default => 0, parent => "local", description => "stub fixup" },
"global" => { default => 1, description => "global fixup" },
diff --git a/tools/winapi/winapi_fixup_statements.pm b/tools/winapi/winapi_fixup_statements.pm
index f7706db..9eb648c 100644
--- a/tools/winapi/winapi_fixup_statements.pm
+++ b/tools/winapi/winapi_fixup_statements.pm
@@ -9,10 +9,19 @@
@EXPORT = qw();
@EXPORT_OK = qw(&fixup_statements);
+use config qw($wine_dir);
use options qw($options);
use output qw($output);
use c_parser;
+use winapi_module_user qw(
+ &get_message_result_kind
+ &get_message_wparam_kind
+ &get_message_lparam_kind
+);
+
+########################################################################
+# fixup_function_call
sub fixup_function_call {
my $name = shift;
@@ -21,37 +30,58 @@
return "$name(" . join(", ", @arguments) . ")";
}
+########################################################################
+# _parse_makelong
+
sub _parse_makelong {
- my $value = shift;
+ local $_ = shift;
my $low;
my $high;
- if($value =~ /^
- (?:\(\w+\)\s*)?
- MAKE(?:LONG|LPARAM|LRESULT|WPARAM)\s*
- \(\s*(.*?)\s*,\s*(.*?)\s*\)$/sx)
+
+ my $name;
+ my @arguments;
+ my @argument_lines;
+ my @argument_columns;
+
+ my $parser = new c_parser;
+
+ my $line = 1;
+ my $column = 0;
+ if($parser->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns) &&
+ $name =~ /^MAKE(?:LONG|LPARAM|LRESULT|WPARAM)$/)
{
- $low = $1;
- $high = $2;
- } elsif($value =~ /^(?:\(\w+\)\s*)?0L?$/) {
+ $low = $arguments[0];
+ $high = $arguments[1];
+ } elsif(/^(?:\(\w+\)\s*)?0L?$/) {
$low = "0";
$high = "0";
} else {
- $low = "($value) & 0xffff";
- $high = "($value) << 16";
+ $low = "($_) & 0xffff";
+ $high = "($_) << 16";
}
+ $low =~ s/^\s*(.*?)\s*$/$1/;
+ $high =~ s/^\s*(.*?)\s*$/$1/;
+
return ($low, $high);
}
-sub fixup_function_call_2_forward_wm_call {
+########################################################################
+# fixup_function_call_2_windowsx
+
+sub fixup_user_message_2_windowsx {
my $name = shift;
(my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)};
- if($msg =~ /^(?:WM_BEGINDRAG|WM_ENTERMENULOOP|WM_EXITMENULOOP|WM_HELP|
- WM_ISACTIVEICON|WM_LBTRACKPOINT|WM_NEXTMENU)$/x)
+ if($msg !~ /^WM_/) {
+ return undef;
+ } elsif($msg =~ /^(?:WM_BEGINDRAG|WM_ENTERMENULOOP|WM_EXITMENULOOP|WM_HELP|
+ WM_ISACTIVEICON|WM_LBTRACKPOINT|WM_NEXTMENU)$/x)
{
return undef;
+ } elsif($msg =~ /^WM_(?:GET|SET)TEXT$/) {
+ return undef;
}
my $suffix;
@@ -62,8 +92,8 @@
$suffix = "";
}
- $wparam =~ s/^\(WPARAM\)//;
- $lparam =~ s/^\(LPARAM\)//;
+ $wparam =~ s/^\(WPARAM\)\s*//;
+ $lparam =~ s/^\(LPARAM\)\s*//;
my @arguments;
if(0) {
@@ -131,67 +161,161 @@
return "FORWARD_" . $msg . "(" . join(", ", @arguments) . ", $name)";
}
+########################################################################
+# _fixup_user_message
+
+sub _get_messages {
+ local $_ = shift;
+
+ if(/^WM_\w+$/) {
+ return ($_)
+ } elsif(/^(.*?)\s*\?\s*(WM_\w+)\s*:\s*(WM_\w+)$/) {
+ return ($2, $3);
+ } elsif(/^\w+$/) {
+ return ();
+ } else {
+ $output->write("_fixup_user_message: '$_'\n");
+ exit 1;
+ }
+}
+
+########################################################################
+# _fixup_user_message
+
+sub _fixup_user_message {
+ my $name = shift;
+ (my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)};
+
+ my $modified = 0;
+
+ my $wkind;
+ my $lkind;
+ foreach my $msg (_get_messages($msg)) {
+ my $new_wkind = &get_message_wparam_kind($msg);
+ if(defined($wkind) && $new_wkind ne $wkind) {
+ $output->write("messsages used together do not have the same type\n");
+ } else {
+ $wkind = $new_wkind;
+ }
+
+ my $new_lkind = &get_message_lparam_kind($msg);
+ if(defined($lkind) && $new_lkind ne $lkind) {
+ $output->write("messsages used together do not have the same type\n");
+ } else {
+ $lkind = $new_lkind;
+ }
+ }
+
+ my @entries = (
+ [ \$wparam, $wkind, "W", "w" ],
+ [ \$lparam, $lkind, "L", "l" ]
+ );
+ foreach my $entry (@entries) {
+ (my $refparam, my $kind, my $upper, my $lower) = @$entry;
+
+ if(!defined($kind)) {
+ if($msg =~ /^WM_/) {
+ $output->write("messsage $msg not defined\n");
+ }
+ } elsif($kind eq "ptr") {
+ if($$refparam =~ /^(\(${upper}PARAM\))?\s*($lower[pP]aram)$/) {
+ if(defined($1)) {
+ $$refparam = $2;
+ $modified = 1;
+ }
+ } elsif($$refparam =~ /^(\(${upper}PARAM\))?\s*0$/) {
+ $$refparam = "(${upper}PARAM) NULL";
+ $modified = 1;
+ } elsif($$refparam !~ /^\(${upper}PARAM\)\s*/) {
+ $$refparam = "(${upper}PARAM) $$refparam";
+ $modified = 1;
+ }
+ } elsif($kind eq "long") {
+ if($$refparam =~ s/^\(${upper}PARAM\)\s*//) {
+ $modified = 1;
+ }
+ }
+ }
+
+ if($modified) {
+ my @arguments = ($hwnd, $msg, $wparam, $lparam);
+ return "$name(" . join(", ", @arguments) . ")";
+ } else {
+ return undef;
+ }
+}
+
+########################################################################
+# fixup_statements
+
sub fixup_statements {
my $function = shift;
my $editor = shift;
+ my $file = $function->file;
my $linkage = $function->linkage;
- my $internal_name = $function->internal_name;
+ my $name = $function->name;
my $statements_line = $function->statements_line;
+ my $statements_column = $function->statements_column;
my $statements = $function->statements;
-
- if(($linkage eq "extern" && !defined($statements)) ||
- ($linkage eq "" && !defined($statements)))
- {
+
+ if(!defined($statements)) {
return;
}
-
- if($options->statements_windowsx && defined($statements)) {
- my $found_function_call = sub {
- my $begin_line = shift;
- my $begin_column = shift;
- my $end_line = shift;
- my $end_column = shift;
- my $name = shift;
- my $arguments = shift;
-
- foreach my $argument (@$arguments) {
- $argument =~ s/^\s*(.*?)\s*$/$1/;
- }
- if($options->statements_windowsx &&
- $name =~ /^(?:DefWindowProc|SendMessage)[AW]$/ &&
- $$arguments[1] =~ /^WM_\w+$/)
- {
- fixup_replace(\&fixup_function_call_2_forward_wm_call, $editor,
- $begin_line, $begin_column, $end_line, $end_column,
- $name, $arguments);
- } elsif(0) {
- $output->write("$begin_line.$begin_column-$end_line.$end_column: " .
- "$name(" . join(", ", @$arguments) . ")\n");
- }
- };
+ if(0 && $statements_line > 490) {
+ $output->write("$statements_line: \\\n");
my $line = $statements_line;
- my $column = 1;
-
- if(!&c_parser::parse_c_statements(\$statements, \$line, \$column, $found_function_call)) {
- $output->write("error: can't parse statements\n");
+ foreach my $statement (split(/\n/, $statements)) {
+ $output->write("$line: $statement\n");
+ $line++;
}
}
-}
-sub fixup_replace {
- my $function = shift;
- my $editor = shift;
- my $begin_line = shift;
- my $begin_column = shift;
- my $end_line = shift;
- my $end_column = shift;
+ my $parser = new c_parser($file);
+
+ my $found_function_call = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ my $end_line = shift;
+ my $end_column = shift;
+ my $name = shift;
+ my $arguments = shift;
+
+ foreach my $argument (@$arguments) {
+ $argument =~ s/^\s*(.*?)\s*$/$1/;
+ }
- my $replace = &$function(@_);
+ my $fixup_function_call;
+ if($name =~ /^(?:DefWindowProc|SendMessage)[AW]$/)
+ {
+ if($options->statements_windowsx) {
+ $fixup_function_call = \&fixup_user_message_2_windowsx;
+ } else {
+ $fixup_function_call = \&_fixup_user_message;
+ }
+ }
- if(defined($replace)) {
- $editor->replace($begin_line, $begin_column, $end_line, $end_column, $replace);
+ if(defined($fixup_function_call)) {
+ my $replace = &$fixup_function_call($name, $arguments);
+
+ if(defined($replace)) {
+ $editor->replace($begin_line, $begin_column, $end_line, $end_column, $replace);
+ }
+ } elsif(0 || $options->debug) {
+ $output->write("$begin_line.$begin_column-$end_line.$end_column: " .
+ "$name(" . join(", ", @$arguments) . ")\n");
+ }
+
+ return 0;
+ };
+
+ $parser->set_found_function_call_callback($found_function_call);
+
+ my $line = $statements_line;
+ my $column = 0;
+ if(!$parser->parse_c_statements(\$statements, \$line, \$column)) {
+ $output->write("error: can't parse statements\n");
}
}
diff --git a/tools/winapi/winapi_module_user.pm b/tools/winapi/winapi_module_user.pm
new file mode 100644
index 0000000..be853c5
--- /dev/null
+++ b/tools/winapi/winapi_module_user.pm
@@ -0,0 +1,445 @@
+package winapi_module_user;
+
+use strict;
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT = qw();
+@EXPORT_OK = qw(
+ &is_user_function
+ &get_message_result_type
+ &get_message_result_kind
+ &get_message_wparam_type
+ &get_message_wparam_kind
+ &get_message_lparam_type
+ &get_message_lparam_kind
+);
+
+use config qw($wine_dir);
+use options qw($options);
+use output qw($output);
+
+use c_parser;
+
+########################################################################
+
+my $message;
+
+########################################################################
+# is_user_function
+
+sub is_user_function {
+ my $name = shift;
+ if($name =~ /^(?:DefWindowProc|SendMessage)[AW]?$/) {
+ }
+}
+
+########################################################################
+# $message
+
+$message = {
+ WM_ACTIVATE => {
+ id => 0, result => "void", wparam => ["", ""], lparam => "HWND" },
+ WM_ACTIVATEAPP => {
+ id => 0, result => "void", wparam => "BOOL", lparam => "LPARAM" },
+
+ WM_BEGINDRAG => {
+ id => 0, result => "", wparam => "", lparam => "" },
+
+ WM_CANCELMODE => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_CHAR => {
+ id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+ WM_CHARTOITEM => {
+ id => 0x002f, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+ WM_CLOSE => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_COMMAND => {
+ id => 0, result => "void", wparam => ["int", "UINT"], lparam => "HWND" },
+ WM_COPY => {
+ id => 0x0301, result => "void", wparam => "void", lparam => "void" },
+ WM_COMPACTING => {
+ id => 0, result => "void", wparam => "UINT", lparam => "void" },
+ WM_COMPAREITEM => {
+ id => 0, result => "int", wparam => "UINT", lparam => "const COMPAREITEMSTRUCT *" },
+
+ WM_CREATE => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
+ WM_CTLCOLORBTN => {
+ id => 0x0135, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLORDLG => {
+ id => 0x136, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLOREDIT => {
+ id => 0x133, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLORLISTBOX => {
+ id => 0x134, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLORMSGBOX => {
+ id => 0x132, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLORSCROLLBAR => {
+ id => 0x137, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+ WM_CTLCOLORSTATIC => {
+ id => 0x138, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
+
+ WM_CUT => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+
+ WM_DEADCHAR => {
+ id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+ WM_DELETEITEM => {
+ id => 0, result => "void", wparam => "UINT", lparam => "const DELETEITEMSTRUCT *" },
+ WM_DEVMODECHANGE => {
+ id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" },
+ WM_DESTROY => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_DRAWITEM => {
+ id => 0, result => "void", wparam => "void", lparam => "const DRAWITEMSTRUCT *" },
+ WM_DROPFILES => {
+ id => 0, result => "void", wparam => "HDROP", lparam => "void" },
+
+ WM_ENABLE => {
+ id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+ WM_ENDSESSION => {
+ id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+ WM_ENTERIDLE => {
+ id => 0x0121, result => "void", wparam => "UINT", lparam => "HWND" },
+ WM_ENTERMENULOOP => {
+ id => 0x0211, result => "", wparam => "", lparam => "" },
+ WM_ERASEBKGND => {
+ id => 0, result => "BOOL", wparam => "HDC", lparam => "void" },
+ WM_EXITMENULOOP => {
+ id => 0x0212, result => "", wparam => "", lparam => "" },
+
+ WM_FONTCHANGE => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+
+ WM_GETTEXT => {
+ id => 0, result => "int", wparam => "int", lparam => "LPTSTR" },
+ WM_GETTEXTLENGTH => {
+ id => 0, result => "int", wparam => "void", lparam => "void" },
+
+ WM_HELP => {
+ id => 0x0053, result => "", wparam => "", lparam => "" },
+ WM_HSCROLL => {
+ id => 0, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+
+ WM_ICONERASEBKGND => {
+ id => 0, result => "BOOL", wparam => "HDC", lparam => "void" },
+ WM_INITMENU => {
+ id => 0, result => "void", wparam => "HMENU", lparam => "void" },
+ WM_INITMENUPOPUP => {
+ id => 0, result => "void", wparam => "HMENU", lparam => ["UINT", "BOOL"] },
+ WM_ISACTIVEICON => {
+ id => 0, result => "", wparam => "", lparam => "" },
+
+ WM_KEYDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_KEYUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_KILLFOCUS => {
+ id => 0, result => "void", wparam => "HWND", lparam => "void" },
+
+ WM_LBTRACKPOINT => {
+ id => 0, result => "", wparam => "", lparam => "" },
+ WM_LBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_LBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_LBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+
+ WM_MBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_MBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_MBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_MEASUREITEM => {
+ id => 0, result => "void", wparam => "UINT", lparam => "MEASUREITEMSTRUCT *" },
+ WM_MENUSELECT => {
+ id => 0, result => "void", wparam => ["", ""], lparam => "HMENU" },
+ WM_MENUCHAR => {
+ id => 0, result => "DWORD", wparam => ["", ""], lparam => "HMENU" },
+ WM_MOUSEACTIVATE => {
+ id => 0, result => "int", wparam => "HWND", lparam => ["", ""] },
+ WM_MOUSEMOVE => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_MOVE => {
+ id => 0, result => "void", wparam => "void", lparam => ["", ""] },
+
+ WM_NCACTIVATE => {
+ id => 0, result => "BOOL", wparam => "BOOL", lparam => "void" },
+ WM_NCLBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCLBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCLBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCMOUSEMOVE => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCMBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCMBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCMBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCRBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCRBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCRBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_NCCALCSIZE => {
+ id => 0, result => "UINT", wparam => "void", lparam => "LPARAM" },
+ WM_NCCREATE => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
+ WM_NCDESTROY => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_NCPAINT => {
+ id => 0, result => "void", wparam => "HRGN", lparam => "void" },
+ WM_NEXTMENU => {
+ id => 0x0213, result => "", wparam => "", lparam => "" },
+ WM_NOTIFY => {
+ id => 0x004e, result => "LRESULT", wparam => "int", lparam => "NMHDR *" },
+
+
+ WM_PALETTEISCHANGING => {
+ id => 0, result => "void", wparam => "HWND", lparam => "void" },
+ WM_PALETTECHANGED => {
+ id => 0, result => "void", wparam => "HWND", lparam => "void" },
+ WM_PAINT => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_PASTE => {
+ id => 0x0302, result => "void", wparam => "void", lparam => "void" },
+ WM_POWER => {
+ id => 0, result => "void", wparam => "int", lparam => "void" },
+
+ WM_QUERYDRAGICON => {
+ id => 0, result => "HICON", wparam => "void", lparam => "void" },
+ WM_QUERYENDSESSION => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+ WM_QUERYNEWPALETTE => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+ WM_QUERYOPEN => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+ WM_QUIT => {
+ id => 0, result => "void", wparam => "WPARAM", lparam => "void" },
+
+ WM_RBUTTONDBLCLK => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_RBUTTONDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_RBUTTONUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+
+ WM_SETCURSOR => {
+ id => 0x0020, result => "", wparam => "HWND", lparam => ["UINT", "UINT"] },
+ WM_SETFOCUS => {
+ id => 0, result => "void", wparam => "HWND", lparam => "void" },
+ WM_SETFONT => {
+ id => 0x0030, result => "void", wparam => "HFONT", lparam => "BOOL" },
+ WM_SETREDRAW => {
+ id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+ WM_SETTEXT => {
+ id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" },
+ WM_SHOWWINDOW => {
+ id => 0, result => "void", wparam => "BOOL", lparam => "UINT" },
+ WM_SIZE => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_SPOOLERSTATUS => {
+ id => 0, result => "void", wparam => "WPARAM", lparam => ["", ""] },
+ WM_SYSCHAR => {
+ id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+ WM_SYSCOLORCHANGE => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+ WM_SYSDEADCHAR => {
+ id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+ WM_SYSKEYDOWN => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+ WM_SYSKEYUP => {
+ id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+
+ WM_TIMECHANGE => {
+ id => 0, result => "void", wparam => "void", lparam => "void" },
+
+ WM_VKEYTOITEM => {
+ id => 0x002e, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+ WM_VSCROLL => {
+ id => 0, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+
+ WM_WINDOWPOSCHANGING => {
+ id => 0, result => "BOOL", wparam => "void", lparam => "LPWINDOWPOS" },
+ WM_WINDOWPOSCHANGED => {
+ id => 0, result => "void", wparam => "void", lparam => "LPARAM" },
+ WM_WININICHANGE => {
+ id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" }
+};
+
+########################################################################
+# _get_kind
+
+sub _get_kind {
+ local $_ = shift;
+
+ if(!defined($_)) {
+ return undef;
+ } elsif(/^(?:HBRUSH|HDC|HFONT|HMENU|HRGN|HWND)$/ || /\*$/ ||
+ /^LP(?!ARAM)/)
+ {
+ return "ptr";
+ } else {
+ return "long";
+ }
+}
+
+########################################################################
+# get_message_result_type
+
+sub get_message_result_type {
+ my $name = shift;
+ return $$message{$name}{result};
+}
+
+########################################################################
+# get_message_result_kind
+
+sub get_message_result_kind {
+ return _get_kind(get_message_result_type(@_));
+}
+
+########################################################################
+# get_message_wparam_type
+
+sub get_message_wparam_type {
+ my $name = shift;
+ return $$message{$name}{wparam};
+}
+
+########################################################################
+# get_message_wparam_kind
+
+sub get_message_wparam_kind {
+ return _get_kind(get_message_wparam_type(@_));
+}
+
+########################################################################
+# get_message_lparam_type
+
+sub get_message_lparam_type {
+ my $name = shift;
+ return $$message{$name}{lparam};
+}
+
+########################################################################
+# get_message_lparam_kind
+
+sub get_message_lparam_kind {
+ return _get_kind(get_message_lparam_type(@_));
+}
+
+########################################################################
+# _parse_windowsx_h
+
+sub _parse_windowsx_h {
+ my $file = "$wine_dir/include/windowsx.h";
+ {
+ open(IN, "< $file");
+ local $/ = undef;
+ $_ = <IN>;
+ close(IN);
+ }
+
+ my $parser = new c_parser($file);
+
+ my $found_preprocessor = sub {
+ my $begin_line = shift;
+ my $begin_column = shift;
+ local $_ = shift;
+
+ if(!s/^\#\s*define\s*// || !/^FORWARD_WM_/) {
+ return 1;
+ }
+
+ my $msg;
+ if(s/^FORWARD_(\w+)\([^\)]*\)\s*(.*?)\s*$/$2/s) {
+ $msg = $1;
+ }
+
+ if($msg eq "WM_SYSTEMERROR") {
+ return 1;
+ }
+
+ my $return_type;
+ if(s/^\(\s*(\w+)\s*\)(?:\(\s*\w+\s*\))*\(\s*\w+\s*\)\(\s*(?:hwnd|\(hwnd\))\s*,\s*(.*?)\s*\)$/$2/) {
+ $return_type = $1;
+ } else {
+ die "$msg: '$_'";
+ }
+
+ my @msgs = ();
+ if(s/^$msg\s*,\s*//) {
+ @msgs = $msg;
+ } elsif(s/^\(\w+\)\s*\?\s*(\w+)\s*:\s*(\w+)\s*,\s*//s) {
+ @msgs = ($1, $2);
+ } else {
+ die "$msg: '$_'";
+ }
+
+ my $wparam;
+ if(s/^\(WPARAM\)(?:\(\s*(\w+)\s*\))*\((.*?)\)\s*,\s*//) {
+ if(defined($1)) {
+ $wparam = $1;
+ } else {
+ $wparam = "WPARAM";
+ }
+ } elsif(s/^MAKEWPARAM\(\s*(.*?)\s*,\s*(.*?)\s*\)\s*,\s*//) {
+ $wparam = "(,)"; # "($1, $2)";
+ } elsif(s/^\((.*?)\)$//) {
+ $wparam = "WPARAM";
+ } elsif(s/^0L\s*,\s*//) {
+ $wparam = "void";
+ } else {
+ die "$msg: '$_'";
+ }
+
+ my $lparam;
+ if(s/^\(LPARAM\)(?:\(\s*(\w+)\s*\))*\((.*?)\)$//) {
+ if(defined($1)) {
+ $lparam = $1;
+ } else {
+ $lparam = "LPARAM";
+ }
+ } elsif(s/^MAKELPARAM\(\s*(.*?)\s*,\s*(.*?)\s*\)$//) {
+ $lparam = "(,)"; # "($1, $2)";
+ } elsif(s/^\((.*?)\)$//) {
+ $lparam = "LPARAM";
+ } elsif(s/^0L$//) {
+ $lparam = "void";
+ } else {
+ die "$msg: '$_'";
+ }
+
+ foreach my $msg (@msgs) {
+ $output->write("$msg => { result => \"$return_type\", wparam => \"$wparam\", lparam => \"$lparam\" },\n");
+ }
+
+ return 1;
+ };
+
+ $parser->set_found_preprocessor_callback($found_preprocessor);
+
+ my $line = 1;
+ my $column = 0;
+
+ my $old_prefix = $output->prefix;
+ $output->progress("$file");
+ $output->prefix("$file: ");
+
+ if(!$parser->parse_c_file(\$_, \$line, \$column)) {
+ $output->write("can't parse file\n");
+ }
+
+ $output->prefix($old_prefix);
+}
+
diff --git a/tools/winapi_check/modules.pm b/tools/winapi_check/modules.pm
index 1880b49..a6598b6 100644
--- a/tools/winapi_check/modules.pm
+++ b/tools/winapi_check/modules.pm
@@ -70,9 +70,7 @@
my $module_file = "$winapi_check_dir/modules.dat";
- if($options->progress) {
- $output->progress("modules.dat");
- }
+ $output->progress("modules.dat");
my %spec_file_found;
my $allowed_dir;
diff --git a/tools/winapi_check/nativeapi.pm b/tools/winapi_check/nativeapi.pm
index dc5bf38..969e58c 100644
--- a/tools/winapi_check/nativeapi.pm
+++ b/tools/winapi_check/nativeapi.pm
@@ -36,9 +36,7 @@
$configure_in_file =~ s/^\.\///;
$config_h_in_file =~ s/^\.\///;
- if($options->progress) {
- $output->progress("$api_file");
- }
+ $output->progress("$api_file");
open(IN, "< $api_file");
local $/ = "\n";
@@ -51,9 +49,7 @@
}
close(IN);
- if($options->progress) {
- $output->progress("$configure_in_file");
- }
+ $output->progress("$configure_in_file");
my $again = 0;
open(IN, "< $configure_in_file");
@@ -102,9 +98,7 @@
}
close(IN);
- if($options->progress) {
- $output->progress("$config_h_in_file");
- }
+ $output->progress("$config_h_in_file");
open(IN, "< $config_h_in_file");
local $/ = "\n";
diff --git a/tools/winapi_check/win32/kernel32.api b/tools/winapi_check/win32/kernel32.api
index a062a4e..2106c83 100644
--- a/tools/winapi_check/win32/kernel32.api
+++ b/tools/winapi_check/win32/kernel32.api
@@ -136,8 +136,6 @@
PLONG
PTIMERAPCROUTINE
PULARGE_INTEGER
-PVOID
-PVOID *
SECURITY_ATTRIBUTES *
SYSLEVEL *
SYSLEVEL **
diff --git a/tools/winapi_check/win32/oleaut32.api b/tools/winapi_check/win32/oleaut32.api
index 5eebc41..616df9d 100644
--- a/tools/winapi_check/win32/oleaut32.api
+++ b/tools/winapi_check/win32/oleaut32.api
@@ -66,10 +66,12 @@
LPOCPFIPARAMS
LPPICTDESC
LPSTREAM
+LPSYSTEMTIME
LPUNKNOWN
LPUNKNOWN *
LPVOID
LPVOID *
+NUMPARSE *
OLECHAR *
OLECHAR **
REFCLSID
@@ -78,6 +80,7 @@
SAFEARRAY *
SAFEARRAY **
SAFEARRAYBOUND *
+UDATE *
UINT *
ULONG *
USHORT *
diff --git a/tools/winapi_check/win32/quartz.api b/tools/winapi_check/win32/quartz.api
index b4d5096..c9b8791 100644
--- a/tools/winapi_check/win32/quartz.api
+++ b/tools/winapi_check/win32/quartz.api
@@ -1,6 +1,5 @@
%long
-DWORD
HRESULT
%ptr
diff --git a/tools/winapi_check/win32/shell32.api b/tools/winapi_check/win32/shell32.api
index 20ce347..d4afdf2 100644
--- a/tools/winapi_check/win32/shell32.api
+++ b/tools/winapi_check/win32/shell32.api
@@ -6,6 +6,7 @@
HANDLE
HBITMAP
HDROP
+HGLOBAL
HMENU
HICON
HINSTANCE
diff --git a/tools/winapi_check/win32/ttydrv.api b/tools/winapi_check/win32/ttydrv.api
index e08e9d3..39439a3 100644
--- a/tools/winapi_check/win32/ttydrv.api
+++ b/tools/winapi_check/win32/ttydrv.api
@@ -43,7 +43,7 @@
RECT *
WINDOWPOS *
struct tagCURSORICONINFO *
-struct tagWND *
+
void *
%str
diff --git a/tools/winapi_check/win32/x11drv.api b/tools/winapi_check/win32/x11drv.api
index 77363b9..f811145 100644
--- a/tools/winapi_check/win32/x11drv.api
+++ b/tools/winapi_check/win32/x11drv.api
@@ -53,7 +53,6 @@
RECT *
TEXTMETRICW *
WINDOWPOS *
-WND *
void *
%str
diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm
index 4eb33e4..b7d32fe 100644
--- a/tools/winapi_check/winapi.pm
+++ b/tools/winapi_check/winapi.pm
@@ -105,9 +105,7 @@
my $extension = 0;
my $forbidden = 0;
- if($options->progress) {
- $output->lazy_progress("$file");
- }
+ $output->lazy_progress("$file");
open(IN, "< $wine_dir/$file") || die "$wine_dir/$file: $!\n";
$/ = "\n";
@@ -217,9 +215,7 @@
my $module;
my $module_file;
- if($options->progress) {
- $output->lazy_progress("$file");
- }
+ $output->lazy_progress("$file");
open(IN, "< $file") || die "$file: $!\n";
$/ = "\n";
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
index b7feb37..16b6102 100755
--- a/tools/winapi_check/winapi_check
+++ b/tools/winapi_check/winapi_check
@@ -26,6 +26,13 @@
);
use output qw($output);
use winapi_check_options qw($options);
+
+if($options->progress) {
+ $output->enable_progress;
+} else {
+ $output->disable_progress;
+}
+
use modules qw($modules);
use nativeapi qw($nativeapi);
use winapi qw($win16api $win32api @winapis);
@@ -50,9 +57,7 @@
foreach my $file (@files) {
$progress_current++;
- if($options->progress) {
- $output->lazy_progress("$file: file $progress_current of $progress_max");
- }
+ $output->lazy_progress("$file: file $progress_current of $progress_max");
my $file_dir = $file;
if(!($file_dir =~ s%(.*?)/[^/]+$%$1%)) {
@@ -128,9 +133,7 @@
my %functions;
$progress_current++;
- if($options->progress) {
- $output->progress("$file: file $progress_current of $progress_max");
- }
+ $output->progress("$file: file $progress_current of $progress_max");
my $create_function = sub {
return 'winapi_function'->new;
@@ -139,11 +142,13 @@
my $found_function = sub {
my $function = shift;
+ my $internal_name = $function->internal_name;
+
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
$output->prefix_callback(sub { return $function->prefix; });
my $function_line = $function->function_line;
my $linkage = $function->linkage;
- my $internal_name = $function->internal_name;
my $external_name = $function->external_name;
my $statements = $function->statements;
@@ -200,9 +205,7 @@
my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file");
$progress_current++;
- if($options->progress) {
- $output->progress("$file: file $progress_current of $progress_max");
- }
+ $output->progress("$file (file $progress_current of $progress_max)");
my $file_dir = $file;
if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) {
@@ -216,11 +219,12 @@
my $found_function = sub {
my $function = shift;
- $output->prefix_callback(sub { return $function->prefix; });
-
my $internal_name = $function->internal_name;
$functions{$internal_name} = $function;
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
+ $output->prefix_callback(sub { return $function->prefix; });
+
my $declared_function = $declared_functions{$internal_name};
my $documentation_line = $function->documentation_line;