Commit aeb023f3 authored by Patrik Stridvall's avatar Patrik Stridvall Committed by Alexandre Julliard

- Continued on the new C parser.

- More reorganizations and fixes. - API files update.
parent 615c0e0c
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;
...@@ -2,92 +2,218 @@ package c_parser; ...@@ -2,92 +2,218 @@ package c_parser;
use strict; 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 options qw($options);
use output qw($output); use output qw($output);
sub _update_c_position { use c_function;
local $_ = shift;
my $refline = shift; ########################################################################
my $refcolumn = shift; # new
#
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
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}};
$$file = shift;
$$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;
}
my $line = $$refline; ########################################################################
my $column = $$refcolumn; # set_found_comment_callback
#
sub set_found_comment_callback {
my $self = shift;
while($_) { my $found_comment = \${$self->{FOUND_COMMENT}};
if(s/^[^\n\t\'\"]*//s) {
$column += length($&);
}
if(s/^\'//) { $$found_comment = shift;
$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; # set_found_declaration_callback
#
sub set_found_declaration_callback {
my $self = shift;
my $found_declaration = \${$self->{FOUND_DECLARATION}};
$$found_declaration = shift;
} }
sub parse_c { ########################################################################
# 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 $pattern = shift;
my $refcurrent = shift; my $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $refmatch = shift;
local $_ = $$refcurrent; local $_ = $$refcurrent;
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; my $column = $$refcolumn;
if(s/$pattern//) { my $match;
_update_c_position($&, \$line, \$column); if(s/^(?:$pattern)//s) {
$self->_update_c_position($&, \$line, \$column);
$match = $&;
} else { } else {
return 0; return 0;
} }
$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$$refcurrent = $_; $$refcurrent = $_;
$$refline = $line; $$refline = $line;
$$refcolumn = $column; $$refcolumn = $column;
$$refmatch = $match;
return 1; 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 $characters = shift;
my $refcurrent = shift; my $refcurrent = shift;
my $refline = shift; my $refline = shift;
...@@ -98,11 +224,6 @@ sub parse_c_until_one_of { ...@@ -98,11 +224,6 @@ sub parse_c_until_one_of {
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; my $column = $$refcolumn;
if(!defined($line) || !defined($column)) {
$output->write("error: \$characters = '$characters' \$_ = '$_'\n");
exit 1;
}
if(!defined($match)) { if(!defined($match)) {
my $blackhole; my $blackhole;
$match = \$blackhole; $match = \$blackhole;
...@@ -179,10 +300,80 @@ sub parse_c_until_one_of { ...@@ -179,10 +300,80 @@ sub parse_c_until_one_of {
return 1; 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 { sub parse_c_block {
my $self = shift;
my $refcurrent = shift; my $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $refstatements = shift; my $refstatements = shift;
my $refstatements_line = shift; my $refstatements_line = shift;
my $refstatements_column = shift; my $refstatements_column = shift;
...@@ -191,6 +382,8 @@ sub parse_c_block { ...@@ -191,6 +382,8 @@ sub parse_c_block {
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; my $column = $$refcolumn;
$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
my $statements; my $statements;
if(s/^\{//) { if(s/^\{//) {
$column++; $column++;
...@@ -199,7 +392,7 @@ sub parse_c_block { ...@@ -199,7 +392,7 @@ sub parse_c_block {
return 0; 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_line = $line;
my $statements_column = $column; my $statements_column = $column;
...@@ -207,7 +400,7 @@ sub parse_c_block { ...@@ -207,7 +400,7 @@ sub parse_c_block {
my $plevel = 1; my $plevel = 1;
while($plevel > 0) { while($plevel > 0) {
my $match; my $match;
parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match); $self->_parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
$column++; $column++;
...@@ -235,63 +428,161 @@ sub parse_c_block { ...@@ -235,63 +428,161 @@ sub parse_c_block {
return 1; 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 $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $found_function_call_callback = shift;
local $_ = $$refcurrent;
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; my $column = $$refcolumn;
local $_ = $$refcurrent; $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
parse_c_until_one_of("\\S", \$_, \$line, \$column); my $begin_line = $line;
my $begin_column = $column + 1;
if(s/^(.*?)(\w+)(\s*)\(//s) { my $end_line = $begin_line;
my $begin_line = $line; my $end_column = $begin_column;
my $begin_column = $column + length($1) + 1; $self->_update_c_position($_, \$end_line, \$end_column);
$line = $begin_line; if(!&$$found_declaration($begin_line, $begin_column, $end_line, $end_column, $_)) {
$column = $begin_column + length("$2$3") - 1; return 1;
}
# Function
my $function = shift;
my $name = $2; 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;
# $output->write("$name: $line.$column: '$_'\n"); 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;
$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
if(s/^(.*?)(\w+\s*\()/$2/s) {
$column += length($1);
my $begin_line = $line;
my $begin_column = $column + 1;
my $name;
my @arguments; my @arguments;
my @argument_lines; my @argument_lines;
my @argument_columns; 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; return 0;
} }
if($name =~ /^sizeof$/) { if($name =~ /^sizeof$/ ||
# Nothing &$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
} 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))
{ {
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//) { } elsif(s/^return//) {
$column += length($&); $column += length($&);
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
if(!parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) { if(!$self->parse_c_expression(\$_, \$line, \$column)) {
return 0; return 0;
} }
} else { } else {
return 0; return 0;
} }
_update_c_position($_, \$line, \$column); $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_; $$refcurrent = $_;
$$refline = $line; $$refline = $line;
...@@ -300,22 +591,358 @@ sub parse_c_expression { ...@@ -300,22 +591,358 @@ sub parse_c_expression {
return 1; 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;
local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
my $declaration = "";
my $declaration_line = $line;
my $declaration_column = $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 $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $found_function_call_callback = shift;
local $_ = $$refcurrent;
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; 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; 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/^(?:case\s+)?(\w+)\s*://) { if(s/^(?:case\s+)?(\w+)\s*://) {
$column += length($&); $column += length($&);
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
} }
# $output->write("$line.$column: '$_'\n"); # $output->write("$line.$column: '$_'\n");
...@@ -326,10 +953,10 @@ sub parse_c_statement { ...@@ -326,10 +953,10 @@ sub parse_c_statement {
my $statements; my $statements;
my $statements_line; my $statements_line;
my $statements_column; 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; 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; return 0;
} }
} elsif(/^(for|if|switch|while)(\s*)\(/) { } elsif(/^(for|if|switch|while)(\s*)\(/) {
...@@ -341,35 +968,34 @@ sub parse_c_statement { ...@@ -341,35 +968,34 @@ sub parse_c_statement {
my @arguments; my @arguments;
my @argument_lines; my @argument_lines;
my @argument_columns; 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; return 0;
} }
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) { if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0; 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) && while(defined(my $argument = shift @arguments) &&
defined(my $argument_line = shift @argument_lines) && defined(my $argument_line = shift @argument_lines) &&
defined(my $argument_column = shift @argument_columns)) 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//) { } elsif(s/^else//) {
$column += length($&); $column += length($&);
if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) { if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0; return 0;
} }
} elsif(parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) { } elsif($self->parse_c_expression(\$_, \$line, \$column)) {
# Nothing # Nothing
} else { } else {
# $output->write("error '$_'\n"); # $self->_parse_c_error($_, $line, $column, "statement");
# exit 1;
} }
_update_c_position($_, \$line, \$column); $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_; $$refcurrent = $_;
$$refline = $line; $$refline = $line;
...@@ -378,18 +1004,24 @@ sub parse_c_statement { ...@@ -378,18 +1004,24 @@ sub parse_c_statement {
return 1; return 1;
} }
########################################################################
# parse_c_statements
sub parse_c_statements { sub parse_c_statements {
my $self = shift;
my $refcurrent = shift; my $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $found_function_call_callback = shift;
my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
local $_ = $$refcurrent;
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; 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 = "";
my $statement_line = $line; my $statement_line = $line;
my $statement_column = $column; my $statement_column = $column;
...@@ -398,7 +1030,7 @@ sub parse_c_statements { ...@@ -398,7 +1030,7 @@ sub parse_c_statements {
my $plevel = 1; my $plevel = 1;
while($plevel > 0 || $blevel > 0) { while($plevel > 0 || $blevel > 0) {
my $match; my $match;
parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match); $self->_parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
# $output->write("'$match' '$_'\n"); # $output->write("'$match' '$_'\n");
...@@ -410,8 +1042,7 @@ sub parse_c_statements { ...@@ -410,8 +1042,7 @@ sub parse_c_statements {
} elsif(s/^[\)\]]//) { } elsif(s/^[\)\]]//) {
$plevel--; $plevel--;
if($plevel <= 0) { if($plevel <= 0) {
$output->write("error $plevel: '$statement' '$match' '$_'\n"); $self->_parse_c_error($_, $line, $column, "statements");
exit 1;
} }
$statement .= $&; $statement .= $&;
} elsif(s/^\{//) { } elsif(s/^\{//) {
...@@ -421,21 +1052,21 @@ sub parse_c_statements { ...@@ -421,21 +1052,21 @@ sub parse_c_statements {
$blevel--; $blevel--;
$statement .= $&; $statement .= $&;
if($blevel == 1) { 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; return 0;
} }
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = ""; $statement = "";
$statement_line = $line; $statement_line = $line;
$statement_column = $column; $statement_column = $column;
} }
} elsif(s/^;//) { } elsif(s/^;//) {
if($plevel == 1 && $blevel == 1) { 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; return 0;
} }
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = ""; $statement = "";
$statement_line = $line; $statement_line = $line;
$statement_column = $column; $statement_column = $column;
...@@ -446,12 +1077,11 @@ sub parse_c_statements { ...@@ -446,12 +1077,11 @@ sub parse_c_statements {
$plevel = 0; $plevel = 0;
$blevel = 0; $blevel = 0;
} else { } else {
$output->write("error $plevel: '$statement' '$match' '$_'\n"); $self->_parse_c_error($_, $line, $column, "statements");
exit 1;
} }
} }
_update_c_position($_, \$line, \$column); $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_; $$refcurrent = $_;
$$refline = $line; $$refline = $line;
...@@ -460,7 +1090,12 @@ sub parse_c_statements { ...@@ -460,7 +1090,12 @@ sub parse_c_statements {
return 1; return 1;
} }
########################################################################
# parse_c_tuple
sub parse_c_tuple { sub parse_c_tuple {
my $self = shift;
my $refcurrent = shift; my $refcurrent = shift;
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
...@@ -489,7 +1124,7 @@ sub parse_c_tuple { ...@@ -489,7 +1124,7 @@ sub parse_c_tuple {
my $plevel = 1; my $plevel = 1;
while($plevel > 0) { while($plevel > 0) {
my $match; my $match;
parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match); $self->_parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
$column++; $column++;
...@@ -512,7 +1147,7 @@ sub parse_c_tuple { ...@@ -512,7 +1147,7 @@ sub parse_c_tuple {
push @$item_lines, $item_line; push @$item_lines, $item_line;
push @$item_columns, $item_column; push @$item_columns, $item_column;
push @$items, $item; push @$items, $item;
parse_c_until_one_of("\\S", \$_, \$line, \$column); $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$item_line = $line; $item_line = $line;
$item_column = $column + 1; $item_column = $column + 1;
$item = ""; $item = "";
...@@ -531,4 +1166,125 @@ sub parse_c_tuple { ...@@ -531,4 +1166,125 @@ sub parse_c_tuple {
return 1; 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; 1;
...@@ -51,9 +51,9 @@ sub error { ...@@ -51,9 +51,9 @@ sub error {
} }
if(defined($tool)) { 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 { } else {
$output->write("make_filter: $context: can't parse output: '$current'\n"); $output->write("$directory: $context: can't parse output: '$current'\n");
} }
exit 1; exit 1;
} }
...@@ -133,8 +133,12 @@ sub line { ...@@ -133,8 +133,12 @@ sub line {
# Nothing # Nothing
} elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) { } elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
# Nothing # Nothing
} elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.o(?:\(.*?\))?):\s*//) { } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
ld_output($1, $_) $tool = "ld";
ld_output($1, $_);
} elsif($tool =~ /^gcc|ld$/ && s/^collect2:\s*//) {
$tool = "ld";
ld_output("collect2", $_);
} elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) { } elsif($tool eq "gcc" && s/^(.+?\.[chly]):\s*//) {
gcc_output($1, $_); gcc_output($1, $_);
} elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) { } elsif($tool eq "winebuild" && s/^(.+?\.spec):\s*//) {
...@@ -427,13 +431,13 @@ sub gcc_output { ...@@ -427,13 +431,13 @@ sub gcc_output {
# Nothing # Nothing
} elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) { } elsif(/^((?:signed |unsigned )?(?:int|long)) format, (different type|\S+) arg \(arg (\d+)\)$/) {
my $type = $2; my $type = $2;
if($type =~ /^ if($type =~ /^(?:
HACCEL|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK| HACCEL|HACMDRIVER|HANDLE|HBITMAP|HBRUSH|HCALL|HCURSOR|HDC|HDRVR|HDESK|HDRAWDIB
HGDIOBJ|HKL|HGLOBAL|HINSTANCE|HKEY| HGDIOBJ|HKL|HGLOBAL|HIMC|HINSTANCE|HKEY|HLOCAL|
HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE| HMENU|HMIDISTRM|HMIDIIN|HMIDIOUT|HMIXER|HMIXEROBJ|HMMIO|HMODULE|
HLINE|HPHONE|HPHONEAPP| HLINE|HPEN|HPHONE|HPHONEAPP|
HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|WSAEVENT| HRASCONN|HRGN|HRSRC|HWAVEIN|HWAVEOUT|HWINSTA|HWND|
handle_t|pointer$/x) SC_HANDLE|WSAEVENT|handle_t|pointer)$/x)
{ {
$supress = 1; $supress = 1;
} else { } else {
...@@ -580,8 +584,14 @@ sub ld_output { ...@@ -580,8 +584,14 @@ sub ld_output {
$file = shift; $file = shift;
local $_ = shift; local $_ = shift;
if(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) { if(0) {
# nothing # Nothing
} elsif(/^In function \`(.*?)\':$/) {
$function = $1;
} elsif(0 && /^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
# Nothing
} else {
$message = "$_";
} }
} }
......
...@@ -162,8 +162,13 @@ sub prefix { ...@@ -162,8 +162,13 @@ sub prefix {
my $prefix = \${$self->{PREFIX}}; my $prefix = \${$self->{PREFIX}};
my $prefix_callback = \${$self->{PREFIX_CALLBACK}}; my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
$$prefix = shift; my $new_prefix = shift;
$$prefix_callback = undef; if(defined($new_prefix)) {
$$prefix = $new_prefix;
$$prefix_callback = undef;
} else {
return $$prefix;
}
} }
sub prefix_callback { sub prefix_callback {
......
...@@ -16,6 +16,12 @@ use config qw( ...@@ -16,6 +16,12 @@ use config qw(
use output qw($output); use output qw($output);
use winapi_extract_options qw($options); use winapi_extract_options qw($options);
if($options->progress) {
$output->enable_progress;
} else {
$output->disable_progress;
}
use function; use function;
use type; use type;
use winapi_function; use winapi_function;
...@@ -144,9 +150,7 @@ foreach my $file (@c_files) { ...@@ -144,9 +150,7 @@ foreach my $file (@c_files) {
my %functions; my %functions;
$progress_current++; $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 { my $create_function = sub {
if($options->stub_statistics) { if($options->stub_statistics) {
...@@ -159,19 +163,20 @@ foreach my $file (@c_files) { ...@@ -159,19 +163,20 @@ foreach my $file (@c_files) {
my $found_function = sub { my $found_function = sub {
my $function = shift; 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_line = $function->documentation_line;
my $documentation = $function->documentation; my $documentation = $function->documentation;
my $function_line = $function->function_line; my $function_line = $function->function_line;
my $linkage = $function->linkage; my $linkage = $function->linkage;
my $return_type = $function->return_type; my $return_type = $function->return_type;
my $calling_convention = $function->calling_convention; my $calling_convention = $function->calling_convention;
my $internal_name = $function->internal_name;
my $statements = $function->statements; my $statements = $function->statements;
$functions{$internal_name} = $function;
$output->prefix_callback(sub { return $function->prefix; });
if($options->spec_files) { if($options->spec_files) {
documentation_specifications($function); documentation_specifications($function);
} }
......
...@@ -19,9 +19,14 @@ use config qw( ...@@ -19,9 +19,14 @@ use config qw(
use output qw($output); use output qw($output);
use winapi_fixup_options qw($options); use winapi_fixup_options qw($options);
if($options->progress) {
$output->enable_progress;
} else {
$output->disable_progress;
}
use c_parser;
use type; use type;
use winapi_function;
use winapi_parser;
use winapi_fixup_documentation qw(&fixup_documentation); use winapi_fixup_documentation qw(&fixup_documentation);
use winapi_fixup_editor; use winapi_fixup_editor;
...@@ -39,50 +44,109 @@ foreach my $file (@c_files) { ...@@ -39,50 +44,109 @@ foreach my $file (@c_files) {
my $editor = new winapi_fixup_editor($file); my $editor = new winapi_fixup_editor($file);
$progress_current++; $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:");
{
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;
my $create_function = sub { # $output->write("$begin_line.$begin_column: preprocessor: $preprocessor\n");
return 'winapi_function'->new;
return 1;
}; };
my $found_function = sub { $parser->set_found_preprocessor_callback($found_preprocessor);
my $function = shift;
my $internal_name = $function->internal_name; my $found_comment = sub {
if($options->progress) { my $begin_line = shift;
$output->progress("$file (file $progress_current of $progress_max): $internal_name"); my $begin_column = shift;
} my $comment = shift;
$output->prefix_callback(sub { return $function->prefix; }); # $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 {
$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) { if($options->documentation) {
fixup_documentation($function, $editor); # fixup_documentation($function, $editor);
} }
if($options->statements) { if($options->statements) {
fixup_statements($function, $editor); fixup_statements($function, $editor);
} }
my $statements = $function->statements;
if(!defined($statements)) {
$function = undef;
$output->prefix("$file: ");
}
$output->prefix(""); return 0;
};
my $create_type = sub {
return 'type'->new;
}; };
$parser->set_found_function_callback($found_function);
my $found_type = sub { my $found_variable = sub {
my $begin_line = shift;
my $begin_column = shift;
my $linkage = shift;
my $type = shift; my $type = shift;
}; my $name = shift;
my $found_preprocessor = sub { # $output->write("$begin_line.$begin_column: $linkage $type $name\n");
my $directive = shift;
my $argument = shift; return 1;
}; };
&winapi_parser::parse_c_file($file, $create_function, $found_function, $create_type, $found_type, $found_preprocessor); $parser->set_found_variable_callback($found_variable);
my $line = 1;
my $column = 0;
if(!$parser->parse_c_file(\$_, \$line, \$column)) {
$output->write("can't parse file\n");
}
$output->prefix("");
$editor->flush; $editor->flush;
} }
...@@ -94,7 +94,7 @@ sub flush { ...@@ -94,7 +94,7 @@ sub flush {
my $line = $. - $lookahead_count; my $line = $. - $lookahead_count;
foreach my $action (@{$$triggers{$line}}) { foreach my $action (@{$$triggers{$line}}) {
if($. < $action->{end_line}) { if($. < $action->{end_line}) {
$lookahead = 1; $lookahead = 1;
next LINE; next LINE;
} }
......
...@@ -29,7 +29,7 @@ my %options_long = ( ...@@ -29,7 +29,7 @@ my %options_long = (
"documentation-ordinal" => { default => 1, parent => "documentation", description => "documentation ordinal fixup" }, "documentation-ordinal" => { default => 1, parent => "documentation", description => "documentation ordinal fixup" },
"documentation-wrong" => { default => 1, parent => "documentation", description => "documentation wrong fixup" }, "documentation-wrong" => { default => 1, parent => "documentation", description => "documentation wrong fixup" },
"statements" => { default => 1, parent => "local", description => "statements 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" }, "stub" => { default => 0, parent => "local", description => "stub fixup" },
"global" => { default => 1, description => "global fixup" }, "global" => { default => 1, description => "global fixup" },
......
...@@ -9,10 +9,19 @@ require Exporter; ...@@ -9,10 +9,19 @@ require Exporter;
@EXPORT = qw(); @EXPORT = qw();
@EXPORT_OK = qw(&fixup_statements); @EXPORT_OK = qw(&fixup_statements);
use config qw($wine_dir);
use options qw($options); use options qw($options);
use output qw($output); use output qw($output);
use c_parser; 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 { sub fixup_function_call {
my $name = shift; my $name = shift;
...@@ -21,37 +30,58 @@ sub fixup_function_call { ...@@ -21,37 +30,58 @@ sub fixup_function_call {
return "$name(" . join(", ", @arguments) . ")"; return "$name(" . join(", ", @arguments) . ")";
} }
########################################################################
# _parse_makelong
sub _parse_makelong { sub _parse_makelong {
my $value = shift; local $_ = shift;
my $low; my $low;
my $high; my $high;
if($value =~ /^
(?:\(\w+\)\s*)? my $name;
MAKE(?:LONG|LPARAM|LRESULT|WPARAM)\s* my @arguments;
\(\s*(.*?)\s*,\s*(.*?)\s*\)$/sx) 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; $low = $arguments[0];
$high = $2; $high = $arguments[1];
} elsif($value =~ /^(?:\(\w+\)\s*)?0L?$/) { } elsif(/^(?:\(\w+\)\s*)?0L?$/) {
$low = "0"; $low = "0";
$high = "0"; $high = "0";
} else { } else {
$low = "($value) & 0xffff"; $low = "($_) & 0xffff";
$high = "($value) << 16"; $high = "($_) << 16";
} }
$low =~ s/^\s*(.*?)\s*$/$1/;
$high =~ s/^\s*(.*?)\s*$/$1/;
return ($low, $high); 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 $name = shift;
(my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)}; (my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)};
if($msg =~ /^(?:WM_BEGINDRAG|WM_ENTERMENULOOP|WM_EXITMENULOOP|WM_HELP| if($msg !~ /^WM_/) {
WM_ISACTIVEICON|WM_LBTRACKPOINT|WM_NEXTMENU)$/x) return undef;
} elsif($msg =~ /^(?:WM_BEGINDRAG|WM_ENTERMENULOOP|WM_EXITMENULOOP|WM_HELP|
WM_ISACTIVEICON|WM_LBTRACKPOINT|WM_NEXTMENU)$/x)
{ {
return undef; return undef;
} elsif($msg =~ /^WM_(?:GET|SET)TEXT$/) {
return undef;
} }
my $suffix; my $suffix;
...@@ -62,8 +92,8 @@ sub fixup_function_call_2_forward_wm_call { ...@@ -62,8 +92,8 @@ sub fixup_function_call_2_forward_wm_call {
$suffix = ""; $suffix = "";
} }
$wparam =~ s/^\(WPARAM\)//; $wparam =~ s/^\(WPARAM\)\s*//;
$lparam =~ s/^\(LPARAM\)//; $lparam =~ s/^\(LPARAM\)\s*//;
my @arguments; my @arguments;
if(0) { if(0) {
...@@ -131,67 +161,161 @@ sub fixup_function_call_2_forward_wm_call { ...@@ -131,67 +161,161 @@ sub fixup_function_call_2_forward_wm_call {
return "FORWARD_" . $msg . "(" . join(", ", @arguments) . ", $name)"; 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 { sub fixup_statements {
my $function = shift; my $function = shift;
my $editor = shift; my $editor = shift;
my $file = $function->file;
my $linkage = $function->linkage; my $linkage = $function->linkage;
my $internal_name = $function->internal_name; my $name = $function->name;
my $statements_line = $function->statements_line; my $statements_line = $function->statements_line;
my $statements_column = $function->statements_column;
my $statements = $function->statements; my $statements = $function->statements;
if(($linkage eq "extern" && !defined($statements)) || if(!defined($statements)) {
($linkage eq "" && !defined($statements)))
{
return; 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 && if(0 && $statements_line > 490) {
$name =~ /^(?:DefWindowProc|SendMessage)[AW]$/ && $output->write("$statements_line: \\\n");
$$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");
}
};
my $line = $statements_line; my $line = $statements_line;
my $column = 1; foreach my $statement (split(/\n/, $statements)) {
$output->write("$line: $statement\n");
if(!&c_parser::parse_c_statements(\$statements, \$line, \$column, $found_function_call)) { $line++;
$output->write("error: can't parse statements\n");
} }
} }
}
sub fixup_replace { my $parser = new c_parser($file);
my $function = shift;
my $editor = shift; my $found_function_call = sub {
my $begin_line = shift; my $begin_line = shift;
my $begin_column = shift; my $begin_column = shift;
my $end_line = shift; my $end_line = shift;
my $end_column = 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($fixup_function_call)) {
my $replace = &$fixup_function_call($name, $arguments);
if(defined($replace)) { if(defined($replace)) {
$editor->replace($begin_line, $begin_column, $end_line, $end_column, $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");
} }
} }
......
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);
}
...@@ -70,9 +70,7 @@ sub new { ...@@ -70,9 +70,7 @@ sub new {
my $module_file = "$winapi_check_dir/modules.dat"; my $module_file = "$winapi_check_dir/modules.dat";
if($options->progress) { $output->progress("modules.dat");
$output->progress("modules.dat");
}
my %spec_file_found; my %spec_file_found;
my $allowed_dir; my $allowed_dir;
......
...@@ -36,9 +36,7 @@ sub new { ...@@ -36,9 +36,7 @@ sub new {
$configure_in_file =~ s/^\.\///; $configure_in_file =~ s/^\.\///;
$config_h_in_file =~ s/^\.\///; $config_h_in_file =~ s/^\.\///;
if($options->progress) { $output->progress("$api_file");
$output->progress("$api_file");
}
open(IN, "< $api_file"); open(IN, "< $api_file");
local $/ = "\n"; local $/ = "\n";
...@@ -51,9 +49,7 @@ sub new { ...@@ -51,9 +49,7 @@ sub new {
} }
close(IN); close(IN);
if($options->progress) { $output->progress("$configure_in_file");
$output->progress("$configure_in_file");
}
my $again = 0; my $again = 0;
open(IN, "< $configure_in_file"); open(IN, "< $configure_in_file");
...@@ -102,9 +98,7 @@ sub new { ...@@ -102,9 +98,7 @@ sub new {
} }
close(IN); close(IN);
if($options->progress) { $output->progress("$config_h_in_file");
$output->progress("$config_h_in_file");
}
open(IN, "< $config_h_in_file"); open(IN, "< $config_h_in_file");
local $/ = "\n"; local $/ = "\n";
......
...@@ -136,8 +136,6 @@ PLARGE_INTEGER ...@@ -136,8 +136,6 @@ PLARGE_INTEGER
PLONG PLONG
PTIMERAPCROUTINE PTIMERAPCROUTINE
PULARGE_INTEGER PULARGE_INTEGER
PVOID
PVOID *
SECURITY_ATTRIBUTES * SECURITY_ATTRIBUTES *
SYSLEVEL * SYSLEVEL *
SYSLEVEL ** SYSLEVEL **
......
...@@ -66,10 +66,12 @@ LPFONTDESC ...@@ -66,10 +66,12 @@ LPFONTDESC
LPOCPFIPARAMS LPOCPFIPARAMS
LPPICTDESC LPPICTDESC
LPSTREAM LPSTREAM
LPSYSTEMTIME
LPUNKNOWN LPUNKNOWN
LPUNKNOWN * LPUNKNOWN *
LPVOID LPVOID
LPVOID * LPVOID *
NUMPARSE *
OLECHAR * OLECHAR *
OLECHAR ** OLECHAR **
REFCLSID REFCLSID
...@@ -78,6 +80,7 @@ REFIID ...@@ -78,6 +80,7 @@ REFIID
SAFEARRAY * SAFEARRAY *
SAFEARRAY ** SAFEARRAY **
SAFEARRAYBOUND * SAFEARRAYBOUND *
UDATE *
UINT * UINT *
ULONG * ULONG *
USHORT * USHORT *
......
%long %long
DWORD
HRESULT HRESULT
%ptr %ptr
......
...@@ -6,6 +6,7 @@ DWORD ...@@ -6,6 +6,7 @@ DWORD
HANDLE HANDLE
HBITMAP HBITMAP
HDROP HDROP
HGLOBAL
HMENU HMENU
HICON HICON
HINSTANCE HINSTANCE
......
...@@ -43,7 +43,7 @@ POINT * ...@@ -43,7 +43,7 @@ POINT *
RECT * RECT *
WINDOWPOS * WINDOWPOS *
struct tagCURSORICONINFO * struct tagCURSORICONINFO *
struct tagWND *
void * void *
%str %str
......
...@@ -53,7 +53,6 @@ POINT * ...@@ -53,7 +53,6 @@ POINT *
RECT * RECT *
TEXTMETRICW * TEXTMETRICW *
WINDOWPOS * WINDOWPOS *
WND *
void * void *
%str %str
......
...@@ -105,9 +105,7 @@ sub parse_api_file { ...@@ -105,9 +105,7 @@ sub parse_api_file {
my $extension = 0; my $extension = 0;
my $forbidden = 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"; open(IN, "< $wine_dir/$file") || die "$wine_dir/$file: $!\n";
$/ = "\n"; $/ = "\n";
...@@ -217,9 +215,7 @@ sub parse_spec_file { ...@@ -217,9 +215,7 @@ sub parse_spec_file {
my $module; my $module;
my $module_file; my $module_file;
if($options->progress) { $output->lazy_progress("$file");
$output->lazy_progress("$file");
}
open(IN, "< $file") || die "$file: $!\n"; open(IN, "< $file") || die "$file: $!\n";
$/ = "\n"; $/ = "\n";
......
...@@ -26,6 +26,13 @@ use config qw( ...@@ -26,6 +26,13 @@ use config qw(
); );
use output qw($output); use output qw($output);
use winapi_check_options qw($options); use winapi_check_options qw($options);
if($options->progress) {
$output->enable_progress;
} else {
$output->disable_progress;
}
use modules qw($modules); use modules qw($modules);
use nativeapi qw($nativeapi); use nativeapi qw($nativeapi);
use winapi qw($win16api $win32api @winapis); use winapi qw($win16api $win32api @winapis);
...@@ -50,9 +57,7 @@ my %include2info; ...@@ -50,9 +57,7 @@ my %include2info;
foreach my $file (@files) { foreach my $file (@files) {
$progress_current++; $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; my $file_dir = $file;
if(!($file_dir =~ s%(.*?)/[^/]+$%$1%)) { if(!($file_dir =~ s%(.*?)/[^/]+$%$1%)) {
...@@ -128,9 +133,7 @@ if($options->headers) { ...@@ -128,9 +133,7 @@ if($options->headers) {
my %functions; my %functions;
$progress_current++; $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 { my $create_function = sub {
return 'winapi_function'->new; return 'winapi_function'->new;
...@@ -139,11 +142,13 @@ if($options->headers) { ...@@ -139,11 +142,13 @@ if($options->headers) {
my $found_function = sub { my $found_function = sub {
my $function = shift; 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; }); $output->prefix_callback(sub { return $function->prefix; });
my $function_line = $function->function_line; my $function_line = $function->function_line;
my $linkage = $function->linkage; my $linkage = $function->linkage;
my $internal_name = $function->internal_name;
my $external_name = $function->external_name; my $external_name = $function->external_name;
my $statements = $function->statements; my $statements = $function->statements;
...@@ -200,9 +205,7 @@ foreach my $file (@c_files) { ...@@ -200,9 +205,7 @@ foreach my $file (@c_files) {
my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file"); my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file");
$progress_current++; $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; my $file_dir = $file;
if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) { if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) {
...@@ -216,11 +219,12 @@ foreach my $file (@c_files) { ...@@ -216,11 +219,12 @@ foreach my $file (@c_files) {
my $found_function = sub { my $found_function = sub {
my $function = shift; my $function = shift;
$output->prefix_callback(sub { return $function->prefix; });
my $internal_name = $function->internal_name; my $internal_name = $function->internal_name;
$functions{$internal_name} = $function; $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 $declared_function = $declared_functions{$internal_name};
my $documentation_line = $function->documentation_line; my $documentation_line = $function->documentation_line;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment