Article 6978 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:6978
Newsgroups: comp.lang.perl
Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!howland.reston.ans.net!europa.eng.gtefsd.com!uunet!boulder!wraeththu.cs.colorado.edu!tchrist
From: Tom Christiansen <tchrist@cs.Colorado.EDU>
Subject: Re: How to determine whether running Perl 4 or perl 5?
Message-ID: <CF579w.H2E@Colorado.EDU>
Originator: tchrist@wraeththu.cs.colorado.edu
Sender: news@Colorado.EDU (USENET News System)
Reply-To: tchrist@cs.colorado.edu (Tom Christiansen)
Organization: University of Colorado, Boulder
References: <lusol-181093162421@meatball.cc.lehigh.edu>
Date: Tue, 19 Oct 1993 11:44:20 GMT
Lines: 119

From the keyboard of lusol@Lehigh.EDU (Stephen O. Lidie):
:Can a Perl program determine at run time whether Perl 4 or Perl 5 is in
:control?

Of course you can use $], although for really old versions,
you must use it as a string and not a number.  The problem is
that perl4 probably won't compile perl5 code at all, so you won't 
get that far.

To deal with this, I have on occasion used this.    It has its limits.
I may make it better and take a path of directories.

#!/usr/local/bin/perl
#
# preambulate -- wrap a perl program with a system-independent preamble.  
#
# Tom Christiansen tchrist@colorado.edu

$mypath = '/usr/local/bin/perl';
($myversion, $mypatchlevel) = $] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;


unless (@ARGV) {
    unshift(@ARGV, '-');
    $was_stdin++;
}

while ($file = shift) {
    open(file, $file) || die "can't open $file: $!";
    $mode = (stat(file))[2] & 0777;
    if ($file ne '-') {
	$TMP = "$file.tmp";
	open (TMP, ">$TMP") || die "can't create $TMP: $!"; 
     } else {
	open (TMP, ">&STDOUT");
     } 
     print TMP <<'EOF';
#!/bin/sh -- need to mention perl here to avoid recursion

'true' || eval 'exec perl -S $0 $argv:q';
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
        if 0;

VERSION_SANITY: {
    package VERSION_SANITY;
    local($_);
EOF
    print TMP <<"EOF";
    \$PERL_PATH = '$mypath';
    local(\$version, \$patchlevel) = ($myversion, $mypatchlevel);
EOF

    print TMP <<'EOF';

    local($want_vp) = sprintf("%d.%03d", $version, $patchlevel);
    local($need_perl) = $PERL_PATH . $want_vp;

    die "can't get version" 
	unless $] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;

    sub try_version {
        warn "current perl version ($got_vp) too low, execing $need_perl\n";
        exec $need_perl, $0, @ARGV;
        warn "exec of $need_perl failed: $!";
    }

    if ($1 < $version || $2 < $patchlevel) { 
	local($got_vp) =  sprintf("%d.%03d", $1, $2);
        &try_version if -x $need_perl;
        for $need_perl (reverse sort </usr/local/bin/perl* /usr/bin/perl*>) {
            next unless $need_perl =~ /perl(\d+)\.(\d+)$/;
            &try_version if $1 >= $version && $2 >= $patchlevel;
        }
        warn "WARNING: perl version too low: $got_vp < $want_vp; good luck...\n";
    } 
} 

@VS'info = (__FILE__, __LINE__); eval <<'___VERSION_SANITY___';

# BEGIN REAL PROGRAM

EOF

    while (<file>) {
	print TMP;
    } 

    print TMP <<'EOF';


# END REAL PROGRAM

___VERSION_SANITY___


if ($@) {
    $_ = $@;
    ($file, $line) =  @VS'info;
    s/ file \(eval\) at line (\d+)/" $file at line " .  ($1 + $line)/eg;
    s/ at \(eval\) line (\d+)/" in $file at line " .  ($1 + $line)/eg;
    die $_;;
}

exit 0;

EOF

    unless ($file eq '-') {
	close TMP;
	chmod $mode, $TMP;
	rename ($file, "$file.bak") || die "can't rename $file to $file.bak: $!";
	rename ($TMP, $file) || die "can't rename $TMP to $file: $!";
    }
}
-- 
    Tom Christiansen      tchrist@cs.colorado.edu       
      "Will Hack Perl for Fine Food and Fun"
	Boulder Colorado  303-444-3212


