- Begun implementation of a C statements parser.
- More reorganizations and fixes.
diff --git a/tools/winapi/winapi_fixup b/tools/winapi/winapi_fixup
index f043138..3583143 100755
--- a/tools/winapi/winapi_fixup
+++ b/tools/winapi/winapi_fixup
@@ -18,14 +18,15 @@
);
use output qw($output);
use winapi_fixup_options qw($options);
-use modules qw($modules);
-use winapi qw($win16api $win32api @winapis);
use type;
-use util;
use winapi_function;
use winapi_parser;
+use winapi_fixup_documentation qw(&fixup_documentation);
+use winapi_fixup_editor;
+use winapi_fixup_statements qw(&fixup_statements);
+
my @c_files = $options->c_files;
@c_files = files_skip(@c_files);
@c_files = files_filter("winelib", @c_files);
@@ -35,400 +36,38 @@
my $progress_max = scalar(@c_files);
foreach my $file (@c_files) {
- my %insert_line;
- my %substitute_line;
- my %delete_line;
-
- my %spec_file;
+ 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)");
}
- my %documentation_line_used;
-
my $create_function = sub {
return 'winapi_function'->new;
};
my $found_function = sub {
my $function = shift;
-
- 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;
-
- if($linkage eq "static" ||
- ($linkage eq "extern" && !defined($statements)) ||
- ($linkage eq "" && !defined($statements)))
- {
- return;
+ if($options->progress) {
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
}
- my @external_names = $function->external_names;
- if($#external_names < 0) {
- return;
- }
-
- if($documentation_line_used{$documentation_line}) {
- $documentation = undef;
- }
- $documentation_line_used{$documentation_line}++;
-
$output->prefix_callback(sub { return $function->prefix; });
- my @module_ordinal_entries = ();
- foreach my $entry2 ($function->get_all_module_ordinal) {
- (my $external_name2, my $module2, my $ordinal2) = @$entry2;
- if(($external_name2 eq "@" ||
- ($win16api->is_module($module2) && !$win16api->is_function_stub_in_module($module2, $external_name2)) ||
- ($win32api->is_module($module2) && !$win32api->is_function_stub_in_module($module2, $external_name2))) &&
- $modules->is_allowed_module_in_file($module2, "$current_dir/$file"))
- {
- push @module_ordinal_entries, $entry2;
- }
+ if($options->documentation) {
+ fixup_documentation($function, $editor);
}
- my $spec_modified = 0;
-
- if($options->stub && defined($documentation)) {
- my $calling_convention16 = $function->calling_convention16;
- my $calling_convention32 = $function->calling_convention32;
-
- foreach my $winapi (@winapis) {
- my @entries = ();
- my $module = $winapi->function_internal_module($internal_name);
- my $ordinal = $winapi->function_internal_ordinal($internal_name);
-
- if($winapi->is_function_stub_in_module($module, $internal_name)) {
- my $external_name = $internal_name;
- if($winapi->name eq "win16") {
- $external_name =~ s/(?:_)?16([AW]?)$//;
- if(defined($1)) {
- $external_name .= $1;
- }
- }
- push @entries, [$external_name, $module, $ordinal];
- }
-
- foreach (split(/\n/, $documentation)) {
- if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
- my $external_name = $1;
- my $module = lc($2);
- my $ordinal = $3;
-
- if($external_name ne "@" &&
- $winapi->is_module($module) &&
- $winapi->is_function_stub_in_module($module, $external_name) &&
- $internal_name !~ /^\U$module\E_\Q$external_name\E$/)
- {
- push @entries, [$external_name, $module, $ordinal];
- }
- }
- }
-
- foreach my $entry (@entries) {
- (my $external_name, my $module, my $ordinal) = @$entry;
-
- my $refargument_types = $function->argument_types;
-
- if(!defined($refargument_types)) {
- next;
- }
-
- my $abort = 0;
- my $n;
- my @argument_kinds = map {
- my $type = $_;
- my $kind;
- if($type ne "..." && !defined($kind = $winapi->translate_argument($type))) {
- $output->write("no translation defined: " . $type . "\n");
- }
-
- # FIXME: Kludge
- if(defined($kind) && $kind eq "longlong") {
- $n += 2;
- ("long", "long");
- } elsif(defined($kind)) {
- $n++;
- $kind;
- } elsif($type eq "...") {
- if($winapi->name eq "win16") {
- $calling_convention16 = "pascal"; # FIXME: Is this correct?
- } else {
- $calling_convention32 = "varargs";
- }
- ();
- } else {
- $abort = 1;
- $n++;
- "undef";
- }
- } @$refargument_types;
-
- my $substitute = {};
- $substitute->{search} = "^\\s*$ordinal\\s+stub\\s+$external_name\\s*(?:#.*?)?\$";
-
- if($winapi->name eq "win16") {
- $substitute->{replace} = "$ordinal $calling_convention16 $external_name(@argument_kinds) $internal_name";
- } else {
- $substitute->{replace} = "$ordinal $calling_convention32 $external_name(@argument_kinds) $internal_name";
- }
-
- if(!defined($spec_file{$module})) {
- $spec_file{$module} = [];
- }
-
- if(!$abort) {
- $spec_modified = 1;
- push @{$spec_file{$module}}, $substitute;
- }
- }
- }
- }
-
- my %found_external_names;
- foreach my $external_name (@external_names) {
- $found_external_names{$external_name} = {};
- }
-
- my $documentation_modified = 0;
-
- if(!$spec_modified &&
- (defined($documentation) && !$documentation_modified) &&
- ($options->documentation_name || $options->documentation_ordinal ||
- $options->documentation_missing))
- {
- local $_;
-
- my $line3;
- my $search;
- my $replace;
-
- my $count = 0;
- my $line2 = $documentation_line - 1;
- foreach (split(/\n/, $documentation)) {
- $line2++;
- if(/^(\s*\*\s*(\S+)\s*)((?:\s*[\(\[]\s*\w+(?:\s*\.\s*[^\s\)\]]*\s*)?[\)\]])+)(.*?)$/) {
- my $part1 = $1;
- my $external_name = $2;
- my $part3 = $3;
- my $part4 = $4;
-
- $part4 =~ s/\s*$//;
-
- my @entries = ();
- while($part3 =~ s/^\s*([\(\[]\s*(\w+)(?:\s*\.\s*([^\s\)\]]*)\s*)?[\)\]])//) {
- push @entries, [$1, $2, $3];
- }
-
- my $found = 0;
- foreach my $external_name2 (@external_names) {
- if($external_name eq $external_name2) {
- foreach my $entry (@entries) {
- (undef, my $module, undef) = @$entry;
- $found_external_names{$external_name2}{$module} = 1;
- }
- $found = 1;
- last;
- }
- }
-
- my $replaced = 0;
- my $replace2 = "";
- foreach my $entry (@entries) {
- my $part12 = $part1;
- (my $part32, my $module, my $ordinal) = @$entry;
-
- foreach my $entry2 (@module_ordinal_entries) {
- (my $external_name2, my $module2, my $ordinal2) = @$entry2;
-
- if($options->documentation_name && lc($module) eq $module2 &&
- $external_name ne $external_name2)
- {
- if(!$found && $part12 =~ s/\b\Q$external_name\E\b/$external_name2/) {
- $external_name = $external_name2;
- $replaced++;
- }
- }
-
- if($options->documentation_ordinal &&
- $external_name eq $external_name2 &&
- lc($module) eq $module2 &&
- ($#entries > 0 || !defined($ordinal) || ($ordinal ne $ordinal2)))
- {
- if(defined($ordinal)) {
- if($part32 =~ s/\Q$module\E\s*.\s*\Q$ordinal\E/\U$module2\E.$ordinal2/ || $#entries > 0) {
- $replaced++;
- }
- } else {
- if($part32 =~ s/\Q$module\E/\U$module2\E.$ordinal2/ || $#entries > 0) {
- $replaced++;
- }
- }
- }
-
- }
- if($replace2) { $replace2 .= "\n"; }
- $replace2 .= "$part12$part32$part4";
- }
-
- if($replaced > 0) {
- $line3 = $line2;
- $search = "^\Q$_\E\$";
- $replace = $replace2;
- }
- $count++;
- } elsif(/^(\s*\*\s*)([^\s\(]+)(?:\(\))?\s*$/) {
- my $part1 = $1;
- my $external_name = $2;
-
- if($internal_name =~ /^(?:\S+_)?\Q$external_name\E(?:16)?$/) {
- foreach my $entry (@module_ordinal_entries) {
- (my $external_name2, my $module, my $ordinal) = @$entry;
-
- $line3 = $line2;
- $search = "^\Q$_\E\$";
- $replace = "$part1$external_name2 (\U$module\E.$ordinal)";
- }
- $count++;
- }
- }
- }
-
- if(defined($line3) && defined($search) && defined($replace)) {
- if($count > 1 || $#external_names >= 1) {
- $output->write("multiple entries (fixup not supported)\n");
- # $output->write("s/$search/$replace/\n");
- # $output->write("@external_names\n");
- } else {
- $documentation_modified = 1;
-
- $substitute_line{$line3}{search} = $search;
- $substitute_line{$line3}{replace} = $replace;
-
- }
- }
- }
-
- if(!$spec_modified && !$documentation_modified &&
- $options->documentation_missing && defined($documentation))
- {
- my $part1;
- my $part2;
- my $part3;
- my $part4;
- my $line3 = 0;
-
- my $line2 = $documentation_line - 1;
- foreach (split(/\n/, $documentation)) {
- $line2++;
- if(/^(\s*\*\s*)(\S+\s*)([\(\[])\s*\w+\s*\.\s*[^\s\)\]]*\s*([\)\]]).*?$/) {
- $part1 = $1;
- $part2 = $2;
- $part3 = $3;
- $part4 = $4;
-
- $part2 =~ s/\S/ /g;
-
- $line3 = $line2 + 1;
- }
- }
-
- foreach my $entry2 (@module_ordinal_entries) {
- (my $external_name2, my $module2, my $ordinal2) = @$entry2;
-
- my $found = 0;
- foreach my $external_name (keys(%found_external_names)) {
- foreach my $module3 (keys(%{$found_external_names{$external_name}})) {
- if($external_name eq $external_name2 && uc($module2) eq $module3) {
- $found = 1;
- }
- }
- }
- # FIXME: Not 100% correct
- if(!$found &&
- !$win16api->is_function_stub_in_module($module2, $internal_name) &&
- !$win32api->is_function_stub_in_module($module2, $internal_name))
- {
- if($line3 > 0) {
- $documentation_modified = 1;
-
- $part2 = $external_name2 . " " x (length($part2) - length($external_name2));
- $insert_line{$line3} = "$part1$part2$part3\U$module2\E.$ordinal2$part4\n";
- } else {
- $output->write("$external_name2 (\U$module2\E.$ordinal2) missing (fixup not supported)\n");
- }
- }
- }
- }
-
- if(!$documentation_modified &&
- defined($documentation) &&
- $options->documentation_wrong)
- {
- my $line2 = $documentation_line - 1;
- foreach (split(/\n/, $documentation)) {
- $line2++;
- if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
- my $external_name = $1;
- my $module = $2;
- my $ordinal = $3;
-
- my $found = 0;
- foreach my $entry2 (@module_ordinal_entries) {
- (my $external_name2, my $module2, my $ordinal2) = @$entry2;
-
- if($external_name eq $external_name2 &&
- lc($module) eq $module2 &&
- $ordinal eq $ordinal2)
- {
- $found = 1;
- }
- }
- if(!$found) {
- if(1) {
- $documentation_modified = 1;
-
- $delete_line{$line2} = "^\Q$_\E\$";
- } else {
- $output->write("$external_name (\U$module\E.$ordinal) wrong (fixup not supported)\n");
- };
- }
- }
- }
- }
-
- if(!$spec_modified && !$documentation_modified && !defined($documentation))
- {
- my $insert = "";
- foreach my $winapi (@winapis) {
- my $external_name = $winapi->function_external_name($internal_name);
- my $module = $winapi->function_internal_module($internal_name);
- my $ordinal = $winapi->function_internal_ordinal($internal_name);
-
- if(defined($external_name) && defined($module) && defined($ordinal)) {
- $insert .= " *\t\t$external_name (\U$module\E.$ordinal)\n";
- }
- }
- if($insert) {
- $insert_line{$function_line} =
- "/" . "*" x 71 . "\n" .
- "$insert" .
- " */\n";
- }
+ if($options->statements) {
+ fixup_statements($function, $editor);
}
$output->prefix("");
};
-
my $create_type = sub {
return 'type'->new;
};
@@ -444,160 +83,6 @@
&winapi_parser::parse_c_file($file, $create_function, $found_function, $create_type, $found_type, $found_preprocessor);
- my $editor = sub {
- local *IN = shift;
- local *OUT = shift;
-
- my $modified = 0;
- while(<IN>) {
- chomp;
-
- my $line;
-
- $line = $insert_line{$.};
- if(defined($line)) {
- if($options->modify) {
- $_ = "$line$_";
- $modified = 1;
- } else {
- my $line2 = $line; chomp($line2);
- my @line2 = split(/\n/, $line2);
- if($#line2 > 0) {
- $output->write("$file: $.: insert: \\\n");
- foreach my $line2 (@line2) {
- $output->write("'$line2'\n");
- }
- } else {
- $output->write("$file: $.: insert: '$line2'\n");
- }
- }
- }
-
- my $search = $substitute_line{$.}{search};
- my $replace = $substitute_line{$.}{replace};
-
- if(defined($search) && defined($replace)) {
- my $modified2 = 0;
- if(s/$search/$replace/) {
- if($options->modify) {
- $modified = 1;
- }
- $modified2 = 1;
- }
-
- if(!$options->modify || !$modified2) {
- my $search2;
- my $replace2;
- if(!$modified2) {
- $search2 = "unmatched search";
- $replace2 = "unmatched replace";
- } else {
- $search2 = "search";
- $replace2 = "replace";
- }
- $output->write("$file: $.: $search2 : '$search'\n");
-
- my @replace2 = split(/\n/, $replace);
- if($#replace2 > 0) {
- $output->write("$file: $.: $replace2: \\\n");
- foreach my $replace2 (@replace2) {
- $output->write("'$replace2'\n");
- }
- } else {
- $output->write("$file: $.: $replace2: '$replace'\n");
- }
- }
- }
-
- $line = $delete_line{$.};
- if(defined($line)) {
- if(/$line/) {
- if($options->modify) {
- $modified = 1;
- next;
- } else {
- $output->write("$file: $.: delete: '$line'\n");
- }
- } else {
- $output->write("$file: $.: unmatched delete: '$line'\n");
- }
- }
-
- print OUT "$_\n";
- }
-
- return $modified;
- };
-
- my $n = 0;
- while(defined(each %insert_line)) { $n++; }
- while(defined(each %substitute_line)) { $n++; }
- while(defined(each %delete_line)) { $n++; }
- if($n > 0) {
- edit_file($file, $editor);
- }
-
- foreach my $module (sort(keys(%spec_file))) {
- my $file;
- foreach my $winapi (@winapis) {
- $file = ($winapi->module_file($module) || $file);
- }
-
- if(defined($file)) {
- $file = file_normalize($file);
- }
-
- my @substitutes = @{$spec_file{$module}};
-
- my $editor = sub {
- local *IN = shift;
- local *OUT = shift;
-
- my $modified = 0;
- while(<IN>) {
- chomp;
-
- my @substitutes2 = ();
- foreach my $substitute (@substitutes) {
- my $search = $substitute->{search};
- my $replace = $substitute->{replace};
-
- if(s/$search/$replace/) {
- if($options->modify) {
- $modified = 1;
- } else {
- $output->write("$file: search : '$search'\n");
- $output->write("$file: replace: '$replace'\n");
- }
- next;
- } else {
- push @substitutes2, $substitute;
- }
- }
- @substitutes = @substitutes2;
-
- print OUT "$_\n";
- }
-
- return $modified;
- };
-
- if(defined($file)) {
- edit_file($file, $editor);
- } else {
- $output->write("$module: doesn't have any spec file\n");
- }
-
- if($#substitutes >= 0) {
- foreach my $substitute (@substitutes) {
- my $search = $substitute->{search};
- my $replace = $substitute->{replace};
-
- $output->write("$file: unmatched search : '$search'\n");
- $output->write("$file: unmatched replace: '$replace'\n");
- }
- }
-
- }
+ $editor->flush;
}