shell32: Fix and simplify the FO_COPY operation, with tests.
[wine.git] / tools / winapi / winapi_fixup_editor.pm
blob1548e3c626eeccb5866311345967f1fbb94b07f6
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 package winapi_fixup_editor;
21 use strict;
23 use options qw($options);
24 use output qw($output);
25 use winapi qw($win16api $win32api @winapis);
27 use util;
29 sub new($$) {
30 my $proto = shift;
31 my $class = ref($proto) || $proto;
32 my $self = {};
33 bless ($self, $class);
35 my $file = \${$self->{FILE}};
37 $$file = shift;
39 return $self;
42 sub add_trigger($$$) {
43 my $self = shift;
45 my $triggers = \%{$self->{TRIGGERS}};
47 my $line = shift;
48 my $action = shift;
50 if(!defined($$triggers{$line})) {
51 $$triggers{$line} = [];
54 push @{$$triggers{$line}}, $action;
57 sub replace($$$$$$) {
58 my $self = shift;
60 my $begin_line = shift;
61 my $begin_column = shift;
62 my $end_line = shift;
63 my $end_column = shift;
64 my $replace = shift;
66 my $file = \${$self->{FILE}};
68 my $line = $begin_line;
69 my $action = {};
71 $self->add_trigger($begin_line, {
72 type => "replace",
73 begin_line => $begin_line,
74 begin_column => $begin_column,
75 end_line => $end_line,
76 end_column => $end_column,
77 replace => $replace
78 });
81 sub flush($) {
82 my $self = shift;
84 my $file = \${$self->{FILE}};
85 my $triggers = \%{$self->{TRIGGERS}};
87 my $editor = sub {
88 local *IN = shift;
89 local *OUT = shift;
91 my $modified = 0;
93 my $again = 0;
94 my $lookahead = 0;
95 my $lookahead_count = 0;
96 LINE: while($again || defined(my $current = <IN>)) {
97 if(!$again) {
98 chomp $current;
100 if($lookahead) {
101 $lookahead = 0;
102 $_ .= "\n" . $current;
103 $lookahead_count++;
104 } else {
105 $_ = $current;
106 $lookahead_count = 0;
108 } else {
109 $lookahead_count = 0;
110 $again = 0;
113 my $line = $. - $lookahead_count;
114 foreach my $action (@{$$triggers{$line}}) {
115 if($. < $action->{end_line}) {
116 $lookahead = 1;
117 next LINE;
120 my $type = $action->{type};
121 my $begin_line = $action->{begin_line};
122 my $begin_column = $action->{begin_column};
123 my $end_line = $action->{end_line};
124 my $end_column = $action->{end_column};
126 if($type eq "replace") {
127 my $replace = $action->{replace};
129 my @lines = split(/\n/, $_);
130 if($#lines < 0) {
131 @lines = ($_);
134 my $begin = "";
135 my $column = 0;
136 $_ = $lines[0];
137 while($column < $begin_column - 1 && s/^.//) {
138 $begin .= $&;
139 if($& eq "\t") {
140 $column = $column + 8 - $column % 8;
141 } else {
142 $column++;
146 my $column2 = 0;
147 $_ = $lines[$#lines];
148 while($column2 < $end_column && s/^.//) {
149 if($& eq "\t") {
150 $column2 = $column2 + 8 - $column2 % 8;
151 } else {
152 $column2++;
155 my $end = $_;
157 $_ = "$begin$replace$end";
158 if($options->modify) {
159 $modified = 1;
160 } else {
161 $output->write("$$file:$begin_line.$begin_column-$end_line.$end_column: $replace\n");
166 print OUT "$_\n";
169 return $modified;
172 my $modified = 0;
173 if(1) {
174 $modified = edit_file($$file, $editor);
177 if(!$modified) {
178 $self->flush_old;
182 ########################################################################
183 # Hack for backward compabillity
186 my %insert_line;
187 my %substitute_line;
188 my %delete_line;
190 my %spec_file;
192 sub flush_old($) {
193 my $self = shift;
195 my $file = ${$self->{FILE}};
197 my $editor = sub {
198 local *IN = shift;
199 local *OUT = shift;
201 my $modified = 0;
202 while(<IN>) {
203 chomp;
205 my $line;
207 $line = $insert_line{$.};
208 if(defined($line)) {
209 if($options->modify) {
210 $_ = "$line$_";
211 $modified = 1;
212 } else {
213 my $line2 = $line; chomp($line2);
214 my @line2 = split(/\n/, $line2);
215 if($#line2 > 0) {
216 $output->write("$file: $.: insert: \\\n");
217 foreach my $line2 (@line2) {
218 $output->write("'$line2'\n");
220 } else {
221 $output->write("$file: $.: insert: '$line2'\n");
226 my $search = $substitute_line{$.}{search};
227 my $replace = $substitute_line{$.}{replace};
229 if(defined($search) && defined($replace)) {
230 my $modified2 = 0;
231 if(s/$search/$replace/) {
232 if($options->modify) {
233 $modified = 1;
235 $modified2 = 1;
238 if(!$options->modify || !$modified2) {
239 my $search2;
240 my $replace2;
241 if(!$modified2) {
242 $search2 = "unmatched search";
243 $replace2 = "unmatched replace";
244 } else {
245 $search2 = "search";
246 $replace2 = "replace";
248 $output->write("$file: $.: $search2 : '$search'\n");
250 my @replace2 = split(/\n/, $replace);
251 if($#replace2 > 0) {
252 $output->write("$file: $.: $replace2: \\\n");
253 foreach my $replace2 (@replace2) {
254 $output->write("'$replace2'\n");
256 } else {
257 $output->write("$file: $.: $replace2: '$replace'\n");
262 $line = $delete_line{$.};
263 if(defined($line)) {
264 if(/$line/) {
265 if($options->modify) {
266 $modified = 1;
267 next;
268 } else {
269 $output->write("$file: $.: delete: '$line'\n");
271 } else {
272 $output->write("$file: $.: unmatched delete: '$line'\n");
276 print OUT "$_\n";
279 return $modified;
282 my $n = 0;
283 while(defined(each %insert_line)) { $n++; }
284 while(defined(each %substitute_line)) { $n++; }
285 while(defined(each %delete_line)) { $n++; }
286 if($n > 0) {
287 edit_file($file, $editor);
290 foreach my $module (sort(keys(%spec_file))) {
291 my $file;
292 foreach my $winapi (@winapis) {
293 $file = ($winapi->module_file($module) || $file);
296 if(defined($file)) {
297 $file = file_normalize($file);
300 my @substitutes = @{$spec_file{$module}};
302 my $editor = sub {
303 local *IN = shift;
304 local *OUT = shift;
306 my $modified = 0;
307 while(<IN>) {
308 chomp;
310 my @substitutes2 = ();
311 foreach my $substitute (@substitutes) {
312 my $search = $substitute->{search};
313 my $replace = $substitute->{replace};
315 if(s/$search/$replace/) {
316 if($options->modify) {
317 $modified = 1;
318 } else {
319 $output->write("$file: search : '$search'\n");
320 $output->write("$file: replace: '$replace'\n");
322 next;
323 } else {
324 push @substitutes2, $substitute;
327 @substitutes = @substitutes2;
329 print OUT "$_\n";
332 return $modified;
335 if(defined($file)) {
336 edit_file($file, $editor);
337 } else {
338 $output->write("$module: doesn't have any spec file\n");
341 if($#substitutes >= 0) {
342 foreach my $substitute (@substitutes) {
343 my $search = $substitute->{search};
344 my $replace = $substitute->{replace};
346 $output->write("$file: unmatched search : '$search'\n");
347 $output->write("$file: unmatched replace: '$replace'\n");
353 %insert_line = ();
354 %substitute_line = ();
355 %delete_line = ();
357 %spec_file = ();
360 sub delete_line($$$) {
361 my $self = shift;
363 my $line = shift;
364 my $pattern = shift;
366 $delete_line{$line} = $pattern;
369 sub insert_line($$$) {
370 my $self = shift;
372 my $line = shift;
373 my $insert = shift;
375 $insert_line{$line} = $insert;
378 sub substitute_line($$$$) {
379 my $self = shift;
381 my $line = shift;
382 my $search = shift;
383 my $replace = shift;
385 $substitute_line{$line}{search} = $search;
386 $substitute_line{$line}{replace} = $replace;
389 sub replace_spec_file($$$$) {
390 my $self = shift;
392 my $module = shift;
393 my $search = shift;
394 my $replace = shift;
396 my $substitute = {};
397 $substitute->{search} = $search;
398 $substitute->{replace} = $replace;
400 if(!defined($spec_file{$module})) {
401 $spec_file{$module} = [];
404 push @{$spec_file{$module}}, $substitute;