It turns out that, if you use a magic number right now, you can modify the paths Parrot uses to load libraries. I found two problems doing so, which the attached test and code patch addresses.
First, Parrot assumed that all include paths were relative. That's no good, but it was easy to fix. Second, Parrot assumed that all include paths had a trailing path specifier -- that is, that concatening the include file/path would work correctly. I fixed that too. The test part of the patch explores both issues. There's one remaining nit that I didn't address, that the enum_lib_paths constants in F<include/parrot/library.h> are not available via iglobals.pasm. I could use PARROT_LIB_PATH_LIBRARY for this. I browsed the constant generator, but didn't find an easy way to generate this information. For now, there's a hard-coded magic number. If there are no objections, I'm happy to apply this patch. -- c $ diffstat add_lib_paths.patch src/library.c | 9 ++++++- t/compilers/imcc/syn/file.t | 56 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-)
=== src/library.c ================================================================== --- src/library.c (revision 20174) +++ src/library.c (local) @@ -214,12 +214,19 @@ n = VTABLE_elements(interpreter, paths); for (i = 0; i < n; ++i) { path = VTABLE_get_string_keyed_int(interpreter, paths, i); - if (string_length(interpreter, prefix)) { + if (string_length(interpreter, prefix) && + !is_abs_path(interpreter,path)) { full_name = string_concat(interpreter, prefix, slash, 0); full_name = string_append(interpreter, full_name, path, 0); } else full_name = string_copy(interpreter, path); + + /* make sure this path has a trailing slash before appending the file */ + if ( string_index(interpreter, full_name, full_name->strlen - 1) + != string_index(interpreter, slash, 0)) + full_name = string_append(interpreter, full_name, slash, 0); + full_name = string_append(interpreter, full_name, file, 0); /* TODO create a string API that just does that * a lot of ICU lib functions also need 0-terminated strings === t/compilers/imcc/syn/file.t ================================================================== --- t/compilers/imcc/syn/file.t (revision 20174) +++ t/compilers/imcc/syn/file.t (local) @@ -5,9 +5,10 @@ use strict; use warnings; use lib qw( . lib ../lib ../../lib ); +use File::Spec; use Test::More; use Parrot::Config; -use Parrot::Test tests => 12; +use Parrot::Test tests => 13; =head1 NAME @@ -426,9 +427,62 @@ OUT } +my @temp_files; +SKIP: +{ + my $temp_dir = File::Spec->tmpdir(); + my $td2 = File::Spec->catfile( $temp_dir, '.' ); + substr( $td2, -1, 1, '' ); + + for my $file ( qw( with_slash without_slash )) + { + push @temp_files, File::Spec->catfile( $temp_dir, "${file}.pir" ); + + open( my $out_fh, '>', $temp_files[-1] ) or + skip("Cannot write temporary file to $temp_files[-1]", 2); + + print {$out_fh} <<"TEMP_PIR"; +.sub $file + print "$file() called!\\n" +.end +TEMP_PIR + } + + pir_output_is(<<"CODE", <<'OUT', "load PIR from added paths, minding slash"); + .include 'iglobals.pasm' + + .sub main :main + .local pmc interp + getinterp interp + + .local pmc lib_paths + lib_paths = interp[.IGLOBALS_LIB_PATHS] + + # XXX - hard-coded magic constant (should be PARROT_LIB_PATH_LIBRARY) + .local pmc include_paths + include_paths = lib_paths[1] + + unshift include_paths, '$temp_dir' + load_bytecode 'with_slash.pir' + + .local pmc dummy + dummy = shift include_paths + unshift include_paths, '$td2' + load_bytecode 'without_slash.pir' + + with_slash() + without_slash() + .end +CODE +with_slash() called! +without_slash() called! +OUT +} + END { unlink $file; unlink "temp.pir"; unlink "temp.pbc"; + unlink @temp_files; }