From c221fbb9f7173bb108d98de09e2738e082acaba4 Mon Sep 17 00:00:00 2001 From: Eddie Runia Date: Tue, 18 May 1999 22:50:12 +0000 Subject: [PATCH] HRB production added + runner. Removed old file in tests/broken. --- harbour/ChangeLog | 11 ++ harbour/source/compiler/harbour.y | 294 +++++++++++++++++++++++++++++- harbour/tests/broken/h090599.txt | 18 -- harbour/tests/broken/hrb.bat | 5 + harbour/tests/broken/run_exp.h | 78 ++++++++ harbour/tests/broken/runner.c | 291 +++++++++++++++++++++++++++++ 6 files changed, 678 insertions(+), 19 deletions(-) delete mode 100644 harbour/tests/broken/h090599.txt create mode 100644 harbour/tests/broken/hrb.bat create mode 100644 harbour/tests/broken/run_exp.h create mode 100644 harbour/tests/broken/runner.c diff --git a/harbour/ChangeLog b/harbour/ChangeLog index f62019028e..3303c6e06b 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -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 * source/rtl/console.c - Use pItem->wLength and pItem->wDec when printing numbers. diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 7586b61a3c..f6cdb72325 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -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) */ LANG_JAVA, /* Java */ LANG_PASCAL, /* Pascal */ - LANG_RESOURCES /* Resources */ + LANG_RESOURCES, /* Resources */ + LANG_PORT_OBJ /* Portable objects */ } 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 ); +} + diff --git a/harbour/tests/broken/h090599.txt b/harbour/tests/broken/h090599.txt deleted file mode 100644 index 304951fa76..0000000000 --- a/harbour/tests/broken/h090599.txt +++ /dev/null @@ -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 diff --git a/harbour/tests/broken/hrb.bat b/harbour/tests/broken/hrb.bat new file mode 100644 index 0000000000..56271c56ba --- /dev/null +++ b/harbour/tests/broken/hrb.bat @@ -0,0 +1,5 @@ +@echo off + +REM From .PRG to .C = Harbour +..\..\bin\harbour %1.prg /n /gh +runner %1.hrb diff --git a/harbour/tests/broken/run_exp.h b/harbour/tests/broken/run_exp.h new file mode 100644 index 0000000000..93ee78af83 --- /dev/null +++ b/harbour/tests/broken/run_exp.h @@ -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 } +}; + + diff --git a/harbour/tests/broken/runner.c b/harbour/tests/broken/runner.c new file mode 100644 index 0000000000..6ae0d8a917 --- /dev/null +++ b/harbour/tests/broken/runner.c @@ -0,0 +1,291 @@ +#include "pcode.h" +#include + +/* #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 + +/* + 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 ); +} +