develooper Front page | perl.perl5.porters | Postings from July 2012

disentangling version's XS from util.c and universal.c might bepossible (was Re: supporting untarring of extensions)

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
July 12, 2012 06:59
Subject:
disentangling version's XS from util.c and universal.c might bepossible (was Re: supporting untarring of extensions)
Message ID:
20120712135906.GZ9583@plum.flirble.org
On Wed, Jul 11, 2012 at 10:23:42PM +0100, Nicholas Clark wrote:
> On Wed, Jul 11, 2012 at 09:49:18PM +0100, Nicholas Clark wrote:
> 
> > You're never going to fix version.pm with this, because parts of it are
> > hard coded into util.c. Sorry.
> > 
> > (But if it *is* possible to kick parts of util.c out into XS code, then
> > it may well be possible to fix how we handle version.pm without changing the
> > build system at all)
> 
> Right. version::vpp provides a pure perl emulation of some of version,
> doesn't it? I see that it wants to use POSIX for locale_h. As an
> experiment, if that's patched to remove that code (assume that it's the "C"
> locale), and util.c is patched to remove all the version:: XS code
> (ie #if 0/#endif), is version::vpp good enough for miniperl to be able to
> get through the entire build process until the build process wants to run
> ./perl ?
> 
> (It's permissible to do evil in lib/buildcustomize.pl such as loading modules
> and alias symbol tables. That has almost complete control over what miniperl
> actually ends up being when it actually gets to run the real script.)

Answer - for *this* approach, seems no. Better suggestion below.

I've "removed" the version XS functions like this:

diff --git a/universal.c b/universal.c
index a7c480f..654a1c0 100644
--- a/universal.c
+++ b/universal.c
@@ -1360,6 +1360,7 @@ struct xsub_details details[] = {
     {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
     {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
     {"UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, NULL},
+#if 0
     {"version::()", XS_version_noop, NULL},
     {"version::new", XS_version_new, NULL},
     {"version::parse", XS_version_new, NULL},
@@ -1388,6 +1389,7 @@ struct xsub_details details[] = {
     {"version::qv", XS_version_qv, NULL},
     {"version::declare", XS_version_qv, NULL},
     {"version::is_qv", XS_version_is_qv, NULL},
+#endif
     {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
     {"utf8::valid", XS_utf8_valid, NULL},
     {"utf8::encode", XS_utf8_encode, NULL},

I've hacked vpp.pm slightly:

$ diff -u lib/version/vpp.pm~ lib/version/vpp.pm
--- lib/version/vpp.pm~ 2011-09-25 15:53:55.000000000 +0200
+++ lib/version/vpp.pm  2012-07-12 12:54:39.797804113 +0200
@@ -115,11 +115,11 @@
     return $string;
 }
 
-package version::vpp;
+package version;
 use strict;
 
-use POSIX qw/locale_h/;
-use locale;
+##use POSIX qw/locale_h/;
+##use locale;
 use vars qw ($VERSION @ISA @REGEXS);
 $VERSION = 0.94;
 
@@ -145,8 +145,8 @@
 my $VERSION_MAX = 0x7FFFFFFF;
 
 # implement prescan_version as closely to the C version as possible
-use constant TRUE  => 1;
-use constant FALSE => 0;
+sub TRUE() {1}
+sub FALSE() {0}
 
 sub isDIGIT {
     my ($char) = shift->thischar();
@@ -573,14 +573,14 @@
            return $self;
        }
 
-       my $currlocale = setlocale(LC_ALL);
+##     my $currlocale = setlocale(LC_ALL);
 
        # if the current locale uses commas for decimal points, we
        # just replace commas with decimal places, rather than changing
        # locales
-       if ( localeconv()->{decimal_point} eq ',' ) {
-           $value =~ tr/,/./;
-       }
+##     if ( localeconv()->{decimal_point} eq ',' ) {
+##         $value =~ tr/,/./;
+##     }
 
        if ( not defined $value or $value =~ /^undef$/ ) {
            # RT #19517 - special case for undef comparison


and I have added this to the end of lib/buildcustomize.pl

require version::vpp;


(note, not use, as @INC isn't set up quite right).

And i hit a roadblock:

$ ./miniperl -Ilib -e 'print "Bother\n" unless $^V eq 5.17.2'
Can't locate B.pm in @INC (@INC contains: /home/nick/Perl/perl/cpan/AutoLoader/lib /home/nick/Perl/perl/dist/Carp/lib /home/nick/Perl/perl/dist/Cwd /home/nick/Perl/perl/dist/Cwd/lib /home/nick/Perl/perl/dist/ExtUtils-Command/lib /home/nick/Perl/perl/dist/ExtUtils-Install/lib /home/nick/Perl/perl/cpan/ExtUtils-MakeMaker/lib /home/nick/Perl/perl/dist/ExtUtils-Manifest/lib /home/nick/Perl/perl/cpan/File-Path/lib /home/nick/Perl/perl/ext/re /home/nick/Perl/perl/dist/Term-ReadLine/lib /home/nick/Perl/perl/lib .) at /home/nick/Perl/perl/lib/version/vpp.pm line 863.

(which prevents lib/Config.pm from being built)

The problem is this, and I can't see a direct way round it:

sub _find_magic_vstring {
    my $value = shift;
    my $tvalue = '';
    require B;
    my $sv = B::svref_2object(\$value);
    my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef;
    while ( $magic ) {
	if ( $magic->TYPE eq 'V' ) {
	    $tvalue = $magic->PTR;
	    $tvalue =~ s/^v?(.+)$/v$1/;
	    last;
	}
	else {
	    $magic = $magic->MOREMAGIC;
	}
    }
    return $tvalue;
}

so that approach doesn't see to work. So:

> Because if that's a yes, then there looks like a route to getting all
> of version.pm/version.xs etc into cpan/, and that painful can of worms
> squished. 


But I think another approach might well work.

I *think* that the code in version's vutil/vutil.c is (pretty much) exactly
the code in (part of) util.c

1) Hence, it ought to be possible to #include "cpan/version/vutil/vutil.c"
   from util.c, and de-dup the code. It will likely need a few #defines
   and #ifdefs added in a couple of places.

I *think* that the code in universal.c is supposed to be the same as
the version/vutil/vxs.c that ExtUtils::ParseXS generates from vxs.xs

Whilst we have somewhat a bootstrapping problem in that miniperl needs that
code to build lib/Config.pm to build ... to build ExtUtils::ParseXS to build
that code, *unlike* DynaLoader this isn't horrible platform specific mess.
So it might well be possible to

2) split out that bit of universal.c into another C file which is #include-ed
   from universal.c

3) potentially, automate *generating* that file from vxs.xs (in some fashion),
   and having a script in regen/ to do this, and a test in t/porting/regen.t
   to check that it doesn't diverge.

Does anyone want to try this, or should I add it to Porting/todo.pod so that
it doesn't get lost?

Nicholas Clark

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About