|  | # | 
|  | # 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; |