From 567255b3e2e0fb0e1b6fcc4e7b809b28dbd6ad9d Mon Sep 17 00:00:00 2001
From: Father Chrysostomos <sprout@cpan.org>
Date: Tue, 24 Mar 2015 22:02:11 -0700
Subject: Update OOK example in perlguts

It was not just the COW changes that needed to be accounted for, but
also the change in the storage of the offset.  The latter changed hap-
pened in 5.12, I think.

(cherry picked from commit f942a0dfa923e36f91c00b44e21563cd50dc750b)

Bug: https://rt.perl.org/Ticket/Display.html?id=122322
Bug-Debian: https://bugs.debian.org/822336
Patch-Name: fixes/5.20.3/docs/ook_example.diff
---
 pod/perlguts.pod | 38 ++++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/pod/perlguts.pod b/pod/perlguts.pod
index d845010e7..61468bc51 100644
--- a/pod/perlguts.pod
+++ b/pod/perlguts.pod
@@ -323,22 +323,40 @@ Hence, at this point, the start of the buffer that we allocated lives
 at C<SvPVX(sv) - SvIV(sv)> in memory and the PV pointer is pointing
 into the middle of this allocated storage.
 
-This is best demonstrated by example:
+This is best demonstrated by example.  Normally copy-on-write will prevent
+the substitution from operator from using this hack, but if you can craft a
+string for which copy-on-write is not possible, you can see it in play.  In
+the current implementation, the final byte of a string buffer is used as a
+copy-on-write reference count.  If the buffer is not big enough, then
+copy-on-write is skipped.  First have a look at an empty string:
+
+  % ./perl -Ilib -MDevel::Peek -le '$a=""; $a .= ""; Dump $a'
+  SV = PV(0x7ffb7c008a70) at 0x7ffb7c030390
+    REFCNT = 1
+    FLAGS = (POK,pPOK)
+    PV = 0x7ffb7bc05b50 ""\0
+    CUR = 0
+    LEN = 10
+
+Notice here the LEN is 10.  (It may differ on your platform.)  Extend the
+length of the string to one less than 10, and do a substitution:
 
-  % ./perl -Ilib -MDevel::Peek -le '$a="12345"; $a=~s/.//; Dump($a)'
-  SV = PVIV(0x8128450) at 0x81340f0
+  % ./perl -Ilib -MDevel::Peek -le '$a=""; $a.="123456789"; $a=~s/.//; Dump($a)'
+  SV = PV(0x7ffa04008a70) at 0x7ffa04030390
     REFCNT = 1
     FLAGS = (POK,OOK,pPOK)
-    IV = 1  (OFFSET)
-    PV = 0x8135781 ( "1" . ) "2345"\0
-    CUR = 4
-    LEN = 5
+    OFFSET = 1
+    PV = 0x7ffa03c05b61 ( "\1" . ) "23456789"\0
+    CUR = 8
+    LEN = 9
 
-Here the number of bytes chopped off (1) is put into IV, and
-C<Devel::Peek::Dump> helpfully reminds us that this is an offset.  The
+Here the number of bytes chopped off (1) is shown next as the OFFSET.  The
 portion of the string between the "real" and the "fake" beginnings is
 shown in parentheses, and the values of C<SvCUR> and C<SvLEN> reflect
-the fake beginning, not the real one.
+the fake beginning, not the real one.  (The first character of the string
+buffer happens to have changed to "\1" here, not "1", because the current
+implementation stores the offset count in the string buffer.  This is
+subject to change.)
 
 Something similar to the offset hack is performed on AVs to enable
 efficient shifting and splicing off the beginning of the array; while
