Ticket #127: r34932-rt56996+tt127.diff

File r34932-rt56996+tt127.diff, 15.2 KB (added by rurban, 6 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 
    
     
    11/* 
    2 Copyright (C) 2004-2007, The Perl Foundation. 
     2Copyright (C) 2004-2009, The Perl Foundation. 
    33$Id$ 
    44 
    55=head1 NAME 
    66 
    7 src/library.c - Interface to Parrot's bytecode library 
     7src/library.c - Search parrot files in the libpaths 
    88 
    99=head1 DESCRIPTION 
    1010 
    11 This file contains C functions to access Parrot's bytecode library functions. 
     11This file contains C functions to find include (via C<.include>),  
     12library (via C<load_bytecode>) or dynext (via C<loadlib>) files. 
    1213 
     14The libpaths are hardcoded, and different when building from source  
     15(F<runtime/parrot>) and when being installed (F<$libdir/parrot>). 
     16 
    1317=head2 Functions 
    1418 
    1519=over 4 
     
    8690 
    8791PARROT_WARN_UNUSED_RESULT 
    8892PARROT_CAN_RETURN_NULL 
    89 static STRING* try_load_path(PARROT_INTERP, ARGMOD(STRING* path)) 
     93static STRING* try_load_file(PARROT_INTERP, ARGMOD(STRING* path)) 
    9094        __attribute__nonnull__(1) 
    9195        __attribute__nonnull__(2) 
    9296        FUNC_MODIFIES(* path); 
     
    121125Platform code may add, delete, or replace search path entries as needed. See 
    122126also F<include/parrot/library.h> for C<enum_lib_paths>. 
    123127 
    124 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    125 then the config hash is checked for the path prefix. This still crashes. 
    126  
    127128=cut 
    128129 
    129130*/ 
    130131 
    131 #undef ENABLE_PARROT_LIBRARY_INSTALLED 
    132  
    133132void 
    134133parrot_init_library_paths(PARROT_INTERP) 
    135134{ 
     
    140139    PMC * const iglobals = interp->iglobals; 
    141140    /* create the lib_paths array */ 
    142141    PMC * const lib_paths = pmc_new(interp, enum_class_FixedPMCArray); 
    143 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    144142    PMC * const config_hash = VTABLE_get_pmc_keyed_int(interp, iglobals, IGLOBALS_CONFIG_HASH); 
    145143    STRING * const key = CONST_STRING(interp, "installed"); 
    146 #endif 
    147144 
    148145    VTABLE_set_integer_native(interp, lib_paths, PARROT_LIB_PATH_SIZE); 
    149146    VTABLE_set_pmc_keyed_int(interp, iglobals, 
    150147            IGLOBALS_LIB_PATHS, lib_paths); 
    151 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    152148    if (VTABLE_elements(interp, config_hash) && 
    153         VTABLE_exists_keyed_str(interp, config_hash, key))) { 
     149        VTABLE_exists_keyed_str(interp, config_hash, key)) { 
    154150        installed = VTABLE_get_integer_keyed_str(interp, config_hash, key); 
    155151    } 
    156 #endif 
    157152 
    158153    /* each is an array of strings */ 
    159154    /* define include paths */ 
    160155    paths = pmc_new(interp, enum_class_ResizableStringArray); 
    161156    VTABLE_set_pmc_keyed_int(interp, lib_paths, 
    162157            PARROT_LIB_PATH_INCLUDE, paths); 
    163 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    164158    if (installed) { 
    165 #endif 
    166159        entry = CONST_STRING(interp, "lib/parrot/include/"); 
    167160        VTABLE_push_string(interp, paths, entry); 
    168161        entry = CONST_STRING(interp, "lib/parrot/"); 
    169162        VTABLE_push_string(interp, paths, entry); 
    170 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    171163    } 
    172164    else { 
    173 #endif 
    174165        entry = CONST_STRING(interp, "runtime/parrot/include/"); 
    175166        VTABLE_push_string(interp, paths, entry); 
    176167        entry = CONST_STRING(interp, "runtime/parrot/"); 
    177168        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); 
    179171    } 
    180 #endif 
    181     entry = CONST_STRING(interp, "./"); 
     172    entry = CONST_STRING(interp, ""); /* do not add the prefix here */ 
    182173    VTABLE_push_string(interp, paths, entry); 
    183174 
    184175    /* define library paths */ 
    185176    paths = pmc_new(interp, enum_class_ResizableStringArray); 
    186177    VTABLE_set_pmc_keyed_int(interp, lib_paths, 
    187178            PARROT_LIB_PATH_LIBRARY, paths); 
    188 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    189179    if (installed) { 
    190 #endif 
    191180        entry = CONST_STRING(interp, "lib/parrot/library/"); 
    192181        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); */ 
    196185    } 
    197186    else { 
    198 #endif 
    199187        entry = CONST_STRING(interp, "runtime/parrot/library/"); 
    200188        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 */ 
    202193        VTABLE_push_string(interp, paths, entry); 
    203 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    204194    } 
    205 #endif 
    206     entry = CONST_STRING(interp, "./"); 
     195    entry = CONST_STRING(interp, ""); /* do not add the prefix here */ 
    207196    VTABLE_push_string(interp, paths, entry); 
    208197 
    209198    /* define dynext paths */ 
    210199    paths = pmc_new(interp, enum_class_ResizableStringArray); 
    211200    VTABLE_set_pmc_keyed_int(interp, lib_paths, 
    212201            PARROT_LIB_PATH_DYNEXT, paths); 
    213 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    214202    if (installed) { 
    215 #endif 
    216203        entry = CONST_STRING(interp, "lib/parrot/dynext/"); 
    217204        VTABLE_push_string(interp, paths, entry); 
    218 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    219205    } 
    220206    else { 
    221 #endif 
    222207        entry = CONST_STRING(interp, "runtime/parrot/dynext/"); 
    223208        VTABLE_push_string(interp, paths, entry); 
    224 #ifdef ENABLE_PARROT_LIBRARY_INSTALLED 
    225209    } 
    226 #endif 
    227210    entry = CONST_STRING(interp, ""); 
    228211    VTABLE_push_string(interp, paths, entry); 
    229212 
     
    467450 
    468451/* 
    469452 
    470 =item C<static STRING* try_load_path> 
     453=item C<static STRING* try_load_file> 
    471454 
    472455Attempts to load a file with name C<path>. If the file is successfully located, 
    473456the finalized name of the file is returned as a STRING. Otherwise, returns 
     
    480463PARROT_WARN_UNUSED_RESULT 
    481464PARROT_CAN_RETURN_NULL 
    482465static STRING* 
    483 try_load_path(PARROT_INTERP, ARGMOD(STRING* path)) 
     466try_load_file(PARROT_INTERP, ARGMOD(STRING* path)) 
    484467{ 
    485468    STRING *final; 
    486469 
     
    488471 
    489472    final = path_finalize(interp, final); 
    490473 
    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)) 
    492477        return final; 
    493     } 
    494478 
    495479    return NULL; 
    496480} 
     
    519503    /* 
    520504      First try the path without guessing the extension to ensure compatibility 
    521505      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 
    522508     */ 
    523509 
    524510    with_ext = string_copy(interp, path); 
    525511 
    526     result = try_load_path(interp, with_ext); 
     512    result = try_load_file(interp, with_ext); 
    527513    if (result) 
    528514        return result; 
    529515 
    530516    /* 
     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    /* 
    531533      Start guessing now. This version tries to find the lowest form of the 
    532534      code, starting with bytecode and working up to PIR. Note the atypical 
    533535      loop control. This is so the array can easily be processed in reverse. 
     
    538540        with_ext = string_append(interp, 
    539541                                 with_ext, const_string(interp, load_ext_code[guess])); 
    540542 
    541         result = try_load_path(interp, with_ext); 
     543        result = try_load_file(interp, with_ext); 
    542544        if (result) 
    543545            return result; 
    544546    } 
    545547 
     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); 
    546552    return NULL; 
    547553} 
    548554 
     
    624630    for (i = 0; i < n; ++i) { 
    625631        STRING * const path = VTABLE_get_string_keyed_int(interp, paths, i); 
    626632 
    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)) 
    628636            full_name = path_concat(interp, prefix, path); 
    629637        else 
    630638            full_name = string_copy(interp, path); 
    631639 
    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); 
    633644 
    634645        full_name = 
    635646            (type & PARROT_RUNTIME_FT_DYNEXT) 
    636                 ? try_load_path(interp, full_name) 
     647                ? try_load_file(interp, full_name) 
    637648                : try_bytecode_extensions(interp, full_name); 
    638649 
    639650        if (full_name) 
     
    642653 
    643654    full_name = 
    644655        (type & PARROT_RUNTIME_FT_DYNEXT) 
    645             ? try_load_path(interp, file) 
     656            ? try_load_file(interp, file) 
    646657            : try_bytecode_extensions(interp, file); 
    647658 
    648659    return full_name; 
  • t/src/library.t

     
     1#! perl 
     2# Copyright (C) 2009, The Perl Foundation. 
     3# $Id$ 
     4 
     5use strict; 
     6use warnings; 
     7use lib qw( . lib ../lib ../../lib ); 
     8use Test::More; 
     9use Parrot::Test; 
     10use Parrot::Config; 
     11 
     12plan tests => 3; 
     13 
     14=head1 NAME 
     15 
     16t/src/library.t - Library search functions 
     17 
     18=head1 SYNOPSIS 
     19 
     20    % prove t/src/library.t 
     21 
     22=head1 DESCRIPTION 
     23 
     24Test some library search functionality for load_bytecode and .include. 
     25The library search path, directories versus missing extensions, finding files 
     26without 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 
     35We test this seperately, because core has another load_bytecode failure RT #39807, 
     36tested in t/op/load_bytecode.t 
     37 
     38=cut 
     39 
     40c_output_is( <<'CODE', <<'OUTPUT', "Parrot_locate_runtime_file" ); 
     41 
     42#include <parrot/parrot.h> 
     43#include <parrot/embed.h> 
     44 
     45int 
     46main(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} 
     75CODE 
     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 
     81OUTPUT 
     82 
     83my $dynpath = "." . $PConfig{slash} . 
     84  File::Spec->catfile("runtime","parrot","dynext","myops_ops") 
     85  . $PConfig{load_ext}; 
     86c_output_is( <<'CODE', <<"OUTPUT", "FT_DYNEXT" ); 
     87 
     88#include <parrot/parrot.h> 
     89#include <parrot/embed.h> 
     90 
     91int 
     92main(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} 
     127CODE 
     128$dynpath 
     129(null) 
     130OUTPUT 
     131 
     132c_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 
     137int 
     138main(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} 
     159CODE 
     160./runtime/parrot/library/Data/Dumper.pir 
     161./runtime/parrot/library/Data/Dumper.pir 
     162OUTPUT 
     163 
     164 
     165# Local Variables: 
     166#   mode: cperl 
     167#   cperl-indent-level: 4 
     168#   fill-column: 100 
     169# End: 
     170# vim: expandtab shiftwidth=4: