2 Copyright (C) 2004, The Perl Foundation.
7 src/library.c - Interface to Parrot's bytecode library
11 This file contains a C function to access parrot's bytecode library functions.
21 #include "parrot/parrot.h"
22 #include "parrot/dynext.h"
24 #include "library.str"
28 =item C<void parrot_init_library_paths(Interp *)>
30 Create an array of StringArrays with library searchpaths and shared
31 extension used for loading various files at runtime. The created
32 structures looks like this:
35 [ "runtime/parrot/include", ... ], # paths for .include 'file'
36 [ "runtime/parrot/library", ... ], # paths for load_bytecode
37 [ "runtime/parrot/dynext", ... ], # paths for loadlib
38 [ ".so", ... ] # list of shared extensions
41 If the platform defines
43 #define PARROT_PLATFORM_LIB_PATH_INIT_HOOK the_init_hook
45 if will be called as a function with this prototype:
47 void the_init_hook(Interp*, PMC *lib_paths);
49 Platform code may add, delete, or replace search path entries as needed. See
50 also F<include/parrot/library.h> for C<enum_lib_paths>.
57 parrot_init_library_paths(Interp
*interpreter
)
59 PMC
*iglobals
, *lib_paths
, *paths
;
62 iglobals
= interpreter
->iglobals
;
63 /* create the lib_paths array */
64 lib_paths
= pmc_new(interpreter
, enum_class_FixedPMCArray
);
65 VTABLE_set_integer_native(interpreter
, lib_paths
, PARROT_LIB_PATH_SIZE
);
66 VTABLE_set_pmc_keyed_int(interpreter
, iglobals
,
67 IGLOBALS_LIB_PATHS
, lib_paths
);
68 /* each is an array of strings */
69 /* define include paths */
70 paths
= pmc_new(interpreter
, enum_class_ResizableStringArray
);
71 VTABLE_set_pmc_keyed_int(interpreter
, lib_paths
,
72 PARROT_LIB_PATH_INCLUDE
, paths
);
73 entry
= CONST_STRING(interpreter
, "runtime/parrot/include/");
74 VTABLE_push_string(interpreter
, paths
, entry
);
75 entry
= CONST_STRING(interpreter
, "runtime/parrot/");
76 VTABLE_push_string(interpreter
, paths
, entry
);
77 entry
= CONST_STRING(interpreter
, "./");
78 VTABLE_push_string(interpreter
, paths
, entry
);
79 entry
= CONST_STRING(interpreter
, "lib/parrot/include/");
80 VTABLE_push_string(interpreter
, paths
, entry
);
81 entry
= CONST_STRING(interpreter
, "lib/parrot/");
82 VTABLE_push_string(interpreter
, paths
, entry
);
84 /* define library paths */
85 paths
= pmc_new(interpreter
, enum_class_ResizableStringArray
);
86 VTABLE_set_pmc_keyed_int(interpreter
, lib_paths
,
87 PARROT_LIB_PATH_LIBRARY
, paths
);
88 entry
= CONST_STRING(interpreter
, "runtime/parrot/library/");
89 VTABLE_push_string(interpreter
, paths
, entry
);
90 entry
= CONST_STRING(interpreter
, "runtime/parrot/");
91 VTABLE_push_string(interpreter
, paths
, entry
);
92 entry
= CONST_STRING(interpreter
, "./");
93 VTABLE_push_string(interpreter
, paths
, entry
);
94 entry
= CONST_STRING(interpreter
, "lib/parrot/library/");
95 VTABLE_push_string(interpreter
, paths
, entry
);
96 entry
= CONST_STRING(interpreter
, "lib/parrot/");
97 VTABLE_push_string(interpreter
, paths
, entry
);
99 /* define dynext paths */
100 paths
= pmc_new(interpreter
, enum_class_ResizableStringArray
);
101 VTABLE_set_pmc_keyed_int(interpreter
, lib_paths
,
102 PARROT_LIB_PATH_DYNEXT
, paths
);
103 entry
= CONST_STRING(interpreter
, "runtime/parrot/dynext/");
104 VTABLE_push_string(interpreter
, paths
, entry
);
105 entry
= CONST_STRING(interpreter
, "");
106 VTABLE_push_string(interpreter
, paths
, entry
);
107 entry
= CONST_STRING(interpreter
, "lib/parrot/dynext/");
108 VTABLE_push_string(interpreter
, paths
, entry
);
111 paths
= pmc_new(interpreter
, enum_class_ResizableStringArray
);
112 VTABLE_set_pmc_keyed_int(interpreter
, lib_paths
,
113 PARROT_LIB_DYN_EXTS
, paths
);
114 /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */
115 entry
= const_string(interpreter
, PARROT_LOAD_EXT
);
116 VTABLE_push_string(interpreter
, paths
, entry
);
117 /* OS/X has .dylib and .bundle */
118 if (strcmp(PARROT_LOAD_EXT
, PARROT_SHARE_EXT
)) {
119 entry
= const_string(interpreter
, PARROT_SHARE_EXT
);
120 VTABLE_push_string(interpreter
, paths
, entry
);
123 #ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK
124 PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interpreter
, lib_paths
);
129 get_search_paths(Interp
*interpreter
, enum_lib_paths which
)
131 PMC
*iglobals
, *lib_paths
;
133 iglobals
= interpreter
->iglobals
;
134 lib_paths
= VTABLE_get_pmc_keyed_int(interpreter
, iglobals
,
136 return VTABLE_get_pmc_keyed_int(interpreter
, lib_paths
, which
);
140 is_abs_path(Interp
* interpreter
, STRING
*file
)
144 file_name
= file
->strstart
;
145 if (file
->strlen
<= 1)
147 assert(file
->encoding
== Parrot_fixed_8_encoding_ptr
||
148 file
->encoding
== Parrot_utf8_encoding_ptr
);
150 if (file_name
[0] == '\\' || file_name
[0] == '/' ||
151 (isalpha(file_name
[0]) && file
->strlen
> 2 &&
152 (strncmp(file_name
+1, ":\\", 2) == 0 ||
153 strncmp(file_name
+1, ":/", 2) == 0)))
155 if (file_name
[0] == '/') /* XXX ../foo, ./bar */
165 =item C<char* Parrot_locate_runtime_file(Interp *, const char *file_name,
166 enum_runtime_ft type)>
168 Locate the full path for C<file_name> and the given file type(s). If
169 successful, returns a C-string allocated with C<string_to_cstring> or
172 =item C<STRING* Parrot_locate_runtime_file_str(Interp *, STRING *file_name,
173 enum_runtime_ft type)>
175 Like above but use and return STRINGs. If successful, the returned STRING
176 is 0-terminated so that C<result-E<gt>strstart> is usable as B<const char*>
177 c-string for C library functions like fopen(3).
178 This is the prefered API function.
180 The C<enum_runtime_ft type> is one or more of the types defined in
181 F<include/parrot/library.h>.
188 Parrot_locate_runtime_file_str(Interp
*interpreter
, STRING
*file
,
189 enum_runtime_ft type
)
191 STRING
*prefix
, *path
, *full_name
, *slash
, *nul
;
195 /* if this is an absolute path return it as is */
196 if (is_abs_path(interpreter
, file
))
199 if (type
& PARROT_RUNTIME_FT_DYNEXT
)
200 paths
= get_search_paths(interpreter
, PARROT_LIB_PATH_DYNEXT
);
201 else if (type
& (PARROT_RUNTIME_FT_PBC
| PARROT_RUNTIME_FT_SOURCE
))
202 paths
= get_search_paths(interpreter
, PARROT_LIB_PATH_LIBRARY
);
204 paths
= get_search_paths(interpreter
, PARROT_LIB_PATH_INCLUDE
);
207 slash
= CONST_STRING(interpreter
, "\\");
209 slash
= CONST_STRING(interpreter
, "/");
212 nul
= string_from_const_cstring(interpreter
, "\0", 1);
213 Parrot_get_runtime_prefix(interpreter
, &prefix
);
214 n
= VTABLE_elements(interpreter
, paths
);
215 for (i
= 0; i
< n
; ++i
) {
216 path
= VTABLE_get_string_keyed_int(interpreter
, paths
, i
);
217 if (string_length(interpreter
, prefix
) &&
218 !is_abs_path(interpreter
,path
)) {
219 full_name
= string_concat(interpreter
, prefix
, slash
, 0);
220 full_name
= string_append(interpreter
, full_name
, path
);
223 full_name
= string_copy(interpreter
, path
);
225 /* make sure this path has a trailing slash before appending the file */
226 if ( string_index(interpreter
, full_name
, full_name
->strlen
- 1)
227 != string_index(interpreter
, slash
, 0))
228 full_name
= string_append(interpreter
, full_name
, slash
);
230 full_name
= string_append(interpreter
, full_name
, file
);
231 /* TODO create a string API that just does that
232 * a lot of ICU lib functions also need 0-terminated strings
233 * the goal is just to have for sure an invisible 0 at end
235 full_name
= string_append(interpreter
, full_name
, nul
);
236 full_name
->bufused
--;
241 assert(full_name
->encoding
== Parrot_fixed_8_encoding_ptr
||
242 full_name
->encoding
== Parrot_utf8_encoding_ptr
);
243 while ( (p
= strchr(full_name
->strstart
, '/')) )
247 if (Parrot_stat_info_intval(interpreter
, full_name
, STAT_EXISTS
)) {
251 /* finally try as is */
252 full_name
= string_append(interpreter
, file
, nul
);
253 full_name
->bufused
--;
258 assert(full_name
->encoding
== Parrot_fixed_8_encoding_ptr
||
259 full_name
->encoding
== Parrot_utf8_encoding_ptr
);
260 while ( (p
= strchr(full_name
->strstart
, '/')) )
264 if (Parrot_stat_info_intval(interpreter
, full_name
, STAT_EXISTS
)) {
271 Parrot_locate_runtime_file(Interp
*interpreter
, const char *file_name
,
272 enum_runtime_ft type
)
274 STRING
*file
= string_from_cstring(interpreter
, file_name
, 0);
275 STRING
*result
= Parrot_locate_runtime_file_str(interpreter
,
278 * XXX valgrind shows e.g.
279 * invalid read of size 8 inside a string of length 69
281 * it seems that dlopen accesses words beyond the string end
283 * see also the log at #37814
285 return string_to_cstring(interpreter
, result
);
289 =item C<const char* Parrot_get_runtime_prefix(Interp *, STRING **prefix_str)>
291 If C<prefix_str> is not NULL, set it to the prefix, else
292 return a malloced c-string for the runtime prefix.
299 Parrot_get_runtime_prefix(Interp
*interpreter
, STRING
**prefix_str
)
306 env
= Parrot_getenv("PARROT_RUNTIME", &free_it
);
309 *prefix_str
= string_from_cstring(interpreter
, env
, 0);
319 config_hash
= VTABLE_get_pmc_keyed_int(interpreter
, interpreter
->iglobals
,
320 (INTVAL
) IGLOBALS_CONFIG_HASH
);
321 key
= CONST_STRING(interpreter
, "prefix");
322 if (!VTABLE_elements(interpreter
, config_hash
)) {
323 const char *pwd
= ".";
327 *prefix_str
= const_string(interpreter
, pwd
);
330 ret
= mem_sys_allocate(3);
334 s
= VTABLE_get_string_keyed_str(interpreter
, config_hash
, key
);
339 return string_to_cstring(interpreter
, s
);
344 =item C<void Parrot_autoload_class(Interp *, STRING *class)>
346 Try to load a library that holds the PMC class.
348 XXX Check if this is still needed with HLL type mappings.
354 Parrot_autoload_class(Interp
*interpreter
, STRING
*class)
356 static const struct {
360 { "Py", "python_group" },
361 { "Tcl", "tcl_group" }
366 cclass
= string_to_cstring(interpreter
, class);
367 for (i
= 0; i
< sizeof(mappings
)/sizeof(mappings
[0]); ++i
) {
368 if (!memcmp(mappings
[i
].prefix
, cclass
, strlen(mappings
[i
].prefix
))) {
369 STRING
*slib
= const_string(interpreter
, mappings
[i
].lib
);
370 Parrot_load_lib(interpreter
, slib
, NULL
);
374 string_cstring_free(cclass
);
381 parrot_split_path_ext(Interp*, STRING *in, STRING **wo_ext, STRING **ext)>
383 Split the pathstring C<in> into <path><filestem><ext>. Return the
384 C<filestem> of the pathstring. Set C<wo_ext> to the part without
385 extension and C<ext> to the extension or NULL.
392 parrot_split_path_ext(Interp
* interpreter
, STRING
*in
,
393 STRING
**wo_ext
, STRING
**ext
)
395 STRING
*slash1
, *slash2
, *dot
, *stem
;
396 INTVAL pos_sl
, pos_dot
, len
;
397 slash1
= CONST_STRING(interpreter
, "/");
398 slash2
= CONST_STRING(interpreter
, "\\");
399 dot
= CONST_STRING(interpreter
, ".");
400 len
= string_length(interpreter
, in
);
401 pos_sl
= CHARSET_RINDEX(interpreter
, in
, slash1
, len
);
403 pos_sl
= CHARSET_RINDEX(interpreter
, in
, slash2
, len
);
404 pos_dot
= CHARSET_RINDEX(interpreter
, in
, dot
, len
);
406 /* XXX directory parrot-0.4.1 or such */
407 if (pos_dot
!= -1 && isdigit( ((char*)in
->strstart
)[pos_dot
+1]))
412 if (pos_sl
&& pos_dot
) {
413 stem
= string_substr(interpreter
, in
, pos_sl
, pos_dot
- pos_sl
- 1,
415 *wo_ext
= string_substr(interpreter
, in
, 0, pos_dot
- 1, NULL
, 0);
416 *ext
= string_substr(interpreter
, in
, pos_dot
, len
- pos_dot
, NULL
, 0);
419 stem
= string_substr(interpreter
, in
, 0, pos_dot
- 1, NULL
, 0);
421 *ext
= string_substr(interpreter
, in
, pos_dot
, len
- pos_dot
, NULL
, 0);
424 stem
= string_substr(interpreter
, in
, pos_sl
, len
- pos_sl
, NULL
, 0);
425 *wo_ext
= string_copy(interpreter
, in
);
429 stem
= string_copy(interpreter
, in
);
441 F<include/parrot/library.h>
450 * c-file-style: "parrot"
452 * vim: expandtab shiftwidth=4: