| # | |
| # 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_fixup_editor; | |
| use strict; | |
| use options qw($options); | |
| use output qw($output); | |
| use winapi qw($win16api $win32api @winapis); | |
| use util; | |
| sub new($$) { | |
| my $proto = shift; | |
| my $class = ref($proto) || $proto; | |
| my $self = {}; | |
| bless ($self, $class); | |
| my $file = \${$self->{FILE}}; | |
| $$file = shift; | |
| return $self; | |
| } | |
| sub add_trigger($$$) { | |
| my $self = shift; | |
| my $triggers = \%{$self->{TRIGGERS}}; | |
| my $line = shift; | |
| my $action = shift; | |
| if(!defined($$triggers{$line})) { | |
| $$triggers{$line} = []; | |
| } | |
| push @{$$triggers{$line}}, $action; | |
| } | |
| sub replace($$$$$$) { | |
| my $self = shift; | |
| my $begin_line = shift; | |
| my $begin_column = shift; | |
| my $end_line = shift; | |
| my $end_column = shift; | |
| my $replace = shift; | |
| my $file = \${$self->{FILE}}; | |
| my $line = $begin_line; | |
| my $action = {}; | |
| $self->add_trigger($begin_line, { | |
| type => "replace", | |
| begin_line => $begin_line, | |
| begin_column => $begin_column, | |
| end_line => $end_line, | |
| end_column => $end_column, | |
| replace => $replace | |
| }); | |
| } | |
| sub flush($) { | |
| my $self = shift; | |
| my $file = \${$self->{FILE}}; | |
| my $triggers = \%{$self->{TRIGGERS}}; | |
| my $editor = sub { | |
| local *IN = shift; | |
| local *OUT = shift; | |
| my $modified = 0; | |
| my $again = 0; | |
| my $lookahead = 0; | |
| my $lookahead_count = 0; | |
| LINE: while($again || defined(my $current = <IN>)) { | |
| if(!$again) { | |
| chomp $current; | |
| if($lookahead) { | |
| $lookahead = 0; | |
| $_ .= "\n" . $current; | |
| $lookahead_count++; | |
| } else { | |
| $_ = $current; | |
| $lookahead_count = 0; | |
| } | |
| } else { | |
| $lookahead_count = 0; | |
| $again = 0; | |
| } | |
| my $line = $. - $lookahead_count; | |
| foreach my $action (@{$$triggers{$line}}) { | |
| if($. < $action->{end_line}) { | |
| $lookahead = 1; | |
| next LINE; | |
| } | |
| my $type = $action->{type}; | |
| my $begin_line = $action->{begin_line}; | |
| my $begin_column = $action->{begin_column}; | |
| my $end_line = $action->{end_line}; | |
| my $end_column = $action->{end_column}; | |
| if($type eq "replace") { | |
| my $replace = $action->{replace}; | |
| my @lines = split(/\n/, $_); | |
| if($#lines < 0) { | |
| @lines = ($_); | |
| } | |
| my $begin = ""; | |
| my $column = 0; | |
| $_ = $lines[0]; | |
| while($column < $begin_column - 1 && s/^.//) { | |
| $begin .= $&; | |
| if($& eq "\t") { | |
| $column = $column + 8 - $column % 8; | |
| } else { | |
| $column++; | |
| } | |
| } | |
| my $column2 = 0; | |
| $_ = $lines[$#lines]; | |
| while($column2 < $end_column && s/^.//) { | |
| if($& eq "\t") { | |
| $column2 = $column2 + 8 - $column2 % 8; | |
| } else { | |
| $column2++; | |
| } | |
| } | |
| my $end = $_; | |
| $_ = "$begin$replace$end"; | |
| if($options->modify) { | |
| $modified = 1; | |
| } else { | |
| $output->write("$$file:$begin_line.$begin_column-$end_line.$end_column: $replace\n"); | |
| } | |
| } | |
| } | |
| print OUT "$_\n"; | |
| } | |
| return $modified; | |
| }; | |
| my $modified = 0; | |
| if(1) { | |
| $modified = edit_file($$file, $editor); | |
| } | |
| if(!$modified) { | |
| $self->flush_old; | |
| } | |
| } | |
| ######################################################################## | |
| # Hack for backward compabillity | |
| # | |
| my %insert_line; | |
| my %substitute_line; | |
| my %delete_line; | |
| my %spec_file; | |
| sub flush_old($) { | |
| my $self = shift; | |
| my $file = ${$self->{FILE}}; | |
| 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"); | |
| } | |
| } | |
| } | |
| %insert_line = (); | |
| %substitute_line = (); | |
| %delete_line = (); | |
| %spec_file = (); | |
| } | |
| sub delete_line($$$) { | |
| my $self = shift; | |
| my $line = shift; | |
| my $pattern = shift; | |
| $delete_line{$line} = $pattern; | |
| } | |
| sub insert_line($$$) { | |
| my $self = shift; | |
| my $line = shift; | |
| my $insert = shift; | |
| $insert_line{$line} = $insert; | |
| } | |
| sub substitute_line($$$$) { | |
| my $self = shift; | |
| my $line = shift; | |
| my $search = shift; | |
| my $replace = shift; | |
| $substitute_line{$line}{search} = $search; | |
| $substitute_line{$line}{replace} = $replace; | |
| } | |
| sub replace_spec_file($$$$) { | |
| my $self = shift; | |
| my $module = shift; | |
| my $search = shift; | |
| my $replace = shift; | |
| my $substitute = {}; | |
| $substitute->{search} = $search; | |
| $substitute->{replace} = $replace; | |
| if(!defined($spec_file{$module})) { | |
| $spec_file{$module} = []; | |
| } | |
| push @{$spec_file{$module}}, $substitute; | |
| } | |
| 1; |