2 Copyright (C) 2004-2009, Parrot Foundation.
7 src/library.c - Interface to Parrot's bytecode library
11 This file contains C functions to access Parrot's bytecode library functions,
12 for include files (via C<.include>), library files (via C<load_bytecode>), and
13 dynext files (via C<loadlib>).
23 #include "parrot/parrot.h"
24 #include "parrot/dynext.h"
25 #include "library.str"
27 /* HEADERIZER HFILE: include/parrot/library.h */
29 /* HEADERIZER BEGIN: static */
30 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
32 static void cnv_to_win32_filesep(ARGMOD(STRING
*path
))
33 __attribute__nonnull__(1)
36 PARROT_WARN_UNUSED_RESULT
37 PARROT_CANNOT_RETURN_NULL
38 static PMC
* get_search_paths(PARROT_INTERP
, enum_lib_paths which
)
39 __attribute__nonnull__(1);
42 static int is_abs_path(ARGIN(const STRING
*file
))
43 __attribute__nonnull__(1);
45 PARROT_WARN_UNUSED_RESULT
46 PARROT_CANNOT_RETURN_NULL
47 static STRING
* path_append(PARROT_INTERP
,
48 ARGMOD(STRING
*l_path
),
49 ARGMOD(STRING
*r_path
))
50 __attribute__nonnull__(1)
51 __attribute__nonnull__(2)
52 __attribute__nonnull__(3)
53 FUNC_MODIFIES(*l_path
)
54 FUNC_MODIFIES(*r_path
);
56 PARROT_WARN_UNUSED_RESULT
57 PARROT_CANNOT_RETURN_NULL
58 static STRING
* path_concat(PARROT_INTERP
,
59 ARGMOD(STRING
*l_path
),
60 ARGMOD(STRING
*r_path
))
61 __attribute__nonnull__(1)
62 __attribute__nonnull__(2)
63 __attribute__nonnull__(3)
64 FUNC_MODIFIES(*l_path
)
65 FUNC_MODIFIES(*r_path
);
67 PARROT_WARN_UNUSED_RESULT
68 PARROT_CANNOT_RETURN_NULL
69 static STRING
* path_finalize(PARROT_INTERP
, ARGMOD(STRING
*path
))
70 __attribute__nonnull__(1)
71 __attribute__nonnull__(2)
74 PARROT_WARN_UNUSED_RESULT
75 PARROT_CANNOT_RETURN_NULL
76 static STRING
* path_guarantee_trailing_separator(PARROT_INTERP
,
78 __attribute__nonnull__(1)
79 __attribute__nonnull__(2)
82 PARROT_WARN_UNUSED_RESULT
83 PARROT_CAN_RETURN_NULL
84 static STRING
* try_bytecode_extensions(PARROT_INTERP
, ARGMOD(STRING
* path
))
85 __attribute__nonnull__(1)
86 __attribute__nonnull__(2)
87 FUNC_MODIFIES(* path
);
89 PARROT_WARN_UNUSED_RESULT
90 PARROT_CAN_RETURN_NULL
91 static STRING
* try_load_path(PARROT_INTERP
, ARGMOD(STRING
* path
))
92 __attribute__nonnull__(1)
93 __attribute__nonnull__(2)
94 FUNC_MODIFIES(* path
);
96 #define ASSERT_ARGS_cnv_to_win32_filesep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
97 PARROT_ASSERT_ARG(path))
98 #define ASSERT_ARGS_get_search_paths __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
99 PARROT_ASSERT_ARG(interp))
100 #define ASSERT_ARGS_is_abs_path __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
101 PARROT_ASSERT_ARG(file))
102 #define ASSERT_ARGS_path_append __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
103 PARROT_ASSERT_ARG(interp) \
104 , PARROT_ASSERT_ARG(l_path) \
105 , PARROT_ASSERT_ARG(r_path))
106 #define ASSERT_ARGS_path_concat __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
107 PARROT_ASSERT_ARG(interp) \
108 , PARROT_ASSERT_ARG(l_path) \
109 , PARROT_ASSERT_ARG(r_path))
110 #define ASSERT_ARGS_path_finalize __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
111 PARROT_ASSERT_ARG(interp) \
112 , PARROT_ASSERT_ARG(path))
113 #define ASSERT_ARGS_path_guarantee_trailing_separator \
114 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
115 PARROT_ASSERT_ARG(interp) \
116 , PARROT_ASSERT_ARG(path))
117 #define ASSERT_ARGS_try_bytecode_extensions __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
118 PARROT_ASSERT_ARG(interp) \
119 , PARROT_ASSERT_ARG(path))
120 #define ASSERT_ARGS_try_load_path __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
121 PARROT_ASSERT_ARG(interp) \
122 , PARROT_ASSERT_ARG(path))
123 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
124 /* HEADERIZER END: static */
129 =item C<void parrot_init_library_paths(PARROT_INTERP)>
131 Create an array of StringArrays with library searchpaths and shared
132 extension used for loading various files at runtime. The created
133 structures looks like this:
136 [ "runtime/parrot/include", ... ], # paths for .include 'file'
137 [ "runtime/parrot/library", ... ], # paths for load_bytecode
138 [ "runtime/parrot/dynext", ... ], # paths for loadlib
139 [ "languages", ... ], # paths for languages
140 [ ".so", ... ] # list of shared extensions
143 If the platform defines
145 #define PARROT_PLATFORM_LIB_PATH_INIT_HOOK the_init_hook
147 it will be called as a function with this prototype:
149 void the_init_hook(PARROT_INTERP, PMC *lib_paths);
151 Platform code may add, delete, or replace search path entries as needed. See
152 also F<include/parrot/library.h> for C<enum_lib_paths>.
159 parrot_init_library_paths(PARROT_INTERP
)
161 ASSERT_ARGS(parrot_init_library_paths
)
164 STRING
*versionlib
= NULL
;
165 STRING
*builddir
= NULL
;
166 PMC
* const iglobals
= interp
->iglobals
;
167 PMC
* const config_hash
= VTABLE_get_pmc_keyed_int(interp
, iglobals
,
168 (INTVAL
)IGLOBALS_CONFIG_HASH
);
170 /* create the lib_paths array */
171 PMC
* const lib_paths
= pmc_new(interp
, enum_class_FixedPMCArray
);
173 VTABLE_set_integer_native(interp
, lib_paths
, PARROT_LIB_PATH_SIZE
);
174 VTABLE_set_pmc_keyed_int(interp
, iglobals
,
175 IGLOBALS_LIB_PATHS
, lib_paths
);
177 if (VTABLE_elements(interp
, config_hash
)) {
178 STRING
* const libkey
= CONST_STRING(interp
, "libdir");
179 STRING
* const verkey
= CONST_STRING(interp
, "versiondir");
180 STRING
* const builddirkey
= CONST_STRING(interp
, "build_dir");
181 STRING
* const installed
= CONST_STRING(interp
, "installed");
183 versionlib
= VTABLE_get_string_keyed_str(interp
, config_hash
, libkey
);
184 entry
= VTABLE_get_string_keyed_str(interp
, config_hash
, verkey
);
185 versionlib
= Parrot_str_append(interp
, versionlib
, entry
);
187 if (!VTABLE_get_integer_keyed_str(interp
, config_hash
, installed
))
188 builddir
= VTABLE_get_string_keyed_str(interp
,
189 config_hash
, builddirkey
);
192 /* each is an array of strings */
193 /* define include paths */
194 paths
= pmc_new(interp
, enum_class_ResizableStringArray
);
195 VTABLE_set_pmc_keyed_int(interp
, lib_paths
,
196 PARROT_LIB_PATH_INCLUDE
, paths
);
197 if (!STRING_IS_NULL(builddir
)) {
198 entry
= Parrot_str_concat(interp
, builddir
, CONST_STRING(interp
, "/"), 0);
199 VTABLE_push_string(interp
, paths
, entry
);
200 entry
= Parrot_str_concat(interp
, builddir
, CONST_STRING(interp
, "/runtime/parrot/include/"), 0);
201 VTABLE_push_string(interp
, paths
, entry
);
203 entry
= CONST_STRING(interp
, "./");
204 VTABLE_push_string(interp
, paths
, entry
);
205 if (!STRING_IS_NULL(versionlib
)) {
206 entry
= Parrot_str_concat(interp
, versionlib
, CONST_STRING(interp
, "/include/"), 0);
207 VTABLE_push_string(interp
, paths
, entry
);
211 /* define library paths */
212 paths
= pmc_new(interp
, enum_class_ResizableStringArray
);
213 VTABLE_set_pmc_keyed_int(interp
, lib_paths
,
214 PARROT_LIB_PATH_LIBRARY
, paths
);
215 if (!STRING_IS_NULL(builddir
)) {
216 entry
= Parrot_str_concat(interp
, builddir
, CONST_STRING(interp
, "/runtime/parrot/library/"), 0);
217 VTABLE_push_string(interp
, paths
, entry
);
219 entry
= CONST_STRING(interp
, "./");
220 VTABLE_push_string(interp
, paths
, entry
);
221 if (!STRING_IS_NULL(versionlib
)) {
222 entry
= Parrot_str_concat(interp
, versionlib
, CONST_STRING(interp
, "/library/"), 0);
223 VTABLE_push_string(interp
, paths
, entry
);
226 /* define languages paths */
227 paths
= pmc_new(interp
, enum_class_ResizableStringArray
);
228 VTABLE_set_pmc_keyed_int(interp
, lib_paths
,
229 PARROT_LIB_PATH_LANG
, paths
);
230 if (!STRING_IS_NULL(builddir
)) {
231 entry
= Parrot_str_concat(interp
, builddir
, CONST_STRING(interp
, "/runtime/parrot/languages/"), 0);
232 VTABLE_push_string(interp
, paths
, entry
);
234 entry
= CONST_STRING(interp
, "./");
235 VTABLE_push_string(interp
, paths
, entry
);
236 if (!STRING_IS_NULL(versionlib
)) {
237 entry
= Parrot_str_concat(interp
, versionlib
, CONST_STRING(interp
, "/languages/"), 0);
238 VTABLE_push_string(interp
, paths
, entry
);
241 /* define dynext paths */
242 paths
= pmc_new(interp
, enum_class_ResizableStringArray
);
243 VTABLE_set_pmc_keyed_int(interp
, lib_paths
,
244 PARROT_LIB_PATH_DYNEXT
, paths
);
245 if (!STRING_IS_NULL(builddir
)) {
246 entry
= Parrot_str_concat(interp
, builddir
, CONST_STRING(interp
, "/runtime/parrot/dynext/"), 0);
247 VTABLE_push_string(interp
, paths
, entry
);
249 entry
= CONST_STRING(interp
, "dynext/");
250 VTABLE_push_string(interp
, paths
, entry
);
251 if (!STRING_IS_NULL(versionlib
)) {
252 entry
= Parrot_str_concat(interp
, versionlib
, CONST_STRING(interp
, "/dynext/"), 0);
253 VTABLE_push_string(interp
, paths
, entry
);
257 paths
= pmc_new(interp
, enum_class_ResizableStringArray
);
258 VTABLE_set_pmc_keyed_int(interp
, lib_paths
,
259 PARROT_LIB_DYN_EXTS
, paths
);
260 /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */
261 entry
= Parrot_str_new_constant(interp
, PARROT_LOAD_EXT
);
262 VTABLE_push_string(interp
, paths
, entry
);
263 /* OS/X has .dylib and .bundle */
264 if (!STREQ(PARROT_LOAD_EXT
, PARROT_SHARE_EXT
)) {
265 entry
= Parrot_str_new_constant(interp
, PARROT_SHARE_EXT
);
266 VTABLE_push_string(interp
, paths
, entry
);
269 #ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK
270 PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interp
, lib_paths
);
276 =item C<static PMC* get_search_paths(PARROT_INTERP, enum_lib_paths which)>
278 Return lib_paths as array of StringArrays with library searchpaths and shared
279 extension used for loading various files at runtime.
280 The structure looks like this:
283 [ "runtime/parrot/include", ... ], # paths for .include 'file'
284 [ "runtime/parrot/library", ... ], # paths for load_bytecode
285 [ "runtime/parrot/dynext", ... ], # paths for loadlib
286 [ "languages", ... ], # paths for languages
287 [ ".so", ... ] # list of shared extensions
294 PARROT_WARN_UNUSED_RESULT
295 PARROT_CANNOT_RETURN_NULL
297 get_search_paths(PARROT_INTERP
, enum_lib_paths which
)
299 ASSERT_ARGS(get_search_paths
)
300 PMC
* const iglobals
= interp
->iglobals
;
301 PMC
* const lib_paths
= VTABLE_get_pmc_keyed_int(interp
, iglobals
,
303 return VTABLE_get_pmc_keyed_int(interp
, lib_paths
, which
);
306 static const char path_separator
= '/';
310 static const char win32_path_separator
= '\\';
316 =item C<static int is_abs_path(const STRING *file)>
318 Determines whether a file name given by a fixed-8 or utf8 C<STRING> is an
319 absolute file name. Returns C<1> if the filename is absolute, returns C<0>
328 is_abs_path(ARGIN(const STRING
*file
))
330 ASSERT_ARGS(is_abs_path
)
331 const char * const file_name
= file
->strstart
;
332 if (file
->strlen
<= 1)
334 PARROT_ASSERT(file
->encoding
== Parrot_fixed_8_encoding_ptr
||
335 file
->encoding
== Parrot_utf8_encoding_ptr
);
337 /* XXX ../foo, ./bar */
338 if (file_name
[0] == path_separator
340 || (file_name
[0] == win32_path_separator
||
341 (isalpha((unsigned char)file_name
[0]) && file
->strlen
> 2 &&
342 (strncmp(file_name
+1, ":\\", 2) == 0 ||
343 strncmp(file_name
+1, ":/", 2) == 0)))
345 /* no space before closing paren */)
357 =item C<static void cnv_to_win32_filesep(STRING *path)>
359 Converts a path with forward slashes to one with backward slashes.
366 cnv_to_win32_filesep(ARGMOD(STRING
*path
))
368 ASSERT_ARGS(cnv_to_win32_filesep
)
371 PARROT_ASSERT(path
->encoding
== Parrot_fixed_8_encoding_ptr
||
372 path
->encoding
== Parrot_utf8_encoding_ptr
);
374 cnv
= path
->strstart
;
375 while ((cnv
= strchr(cnv
, path_separator
)) != NULL
)
376 *cnv
= win32_path_separator
;
383 =item C<static STRING* path_finalize(PARROT_INTERP, STRING *path)>
385 Ensures the given STRING C<path> has a C-style NULL character at the end. The
386 length of the string is not increased to account for this NULL, however. In
387 WIN32 systems, the path separator is switched from the unix-style "/" to the
394 PARROT_WARN_UNUSED_RESULT
395 PARROT_CANNOT_RETURN_NULL
397 path_finalize(PARROT_INTERP
, ARGMOD(STRING
*path
))
399 ASSERT_ARGS(path_finalize
)
401 /* TODO create a string API that just does that
402 * a lot of ICU lib functions also need 0-terminated strings
403 * the goal is just to have for sure an invisible 0 at end
406 STRING
* const nul
= string_chr(interp
, '\0');
408 path
= Parrot_str_append(interp
, path
, nul
);
413 cnv_to_win32_filesep(path
);
421 =item C<static STRING* path_guarantee_trailing_separator(PARROT_INTERP, STRING
424 unary path argument. the path string will have a
425 trailing path-separator appended if it is not
432 PARROT_WARN_UNUSED_RESULT
433 PARROT_CANNOT_RETURN_NULL
435 path_guarantee_trailing_separator(PARROT_INTERP
, ARGMOD(STRING
*path
))
437 ASSERT_ARGS(path_guarantee_trailing_separator
)
438 STRING
* const path_separator_string
= string_chr(interp
, path_separator
);
440 /* make sure the path has a trailing slash before appending the file */
441 if (Parrot_str_indexed(interp
, path
, path
->strlen
- 1)
442 != Parrot_str_indexed(interp
, path_separator_string
, 0))
443 path
= Parrot_str_append(interp
, path
, path_separator_string
);
450 =item C<static STRING* path_append(PARROT_INTERP, STRING *l_path, STRING
453 binary path arguments, the left arg is modified.
454 a trailing separator is guaranteed for the left
455 argument and the right argument is appended
461 PARROT_WARN_UNUSED_RESULT
462 PARROT_CANNOT_RETURN_NULL
464 path_append(PARROT_INTERP
, ARGMOD(STRING
*l_path
), ARGMOD(STRING
*r_path
))
466 ASSERT_ARGS(path_append
)
467 l_path
= path_guarantee_trailing_separator(interp
, l_path
);
468 l_path
= Parrot_str_append(interp
, l_path
, r_path
);
475 =item C<static STRING* path_concat(PARROT_INTERP, STRING *l_path, STRING
478 binary path arguments. A new string is created
479 that is the concatenation of the two path components
480 with a path-separator.
486 PARROT_WARN_UNUSED_RESULT
487 PARROT_CANNOT_RETURN_NULL
489 path_concat(PARROT_INTERP
, ARGMOD(STRING
*l_path
), ARGMOD(STRING
*r_path
))
491 ASSERT_ARGS(path_concat
)
494 join
= Parrot_str_copy(interp
, l_path
);
495 join
= path_guarantee_trailing_separator(interp
, join
);
496 join
= Parrot_str_append(interp
, join
, r_path
);
503 =item C<static STRING* try_load_path(PARROT_INTERP, STRING* path)>
505 Attempts to load a file with name C<path>. If the file is successfully located,
506 the finalized name of the file is returned as a STRING. Otherwise, returns
513 PARROT_WARN_UNUSED_RESULT
514 PARROT_CAN_RETURN_NULL
516 try_load_path(PARROT_INTERP
, ARGMOD(STRING
* path
))
518 ASSERT_ARGS(try_load_path
)
521 final
= Parrot_str_copy(interp
, path
);
523 final
= path_finalize(interp
, final
);
525 if (Parrot_stat_info_intval(interp
, final
, STAT_EXISTS
)) {
534 =item C<static STRING* try_bytecode_extensions(PARROT_INTERP, STRING* path)>
536 Guess extensions, so that the user can drop the extensions
537 leaving it up to the build process/install whether or not
538 a .pbc, .pasm or a .pir file is used.
544 PARROT_WARN_UNUSED_RESULT
545 PARROT_CAN_RETURN_NULL
547 try_bytecode_extensions(PARROT_INTERP
, ARGMOD(STRING
* path
))
549 ASSERT_ARGS(try_bytecode_extensions
)
550 STRING
*test_path
, *result
;
551 STRING
* const bytecode_extension
= CONST_STRING(interp
, ".pbc");
552 STRING
* const pir_extension
= CONST_STRING(interp
, ".pir");
553 STRING
* const pasm_extension
= CONST_STRING(interp
, ".pasm");
555 test_path
= Parrot_str_copy(interp
, path
);
557 /* First try the path as given. */
558 result
= try_load_path(interp
, test_path
);
563 If the original requested file doesn't exist, try it with a
564 different extension. A requested PIR or PASM file will check for a
565 corresponding bytecode file. A requested bytecode file will check
566 first for a corresponding PIR file, then for a PASM file.
569 if (!STRING_IS_NULL(test_path
)) {
570 if (Parrot_str_byte_length(interp
, test_path
) > 4) {
571 STRING
*orig_ext
= Parrot_str_substr(interp
, test_path
, -4, 4, NULL
, 0);
572 /* First try substituting .pbc for the .pir extension */
573 if (Parrot_str_equal(interp
, orig_ext
, pir_extension
)) {
574 STRING
* const without_ext
= Parrot_str_chopn(interp
, test_path
, 4);
575 test_path
= Parrot_str_append(interp
, without_ext
, bytecode_extension
);
576 result
= try_load_path(interp
, test_path
);
580 /* Next try substituting .pir, then .pasm for the .pbc extension */
581 else if (Parrot_str_equal(interp
, orig_ext
, bytecode_extension
)) {
582 STRING
* const without_ext
= Parrot_str_chopn(interp
, test_path
, 4);
583 test_path
= Parrot_str_append(interp
, without_ext
, pir_extension
);
584 result
= try_load_path(interp
, test_path
);
588 test_path
= Parrot_str_append(interp
, without_ext
, pasm_extension
);
589 result
= try_load_path(interp
, test_path
);
596 /* Finally, try substituting .pbc for the .pasm extension. */
597 if (Parrot_str_byte_length(interp
, test_path
) > 5) {
598 STRING
* const orig_ext
= Parrot_str_substr(interp
, test_path
, -5, 5, NULL
, 0);
599 if (Parrot_str_equal(interp
, orig_ext
, pasm_extension
)) {
600 STRING
* const without_ext
= Parrot_str_chopn(interp
, test_path
, 5);
601 test_path
= Parrot_str_append(interp
, without_ext
, bytecode_extension
);
602 result
= try_load_path(interp
, test_path
);
614 =item C<void Parrot_lib_add_path(PARROT_INTERP, STRING *path_str, enum_lib_paths
617 Add a path to the library searchpath of the given type (passing in a STRING).
625 Parrot_lib_add_path(PARROT_INTERP
,
626 ARGIN(STRING
*path_str
),
627 enum_lib_paths which
)
629 ASSERT_ARGS(Parrot_lib_add_path
)
630 PMC
* const iglobals
= interp
->iglobals
;
631 PMC
* const lib_paths
= VTABLE_get_pmc_keyed_int(interp
, iglobals
,
633 PMC
* const paths
= VTABLE_get_pmc_keyed_int(interp
, lib_paths
, which
);
634 VTABLE_unshift_string(interp
, paths
, path_str
);
639 =item C<void Parrot_lib_add_path_from_cstring(PARROT_INTERP, const char *path,
640 enum_lib_paths which)>
642 Add a path to the library searchpath of the given type (passing in a C string).
650 Parrot_lib_add_path_from_cstring(PARROT_INTERP
,
651 ARGIN(const char *path
),
652 enum_lib_paths which
)
654 ASSERT_ARGS(Parrot_lib_add_path_from_cstring
)
655 STRING
* const path_str
= Parrot_str_new(interp
, path
, 0);
656 Parrot_lib_add_path(interp
, path_str
, which
);
661 =item C<STRING* Parrot_locate_runtime_file_str(PARROT_INTERP, STRING *file,
662 enum_runtime_ft type)>
664 Locate the full path for C<file_name> and the given file type(s).
666 The C<enum_runtime_ft type> is one or more of the types defined in
667 F<include/parrot/library.h>.
674 PARROT_WARN_UNUSED_RESULT
675 PARROT_CAN_RETURN_NULL
677 Parrot_locate_runtime_file_str(PARROT_INTERP
, ARGMOD(STRING
*file
),
678 enum_runtime_ft type
)
680 ASSERT_ARGS(Parrot_locate_runtime_file_str
)
686 /* if this is an absolute path return it as is */
687 if (is_abs_path(file
))
690 if (type
& PARROT_RUNTIME_FT_LANG
)
691 paths
= get_search_paths(interp
, PARROT_LIB_PATH_LANG
);
692 else if (type
& PARROT_RUNTIME_FT_DYNEXT
)
693 paths
= get_search_paths(interp
, PARROT_LIB_PATH_DYNEXT
);
694 else if (type
& (PARROT_RUNTIME_FT_PBC
| PARROT_RUNTIME_FT_SOURCE
))
695 paths
= get_search_paths(interp
, PARROT_LIB_PATH_LIBRARY
);
697 paths
= get_search_paths(interp
, PARROT_LIB_PATH_INCLUDE
);
699 prefix
= Parrot_get_runtime_path(interp
);
700 n
= VTABLE_elements(interp
, paths
);
702 for (i
= 0; i
< n
; ++i
) {
703 STRING
* const path
= VTABLE_get_string_keyed_int(interp
, paths
, i
);
706 full_name
= Parrot_str_copy(interp
, path
);
707 full_name
= path_append(interp
, full_name
, file
);
710 (type
& PARROT_RUNTIME_FT_DYNEXT
)
711 ? try_load_path(interp
, full_name
)
712 : try_bytecode_extensions(interp
, full_name
);
717 if (Parrot_str_byte_length(interp
, prefix
) && !is_abs_path(path
)) {
718 full_name
= path_concat(interp
, prefix
, full_name
);
721 (type
& PARROT_RUNTIME_FT_DYNEXT
)
722 ? try_load_path(interp
, full_name
)
723 : try_bytecode_extensions(interp
, full_name
);
731 (type
& PARROT_RUNTIME_FT_DYNEXT
)
732 ? try_load_path(interp
, file
)
733 : try_bytecode_extensions(interp
, file
);
740 =item C<char* Parrot_locate_runtime_file(PARROT_INTERP, const char *file_name,
741 enum_runtime_ft type)>
743 Locate the full path for C<file_name> and the given file type(s). If
744 successful, returns a C-string allocated with C<Parrot_str_to_cstring> or
745 NULL otherwise. Remember to free the string with C<Parrot_str_free_cstring()>.
747 If successful, the returned STRING is 0-terminated so that
748 C<result-E<gt>strstart> is usable as B<const char*> c-string for C library
749 functions like fopen(3). This is the preferred API function.
751 The C<enum_runtime_ft type> is one or more of the types defined in
752 F<include/parrot/library.h>.
760 PARROT_WARN_UNUSED_RESULT
761 PARROT_CAN_RETURN_NULL
764 Parrot_locate_runtime_file(PARROT_INTERP
, ARGIN(const char *file_name
),
765 enum_runtime_ft type
)
767 ASSERT_ARGS(Parrot_locate_runtime_file
)
768 STRING
* const file
= Parrot_str_new(interp
, file_name
, 0);
769 STRING
* const result
= Parrot_locate_runtime_file_str(interp
, file
, type
);
771 * XXX valgrind shows e.g.
772 * invalid read of size 8 inside a string of length 69
774 * it seems that dlopen accesses words beyond the string end
776 * see also the log at #37814
778 return result
? Parrot_str_to_cstring(interp
, result
) : NULL
;
783 =item C<char* Parrot_get_runtime_prefix(PARROT_INTERP)>
785 Return a malloced C-string for the runtime prefix. The calling function
788 This function is deprecated, use Parrot_get_runtime_path instead.
797 PARROT_CANNOT_RETURN_NULL
799 Parrot_get_runtime_prefix(PARROT_INTERP
)
801 ASSERT_ARGS(Parrot_get_runtime_prefix
)
802 char * const env
= Parrot_getenv(interp
, CONST_STRING(interp
, "PARROT_RUNTIME"));
807 PMC
* const config_hash
=
808 VTABLE_get_pmc_keyed_int(interp
, interp
->iglobals
, (INTVAL
) IGLOBALS_CONFIG_HASH
);
810 if (VTABLE_elements(interp
, config_hash
)) {
811 STRING
* const key
= CONST_STRING(interp
, "prefix");
812 STRING
* const s
= VTABLE_get_string_keyed_str(interp
, config_hash
, key
);
813 return Parrot_str_to_cstring(interp
, s
);
816 return mem_sys_strdup(".");
822 =item C<STRING * Parrot_get_runtime_path(PARROT_INTERP)>
824 Return a string for the runtime prefix.
831 PARROT_CANNOT_RETURN_NULL
833 Parrot_get_runtime_path(PARROT_INTERP
)
835 ASSERT_ARGS(Parrot_get_runtime_path
)
836 char * const env
= Parrot_getenv(interp
, CONST_STRING(interp
, "PARROT_RUNTIME"));
841 result
= Parrot_str_new(interp
, env
, 0);
844 PMC
* const config_hash
=
845 VTABLE_get_pmc_keyed_int(interp
, interp
->iglobals
, (INTVAL
) IGLOBALS_CONFIG_HASH
);
847 if (VTABLE_elements(interp
, config_hash
)) {
848 STRING
* const key
= CONST_STRING(interp
, "prefix");
849 result
= VTABLE_get_string_keyed_str(interp
, config_hash
, key
);
852 result
= CONST_STRING(interp
, ".");
859 =item C<STRING * parrot_split_path_ext(PARROT_INTERP, STRING *in, STRING
860 **wo_ext, STRING **ext)>
862 Split the pathstring C<in> into <path><filestem><ext>. Return the
863 C<filestem> of the pathstring. Set C<wo_ext> to the part without
864 extension and C<ext> to the extension or NULL.
870 PARROT_IGNORABLE_RESULT
871 PARROT_CANNOT_RETURN_NULL
873 parrot_split_path_ext(PARROT_INTERP
, ARGMOD(STRING
*in
),
874 ARGOUT(STRING
**wo_ext
), ARGOUT(STRING
**ext
))
876 ASSERT_ARGS(parrot_split_path_ext
)
878 /* This is a quick fix for TT #65
879 * TODO: redo it with the string reimplementation
881 const char * charset
= Parrot_charset_c_name(interp
,
882 Parrot_charset_number_of_str(interp
, in
));
883 STRING
* const slash1
= string_make(interp
, "/", 1, charset
,
884 PObj_external_FLAG
|PObj_constant_FLAG
);
885 STRING
* const slash2
= string_make(interp
, "\\", 1, charset
,
886 PObj_external_FLAG
|PObj_constant_FLAG
);
887 STRING
* const dot
= string_make(interp
, ".", 1, charset
,
888 PObj_external_FLAG
|PObj_constant_FLAG
);
890 const INTVAL len
= Parrot_str_byte_length(interp
, in
);
892 INTVAL pos_sl
, pos_dot
;
894 pos_sl
= CHARSET_RINDEX(interp
, in
, slash1
, len
);
896 pos_sl
= CHARSET_RINDEX(interp
, in
, slash2
, len
);
897 pos_dot
= CHARSET_RINDEX(interp
, in
, dot
, len
);
899 /* ignore dot in directory name */
900 if (pos_dot
!= -1 && pos_dot
< pos_sl
)
905 if (pos_sl
&& pos_dot
) {
906 stem
= Parrot_str_substr(interp
, in
, pos_sl
, pos_dot
- pos_sl
- 1,
908 *wo_ext
= Parrot_str_substr(interp
, in
, 0, pos_dot
- 1, NULL
, 0);
909 *ext
= Parrot_str_substr(interp
, in
, pos_dot
, len
- pos_dot
, NULL
, 0);
912 stem
= Parrot_str_substr(interp
, in
, 0, pos_dot
- 1, NULL
, 0);
914 *ext
= Parrot_str_substr(interp
, in
, pos_dot
, len
- pos_dot
, NULL
, 0);
917 stem
= Parrot_str_substr(interp
, in
, pos_sl
, len
- pos_sl
, NULL
, 0);
918 *wo_ext
= Parrot_str_copy(interp
, in
);
922 stem
= Parrot_str_copy(interp
, in
);
935 F<include/parrot/library.h>
944 * c-file-style: "parrot"
946 * vim: expandtab shiftwidth=4: