integrate cfgperl contents into mainline
Gurusamy Sarathy [Sun, 1 Aug 1999 21:23:18 +0000 (21:23 +0000)]
p4raw-id: //depot/perl@3860

1  2 
Configure
Makefile.SH
embed.pl
perl.h
pod/perldelta.pod
pod/perldiag.pod
proto.h
regexec.c
util.c

diff --combined Configure
+++ b/Configure
@@@ -20,7 -20,7 +20,7 @@@
  
  # $Id: Head.U,v 3.0.1.9 1997/02/28 15:02:09 ram Exp $
  #
- # Generated on Wed Jul 28 20:32:22 EET DST 1999 [metaconfig 3.0 PL70]
+ # Generated on Sun Aug  1 00:18:49 EET DST 1999 [metaconfig 3.0 PL70]
  # (with additional metaconfig patches by perlbug@perl.com)
  
  cat >/tmp/c1$$ <<EOF
@@@ -282,6 -282,8 +282,8 @@@ baserev='
  bin=''
  binexp=''
  installbin=''
+ bincompat5005=''
+ d_bincompat5005=''
  byteorder=''
  cc=''
  gccversion=''
@@@ -2570,24 -2572,16 +2572,16 @@@ case "$usethreads" i
  : user has specified that a threading perl is to be built,
  : we may need to set or change some other defaults.
        if $test -f usethreads.cbu; then
+               echo "Your platform has some specific hints for threaded builds, using them..."
                . ./usethreads.cbu
-       fi
-       case "$osname" in
-       aix|dec_osf|dos_djgpp|freebsd|hpux|irix|linux|next|openbsd|os2|solaris|vmesa)
-               # Known thread-capable platforms.
-               ;;
-       *)
-               cat >&4 <<EOM
- $osname is not known to support threads.
- Please let perlbug@perl.com know how to do that.
- Cannot continue, aborting.
+       else
+               $cat <<EOM
+ (Your platform doesn't have any specific hints for threaded builds.
+  Assuming POSIX threads, then.)
  EOM
-               exit 1
-       ;;
-       esac # $osname
+       fi
      ;;
- esac # $usethreads
+ esac
  
  cat <<EOM
  
  set usemultiplicity
  eval $setvar 
  
+ : determine where manual pages are on this system
+ echo " "
+ case "$sysman" in
+ '') 
+       syspath='/usr/man/man1 /usr/man/mann /usr/man/manl /usr/man/local/man1'
+       syspath="$syspath /usr/man/u_man/man1 /usr/share/man/man1"
+       syspath="$syspath /usr/catman/u_man/man1 /usr/man/l_man/man1"
+       syspath="$syspath /usr/local/man/u_man/man1 /usr/local/man/l_man/man1"
+       syspath="$syspath /usr/man/man.L /local/man/man1 /usr/local/man/man1"
+       sysman=`./loc . /usr/man/man1 $syspath`
+       ;;
+ esac
+ if $test -d "$sysman"; then
+       echo "System manual is in $sysman." >&4
+ else
+       echo "Could not find manual pages in source form." >&4
+ fi
+ : see what memory models we can support
+ case "$models" in
+ '')
+       $cat >pdp11.c <<'EOP'
+ int main() {
+ #ifdef pdp11
+       exit(0);
+ #else
+       exit(1);
+ #endif
+ }
+ EOP
+       ( cc -o pdp11 pdp11.c ) >/dev/null 2>&1
+       if $test -f pdp11 && ./pdp11 2>/dev/null; then
+               dflt='unsplit split'
+       else
+               tans=`./loc . X /lib/small /lib/large /usr/lib/small /usr/lib/large /lib/medium /usr/lib/medium /lib/huge`
+               case "$tans" in
+               X) dflt='none';;
+               *) if $test -d /lib/small || $test -d /usr/lib/small; then
+                               dflt='small'
+                       else
+                               dflt=''
+                       fi
+                       if $test -d /lib/medium || $test -d /usr/lib/medium; then
+                               dflt="$dflt medium"
+                       fi
+                       if $test -d /lib/large || $test -d /usr/lib/large; then
+                               dflt="$dflt large"
+                       fi
+                       if $test -d /lib/huge || $test -d /usr/lib/huge; then
+                               dflt="$dflt huge"
+                       fi
+               esac
+       fi;;
+ *) dflt="$models";;
+ esac
+ $cat <<EOM
+  
+ Some systems have different model sizes.  On most systems they are called
+ small, medium, large, and huge.  On the PDP11 they are called unsplit and
+ split.  If your system doesn't support different memory models, say "none".
+ If you wish to force everything to one memory model, say "none" here and
+ put the appropriate flags later when it asks you for other cc and ld flags.
+ Venix systems may wish to put "none" and let the compiler figure things out.
+ (In the following question multiple model names should be space separated.)
+ The default for most systems is "none".
+ EOM
+ rp="Which memory models are supported?"
+ . ./myread
+ models="$ans"
+ case "$models" in
+ none)
+       small=''
+       medium=''
+       large=''
+       huge=''
+       unsplit=''
+       split=''
+       ;;
+ *split)
+       case "$split" in
+       '') if $contains '\-i' $sysman/ld.1 >/dev/null 2>&1 || \
+                        $contains '\-i' $sysman/cc.1 >/dev/null 2>&1; then
+                       dflt='-i'
+               else
+                       dflt='none'
+               fi;;
+       *) dflt="$split";;
+       esac
+       rp="What flag indicates separate I and D space?"
+       . ./myread
+       tans="$ans"
+       case "$tans" in
+       none) tans='';;
+       esac
+       split="$tans"
+       unsplit='';;
+ *large*|*small*|*medium*|*huge*)
+       case "$models" in
+       *large*)
+               case "$large" in
+               '') dflt='-Ml';;
+               *) dflt="$large";;
+               esac
+       rp="What flag indicates large model?"
+       . ./myread
+       tans="$ans"
+       case "$tans" in
+       none) tans='';
+       esac
+       large="$tans";;
+       *) large='';;
+       esac
+       case "$models" in
+       *huge*) case "$huge" in
+               '') dflt='-Mh';;
+               *) dflt="$huge";;
+               esac
+               rp="What flag indicates huge model?"
+               . ./myread
+               tans="$ans"
+               case "$tans" in
+               none) tans='';
+               esac
+               huge="$tans";;
+       *) huge="$large";;
+       esac
+       case "$models" in
+       *medium*) case "$medium" in
+               '') dflt='-Mm';;
+               *) dflt="$medium";;
+               esac
+               rp="What flag indicates medium model?"
+               . ./myread
+               tans="$ans"
+               case "$tans" in
+               none) tans='';
+               esac
+               medium="$tans";;
+       *) medium="$large";;
+       esac
+       case "$models" in
+       *small*) case "$small" in
+               '') dflt='none';;
+               *) dflt="$small";;
+               esac
+               rp="What flag indicates small model?"
+               . ./myread
+               tans="$ans"
+               case "$tans" in
+               none) tans='';
+               esac
+               small="$tans";;
+       *) small='';;
+       esac
+       ;;
+ *)
+       echo "Unrecognized memory models--you may have to edit Makefile.SH" >&4
+       ;;
+ esac
+ $rm -f pdp11.* pdp11
+ : make some quick guesses about what we are up against
+ echo " "
+ $echo $n "Hmm...  $c"
+ echo exit 1 >bsd
+ echo exit 1 >usg
+ echo exit 1 >v7
+ echo exit 1 >osf1
+ echo exit 1 >eunice
+ echo exit 1 >xenix
+ echo exit 1 >venix
+ echo exit 1 >os2
+ d_bsd="$undef"
+ $cat /usr/include/signal.h /usr/include/sys/signal.h >foo 2>/dev/null
+ if test -f /osf_boot || $contains 'OSF/1' /usr/include/ctype.h >/dev/null 2>&1
+ then
+       echo "Looks kind of like an OSF/1 system, but we'll see..."
+       echo exit 0 >osf1
+ elif test `echo abc | tr a-z A-Z` = Abc ; then
+       xxx=`./loc addbib blurfl $pth`
+       if $test -f $xxx; then
+       echo "Looks kind of like a USG system with BSD features, but we'll see..."
+               echo exit 0 >bsd
+               echo exit 0 >usg
+       else
+               if $contains SIGTSTP foo >/dev/null 2>&1 ; then
+                       echo "Looks kind of like an extended USG system, but we'll see..."
+               else
+                       echo "Looks kind of like a USG system, but we'll see..."
+               fi
+               echo exit 0 >usg
+       fi
+ elif $contains SIGTSTP foo >/dev/null 2>&1 ; then
+       echo "Looks kind of like a BSD system, but we'll see..."
+       d_bsd="$define"
+       echo exit 0 >bsd
+ else
+       echo "Looks kind of like a Version 7 system, but we'll see..."
+       echo exit 0 >v7
+ fi
+ case "$eunicefix" in
+ *unixtovms*)
+       $cat <<'EOI'
+ There is, however, a strange, musty smell in the air that reminds me of
+ something...hmm...yes...I've got it...there's a VMS nearby, or I'm a Blit.
+ EOI
+       echo exit 0 >eunice
+       d_eunice="$define"
+ : it so happens the Eunice I know will not run shell scripts in Unix format
+       ;;
+ *)
+       echo " "
+       echo "Congratulations.  You aren't running Eunice."
+       d_eunice="$undef"
+       ;;
+ esac
+ : Detect OS2.  The p_ variable is set above in the Head.U unit.
+ case "$p_" in
+ :) ;;
+ *)
+       $cat <<'EOI'
+ I have the feeling something is not exactly right, however...don't tell me...
+ lemme think...does HAL ring a bell?...no, of course, you're only running OS/2!
+ EOI
+       echo exit 0 >os2
+       ;;
+ esac
+ if test -f /xenix; then
+       echo "Actually, this looks more like a XENIX system..."
+       echo exit 0 >xenix
+       d_xenix="$define"
+ else
+       echo " "
+       echo "It's not Xenix..."
+       d_xenix="$undef"
+ fi
+ chmod +x xenix
+ $eunicefix xenix
+ if test -f /venix; then
+       echo "Actually, this looks more like a VENIX system..."
+       echo exit 0 >venix
+ else
+       echo " "
+       if ./xenix; then
+               : null
+       else
+               echo "Nor is it Venix..."
+       fi
+ fi
+ chmod +x bsd usg v7 osf1 eunice xenix venix os2
+ $eunicefix bsd usg v7 osf1 eunice xenix venix os2
+ $rm -f foo
+ : see if we need a special compiler
+ echo " "
+ if ./usg; then
+       case "$cc" in
+       '') case "$Mcc" in
+               /*) dflt='Mcc';;
+               *) case "$large" in
+                       -M*) dflt='cc';;
+                       *)      if $contains '\-M' $sysman/cc.1 >/dev/null 2>&1 ; then
+                                       if $contains '\-M' $sysman/cpp.1 >/dev/null 2>&1; then
+                                               dflt='cc'
+                                       else
+                                               dflt='cc -M'
+                                       fi
+                               else
+                                       dflt='cc'
+                               fi;;
+                       esac;;
+               esac;;
+       *)  dflt="$cc";;
+       esac
+       case "$dflt" in
+       *M*)    $cat <<'EOM'
+ On some older systems the default C compiler will not resolve multiple global
+ references that happen to have the same name.  On some such systems the "Mcc"
+ command may be used to force these to be resolved.  On other systems a "cc -M"
+ command is required.  (Note that the -M flag on other systems indicates a
+ memory model to use!) If you have the Gnu C compiler, you might wish to use
+ that instead.
+ EOM
+       ;;
+       esac
+       rp="Use which C compiler?"
+       . ./myread
+       cc="$ans"
+ else
+       case "$cc" in
+       '') dflt=cc;;
+       *) dflt="$cc";;
+       esac
+       rp="Use which C compiler?"
+       . ./myread
+       cc="$ans"
+ fi
+ : Look for a hint-file generated 'call-back-unit'.  Now that the
+ : user has specified the compiler, we may need to set or change some
+ : other defaults.
+ if $test -f cc.cbu; then
+     . ./cc.cbu
+ fi
+ echo " "
+ echo "Checking for GNU cc in disguise and/or its version number..." >&4
+ $cat >gccvers.c <<EOM
+ #include <stdio.h>
+ int main() {
+ #ifdef __GNUC__
+ #ifdef __VERSION__
+       printf("%s\n", __VERSION__);
+ #else
+       printf("%s\n", "1");
+ #endif
+ #endif
+       exit(0);
+ }
+ EOM
+ if $cc -o gccvers gccvers.c; then
+       gccversion=`./gccvers`
+       case "$gccversion" in
+       '') echo "You are not using GNU cc." ;;
+       *)  echo "You are using GNU cc $gccversion." ;;
+       esac
+ else
+       echo " "
+       echo "*** WHOA THERE!!! ***" >&4
+       echo "    Your C compiler \"$cc\" doesn't seem to be working!" >&4
+       case "$knowitall" in
+       '')
+       echo "    You'd better start hunting for one and let me know about it." >&4
+               exit 1
+               ;;
+       esac
+ fi
+ $rm -f gccvers*
+ case "$gccversion" in
+ 1*) cpp=`./loc gcc-cpp $cpp $pth` ;;
+ esac
  cat <<EOM
  
  Perl can be built to take advantage of explicit 64-bit interfaces,
@@@ -2645,22 -2983,23 +2983,23 @@@ case "$use64bits" i
  : user has specified that a 64 bit perl is to be built,
  : we may need to set or change some other defaults.
        if $test -f use64bits.cbu; then
+               echo "Your platform has some specific hints for 64-bit builds, using them..."
                . ./use64bits.cbu
-       fi
-       case "$osname" in
-       aix|dec_osf|hpux|irix|solaris|unicos)
-               # Known 64-bit capable platforms.
-               ;;
-       *)
-               cat >&4 <<EOM
- $osname is not known to support 64-bit interfaces.
- Please let perlbug@perl.com know how to do that.
- Cannot continue, aborting.
+       else
+               $cat <<EOM
+ (Your platform doesn't have any specific hints for 64-bit builds.
+  This is probably okay, especially if your system is a true 64-bit system.)
  EOM
-               exit 1
-               ;;
-       esac
+               case "$gccversion" in
+               '')     ;;
+               *)      $cat <<EOM
+ But since you seem to be using gcc,
+ I will now add -DUSE_LONG_LONG to the compilation flags.
+ EOM
+                       ccflags="$ccflags -DUSE_LONG_LONG"
+                       ;;
+               esac
+       fi
        ;;
  esac
  
        installarchlib="$archlibexp"
  fi
  
- : make some quick guesses about what we are up against
- echo " "
- $echo $n "Hmm...  $c"
- echo exit 1 >bsd
- echo exit 1 >usg
- echo exit 1 >v7
- echo exit 1 >osf1
- echo exit 1 >eunice
- echo exit 1 >xenix
- echo exit 1 >venix
- echo exit 1 >os2
- d_bsd="$undef"
- $cat /usr/include/signal.h /usr/include/sys/signal.h >foo 2>/dev/null
- if test -f /osf_boot || $contains 'OSF/1' /usr/include/ctype.h >/dev/null 2>&1
- then
-       echo "Looks kind of like an OSF/1 system, but we'll see..."
-       echo exit 0 >osf1
- elif test `echo abc | tr a-z A-Z` = Abc ; then
-       xxx=`./loc addbib blurfl $pth`
-       if $test -f $xxx; then
-       echo "Looks kind of like a USG system with BSD features, but we'll see..."
-               echo exit 0 >bsd
-               echo exit 0 >usg
-       else
-               if $contains SIGTSTP foo >/dev/null 2>&1 ; then
-                       echo "Looks kind of like an extended USG system, but we'll see..."
-               else
-                       echo "Looks kind of like a USG system, but we'll see..."
-               fi
-               echo exit 0 >usg
-       fi
- elif $contains SIGTSTP foo >/dev/null 2>&1 ; then
-       echo "Looks kind of like a BSD system, but we'll see..."
-       d_bsd="$define"
-       echo exit 0 >bsd
- else
-       echo "Looks kind of like a Version 7 system, but we'll see..."
-       echo exit 0 >v7
- fi
- case "$eunicefix" in
- *unixtovms*)
-       $cat <<'EOI'
- There is, however, a strange, musty smell in the air that reminds me of
- something...hmm...yes...I've got it...there's a VMS nearby, or I'm a Blit.
- EOI
-       echo exit 0 >eunice
-       d_eunice="$define"
- : it so happens the Eunice I know will not run shell scripts in Unix format
-       ;;
- *)
-       echo " "
-       echo "Congratulations.  You aren't running Eunice."
-       d_eunice="$undef"
-       ;;
- esac
- : Detect OS2.  The p_ variable is set above in the Head.U unit.
- case "$p_" in
- :) ;;
- *)
-       $cat <<'EOI'
- I have the feeling something is not exactly right, however...don't tell me...
- lemme think...does HAL ring a bell?...no, of course, you're only running OS/2!
- EOI
-       echo exit 0 >os2
-       ;;
- esac
- if test -f /xenix; then
-       echo "Actually, this looks more like a XENIX system..."
-       echo exit 0 >xenix
-       d_xenix="$define"
- else
-       echo " "
-       echo "It's not Xenix..."
-       d_xenix="$undef"
- fi
- chmod +x xenix
- $eunicefix xenix
- if test -f /venix; then
-       echo "Actually, this looks more like a VENIX system..."
-       echo exit 0 >venix
- else
-       echo " "
-       if ./xenix; then
-               : null
-       else
-               echo "Nor is it Venix..."
-       fi
- fi
- chmod +x bsd usg v7 osf1 eunice xenix venix os2
- $eunicefix bsd usg v7 osf1 eunice xenix venix os2
- $rm -f foo
+ : Binary compatibility with 5.005 is not possible for builds
+ : with advanced features
+ case "$usethreads$usemultiplicity" in
+ *define*) bincompat5005="$undef" ;;
+ *)    $cat <<EOM
+ Perl 5.006 can be compiled for binary compatibility with 5.005.
+ If you decide to do so, you will be able to continue using most
+ of the extensions that were compiled for Perl 5.005.
+ EOM
+       case "$bincompat5005$d_bincompat5005" in
+       *"$undef"*) dflt=n ;;
+       *) dflt=y ;;
+       esac
+       rp='Binary compatibility with Perl 5.005?'
+       . ./myread
+       case "$ans" in
+       y*) val="$define" ;;
+       *)  val="$undef" ;;
+       esac
+       set d_bincompat5005
+       eval $setvar
+       case "$d_bincompat5005" in
+       "$define") bincompat5005="$define" ;;
+       *) bincompat5005="$undef" ;;
+       esac
+       ;;
+ esac
  
  : see if setuid scripts can be secure
  $cat <<EOM
  set d_dosuid
  eval $setvar
  
- : determine where manual pages are on this system
- echo " "
- case "$sysman" in
- '') 
-       syspath='/usr/man/man1 /usr/man/mann /usr/man/manl /usr/man/local/man1'
-       syspath="$syspath /usr/man/u_man/man1 /usr/share/man/man1"
-       syspath="$syspath /usr/catman/u_man/man1 /usr/man/l_man/man1"
-       syspath="$syspath /usr/local/man/u_man/man1 /usr/local/man/l_man/man1"
-       syspath="$syspath /usr/man/man.L /local/man/man1 /usr/local/man/man1"
-       sysman=`./loc . /usr/man/man1 $syspath`
-       ;;
- esac
- if $test -d "$sysman"; then
-       echo "System manual is in $sysman." >&4
- else
-       echo "Could not find manual pages in source form." >&4
- fi
- : see what memory models we can support
- case "$models" in
- '')
-       $cat >pdp11.c <<'EOP'
- int main() {
- #ifdef pdp11
-       exit(0);
- #else
-       exit(1);
- #endif
- }
- EOP
-       ( cc -o pdp11 pdp11.c ) >/dev/null 2>&1
-       if $test -f pdp11 && ./pdp11 2>/dev/null; then
-               dflt='unsplit split'
-       else
-               tans=`./loc . X /lib/small /lib/large /usr/lib/small /usr/lib/large /lib/medium /usr/lib/medium /lib/huge`
-               case "$tans" in
-               X) dflt='none';;
-               *) if $test -d /lib/small || $test -d /usr/lib/small; then
-                               dflt='small'
-                       else
-                               dflt=''
-                       fi
-                       if $test -d /lib/medium || $test -d /usr/lib/medium; then
-                               dflt="$dflt medium"
-                       fi
-                       if $test -d /lib/large || $test -d /usr/lib/large; then
-                               dflt="$dflt large"
-                       fi
-                       if $test -d /lib/huge || $test -d /usr/lib/huge; then
-                               dflt="$dflt huge"
-                       fi
-               esac
-       fi;;
- *) dflt="$models";;
- esac
- $cat <<EOM
-  
- Some systems have different model sizes.  On most systems they are called
- small, medium, large, and huge.  On the PDP11 they are called unsplit and
- split.  If your system doesn't support different memory models, say "none".
- If you wish to force everything to one memory model, say "none" here and
- put the appropriate flags later when it asks you for other cc and ld flags.
- Venix systems may wish to put "none" and let the compiler figure things out.
- (In the following question multiple model names should be space separated.)
- The default for most systems is "none".
- EOM
- rp="Which memory models are supported?"
- . ./myread
- models="$ans"
- case "$models" in
- none)
-       small=''
-       medium=''
-       large=''
-       huge=''
-       unsplit=''
-       split=''
-       ;;
- *split)
-       case "$split" in
-       '') if $contains '\-i' $sysman/ld.1 >/dev/null 2>&1 || \
-                        $contains '\-i' $sysman/cc.1 >/dev/null 2>&1; then
-                       dflt='-i'
-               else
-                       dflt='none'
-               fi;;
-       *) dflt="$split";;
-       esac
-       rp="What flag indicates separate I and D space?"
-       . ./myread
-       tans="$ans"
-       case "$tans" in
-       none) tans='';;
-       esac
-       split="$tans"
-       unsplit='';;
- *large*|*small*|*medium*|*huge*)
-       case "$models" in
-       *large*)
-               case "$large" in
-               '') dflt='-Ml';;
-               *) dflt="$large";;
-               esac
-       rp="What flag indicates large model?"
-       . ./myread
-       tans="$ans"
-       case "$tans" in
-       none) tans='';
-       esac
-       large="$tans";;
-       *) large='';;
-       esac
-       case "$models" in
-       *huge*) case "$huge" in
-               '') dflt='-Mh';;
-               *) dflt="$huge";;
-               esac
-               rp="What flag indicates huge model?"
-               . ./myread
-               tans="$ans"
-               case "$tans" in
-               none) tans='';
-               esac
-               huge="$tans";;
-       *) huge="$large";;
-       esac
-       case "$models" in
-       *medium*) case "$medium" in
-               '') dflt='-Mm';;
-               *) dflt="$medium";;
-               esac
-               rp="What flag indicates medium model?"
-               . ./myread
-               tans="$ans"
-               case "$tans" in
-               none) tans='';
-               esac
-               medium="$tans";;
-       *) medium="$large";;
-       esac
-       case "$models" in
-       *small*) case "$small" in
-               '') dflt='none';;
-               *) dflt="$small";;
-               esac
-               rp="What flag indicates small model?"
-               . ./myread
-               tans="$ans"
-               case "$tans" in
-               none) tans='';
-               esac
-               small="$tans";;
-       *) small='';;
-       esac
-       ;;
- *)
-       echo "Unrecognized memory models--you may have to edit Makefile.SH" >&4
-       ;;
- esac
- $rm -f pdp11.* pdp11
- : see if we need a special compiler
- echo " "
- if ./usg; then
-       case "$cc" in
-       '') case "$Mcc" in
-               /*) dflt='Mcc';;
-               *) case "$large" in
-                       -M*) dflt='cc';;
-                       *)      if $contains '\-M' $sysman/cc.1 >/dev/null 2>&1 ; then
-                                       if $contains '\-M' $sysman/cpp.1 >/dev/null 2>&1; then
-                                               dflt='cc'
-                                       else
-                                               dflt='cc -M'
-                                       fi
-                               else
-                                       dflt='cc'
-                               fi;;
-                       esac;;
-               esac;;
-       *)  dflt="$cc";;
-       esac
-       case "$dflt" in
-       *M*)    $cat <<'EOM'
- On some older systems the default C compiler will not resolve multiple global
- references that happen to have the same name.  On some such systems the "Mcc"
- command may be used to force these to be resolved.  On other systems a "cc -M"
- command is required.  (Note that the -M flag on other systems indicates a
- memory model to use!) If you have the Gnu C compiler, you might wish to use
- that instead.
- EOM
-       ;;
-       esac
-       rp="Use which C compiler?"
-       . ./myread
-       cc="$ans"
- else
-       case "$cc" in
-       '') dflt=cc;;
-       *) dflt="$cc";;
-       esac
-       rp="Use which C compiler?"
-       . ./myread
-       cc="$ans"
- fi
- : Look for a hint-file generated 'call-back-unit'.  Now that the
- : user has specified the compiler, we may need to set or change some
- : other defaults.
- if $test -f cc.cbu; then
-     . ./cc.cbu
- fi
- echo " "
- echo "Checking for GNU cc in disguise and/or its version number..." >&4
- $cat >gccvers.c <<EOM
- #include <stdio.h>
- int main() {
- #ifdef __GNUC__
- #ifdef __VERSION__
-       printf("%s\n", __VERSION__);
- #else
-       printf("%s\n", "1");
- #endif
- #endif
-       exit(0);
- }
- EOM
- if $cc -o gccvers gccvers.c; then
-       gccversion=`./gccvers`
-       case "$gccversion" in
-       '') echo "You are not using GNU cc." ;;
-       *)  echo "You are using GNU cc $gccversion." ;;
-       esac
- else
-       echo " "
-       echo "*** WHOA THERE!!! ***" >&4
-       echo "    Your C compiler \"$cc\" doesn't seem to be working!" >&4
-       case "$knowitall" in
-       '')
-       echo "    You'd better start hunting for one and let me know about it." >&4
-               exit 1
-               ;;
-       esac
- fi
- $rm -f gccvers*
- case "$gccversion" in
- 1*) cpp=`./loc gcc-cpp $cpp $pth` ;;
- esac
  : What should the include directory be ?
  echo " "
  $echo $n "Hmm...  $c"
@@@ -4476,7 -4503,6 +4503,7 @@@ exit 
  EOF
  chmod +x findhdr
  
 +
  : define an alternate in-header-list? function
  inhdr='echo " "; td=$define; tu=$undef; yyy=$@;
  cont=true; xxf="echo \"<\$1> found.\" >&4";
@@@ -13072,6 -13098,7 +13099,7 @@@ awk='$awk
  baserev='$baserev'
  bash='$bash'
  bin='$bin'
+ bincompat5005='$bincompat5005'
  binexp='$binexp'
  bison='$bison'
  byacc='$byacc'
@@@ -13116,6 -13143,7 +13144,7 @@@ d_archlib='$d_archlib
  d_attribut='$d_attribut'
  d_bcmp='$d_bcmp'
  d_bcopy='$d_bcopy'
+ d_bincompat5005='$d_bincompat5005'
  d_bsd='$d_bsd'
  d_bsdgetpgrp='$d_bsdgetpgrp'
  d_bsdsetpgrp='$d_bsdsetpgrp'
diff --combined Makefile.SH
@@@ -303,7 -303,7 +303,7 @@@ ext.libs: $(static_ext
  # Load up custom Makefile.SH fragment for shared loading and executables:
  case "$osname" in
  cygwin*)
 -      Makefile_s="cygwin32/Makefile.SHs"
 +      Makefile_s="cygwin/Makefile.SHs"
        ;;
  *)
        Makefile_s="$osname/Makefile.SHs"
@@@ -332,7 -332,7 +332,7 @@@ $(LIBPERL_NONSHR): perl$(OBJ_EXT) $(obj
        $(AR) rcu $(LIBPERL_NONSHR) perl$(OBJ_EXT) $(obj)
  
  $(MINIPERL_NONSHR): $(LIBPERL_NONSHR) miniperlmain$(OBJ_EXT)
-       $(CC) -o $(MINIPERL_NONSHR) miniperlmain$(OBJ_EXT) $(LIBPERL_NONSHR) $(LIBS)
+       $(CC) $(LDFLAGS) -o $(MINIPERL_NONSHR) miniperlmain$(OBJ_EXT) $(LIBPERL_NONSHR) $(LIBS)
  
  MINIPERLEXP           = $(MINIPERL_NONSHR)
  
@@@ -357,16 -357,6 +357,16 @@@ perl.exp: $(MINIPERLEXP) makedef.pl con
  
  !NO!SUBS!
        ;;
 +os2)
 +      $spitshell >>Makefile <<'!NO!SUBS!'
 +MINIPERLEXP           = miniperl
 +
 +perl5.def: $(MINIPERLEXP) makedef.pl config.sh $(SYM) $(SYMH) miniperl.map
 +      ./$(MINIPERLEXP) makedef.pl PLATFORM=os2 -DPERL_DLL=$(PERL_DLL) > perl.exp.tmp
 +      sh mv-if-diff perl.exp.tmp perl5.def
 +
 +!NO!SUBS!
 +      ;;
  esac
  
  if test -r $Makefile_s ; then
diff --combined embed.pl
+++ b/embed.pl
@@@ -1572,10 -1572,10 +1572,10 @@@ p    |OP*    |scalar         |OP* 
  p     |OP*    |scalarkids     |OP* o
  p     |OP*    |scalarseq      |OP* o
  p     |OP*    |scalarvoid     |OP* o
- p     |UV     |scan_bin       |char* start|I32 len|I32* retlen
- p     |UV     |scan_hex       |char* start|I32 len|I32* retlen
+ p     |NV     |scan_bin       |char* start|I32 len|I32* retlen
+ p     |NV     |scan_hex       |char* start|I32 len|I32* retlen
  p     |char*  |scan_num       |char* s
- p     |UV     |scan_oct       |char* start|I32 len|I32* retlen
+ p     |NV     |scan_oct       |char* start|I32 len|I32* retlen
  p     |OP*    |scope          |OP* o
  p     |char*  |screaminstr    |SV* bigsv|SV* littlesv|I32 start_shift \
                                |I32 end_shift|I32 *state|I32 last
@@@ -1932,10 -1932,9 +1932,10 @@@ s     |char*|regwhite |char *|char 
  s     |char*|nextchar
  s     |regnode*|dumpuntil     |regnode *start|regnode *node \
                                |regnode *last|SV* sv|I32 l
 -s     |void   |scan_commit    |scan_data_t *data
 +s     |void   |scan_commit    |struct scan_data_t *data
  s     |I32    |study_chunk    |regnode **scanp|I32 *deltap \
 -                              |regnode *last|scan_data_t *data|U32 flags
 +                              |regnode *last|struct scan_data_t *data \
 +                              |U32 flags
  s     |I32    |add_data       |I32 n|char *s
  rs    |void|re_croak2 |const char* pat1|const char* pat2|...
  s     |I32    |regpposixcc    |I32 value
diff --combined perl.h
--- 1/perl.h
--- 2/perl.h
+++ b/perl.h
@@@ -23,9 -23,6 +23,9 @@@
  #define VOIDUSED 1
  #include "config.h"
  
 +/* See L<perlguts/"The Perl API"> for detailed notes on
 + * PERL_IMPLICIT_CONTEXT and PERL_IMPLICIT_SYS */
 +
  /* XXXXXX testing threads via implicit pointer */
  #ifdef USE_THREADS
  #  ifndef PERL_IMPLICIT_CONTEXT
