Author: rurban
Date: Sun Jan  4 12:03:59 2009
New Revision: 34932

Added:
   branches/pdd30install_stage3/t/src/library.t   (contents, props changed)
Modified:
   branches/pdd30install_stage3/src/library.c

Log:
- Optimize RT #56996 fhs-runtime by never accessing wrong paths.
  ENABLE_PARROT_LIBRARY_INSTALLED is now enabled
- Fix TT #127 do not stat extensions when an extension was 
  already given, + find a file without given extension if such 
  a directory exists.
- Rename try_load_path() to try_load_file() as it should find 
  no directories.
- Add testcases for most odd library search cases.
- Internal new behaviour for "" libpath: do not prefix this with 
  the prefix as needed by installables, prefix only with "./"
- Remove {runtime|libdir}/parrot lib_path for load_bytecode.
  load_bytecode "include/file.pasm" must be written as 
  load_bytecode "../include/file.pasm".
  This saves us 4 stats when the file is not in 
  the runtime library but locally.



Modified: branches/pdd30install_stage3/src/library.c
==============================================================================
--- branches/pdd30install_stage3/src/library.c  (original)
+++ branches/pdd30install_stage3/src/library.c  Sun Jan  4 12:03:59 2009
@@ -1,14 +1,18 @@
 /*
-Copyright (C) 2004-2007, The Perl Foundation.
+Copyright (C) 2004-2009, The Perl Foundation.
 $Id$
 
 =head1 NAME
 
-src/library.c - Interface to Parrot's bytecode library
+src/library.c - Search parrot files in the libpaths
 
 =head1 DESCRIPTION
 
-This file contains C functions to access Parrot's bytecode library functions.
+This file contains C functions to find include (via C<.include>), 
+library (via C<load_bytecode>) or dynext (via C<loadlib>) files.
+
+The libpaths are hardcoded, and different when building from source 
+(F<runtime/parrot>) and when being installed (F<$libdir/parrot>).
 
 =head2 Functions
 
@@ -86,7 +90,7 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-static STRING* try_load_path(PARROT_INTERP, ARGMOD(STRING* path))
+static STRING* try_load_file(PARROT_INTERP, ARGMOD(STRING* path))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
         FUNC_MODIFIES(* path);
@@ -121,15 +125,10 @@
 Platform code may add, delete, or replace search path entries as needed. See
 also F<include/parrot/library.h> for C<enum_lib_paths>.
 
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
-then the config hash is checked for the path prefix. This still crashes.
-
 =cut
 
 */
 
-#undef ENABLE_PARROT_LIBRARY_INSTALLED
-
 void
 parrot_init_library_paths(PARROT_INTERP)
 {
@@ -140,90 +139,74 @@
     PMC * const iglobals = interp->iglobals;
     /* create the lib_paths array */
     PMC * const lib_paths = pmc_new(interp, enum_class_FixedPMCArray);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     PMC * const config_hash = VTABLE_get_pmc_keyed_int(interp, iglobals, 
IGLOBALS_CONFIG_HASH);
     STRING * const key = CONST_STRING(interp, "installed");
-#endif
 
     VTABLE_set_integer_native(interp, lib_paths, PARROT_LIB_PATH_SIZE);
     VTABLE_set_pmc_keyed_int(interp, iglobals,
             IGLOBALS_LIB_PATHS, lib_paths);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     if (VTABLE_elements(interp, config_hash) &&
-        VTABLE_exists_keyed_str(interp, config_hash, key))) {
+        VTABLE_exists_keyed_str(interp, config_hash, key)) {
         installed = VTABLE_get_integer_keyed_str(interp, config_hash, key);
     }
-#endif
 
     /* each is an array of strings */
     /* define include paths */
     paths = pmc_new(interp, enum_class_ResizableStringArray);
     VTABLE_set_pmc_keyed_int(interp, lib_paths,
             PARROT_LIB_PATH_INCLUDE, paths);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     if (installed) {
-#endif
         entry = CONST_STRING(interp, "lib/parrot/include/");
         VTABLE_push_string(interp, paths, entry);
         entry = CONST_STRING(interp, "lib/parrot/");
         VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     }
     else {
-#endif
         entry = CONST_STRING(interp, "runtime/parrot/include/");
         VTABLE_push_string(interp, paths, entry);
         entry = CONST_STRING(interp, "runtime/parrot/");
         VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
+        entry = CONST_STRING(interp, "./");  /* requires the build_dir */
+        VTABLE_push_string(interp, paths, entry);
     }
-#endif
-    entry = CONST_STRING(interp, "./");
+    entry = CONST_STRING(interp, ""); /* do not add the prefix here */
     VTABLE_push_string(interp, paths, entry);
 
     /* define library paths */
     paths = pmc_new(interp, enum_class_ResizableStringArray);
     VTABLE_set_pmc_keyed_int(interp, lib_paths,
             PARROT_LIB_PATH_LIBRARY, paths);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     if (installed) {
-#endif
         entry = CONST_STRING(interp, "lib/parrot/library/");
         VTABLE_push_string(interp, paths, entry);
-        entry = CONST_STRING(interp, "lib/parrot/");
-        VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
+        /* This can be removed. TT #126 */
+        /* entry = CONST_STRING(interp, "lib/parrot/");
+           VTABLE_push_string(interp, paths, entry); */
     }
     else {
-#endif
         entry = CONST_STRING(interp, "runtime/parrot/library/");
         VTABLE_push_string(interp, paths, entry);
-        entry = CONST_STRING(interp, "runtime/parrot/");
+        /* This can be removed. TT #126 */
+        /*entry = CONST_STRING(interp, "runtime/parrot/"); 
+          VTABLE_push_string(interp, paths, entry);*/
+        entry = CONST_STRING(interp, "./");  /* with the build_dir */
         VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     }
-#endif
-    entry = CONST_STRING(interp, "./");
+    entry = CONST_STRING(interp, ""); /* do not add the prefix here */
     VTABLE_push_string(interp, paths, entry);
 
     /* define dynext paths */
     paths = pmc_new(interp, enum_class_ResizableStringArray);
     VTABLE_set_pmc_keyed_int(interp, lib_paths,
             PARROT_LIB_PATH_DYNEXT, paths);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     if (installed) {
-#endif
         entry = CONST_STRING(interp, "lib/parrot/dynext/");
         VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     }
     else {
-#endif
         entry = CONST_STRING(interp, "runtime/parrot/dynext/");
         VTABLE_push_string(interp, paths, entry);
-#ifdef ENABLE_PARROT_LIBRARY_INSTALLED
     }
-#endif
     entry = CONST_STRING(interp, "");
     VTABLE_push_string(interp, paths, entry);
 
@@ -467,7 +450,7 @@
 
 /*
 
-=item C<static STRING* try_load_path>
+=item C<static STRING* try_load_file>
 
 Attempts to load a file with name C<path>. If the file is successfully located,
 the finalized name of the file is returned as a STRING. Otherwise, returns
@@ -480,7 +463,7 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
 static STRING*
-try_load_path(PARROT_INTERP, ARGMOD(STRING* path))
+try_load_file(PARROT_INTERP, ARGMOD(STRING* path))
 {
     STRING *final;
 
@@ -488,9 +471,10 @@
 
     final = path_finalize(interp, final);
 
-    if (Parrot_stat_info_intval(interp, final, STAT_EXISTS)) {
+    /* only files */
+    if (Parrot_stat_info_intval(interp, final, STAT_EXISTS)
+        && !Parrot_stat_info_intval(interp, final, STAT_ISDIR))
         return final;
-    }
 
     return NULL;
 }
@@ -519,15 +503,33 @@
     /*
       First try the path without guessing the extension to ensure compatibility
       with existing code.
+      But if that finds a directory skip it.
+      e.g. load_bytecode "Test/Builder" => .pbc or .pir, but not the dir
      */
 
     with_ext = string_copy(interp, path);
 
-    result = try_load_path(interp, with_ext);
+    result = try_load_file(interp, with_ext);
     if (result)
         return result;
 
     /*
+      Check if the file already contains one of the 3 known extensions.
+      If so fail. A file test.pir.pbc will not be found on "test.pir"
+    */
+    for (guess = 0 ; guess <= LOAD_EXT_CODE_LAST ; guess++) {
+        STRING *d;
+        int len_ext = strlen(load_ext_code[guess]);
+        int len_str = with_ext->strlen;
+        if (len_str <= len_ext) continue;
+        if (!string_equal(interp, string_substr(interp, with_ext, -len_ext,
+                                                len_ext, NULL, 0),
+                          const_string(interp, load_ext_code[guess]))) {
+            return NULL;
+        }
+    }
+
+    /*
       Start guessing now. This version tries to find the lowest form of the
       code, starting with bytecode and working up to PIR. Note the atypical
       loop control. This is so the array can easily be processed in reverse.
@@ -538,11 +540,15 @@
         with_ext = string_append(interp,
                                  with_ext, const_string(interp, 
load_ext_code[guess]));
 
-        result = try_load_path(interp, with_ext);
+        result = try_load_file(interp, with_ext);
         if (result)
             return result;
     }
 
+    if (Parrot_stat_info_intval(interp, path, STAT_EXISTS)
+        && Parrot_stat_info_intval(interp, path, STAT_ISDIR))
+        Parrot_ex_throw_from_c_args(interp, NULL, 
EXCEPTION_SUBSTR_OUT_OF_STRING,
+                                    "'%s' is a directory", path->strstart);
     return NULL;
 }
 
@@ -624,16 +630,21 @@
     for (i = 0; i < n; ++i) {
         STRING * const path = VTABLE_get_string_keyed_int(interp, paths, i);
 
-        if (string_length(interp, prefix) && !is_abs_path(path))
+        if (string_length(interp, prefix)
+            && string_length(interp, path) /* empty libpath uses no prefix */
+            && !is_abs_path(path))
             full_name = path_concat(interp, prefix, path);
         else
             full_name = string_copy(interp, path);
 
-        full_name = path_append(interp, full_name, file);
+        if (string_length(interp, path))
+            full_name = path_append(interp, full_name, file);
+        else
+            full_name = string_copy(interp, file);
 
         full_name =
             (type & PARROT_RUNTIME_FT_DYNEXT)
-                ? try_load_path(interp, full_name)
+                ? try_load_file(interp, full_name)
                 : try_bytecode_extensions(interp, full_name);
 
         if (full_name)
@@ -642,7 +653,7 @@
 
     full_name =
         (type & PARROT_RUNTIME_FT_DYNEXT)
-            ? try_load_path(interp, file)
+            ? try_load_file(interp, file)
             : try_bytecode_extensions(interp, file);
 
     return full_name;

Added: branches/pdd30install_stage3/t/src/library.t
==============================================================================
--- (empty file)
+++ branches/pdd30install_stage3/t/src/library.t        Sun Jan  4 12:03:59 2009
@@ -0,0 +1,170 @@
+#! perl
+# Copyright (C) 2009, The Perl Foundation.
+# $Id$
+
+use strict;
+use warnings;
+use lib qw( . lib ../lib ../../lib );
+use Test::More;
+use Parrot::Test;
+use Parrot::Config;
+
+plan tests => 3;
+
+=head1 NAME
+
+t/src/library.t - Library search functions
+
+=head1 SYNOPSIS
+
+    % prove t/src/library.t
+
+=head1 DESCRIPTION
+
+Test some library search functionality for load_bytecode and .include.
+The library search path, directories versus missing extensions, finding files
+without extensions.
+
+  TT#123 remove more hard-coded runtime/ paths from libs
+  TT#126 optimize load_bytecode, .include paths: no library/ and include/ 
prefix
+  TT#127 do not stat extensions when an extension was already given.
+         If the given string is a directory, do not fail, try the extensions 
instead.
+         e.g. load_bytecode 'Test/Builder'
+  TT#128 [TODO] Honor source filetype when a .pbc is present
+
+We test this seperately, because core has another load_bytecode failure RT 
#39807,
+tested in t/op/load_bytecode.t
+
+=cut
+
+c_output_is( <<'CODE', <<'OUTPUT', "Parrot_locate_runtime_file" );
+
+#include <parrot/parrot.h>
+#include <parrot/embed.h>
+
+int
+main(int argc, char* argv[])
+{
+    Interp *interp;
+    int error_val;
+    char *path;
+
+    interp = Parrot_new(NULL);
+    if (!interp) {
+        return 1;
+    }
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper.pir", 
PARROT_RUNTIME_FT_SOURCE);
+    printf("%s\n", path);
+    if (path) free(path);
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper.pbc", 
PARROT_RUNTIME_FT_PBC);
+    printf("%s\n", path);
+    if (path) free(path);
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper", 
PARROT_RUNTIME_FT_PBC);
+    printf("%s\n", path);
+    if (path) free(path);
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper.pir", 
PARROT_RUNTIME_FT_INCLUDE);
+    printf("%s\n", path);
+    if (path) free(path);
+    path = Parrot_locate_runtime_file(interp, "library/Data/Dumper.pir", 
PARROT_RUNTIME_FT_INCLUDE);
+    printf("%s\n", path);
+    if (path) free(path);
+
+    Parrot_exit(interp, 0);
+    return 0;
+}
+CODE
+./runtime/parrot/library/Data/Dumper.pir
+./runtime/parrot/library/Data/Dumper.pbc
+./runtime/parrot/library/Data/Dumper.pbc
+(null)
+./runtime/parrot/library/Data/Dumper.pir
+OUTPUT
+
+my $dynpath = "." . $PConfig{slash} .
+  File::Spec->catfile("runtime","parrot","dynext","myops_ops")
+  . $PConfig{load_ext};
+c_output_is( <<'CODE', <<"OUTPUT", "FT_DYNEXT" );
+
+#include <parrot/parrot.h>
+#include <parrot/embed.h>
+
+int
+main(int argc, char* argv[])
+{
+    Interp *interp;
+    char *path;
+    STRING *result, *full_name, *wo_ext;
+    INTVAL i, n;
+
+    interp = Parrot_new(NULL);
+    if (!interp) {
+        return 1;
+    }
+
+    wo_ext = const_string(interp, "myops_ops");
+    full_name = string_concat(interp, wo_ext, const_string(interp, 
PARROT_LOAD_EXT), 0);
+    result = Parrot_locate_runtime_file_str(interp, full_name,
+                                            PARROT_RUNTIME_FT_DYNEXT);
+    if (result) {
+        printf("%s\n", result->strstart);
+    }
+    else {
+        if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) {
+            full_name = string_concat(interp, wo_ext, const_string(interp, 
PARROT_SHARE_EXT), 0);
+            result = Parrot_locate_runtime_file_str(interp, full_name,
+                                                    PARROT_RUNTIME_FT_DYNEXT);
+        }
+        printf("%s\n", result->strstart);
+    }
+
+    path = Parrot_locate_runtime_file(interp, "not_existing_op", 
PARROT_RUNTIME_FT_INCLUDE);
+    printf("%s\n", path);
+    if (path) free(path);
+
+    Parrot_exit(interp, 0);
+    return 0;
+}
+CODE
+$dynpath
+(null)
+OUTPUT
+
+c_output_is( <<'CODE', <<'OUTPUT', "FT_SOURCE, FT_PIR", 'todo' => 'TT #128 
force pir')
+
+#include <parrot/parrot.h>
+#include <parrot/embed.h>
+
+int
+main(int argc, char* argv[])
+{
+    Interp *interp;
+    int error_val;
+    char *path;
+
+    interp = Parrot_new(NULL);
+    if (!interp) {
+        return 1;
+    }
+
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper", 
PARROT_RUNTIME_FT_SOURCE);
+    printf("%s\n", path);
+    if (path) free(path);
+    path = Parrot_locate_runtime_file(interp, "Data/Dumper", 
PARROT_RUNTIME_FT_PIR);
+    printf("%s\n", path);
+    if (path) free(path);
+
+    Parrot_exit(interp, 0);
+    return 0;
+}
+CODE
+./runtime/parrot/library/Data/Dumper.pir
+./runtime/parrot/library/Data/Dumper.pir
+OUTPUT
+
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

Reply via email to