diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/pods/perlhacktut.pod')
-rw-r--r-- | Master/tlpkg/tlperl/lib/pods/perlhacktut.pod | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/Master/tlpkg/tlperl/lib/pods/perlhacktut.pod b/Master/tlpkg/tlperl/lib/pods/perlhacktut.pod deleted file mode 100644 index 33a9ef23e8d..00000000000 --- a/Master/tlpkg/tlperl/lib/pods/perlhacktut.pod +++ /dev/null @@ -1,188 +0,0 @@ -=encoding utf8 - -=for comment -Consistent formatting of this file is achieved with: - perl ./Porting/podtidy pod/perlhacktut.pod - -=head1 NAME - -perlhacktut - Walk through the creation of a simple C code patch - -=head1 DESCRIPTION - -This document takes you through a simple patch example. - -If you haven't read L<perlhack> yet, go do that first! You might also -want to read through L<perlsource> too. - -Once you're done here, check out L<perlhacktips> next. - -=head1 EXAMPLE OF A SIMPLE PATCH - -Let's take a simple patch from start to finish. - -Here's something Larry suggested: if a C<U> is the first active format -during a C<pack>, (for example, C<pack "U3C8", @stuff>) then the -resulting string should be treated as UTF-8 encoded. - -If you are working with a git clone of the Perl repository, you will -want to create a branch for your changes. This will make creating a -proper patch much simpler. See the L<perlgit> for details on how to do -this. - -=head2 Writing the patch - -How do we prepare to fix this up? First we locate the code in question -- the C<pack> happens at runtime, so it's going to be in one of the -F<pp> files. Sure enough, C<pp_pack> is in F<pp.c>. Since we're going -to be altering this file, let's copy it to F<pp.c~>. - -[Well, it was in F<pp.c> when this tutorial was written. It has now -been split off with C<pp_unpack> to its own file, F<pp_pack.c>] - -Now let's look over C<pp_pack>: we take a pattern into C<pat>, and then -loop over the pattern, taking each format character in turn into -C<datum_type>. Then for each possible format character, we swallow up -the other arguments in the pattern (a field width, an asterisk, and so -on) and convert the next chunk input into the specified format, adding -it onto the output SV C<cat>. - -How do we know if the C<U> is the first format in the C<pat>? Well, if -we have a pointer to the start of C<pat> then, if we see a C<U> we can -test whether we're still at the start of the string. So, here's where -C<pat> is set up: - - STRLEN fromlen; - register char *pat = SvPVx(*++MARK, fromlen); - register char *patend = pat + fromlen; - register I32 len; - I32 datumtype; - SV *fromstr; - -We'll have another string pointer in there: - - STRLEN fromlen; - register char *pat = SvPVx(*++MARK, fromlen); - register char *patend = pat + fromlen; - + char *patcopy; - register I32 len; - I32 datumtype; - SV *fromstr; - -And just before we start the loop, we'll set C<patcopy> to be the start -of C<pat>: - - items = SP - MARK; - MARK++; - sv_setpvn(cat, "", 0); - + patcopy = pat; - while (pat < patend) { - -Now if we see a C<U> which was at the start of the string, we turn on -the C<UTF8> flag for the output SV, C<cat>: - - + if (datumtype == 'U' && pat==patcopy+1) - + SvUTF8_on(cat); - if (datumtype == '#') { - while (pat < patend && *pat != '\n') - pat++; - -Remember that it has to be C<patcopy+1> because the first character of -the string is the C<U> which has been swallowed into C<datumtype!> - -Oops, we forgot one thing: what if there are spaces at the start of the -pattern? C<pack(" U*", @stuff)> will have C<U> as the first active -character, even though it's not the first thing in the pattern. In this -case, we have to advance C<patcopy> along with C<pat> when we see -spaces: - - if (isSPACE(datumtype)) - continue; - -needs to become - - if (isSPACE(datumtype)) { - patcopy++; - continue; - } - -OK. That's the C part done. Now we must do two additional things before -this patch is ready to go: we've changed the behaviour of Perl, and so -we must document that change. We must also provide some more regression -tests to make sure our patch works and doesn't create a bug somewhere -else along the line. - -=head2 Testing the patch - -The regression tests for each operator live in F<t/op/>, and so we make -a copy of F<t/op/pack.t> to F<t/op/pack.t~>. Now we can add our tests -to the end. First, we'll test that the C<U> does indeed create Unicode -strings. - -t/op/pack.t has a sensible ok() function, but if it didn't we could use -the one from t/test.pl. - - require './test.pl'; - plan( tests => 159 ); - -so instead of this: - - print 'not ' unless "1.20.300.4000" eq sprintf "%vd", - pack("U*",1,20,300,4000); - print "ok $test\n"; $test++; - -we can write the more sensible (see L<Test::More> for a full -explanation of is() and other testing functions). - - is( "1.20.300.4000", sprintf "%vd", pack("U*",1,20,300,4000), - "U* produces Unicode" ); - -Now we'll test that we got that space-at-the-beginning business right: - - is( "1.20.300.4000", sprintf "%vd", pack(" U*",1,20,300,4000), - " with spaces at the beginning" ); - -And finally we'll test that we don't make Unicode strings if C<U> is -B<not> the first active format: - - isnt( v1.20.300.4000, sprintf "%vd", pack("C0U*",1,20,300,4000), - "U* not first isn't Unicode" ); - -Mustn't forget to change the number of tests which appears at the top, -or else the automated tester will get confused. This will either look -like this: - - print "1..156\n"; - -or this: - - plan( tests => 156 ); - -We now compile up Perl, and run it through the test suite. Our new -tests pass, hooray! - -=head2 Documenting the patch - -Finally, the documentation. The job is never done until the paperwork -is over, so let's describe the change we've just made. The relevant -place is F<pod/perlfunc.pod>; again, we make a copy, and then we'll -insert this text in the description of C<pack>: - - =item * - - If the pattern begins with a C<U>, the resulting string will be treated - as UTF-8-encoded Unicode. You can force UTF-8 encoding on in a string - with an initial C<U0>, and the bytes that follow will be interpreted as - Unicode characters. If you don't want this to happen, you can begin - your pattern with C<C0> (or anything else) to force Perl not to UTF-8 - encode your string, and then follow this with a C<U*> somewhere in your - pattern. - -=head2 Submit - -See L<perlhack> for details on how to submit this patch. - -=head1 AUTHOR - -This document was originally written by Nathan Torkington, and is -maintained by the perl5-porters mailing list. |