# New Ticket Created by Mike Mattie # Please include the string: [perl #42944] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=42944 >
Hello, This is a patch, and two new files: parrot/include/path.h src/path.c These changes move the static path handling utilities out of library.c into their own translation unit. This allows all of the parrot code to use a single implementation of common path handling functions. slight modifications were made to the win32 specific portions that need to be re-tested on that platform. I modified the config/gen/makefiles/root.in to get it compiling properly , but I might have missed something as this is my first change to the makefile. I get two harness failures I haven't figured out yet: t/op/sprintf.....................................ok 1/308parrot: src/string.c:727: string_str_index: Assertion `s->encoding && s->charset && !(((s)->obj.flags) & b_PObj_on_free_list_FLAG)' failed. This may be because I modified the functions in path.c to use more of the string API instead of bypassing it. Someone else may be able to decode this assertion failure so I can pinpoint where it is coming from. I suspect that it is coming from path.c:217 . In fact that entire function needs to be reviewed, I don't have the unicode experience to understand it's string manipulation. beyond the change on 217 I haven't touched that code with a cleanup yet. # Failed test (t/perl/Parrot_IO.t at line 159) t/perl/Parrot_IO.................................NOK 51/57# Looks like you failed 1 test of 57. This one I don't get at all. This could be random. Other than those two failures the test-suite passed on i686-pc-gnu-linux Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- t/op/sprintf.t 0 6 308 234 192-308 t/perl/Parrot_IO.t 1 256 57 1 51 9 tests and 512 subtests skipped. Failed 2/304 test scripts. 118/7217 subtests failed. Files=304, Tests=7217, 575 wallclock secs (288.14 cusr + 46.41 csys = 334.55 CPU) Failed 2/304 test programs. 118/7217 subtests failed. Cheers, Mike Mattie
/*
Copyright (C) 2004-2007, The Perl Foundation.
=head1 NAME
src/path.c
=head1 DESCRIPTION
This file contains a C functions for parrot's platform independent
path handling.
=head2 Functions
=over 6
=cut
*/
#include "parrot/parrot.h"
#include "parrot/path.h"
#include "path.str"
static const char parrot_path_separator = '/';
#ifdef WIN32
static const char platform_path_separator = '\\';
/*
* Converts a path with forward slashes to one with backward slashes.
*/
static void
cnv_to_platform_filesep (STRING *path) {
char* cnv;
assert(path->encoding == Parrot_fixed_8_encoding_ptr ||
path->encoding == Parrot_utf8_encoding_ptr);
cnv = Parrot_string_cstring(path);
while ((cnv = strchr(cnv, parrot_path_separator)) != NULL)
*cnv = platform_path_seperator;
}
#else
static const char platform_path_separator = '/';
#endif
/*
=item C<STRING *
parrot_path_is_abs(Interp*, STRING *path)>
return true if the given file is an absolute path, false if relative.
=cut
*/
int
parrot_path_is_abs(Interp* interp, STRING *path)
{
const char *file_name;
if ( !string_length(interp, path) )
return 0;
assert(path->encoding == Parrot_fixed_8_encoding_ptr
|| path->encoding == Parrot_utf8_encoding_ptr);
file_name = Parrot_string_cstring(interp,path);
return (file_name[0] == parrot_path_separator
#ifdef WIN32
|| file_name[0] == platform_path_seperator
|| (isalpha(file_name[0])
&& string_length(file) > 2
&& (strncmp(file_name+1, ":\\", 2) == 0
|| strncmp(file_name+1, ":/", 2) == 0))
#endif
) ? 1 : 0;
}
/*
=item C<STRING *
parrot_path_trailing_separator(Interp*, STRING *path)>
Ensure that the given path has a trailing path separator.
A new string may be returned.
=cut
*/
STRING*
parrot_path_trailing_separator(Interp *interp, STRING *path)
{
STRING *path_separator_string = string_chr(interp, platform_path_separator);
/* make sure the path has a trailing slash before appending the file */
if (string_index(interp, path , string_length(interp,path) - 1)
!= string_index(interp, path_separator_string, 0))
path = string_append(interp, path , path_separator_string);
return path;
}
/*
=item C<STRING *
parrot_path_platform_localize(Interp*, STRING *path)>
Localize a path to the platform by converting the parrot path
seperator to the platform seperator if necessary. Also a "hidden
zero" is appended to the path making it suitable for use by C API's
such as platform file/IO.
=cut
*/
STRING*
parrot_path_platform_localize(Interp *interp, STRING *path)
{
#ifdef WIN32
cnv_to_platform_filesep(path);
#endif
/* TODO create a string API that just does that
* a lot of ICU lib functions also need 0-terminated strings
* the goal is just to have for sure an invisible 0 at end
*/
STRING *nul = string_chr(interp, '\0');
path = string_append(interp, path, nul);
path->bufused--;
path->strlen--;
return path;
}
/*
=item C<STRING *
parrot_path_append(Interp*, STRING *orig, STRING *append)>
Concatenate two paths with the platform specific path seperator. The
result may be a new string.
=cut
*/
STRING*
parrot_path_append(Interp *interp, STRING *orig, STRING *append)
{
orig = parrot_path_trailing_separator(interp, orig);
return string_append(interp, orig, append);
}
/*
=item C<STRING *
parrot_path_concat(Interp*, STRING *orig, STRING *append)>
Concatenate two paths with the platform specific path seperator.
The result is garunteed to be a new string.
=cut
*/
STRING*
parrot_path_concat(Interp *interp, STRING *orig, STRING *append)
{
STRING* join;
join = string_copy(interp, orig);
join = parrot_path_trailing_separator(interp, join);
return string_append(interp, join , append);
}
/*
=item C<STRING *
parrot_split_path_ext(Interp*, STRING *in, STRING **wo_ext, STRING **ext)>
Split the pathstring C<in> into <path><filestem><ext>. Return the
C<filestem> of the pathstring. Set C<wo_ext> to the part without
extension and C<ext> to the extension or NULL.
=cut
*/
STRING *
parrot_split_path_ext(Interp* interp, STRING *in,
STRING **wo_ext, STRING **ext)
{
STRING *slash1, *slash2, *dot, *stem;
INTVAL pos_sl, pos_dot, len;
slash1 = CONST_STRING(interp, "/");
slash2 = CONST_STRING(interp, "\\");
dot = CONST_STRING(interp, ".");
len = string_length(interp, in);
pos_sl = CHARSET_RINDEX(interp, in, slash1, len);
if (pos_sl == -1)
pos_sl = CHARSET_RINDEX(interp, in, slash2, len);
pos_dot = CHARSET_RINDEX(interp, in, dot, len);
/* XXX directory parrot-0.4.1 or such */
if (pos_dot != -1 && isdigit(((char*)in->strstart)[pos_dot+1]))
pos_dot = -1;
++pos_dot;
++pos_sl;
if (pos_sl && pos_dot) {
stem = string_substr(interp, in, pos_sl, pos_dot - pos_sl - 1,
NULL, 0);
*wo_ext = string_substr(interp, in, 0, pos_dot - 1, NULL, 0);
*ext = string_substr(interp, in, pos_dot, len - pos_dot, NULL, 0);
}
else if (pos_dot) {
stem = string_substr(interp, in, 0, pos_dot - 1, NULL, 0);
*wo_ext = stem;
*ext = string_substr(interp, in, pos_dot, len - pos_dot, NULL, 0);
}
else if (pos_sl) {
stem = string_substr(interp, in, pos_sl, len - pos_sl, NULL, 0);
*wo_ext = string_copy(interp, in);
*ext = 0;
}
else {
stem = string_copy(interp, in);
*wo_ext = stem;
*ext = NULL;
}
return stem;
}
/*
=back
=head1 SEE ALSO
F<include/parrot/path.h>
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
/* path.h
* Copyright (C) 2007, The Perl Foundation.
*
* Overview:
* Contains functions for handling paths in a platform
* independent manner, similar to Path::Spec from perl5
*
* Data Structure and Algorithms:
* History:
* Notes:
* References:
*/
#ifndef PARROT_PATH_H_GUARD
#define PARROT_PATH_H_GUARD
int
parrot_path_is_abs(Interp* interp, STRING *path);
STRING*
parrot_path_trailing_separator(Interp *interp, STRING *path);
STRING*
parrot_path_platform_localize(Interp *interp, STRING *path);
STRING*
parrot_path_append(Interp *interp, STRING *orig, STRING *append);
STRING*
parrot_path_concat(Interp *interp, STRING *orig, STRING *append);
STRING * parrot_split_path_ext(Interp* , STRING *in,
STRING **wo_ext, STRING **ext);
#endif /* PARROT_PATH_H_GUARD */
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
--- HEAD/src/dynext.c 2007-05-12 04:26:05.000000000 -0700
+++ path-api/src/dynext.c 2007-05-14 04:02:41.000000000 -0700
@@ -18,6 +18,7 @@
#include "parrot/parrot.h"
#include "parrot/dynext.h"
+#include "parrot/path.h"
/* _PARROTLIB is now the default */
/*#define _PARROTLIB not working: "make testr" */
--- HEAD/src/library.c 2007-05-12 15:41:34.000000000 -0700
+++ path-api/src/library.c 2007-05-14 03:58:26.000000000 -0700
@@ -19,10 +19,12 @@
*/
#include "parrot/parrot.h"
-#include "parrot/dynext.h"
-#include <assert.h>
+#include "parrot/path.h"
+
#include "library.str"
+#include <assert.h>
+
/*
=item C<void parrot_init_library_paths(Interp *)>
@@ -136,126 +138,6 @@
return VTABLE_get_pmc_keyed_int(interp, lib_paths, which);
}
-static int
-is_abs_path(Interp* interp, STRING *file)
-{
- char *file_name;
-
- file_name = file->strstart;
- if (file->strlen <= 1)
- return 0;
- assert(file->encoding == Parrot_fixed_8_encoding_ptr ||
- file->encoding == Parrot_utf8_encoding_ptr);
-#ifdef WIN32
- if (file_name[0] == '\\' || file_name[0] == '/' ||
- (isalpha(file_name[0]) && file->strlen > 2 &&
- (strncmp(file_name+1, ":\\", 2) == 0 ||
- strncmp(file_name+1, ":/", 2) == 0)))
-#else
- if (file_name[0] == '/') /* XXX ../foo, ./bar */
-#endif
- {
- return 1;
- }
- return 0;
-}
-
-static const char path_separator = '/';
-
-#ifdef WIN32
-
-static const char win32_path_separator = '\\';
-
-/*
- Converts a path with forward slashes to one with backward slashes.
-*/
-static void
-cnv_to_win32_filesep (STRING *path) {
- char* cnv;
-
- assert(path->encoding == Parrot_fixed_8_encoding_ptr ||
- path->encoding == Parrot_utf8_encoding_ptr);
-
- cnv = path->strstart;
- while ((cnv = strchr(cnv, path_separator)) != NULL)
- *cnv = win32_path_separator;
-}
-
-#endif
-
-static STRING*
-path_finalize(Interp *interp, STRING *path)
-{
-
- /* TODO create a string API that just does that
- * a lot of ICU lib functions also need 0-terminated strings
- * the goal is just to have for sure an invisible 0 at end
- */
-
- STRING *nul = string_chr(interp, '\0');
-
- path = string_append(interp, path, nul);
- path->bufused--;
- path->strlen--;
-
-#ifdef WIN32
- cnv_to_win32_filesep(path);
-#endif
-
- return path;
-}
-
-/*
- unary path argument. the path string will have a
- trailing path-separator appended if it is not
- there already.
- */
-
-static STRING*
-path_guarantee_trailing_separator(Interp *interp, STRING *path)
-{
- STRING *path_separator_string = string_chr(interp, path_separator);
-
- /* make sure the path has a trailing slash before appending the file */
- if (string_index(interp, path , path->strlen - 1)
- != string_index(interp, path_separator_string, 0))
- path = string_append(interp, path , path_separator_string);
-
- return path;
-}
-
-/*
- binary path arguments, the left arg is modified.
- a trailing separator is guaranteed for the left
- argument and the right argument is appended
- */
-
-static STRING*
-path_append(Interp *interp, STRING *l_path, STRING *r_path)
-{
- l_path = path_guarantee_trailing_separator(interp, l_path);
- l_path = string_append(interp, l_path , r_path);
-
- return l_path;
-}
-
-/*
- binary path arguments. A new string is created
- that is the concatenation of the two path components
- with a path-separator.
- */
-
-static STRING*
-path_concat(Interp *interp, STRING *l_path, STRING *r_path)
-{
- STRING* join;
-
- join = string_copy(interp, l_path);
- join = path_guarantee_trailing_separator(interp, join);
- join = string_append(interp, join , r_path);
-
- return join;
-}
#define LOAD_EXT_CODE_LAST 3
@@ -280,7 +162,7 @@
string_to_cstring(interp, final ));
#endif
- final = path_finalize(interp, final );
+ final = parrot_path_platform_localize(interp, final );
if (Parrot_stat_info_intval(interp, final , STAT_EXISTS)) {
return final;
@@ -368,7 +250,7 @@
#endif
/* if this is an absolute path return it as is */
- if (is_abs_path(interp, file))
+ if (parrot_path_is_abs(interp, file))
return file;
if (type & PARROT_RUNTIME_FT_DYNEXT)
@@ -383,13 +265,13 @@
for (i = 0; i < n; ++i) {
path = VTABLE_get_string_keyed_int(interp, paths, i);
if (string_length(interp, prefix) &&
- !is_abs_path(interp,path)) {
- full_name = path_concat(interp, prefix , path);
+ !parrot_path_is_abs(interp,path)) {
+ full_name = parrot_path_concat(interp, prefix , path);
}
else
full_name = string_copy(interp, path);
- full_name = path_append(interp, full_name , file);
+ full_name = parrot_path_append(interp, full_name , file);
full_name = ( type & PARROT_RUNTIME_FT_DYNEXT )
? try_load_path(interp, full_name)
@@ -484,63 +366,6 @@
/*
-=item C<STRING *
-parrot_split_path_ext(Interp*, STRING *in, STRING **wo_ext, STRING **ext)>
-
-Split the pathstring C<in> into <path><filestem><ext>. Return the
-C<filestem> of the pathstring. Set C<wo_ext> to the part without
-extension and C<ext> to the extension or NULL.
-
-=cut
-
-*/
-
-STRING *
-parrot_split_path_ext(Interp* interp, STRING *in,
- STRING **wo_ext, STRING **ext)
-{
- STRING *slash1, *slash2, *dot, *stem;
- INTVAL pos_sl, pos_dot, len;
- slash1 = CONST_STRING(interp, "/");
- slash2 = CONST_STRING(interp, "\\");
- dot = CONST_STRING(interp, ".");
- len = string_length(interp, in);
- pos_sl = CHARSET_RINDEX(interp, in, slash1, len);
- if (pos_sl == -1)
- pos_sl = CHARSET_RINDEX(interp, in, slash2, len);
- pos_dot = CHARSET_RINDEX(interp, in, dot, len);
-
- /* XXX directory parrot-0.4.1 or such */
- if (pos_dot != -1 && isdigit(((char*)in->strstart)[pos_dot+1]))
- pos_dot = -1;
-
- ++pos_dot;
- ++pos_sl;
- if (pos_sl && pos_dot) {
- stem = string_substr(interp, in, pos_sl, pos_dot - pos_sl - 1,
- NULL, 0);
- *wo_ext = string_substr(interp, in, 0, pos_dot - 1, NULL, 0);
- *ext = string_substr(interp, in, pos_dot, len - pos_dot, NULL, 0);
- }
- else if (pos_dot) {
- stem = string_substr(interp, in, 0, pos_dot - 1, NULL, 0);
- *wo_ext = stem;
- *ext = string_substr(interp, in, pos_dot, len - pos_dot, NULL, 0);
- }
- else if (pos_sl) {
- stem = string_substr(interp, in, pos_sl, len - pos_sl, NULL, 0);
- *wo_ext = string_copy(interp, in);
- *ext = 0;
- }
- else {
- stem = string_copy(interp, in);
- *wo_ext = stem;
- *ext = NULL;
- }
- return stem;
-}
-/*
-
=back
=head1 SEE ALSO
--- HEAD/include/parrot/library.h 2007-05-12 04:26:20.000000000 -0700
+++ path-api/include/parrot/library.h 2007-05-14 03:21:46.000000000 -0700
@@ -40,8 +40,6 @@
PARROT_API char* Parrot_get_runtime_prefix(Interp *, STRING **prefix);
void parrot_init_library_paths(Interp *);
-STRING * parrot_split_path_ext(Interp* , STRING *in,
- STRING **wo_ext, STRING **ext);
#endif /* PARROT_LIBRARY_H_GUARD */
--- HEAD/config/gen/makefiles/root.in 2007-05-12 15:41:35.000000000 -0700
+++ path-api/config/gen/makefiles/root.in 2007-05-14 03:50:54.000000000 -0700
@@ -483,6 +483,7 @@
$(PF_DIR)/pf_items$(O) \
$(SRC_DIR)/stm/backend$(O) \
$(SRC_DIR)/stm/waitlist$(O) \
+ $(SRC_DIR)/path$(O) \
@TEMP_gc_o@
O_FILES = \
@@ -609,6 +610,7 @@
$(SRC_DIR)/global.str \
$(SRC_DIR)/global_setup.str \
$(SRC_DIR)/library.str \
+ $(SRC_DIR)/path.str \
$(SRC_DIR)/mmd.str \
$(SRC_DIR)/pmc.str \
$(SRC_DIR)/objects.str \
signature.asc
Description: PGP signature
