Ticket #688: pbc_to_exe_win32_msvc_fix.patch
File pbc_to_exe_win32_msvc_fix.patch, 10.2 KB (added by Util, 13 years ago) |
---|
-
tools/dev/pbc_to_exe.pir
20 20 21 21 .sub 'main' :main 22 22 .param pmc argv 23 24 load_bytecode 'config.pbc' 25 23 26 .local string infile 24 27 .local string cfile 25 28 .local string objfile 26 29 .local string exefile 27 .local string out28 .local int closeresult29 30 30 .local string gcc31 .local int is_gcc32 load_bytecode 'config.pbc'33 $P0 = '_config'()34 gcc = $P0['gccversion']35 $I0 = length gcc36 is_gcc = $I0 > 037 38 31 (infile, cfile, objfile, exefile) = 'handle_args'(argv) 39 32 unless infile > '' goto err_infile 40 33 34 35 .local string code_type 36 code_type = 'determine_code_type'() 37 41 38 .local string codestring 42 unless is_gcc goto code_for_non_gcc 39 if code_type == 'gcc' goto code_for_gcc 40 if code_type == 'msvc' goto code_for_msvc 41 goto code_for_default 43 42 code_for_gcc: 44 43 codestring = 'generate_code_gcc'(infile) 45 44 goto code_end 46 code_for_non_gcc: 45 code_for_msvc: 46 codestring = 'generate_code_msvc'(infile) 47 goto code_end 48 code_for_default: 47 49 codestring = 'generate_code'(infile) 48 50 code_end: 49 51 52 50 53 open_outfile: 51 54 .local pmc outfh 52 55 outfh = open cfile, 'w' … … 54 57 print outfh, <<'HEADER' 55 58 #include "parrot/parrot.h" 56 59 #include "parrot/embed.h" 60 void * get_program_code(void); 57 61 HEADER 58 62 59 63 print outfh, codestring … … 63 67 { 64 68 PackFile *pf; 65 69 Parrot_Interp interp; 70 unsigned char *program_code_addr; 66 71 72 program_code_addr = get_program_code(); 73 if (!program_code_addr) 74 return 1; 75 67 76 Parrot_set_config_hash(); 68 77 69 78 interp = Parrot_new( NULL ); 70 71 79 if (!interp) 72 80 return 1; 73 81 … … 76 84 Parrot_set_flag(interp, PARROT_DESTROY_FLAG); 77 85 78 86 pf = PackFile_new(interp, 0); 87 if (!pf) 88 return 1; 79 89 80 90 if (!PackFile_unpack(interp, pf, 81 (const opcode_t *)program_code , bytecode_size))91 (const opcode_t *)program_code_addr, bytecode_size)) 82 92 return 1; 83 93 84 94 do_sub_pragmas(interp, pf->cur_cs, PBC_PBC, NULL); … … 92 102 } 93 103 MAIN 94 104 105 95 106 # The close opcode does not return a result code, 96 107 # use the method instead. 108 .local int closeresult 97 109 closeresult = outfh.'close'() 98 110 unless closeresult == 0 goto err_close 99 111 112 113 .local string extra_obj 114 extra_obj = '' 115 if code_type != 'msvc' goto no_extra 116 extra_obj = 'replace_pbc_extension'(infile, '.RES') 117 no_extra: 118 119 100 120 'compile_file'(cfile, objfile) 101 'link_file'(objfile, exefile )121 'link_file'(objfile, exefile, extra_obj) 102 122 .return () 103 123 104 124 err_infile: … … 113 133 .sub 'handle_args' 114 134 .param pmc argv 115 135 136 .local string obj, exe 137 $P0 = '_config'() 138 obj = $P0['o'] 139 exe = $P0['exe'] 140 116 141 .local pmc args 117 142 args = argv 118 143 … … 133 158 .return () 134 159 135 160 proper_install: 136 .local string cfile, objfile, obj, exefile, exe161 .local string cfile, objfile, exefile 137 162 138 $P0 = '_config'() 139 obj = $P0['o'] 140 exe = $P0['exe'] 163 cfile = 'replace_pbc_extension'(infile, '.c') 164 objfile = 'replace_pbc_extension'(infile, obj) 165 $S0 = 'replace_pbc_extension'(infile, exe) 166 exefile = concat 'installable_', $S0 141 167 142 .local int infile_len143 infile_len = length infile144 infile_len -= 3145 146 cfile = substr infile, 0, infile_len147 cfile .= 'c'148 149 dec infile_len150 objfile = substr infile, 0, infile_len151 exefile = 'installable_'152 exefile .= objfile153 exefile .= exe154 objfile .= obj155 168 .return(infile, cfile, objfile, exefile) 156 169 157 170 proper_args: 158 .local string infile, cfile, objfile, obj, exefile, exe171 .local string infile, cfile, objfile, exefile 159 172 160 $P0 = '_config'()161 obj = $P0['o']162 exe = $P0['exe']163 164 173 $P0 = shift args 165 174 infile = shift args 166 175 167 .local int infile_len168 infile_len = length infile169 infile_len -= 3176 cfile = 'replace_pbc_extension'(infile, '.c') 177 objfile = 'replace_pbc_extension'(infile, obj) 178 exefile = 'replace_pbc_extension'(infile, exe) 170 179 171 cfile = substr infile, 0, infile_len172 cfile .= 'c'173 174 dec infile_len175 objfile = substr infile, 0, infile_len176 objfile .= obj177 exefile = substr infile, 0, infile_len178 exefile .= exe179 180 180 # substitute .c for .pbc 181 181 # remove .c for executable 182 182 … … 184 184 .return(infile, cfile, objfile, exefile) 185 185 .end 186 186 187 .sub 'determine_code_type' 188 .local pmc config 189 .local string gcc_ver 190 .local string cc 191 .local string os_name 192 193 config = '_config'() 194 195 gcc_ver = config['gccversion'] 196 unless gcc_ver > '' goto not_gcc 197 .return ('gcc') 198 not_gcc: 199 200 cc = config['cc'] 201 os_name = config['osname'] 202 203 if os_name != 'MSWin32' goto not_msvc 204 if cc != 'cl' goto not_msvc 205 .return ('msvc') 206 not_msvc: 207 208 .return ('default') 209 .end 210 211 187 212 .sub 'generate_code' 188 213 .param string infile 189 214 .local pmc ifh … … 227 252 $S0 = size 228 253 codestring .= $S0 229 254 codestring .= ";\n" 255 codestring .= <<'END_OF_FUNCTION' 256 void * get_program_code(void) 257 { 258 return program_code; 259 } 260 END_OF_FUNCTION 261 230 262 .return (codestring) 231 263 232 264 err_infile: 233 265 die "cannot open infile" 234 266 .end 235 267 268 236 269 # The PBC will be represented as a C string, so this sub builds a table 237 270 # of the C representation of each ASCII character, for lookup by ordinal value. 238 271 .sub 'generate_encoding_table' … … 312 345 $S0 = size 313 346 codestring .= $S0 314 347 codestring .= ";\n" 348 349 codestring .= <<'END_OF_FUNCTION' 350 void * get_program_code(void) 351 { 352 return program_code; 353 } 354 END_OF_FUNCTION 355 315 356 .return (codestring) 316 357 317 358 err_infile: 318 359 die "cannot open infile" 319 360 .end 320 361 362 363 # Transforms the .pbc path into one with a different extension. 364 # Passing '' means no extension. 365 # Extensions without leading dots will have a dot pre-pended. 366 .sub 'replace_pbc_extension' 367 .param string pbc_path 368 .param string new_extension 369 370 $S0 = substr pbc_path, -4 371 downcase $S0 372 if $S0 != '.pbc' goto err_pbc_path_not_pbc 373 .local string base_path 374 base_path = substr pbc_path, 0 375 substr base_path, -4, 4, '' 376 377 .local string new_path 378 new_path = substr base_path, 0 379 380 unless new_extension > '' goto ext_null 381 382 $S1 = substr new_extension, 0, 1 383 if $S1 == '.' goto has_dot 384 new_path .= '.' 385 386 has_dot: 387 new_path .= new_extension 388 389 ext_null: 390 .return (new_path) 391 392 err_pbc_path_not_pbc: 393 die "input pbc file name does not end in '.pbc'" 394 .end 395 396 397 # In addition to generating the code for inclusion in the C file, 398 # this sub creates supplemental .rc and .RES files. 399 .sub 'generate_code_msvc' 400 .param string pbc_path 401 402 .local string rc_path 403 .local string res_path 404 rc_path = 'replace_pbc_extension'(pbc_path, '.rc' ) 405 res_path = 'replace_pbc_extension'(pbc_path, '.res') 406 407 # The exact numbers are not relevant; 408 # they are used to identify the resource within the final executable. 409 .local string rc_constant_defines 410 rc_constant_defines = <<'END_OF_DEFINES' 411 #define RESOURCE_NAME_ID_WHOLE_PBC 333 412 #define RESOURCE_TYPE_ID_WHOLE_PBC 444 413 END_OF_DEFINES 414 415 416 .local string rc_contents 417 rc_contents = '' 418 rc_contents .= rc_constant_defines 419 rc_contents .= 'RESOURCE_NAME_ID_WHOLE_PBC RESOURCE_TYPE_ID_WHOLE_PBC ' 420 rc_contents .= pbc_path 421 rc_contents .= "\n" 422 423 .local pmc rc_fh 424 rc_fh = open rc_path, 'w' 425 unless rc_fh goto err_rc_open 426 print rc_fh, rc_contents 427 $I0 = rc_fh.'close'() 428 unless $I0 == 0 goto err_rc_close 429 430 431 .local int pbc_size 432 $P1 = new ['OS'] 433 $P2 = $P1.'stat'(pbc_path) 434 pbc_size = $P2[7] 435 436 437 .local string codestring 438 codestring = '' 439 codestring .= '#include <windows.h>' 440 codestring .= "\n" 441 codestring .= rc_constant_defines 442 codestring .= "const unsigned int bytecode_size = " 443 $S0 = pbc_size 444 codestring .= $S0 445 codestring .= ";\n" 446 447 codestring .= <<'END_OF_FUNCTION' 448 void * get_program_code(void) 449 { 450 HRSRC hResource; 451 DWORD size; 452 HGLOBAL hPBC; 453 LPVOID actual_pointer_to_pbc_in_memory; 454 455 hResource = FindResource( 456 NULL, 457 MAKEINTRESOURCE(RESOURCE_NAME_ID_WHOLE_PBC), 458 MAKEINTRESOURCE(RESOURCE_TYPE_ID_WHOLE_PBC) 459 ); 460 if (!hResource) 461 return NULL; 462 463 size = SizeofResource( NULL, hResource ); 464 if (size != bytecode_size) 465 return NULL; 466 467 hPBC = LoadResource( NULL, hResource ); 468 if (!hPBC) 469 return NULL; 470 471 actual_pointer_to_pbc_in_memory = LockResource( hPBC ); 472 if (!actual_pointer_to_pbc_in_memory) 473 return NULL; 474 475 return actual_pointer_to_pbc_in_memory; 476 } 477 END_OF_FUNCTION 478 479 .local string rc_cmd 480 rc_cmd = 'rc ' 481 rc_cmd .= rc_path 482 483 say rc_cmd 484 .local int status 485 status = spawnw rc_cmd 486 unless status goto rc_ok 487 488 die "RC command failed" 489 rc_ok: 490 491 .return (codestring) 492 493 err_h_open: 494 die "cannot open .h file" 495 err_rc_open: 496 die "cannot open .rc file" 497 err_h_close: 498 die "cannot close .h file" 499 err_rc_close: 500 die "cannot close .rc file" 501 .end 502 321 503 # util functions 322 504 .sub 'compile_file' 323 505 .param string cfile … … 371 553 .sub 'link_file' 372 554 .param string objfile 373 555 .param string exefile 556 .param string extra_obj 374 557 .param int install :optional 375 558 376 559 $P0 = '_config'() … … 415 598 link .= pathquote 416 599 link .= objfile 417 600 link .= pathquote 601 unless extra_obj > '' goto skip_extra_obj 418 602 link .= ' ' 603 link .= pathquote 604 link .= extra_obj 605 link .= pathquote 606 skip_extra_obj: 607 link .= ' ' 419 608 link .= config 420 609 link .= ' ' 421 610 link .= rpath