@@@ -507,12 -504,10 +507,10 @@@ register struct op *Perl_op asm(stringi
  
  #ifdef MYMALLOC
  #  ifdef PERL_POLLUTE_MALLOC
- #   ifndef PERL_EXTMALLOC_DEF
  #    define Perl_malloc               malloc
  #    define Perl_calloc               calloc
  #    define Perl_realloc      realloc
  #    define Perl_mfree                free
- #   endif
  #  else
  #    define EMBEDMYMALLOC     /* for compatibility */
  #  endif
@@@ -1027,6 -1022,8 +1025,8 @@@ Free_t   Perl_mfree (Malloc_t where)
  #    define UV_MAX PERL_UQUAD_MAX
  #    define UV_MIN PERL_UQUAD_MIN
  #  endif
+ #  define IV_SIZEOF 8
+ #  define UV_SIZEOF 8
  #else
     typedef          long               IV;
     typedef        unsigned long      UV;
  #    define UV_MAX PERL_ULONG_MAX
  #    define UV_MIN PERL_ULONG_MIN
  #  endif
+ #  define UV_SIZEOF LONGSIZE
+ #  define IV_SIZEOF LONGSIZE
  #endif
  
  #ifdef USE_LONG_DOUBLE
@@@ -1445,10 -1444,6 +1447,10 @@@ typedef union any ANY
  #   endif
  #endif
  
 +#if defined(OS2)
 +#  include "iperlsys.h"
 +#endif
 +
  #if defined(__OPEN_VM)
  # include "vmesa/vmesaish.h"
  #endif
@@@ -1648,7 -1643,7 +1650,7 @@@ typedef pthread_key_t   perl_key
  #   endif
  #endif
  
 -#if defined(CYGWIN32)
 +#if defined(CYGWIN)
  /* USEMYBINMODE
   *   This symbol, if defined, indicates that the program should
   *   use the routine my_binmode(FILE *fp, char iotype) to insure
   */
  #  define USEMYBINMODE / **/
  #  define my_binmode(fp, iotype) \
 -            (PerlLIO_setmode(PerlIO_fileno(fp), O_BINARY) != -1 ? TRUE : NULL)
 +            (PerlLIO_setmode(PerlIO_fileno(fp), O_BINARY) != -1 ? TRUE : FALSE)
  #endif
  
  #ifdef UNION_ANY_DEFINITION
@@@ -1678,15 -1673,25 +1680,15 @@@ union any 
  #define ARGSproto
  #endif /* USE_THREADS */
  
 -#if defined(CYGWIN32)
 -/* USEMYBINMODE
 - *   This symbol, if defined, indicates that the program should
 - *   use the routine my_binmode(FILE *fp, char iotype) to insure
 - *   that a file is in "binary" mode -- that is, that no translation
 - *   of bytes occurs on read or write operations.
 - */
 -#define USEMYBINMODE / **/
 -#define my_binmode(fp, iotype) \
 -        (PerlLIO_setmode(PerlIO_fileno(fp), O_BINARY) != -1 ? TRUE : FALSE)
 -#endif
 -
  typedef I32 (*filter_t) (pTHXo_ int, SV *, int);
  
  #define FILTER_READ(idx, sv, len)  filter_read(idx, sv, len)
  #define FILTER_DATA(idx)         (AvARRAY(PL_rsfp_filters)[idx])
  #define FILTER_ISREADER(idx)     (idx >= AvFILLp(PL_rsfp_filters))
  
 -#include "iperlsys.h"
 +#if !defined(OS2)
 +#  include "iperlsys.h"
 +#endif
  #include "regexp.h"
  #include "sv.h"
  #include "util.h"
@@@ -1727,7 -1732,25 +1729,7 @@@ struct _sublex_info 
  
  typedef struct magic_state MGS;       /* struct magic_state defined in mg.c */
  
 -/* Length of a variant. */
 -
 -typedef struct {
 -    I32 len_min;
 -    I32 len_delta;
 -    I32 pos_min;
 -    I32 pos_delta;
 -    SV *last_found;
 -    I32 last_end;                     /* min value, <0 unless valid. */
 -    I32 last_start_min;
 -    I32 last_start_max;
 -    SV **longest;                     /* Either &l_fixed, or &l_float. */
 -    SV *longest_fixed;
 -    I32 offset_fixed;
 -    SV *longest_float;
 -    I32 offset_float_min;
 -    I32 offset_float_max;
 -    I32 flags;
 -} scan_data_t;
 +struct scan_data_t;           /* Used in S_* functions in regcomp.c */
  
  typedef I32 CHECKPOINT;
  
@@@ -2473,7 -2496,7 +2475,7 @@@ struct perl_vars 
  EXT struct perl_vars PL_Vars;
  EXT struct perl_vars *PL_VarsPtr INIT(&PL_Vars);
  #else /* PERL_CORE */
 -#if !defined(__GNUC__) || !(defined(WIN32) || defined(CYGWIN32))
 +#if !defined(__GNUC__) || !(defined(WIN32) || defined(CYGWIN))
  EXT
  #endif /* WIN32 */
  struct perl_vars *PL_VarsPtr;
diff --combined pod/perldelta.pod
@@@ -37,15 -37,11 +37,15 @@@ specified via MakeMaker
  This new build option provides a set of macros for all API functions
  such that an implicit interpreter/thread context argument is passed to
  every API function.  As a result of this, something like C<sv_setsv(foo,bar)>
 -amounts to a macro invocation that actually translates to
 +amounts to a macro invocation that actually translates to something like
  C<Perl_sv_setsv(my_perl,foo,bar)>.  While this is generally expected
  to not have any significant source compatibility issues, the difference
  between a macro and a real function call will need to be considered.
  
 +This means that there B<is> a source compatibility issue as a result of
 +this if your extensions attempt to use pointers to any of the Perl API
 +functions.
 +
  Note that the above issue is not relevant to the default build of
  Perl, whose interfaces continue to match those of prior versions
  (but subject to the other options described here).
@@@ -54,9 -50,6 +54,9 @@@ For testing purposes, the 5.005_58 rele
  PERL_IMPLICIT_CONTEXT whenever Perl is built with -Dusethreads or
  -Dusemultiplicity.
  
 +See L<perlguts/"The Perl API"> for detailed information on the
 +ramifications of building Perl using this option.
 +
  =item C<PERL_POLLUTE_MALLOC>
  
  Enabling Perl's malloc in release 5.005 and earlier caused
@@@ -141,13 -134,6 +141,6 @@@ C<oct()>
      $answer = 0b101010;
      printf "The answer is: %b\n", oct("0b101010");
  
- =head2 Literal hexadecimal, octal, and binary numbers must fit within native sizes
- The warning that used to be produced when encountering hexadecimal, octal,
- and binary literals that are too large to be represented as native integers
- has now been promoted to a fatal error.  Literal decimal numbers are
- unaffected.
  =head2 syswrite() ease-of-use
  
  The length argument of C<syswrite()> is now optional.
diff --combined pod/perldiag.pod
@@@ -18,11 -18,8 +18,11 @@@ desperation)
  Optional warnings are enabled by using the B<-w> switch.  Warnings may
  be captured by setting C<$SIG{__WARN__}> to a reference to a routine that
  will be called on each warning instead of printing it.  See L<perlvar>.
 +
  Trappable errors may be trapped using the eval operator.  See
 -L<perlfunc/eval>.
 +L<perlfunc/eval>.  In almost all cases, warnings may be selectively
 +disabled or promoted to fatal errors using the C<warning> pragma.
 +See L<warning>.
  
  Some of these messages are generic.  Spots that vary are denoted with a %s,
  just as in a printf format.  Note that some messages start with a %s!
@@@ -472,9 -469,9 +472,9 @@@ likely depends on its correct operation
  
  =item Binary number > 0b11111111111111111111111111111111 non-portable
  
- (W) The binary number you specified is larger than 2**32-1 and therefore
- generally non-portable between systems.  See L<perlport> for more on
- portability concerns.
+ (W) The binary number you specified is larger than 2**32-1
+ (4294967295) and therefore non-portable between systems.  See
+ L<perlport> for more on portability concerns.
  
  =item bind() on closed fd
  
