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 <[email protected]>
Subject: Re: How to determine whether running Perl 4 or perl 5?
Message-ID: <[email protected]>
Originator: [email protected]
Sender: [email protected] (USENET News System)
Reply-To: [email protected] (Tom Christiansen)
Organization: University of Colorado, Boulder
References: <[email protected]>
Date: Tue, 19 Oct 1993 11:44:20 GMT
Lines: 119

From the keyboard of [email protected] (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 [email protected]

$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      [email protected]
     "Will Hack Perl for Fine Food and Fun"
       Boulder Colorado  303-444-3212