HRB production added + runner.
Removed old file in tests/broken.
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
19990518-23:40 CET Eddie Runia
|
||||
* source/compiler/harbour.y
|
||||
GenPortObj added. Can be accessed through /gHRB
|
||||
generates portable object structure.
|
||||
* tests/broken/hrb.bat
|
||||
added. simple batch file for HRB compilation
|
||||
* tests/broken/runner.c
|
||||
added. runner program
|
||||
* tests/broken/run_exp.h
|
||||
added. runner include file containing 'exportable' functions.
|
||||
|
||||
19990518-17:30 EDT David G. Holm <dholm@jsd-llc.com>
|
||||
* source/rtl/console.c
|
||||
- Use pItem->wLength and pItem->wDec when printing numbers.
|
||||
|
||||
@@ -198,6 +198,7 @@ void GenCCode( char *, char * ); /* generates the C language output */
|
||||
void GenJava( char *, char * ); /* generates the Java language output */
|
||||
void GenPascal( char *, char * ); /* generates the Pascal language output */
|
||||
void GenRC( char *, char * ); /* generates the RC language output */
|
||||
void GenPortObj( char *, char * ); /* generates the portable objects */
|
||||
#ifdef OBJ_GENERATION
|
||||
void GenObj32( char *, char * ); /* generates OBJ 32 bits */
|
||||
#endif
|
||||
@@ -211,7 +212,8 @@ typedef enum
|
||||
LANG_C, /* C language (by default) <file.c> */
|
||||
LANG_JAVA, /* Java <file.java> */
|
||||
LANG_PASCAL, /* Pascal <file.pas> */
|
||||
LANG_RESOURCES /* Resources <file.rc> */
|
||||
LANG_RESOURCES, /* Resources <file.rc> */
|
||||
LANG_PORT_OBJ /* Portable objects <file.hrb> */
|
||||
} LANGUAGES; /* supported Harbour output languages */
|
||||
|
||||
extern int iLine; /* currently compiled source code line */
|
||||
@@ -1039,6 +1041,11 @@ int harbour_main( int argc, char * argv[] )
|
||||
_iLanguage = LANG_RESOURCES;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
_iLanguage = LANG_PORT_OBJ;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf( "\nUnsupported output language option\n" );
|
||||
exit( 1 );
|
||||
@@ -1200,6 +1207,12 @@ int harbour_main( int argc, char * argv[] )
|
||||
MakeFilename( szFileName, pFileName );
|
||||
GenRC( szFileName, pFileName->name );
|
||||
break;
|
||||
|
||||
case LANG_PORT_OBJ:
|
||||
pFileName->extension =".hrb";
|
||||
MakeFilename( szFileName, pFileName );
|
||||
GenPortObj( szFileName, pFileName->name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef OBJ_GENERATION
|
||||
@@ -3301,3 +3314,282 @@ char * strupr( char * p )
|
||||
return( p );
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SYM_NOLINK 0 /* Symbol does not have to be linked */
|
||||
#define SYM_FUNC 1 /* Defined function */
|
||||
#define SYM_EXTERN 2 /* Previously defined function */
|
||||
|
||||
void GenPortObj( char *szFileName, char *szName )
|
||||
{
|
||||
PFUNCTION pFunc = functions.pFirst, pFTemp;
|
||||
PCOMSYMBOL pSym = symbols.pFirst;
|
||||
WORD w, wLen, wSym, wVar;
|
||||
LONG lPCodePos;
|
||||
LONG lPad;
|
||||
LONG lSymbols;
|
||||
char chr;
|
||||
FILE * yyc; /* file handle for C output */
|
||||
|
||||
if( ! ( yyc = fopen( szFileName, "wb" ) ) )
|
||||
{
|
||||
printf( "Error opening file %s\n", szFileName );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ! _iQuiet )
|
||||
printf( "\ngenerating portable object file...\n" );
|
||||
|
||||
/* writes the symbol table */
|
||||
|
||||
if( ! _iStartProc )
|
||||
pSym = pSym->pNext; /* starting procedure is always the first symbol */
|
||||
|
||||
lSymbols = 0; /* Count number of symbols */
|
||||
while( pSym )
|
||||
{
|
||||
lSymbols++;
|
||||
pSym = pSym->pNext;
|
||||
}
|
||||
fputc( (BYTE) ( ( lSymbols ) & 255 ), yyc ); /* Write number symbols */
|
||||
fputc( (BYTE) ( ( lSymbols >> 8 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( lSymbols >> 16 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( lSymbols >> 24 ) & 255 ), yyc );
|
||||
|
||||
pSym = symbols.pFirst;
|
||||
if( ! _iStartProc )
|
||||
pSym = pSym->pNext; /* starting procedure is always the first symbol */
|
||||
|
||||
while( pSym )
|
||||
{
|
||||
fputs( pSym->szName, yyc );
|
||||
fputc( 0, yyc );
|
||||
if( pSym->cScope != FS_MESSAGE )
|
||||
fputc( pSym->cScope, yyc );
|
||||
else
|
||||
fputc( 0, yyc );
|
||||
|
||||
/* specify the function address if it is a defined function or a
|
||||
external called function */
|
||||
if( ( pFTemp = GetFunction( pSym->szName ) ) ) /* is it a defined function ? */
|
||||
{
|
||||
fputc( SYM_FUNC, yyc );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( pFTemp = GetFuncall( pSym->szName ) ) )
|
||||
{
|
||||
fputc( SYM_EXTERN, yyc );
|
||||
}
|
||||
else
|
||||
{
|
||||
fputc( SYM_NOLINK, yyc );
|
||||
}
|
||||
}
|
||||
pSym = pSym->pNext;
|
||||
}
|
||||
|
||||
pFunc = functions.pFirst;
|
||||
if( ! _iStartProc )
|
||||
pFunc = pFunc->pNext;
|
||||
|
||||
lSymbols = 0; /* Count number of symbols */
|
||||
while( pFunc )
|
||||
{
|
||||
lSymbols++;
|
||||
pFunc = pFunc->pNext;
|
||||
}
|
||||
fputc( (BYTE) ( ( lSymbols ) & 255 ), yyc ); /* Write number symbols */
|
||||
fputc( (BYTE) ( ( lSymbols >> 8 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( lSymbols >> 16 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( lSymbols >> 24 ) & 255 ), yyc );
|
||||
|
||||
/* Generate functions data
|
||||
*/
|
||||
pFunc = functions.pFirst;
|
||||
if( ! _iStartProc )
|
||||
pFunc = pFunc->pNext; /* No implicit starting procedure */
|
||||
|
||||
while( pFunc )
|
||||
{
|
||||
/* if( pFunc->cScope != FS_PUBLIC )
|
||||
fprintf( yyc, "static " ); */
|
||||
|
||||
fputs( pFunc->szName, yyc );
|
||||
fputc( 0, yyc );
|
||||
fputc( (BYTE) ( ( pFunc->lPCodePos ) & 255 ), yyc ); /* Write size */
|
||||
fputc( (BYTE) ( ( pFunc->lPCodePos >> 8 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( pFunc->lPCodePos >> 16 ) & 255 ), yyc );
|
||||
fputc( (BYTE) ( ( pFunc->lPCodePos >> 24 ) & 255 ), yyc );
|
||||
|
||||
printf( "Creating output for %s\n", pFunc->szName );
|
||||
|
||||
lPCodePos = 0;
|
||||
lPad = 0; /* Number of bytes optimized */
|
||||
while( lPCodePos < pFunc->lPCodePos )
|
||||
{
|
||||
switch( pFunc->pCode[ lPCodePos ] )
|
||||
{
|
||||
case AND_:
|
||||
case _ARRAYAT:
|
||||
case _ARRAYPUT:
|
||||
case _DEC:
|
||||
case _DIVIDE:
|
||||
case _DUPLICATE:
|
||||
case _EQUAL:
|
||||
case _EXACTLYEQUAL:
|
||||
case _FALSE:
|
||||
case _FORTEST:
|
||||
case _FUNCPTR:
|
||||
case _GREATER:
|
||||
case _GREATEREQUAL:
|
||||
case _INC:
|
||||
case _INSTRING:
|
||||
case _LESS:
|
||||
case _LESSEQUAL:
|
||||
case _MINUS:
|
||||
case _MODULUS:
|
||||
case _MULT:
|
||||
case _NEGATE:
|
||||
case _NOT:
|
||||
case _NOTEQUAL:
|
||||
case OR_:
|
||||
case _PLUS:
|
||||
case _POP:
|
||||
case _POWER:
|
||||
case _PUSHNIL:
|
||||
case _PUSHSELF:
|
||||
case _RETVALUE:
|
||||
case _TRUE:
|
||||
case _ZERO:
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
break;
|
||||
|
||||
case _DIMARRAY:
|
||||
case _DO:
|
||||
case _ENDBLOCK:
|
||||
case _FUNCTION:
|
||||
case _GENARRAY:
|
||||
case _JUMP:
|
||||
case _JUMPFALSE:
|
||||
case _JUMPTRUE:
|
||||
case _LINE:
|
||||
case _MESSAGE:
|
||||
case _POPLOCAL:
|
||||
case _POPMEMVAR:
|
||||
case _POPSTATIC:
|
||||
case _PUSHINT:
|
||||
case _PUSHLOCAL:
|
||||
case _PUSHLOCALREF:
|
||||
case _PUSHMEMVAR:
|
||||
case _PUSHMEMVARREF:
|
||||
case _PUSHSTATIC:
|
||||
case _PUSHSTATICREF:
|
||||
case _PUSHSYM:
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
break;
|
||||
|
||||
case _FRAME:
|
||||
if( pFunc->pCode[ lPCodePos + 1 ] || pFunc->pCode[ lPCodePos + 2 ] )
|
||||
{
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
}
|
||||
else
|
||||
{
|
||||
lPad += 3;
|
||||
lPCodePos += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case _PUSHBLOCK:
|
||||
wVar = * ( ( WORD *) &( pFunc->pCode [ lPCodePos + 5 ] ) );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
/* create the table of referenced local variables */
|
||||
while( wVar-- )
|
||||
{
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
}
|
||||
break;
|
||||
|
||||
case _PUSHDOUBLE:
|
||||
{
|
||||
int i;
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
for( i = 0; i < sizeof( double ); ++i )
|
||||
fputc( ( ( BYTE * ) pFunc->pCode )[ lPCodePos + i ], yyc );
|
||||
lPCodePos += sizeof( double );
|
||||
}
|
||||
break;
|
||||
|
||||
case _PUSHLONG:
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos++ ], yyc );
|
||||
break;
|
||||
|
||||
case _PUSHSTR:
|
||||
wLen = pFunc->pCode[ lPCodePos + 1 ] +
|
||||
pFunc->pCode[ lPCodePos + 2 ] * 256;
|
||||
fputc( pFunc->pCode[ lPCodePos ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos + 1 ], yyc );
|
||||
fputc( pFunc->pCode[ lPCodePos + 2 ], yyc );
|
||||
lPCodePos +=3;
|
||||
while( wLen-- )
|
||||
{
|
||||
fputc( pFunc->pCode[ lPCodePos ++ ], yyc );
|
||||
}
|
||||
break;
|
||||
|
||||
case _SFRAME:
|
||||
/* we only generate it if there are statics used in this function */
|
||||
if( pFunc->bFlags & FUN_USES_STATICS )
|
||||
{
|
||||
w = GetSymbolPos( _pInitFunc->szName ) - ( _iStartProc ? 1: 2 );
|
||||
fputc( pFunc->pCode[ lPCodePos ], yyc );
|
||||
fputc( LOBYTE( w ), yyc );
|
||||
fputc( HIBYTE( w ), yyc );
|
||||
}
|
||||
else
|
||||
lPad += 3;
|
||||
lPCodePos += 3;
|
||||
break;
|
||||
|
||||
case _STATICS:
|
||||
w = GetSymbolPos( _pInitFunc->szName ) - ( _iStartProc ? 1: 2 );
|
||||
fputc( pFunc->pCode[ lPCodePos ], yyc );
|
||||
fputc( LOBYTE( w ), yyc );
|
||||
fputc( HIBYTE( w ), yyc );
|
||||
lPCodePos += 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf( "Incorrect pcode value!\n" );
|
||||
lPCodePos = pFunc->lPCodePos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fputc( _ENDPROC, yyc );
|
||||
for( ; lPad; lPad-- )
|
||||
fputc( 0, yyc ); /* Pad optimalizations */
|
||||
pFunc = pFunc->pNext;
|
||||
}
|
||||
|
||||
fclose( yyc );
|
||||
|
||||
if( ! _iQuiet )
|
||||
printf( "%s -> done!\n", szFileName );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
The following bugs have been recovered from h090599 :
|
||||
|
||||
1. Makefile.b16 + .b32
|
||||
2. Second() functions renamed
|
||||
|
||||
The following bugs are unresolved :
|
||||
|
||||
1. Eval is loosing memory
|
||||
aEval is fine; Eval looses them somewhere (no Return argument??)
|
||||
2. Dates & Set_Test and Test10 crash during compile
|
||||
3. TestId is broken
|
||||
Does not compile without /dTEST
|
||||
Crashes with /dTEST
|
||||
It decides to do something different though :-)
|
||||
|
||||
Some warnings left and right
|
||||
|
||||
Eddie
|
||||
5
harbour/tests/broken/hrb.bat
Normal file
5
harbour/tests/broken/hrb.bat
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
|
||||
REM From .PRG to .C = Harbour
|
||||
..\..\bin\harbour %1.prg /n /gh
|
||||
runner %1.hrb
|
||||
78
harbour/tests/broken/run_exp.h
Normal file
78
harbour/tests/broken/run_exp.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
*
|
||||
* This file contains the exportable functions available to the Harbour program
|
||||
*
|
||||
* Currently being discussed in 'Static initializers'
|
||||
*
|
||||
* If the discussion has finished, it can be removed from here.
|
||||
*
|
||||
* Currently containing :
|
||||
*
|
||||
* Arrays
|
||||
* Console
|
||||
* HVM
|
||||
*
|
||||
*/
|
||||
HARBOUR ARRAY();
|
||||
HARBOUR AADD();
|
||||
HARBOUR ASIZE();
|
||||
HARBOUR ATAIL();
|
||||
HARBOUR AINS();
|
||||
HARBOUR ADEL();
|
||||
HARBOUR AFILL();
|
||||
HARBOUR ASCAN();
|
||||
HARBOUR AEVAL();
|
||||
HARBOUR ACOPY();
|
||||
HARBOUR ACLONE();
|
||||
HARBOUR __ACCEPT();
|
||||
HARBOUR OUTSTD();
|
||||
HARBOUR QQOUT();
|
||||
HARBOUR QOUT();
|
||||
HARBOUR ERRORSYS();
|
||||
HARBOUR ERRORNEW();
|
||||
HARBOUR EVAL();
|
||||
HARBOUR VALTYPE();
|
||||
HARBOUR UPPER();
|
||||
HARBOUR VAL();
|
||||
HARBOUR STRDUMP();
|
||||
HARBOUR TRIM();
|
||||
HARBOUR LTRIM();
|
||||
HARBOUR RTRIM();
|
||||
HARBOUR CHR();
|
||||
|
||||
/* Same story.
|
||||
|
||||
All the function pointers of the internal functions
|
||||
Including Runner itself, since the first symbol gets executed by Harbour ;-)
|
||||
*/
|
||||
static SYMBOL symbols[] = {
|
||||
{ "Runner", FS_PUBLIC, Runner , 0 },
|
||||
{ "ARRAY", FS_PUBLIC, ARRAY , 0 },
|
||||
{ "AADD", FS_PUBLIC, AADD , 0 },
|
||||
{ "ASIZE", FS_PUBLIC, ASIZE , 0 },
|
||||
{ "ATAIL", FS_PUBLIC, ATAIL , 0 },
|
||||
{ "AINS", FS_PUBLIC, AINS , 0 },
|
||||
{ "ADEL", FS_PUBLIC, ADEL , 0 },
|
||||
{ "AFILL", FS_PUBLIC, AFILL , 0 },
|
||||
{ "ASCAN", FS_PUBLIC, ASCAN , 0 },
|
||||
{ "AEVAL", FS_PUBLIC, AEVAL , 0 },
|
||||
{ "ACOPY", FS_PUBLIC, ACOPY , 0 },
|
||||
{ "ACLONE", FS_PUBLIC, ACLONE , 0 },
|
||||
{ "__ACCEPT", FS_PUBLIC, __ACCEPT, 0 },
|
||||
{ "OUTSTD", FS_PUBLIC, OUTSTD , 0 },
|
||||
{ "QQOUT", FS_PUBLIC, QQOUT , 0 },
|
||||
{ "QOUT", FS_PUBLIC, QOUT , 0 },
|
||||
{ "ERRORSYS", FS_PUBLIC, ERRORSYS, 0 },
|
||||
{ "ERRORNEW", FS_PUBLIC, ERRORNEW, 0 },
|
||||
{ "EVAL", FS_PUBLIC, EVAL , 0 },
|
||||
{ "VALTYPE", FS_PUBLIC, VALTYPE , 0 },
|
||||
{ "UPPER", FS_PUBLIC, UPPER , 0 },
|
||||
{ "STRDUMP", FS_PUBLIC, STRDUMP , 0 },
|
||||
{ "TRIM", FS_PUBLIC, TRIM , 0 },
|
||||
{ "LTRIM", FS_PUBLIC, LTRIM , 0 },
|
||||
{ "RTRIM", FS_PUBLIC, RTRIM , 0 },
|
||||
{ "CHR", FS_PUBLIC, CHR , 0 },
|
||||
{ "VAL", FS_PUBLIC, VAL , 0 }
|
||||
};
|
||||
|
||||
|
||||
291
harbour/tests/broken/runner.c
Normal file
291
harbour/tests/broken/runner.c
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "pcode.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* #if DOS32 */
|
||||
static BYTE prgFunction[] = { 0x68, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x83, 0xC4, 0x08,
|
||||
0xC3 };
|
||||
/* push offset pcode
|
||||
push offset symbols
|
||||
call near relative VirtualMachine
|
||||
add esp, 8
|
||||
ret near */
|
||||
|
||||
/* This is the assembler output from : VirtualMachine(pcode,symbols). */
|
||||
|
||||
/* #elseif DOS16 */
|
||||
/* #elseif MAC */
|
||||
/* #elseif ... */
|
||||
/* #endif */
|
||||
|
||||
typedef union
|
||||
{
|
||||
PBYTE pAsmData; /* The assembler bytes */
|
||||
HARBOURFUNC pFunPtr; /* The (dynamic) harbour function */
|
||||
} ASM_CALL, *PASM_CALL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *szName; /* Name of the function */
|
||||
PASM_CALL pAsmCall; /* Assembler call */
|
||||
PBYTE pCode; /* P-code */
|
||||
} DYNFUNC, *PDYNFUNC;
|
||||
|
||||
#define SYM_NOLINK 0 /* Symbol does not have to be linked */
|
||||
#define SYM_FUNC 1 /* Defined function */
|
||||
#define SYM_EXTERN 2 /* Previously defined function */
|
||||
|
||||
PASM_CALL CreateFun( PSYMBOL, PBYTE ); /* Create a dynamic function*/
|
||||
|
||||
HARBOUR Runner();
|
||||
|
||||
#include "run_exp.h"
|
||||
/*
|
||||
*
|
||||
* This file contains the exportable functions available to the Harbour program
|
||||
*
|
||||
* Currently being discussed in 'Static initializers'
|
||||
*
|
||||
* If the discussion has finished, it can be removed from here.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Same story.
|
||||
|
||||
All the function pointers of the internal functions
|
||||
Including Runner itself, since the first symbol gets executed by Harbour ;-)
|
||||
*/
|
||||
#include <init.h>
|
||||
|
||||
/*
|
||||
Runner
|
||||
|
||||
This program will get the data from the .HRB file and run the p-code
|
||||
contained in it.
|
||||
|
||||
In due time it should also be able to collect the data from the
|
||||
binary/executable itself
|
||||
*/
|
||||
HARBOUR Runner( void )
|
||||
{
|
||||
char cLong[4]; /* Temporary long */
|
||||
char *szFileName;
|
||||
char *szTemp; /* Temporary buffer */
|
||||
char *szIdx;
|
||||
|
||||
FILE *file;
|
||||
|
||||
ULONG ulSymbols; /* Number of symbols */
|
||||
ULONG ulFuncs; /* Number of functions */
|
||||
ULONG ulSize; /* Size of function */
|
||||
ULONG ul, ul2;
|
||||
|
||||
BYTE bCont;
|
||||
|
||||
PSYMBOL pSymRead = NULL; /* Symbols read */
|
||||
PDYNFUNC pPCode = NULL; /* Functions read */
|
||||
PDYNSYM pDynSym;
|
||||
|
||||
if( _pcount() == 0 )
|
||||
printf( "\nPlease give HRB file name\n" );
|
||||
else
|
||||
{
|
||||
szFileName = _parc( 1 );
|
||||
file = fopen( szFileName, "rb" ); /* Open as binary */
|
||||
if( file )
|
||||
{
|
||||
fread( &cLong, 4, 1, file ); /* Read number of symbols */
|
||||
ulSymbols = ( (BYTE) cLong[0] ) +
|
||||
( (BYTE) cLong[1] ) * 0x100 +
|
||||
( (BYTE) cLong[2] ) * 0x10000 +
|
||||
( (BYTE) cLong[3] ) * 0x1000000;
|
||||
printf("\nNumber of symbols=%li\n", ulSymbols );
|
||||
|
||||
pSymRead = _xgrab( ulSymbols * sizeof( SYMBOL ) );
|
||||
|
||||
szTemp = _xgrab( 256 ); /* Must be enough for now */
|
||||
|
||||
for( ul=0; ul < ulSymbols; ul++) /* Read symbols in .HRB */
|
||||
{
|
||||
szIdx = szTemp;
|
||||
bCont = TRUE;
|
||||
do
|
||||
{
|
||||
fread( szIdx, 1, 1, file );
|
||||
if( *szIdx )
|
||||
szIdx++;
|
||||
else
|
||||
bCont = FALSE;
|
||||
} while( bCont );
|
||||
|
||||
pSymRead[ ul ].szName = (char *) _xgrab( szIdx - szTemp + 1 );
|
||||
strcpy( pSymRead[ ul ].szName, szTemp );
|
||||
printf("\nName = %s.", pSymRead[ ul].szName );
|
||||
|
||||
fread( szTemp, 2, 1, file );
|
||||
|
||||
pSymRead[ ul ].cScope = szTemp[ 0 ];
|
||||
pSymRead[ ul ].pFunPtr = (void *) szTemp[ 1 ];
|
||||
pSymRead[ ul ].pDynSym = NULL;
|
||||
}
|
||||
|
||||
fread( &cLong, 4, 1, file ); /* Read number of functions */
|
||||
ulFuncs = ( (BYTE) cLong[0] ) +
|
||||
( (BYTE) cLong[1] ) * 0x100 +
|
||||
( (BYTE) cLong[2] ) * 0x10000 +
|
||||
( (BYTE) cLong[3] ) * 0x1000000;
|
||||
printf("\nNumber of functions=%li\n", ulFuncs );
|
||||
|
||||
pPCode = ( PDYNFUNC ) _xgrab( ulFuncs * sizeof( DYNFUNC ) );
|
||||
for( ul=0; ul < ulFuncs; ul++) /* Read symbols in .HRB */
|
||||
{
|
||||
szIdx = szTemp;
|
||||
bCont = TRUE;
|
||||
do
|
||||
{
|
||||
fread( szIdx, 1, 1, file );
|
||||
if( *szIdx )
|
||||
szIdx++;
|
||||
else
|
||||
bCont = FALSE;
|
||||
} while( bCont );
|
||||
printf("\nName = %s.", szTemp );
|
||||
pPCode[ ul ].szName = (char *) _xgrab( szIdx - szTemp + 1);
|
||||
strcpy( pPCode[ ul ].szName, szTemp );
|
||||
|
||||
fread( &cLong, 4, 1, file ); /* Read size of function */
|
||||
ulSize = ( (BYTE) cLong[0] ) +
|
||||
( (BYTE) cLong[1] ) * 0x100 +
|
||||
( (BYTE) cLong[2] ) * 0x10000 +
|
||||
( (BYTE) cLong[3] ) * 0x1000000 + 1;
|
||||
printf("\nSize of function=%li\n", ulSize );
|
||||
pPCode[ ul ].pCode = _xgrab( ulSize );
|
||||
fread( pPCode[ ul ].pCode, 1, ulSize, file );
|
||||
/* Read the block */
|
||||
|
||||
pPCode[ ul ].pAsmCall = CreateFun( pSymRead, pPCode[ ul ].pCode );
|
||||
/* Create matching dynamic */
|
||||
/* function */
|
||||
}
|
||||
|
||||
ul2 = 0;
|
||||
for( ul = 0; ul < ulSymbols; ul++ ) /* Quick & Dirty linking */
|
||||
{
|
||||
|
||||
if( ( (ULONG) pSymRead[ ul ].pFunPtr ) == SYM_FUNC )
|
||||
{ /* Internal function */
|
||||
pSymRead[ ul ].pFunPtr = pPCode[ ul2++ ].pAsmCall->pFunPtr;
|
||||
}
|
||||
else if( ( (ULONG) pSymRead[ ul ].pFunPtr ) == SYM_EXTERN )
|
||||
{ /* External function */
|
||||
pDynSym = FindDynSym( pSymRead[ ul ].szName );
|
||||
if( !pDynSym )
|
||||
{
|
||||
printf( "\nCould you please add : %s to run_exp.h and compile me\nThank you.",
|
||||
pSymRead[ ul ].szName );
|
||||
exit( 1 );
|
||||
}
|
||||
pSymRead[ ul ].pFunPtr = pDynSym->pFunPtr;
|
||||
}
|
||||
}
|
||||
|
||||
pSymRead[ 0 ].pFunPtr(); /* Run the thing !!! */
|
||||
|
||||
for( ul = 0; ul < ulFuncs; ul++ )
|
||||
{
|
||||
_xfree( pPCode[ ul ].pAsmCall->pAsmData );
|
||||
_xfree( pPCode[ ul ].pAsmCall );
|
||||
_xfree( pPCode[ ul ].pCode );
|
||||
_xfree( pPCode[ ul ].szName );
|
||||
}
|
||||
|
||||
for( ul = 0; ul < ulSymbols; ul++ )
|
||||
{
|
||||
_xfree( pSymRead[ ul ].szName );
|
||||
}
|
||||
|
||||
_xfree( pPCode );
|
||||
_xfree( szTemp );
|
||||
_xfree( pSymRead );
|
||||
fclose( file );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "\nCannot open %s\n", szFileName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Patch an address of the dynamic function */
|
||||
void Patch( PBYTE pCode, ULONG ulOffset, void *Address )
|
||||
{
|
||||
/* #if 32 bits and low byte first */
|
||||
|
||||
pCode[ ulOffset ] = ( (ULONG) Address ) & 0xFF;
|
||||
pCode[ ulOffset + 1 ] = ( (ULONG) Address >> 8 ) & 0xFF;
|
||||
pCode[ ulOffset + 2 ] = ( (ULONG) Address >> 16 ) & 0xFF;
|
||||
pCode[ ulOffset + 3 ] = ( (ULONG) Address >> 24 ) & 0xFF;
|
||||
|
||||
/* #elseif 16 bits and low byte first */
|
||||
/* #elseif 32 bits and high byte first */
|
||||
/* #elseif ... */
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* Intel specific ?? Patch an address relative to the next instruction */
|
||||
void PatchRelative( PBYTE pCode, ULONG ulOffset, void *Address, ULONG ulNext )
|
||||
{
|
||||
/* #if 32 bits and low byte first */
|
||||
ULONG ulBase = (ULONG) pCode + ulNext;
|
||||
/* Relative to next instruction */
|
||||
ULONG ulRelative = (ULONG) Address - ulBase;
|
||||
|
||||
pCode[ ulOffset ] = ( ulRelative ) & 0xFF;
|
||||
pCode[ ulOffset + 1 ] = ( ulRelative >> 8 ) & 0xFF;
|
||||
pCode[ ulOffset + 2 ] = ( ulRelative >> 16 ) & 0xFF;
|
||||
pCode[ ulOffset + 3 ] = ( ulRelative >> 24 ) & 0xFF;
|
||||
|
||||
/* #elseif 16 bits and low byte first */
|
||||
/* #elseif 32 bits and high byte first */
|
||||
/* #elseif ... */
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/*
|
||||
Create dynamic function.
|
||||
|
||||
This function is needed, since it will allow the existing strategy of
|
||||
function pointers to work properly.
|
||||
|
||||
For each Harbour function a little program calling the virtual machine
|
||||
should be present (see : *.c)
|
||||
|
||||
Since these programs no longer exists when using this system, they should
|
||||
be create dynamically at run-time.
|
||||
|
||||
If a .PRG contains 10 functions, 10 dynamic functions are created which
|
||||
are all the same :-) except for 1 pointer.
|
||||
*/
|
||||
PASM_CALL CreateFun( PSYMBOL pSymbols, PBYTE pCode )
|
||||
{
|
||||
PASM_CALL asmRet = (PASM_CALL) _xgrab( sizeof( ASM_CALL ) );
|
||||
|
||||
asmRet->pAsmData = (PBYTE) _xgrab( sizeof( prgFunction ) );
|
||||
memcpy( asmRet->pAsmData, prgFunction, sizeof( prgFunction ) );
|
||||
/* Copy new assembler code in */
|
||||
/* #if DOS32 */
|
||||
|
||||
Patch( asmRet->pAsmData, 1, pSymbols ); /* Insert pointer to testsym */
|
||||
Patch( asmRet->pAsmData, 6, pCode); /* Insert pointer to testcode */
|
||||
PatchRelative( asmRet->pAsmData, 11, &VirtualMachine, 15 );
|
||||
/* Insert pointer to VirtualMachine() */
|
||||
|
||||
/* #elseif DOS16 */
|
||||
/* #elseif MAC */
|
||||
/* #elseif ... */
|
||||
/* #endif */
|
||||
return( asmRet );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user