-
-
01 Jan 2017 21:24:12 UTC
- Distribution: POD2-ES
- Source (raw)
- Browse (raw)
- Changes
- How to Contribute
- Repository
- Issues
- Testers (586 / 0 / 0)
- Kwalitee
Bus factor: 0- License: perl_5
- Activity
24 month- Tools
- Download (323.86KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
and 1 contributors- Equipo de Perl en Español
- Dependencies
- POD2::Base
- Pod::Perldoc
- Test::More
- and possibly others
- Reverse dependencies
- CPAN Testers List
- Dependency graph
NAME
perlhacktut - Tutorial de creación de un parche sencillo de código C
DESCRIPCIÓN
Este documento describe la creación de un parche sencillo.
Si todavía no ha leído perlhack, es lo primero que debe hacer. También debería leer perlsource.
Por último, consulte perlhacktips.
EJEMPLO DE PARCHE SENCILLO
Vamos a crear un parche sencillo de principio a fin.
Para ello, nos ocuparemos de implementar algo que propuso Larry: si el primer formato activo en una instrucción
pack
esU
(por ejemplo,pack "U3C8", @algo
), entonces la cadena resultante debería tratarse como codificada en UTF-8.Si trabaja con un clon del repositorio git de Perl, tendrá que crear una rama para incorporar sus cambios. Esto facilitará la creación de parches. Encontrará más información en perlgit.
Escribir el parche
¿Cómo nos preparamos para corregir esto? Primero tenemos que buscar el código en cuestión. La función
pack
se usa en tiempo de ejecución, por lo que estará en uno de los archivos pp. Como sospechábamos,pp_pack
está en pp.c. Puesto que vamos a modificar este archivo, antes creamos una copia y le asignamos el nombre pp.c~.[Bueno, estaba en pp.c en el momento de redactar este tutorial. Ahora se ha escindido de
pp_unpack
en su propio archivo, pp_pack.c]Echemos un vistazo a
pp_pack
: tenemos un patrón enpat
y un bucle que recorre el patrón y pasa de uno en uno los caracteres de formato adatum_type
. Luego, para cada carácter de formato posible, se consumen los demás argumentos del patrón (un ancho de campo, un asterisco, etc.) y se convierte el siguiente fragmento de entrada al formato especificado, agregándolo al SV de salida,cat
.¿Cómo sabemos si la
U
es el primer formato enpat
? Si tenemos un puntero al comienzo depat
y vemos unaU
, podemos comprobar si aún estamos en el principio de la cadena. Aquí es donde se establecepat
:STRLEN fromlen; char *pat = SvPVx(*++MARK, fromlen); char *patend = pat + fromlen; I32 len; I32 datumtype; SV *fromstr;
Tendremos ahí otro puntero de cadena:
STRLEN fromlen; char *pat = SvPVx(*++MARK, fromlen); char *patend = pat + fromlen; + char *patcopy; I32 len; I32 datumtype; SV *fromstr;
Justo antes de empezar el bucle, se establece
patcopy
como comienzo depat
:items = SP - MARK; MARK++; sv_setpvn(cat, "", 0); + patcopy = pat; while (pat < patend) {
Ahora bien, si vemos una
U
al principio de la cadena, activamos la marcaUTF8
para el SV de salida,cat
:+ if (datumtype == 'U' && pat==patcopy+1) + SvUTF8_on(cat); if (datumtype == '#') { while (pat < patend && *pat != '\n') pat++;
Recuerde que tiene que ser
patcopy+1
, ya que el primer carácter de la cadena es laU
consumida pordatumtype
.Vaya, nos olvidamos de una cosa: ¿qué pasa si hay espacios al principio del patrón?
pack(" U*", @algo)
tendráU
como primer carácter activo, pero no es el primer carácter del patrón. En este caso, tenemos que incrementarpatcopy
junto conpat
cuando veamos espacios:if (isSPACE(datumtype)) continue;
debe convertirse en
if (isSPACE(datumtype)) { patcopy++; continue; }
Muy bien. Ya hemos corregido el código C. Ahora tenemos que hacer dos cosas más para terminar de preparar el parche: hemos cambiado el comportamiento de Perl, por lo que debemos documentar el cambio. También tenemos que proporcionar pruebas de regresión adicionales para asegurarnos de que nuestro parche funciona y no crea ningún error en otro lugar.
Comprobar el parche
Las pruebas de regresión para cada operador se encuentran en t/op/, así que hacemos una copia de t/op/pack.t en t/op/pack.t~. Ahora podemos agregar nuestras pruebas al final. En primer lugar, comprobaremos que
U
crea realmente cadenas Unicode.t/op/pack.t tiene una función ok() adecuada, pero si no la tuviera, podríamos usar la de t/test.pl.
require './test.pl'; plan( tests => 159 );
así que en vez de esto:
print 'not ' unless "1.20.300.4000" eq sprintf "%vd", pack("U*",1,20,300,4000); print "ok $test\n"; $test++;
podemos escribir una prueba más apropiada (en Test::More encontrará una descripción completa de is() y otras funciones para realizar pruebas):
is( "1.20.300.4000", sprintf "%vd", pack("U*",1,20,300,4000), "U* produce Unicode" );
Ahora comprobamos que la comprobación de espacio inicial es correcta:
is( "1.20.300.4000", sprintf "%vd", pack(" U*",1,20,300,4000), " con espacios al principio" );
Por último, vamos a comprobar que no creamos cadenas Unicode si
U
no es el primer formato activo:isnt( v1.20.300.4000, sprintf "%vd", pack("C0U*",1,20,300,4000), "U* no es el primer formato, así que no es Unicode" );
No hay que olvidarse de actualizar el número de pruebas especificado al principio del código, para que el programa de ejecución automática de pruebas no se confunda. Será algo así:
print "1..156\n";
o bien:
plan( tests => 156 );
Ahora compilamos Perl y ejecutamos la serie de pruebas. ¡Pruebas nuevas superadas! ¡Viva!
Documentar el parche
Por último, falta la documentación. Para acabar el trabajo no queda más remedio que ocuparse del papeleo, así que vamos a describir el cambio que acabamos de hacer. El lugar correspondiente es pod/perlfunc.pod. Una vez más, hacemos antes una copia de seguridad y después insertamos el texto siguiente en la descripción de
pack
:=item * Si el patrón comienza con una C<U>, la cadena resultante se tratará como caracteres Unicode codificados en UTF-8. Puede forzar la aplicación de una codificación UTF-8 en una cadena con C<U0> al principio, y los bytes que siguen se interpretarán como caracteres Unicode. Si no desea que ocurra esto, puede comenzar el patrón con C<C0> (o cualquier otra cosa) para evitar que Perl fuerce la codificación en UTF-8 de la cadena, y luego continuar con C<U*> en algún lugar del patrón.
Enviar
Vea perlhack para obtener más información sobre cómo enviar este parche.
AUTOR
Actualmente la lista de correo perl5-porters se encarga de actualizar este documento redactado originalmente por Nathan Torkington.
TRADUCTORES
Joaquín Ferrero (Tech Lead)
Enrique Nell (Language Lead)
Module Install Instructions
To install POD2::ES, copy and paste the appropriate command in to your terminal.
cpanm POD2::ES
perl -MCPAN -e shell install POD2::ES
For more information on module installation, please visit the detailed CPAN module installation guide.