Publicidad

sábado, 15 de noviembre de 2008

M4???

Hola!!!
No supe como subir la presentación aquí les dejo mejor la información si es que les quedó duda sale:
Introducción a M4

Para las personas a las que nos da pereza escribir demasiado nos gusta descubrir formas de que el ordenador escriba por nosotros. Una de ellas es usando M4.
¿Qué es M4?
M4 es un procesador de macros. Por macros se entiende expansiones de texto. Para entender esto basta recordar el conocido procesador de macros CPP utilizado en todas las suites de compiladores de C.
Todo el que ha programado en C sabe utilizar el CPP. Se sabe que usando #define SUMA(a, b) (a) + (b), antes de compilar se procesará todo el fichero fuente buscando SUMA(talo, cualo) para ser substituido por (talo) + (cualo). M4 tiene la misma función, la diferencia está en que utiliza un lenguaje de macros diferente y de propósito general; lo cual resulta más potente.
Funcionamiento
Si ejecutáis el comando m4 (o gm4 si estáis con *BSD y queréis usar GNU M4, BSD trae su propio procesador M4 para la configuración del sendmail) sin argumentos el comando espera texto por la entrada estándar. Tras cada línea introducida, ésta se procesa y se imprime el resultado por la salida estándar. También se puede usar con tuberías y, si como argumentos le pasáis nombres de ficheros, éstos se procesan de forma secuencial imprimiendo el resultado por la salida estándar.
Utilidades de M4
La mayor utilidad que se le ha dado a M4 ha sido en las famosas autotools de GNU (autoconf, automake, etc). Realmente el procesador de M4 se limita a substituir ciertas cadenas de texto por otras (a lo que llamaremos expansión), así podemos usarlo para tantas situaciones como nuestra imaginación nos permita. Otro ejemplo es utilizar M4 para escribir páginas web, creando una abstracción por encima del HTML.
Introducción a la sintaxis de M4
De M4 lo único que cuesta aprender es la forma de expansión que lleva a cabo al encontrar una macro. A pesar de ello el manual oficial lo explica todo muy bien. Pero como en todo se aprende y se entiende practicando.
Utilización de macros
Para utilizar una macro basta con escribir su nombre. Si tenemos que utilizar parámetros en dicha macro los rodearemos por paréntesis. Por ejemplo, si tenemos la macro CANTINFLAS la podemos utilizar escribiendo su nombre en una palabra por sí misma. Las siguientes líneas expanden la macro CANTINFLAS:CANTINFLASHola señor CANTINFLASHola señor CANTINFLAS()puntoycoma.Hola señor CANTINFLAS(punto, y, coma).Hola señor CANTINFLAS(punto y coma).
Las dos primeras expanden la macro sin argumentos, la tercera expande la macro con el argumento de cadena vacía (se consigue escribiendo un quoteado vacío `'), la cuarta expande la macro con tres argumentos y la quinta expande la macro con un argumento.
Las siguientes líneas NO expanden la macro CANTINFLAS:eseCANTINFLASpoderosoCANTINFLASilloantiCANTINFLAS()
Definición de macros
La macro más esencial que necesitamos es aquella que nos permite definir nuevas macros. Esta macro se llama define; que admite dos argumentos: el primero es el nombre de la nueva macro y el segundo es el texto por el que será reemplazada cada aparición de dicha macro. Es la misma idea que los #define del CPP. Veamos unos ejemplos:define(`CANTINFLAS', `Bigote arrocet')define(`BOLD', `$1')define(HOLA, Hola mundo cruel)
Así, cada vez que se encuentre CANTINFLAS será substituido por Bigote arrocet, de la misma forma que cada vez que se encuentre HOLA se expandirá en Hola mundo cruel.
El $1 se expande por el primer argumento que se le pase a la macro. Por lo que si escribimos BOLD(hola) será substituido por hola. Pasa lo mismo para $2, $3, etc...
También se puede usar $0 que se expande como el nombre de la macro. Después tenemos $* que expande todos los argumentos separados por comas y $@ que hace lo mismo pero además quotea el resultado para evitar expansiones del mismo. La cadena $# se expande como el número de argumentos pasados a la macro.
IMPORTANTE: El uso de $1, $@ y demás expansiones especiales únicamente funcionan dentro de la macro define. Si, dentro de una macro define, queréis que se expanda literalmente, por ejemplo, $@ tendréis que hacerlo escribiendo algo como $`'@. Como siempre, lo mejor es probar.
Comentarios
En M4 existen dos tipos de comentarios: los que se se omiten en el resultado de la expansión y los que no se interpretan pero pasan tal cual hacia la salida estándar. Probad esto con vuestro M4 y veréis la diferencia:dnl Comentario que no aparecerá en el resultado.# Comentario que sí aparecerá en el resultado
Quoteado o protección de cadenas de texto
Los delimitadores de cadenas, digamos, protegidas son ` y '. Pero es posible cambiarlos con la macro changequote. Voy a intentar explicar esto con cuidado pues es la clave para entender el funcionamiento de M4.
Cuando hablamos de una expansión nos referimos a dos cosas:
Expandir una macro o
Si se trata de un texto rodeado por ` ' simplemente se eliminan las comillas.
Si se ha dado el segundo caso no hacemos nada más. Pero el proceso de expansión de una macro es algo más sofisticado y, además, recursivo. Cuando M4 reconoce una macro procede a expandirla de la siguiente forma:
Expansión de los argumentos
Se procede a la substitución del texto
Se vuelve a procesar el resultado de esta expansión
Mucho ojo porque esto pasa para cada macro que se encuentra. Si resulta que mientras se expanden los argumentos de una macro se reconoce otra macro se realiza este mismo proceso para esta última. He aquí la importancia de saber proteger el texto quoteándolo. Así pues, para la inclusión de cadenas literales en el argumento de una macro basta con rodearla de comillas dobles, como por ejemplo:define(`CANTINFLAS', `$1')Hola señor CANTINFLAS(``Y esto aparece tal cual, metamos lo quemetamos'')
El procedimiento sería el siguiente. Se reconoce la macro define por lo que se expanden sus argumentos. Como los argumentos estaban quoteados, se quitan las comillas y no se produce ninguna expansión extra. Esta macro se expande en la cadena vacía `'.
Posteriormente se encuentra la macro CANTINFLAS (previamente definida) y se procede a su expansión. Se expande su argumento (que estaba protegido) por lo que se le quitan las comillas externas. La expansión de la macro produce dicho argumento tal cual fue expandido, es decir, `Y esto aparece tal cual, metamos lo que metamos'. Tras esto se vuelve a procesar este texto resultante por lo que se vuelven a eliminar las comillas quedando el texto literal.
Nótese que si se encuentra una macro mientras se procesaba otra (paso 3), se vuelve a llevar a cabo todo el proceso de expansión sobre aquella. Para aprender mejor este proceso os recomiendo que hagáis las siguientes pruebas:define(`echo1', `$*')define(`echo2', `$@')define(`echo3', `$1')echo3(`echo2(una, `prueba')'), tonta)echo3(echo1(`echo2(una)', `prueba'), `tonta')echo2(`echo1(echo3(una))', echo2(`prueba', tonta))
...y así sucesivamente.
Ramificaciones
Con M4 es posible retrasar la salida de texto gracias a las ramificaciones (en inglés: diversions). Cuando cambiamos de ramificación el texto generado se guarda temporalmente para ser expulsado por nosotros manualmente o automáticamente al final. Las macros involucradas en éste proceso son divert y undivert. Ambas aceptan un único parámetro numérico que es el número de ramificación.
La ramificación por defecto es la número 0. Cuando cambiamos de rama con divert e introducimos texto éste se guarda en la rama correspondiente. Cuando se acaba la entrada estándar es expulsado por orden ascendente de ramificación. A no ser que lo expulsemos nosotros manualmente con undivert. Vamos a ver algunos ejemplos.Aquí pongo texto normaldivert(2)Éste texto se ramifica por la rama 2.divert(3)Hola hola ésto es la ramificación divnum !!!divert(1)Éste texto se ramifica por la rama 1 pero aparece antes que el de larama 2.divert(0)Volvemos a la salida estándar.undivert(3)divert(-1)Éste texto NO APARECE en la salida
En realidad divert se expande en la cadena vacía pero cambia la ramificación actual. Sin embargo undivert se expande por el texto almacenado en la rama indicada. Hay otra macro relacionada llamada divnum que no necesita argumentos y que se expande por el número de ramificación actual.
Notas finales
Si necesitamos que una macro se expanda entre texto que no está separado por espacios podemos usar la cadena vacía `'. Por ejemplo:ese`'CANTINFLAS`'poderosoanti`'CANTINFLAS()
También mencionar que M4 tiene macros para implementar condicionales, como ifdef e ifelse. Pero realmente os recomiendo echarle un vistazo al manual que es muy completo salvo por la explicación de la expansión.
Finalmente, quiero hacer notar de que M4 no es un lenguaje de programación sino un procesador de macros. Simplemente se limita a reconocer y expandir macros. En el manual hay un ejemplo de como implementar un bucle (de forma recursiva) pero como ejemplo ilustrativo. Si tenéis ganas de ver M4 en su máximo esplendor echadle un vistazo a los ficheros .m4 de las distribuciones de autoconf y automake.
6.18.1. Instalación de M4
Prepara M4 para su compilación: ./configure --prefix=/usr
Compila el paquete: make
Para comprobar los resultados, ejecuta: make check.
Instala el paquete: make install
6.18.2. Contenido de M4
Programa instalado: m4
Descripción corta
m4
Copia los ficheros dados expandiendo en el proceso las macros que contengan. Estas macros pueden ser internas o definidas por el usuario y pueden tomar cualquier número de argumentos. Además de hacer la expansión de macros, m4 tiene funciones internas para incluir los ficheros indicados, lanzar comandos UNIX, hacer aritmética entera, manipular texto de diversas formas, recursión, etc. El programa m4 puede ser usado como interfaz para un compilador o como procesador de macros por sí mismo.

No hay comentarios: