/* * $Id$ */ /* * Las siguientes partes son derechos adquiridos de sus autores individuales. * www - http://www.harbour-project.org * * Copyright 2001 Antonio Linares * Documentaci¢n en Ingl‚s * * Copyright 2001 Alejandro de G rate * Traducci¢n al Espa¤ol de pcode.txt * * Vea doc/license.txt por los t‚rminos de la licencia. * */ El OBJ de Clipper y el modelo pcode (GNU|Open|Clipper project) ============================================================== Consideremos el siguiente ejemplo de Clipper, test.prg: function Main() ? "Hola mundo!" return nil Una vez que esto se compila dentro de un OBJ, qu‚ es lo que hay dentro de ‚l ? En efecto, lo que nosostros tenemos es un equivalente a la siguiente aplicaci¢n de lenguaje C: SYMBOL symbols[] = { ... }; void MAIN( void ) { BYTE pcode[] = { ... }; VirtualMachine( pcode, symbols ); } B sicamente, el c¢digo fuente de test.prg ha sido convertido en una secuencia de bytes pcode contenidos en el array pcode[] = {...} Todo lo que nuestra funci¢n MAIN hace es invocar, en tiempo de ejecuci¢n a la funci¢n de VirtualMachine() que procesar  aquellos bytes de pcodes. Vamos a revisar la estructura de pcodes de test.prg con m s detalle: 0000 (2A) LINE 0 2A 00 00 0003 (2A) LINE 3 2A 03 00 0006 (13) SYMF [QOUT] 13 02 00 0009 (01) PUSHC "Hello world!" 01 ... 0018 (27) DO(1) 27 01 00 001B (2A) LINE 5 2A 05 00 001E (7B) UNDEF 7B 001F (79) SAVE_RET 79 0020 (1E) JMP 0023 1E 00 00 0023 (60) ENDPROC 60 Nosotros podemos definir un archivo hbpcode.h para leer mejor aquellos pcode: ---------------------- hbpcode.h #define LINE 0x2A #define SYMF 0x13 #define PUSHC 0x01 #define DO 0x27 #define UNDEF 0x7B ... ---------------------- As¡ finalmente esto quedar¡a como: BYTE pcode[] = { LINE, 0, 0, LINE, 3, 0, SYMF, 2, 0, PUSHC, 'H', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o', '!', '0', DO, 1, 0, LINE, 5, 0, UNDEF, SAVE_RET, JMP, 0, 0, ENDPROC }; Y qu‚ es SYMBOL symbols[] ? Cliper crea una tabla de s¡mbolos en el archivo OBJ que luego ser  usada para crear una tabla din mica de s¡mbolos compartida por la aplicaci¢n entera. cada uno de esos s¡mbolos tiene la siguiente estructura: typedef struct { char * szName; // Clipper de hecho mantiene un array aqu¡ (11 bytes) BYTE bScope; LPVOID pVoid; } SYMBOL; #define PUBLIC 0 // el alcance de la funci¢n ! SYMBOL symbols[] = { { "MAIN", PUBLIC, MAIN }, { "QQOUT", PUBLIC, QQOUT } }; Recordemos que el nombre de una funci¢n (MAIN, QQOUT) es la direcci¢n de la funci¢n, as¡ nuestra tabla de s¡mbolos estar  lista para usarla para saltar y ejecutar cualquier funci¢n enlazada (linkeada). De hecho, el pcode SYMF 2, 0 en nuestro ejemplo, instruir  a la funci¢n VirtualMachine(), para usar el 2do s¡mbolo que es QQOUT. Vamos a leer el pcode: LINE 0, 0 => Nosotros estamos ubicados en la l¡nea 0 LINE 3, 0 => Nosotros estamos ubicados en la l¡nea 3 SYMF 2, 0 => Vamos a llamar a QQOUT desde nuestra tabla de s¡mbolos PUSHC ... => Esta cadena va a ser usada como un par metro DO 1, 0 => ok, saltemos a QQOUT y recordemos que le dimos 1 par metro LINE 5, 0 => Estamos de vuelta desde QQOUT y estamos ubicados en l¡nea 5 UNDEF => Nosotros vamos a retornar este valor (NIL) SAVE_RET => Ok, retornemoslo JMP 0 => No saltamos dondequiera, continuamos con el pr¢ximo pcode ENDPROC => Es el fin. hemos completado la ejecuci¢n de esta funci¢n Todas estas funciones ser n evaluadas desde nuestra funci¢n VirtualMachine(), (Clipper la llama _plankton() ). Todas las funciones terminan usando ENDPROC, as¡ cuando VirtualMachine() encuentra ENDPROC sabe que ha alcanzado el final de una funci¢n pcode. Ahora que nosotros entendemos claramente el modelo b sico, nosotros estamos en condiciones de comenzar a implementar "reglas de producci¢n" en nuestra sintaxis yacc (harbour.y) para generar el archivo de salida espec¡fico (test.c) con la estructura de arriba (¢ nosotros podemos f cilmente generar el archivo OBJ para ‚l). Continuar ... Antonio Linares