@@@ -1350,8 -1347,7 +1350,8 @@@ the name
  
  =item Format %s redefined
  
 -(W) You redefined a format.  To suppress this warning, say
 +(W) You redefined a format, perhaps accidentally.  To suppress this warning,
 +say
  
      {
        no warning;
@@@ -1426,9 -1422,9 +1426,9 @@@ is now heavily deprecated
  
  =item Hexadecimal number > 0xffffffff non-portable
  
- (W) The hexadecimal number you specified is larger than 2**32-1 and
- therefore non-portable between systems.  See L<perlport> for more on
- portability concerns.
+ (W) The hexadecimal number you specified is larger than 2**32-1
+ (4294967295) and therefore non-portable between systems.  See
+ L<perlport> for more on portability concerns.
  
  =item Identifier too long
  
@@@ -1544,18 -1540,15 +1544,15 @@@ known value, using trustworthy data.  S
  
  =item Integer overflow in %s number
  
- (F,X) The hexadecimal, octal or binary number you have specified
- either as a literal in your code or as a scalar is too big for your
- architecture. On a 32-bit architecture the largest literal hex, octal
- or binary number representable without overflow is 0xFFFFFFFF,
- 037777777777, or 0b11111111111111111111111111111111 respectively.
- Note that Perl transparently promotes decimal literals to a floating
- point representation internally--subject to loss of precision errors
- in subsequent operations--so this limit usually doesn't apply to
- decimal literals.  If the overflow is in a literal of your code, the
- error is untrappable (there is no way the code could work safely in
- your system), if the overflow happens in hex() or oct() the error is
- trappable.
+ (W) The hexadecimal, octal or binary number you have specified either
+ as a literal in your code or as a scalar is too big for your
+ architecture, and has been converted to a floating point number.  On a
+ 32-bit architecture the largest hexadecimal, octal or binary number
+ representable without overflow is 0xFFFFFFFF, 037777777777, or
+ 0b11111111111111111111111111111111 respectively.  Note that Perl
+ transparently promotes all numbers to a floating point representation
+ internally--subject to loss of precision errors in subsequent
+ operations.
  
  =item Internal inconsistency in tracking vforks
  
@@@ -1982,10 -1975,12 +1979,10 @@@ try using scientific notation (e.g. "1e
  
  =item Octal number > 037777777777 non-portable
  
- (W) The octal number you specified is larger than 2**32-1 and
- therefore non-portable between systems.  See L<perlport> for more on
- portability concerns.
+ (W) The octal number you specified is larger than 2**32-1 (4294967295)
+ and therefore non-portable between systems.  See L<perlport> for more
+ on portability concerns.
  
 -See also L<perlport> for writing portable code.
 -
  =item Odd number of elements in hash assignment
  
  (S) You specified an odd number of elements to initialize a hash, which
@@@ -2619,8 -2614,7 +2616,8 @@@ may break this
  
  =item Subroutine %s redefined
  
 -(W) You redefined a subroutine.  To suppress this warning, say
 +(W) You redefined a subroutine, perhaps accidentally.  To suppress this
 +warning, say
  
      {
        no warning;
diff --combined proto.h
+++ b/proto.h
@@@ -536,10 -536,10 +536,10 @@@ VIRTUAL OP*     Perl_scalar(pTHX_ OP* o)
  VIRTUAL OP*   Perl_scalarkids(pTHX_ OP* o);
  VIRTUAL OP*   Perl_scalarseq(pTHX_ OP* o);
  VIRTUAL OP*   Perl_scalarvoid(pTHX_ OP* o);
- VIRTUAL UV    Perl_scan_bin(pTHX_ char* start, I32 len, I32* retlen);
- VIRTUAL UV    Perl_scan_hex(pTHX_ char* start, I32 len, I32* retlen);
+ VIRTUAL NV    Perl_scan_bin(pTHX_ char* start, I32 len, I32* retlen);
+ VIRTUAL NV    Perl_scan_hex(pTHX_ char* start, I32 len, I32* retlen);
  VIRTUAL char* Perl_scan_num(pTHX_ char* s);
- VIRTUAL UV    Perl_scan_oct(pTHX_ char* start, I32 len, I32* retlen);
+ VIRTUAL NV    Perl_scan_oct(pTHX_ char* start, I32 len, I32* retlen);
  VIRTUAL OP*   Perl_scope(pTHX_ OP* o);
  VIRTUAL char* Perl_screaminstr(pTHX_ SV* bigsv, SV* littlesv, I32 start_shift, I32 end_shift, I32 *state, I32 last);
  #if !defined(VMS)
@@@ -868,8 -868,8 +868,8 @@@ STATIC void        S_regtail(pTHX_ regnode *, 
  STATIC char*  S_regwhite(pTHX_ char *, char *);
  STATIC char*  S_nextchar(pTHX);
  STATIC regnode*       S_dumpuntil(pTHX_ regnode *start, regnode *node, regnode *last, SV* sv, I32 l);
 -STATIC void   S_scan_commit(pTHX_ scan_data_t *data);
 -STATIC I32    S_study_chunk(pTHX_ regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32 flags);
 +STATIC void   S_scan_commit(pTHX_ struct scan_data_t *data);
 +STATIC I32    S_study_chunk(pTHX_ regnode **scanp, I32 *deltap, regnode *last, struct scan_data_t *data, U32 flags);
  STATIC I32    S_add_data(pTHX_ I32 n, char *s);
  STATIC void   S_re_croak2(pTHX_ const char* pat1, const char* pat2, ...) __attribute__((noreturn));
  STATIC I32    S_regpposixcc(pTHX_ I32 value);
diff --combined regexec.c
+++ b/regexec.c
@@@ -270,33 -270,25 +270,33 @@@ S_cache_re(pTHX_ regexp *prog
  
  /* Assumptions: if ANCH_GPOS, then strpos is anchored. XXXX Check GPOS logic */
  
 -/* If SCREAM, then sv should be compatible with strpos and strend.
 +/* If SCREAM, then SvPVX(sv) should be compatible with strpos and strend.
     Otherwise, only SvCUR(sv) is used to get strbeg. */
  
  /* XXXX We assume that strpos is strbeg unless sv. */
  
 +/* A failure to find a constant substring means that there is no need to make
 +   an expensive call to REx engine, thus we celebrate a failure.  Similarly,
 +   finding a substring too deep into the string means that less calls to
 +   regtry() should be needed. */
 +
  char *
  Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
                     char *strend, U32 flags, re_scream_pos_data *data)
  {
 -    I32 start_shift;
 +    register I32 start_shift;
      /* Should be nonnegative! */
 -    I32 end_shift;
 -    char *s;
 +    register I32 end_shift;
 +    register char *s;
 +    register SV *check;
      char *t;
      I32 ml_anch;
 +    char *tmp;
 +    register char *other_last = Nullch;
  
      DEBUG_r( if (!PL_colorset) reginitcolors() );
      DEBUG_r(PerlIO_printf(Perl_debug_log,
 -                    "%sGuessing start of match:%s `%s%.60s%s%s' against `%s%.*s%s%s'\n",
 +                    "%sGuessing start of match, REx%s `%s%.60s%s%s' against `%s%.*s%s%s'...\n",
                      PL_colors[4],PL_colors[5],PL_colors[0],
                      prog->precomp,
                      PL_colors[1],
                      (strend - strpos > 60 ? "..." : ""))
        );
  
 -    if (prog->minlen > strend - strpos)
 +    if (prog->minlen > strend - strpos) {
 +      DEBUG_r(PerlIO_printf(Perl_debug_log, "String too short...\n"));
        goto fail;
 -
 -    /* XXXX Move further down? */
 -    start_shift = prog->check_offset_min;     /* okay to underestimate on CC */
 -    /* Should be nonnegative! */
 -    end_shift = prog->minlen - start_shift -
 -      CHR_SVLEN(prog->check_substr) + (SvTAIL(prog->check_substr) != 0);
 -
 -    if (prog->reganch & ROPT_ANCH) {
 +    }
 +    if (prog->reganch & ROPT_ANCH) {  /* Match at beg-of-str or after \n */
        ml_anch = !( (prog->reganch & ROPT_ANCH_SINGLE)
                     || ( (prog->reganch & ROPT_ANCH_BOL)
 -                        && !PL_multiline ) );
 +                        && !PL_multiline ) ); /* Check after \n? */
  
        if ((prog->check_offset_min == prog->check_offset_max) && !ml_anch) {
 -          /* Anchored... */
 +          /* Substring at constant offset from beg-of-str... */
            I32 slen;
  
            if ( !(prog->reganch & ROPT_ANCH_GPOS) /* Checked by the caller */
 -               && (sv && (strpos + SvCUR(sv) != strend)) )
 +               && (sv && (strpos + SvCUR(sv) != strend)) ) {
 +              DEBUG_r(PerlIO_printf(Perl_debug_log, "Not at start...\n"));
                goto fail;
 -
 +          }
            PL_regeol = strend;                 /* Used in HOP() */
 -          s = (char*)HOP((U8*)strpos, prog->check_offset_min);
 +          s = HOPc(strpos, prog->check_offset_min);
            if (SvTAIL(prog->check_substr)) {
                slen = SvCUR(prog->check_substr);       /* >= 1 */
  
 -              if ( strend - s > slen || strend - s < slen - 1 ) {
 -                  s = Nullch;
 -                  goto finish;
 -              }
 -              if ( strend - s == slen && strend[-1] != '\n') {
 -                  s = Nullch;
 -                  goto finish;
 +              if ( strend - s > slen || strend - s < slen - 1 
 +                   || (strend - s == slen && strend[-1] != '\n')) {
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log, "String too long...\n"));
 +                  goto fail_finish;
                }
                /* Now should match s[0..slen-2] */
                slen--;
                if (slen && (*SvPVX(prog->check_substr) != *s
                             || (slen > 1
 -                               && memNE(SvPVX(prog->check_substr), s, slen))))
 -                  s = Nullch;
 +                               && memNE(SvPVX(prog->check_substr), s, slen)))) {
 +                report_neq:
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log, "String not equal...\n"));
 +                  goto fail_finish;
 +              }
            }
            else if (*SvPVX(prog->check_substr) != *s
                     || ((slen = SvCUR(prog->check_substr)) > 1
                         && memNE(SvPVX(prog->check_substr), s, slen)))
 -                  s = Nullch;
 -          else
 -                  s = strpos;
 -          goto finish;
 +              goto report_neq;
 +          goto success_at_start;
        }
 +      /* Match is anchored, but substr is not anchored wrt beg-of-str. */
        s = strpos;
 -      if (!ml_anch && (s + prog->check_offset_max < strend - prog->minlen))
 -          end_shift += strend - s - prog->minlen - prog->check_offset_max;
 +      start_shift = prog->check_offset_min; /* okay to underestimate on CC */
 +      /* Should be nonnegative! */
 +      end_shift = prog->minlen - start_shift -
 +          CHR_SVLEN(prog->check_substr) + (SvTAIL(prog->check_substr) != 0);
 +      if (!ml_anch) {
 +          I32 end = prog->check_offset_max + CHR_SVLEN(prog->check_substr)
 +                                       - (SvTAIL(prog->check_substr) != 0);
 +          I32 eshift = strend - s - end;
 +
 +          if (end_shift < eshift)
 +              end_shift = eshift;
 +      }
      }
 -    else {
 +    else {                            /* Can match at random position */
        ml_anch = 0;
        s = strpos;
 +      start_shift = prog->check_offset_min; /* okay to underestimate on CC */
 +      /* Should be nonnegative! */
 +      end_shift = prog->minlen - start_shift -
 +          CHR_SVLEN(prog->check_substr) + (SvTAIL(prog->check_substr) != 0);
      }
  
 -  restart:
 +#ifdef DEBUGGING      /* 7/99: reports of failure (with the older version) */
      if (end_shift < 0)
 -      end_shift = 0; /* can happen when strend == strpos */
 +      croak("panic: end_shift");
 +#endif
 +
 +    check = prog->check_substr;
 +  restart:
 +    /* Find a possible match in the region s..strend by looking for
 +       the "check" substring in the region corrected by start/end_shift. */
      if (flags & REXEC_SCREAM) {
 -      SV *c = prog->check_substr;
        char *strbeg = SvPVX(sv);       /* XXXX Assume PV_force() on SCREAM! */
        I32 p = -1;                     /* Internal iterator of scream. */
        I32 *pp = data ? data->scream_pos : &p;
  
 -      if (PL_screamfirst[BmRARE(c)] >= 0
 -          || ( BmRARE(c) == '\n'
 -               && (BmPREVIOUS(c) == SvCUR(c) - 1)
 -               && SvTAIL(c) ))
 -          s = screaminstr(sv, prog->check_substr, 
 -                          start_shift + (strpos - strbeg), end_shift, pp, 0);
 +      if (PL_screamfirst[BmRARE(check)] >= 0
 +          || ( BmRARE(check) == '\n'
 +               && (BmPREVIOUS(check) == SvCUR(check) - 1)
 +               && SvTAIL(check) ))
 +          s = screaminstr(sv, check, 
 +                          start_shift + (s - strbeg), end_shift, pp, 0);
        else
 -          s = Nullch;
 +          goto fail_finish;
        if (data)
            *data->scream_olds = s;
      }
      else
        s = fbm_instr((unsigned char*)s + start_shift,
                      (unsigned char*)strend - end_shift,
 -                    prog->check_substr, PL_multiline ? FBMrf_MULTILINE : 0);
 +                    check, PL_multiline ? FBMrf_MULTILINE : 0);
  
      /* Update the count-of-usability, remove useless subpatterns,
        unshift s.  */
 -  finish:
 -    if (!s) {
 -      ++BmUSEFUL(prog->check_substr); /* hooray */
 -      goto fail;                      /* not present */
 +
 +    DEBUG_r(PerlIO_printf(Perl_debug_log, "%s %s substr `%s%.*s%s'%s%s",
 +                        (s ? "Found" : "Did not find"),
 +                        ((check == prog->anchored_substr) ? "anchored" : "floating"),
 +                        PL_colors[0],
 +                        SvCUR(check) - (SvTAIL(check)!=0), SvPVX(check),
 +                        PL_colors[1], (SvTAIL(check) ? "$" : ""),
 +                        (s ? " at offset " : "...\n") ) );
 +
 +    if (!s)
 +      goto fail_finish;
 +
 +    /* Finish the diagnostic message */
 +    DEBUG_r(PerlIO_printf(Perl_debug_log, "%ld...\n", (long)(s - strpos)) );
 +
 +    /* Got a candidate.  Check MBOL anchoring, and the *other* substr.
 +       Start with the other substr.
 +       XXXX no SCREAM optimization yet - and a very coarse implementation
 +       XXXX /ttx+/ results in anchored=`ttx', floating=`x'.  floating will
 +              *always* match.  Probably should be marked during compile...
 +       Probably it is right to do no SCREAM here...
 +     */
 +
 +    if (prog->float_substr && prog->anchored_substr) {
 +      /* Take into account the anchored substring. */
 +      /* XXXX May be hopelessly wrong for UTF... */
 +      if (!other_last)
 +          other_last = strpos - 1;
 +      if (check == prog->float_substr) {
 +              char *last = s - start_shift, *last1, *last2;
 +              char *s1 = s;
 +
 +              tmp = PL_bostr;
 +              t = s - prog->check_offset_max;
 +              if (s - strpos > prog->check_offset_max  /* signed-corrected t > strpos */
 +                  && (!(prog->reganch & ROPT_UTF8)
 +                      || (PL_bostr = strpos, /* Used in regcopmaybe() */
 +                          (t = reghopmaybe_c(s, -(prog->check_offset_max)))
 +                          && t > strpos)))
 +                  ;
 +              else
 +                  t = strpos;
 +              t += prog->anchored_offset;
 +              if (t <= other_last)
 +                  t = other_last + 1;
 +              PL_bostr = tmp;
 +              last2 = last1 = strend - prog->minlen;
 +              if (last < last1)
 +                  last1 = last;
 + /* XXXX It is not documented what units *_offsets are in.  Assume bytes.  */
 +              /* On end-of-str: see comment below. */
 +              s = fbm_instr((unsigned char*)t,
 +                            (unsigned char*)last1 + prog->anchored_offset
 +                               + SvCUR(prog->anchored_substr)
 +                               - (SvTAIL(prog->anchored_substr)!=0),
 +                            prog->anchored_substr, PL_multiline ? FBMrf_MULTILINE : 0);
 +              DEBUG_r(PerlIO_printf(Perl_debug_log, "%s anchored substr `%s%.*s%s'%s",
 +                      (s ? "Found" : "Contradicts"),
 +                      PL_colors[0],
 +                        SvCUR(prog->anchored_substr)
 +                        - (SvTAIL(prog->anchored_substr)!=0),
 +                        SvPVX(prog->anchored_substr),
 +                        PL_colors[1], (SvTAIL(prog->anchored_substr) ? "$" : "")));
 +              if (!s) {
 +                  if (last1 >= last2) {
 +                      DEBUG_r(PerlIO_printf(Perl_debug_log,
 +                                              ", giving up...\n"));
 +                      goto fail_finish;
 +                  }
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log,
 +                      ", trying floating at offset %ld...\n",
 +                      (long)(s1 + 1 - strpos)));
 +                  PL_regeol = strend;                 /* Used in HOP() */
 +                  other_last = last1 + prog->anchored_offset;
 +                  s = HOPc(last, 1);
 +                  goto restart;
 +              }
 +              else {
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log, " at offset %ld...\n",
 +                        (long)(s - strpos)));
 +                  t = s - prog->anchored_offset;
 +                  other_last = s - 1;
 +                  if (t == strpos)
 +                      goto try_at_start;
 +                  s = s1;
 +                  goto try_at_offset;
 +              }
 +      }
 +      else {          /* Take into account the floating substring. */
 +              char *last, *last1;
 +              char *s1 = s;
 +
 +              t = s - start_shift;
 +              last1 = last = strend - prog->minlen + prog->float_min_offset;
 +              if (last - t > prog->float_max_offset)
 +                  last = t + prog->float_max_offset;
 +              s = t + prog->float_min_offset;
 +              if (s <= other_last)
 +                  s = other_last + 1;
 + /* XXXX It is not documented what units *_offsets are in.  Assume bytes.  */
 +              /* fbm_instr() takes into account exact value of end-of-str
 +                 if the check is SvTAIL(ed).  Since false positives are OK,
 +                 and end-of-str is not later than strend we are OK. */
 +              s = fbm_instr((unsigned char*)s,
 +                            (unsigned char*)last + SvCUR(prog->float_substr)
 +                                - (SvTAIL(prog->float_substr)!=0),
 +                            prog->float_substr, PL_multiline ? FBMrf_MULTILINE : 0);
 +              DEBUG_r(PerlIO_printf(Perl_debug_log, "%s floating substr `%s%.*s%s'%s",
 +                      (s ? "Found" : "Contradicts"),
 +                      PL_colors[0],
 +                        SvCUR(prog->float_substr)
 +                        - (SvTAIL(prog->float_substr)!=0),
 +                        SvPVX(prog->float_substr),
 +                        PL_colors[1], (SvTAIL(prog->float_substr) ? "$" : "")));
 +              if (!s) {
 +                  if (last1 == last) {
 +                      DEBUG_r(PerlIO_printf(Perl_debug_log,
 +                                              ", giving up...\n"));
 +                      goto fail_finish;
 +                  }
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log,
 +                      ", trying anchored starting at offset %ld...\n",
 +                      (long)(s1 + 1 - strpos)));
 +                  other_last = last;
 +                  PL_regeol = strend;                 /* Used in HOP() */
 +                  s = HOPc(t, 1);
 +                  goto restart;
 +              }
 +              else {
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log, " at offset %ld...\n",
 +                        (long)(s - strpos)));
 +                  other_last = s - 1;
 +                  if (t == strpos)
 +                      goto try_at_start;
 +                  s = s1;
 +                  goto try_at_offset;
 +              }
 +      }
      }
 -    else if (s - strpos > prog->check_offset_max &&
 -           ((prog->reganch & ROPT_UTF8)
 -            ? ((t = reghopmaybe_c(s, -(prog->check_offset_max)))
 -               && t >= strpos)
 -            : (t = s - prog->check_offset_max) != 0) ) {
 +
 +    t = s - prog->check_offset_max;
 +    tmp = PL_bostr;
 +    if (s - strpos > prog->check_offset_max  /* signed-corrected t > strpos */
 +        && (!(prog->reganch & ROPT_UTF8)
 +          || (PL_bostr = strpos, /* Used in regcopmaybe() */
 +              ((t = reghopmaybe_c(s, -(prog->check_offset_max)))
 +               && t > strpos)))) {
 +      PL_bostr = tmp;
 +      /* Fixed substring is found far enough so that the match
 +         cannot start at strpos. */
 +      try_at_offset:
        if (ml_anch && t[-1] != '\n') {
 -        find_anchor:
 -          while (t < strend - end_shift - prog->minlen) {
 +        find_anchor:          /* Eventually fbm_*() should handle this */
 +          while (t < strend - prog->minlen) {
                if (*t == '\n') {
                    if (t < s - prog->check_offset_min) {
                        s = t + 1;
 +                      DEBUG_r(PerlIO_printf(Perl_debug_log, "Found /%s^%s/m at offset %ld...\n",
 +                          PL_colors[0],PL_colors[1], (long)(s - strpos)));
                        goto set_useful;
                    }
 +                  DEBUG_r(PerlIO_printf(Perl_debug_log, "Found /%s^%s/m, restarting at offset %ld...\n",
 +                      PL_colors[0],PL_colors[1], (long)(t + 1 - strpos)));
                    s = t + 1;
                    goto restart;
                }
                t++;
            }
 -          s = Nullch;
 -          goto finish;
 +          DEBUG_r(PerlIO_printf(Perl_debug_log, "Did not find /%s^%s/m...\n",
 +                      PL_colors[0],PL_colors[1]));
 +          goto fail_finish;
        }
        s = t;
        set_useful:
 -      ++BmUSEFUL(prog->check_substr); /* hooray/2 */
 +      ++BmUSEFUL(prog->check_substr); /* hooray/5 */
      }
      else {
 -      if (ml_anch && sv 
 +      PL_bostr = tmp;
 +      /* The found string does not prohibit matching at beg-of-str
 +         - no optimization of calling REx engine can be performed,
 +         unless it was an MBOL and we are not after MBOL. */
 +      try_at_start:
 +      /* Even in this situation we may use MBOL flag if strpos is offset
 +         wrt the start of the string. */
 +      if (ml_anch && sv
            && (strpos + SvCUR(sv) != strend) && strpos[-1] != '\n') {
            t = strpos;
            goto find_anchor;
        }
 +      success_at_start:
        if (!(prog->reganch & ROPT_NAUGHTY)
            && --BmUSEFUL(prog->check_substr) < 0
            && prog->check_substr == prog->float_substr) { /* boo */
            s = strpos;
      }
  
 -    DEBUG_r(PerlIO_printf(Perl_debug_log, "%sFound%s at offset %ld\n",
 -                        PL_colors[4],PL_colors[5], (long)(s - strpos)) );
 +    DEBUG_r(PerlIO_printf(Perl_debug_log, "%sGuessed:%s match at offset %ld\n",
 +                        PL_colors[4], PL_colors[5], (long)(s - strpos)) );
      return s;
 +
 +  fail_finish:                                /* Substring not found */
 +    BmUSEFUL(prog->check_substr) += 5;        /* hooray */
    fail:
 -    DEBUG_r(PerlIO_printf(Perl_debug_log, "%sNot found...%s\n",
 +    DEBUG_r(PerlIO_printf(Perl_debug_log, "%sMatch rejected by optimizer%s\n",
                          PL_colors[4],PL_colors[5]));
      return Nullch;
  }
@@@ -683,7 -504,6 +683,7 @@@ Perl_regexec_flags(pTHX_ register regex
  
      PL_reg_flags = 0;
      PL_reg_eval_set = 0;
 +    PL_reg_maxiter = 0;
  
      if (prog->reganch & ROPT_UTF8)
        PL_reg_flags |= RF_utf8;
  
      DEBUG_r( if (!PL_colorset) reginitcolors() );
      DEBUG_r(PerlIO_printf(Perl_debug_log,
 -                    "%sMatching%s `%s%.60s%s%s' against `%s%.*s%s%s'\n",
 +                    "%sMatching REx%s `%s%.60s%s%s' against `%s%.*s%s%s'\n",
                      PL_colors[4],PL_colors[5],PL_colors[0],
                      prog->precomp,
                      PL_colors[1],
                s += UTF8SKIP(s);
            }
            break;
-       case ALNUMC:
-           while (s < strend) {
-               if (isALNUMC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case ALNUMCUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_alnumc, (U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case ALNUMCL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isALNUMC_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case ALNUMCLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isALNUMC_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NALNUMC:
-           while (s < strend) {
-               if (!isALNUMC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
+       }
+     }
+     else {
+       dontbother = 0;
+       if (prog->float_substr != Nullsv) {     /* Trim the end. */
+           char *last;
+           I32 oldpos = scream_pos;
+           if (flags & REXEC_SCREAM) {
+               last = screaminstr(sv, prog->float_substr, s - strbeg,
+                                  end_shift, &scream_pos, 1); /* last one */
+               if (!last)
+                   last = scream_olds; /* Only one occurence. */
            }
-           break;
-       case NALNUMCUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_alnumc, (U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
+           else {
+               STRLEN len;
+               char *little = SvPV(prog->float_substr, len);
+               if (SvTAIL(prog->float_substr)) {
+                   if (memEQ(strend - len + 1, little, len - 1))
+                       last = strend - len + 1;
+                   else if (!PL_multiline)
+                       last = memEQ(strend - len, little, len) 
+                           ? strend - len : Nullch;
                    else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NALNUMCL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isALNUMC_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
+                       goto find_last;
+               } else {
+                 find_last:
+                   if (len) 
+                       last = rninstr(s, strend, little, little + len);
                    else
-                       tmp = doevery;
+                       last = strend;  /* matching `$' */
                }
-               else
-                   tmp = 1;
-               s++;
            }
-           break;
-       case NALNUMCLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isALNUMC_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
+           if (last == NULL) goto phooey; /* Should not happen! */
+           dontbother = strend - last + prog->float_min_offset;
+       }
+       if (minlen && (dontbother < minlen))
+           dontbother = minlen - 1;
+       strend -= dontbother;              /* this one's always in bytes! */
+       /* We don't know much -- general case. */
+       if (UTF) {
+           for (;;) {
+               if (regtry(prog, s))
+                   goto got_it;
+               if (s >= strend)
+                   break;
                s += UTF8SKIP(s);
+           };
+       }
+       else {
+           do {
+               if (regtry(prog, s))
+                   goto got_it;
+           } while (s++ < strend);
+       }
+     }
+     /* Failure. */
+     goto phooey;
+ got_it:
+     RX_MATCH_TAINTED_set(prog, PL_reg_flags & RF_tainted);
+     if (PL_reg_eval_set) {
+       /* Preserve the current value of $^R */
+       if (oreplsv != GvSV(PL_replgv))
+           sv_setsv(oreplsv, GvSV(PL_replgv));/* So that when GvSV(replgv) is
+                                                 restored, the value remains
+                                                 the same. */
+       restore_pos(aTHXo_ 0);
+     }
+     /* make sure $`, $&, $', and $digit will work later */
+     if ( !(flags & REXEC_NOT_FIRST) ) {
+       if (RX_MATCH_COPIED(prog)) {
+           Safefree(prog->subbeg);
+           RX_MATCH_COPIED_off(prog);
+       }
+       if (flags & REXEC_COPY_STR) {
+           I32 i = PL_regeol - startpos + (stringarg - strbeg);
+           s = savepvn(strbeg, i);
+           prog->subbeg = s;
+           prog->sublen = i;
+           RX_MATCH_COPIED_on(prog);
+       }
+       else {
+           prog->subbeg = strbeg;
+           prog->sublen = PL_regeol - strbeg;  /* strend may have been modified */
+       }
+     }
+     
+     return 1;
+ phooey:
+     if (PL_reg_eval_set)
+       restore_pos(aTHXo_ 0);
+     return 0;
+ }
+ /*
+  - regtry - try match at specific point
+  */
+ STATIC I32                    /* 0 failure, 1 success */
+ S_regtry(pTHX_ regexp *prog, char *startpos)
+ {
+     dTHR;
+     register I32 i;
+     register I32 *sp;
+     register I32 *ep;
+     CHECKPOINT lastcp;
+     if ((prog->reganch & ROPT_EVAL_SEEN) && !PL_reg_eval_set) {
+       MAGIC *mg;
+       PL_reg_eval_set = RS_init;
+       DEBUG_r(DEBUG_s(
+           PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %i\n",
+                         PL_stack_sp - PL_stack_base);
+           ));
+       SAVEINT(cxstack[cxstack_ix].blk_oldsp);
+       cxstack[cxstack_ix].blk_oldsp = PL_stack_sp - PL_stack_base;
+       /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
+       SAVETMPS;
+       /* Apparently this is not needed, judging by wantarray. */
+       /* SAVEINT(cxstack[cxstack_ix].blk_gimme);
+          cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
+       if (PL_reg_sv) {
+           /* Make $_ available to executed code. */
+           if (PL_reg_sv != DEFSV) {
+               /* SAVE_DEFSV does *not* suffice here for USE_THREADS */
+               SAVESPTR(DEFSV);
+               DEFSV = PL_reg_sv;
            }
-           break;
-       case ASCII:
-           while (s < strend) {
-               if (isASCII(*(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NASCII:
-           while (s < strend) {
-               if (!isASCII(*(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case CNTRL:
-           while (s < strend) {
-               if (isCNTRL(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case CNTRLUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_cntrl,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case CNTRLL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isCNTRL_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case CNTRLLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isCNTRL_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NCNTRL:
-           while (s < strend) {
-               if (!isCNTRL(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NCNTRLUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_cntrl,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NCNTRLL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isCNTRL_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NCNTRLLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isCNTRL_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case GRAPH:
-           while (s < strend) {
-               if (isGRAPH(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case GRAPHUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_graph,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case GRAPHL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isGRAPH_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case GRAPHLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isGRAPH_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NGRAPH:
-           while (s < strend) {
-               if (!isGRAPH(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NGRAPHUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_graph,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NGRAPHL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isGRAPH_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NGRAPHLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isGRAPH_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case LOWER:
-           while (s < strend) {
-               if (isLOWER(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case LOWERUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_lower,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case LOWERL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isLOWER_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case LOWERLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isLOWER_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NLOWER:
-           while (s < strend) {
-               if (!isLOWER(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NLOWERUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_lower,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NLOWERL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isLOWER_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NLOWERLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isLOWER_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case PRINT:
-           while (s < strend) {
-               if (isPRINT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case PRINTUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_print,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case PRINTL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isPRINT_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case PRINTLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isPRINT_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NPRINT:
-           while (s < strend) {
-               if (!isPRINT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NPRINTUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_print,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NPRINTL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isPRINT_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NPRINTLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isPRINT_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case PUNCT:
-           while (s < strend) {
-               if (isPUNCT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case PUNCTUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_punct,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case PUNCTL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isPUNCT_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case PUNCTLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isPUNCT_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NPUNCT:
-           while (s < strend) {
-               if (!isPUNCT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NPUNCTUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_punct,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NPUNCTL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isPUNCT_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NPUNCTLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isPUNCT_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case UPPER:
-           while (s < strend) {
-               if (isUPPER(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case UPPERUTF8:
-           while (s < strend) {
-               if (swash_fetch(PL_utf8_upper,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case UPPERL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (isUPPER_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case UPPERLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (*s == ' ' || isUPPER_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NUPPER:
-           while (s < strend) {
-               if (!isUPPER(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NUPPERUTF8:
-           while (s < strend) {
-               if (!swash_fetch(PL_utf8_upper,(U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case NUPPERL:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isUPPER_LC(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NUPPERLUTF8:
-           PL_reg_flags |= RF_tainted;
-           while (s < strend) {
-               if (!isUPPER_LC_utf8((U8*)s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s += UTF8SKIP(s);
-           }
-           break;
-       case XDIGIT:
-           while (s < strend) {
-               if (isXDIGIT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       case NXDIGIT:
-           while (s < strend) {
-               if (!isXDIGIT(*s)) {
-                   if (tmp && regtry(prog, s))
-                       goto got_it;
-                   else
-                       tmp = doevery;
-               }
-               else
-                   tmp = 1;
-               s++;
-           }
-           break;
-       }
-     }
-     else {
-       dontbother = 0;
-       if (prog->float_substr != Nullsv) {     /* Trim the end. */
-           char *last;
-           I32 oldpos = scream_pos;
-           if (flags & REXEC_SCREAM) {
-               last = screaminstr(sv, prog->float_substr, s - strbeg,
-                                  end_shift, &scream_pos, 1); /* last one */
-               if (!last)
-                   last = scream_olds; /* Only one occurence. */
-           }
-           else {
-               STRLEN len;
-               char *little = SvPV(prog->float_substr, len);
-               if (SvTAIL(prog->float_substr)) {
-                   if (memEQ(strend - len + 1, little, len - 1))
-                       last = strend - len + 1;
-                   else if (!PL_multiline)
-                       last = memEQ(strend - len, little, len) 
-                           ? strend - len : Nullch;
-                   else
-                       goto find_last;
-               } else {
-                 find_last:
-                   if (len) 
-                       last = rninstr(s, strend, little, little + len);
-                   else
-                       last = strend;  /* matching `$' */
-               }
-           }
-           if (last == NULL) goto phooey; /* Should not happen! */
-           dontbother = strend - last + prog->float_min_offset;
-       }
-       if (minlen && (dontbother < minlen))
-           dontbother = minlen - 1;
-       strend -= dontbother;              /* this one's always in bytes! */
-       /* We don't know much -- general case. */
-       if (UTF) {
-           for (;;) {
-               if (regtry(prog, s))
-                   goto got_it;
-               if (s >= strend)
-                   break;
-               s += UTF8SKIP(s);
-           };
-       }
-       else {
-           do {
-               if (regtry(prog, s))
-                   goto got_it;
-           } while (s++ < strend);
-       }
-     }
-     /* Failure. */
-     goto phooey;
- got_it:
-     RX_MATCH_TAINTED_set(prog, PL_reg_flags & RF_tainted);
-     if (PL_reg_eval_set) {
-       /* Preserve the current value of $^R */
-       if (oreplsv != GvSV(PL_replgv))
-           sv_setsv(oreplsv, GvSV(PL_replgv));/* So that when GvSV(replgv) is
-                                                 restored, the value remains
-                                                 the same. */
-       restore_pos(aTHXo_ 0);
-     }
-     /* make sure $`, $&, $', and $digit will work later */
-     if ( !(flags & REXEC_NOT_FIRST) ) {
-       if (RX_MATCH_COPIED(prog)) {
-           Safefree(prog->subbeg);
-           RX_MATCH_COPIED_off(prog);
-       }
-       if (flags & REXEC_COPY_STR) {
-           I32 i = PL_regeol - startpos + (stringarg - strbeg);
-           s = savepvn(strbeg, i);
-           prog->subbeg = s;
-           prog->sublen = i;
-           RX_MATCH_COPIED_on(prog);
-       }
-       else {
-           prog->subbeg = strbeg;
-           prog->sublen = PL_regeol - strbeg;  /* strend may have been modified */
-       }
-     }
-     
-     return 1;
- phooey:
-     if (PL_reg_eval_set)
-       restore_pos(aTHXo_ 0);
-     return 0;
- }
- /*
-  - regtry - try match at specific point
-  */
- STATIC I32                    /* 0 failure, 1 success */
- S_regtry(pTHX_ regexp *prog, char *startpos)
- {
-     dTHR;
-     register I32 i;
-     register I32 *sp;
-     register I32 *ep;
-     CHECKPOINT lastcp;
-     if ((prog->reganch & ROPT_EVAL_SEEN) && !PL_reg_eval_set) {
-       MAGIC *mg;
-       PL_reg_eval_set = RS_init;
-       DEBUG_r(DEBUG_s(
-           PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %i\n",
-                         PL_stack_sp - PL_stack_base);
-           ));
-       SAVEINT(cxstack[cxstack_ix].blk_oldsp);
-       cxstack[cxstack_ix].blk_oldsp = PL_stack_sp - PL_stack_base;
-       /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
-       SAVETMPS;
-       /* Apparently this is not needed, judging by wantarray. */
-       /* SAVEINT(cxstack[cxstack_ix].blk_gimme);
-          cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
-       if (PL_reg_sv) {
-           /* Make $_ available to executed code. */
-           if (PL_reg_sv != DEFSV) {
-               /* SAVE_DEFSV does *not* suffice here for USE_THREADS */
-               SAVESPTR(DEFSV);
-               DEFSV = PL_reg_sv;
-           }
-       
-           if (!(SvTYPE(PL_reg_sv) >= SVt_PVMG && SvMAGIC(PL_reg_sv) 
-                 && (mg = mg_find(PL_reg_sv, 'g')))) {
-               /* prepare for quick setting of pos */
-               sv_magic(PL_reg_sv, (SV*)0, 'g', Nullch, 0);
-               mg = mg_find(PL_reg_sv, 'g');
-               mg->mg_len = -1;
-           }
-           PL_reg_magic    = mg;
-           PL_reg_oldpos   = mg->mg_len;
-           SAVEDESTRUCTOR(restore_pos, 0);
-         }
-       if (!PL_reg_curpm)
-           New(22,PL_reg_curpm, 1, PMOP);
-       PL_reg_curpm->op_pmregexp = prog;
-       PL_reg_oldcurpm = PL_curpm;
-       PL_curpm = PL_reg_curpm;
-       if (RX_MATCH_COPIED(prog)) {
-           /*  Here is a serious problem: we cannot rewrite subbeg,
-               since it may be needed if this match fails.  Thus
-               $` inside (?{}) could fail... */
-           PL_reg_oldsaved = prog->subbeg;
-           PL_reg_oldsavedlen = prog->sublen;
-           RX_MATCH_COPIED_off(prog);
-       }
-       else
-           PL_reg_oldsaved = Nullch;
-       prog->subbeg = PL_bostr;
-       prog->sublen = PL_regeol - PL_bostr; /* strend may have been modified */
-     }
-     prog->startp[0] = startpos - PL_bostr;
-     PL_reginput = startpos;
-     PL_regstartp = prog->startp;
-     PL_regendp = prog->endp;
-     PL_reglastparen = &prog->lastparen;
-     prog->lastparen = 0;
-     PL_regsize = 0;
-     DEBUG_r(PL_reg_starttry = startpos);
-     if (PL_reg_start_tmpl <= prog->nparens) {
-       PL_reg_start_tmpl = prog->nparens*3/2 + 3;
-         if(PL_reg_start_tmp)
-             Renew(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
-         else
-             New(22,PL_reg_start_tmp, PL_reg_start_tmpl, char*);
-     }
-     /* XXXX What this code is doing here?!!!  There should be no need
-        to do this again and again, PL_reglastparen should take care of
-        this!  */
-     sp = prog->startp;
-     ep = prog->endp;
-     if (prog->nparens) {
-       for (i = prog->nparens; i >= 1; i--) {
-           *++sp = -1;
-           *++ep = -1;
-       }
-     }
-     REGCP_SET;
-     if (regmatch(prog->program + 1)) {
-       prog->endp[0] = PL_reginput - PL_bostr;
-       return 1;
-     }
-     REGCP_UNWIND;
-     return 0;
- }
- /*
-  - regmatch - main matching routine
-  *
-  * Conceptually the strategy is simple:  check to see whether the current
-  * node matches, call self recursively to see whether the rest matches,
-  * and then act accordingly.  In practice we make some effort to avoid
-  * recursion, in particular by going through "ordinary" nodes (that don't
-  * need to know whether the rest of the match failed) by a loop instead of
-  * by recursion.
-  */
- /* [lwall] I've hoisted the register declarations to the outer block in order to
-  * maybe save a little bit of pushing and popping on the stack.  It also takes
-  * advantage of machines that use a register save mask on subroutine entry.
-  */
- STATIC I32                    /* 0 failure, 1 success */
- S_regmatch(pTHX_ regnode *prog)
- {
-     dTHR;
-     register regnode *scan;   /* Current node. */
-     regnode *next;            /* Next node. */
-     regnode *inner;           /* Next node in internal branch. */
-     register I32 nextchr;     /* renamed nextchr - nextchar colides with
-                                  function of same name */
-     register I32 n;           /* no or next */
-     register I32 ln;          /* len or last */
-     register char *s;         /* operand or save */
-     register char *locinput = PL_reginput;
-     register I32 c1, c2, paren;       /* case fold search, parenth */
-     int minmod = 0, sw = 0, logical = 0;
- #ifdef DEBUGGING
-     PL_regindent++;
- #endif
-     /* Note that nextchr is a byte even in UTF */
-     nextchr = UCHARAT(locinput);
-     scan = prog;
-     while (scan != NULL) {
- #define sayNO_L (logical ? (logical = 0, sw = 0, goto cont) : sayNO)
- #ifdef DEBUGGING
- #  define sayYES goto yes
- #  define sayNO goto no
- #  define saySAME(x) if (x) goto yes; else goto no
- #  define REPORT_CODE_OFF 24
- #else
- #  define sayYES return 1
- #  define sayNO return 0
- #  define saySAME(x) return x
- #endif
-       DEBUG_r( {
-           SV *prop = sv_newmortal();
-           int docolor = *PL_colors[0];
-           int taill = (docolor ? 10 : 7); /* 3 chars for "> <" */
-           int l = (PL_regeol - locinput > taill ? taill : PL_regeol - locinput);
-           /* The part of the string before starttry has one color
-              (pref0_len chars), between starttry and current
-              position another one (pref_len - pref0_len chars),
-              after the current position the third one.
-              We assume that pref0_len <= pref_len, otherwise we
-              decrease pref0_len.  */
-           int pref_len = (locinput - PL_bostr > (5 + taill) - l 
-                           ? (5 + taill) - l : locinput - PL_bostr);
-           int pref0_len = pref_len  - (locinput - PL_reg_starttry);
-           if (l + pref_len < (5 + taill) && l < PL_regeol - locinput)
-               l = ( PL_regeol - locinput > (5 + taill) - pref_len 
-                     ? (5 + taill) - pref_len : PL_regeol - locinput);
-           if (pref0_len < 0)
-               pref0_len = 0;
-           if (pref0_len > pref_len)
-               pref0_len = pref_len;
-           regprop(prop, scan);
-           PerlIO_printf(Perl_debug_log, 
-                         "%4i <%s%.*s%s%s%.*s%s%s%s%.*s%s>%*s|%3d:%*s%s\n",
-                         locinput - PL_bostr, 
-                         PL_colors[4], pref0_len, 
-                         locinput - pref_len, PL_colors[5],
-                         PL_colors[2], pref_len - pref0_len, 
-                         locinput - pref_len + pref0_len, PL_colors[3],
-                         (docolor ? "" : "> <"),
-                         PL_colors[0], l, locinput, PL_colors[1],
-                         15 - l - pref_len + 1,
-                         "",
-                         scan - PL_regprogram, PL_regindent*2, "",
-                         SvPVX(prop));
-       } );
-       next = scan + NEXT_OFF(scan);
-       if (next == scan)
-           next = NULL;
-       switch (OP(scan)) {
-       case BOL:
-           if (locinput == PL_bostr
-               ? PL_regprev == '\n'
-               : (PL_multiline && 
-                  (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
-           {
-               /* regtill = regbol; */
-               break;
-           }
-           sayNO;
-       case MBOL:
-           if (locinput == PL_bostr
-               ? PL_regprev == '\n'
-               : ((nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
-           {
-               break;
-           }
-           sayNO;
-       case SBOL:
-           if (locinput == PL_regbol && PL_regprev == '\n')
-               break;
-           sayNO;
-       case GPOS:
-           if (locinput == PL_reg_ganch)
-               break;
-           sayNO;
-       case EOL:
-           if (PL_multiline)
-               goto meol;
-           else
-               goto seol;
-       case MEOL:
-         meol:
-           if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
-               sayNO;
-           break;
-       case SEOL:
-         seol:
-           if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
-               sayNO;
-           if (PL_regeol - locinput > 1)
-               sayNO;
-           break;
-       case EOS:
-           if (PL_regeol != locinput)
-               sayNO;
-           break;
-       case SANYUTF8:
-           if (nextchr & 0x80) {
-               locinput += PL_utf8skip[nextchr];
-               if (locinput > PL_regeol)
-                   sayNO;
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case SANY:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ANYUTF8:
-           if (nextchr & 0x80) {
-               locinput += PL_utf8skip[nextchr];
-               if (locinput > PL_regeol)
-                   sayNO;
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case REG_ANY:
-           if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case EXACT:
-           s = (char *) OPERAND(scan);
-           ln = UCHARAT(s++);
-           /* Inline the first character, for speed. */
-           if (UCHARAT(s) != nextchr)
-               sayNO;
-           if (PL_regeol - locinput < ln)
-               sayNO;
-           if (ln > 1 && memNE(s, locinput, ln))
-               sayNO;
-           locinput += ln;
-           nextchr = UCHARAT(locinput);
-           break;
-       case EXACTFL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case EXACTF:
-           s = (char *) OPERAND(scan);
-           ln = UCHARAT(s++);
-           if (UTF) {
-               char *l = locinput;
-               char *e = s + ln;
-               c1 = OP(scan) == EXACTF;
-               while (s < e) {
-                   if (l >= PL_regeol)
-                       sayNO;
-                   if (utf8_to_uv((U8*)s, 0) != (c1 ?
-                                                 toLOWER_utf8((U8*)l) :
-                                                 toLOWER_LC_utf8((U8*)l)))
-                   {
-                       sayNO;
-                   }
-                   s += UTF8SKIP(s);
-                   l += UTF8SKIP(l);
-               }
-               locinput = l;
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           /* Inline the first character, for speed. */
-           if (UCHARAT(s) != nextchr &&
-               UCHARAT(s) != ((OP(scan) == EXACTF)
-                              ? PL_fold : PL_fold_locale)[nextchr])
-               sayNO;
-           if (PL_regeol - locinput < ln)
-               sayNO;
-           if (ln > 1 && (OP(scan) == EXACTF
-                          ? ibcmp(s, locinput, ln)
-                          : ibcmp_locale(s, locinput, ln)))
-               sayNO;
-           locinput += ln;
-           nextchr = UCHARAT(locinput);
-           break;
-       case ANYOFUTF8:
-           s = (char *) OPERAND(scan);
-           if (!REGINCLASSUTF8(scan, (U8*)locinput))
-               sayNO;
-           if (locinput >= PL_regeol)
-               sayNO;
-           locinput += PL_utf8skip[nextchr];
-           nextchr = UCHARAT(locinput);
-           break;
-       case ANYOF:
-           s = (char *) OPERAND(scan);
-           if (nextchr < 0)
-               nextchr = UCHARAT(locinput);
-           if (!REGINCLASS(s, nextchr))
-               sayNO;
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALNUML:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALNUM:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == ALNUM
-                 ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALNUMLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALNUMUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == ALNUMUTF8
-                     ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
-                     : isALNUM_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (!(OP(scan) == ALNUMUTF8
-                 ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALNUML:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALNUM:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (OP(scan) == NALNUM
-               ? isALNUM(nextchr) : isALNUM_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALNUMLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALNUMUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (OP(scan) == NALNUMUTF8
-                   ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
-                   : isALNUM_LC_utf8((U8*)locinput))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (OP(scan) == NALNUMUTF8
-               ? isALNUM(nextchr) : isALNUM_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case BOUNDL:
-       case NBOUNDL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case BOUND:
-       case NBOUND:
-           /* was last char in word? */
-           ln = (locinput != PL_regbol) ? UCHARAT(locinput - 1) : PL_regprev;
-           if (OP(scan) == BOUND || OP(scan) == NBOUND) {
-               ln = isALNUM(ln);
-               n = isALNUM(nextchr);
-           }
-           else {
-               ln = isALNUM_LC(ln);
-               n = isALNUM_LC(nextchr);
-           }
-           if (((!ln) == (!n)) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
-               sayNO;
-           break;
-       case BOUNDLUTF8:
-       case NBOUNDLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case BOUNDUTF8:
-       case NBOUNDUTF8:
-           /* was last char in word? */
-           ln = (locinput != PL_regbol)
-               ? utf8_to_uv(reghop((U8*)locinput, -1), 0) : PL_regprev;
-           if (OP(scan) == BOUNDUTF8 || OP(scan) == NBOUNDUTF8) {
-               ln = isALNUM_uni(ln);
-               n = swash_fetch(PL_utf8_alnum, (U8*)locinput);
-           }
-           else {
-               ln = isALNUM_LC_uni(ln);
-               n = isALNUM_LC_utf8((U8*)locinput);
-           }
-           if (((!ln) == (!n)) == (OP(scan) == BOUNDUTF8 || OP(scan) == BOUNDLUTF8))
-               sayNO;
-           break;
-       case SPACEL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case SPACE:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (!(OP(scan) == SPACE
-                 ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case SPACELUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case SPACEUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == SPACEUTF8
-                     ? swash_fetch(PL_utf8_space,(U8*)locinput)
-                     : isSPACE_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (!(OP(scan) == SPACEUTF8
-                 ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NSPACEL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NSPACE:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == SPACE
-               ? isSPACE(nextchr) : isSPACE_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NSPACELUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NSPACEUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (OP(scan) == NSPACEUTF8
-                   ? swash_fetch(PL_utf8_space,(U8*)locinput)
-                   : isSPACE_LC_utf8((U8*)locinput))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (OP(scan) == NSPACEUTF8
-               ? isSPACE(nextchr) : isSPACE_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case DIGITL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case DIGIT:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (!(OP(scan) == DIGIT
-                 ? isDIGIT(nextchr) : isDIGIT_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case DIGITLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case DIGITUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (OP(scan) == NDIGITUTF8
-                   ? swash_fetch(PL_utf8_digit,(U8*)locinput)
-                   : isDIGIT_LC_utf8((U8*)locinput))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (!isDIGIT(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NDIGITL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NDIGIT:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == DIGIT
-               ? isDIGIT(nextchr) : isDIGIT_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NDIGITLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NDIGITUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_digit,(U8*)locinput))
-                   sayNO;
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (isDIGIT(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALNUMCL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALNUMC:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == ALNUMC
-                 ? isALNUMC(nextchr) : isALNUMC_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALNUMCLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALNUMCUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == ALNUMCUTF8
-                     ? swash_fetch(PL_utf8_alnumc, (U8*)locinput)
-                     : isALNUMC_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
+       
+           if (!(SvTYPE(PL_reg_sv) >= SVt_PVMG && SvMAGIC(PL_reg_sv) 
+                 && (mg = mg_find(PL_reg_sv, 'g')))) {
+               /* prepare for quick setting of pos */
+               sv_magic(PL_reg_sv, (SV*)0, 'g', Nullch, 0);
+               mg = mg_find(PL_reg_sv, 'g');
+               mg->mg_len = -1;
            }
-           if (!(OP(scan) == ALNUMCUTF8
-                 ? isALNUMC(nextchr) : isALNUMC_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALNUMCL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALNUMC:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == ALNUMC
-               ? isALNUMC(nextchr) : isALNUMC_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALNUMCLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALNUMCUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_alnumc,(U8*)locinput))
-                   sayNO;
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
+           PL_reg_magic    = mg;
+           PL_reg_oldpos   = mg->mg_len;
+           SAVEDESTRUCTOR(restore_pos, 0);
+         }
+       if (!PL_reg_curpm)
+           New(22,PL_reg_curpm, 1, PMOP);
+       PL_reg_curpm->op_pmregexp = prog;
+       PL_reg_oldcurpm = PL_curpm;
+       PL_curpm = PL_reg_curpm;
+       if (RX_MATCH_COPIED(prog)) {
+           /*  Here is a serious problem: we cannot rewrite subbeg,
+               since it may be needed if this match fails.  Thus
+               $` inside (?{}) could fail... */
+           PL_reg_oldsaved = prog->subbeg;
+           PL_reg_oldsavedlen = prog->sublen;
+           RX_MATCH_COPIED_off(prog);
+       }
+       else
+           PL_reg_oldsaved = Nullch;
+       prog->subbeg = PL_bostr;
+       prog->sublen = PL_regeol - PL_bostr; /* strend may have been modified */
+     }
+     prog->startp[0] = startpos - PL_bostr;
+     PL_reginput = startpos;
+     PL_regstartp = prog->startp;
+     PL_regendp = prog->endp;
+     PL_reglastparen = &prog->lastparen;
+     prog->lastparen = 0;
+     PL_regsize = 0;
+     DEBUG_r(PL_reg_starttry = startpos);
+     if (PL_reg_start_tmpl <= prog->nparens) {
+       PL_reg_start_tmpl = prog->nparens*3/2 + 3;
+         if(PL_reg_start_tmp)
+             Renew(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
+         else
+             New(22,PL_reg_start_tmp, PL_reg_start_tmpl, char*);
+     }
+     /* XXXX What this code is doing here?!!!  There should be no need
+        to do this again and again, PL_reglastparen should take care of
+        this!  */
+     sp = prog->startp;
+     ep = prog->endp;
+     if (prog->nparens) {
+       for (i = prog->nparens; i >= 1; i--) {
+           *++sp = -1;
+           *++ep = -1;
+       }
+     }
+     REGCP_SET;
+     if (regmatch(prog->program + 1)) {
+       prog->endp[0] = PL_reginput - PL_bostr;
+       return 1;
+     }
+     REGCP_UNWIND;
+     return 0;
+ }
+ /*
+  - regmatch - main matching routine
+  *
+  * Conceptually the strategy is simple:  check to see whether the current
+  * node matches, call self recursively to see whether the rest matches,
+  * and then act accordingly.  In practice we make some effort to avoid
+  * recursion, in particular by going through "ordinary" nodes (that don't
+  * need to know whether the rest of the match failed) by a loop instead of
+  * by recursion.
+  */
+ /* [lwall] I've hoisted the register declarations to the outer block in order to
+  * maybe save a little bit of pushing and popping on the stack.  It also takes
+  * advantage of machines that use a register save mask on subroutine entry.
+  */
+ STATIC I32                    /* 0 failure, 1 success */
+ S_regmatch(pTHX_ regnode *prog)
+ {
+     dTHR;
+     register regnode *scan;   /* Current node. */
+     regnode *next;            /* Next node. */
+     regnode *inner;           /* Next node in internal branch. */
+     register I32 nextchr;     /* renamed nextchr - nextchar colides with
+                                  function of same name */
+     register I32 n;           /* no or next */
+     register I32 ln;          /* len or last */
+     register char *s;         /* operand or save */
+     register char *locinput = PL_reginput;
+     register I32 c1, c2, paren;       /* case fold search, parenth */
+     int minmod = 0, sw = 0, logical = 0;
+ #ifdef DEBUGGING
+     PL_regindent++;
+ #endif
+     /* Note that nextchr is a byte even in UTF */
+     nextchr = UCHARAT(locinput);
+     scan = prog;
+     while (scan != NULL) {
+ #define sayNO_L (logical ? (logical = 0, sw = 0, goto cont) : sayNO)
+ #ifdef DEBUGGING
+ #  define sayYES goto yes
+ #  define sayNO goto no
+ #  define saySAME(x) if (x) goto yes; else goto no
+ #  define REPORT_CODE_OFF 24
+ #else
+ #  define sayYES return 1
+ #  define sayNO return 0
+ #  define saySAME(x) return x
+ #endif
+       DEBUG_r( {
+           SV *prop = sv_newmortal();
+           int docolor = *PL_colors[0];
+           int taill = (docolor ? 10 : 7); /* 3 chars for "> <" */
+           int l = (PL_regeol - locinput > taill ? taill : PL_regeol - locinput);
+           /* The part of the string before starttry has one color
+              (pref0_len chars), between starttry and current
+              position another one (pref_len - pref0_len chars),
+              after the current position the third one.
+              We assume that pref0_len <= pref_len, otherwise we
+              decrease pref0_len.  */
+           int pref_len = (locinput - PL_bostr > (5 + taill) - l 
+                           ? (5 + taill) - l : locinput - PL_bostr);
+           int pref0_len = pref_len  - (locinput - PL_reg_starttry);
+           if (l + pref_len < (5 + taill) && l < PL_regeol - locinput)
+               l = ( PL_regeol - locinput > (5 + taill) - pref_len 
+                     ? (5 + taill) - pref_len : PL_regeol - locinput);
+           if (pref0_len < 0)
+               pref0_len = 0;
+           if (pref0_len > pref_len)
+               pref0_len = pref_len;
+           regprop(prop, scan);
+           PerlIO_printf(Perl_debug_log, 
+                         "%4i <%s%.*s%s%s%.*s%s%s%s%.*s%s>%*s|%3d:%*s%s\n",
+                         locinput - PL_bostr, 
+                         PL_colors[4], pref0_len, 
+                         locinput - pref_len, PL_colors[5],
+                         PL_colors[2], pref_len - pref0_len, 
+                         locinput - pref_len + pref0_len, PL_colors[3],
+                         (docolor ? "" : "> <"),
+                         PL_colors[0], l, locinput, PL_colors[1],
+                         15 - l - pref_len + 1,
+                         "",
+                         scan - PL_regprogram, PL_regindent*2, "",
+                         SvPVX(prop));
+       } );
+       next = scan + NEXT_OFF(scan);
+       if (next == scan)
+           next = NULL;
+       switch (OP(scan)) {
+       case BOL:
+           if (locinput == PL_bostr
+               ? PL_regprev == '\n'
+               : (PL_multiline && 
+                  (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
+           {
+               /* regtill = regbol; */
                break;
            }
-           if (isALNUMC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALPHAL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALPHA:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == ALPHA
-                 ? isALPHA(nextchr) : isALPHA_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ALPHALUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case ALPHAUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == ALPHAUTF8
-                     ? swash_fetch(PL_utf8_alpha, (U8*)locinput)
-                     : isALPHA_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
+           sayNO;
+       case MBOL:
+           if (locinput == PL_bostr
+               ? PL_regprev == '\n'
+               : ((nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
+           {
                break;
            }
-           if (!(OP(scan) == ALPHAUTF8
-                 ? isALPHA(nextchr) : isALPHA_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALPHAL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALPHA:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == ALPHA
-               ? isALPHA(nextchr) : isALPHA_LC(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NALPHALUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NALPHAUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_alpha,(U8*)locinput))
-                   sayNO;
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
+           sayNO;
+       case SBOL:
+           if (locinput == PL_regbol && PL_regprev == '\n')
                break;
-           }
-           if (isALPHA(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case ASCII:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (!isASCII(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NASCII:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (isASCII(nextchr))
+           sayNO;
+       case GPOS:
+           if (locinput == PL_reg_ganch)
+               break;
+           sayNO;
+       case EOL:
+           if (PL_multiline)
+               goto meol;
+           else
+               goto seol;
+       case MEOL:
+         meol:
+           if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
                sayNO;
-           nextchr = UCHARAT(++locinput);
            break;
-       case CNTRLL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case CNTRL:
-           if (!nextchr)
+       case SEOL:
+         seol:
+           if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
                sayNO;
-           if (!(OP(scan) == CNTRL
-                 ? isCNTRL(nextchr) : isCNTRL_LC(nextchr)))
+           if (PL_regeol - locinput > 1)
                sayNO;
-           nextchr = UCHARAT(++locinput);
            break;
-       case CNTRLLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case CNTRLUTF8:
-           if (!nextchr)
+       case EOS:
+           if (PL_regeol != locinput)
                sayNO;
+           break;
+       case SANYUTF8:
            if (nextchr & 0x80) {
-               if (!(OP(scan) == CNTRLUTF8
-                     ? swash_fetch(PL_utf8_cntrl, (U8*)locinput)
-                     : isCNTRL_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
                locinput += PL_utf8skip[nextchr];
+               if (locinput > PL_regeol)
+                   sayNO;
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (!(OP(scan) == CNTRLUTF8
-                 ? isCNTRL(nextchr) : isCNTRL_LC(nextchr)))
+           if (!nextchr && locinput >= PL_regeol)
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NCNTRLL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NCNTRL:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == CNTRL
-               ? isCNTRL(nextchr) : isCNTRL_LC(nextchr))
+       case SANY:
+           if (!nextchr && locinput >= PL_regeol)
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NCNTRLLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NCNTRLUTF8:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
+       case ANYUTF8:
            if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_cntrl,(U8*)locinput))
-                   sayNO;
                locinput += PL_utf8skip[nextchr];
+               if (locinput > PL_regeol)
+                   sayNO;
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (isCNTRL(nextchr))
+           if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case GRAPHL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case GRAPH:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == GRAPH
-                 ? isGRAPH(nextchr) : isGRAPH_LC(nextchr)))
+       case REG_ANY:
+           if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case GRAPHLUTF8:
+       case EXACT:
+           s = (char *) OPERAND(scan);
+           ln = UCHARAT(s++);
+           /* Inline the first character, for speed. */
+           if (UCHARAT(s) != nextchr)
+               sayNO;
+           if (PL_regeol - locinput < ln)
+               sayNO;
+           if (ln > 1 && memNE(s, locinput, ln))
+               sayNO;
+           locinput += ln;
+           nextchr = UCHARAT(locinput);
+           break;
+       case EXACTFL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case GRAPHUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == GRAPHUTF8
-                     ? swash_fetch(PL_utf8_graph, (U8*)locinput)
-                     : isGRAPH_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
+       case EXACTF:
+           s = (char *) OPERAND(scan);
+           ln = UCHARAT(s++);
+           if (UTF) {
+               char *l = locinput;
+               char *e = s + ln;
+               c1 = OP(scan) == EXACTF;
+               while (s < e) {
+                   if (l >= PL_regeol)
+                       sayNO;
+                   if (utf8_to_uv((U8*)s, 0) != (c1 ?
+                                                 toLOWER_utf8((U8*)l) :
+                                                 toLOWER_LC_utf8((U8*)l)))
+                   {
+                       sayNO;
+                   }
+                   s += UTF8SKIP(s);
+                   l += UTF8SKIP(l);
                }
-               locinput += PL_utf8skip[nextchr];
+               locinput = l;
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (!(OP(scan) == GRAPHUTF8
-                 ? isGRAPH(nextchr) : isGRAPH_LC(nextchr)))
+           /* Inline the first character, for speed. */
+           if (UCHARAT(s) != nextchr &&
+               UCHARAT(s) != ((OP(scan) == EXACTF)
+                              ? PL_fold : PL_fold_locale)[nextchr])
                sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NGRAPHL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NGRAPH:
-           if (!nextchr)
+           if (PL_regeol - locinput < ln)
                sayNO;
-           if (OP(scan) == GRAPH
-               ? isGRAPH(nextchr) : isGRAPH_LC(nextchr))
+           if (ln > 1 && (OP(scan) == EXACTF
+                          ? ibcmp(s, locinput, ln)
+                          : ibcmp_locale(s, locinput, ln)))
                sayNO;
-           nextchr = UCHARAT(++locinput);
+           locinput += ln;
+           nextchr = UCHARAT(locinput);
            break;
-       case NGRAPHLUTF8:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NGRAPHUTF8:
-           if (!nextchr && locinput >= PL_regeol)
+       case ANYOFUTF8:
+           s = (char *) OPERAND(scan);
+           if (!REGINCLASSUTF8(scan, (U8*)locinput))
                sayNO;
-           if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_graph,(U8*)locinput))
-                   sayNO;
-               locinput += PL_utf8skip[nextchr];
+           if (locinput >= PL_regeol)
+               sayNO;
+           locinput += PL_utf8skip[nextchr];
+           nextchr = UCHARAT(locinput);
+           break;
+       case ANYOF:
+           s = (char *) OPERAND(scan);
+           if (nextchr < 0)
                nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (isGRAPH(nextchr))
+           if (!REGINCLASS(s, nextchr))
+               sayNO;
+           if (!nextchr && locinput >= PL_regeol)
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case LOWERL:
+       case ALNUML:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case LOWER:
+       case ALNUM:
            if (!nextchr)
                sayNO;
-           if (!(OP(scan) == LOWER
-                 ? isLOWER(nextchr) : isLOWER_LC(nextchr)))
+           if (!(OP(scan) == ALNUM
+                 ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case LOWERLUTF8:
+       case ALNUMLUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case LOWERUTF8:
+       case ALNUMUTF8:
            if (!nextchr)
                sayNO;
            if (nextchr & 0x80) {
-               if (!(OP(scan) == LOWERUTF8
-                     ? swash_fetch(PL_utf8_lower, (U8*)locinput)
-                     : isLOWER_LC_utf8((U8*)locinput)))
+               if (!(OP(scan) == ALNUMUTF8
+                     ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
+                     : isALNUM_LC_utf8((U8*)locinput)))
                {
                    sayNO;
                }
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (!(OP(scan) == LOWERUTF8
-                 ? isLOWER(nextchr) : isLOWER_LC(nextchr)))
+           if (!(OP(scan) == ALNUMUTF8
+                 ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NLOWERL:
+       case NALNUML:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NLOWER:
-           if (!nextchr)
+       case NALNUM:
+           if (!nextchr && locinput >= PL_regeol)
                sayNO;
-           if (OP(scan) == LOWER
-               ? isLOWER(nextchr) : isLOWER_LC(nextchr))
+           if (OP(scan) == NALNUM
+               ? isALNUM(nextchr) : isALNUM_LC(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NLOWERLUTF8:
+       case NALNUMLUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NLOWERUTF8:
+       case NALNUMUTF8:
            if (!nextchr && locinput >= PL_regeol)
                sayNO;
            if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_lower,(U8*)locinput))
+               if (OP(scan) == NALNUMUTF8
+                   ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
+                   : isALNUM_LC_utf8((U8*)locinput))
+               {
                    sayNO;
+               }
                locinput += PL_utf8skip[nextchr];
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (isLOWER(nextchr))
+           if (OP(scan) == NALNUMUTF8
+               ? isALNUM(nextchr) : isALNUM_LC(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case PRINTL:
+       case BOUNDL:
+       case NBOUNDL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case PRINT:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == PRINT
-                 ? isPRINT(nextchr) : isPRINT_LC(nextchr)))
+       case BOUND:
+       case NBOUND:
+           /* was last char in word? */
+           ln = (locinput != PL_regbol) ? UCHARAT(locinput - 1) : PL_regprev;
+           if (OP(scan) == BOUND || OP(scan) == NBOUND) {
+               ln = isALNUM(ln);
+               n = isALNUM(nextchr);
+           }
+           else {
+               ln = isALNUM_LC(ln);
+               n = isALNUM_LC(nextchr);
+           }
+           if (((!ln) == (!n)) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
                sayNO;
-           nextchr = UCHARAT(++locinput);
            break;
-       case PRINTLUTF8:
+       case BOUNDLUTF8:
+       case NBOUNDLUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case PRINTUTF8:
-           if (!nextchr)
-               sayNO;
-           if (nextchr & 0x80) {
-               if (!(OP(scan) == PRINTUTF8
-                     ? swash_fetch(PL_utf8_print, (U8*)locinput)
-                     : isPRINT_LC_utf8((U8*)locinput)))
-               {
-                   sayNO;
-               }
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
+       case BOUNDUTF8:
+       case NBOUNDUTF8:
+           /* was last char in word? */
+           ln = (locinput != PL_regbol)
+               ? utf8_to_uv(reghop((U8*)locinput, -1), 0) : PL_regprev;
+           if (OP(scan) == BOUNDUTF8 || OP(scan) == NBOUNDUTF8) {
+               ln = isALNUM_uni(ln);
+               n = swash_fetch(PL_utf8_alnum, (U8*)locinput);
            }
-           if (!(OP(scan) == PRINTUTF8
-                 ? isPRINT(nextchr) : isPRINT_LC(nextchr)))
+           else {
+               ln = isALNUM_LC_uni(ln);
+               n = isALNUM_LC_utf8((U8*)locinput);
+           }
+           if (((!ln) == (!n)) == (OP(scan) == BOUNDUTF8 || OP(scan) == BOUNDLUTF8))
                sayNO;
-           nextchr = UCHARAT(++locinput);
            break;
-       case NPRINTL:
+       case SPACEL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NPRINT:
-           if (!nextchr)
+       case SPACE:
+           if (!nextchr && locinput >= PL_regeol)
                sayNO;
-           if (OP(scan) == PRINT
-               ? isPRINT(nextchr) : isPRINT_LC(nextchr))
+           if (!(OP(scan) == SPACE
+                 ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NPRINTLUTF8:
+       case SPACELUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NPRINTUTF8:
+       case SPACEUTF8:
            if (!nextchr && locinput >= PL_regeol)
                sayNO;
            if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_print,(U8*)locinput))
+               if (!(OP(scan) == SPACEUTF8
+                     ? swash_fetch(PL_utf8_space,(U8*)locinput)
+                     : isSPACE_LC_utf8((U8*)locinput)))
+               {
                    sayNO;
+               }
                locinput += PL_utf8skip[nextchr];
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (isPRINT(nextchr))
+           if (!(OP(scan) == SPACEUTF8
+                 ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case PUNCTL:
+       case NSPACEL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case PUNCT:
+       case NSPACE:
            if (!nextchr)
                sayNO;
-           if (!(OP(scan) == PUNCT
-                 ? isPUNCT(nextchr) : isPUNCT_LC(nextchr)))
+           if (OP(scan) == SPACE
+               ? isSPACE(nextchr) : isSPACE_LC(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case PUNCTLUTF8:
+       case NSPACELUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case PUNCTUTF8:
+       case NSPACEUTF8:
            if (!nextchr)
                sayNO;
            if (nextchr & 0x80) {
-               if (!(OP(scan) == PUNCTUTF8
-                     ? swash_fetch(PL_utf8_punct, (U8*)locinput)
-                     : isPUNCT_LC_utf8((U8*)locinput)))
+               if (OP(scan) == NSPACEUTF8
+                   ? swash_fetch(PL_utf8_space,(U8*)locinput)
+                   : isSPACE_LC_utf8((U8*)locinput))
                {
                    sayNO;
                }
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (!(OP(scan) == PUNCTUTF8
-                 ? isPUNCT(nextchr) : isPUNCT_LC(nextchr)))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NPUNCTL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case NPUNCT:
-           if (!nextchr)
-               sayNO;
-           if (OP(scan) == PUNCT
-               ? isPUNCT(nextchr) : isPUNCT_LC(nextchr))
+           if (OP(scan) == NSPACEUTF8
+               ? isSPACE(nextchr) : isSPACE_LC(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NPUNCTLUTF8:
+       case DIGITL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NPUNCTUTF8:
+       case DIGIT:
            if (!nextchr && locinput >= PL_regeol)
                sayNO;
-           if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_punct,(U8*)locinput))
-                   sayNO;
-               locinput += PL_utf8skip[nextchr];
-               nextchr = UCHARAT(locinput);
-               break;
-           }
-           if (isPUNCT(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case UPPERL:
-           PL_reg_flags |= RF_tainted;
-           /* FALL THROUGH */
-       case UPPER:
-           if (!nextchr)
-               sayNO;
-           if (!(OP(scan) == UPPER
-                 ? isUPPER(nextchr) : isUPPER_LC(nextchr)))
+           if (!(OP(scan) == DIGIT
+                 ? isDIGIT(nextchr) : isDIGIT_LC(nextchr)))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case UPPERLUTF8:
+       case DIGITLUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case UPPERUTF8:
+       case DIGITUTF8:
            if (!nextchr)
                sayNO;
            if (nextchr & 0x80) {
-               if (!(OP(scan) == UPPERUTF8
-                     ? swash_fetch(PL_utf8_upper, (U8*)locinput)
-                     : isUPPER_LC_utf8((U8*)locinput)))
+               if (OP(scan) == NDIGITUTF8
+                   ? swash_fetch(PL_utf8_digit,(U8*)locinput)
+                   : isDIGIT_LC_utf8((U8*)locinput))
                {
                    sayNO;
                }
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (!(OP(scan) == UPPERUTF8
-                 ? isUPPER(nextchr) : isUPPER_LC(nextchr)))
+           if (!isDIGIT(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NUPPERL:
+       case NDIGITL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NUPPER:
+       case NDIGIT:
            if (!nextchr)
                sayNO;
-           if (OP(scan) == UPPER
-               ? isUPPER(nextchr) : isUPPER_LC(nextchr))
+           if (OP(scan) == DIGIT
+               ? isDIGIT(nextchr) : isDIGIT_LC(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
-       case NUPPERLUTF8:
+       case NDIGITLUTF8:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
-       case NUPPERUTF8:
+       case NDIGITUTF8:
            if (!nextchr && locinput >= PL_regeol)
                sayNO;
            if (nextchr & 0x80) {
-               if (swash_fetch(PL_utf8_upper,(U8*)locinput))
+               if (swash_fetch(PL_utf8_digit,(U8*)locinput))
                    sayNO;
                locinput += PL_utf8skip[nextchr];
                nextchr = UCHARAT(locinput);
                break;
            }
-           if (isUPPER(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case XDIGIT:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (!isXDIGIT(nextchr))
-               sayNO;
-           nextchr = UCHARAT(++locinput);
-           break;
-       case NXDIGIT:
-           if (!nextchr && locinput >= PL_regeol)
-               sayNO;
-           if (isXDIGIT(nextchr))
+           if (isDIGIT(nextchr))
                sayNO;
            nextchr = UCHARAT(++locinput);
            break;
        case REFF:
            n = ARG(scan);  /* which paren pair */
            ln = PL_regstartp[n];
 +          PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
            if (*PL_reglastparen < n || ln == -1)
                sayNO;                  /* Do not match unless seen CLOSEn. */
            if (ln == PL_regendp[n])
                    *PL_reglastparen = 0;
                    PL_reg_call_cc = &state;
                    PL_reginput = locinput;
 +
 +                  /* XXXX This is too dramatic a measure... */
 +                  PL_reg_maxiter = 0;
 +
                    if (regmatch(re->program + 1)) {
                        ReREFCNT_dec(re);
                        regcpblow(cp);
                    PL_regcc = state.cc;
                    PL_reg_re = state.re;
                    cache_re(PL_reg_re);
 +
 +                  /* XXXX This is too dramatic a measure... */
 +                  PL_reg_maxiter = 0;
 +
                    sayNO;
                }
                sw = SvTRUE(ret);
            sw = (*PL_reglastparen >= n && PL_regendp[n] != -1);
            break;
        case IFTHEN:
 +          PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
            if (sw)
                next = NEXTOPER(NEXTOPER(scan));
            else {
                /*
                 * This is really hard to understand, because after we match
                 * what we're trying to match, we must make sure the rest of
 -               * the RE is going to match for sure, and to do that we have
 +               * the REx is going to match for sure, and to do that we have
                 * to go back UP the parse tree by recursing ever deeper.  And
                 * if it fails, we have to reset our parent's current state
                 * that we can try again after backing off.
                    sayNO;
                }
  
 +              if (scan->flags) {
 +                  /* Check whether we already were at this position.
 +                      Postpone detection until we know the match is not
 +                      *that* much linear. */
 +              if (!PL_reg_maxiter) {
 +                  PL_reg_maxiter = (PL_regeol - PL_bostr + 1) * (scan->flags>>4);
 +                  PL_reg_leftiter = PL_reg_maxiter;
 +              }
 +              if (PL_reg_leftiter-- == 0) {
 +                  I32 size = (PL_reg_maxiter + 7)/8;
 +                  if (PL_reg_poscache) {
 +                      if (PL_reg_poscache_size < size) {
 +                          Renew(PL_reg_poscache, size, char);
 +                          PL_reg_poscache_size = size;
 +                      }
 +                      Zero(PL_reg_poscache, size, char);
 +                  }
 +                  else {
 +                      PL_reg_poscache_size = size;
 +                      Newz(29, PL_reg_poscache, size, char);
 +                  }
 +                  DEBUG_r(
 +                      PerlIO_printf(Perl_debug_log,
 +            "%sDetected a super-linear match, switching on caching%s...\n",
 +                                    PL_colors[4], PL_colors[5])
 +                      );
 +              }
 +              if (PL_reg_leftiter < 0) {
 +                  I32 o = locinput - PL_bostr, b;
 +
 +                  o = (scan->flags & 0xf) - 1 + o * (scan->flags>>4);
 +                  b = o % 8;
 +                  o /= 8;
 +                  if (PL_reg_poscache[o] & (1<<b)) {
 +                  DEBUG_r(
 +                      PerlIO_printf(Perl_debug_log,
 +                                    "%*s  already tried at this position...\n",
 +                                    REPORT_CODE_OFF+PL_regindent*2, "")
 +                      );
 +                      sayNO;
 +                  }
 +                  PL_reg_poscache[o] |= (1<<b);
 +              }
 +              }
 +
                /* Prefer next over scan for minimal matching. */
  
                if (cc->minmod) {
diff --combined util.c
--- 1/util.c
--- 2/util.c
+++ b/util.c
@@@ -1783,7 -1783,7 +1783,7 @@@ Perl_vwarner(pTHX_ U32  err, const char
  }
  
  #ifndef VMS  /* VMS' my_setenv() is in VMS.c */
 -#if !defined(WIN32) && !defined(CYGWIN32)
 +#if !defined(WIN32) && !defined(CYGWIN)
  void
  Perl_my_setenv(pTHX_ char *nam, char *val)
  {
  #endif  /* PERL_USE_SAFE_PUTENV */
  }
  
 -#else /* WIN32 || CYGWIN32 */
 -#if defined(CYGWIN32)
 +#else /* WIN32 || CYGWIN */
 +#if defined(CYGWIN)
  /*
   * Save environ of perl.exe, currently Cygwin links in separate environ's
   * for each exe/dll.  Probably should be a member of impure_ptr.
@@@ -2547,7 -2547,7 +2547,7 @@@ Perl_my_pclose(pTHX_ PerlIO *ptr
  }
  #endif /* !DOSISH */
  
 -#if  !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
 +#if  !defined(DOSISH) || defined(OS2) || defined(WIN32)
  I32
  Perl_wait4pid(pTHX_ int pid, int *statusp, int flags)
  {
@@@ -2776,24 -2776,22 +2776,22 @@@ Perl_same_dirent(pTHX_ char *a, char *b
  }
  #endif /* !HAS_RENAME */
  
- UV
+ NV
  Perl_scan_bin(pTHX_ char *start, I32 len, I32 *retlen)
  {
      register char *s = start;
-     register UV retval = 0;
-     register UV n;
-     register I32 d = 0;
+     register NV rnv = 0.0;
+     register UV ruv = 0;
      register bool seenb = FALSE;
-     register bool overflow = FALSE;
+     register bool overflowed = FALSE;
  
      for (; len-- && *s; s++) {
        if (!(*s == '0' || *s == '1')) {
            if (*s == '_')
-               continue;
-           if (seenb == FALSE && *s == 'b' && retval == 0) {
+               continue; /* Note: does not check for __ and the like. */
+           if (seenb == FALSE && *s == 'b' && ruv == 0) {
                /* Disallow 0bbb0b0bbb... */
                seenb = TRUE;
-               d = 0; /* Forget any leading zeros before the 'b'. */
                continue;
            }
            else {
                break;
            }
        }
-       n = retval << 1;
-       overflow |= (n >> 1) != retval;
-       retval = n | (*s - '0');
-       d++;
+       if (!overflowed) {
+           register UV xuv = ruv << 1;
+           if ((xuv >> 1) != ruv) {
+               dTHR;
+               overflowed = TRUE;
+               rnv = (NV) ruv;
+               if (ckWARN_d(WARN_UNSAFE))
+                   Perl_warner(aTHX_ WARN_UNSAFE,
+                               "Integer overflow in binary number");
+           } else
+               ruv = xuv | (*s - '0');
+       }
+       if (overflowed) {
+           rnv *= 2;
+           /* If an NV has not enough bits in its mantissa to
+            * represent an UV this summing of small low-order numbers
+            * is a waste of time (because the NV cannot preserve
+            * the low-order bits anyway): we could just remember when
+            * did we overflow and in the end just multiply rnv by the
+            * right amount. */
+           rnv += (*s - '0');
+       }
      }
-     if (sizeof(UV) > 4 && d > 32) {
+     if (!overflowed)
+       rnv = (NV) ruv;
+     if (   ( overflowed && rnv > 4294967295.0)
+ #if UV_SIZEOF > 4
+       || (!overflowed && ruv > 0xffffffff  )
+ #endif
+       ) { 
        dTHR;
        if (ckWARN(WARN_UNSAFE))
            Perl_warner(aTHX_ WARN_UNSAFE,
                        "Binary number > 0b11111111111111111111111111111111 non-portable");
      }
-     if (overflow)
-       Perl_croak(aTHX_ "Integer overflow in binary number");
      *retlen = s - start;
-     return retval;
+     return rnv;
  }
- UV
+ NV
  Perl_scan_oct(pTHX_ char *start, I32 len, I32 *retlen)
  {
      register char *s = start;
-     register UV retval = 0;
-     register UV n;
-     register I32 d = 0;
-     register bool overflow = FALSE;
+     register NV rnv = 0.0;
+     register UV ruv = 0;
+     register bool overflowed = FALSE;
  
      for (; len-- && *s; s++) {
        if (!(*s >= '0' && *s <= '7')) {
            if (*s == '_')
-               continue;
+               continue; /* Note: does not check for __ and the like. */
            else {
                /* Allow \octal to work the DWIM way (that is, stop scanning
                 * as soon as non-octal characters are seen, complain only iff
                break;
            }
        }
-       n = retval << 3;
-       overflow |= (n >> 3) != retval;
-       retval = n | (*s - '0');
-       d++;
+       if (!overflowed) {
+           register UV xuv = ruv << 3;
+           if ((xuv >> 3) != ruv) {
+               dTHR;
+               overflowed = TRUE;
+               rnv = (NV) ruv;
+               if (ckWARN_d(WARN_UNSAFE))
+                   Perl_warner(aTHX_ WARN_UNSAFE,
+                               "Integer overflow in octal number");
+           } else
+               ruv = xuv | (*s - '0');
+       }
+       if (overflowed) {
+           rnv *= 8.0;
+           /* If an NV has not enough bits in its mantissa to
+            * represent an UV this summing of small low-order numbers
+            * is a waste of time (because the NV cannot preserve
+            * the low-order bits anyway): we could just remember when
+            * did we overflow and in the end just multiply rnv by the
+            * right amount of 8-tuples. */
+           rnv += (NV)(*s - '0');
+       }
      }
-     if (sizeof(UV) > 4 && d > 10 && (retval >> 30) > 3) {
+     if (!overflowed)
+       rnv = (NV) ruv;
+     if (   ( overflowed && rnv > 4294967295.0)
+ #if UV_SIZEOF > 4
+       || (!overflowed && ruv > 0xffffffff  )
+ #endif
+       ) {
        dTHR;
        if (ckWARN(WARN_UNSAFE))
            Perl_warner(aTHX_ WARN_UNSAFE,
                        "Octal number > 037777777777 non-portable");
      }
-     if (overflow)
-       Perl_croak(aTHX_ "Integer overflow in octal number");
      *retlen = s - start;
-     return retval;
+     return rnv;
  }
  
- UV
+ NV
  Perl_scan_hex(pTHX_ char *start, I32 len, I32 *retlen)
  {
      register char *s = start;
-     register UV retval = 0;
-     char *tmp = s;
-     register UV n;
-     register I32 d = 0;
+     register NV rnv = 0.0;
+     register UV ruv = 0;
      register bool seenx = FALSE;
-     register bool overflow = FALSE;
+     register bool overflowed = FALSE;
+     char *hexdigit;
  
-     while (len-- && *s) {
-       tmp = strchr((char *) PL_hexdigit, *s++);
-       if (!tmp) {
-           if (*(s-1) == '_')
-               continue;
-           if (seenx == FALSE && *(s-1) == 'x' && retval == 0) {
+     for (; len-- && *s; s++) {
+       hexdigit = strchr((char *) PL_hexdigit, *s);
+       if (!hexdigit) {
+           if (*s == '_')
+               continue; /* Note: does not check for __ and the like. */
+           if (seenx == FALSE && *s == 'x' && ruv == 0) {
                /* Disallow 0xxx0x0xxx... */
                seenx = TRUE;
-               d = 0; /* Forget any leading zeros before the 'x'. */
                continue;
            }
            else {
                dTHR;
-               --s;
                if (ckWARN(WARN_UNSAFE))
                    Perl_warner(aTHX_ WARN_UNSAFE,
                                "Illegal hexadecimal digit '%c' ignored", *s);
                break;
            }
        }
-       d++;
-       n = retval << 4;
-       overflow |= (n >> 4) != retval;
-       retval = n | ((tmp - PL_hexdigit) & 15);
+       if (!overflowed) {
+           register UV xuv = ruv << 4;
+           if ((xuv >> 4) != ruv) {
+               dTHR;
+               overflowed = TRUE;
+               rnv = (NV) ruv;
+               if (ckWARN_d(WARN_UNSAFE))
+                   Perl_warner(aTHX_ WARN_UNSAFE,
+                               "Integer overflow in hexadecimal number");
+           } else
+               ruv = xuv | ((hexdigit - PL_hexdigit) & 15);
+       }
+       if (overflowed) {
+           rnv *= 16.0;
+           /* If an NV has not enough bits in its mantissa to
+            * represent an UV this summing of small low-order numbers
+            * is a waste of time (because the NV cannot preserve
+            * the low-order bits anyway): we could just remember when
+            * did we overflow and in the end just multiply rnv by the
+            * right amount of 16-tuples. */
+           rnv += (NV)((hexdigit - PL_hexdigit) & 15);
+       }
      }
-     if (sizeof(UV) > 4 && d > 8) {
+     if (!overflowed)
+       rnv = (NV) ruv;
+     if (   ( overflowed && rnv > 4294967295.0)
+ #if UV_SIZEOF > 4
+       || (!overflowed && ruv > 0xffffffff  )
+ #endif
+       ) { 
        dTHR;
        if (ckWARN(WARN_UNSAFE))
            Perl_warner(aTHX_ WARN_UNSAFE,
                        "Hexadecimal number > 0xffffffff non-portable");
      }
-     if (overflow)
-       Perl_croak(aTHX_ "Integer overflow in hexadecimal number");
      *retlen = s - start;
-     return retval;
+     return rnv;
  }
  
  char*