141 lines
4.3 KiB
Plaintext
141 lines
4.3 KiB
Plaintext
|
|
/*
|
|
* 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 <alex_degarate@hotmail.com>
|
|
* 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
|
|
|
|
|