Ticket #127: r34932-rt56996+tt127.diff
File r34932-rt56996+tt127.diff, 15.2 KB (added by rurban, 13 years ago) |
---|
-
src/library.c
r34932 | rurban++ | branches/pdd30install_stage3 (2 files): 20:04 : - Optimize RT #56996 fhs-runtime by never accessing wrong paths. 20:04 : ENABLE_PARROT_LIBRARY_INSTALLED is now enabled 20:04 : - Fix TT #127 do not stat extensions when an extension was 20:04 : already given, + find a file without given extension if such 20:04 : a directory exists. 20:04 : - Rename try_load_path() to try_load_file() as it should find 20:04 : no directories. 20:04 : - Add testcases for most odd library search cases. 20:04 : - Internal new behaviour for "" libpath: do not prefix this with 20:04 : the prefix as needed by installables, prefix only with "./" 20:04 : - Remove {runtime|libdir}/parrot lib_path for load_bytecode. 20:04 : load_bytecode "include/file.pasm" must be written as 20:04 : load_bytecode "../include/file.pasm". 20:04 : This saves us 4 stats when the file is not in 20:04 : the runtime library but locally. 20:04 review: http://www.parrotvm.org/svn/pa[ ]evision?rev=34932
1 1 /* 2 Copyright (C) 2004-200 7, The Perl Foundation.2 Copyright (C) 2004-2009, The Perl Foundation. 3 3 $Id$ 4 4 5 5 =head1 NAME 6 6 7 src/library.c - Interface to Parrot's bytecode library7 src/library.c - Search parrot files in the libpaths 8 8 9 9 =head1 DESCRIPTION 10 10 11 This file contains C functions to access Parrot's bytecode library functions. 11 This file contains C functions to find include (via C<.include>), 12 library (via C<load_bytecode>) or dynext (via C<loadlib>) files. 12 13 14 The libpaths are hardcoded, and different when building from source 15 (F<runtime/parrot>) and when being installed (F<$libdir/parrot>). 16 13 17 =head2 Functions 14 18 15 19 =over 4 … … 86 90 87 91 PARROT_WARN_UNUSED_RESULT 88 92 PARROT_CAN_RETURN_NULL 89 static STRING* try_load_ path(PARROT_INTERP, ARGMOD(STRING* path))93 static STRING* try_load_file(PARROT_INTERP, ARGMOD(STRING* path)) 90 94 __attribute__nonnull__(1) 91 95 __attribute__nonnull__(2) 92 96 FUNC_MODIFIES(* path); … … 121 125 Platform code may add, delete, or replace search path entries as needed. See 122 126 also F<include/parrot/library.h> for C<enum_lib_paths>. 123 127 124 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED125 then the config hash is checked for the path prefix. This still crashes.126 127 128 =cut 128 129 129 130 */ 130 131 131 #undef ENABLE_PARROT_LIBRARY_INSTALLED132 133 132 void 134 133 parrot_init_library_paths(PARROT_INTERP) 135 134 { … … 140 139 PMC * const iglobals = interp->iglobals; 141 140 /* create the lib_paths array */ 142 141 PMC * const lib_paths = pmc_new(interp, enum_class_FixedPMCArray); 143 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED144 142 PMC * const config_hash = VTABLE_get_pmc_keyed_int(interp, iglobals, IGLOBALS_CONFIG_HASH); 145 143 STRING * const key = CONST_STRING(interp, "installed"); 146 #endif147 144 148 145 VTABLE_set_integer_native(interp, lib_paths, PARROT_LIB_PATH_SIZE); 149 146 VTABLE_set_pmc_keyed_int(interp, iglobals, 150 147 IGLOBALS_LIB_PATHS, lib_paths); 151 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED152 148 if (VTABLE_elements(interp, config_hash) && 153 VTABLE_exists_keyed_str(interp, config_hash, key)) ){149 VTABLE_exists_keyed_str(interp, config_hash, key)) { 154 150 installed = VTABLE_get_integer_keyed_str(interp, config_hash, key); 155 151 } 156 #endif157 152 158 153 /* each is an array of strings */ 159 154 /* define include paths */ 160 155 paths = pmc_new(interp, enum_class_ResizableStringArray); 161 156 VTABLE_set_pmc_keyed_int(interp, lib_paths, 162 157 PARROT_LIB_PATH_INCLUDE, paths); 163 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED164 158 if (installed) { 165 #endif166 159 entry = CONST_STRING(interp, "lib/parrot/include/"); 167 160 VTABLE_push_string(interp, paths, entry); 168 161 entry = CONST_STRING(interp, "lib/parrot/"); 169 162 VTABLE_push_string(interp, paths, entry); 170 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED171 163 } 172 164 else { 173 #endif174 165 entry = CONST_STRING(interp, "runtime/parrot/include/"); 175 166 VTABLE_push_string(interp, paths, entry); 176 167 entry = CONST_STRING(interp, "runtime/parrot/"); 177 168 VTABLE_push_string(interp, paths, entry); 178 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 169 entry = CONST_STRING(interp, "./"); /* requires the build_dir */ 170 VTABLE_push_string(interp, paths, entry); 179 171 } 180 #endif 181 entry = CONST_STRING(interp, "./"); 172 entry = CONST_STRING(interp, ""); /* do not add the prefix here */ 182 173 VTABLE_push_string(interp, paths, entry); 183 174 184 175 /* define library paths */ 185 176 paths = pmc_new(interp, enum_class_ResizableStringArray); 186 177 VTABLE_set_pmc_keyed_int(interp, lib_paths, 187 178 PARROT_LIB_PATH_LIBRARY, paths); 188 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED189 179 if (installed) { 190 #endif191 180 entry = CONST_STRING(interp, "lib/parrot/library/"); 192 181 VTABLE_push_string(interp, paths, entry); 193 entry = CONST_STRING(interp, "lib/parrot/");194 VTABLE_push_string(interp, paths, entry);195 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 182 /* This can be removed. TT #126 */ 183 /* entry = CONST_STRING(interp, "lib/parrot/"); 184 VTABLE_push_string(interp, paths, entry); */ 196 185 } 197 186 else { 198 #endif199 187 entry = CONST_STRING(interp, "runtime/parrot/library/"); 200 188 VTABLE_push_string(interp, paths, entry); 201 entry = CONST_STRING(interp, "runtime/parrot/"); 189 /* This can be removed. TT #126 */ 190 /*entry = CONST_STRING(interp, "runtime/parrot/"); 191 VTABLE_push_string(interp, paths, entry);*/ 192 entry = CONST_STRING(interp, "./"); /* with the build_dir */ 202 193 VTABLE_push_string(interp, paths, entry); 203 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED204 194 } 205 #endif 206 entry = CONST_STRING(interp, "./"); 195 entry = CONST_STRING(interp, ""); /* do not add the prefix here */ 207 196 VTABLE_push_string(interp, paths, entry); 208 197 209 198 /* define dynext paths */ 210 199 paths = pmc_new(interp, enum_class_ResizableStringArray); 211 200 VTABLE_set_pmc_keyed_int(interp, lib_paths, 212 201 PARROT_LIB_PATH_DYNEXT, paths); 213 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED214 202 if (installed) { 215 #endif216 203 entry = CONST_STRING(interp, "lib/parrot/dynext/"); 217 204 VTABLE_push_string(interp, paths, entry); 218 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED219 205 } 220 206 else { 221 #endif222 207 entry = CONST_STRING(interp, "runtime/parrot/dynext/"); 223 208 VTABLE_push_string(interp, paths, entry); 224 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED225 209 } 226 #endif227 210 entry = CONST_STRING(interp, ""); 228 211 VTABLE_push_string(interp, paths, entry); 229 212 … … 467 450 468 451 /* 469 452 470 =item C<static STRING* try_load_ path>453 =item C<static STRING* try_load_file> 471 454 472 455 Attempts to load a file with name C<path>. If the file is successfully located, 473 456 the finalized name of the file is returned as a STRING. Otherwise, returns … … 480 463 PARROT_WARN_UNUSED_RESULT 481 464 PARROT_CAN_RETURN_NULL 482 465 static STRING* 483 try_load_ path(PARROT_INTERP, ARGMOD(STRING* path))466 try_load_file(PARROT_INTERP, ARGMOD(STRING* path)) 484 467 { 485 468 STRING *final; 486 469 … … 488 471 489 472 final = path_finalize(interp, final); 490 473 491 if (Parrot_stat_info_intval(interp, final, STAT_EXISTS)) { 474 /* only files */ 475 if (Parrot_stat_info_intval(interp, final, STAT_EXISTS) 476 && !Parrot_stat_info_intval(interp, final, STAT_ISDIR)) 492 477 return final; 493 }494 478 495 479 return NULL; 496 480 } … … 519 503 /* 520 504 First try the path without guessing the extension to ensure compatibility 521 505 with existing code. 506 But if that finds a directory skip it. 507 e.g. load_bytecode "Test/Builder" => .pbc or .pir, but not the dir 522 508 */ 523 509 524 510 with_ext = string_copy(interp, path); 525 511 526 result = try_load_ path(interp, with_ext);512 result = try_load_file(interp, with_ext); 527 513 if (result) 528 514 return result; 529 515 530 516 /* 517 Check if the file already contains one of the 3 known extensions. 518 If so fail. A file test.pir.pbc will not be found on "test.pir" 519 */ 520 for (guess = 0 ; guess <= LOAD_EXT_CODE_LAST ; guess++) { 521 STRING *d; 522 int len_ext = strlen(load_ext_code[guess]); 523 int len_str = with_ext->strlen; 524 if (len_str <= len_ext) continue; 525 if (!string_equal(interp, string_substr(interp, with_ext, -len_ext, 526 len_ext, NULL, 0), 527 const_string(interp, load_ext_code[guess]))) { 528 return NULL; 529 } 530 } 531 532 /* 531 533 Start guessing now. This version tries to find the lowest form of the 532 534 code, starting with bytecode and working up to PIR. Note the atypical 533 535 loop control. This is so the array can easily be processed in reverse. … … 538 540 with_ext = string_append(interp, 539 541 with_ext, const_string(interp, load_ext_code[guess])); 540 542 541 result = try_load_ path(interp, with_ext);543 result = try_load_file(interp, with_ext); 542 544 if (result) 543 545 return result; 544 546 } 545 547 548 if (Parrot_stat_info_intval(interp, path, STAT_EXISTS) 549 && Parrot_stat_info_intval(interp, path, STAT_ISDIR)) 550 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_SUBSTR_OUT_OF_STRING, 551 "'%s' is a directory", path->strstart); 546 552 return NULL; 547 553 } 548 554 … … 624 630 for (i = 0; i < n; ++i) { 625 631 STRING * const path = VTABLE_get_string_keyed_int(interp, paths, i); 626 632 627 if (string_length(interp, prefix) && !is_abs_path(path)) 633 if (string_length(interp, prefix) 634 && string_length(interp, path) /* empty libpath uses no prefix */ 635 && !is_abs_path(path)) 628 636 full_name = path_concat(interp, prefix, path); 629 637 else 630 638 full_name = string_copy(interp, path); 631 639 632 full_name = path_append(interp, full_name, file); 640 if (string_length(interp, path)) 641 full_name = path_append(interp, full_name, file); 642 else 643 full_name = string_copy(interp, file); 633 644 634 645 full_name = 635 646 (type & PARROT_RUNTIME_FT_DYNEXT) 636 ? try_load_ path(interp, full_name)647 ? try_load_file(interp, full_name) 637 648 : try_bytecode_extensions(interp, full_name); 638 649 639 650 if (full_name) … … 642 653 643 654 full_name = 644 655 (type & PARROT_RUNTIME_FT_DYNEXT) 645 ? try_load_ path(interp, file)656 ? try_load_file(interp, file) 646 657 : try_bytecode_extensions(interp, file); 647 658 648 659 return full_name; -
t/src/library.t
1 #! perl 2 # Copyright (C) 2009, The Perl Foundation. 3 # $Id$ 4 5 use strict; 6 use warnings; 7 use lib qw( . lib ../lib ../../lib ); 8 use Test::More; 9 use Parrot::Test; 10 use Parrot::Config; 11 12 plan tests => 3; 13 14 =head1 NAME 15 16 t/src/library.t - Library search functions 17 18 =head1 SYNOPSIS 19 20 % prove t/src/library.t 21 22 =head1 DESCRIPTION 23 24 Test some library search functionality for load_bytecode and .include. 25 The library search path, directories versus missing extensions, finding files 26 without extensions. 27 28 TT#123 remove more hard-coded runtime/ paths from libs 29 TT#126 optimize load_bytecode, .include paths: no library/ and include/ prefix 30 TT#127 do not stat extensions when an extension was already given. 31 If the given string is a directory, do not fail, try the extensions instead. 32 e.g. load_bytecode 'Test/Builder' 33 TT#128 [TODO] Honor source filetype when a .pbc is present 34 35 We test this seperately, because core has another load_bytecode failure RT #39807, 36 tested in t/op/load_bytecode.t 37 38 =cut 39 40 c_output_is( <<'CODE', <<'OUTPUT', "Parrot_locate_runtime_file" ); 41 42 #include <parrot/parrot.h> 43 #include <parrot/embed.h> 44 45 int 46 main(int argc, char* argv[]) 47 { 48 Interp *interp; 49 int error_val; 50 char *path; 51 52 interp = Parrot_new(NULL); 53 if (!interp) { 54 return 1; 55 } 56 path = Parrot_locate_runtime_file(interp, "Data/Dumper.pir", PARROT_RUNTIME_FT_SOURCE); 57 printf("%s\n", path); 58 if (path) free(path); 59 path = Parrot_locate_runtime_file(interp, "Data/Dumper.pbc", PARROT_RUNTIME_FT_PBC); 60 printf("%s\n", path); 61 if (path) free(path); 62 path = Parrot_locate_runtime_file(interp, "Data/Dumper", PARROT_RUNTIME_FT_PBC); 63 printf("%s\n", path); 64 if (path) free(path); 65 path = Parrot_locate_runtime_file(interp, "Data/Dumper.pir", PARROT_RUNTIME_FT_INCLUDE); 66 printf("%s\n", path); 67 if (path) free(path); 68 path = Parrot_locate_runtime_file(interp, "library/Data/Dumper.pir", PARROT_RUNTIME_FT_INCLUDE); 69 printf("%s\n", path); 70 if (path) free(path); 71 72 Parrot_exit(interp, 0); 73 return 0; 74 } 75 CODE 76 ./runtime/parrot/library/Data/Dumper.pir 77 ./runtime/parrot/library/Data/Dumper.pbc 78 ./runtime/parrot/library/Data/Dumper.pbc 79 (null) 80 ./runtime/parrot/library/Data/Dumper.pir 81 OUTPUT 82 83 my $dynpath = "." . $PConfig{slash} . 84 File::Spec->catfile("runtime","parrot","dynext","myops_ops") 85 . $PConfig{load_ext}; 86 c_output_is( <<'CODE', <<"OUTPUT", "FT_DYNEXT" ); 87 88 #include <parrot/parrot.h> 89 #include <parrot/embed.h> 90 91 int 92 main(int argc, char* argv[]) 93 { 94 Interp *interp; 95 char *path; 96 STRING *result, *full_name, *wo_ext; 97 INTVAL i, n; 98 99 interp = Parrot_new(NULL); 100 if (!interp) { 101 return 1; 102 } 103 104 wo_ext = const_string(interp, "myops_ops"); 105 full_name = string_concat(interp, wo_ext, const_string(interp, PARROT_LOAD_EXT), 0); 106 result = Parrot_locate_runtime_file_str(interp, full_name, 107 PARROT_RUNTIME_FT_DYNEXT); 108 if (result) { 109 printf("%s\n", result->strstart); 110 } 111 else { 112 if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) { 113 full_name = string_concat(interp, wo_ext, const_string(interp, PARROT_SHARE_EXT), 0); 114 result = Parrot_locate_runtime_file_str(interp, full_name, 115 PARROT_RUNTIME_FT_DYNEXT); 116 } 117 printf("%s\n", result->strstart); 118 } 119 120 path = Parrot_locate_runtime_file(interp, "not_existing_op", PARROT_RUNTIME_FT_INCLUDE); 121 printf("%s\n", path); 122 if (path) free(path); 123 124 Parrot_exit(interp, 0); 125 return 0; 126 } 127 CODE 128 $dynpath 129 (null) 130 OUTPUT 131 132 c_output_is( <<'CODE', <<'OUTPUT', "FT_SOURCE, FT_PIR", 'todo' => 'TT #128 force pir') 133 134 #include <parrot/parrot.h> 135 #include <parrot/embed.h> 136 137 int 138 main(int argc, char* argv[]) 139 { 140 Interp *interp; 141 int error_val; 142 char *path; 143 144 interp = Parrot_new(NULL); 145 if (!interp) { 146 return 1; 147 } 148 149 path = Parrot_locate_runtime_file(interp, "Data/Dumper", PARROT_RUNTIME_FT_SOURCE); 150 printf("%s\n", path); 151 if (path) free(path); 152 path = Parrot_locate_runtime_file(interp, "Data/Dumper", PARROT_RUNTIME_FT_PIR); 153 printf("%s\n", path); 154 if (path) free(path); 155 156 Parrot_exit(interp, 0); 157 return 0; 158 } 159 CODE 160 ./runtime/parrot/library/Data/Dumper.pir 161 ./runtime/parrot/library/Data/Dumper.pir 162 OUTPUT 163 164 165 # Local Variables: 166 # mode: cperl 167 # cperl-indent-level: 4 168 # fill-column: 100 169 # End: 170 # vim: expandtab shiftwidth=4: