Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 1 | package winapi_fixup_statements; |
| 2 | |
| 3 | use strict; |
| 4 | |
| 5 | use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); |
| 6 | require Exporter; |
| 7 | |
| 8 | @ISA = qw(Exporter); |
| 9 | @EXPORT = qw(); |
| 10 | @EXPORT_OK = qw(&fixup_statements); |
| 11 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 12 | use config qw($wine_dir); |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 13 | use options qw($options); |
| 14 | use output qw($output); |
| 15 | |
| 16 | use c_parser; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 17 | use winapi_module_user qw( |
| 18 | &get_message_result_kind |
| 19 | &get_message_wparam_kind |
| 20 | &get_message_lparam_kind |
| 21 | ); |
| 22 | |
| 23 | ######################################################################## |
| 24 | # fixup_function_call |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 25 | |
| 26 | sub fixup_function_call { |
| 27 | my $name = shift; |
| 28 | my @arguments = @{(shift)};; |
| 29 | |
| 30 | return "$name(" . join(", ", @arguments) . ")"; |
| 31 | } |
| 32 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 33 | ######################################################################## |
| 34 | # _parse_makelong |
| 35 | |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 36 | sub _parse_makelong { |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 37 | local $_ = shift; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 38 | |
| 39 | my $low; |
| 40 | my $high; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 41 | |
| 42 | my $name; |
| 43 | my @arguments; |
| 44 | my @argument_lines; |
| 45 | my @argument_columns; |
| 46 | |
| 47 | my $parser = new c_parser; |
| 48 | |
| 49 | my $line = 1; |
| 50 | my $column = 0; |
| 51 | if($parser->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns) && |
| 52 | $name =~ /^MAKE(?:LONG|LPARAM|LRESULT|WPARAM)$/) |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 53 | { |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 54 | $low = $arguments[0]; |
| 55 | $high = $arguments[1]; |
| 56 | } elsif(/^(?:\(\w+\)\s*)?0L?$/) { |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 57 | $low = "0"; |
| 58 | $high = "0"; |
| 59 | } else { |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 60 | $low = "($_) & 0xffff"; |
| 61 | $high = "($_) << 16"; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 62 | } |
| 63 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 64 | $low =~ s/^\s*(.*?)\s*$/$1/; |
| 65 | $high =~ s/^\s*(.*?)\s*$/$1/; |
| 66 | |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 67 | return ($low, $high); |
| 68 | } |
| 69 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 70 | ######################################################################## |
| 71 | # fixup_function_call_2_windowsx |
| 72 | |
| 73 | sub fixup_user_message_2_windowsx { |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 74 | my $name = shift; |
| 75 | (my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)}; |
| 76 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 77 | if($msg !~ /^WM_/) { |
| 78 | return undef; |
| 79 | } elsif($msg =~ /^(?:WM_BEGINDRAG|WM_ENTERMENULOOP|WM_EXITMENULOOP|WM_HELP| |
| 80 | WM_ISACTIVEICON|WM_LBTRACKPOINT|WM_NEXTMENU)$/x) |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 81 | { |
| 82 | return undef; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 83 | } elsif($msg =~ /^WM_(?:GET|SET)TEXT$/) { |
| 84 | return undef; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | my $suffix; |
| 88 | $name =~ /([AW])?$/; |
| 89 | if(defined($1)) { |
| 90 | $suffix = $1; |
| 91 | } else { |
| 92 | $suffix = ""; |
| 93 | } |
| 94 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 95 | $wparam =~ s/^\(WPARAM\)\s*//; |
| 96 | $lparam =~ s/^\(LPARAM\)\s*//; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 97 | |
| 98 | my @arguments; |
| 99 | if(0) { |
| 100 | # Nothing |
| 101 | } elsif($msg =~ /^WM_COMMAND$/) { |
| 102 | (my $id, my $code_notify) = _parse_makelong($wparam); |
| 103 | my $hwndctl = $lparam; |
| 104 | @arguments = ($id, $hwndctl, $code_notify); |
| 105 | } elsif($msg =~ /^WM_(?:COPY|CUT|PASTE)$/) { |
| 106 | @arguments = (); |
| 107 | } elsif($msg =~ /^WM_(?:CHARTO|VKEYTO)ITEM$/) { |
| 108 | (my $key, my $caret) = _parse_makelong($wparam); |
| 109 | my $hwndctl = $lparam; |
| 110 | @arguments = ($key, $hwndctl, $caret); |
| 111 | } elsif($msg =~ /^WM_(?:COMPARE|DELETE|DRAW|MEASURE)ITEM$/) { |
| 112 | @arguments = ($lparam); |
| 113 | } elsif($msg =~ s/^WM_GETTEXT$/$&$suffix/) { |
| 114 | @arguments = ($wparam, $lparam); |
| 115 | } elsif($msg =~ /^WM_INITMENU$/) { |
| 116 | my $hmenu = $wparam; |
| 117 | @arguments = ($hmenu); |
| 118 | } elsif($msg =~ /^WM_INITMENUPOPUP$/) { |
| 119 | my $hmenu = $wparam; |
| 120 | (my $item, my $system_menu) = _parse_makelong($lparam); |
| 121 | @arguments = ($hmenu, $item, $system_menu); |
| 122 | } elsif($msg =~ /^WM_MENUCHAR$/) { |
| 123 | (my $ch, my $flags) = _parse_makelong($wparam); |
| 124 | my $hmenu = $lparam; |
| 125 | @arguments = ($ch, $flags, $hmenu); |
| 126 | } elsif($msg =~ /^WM_MENUSELECT$/) { |
| 127 | (my $item, my $flags) = _parse_makelong($wparam); |
| 128 | my $hmenu = $lparam; |
| 129 | my $hmenu_popup = "NULL"; # FIXME: Is this really correct? |
| 130 | @arguments = ($hmenu, $item, $hmenu_popup, $flags); |
| 131 | } elsif($msg =~ s/^WM_(NC)?LBUTTONDBLCLK$/WM_$1LBUTTONDOWN/) { |
| 132 | my $double_click = "TRUE"; |
| 133 | my $key_flags = $wparam; |
| 134 | (my $x, my $y) = _parse_makelong($lparam); |
| 135 | @arguments = ($double_click, $x, $y, $key_flags); |
| 136 | } elsif($msg =~ /^WM_(NC)?LBUTTONDOWN$/) { |
| 137 | my $double_click = "FALSE"; |
| 138 | my $key_flags = $wparam; |
| 139 | (my $x, my $y) = _parse_makelong($lparam); |
| 140 | @arguments = ($double_click, $x, $y, $key_flags); |
| 141 | } elsif($msg =~ /^WM_LBUTTONUP$/) { |
| 142 | my $key_flags = $wparam; |
| 143 | (my $x, my $y) = _parse_makelong($lparam); |
| 144 | @arguments = ($x, $y, $key_flags); |
| 145 | } elsif($msg =~ /^WM_SETCURSOR$/) { |
| 146 | my $hwnd_cursor = $wparam; |
| 147 | (my $code_hit_test, my $msg2) = _parse_makelong($lparam); |
| 148 | @arguments = ($hwnd_cursor, $code_hit_test, $msg2); |
| 149 | } elsif($msg =~ s/^WM_SETTEXT$/$&$suffix/) { |
| 150 | my $text = $lparam; |
| 151 | @arguments = ($text); |
| 152 | } elsif($msg =~ /^WM_(?:SYS)?KEYDOWN$/) { |
| 153 | my $vk = $wparam; |
| 154 | (my $repeat, my $flags) = _parse_makelong($lparam); |
| 155 | @arguments = ($vk, $repeat, $flags); |
| 156 | } else { |
| 157 | @arguments = ($wparam, $lparam); |
| 158 | } |
| 159 | unshift @arguments, $hwnd; |
| 160 | |
| 161 | return "FORWARD_" . $msg . "(" . join(", ", @arguments) . ", $name)"; |
| 162 | } |
| 163 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 164 | ######################################################################## |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 165 | # _get_messages |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 166 | |
| 167 | sub _get_messages { |
| 168 | local $_ = shift; |
| 169 | |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 170 | if(/^(?:BM|CB|EM|LB|STM|WM)_\w+(.*?)$/) { |
| 171 | if(!$1) { |
| 172 | return ($_); |
| 173 | } else { |
| 174 | return (); |
| 175 | } |
| 176 | } elsif(/^(.*?)\s*\?\s*((?:BM|CB|EM|LB|STM|WM)_\w+)\s*:\s*((?:BM|CB|EM|LB|STM|WM)_\w+)$/) { |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 177 | return ($2, $3); |
| 178 | } elsif(/^\w+$/) { |
| 179 | return (); |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 180 | } elsif(/^RegisterWindowMessage[AW]\s*\(.*?\)$/) { |
| 181 | return (); |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 182 | } else { |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 183 | $output->write("warning: _get_messages: '$_'\n"); |
| 184 | return (); |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 185 | } |
| 186 | } |
| 187 | |
| 188 | ######################################################################## |
| 189 | # _fixup_user_message |
| 190 | |
| 191 | sub _fixup_user_message { |
| 192 | my $name = shift; |
| 193 | (my $hwnd, my $msg, my $wparam, my $lparam) = @{(shift)}; |
| 194 | |
| 195 | my $modified = 0; |
| 196 | |
| 197 | my $wkind; |
| 198 | my $lkind; |
| 199 | foreach my $msg (_get_messages($msg)) { |
| 200 | my $new_wkind = &get_message_wparam_kind($msg); |
| 201 | if(defined($wkind) && $new_wkind ne $wkind) { |
| 202 | $output->write("messsages used together do not have the same type\n"); |
| 203 | } else { |
| 204 | $wkind = $new_wkind; |
| 205 | } |
| 206 | |
| 207 | my $new_lkind = &get_message_lparam_kind($msg); |
| 208 | if(defined($lkind) && $new_lkind ne $lkind) { |
| 209 | $output->write("messsages used together do not have the same type\n"); |
| 210 | } else { |
| 211 | $lkind = $new_lkind; |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | my @entries = ( |
| 216 | [ \$wparam, $wkind, "W", "w" ], |
| 217 | [ \$lparam, $lkind, "L", "l" ] |
| 218 | ); |
| 219 | foreach my $entry (@entries) { |
| 220 | (my $refparam, my $kind, my $upper, my $lower) = @$entry; |
| 221 | |
| 222 | if(!defined($kind)) { |
| 223 | if($msg =~ /^WM_/) { |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 224 | $output->write("messsage $msg not properly defined\n"); |
| 225 | $modified = 0; |
| 226 | last; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 227 | } |
| 228 | } elsif($kind eq "ptr") { |
| 229 | if($$refparam =~ /^(\(${upper}PARAM\))?\s*($lower[pP]aram)$/) { |
| 230 | if(defined($1)) { |
| 231 | $$refparam = $2; |
| 232 | $modified = 1; |
| 233 | } |
| 234 | } elsif($$refparam =~ /^(\(${upper}PARAM\))?\s*0$/) { |
| 235 | $$refparam = "(${upper}PARAM) NULL"; |
| 236 | $modified = 1; |
| 237 | } elsif($$refparam !~ /^\(${upper}PARAM\)\s*/) { |
| 238 | $$refparam = "(${upper}PARAM) $$refparam"; |
| 239 | $modified = 1; |
| 240 | } |
| 241 | } elsif($kind eq "long") { |
| 242 | if($$refparam =~ s/^\(${upper}PARAM\)\s*//) { |
| 243 | $modified = 1; |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | if($modified) { |
| 249 | my @arguments = ($hwnd, $msg, $wparam, $lparam); |
| 250 | return "$name(" . join(", ", @arguments) . ")"; |
| 251 | } else { |
| 252 | return undef; |
| 253 | } |
| 254 | } |
| 255 | |
| 256 | ######################################################################## |
| 257 | # fixup_statements |
| 258 | |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 259 | sub fixup_statements { |
| 260 | my $function = shift; |
| 261 | my $editor = shift; |
| 262 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 263 | my $file = $function->file; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 264 | my $linkage = $function->linkage; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 265 | my $name = $function->name; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 266 | my $statements_line = $function->statements_line; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 267 | my $statements_column = $function->statements_column; |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 268 | my $statements = $function->statements; |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 269 | |
| 270 | if(!defined($statements)) { |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 271 | return; |
| 272 | } |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 273 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 274 | my $parser = new c_parser($file); |
| 275 | |
| 276 | my $found_function_call = sub { |
| 277 | my $begin_line = shift; |
| 278 | my $begin_column = shift; |
| 279 | my $end_line = shift; |
| 280 | my $end_column = shift; |
| 281 | my $name = shift; |
| 282 | my $arguments = shift; |
| 283 | |
| 284 | foreach my $argument (@$arguments) { |
| 285 | $argument =~ s/^\s*(.*?)\s*$/$1/; |
| 286 | } |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 287 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 288 | my $fixup_function_call; |
| 289 | if($name =~ /^(?:DefWindowProc|SendMessage)[AW]$/) |
| 290 | { |
| 291 | if($options->statements_windowsx) { |
| 292 | $fixup_function_call = \&fixup_user_message_2_windowsx; |
| 293 | } else { |
| 294 | $fixup_function_call = \&_fixup_user_message; |
| 295 | } |
| 296 | } |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 297 | |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 298 | if(defined($fixup_function_call)) { |
| 299 | my $replace = &$fixup_function_call($name, $arguments); |
| 300 | |
| 301 | if(defined($replace)) { |
| 302 | $editor->replace($begin_line, $begin_column, $end_line, $end_column, $replace); |
| 303 | } |
Patrik Stridvall | d171a55 | 2001-09-10 23:16:05 +0000 | [diff] [blame^] | 304 | } elsif($options->debug) { |
Patrik Stridvall | aeb023f | 2001-08-22 18:09:15 +0000 | [diff] [blame] | 305 | $output->write("$begin_line.$begin_column-$end_line.$end_column: " . |
| 306 | "$name(" . join(", ", @$arguments) . ")\n"); |
| 307 | } |
| 308 | |
| 309 | return 0; |
| 310 | }; |
| 311 | |
| 312 | $parser->set_found_function_call_callback($found_function_call); |
| 313 | |
| 314 | my $line = $statements_line; |
| 315 | my $column = 0; |
| 316 | if(!$parser->parse_c_statements(\$statements, \$line, \$column)) { |
| 317 | $output->write("error: can't parse statements\n"); |
Patrik Stridvall | 4b33b13 | 2001-08-09 21:35:38 +0000 | [diff] [blame] | 318 | } |
| 319 | } |
| 320 | |
| 321 | 1; |