Commit 11f03599 authored by Patrik Stridvall's avatar Patrik Stridvall Committed by Alexandre Julliard

- Made the new C parser handle the current Wine source.

- Added a compabillity layer between the old and the new C parser. - Added parsing of data structures.
parent 2693eb9a
#
# Copyright 2002 Patrik Stridvall
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
package c_type;
use strict;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub kind {
my $self = shift;
my $kind = \${$self->{KIND}};
local $_ = shift;
if(defined($_)) { $$kind = $_; }
return $$kind;
}
sub _name {
my $self = shift;
my $_name = \${$self->{_NAME}};
local $_ = shift;
if(defined($_)) { $$_name = $_; }
return $$_name;
}
sub name {
my $self = shift;
my $name = \${$self->{NAME}};
local $_ = shift;
if(defined($_)) { $$name = $_; }
return $$name;
}
sub fields {
my $self = shift;
my @field_types = @{$self->field_types};
my @field_names = @{$self->field_names};
my $count = scalar(@field_types);
my @fields = ();
for (my $n = 0; $n < $count; $n++) {
push @fields, [$field_types[$n], $field_names[$n]];
}
return @fields;
}
sub field_types {
my $self = shift;
my $field_types = \${$self->{FIELD_TYPES}};
local $_ = shift;
if(defined($_)) { $$field_types = $_; }
return $$field_types;
}
sub field_names {
my $self = shift;
my $field_names = \${$self->{FIELD_NAMES}};
local $_ = shift;
if(defined($_)) { $$field_names = $_; }
return $$field_names;
}
1;
......@@ -37,11 +37,13 @@ if($options->progress) {
$output->disable_progress;
}
use c_parser;
use function;
use type;
use winapi_function;
use winapi_parser;
use winapi qw($win16api $win32api @winapis);
use winapi_c_parser;
use winapi_function;
my %module2entries;
my %module2spec_file;
......@@ -174,8 +176,15 @@ sub statements_stub {
}
}
my @h_files = ();
if($options->headers) {
@h_files = $options->h_files;
@h_files = files_skip(@h_files);
@h_files = files_filter("winelib", @h_files);
}
my @c_files = ();
if($options->spec_files || $options->pseudo_stub_statistics) {
if(1 || $options->spec_files || $options->pseudo_stub_statistics) {
@c_files = $options->c_files;
@c_files = files_skip(@c_files);
@c_files = files_filter("winelib", @c_files);
......@@ -183,77 +192,148 @@ if($options->spec_files || $options->pseudo_stub_statistics) {
my $progress_output;
my $progress_current = 0;
my $progress_max = scalar(@c_files);
my $progress_max = scalar(@h_files) + scalar(@c_files);
foreach my $file (@c_files) {
foreach my $file (@h_files, @c_files) {
my %functions;
$progress_current++;
$output->progress("$file (file $progress_current of $progress_max)");
my $create_function = sub {
if($options->stub_statistics) {
return 'winapi_function'->new;
{
open(IN, "< $file");
local $/ = undef;
$_ = <IN>;
close(IN);
}
my $max_line = 0;
{
local $_ = $_;
while(s/^.*?\n//) { $max_line++; }
if($_) { $max_line++; }
}
my $parser;
if (!$options->old) {
$parser = new c_parser($file);
} else {
$parser = new winapi_c_parser($file);
}
my $function;
my $line;
my $update_output = sub {
my $progress = "";
my $prefix = "";
$progress .= "$file (file $progress_current of $progress_max)";
$prefix .= "$file:";
if(defined($function)) {
my $name = $function->name;
my $begin_line = $function->begin_line;
my $begin_column = $function->begin_column;
$progress .= ": function $name";
$prefix .= "$begin_line.$begin_column: function $name: ";
} else {
return 'function'->new;
$prefix .= " ";
}
if(defined($line)) {
$progress .= ": line $line of $max_line";
}
$output->progress($progress);
$output->prefix($prefix);
};
&$update_output();
my $found_function = sub {
my $function = shift;
$function = shift;
my $name = $function->name;
$functions{$name} = $function;
&$update_output();
my $old_function;
if($options->stub_statistics) {
$old_function = 'winapi_function'->new;
} else {
$old_function = 'function'->new;
}
my $internal_name = $function->internal_name;
$functions{$internal_name} = $function;
$function->file($file);
$old_function->debug_channels([]); # FIXME: Not complete
$output->progress("$file (file $progress_current of $progress_max): $internal_name");
$output->prefix_callback(sub { return $function->prefix; });
$old_function->documentation_line(0); # FIXME: Not complete
$old_function->documentation(""); # FIXME: Not complete
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 $statements = $function->statements;
$old_function->function_line($function->begin_line());
$old_function->linkage($function->linkage);
$old_function->return_type($function->return_type);
$old_function->calling_convention($function->calling_convention);
$old_function->internal_name($function->name);
if (defined($function->argument_types)) {
$old_function->argument_types([@{$function->argument_types}]);
}
if (defined($function->argument_names)) {
$old_function->argument_names([@{$function->argument_names}]);
}
$old_function->argument_documentations([]); # FIXME: Not complete
$old_function->statements_line($function->statements_line);
$old_function->statements($function->statements);
if($options->spec_files || $options->winetest) {
documentation_specifications($function);
documentation_specifications($old_function);
}
if($options->stub_statistics) {
statements_stub($function);
statements_stub($old_function);
}
$output->prefix("");
};
my $create_type = sub {
return 'type'->new;
$function = undef;
&$update_output();
};
$parser->set_found_function_callback($found_function);
my $found_type = sub {
my $type = shift;
};
my $found_preprocessor = sub {
my $directive = shift;
my $argument = shift;
&$update_output();
my $kind = $type->kind;
my $_name = $type->_name;
my $name = $type->name;
foreach my $field ($type->fields) {
(my $field_type, my $field_name) = @$field;
if ($options->struct) {
if ($name) {
$output->write("$name:$field_type:$field_name\n");
} else {
$output->write("$kind $_name:$field_type:$field_name\n");
}
}
}
return 1;
};
$parser->set_found_type_callback($found_type);
&winapi_parser::parse_c_file($file, {
# c_comment_found => $found_c_comment,
# cplusplus_comment_found => $found_cplusplus_comment,
function_create => $create_function,
function_found => $found_function,
type_create => $create_type,
type_found => $found_type,
preprocessor_found => $found_preprocessor
});
my @internal_names = keys(%functions);
if($#internal_names < 0) {
$output->write("$file: doesn't contain any functions\n");
{
my $line = 1;
my $column = 0;
if(!$parser->parse_c_file(\$_, \$line, \$column)) {
$output->write("can't parse file\n");
}
}
$output->prefix("");
}
sub output_function {
......
......@@ -40,13 +40,14 @@ my %options_long = (
"win16" => { default => 1, description => "Win16 extraction" },
"win32" => { default => 1, description => "Win32 extraction" },
"local" => { default => 1, description => "local extraction" },
"global" => { default => 1, description => "global extraction" },
"spec-files" => { default => 0, parent => "global", description => "spec files extraction" },
"stub-statistics" => { default => 1, parent => "global", description => "stub statistics" },
"pseudo-stub-statistics" => { default => 1, parent => "global", description => "pseudo stub statistics" },
"winetest" => { default => 1, parent => "global", description => "winetest extraction" },
"old" => { default => 0, description => "use the old parser" },
"headers" => { default => 0, description => "parse the .h files as well" },
"struct" => { default => 0, parent => "headers", description => "struct extraction" },
"spec-files" => { default => 0, parent => "old", description => "spec files extraction" },
"stub-statistics" => { default => 0, parent => "old", description => "stub statistics" },
"pseudo-stub-statistics" => { default => 0, parent => "stub-statistics", description => "pseudo stub statistics" },
"winetest" => { default => 0, parent => "old", description => "winetest extraction" },
);
my %options_short = (
......
......@@ -40,6 +40,7 @@ if($options->progress) {
$output->disable_progress;
}
use winapi_c_parser;
use c_parser;
use type;
......@@ -76,7 +77,12 @@ foreach my $file (@c_files) {
if($_) { $max_line++; }
}
my $parser = new c_parser($file);
my $parser;
if (1) {
$parser = new c_parser($file);
} else {
$parser = new winapi_c_parser($file);
}
my $function;
my $line;
......
#
# Copyright 1999, 2000, 2001 Patrik Stridvall
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
package winapi_c_parser;
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);
use c_function;
use c_type;
use function;
use winapi_function;
use winapi_parser;
########################################################################
# new
#
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
my $file = \${$self->{FILE}};
my $create_function = \${$self->{CREATE_FUNCTION}};
my $create_type = \${$self->{CREATE_TYPE}};
my $found_comment = \${$self->{FOUND_COMMENT}};
my $found_declaration = \${$self->{FOUND_DECLARATION}};
my $found_function = \${$self->{FOUND_FUNCTION}};
my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
my $found_line = \${$self->{FOUND_LINE}};
my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
my $found_statement = \${$self->{FOUND_STATEMENT}};
my $found_type = \${$self->{FOUND_TYPE}};
my $found_variable = \${$self->{FOUND_VARIABLE}};
$$file = shift;
$$create_function = sub { return new c_function; };
$$create_type = sub { return new c_type; };
$$found_comment = sub { return 1; };
$$found_declaration = sub { return 1; };
$$found_function = sub { return 1; };
$$found_function_call = sub { return 1; };
$$found_line = sub { return 1; };
$$found_preprocessor = sub { return 1; };
$$found_statement = sub { return 1; };
$$found_type = sub { return 1; };
$$found_variable = sub { return 1; };
return $self;
}
########################################################################
# 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_line_callback
#
sub set_found_line_callback {
my $self = shift;
my $found_line = \${$self->{FOUND_LINE}};
$$found_line = 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_type_callback
#
sub set_found_type_callback {
my $self = shift;
my $found_type = \${$self->{FOUND_TYPE}};
$$found_type = shift;
}
########################################################################
# set_found_variable_callback
#
sub set_found_variable_callback {
my $self = shift;
my $found_variable = \${$self->{FOUND_VARIABLE}};
$$found_variable = shift;
}
########################################################################
# parse_c_file
sub parse_c_file {
my $self = shift;
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_line = \${$self->{FOUND_LINE}};
my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
my $found_statement = \${$self->{FOUND_STATEMENT}};
my $found_variable = \${$self->{FOUND_VARIABLE}};
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
my $_create_function = sub {
return 'function'->new;
};
my $_create_type = sub {
return 'type'->new;
};
my $_found_function = sub {
my $old_function = shift;
my $function = new c_function;
$function->begin_line($old_function->function_line);
$function->begin_column(0);
$function->end_line($old_function->function_line);
$function->end_column(0);
$function->linkage($old_function->linkage);
$function->return_type($old_function->return_type);
$function->calling_convention($old_function->calling_convention);
$function->name($old_function->internal_name);
&$$found_function($function);
};
my $_found_preprocessor = sub {
my $directive = shift;
my $argument = shift;
my $begin_line = 0;
my $begin_column = 0;
my $preprocessor = "#$directive $argument";
&$$found_preprocessor($begin_line, $begin_column, $preprocessor);
};
my $_found_type = sub {
my $type = shift;
};
&winapi_parser::parse_c_file($$file, {
# c_comment_found => $found_c_comment,
# cplusplus_comment_found => $found_cplusplus_comment,
function_create => $_create_function,
function_found => $_found_function,
preprocessor_found => $_found_preprocessor,
type_create => $_create_type,
type_found => $_found_type,
});
}
1;
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