* harbour/bin/hb-func.sh
* harbour/bin/hb-mkslib.sh
* harbour/bin/postinst.sh
* harbour/config/bsd/gcc.cf
* harbour/config/darwin/gcc.cf
* harbour/config/dos/owatcom.cf
* harbour/config/hpux/gcc.cf
* harbour/config/linux/gcc.cf
* harbour/config/linux/owatcom.cf
* harbour/config/os2/gcc.cf
* harbour/config/sunos/gcc.cf
* harbour/config/w32/watcom.cf
* harbour/contrib/rdd_ads/ads1.c
* harbour/contrib/rdd_ads/adsfunc.c
* harbour/include/hbapifs.h
* harbour/include/hbexprc.c
* harbour/include/hbsetup.h
* harbour/source/common/expropt2.c
* harbour/source/common/hbdate.c
* harbour/source/common/hbgete.c
* harbour/source/common/hbstr.c
* harbour/source/common/hbver.c
* harbour/source/common/hbverdsp.c
* harbour/source/compiler/cmdcheck.c
* harbour/source/compiler/fixflex.c
* harbour/source/compiler/gencobj.c
* harbour/source/compiler/genobj32.c
* harbour/source/compiler/harbour.c
* harbour/source/compiler/harbour.l
* harbour/source/compiler/harbour.y
* harbour/source/compiler/harbour.yyc
* harbour/source/compiler/hbfix.c
* harbour/source/compiler/hbfunchk.c
* harbour/source/pp/ppcore.c
* harbour/source/pp/ppgen.c
* harbour/source/pp/pplib.c
* harbour/source/rdd/dbcmd.c
* harbour/source/rdd/workarea.c
* harbour/source/rdd/dbfcdx/dbfcdx1.c
* harbour/source/rdd/dbffpt/dbffpt1.c
* harbour/source/rdd/hsx/hsx.c
* harbour/source/rtl/accept.c
* harbour/source/rtl/ampm.c
* harbour/source/rtl/console.c
* harbour/source/rtl/defpath.c
* harbour/source/rtl/errorint.c
* harbour/source/rtl/filesys.c
* harbour/source/rtl/fkmax.c
* harbour/source/rtl/fstemp.c
* harbour/source/rtl/hbffind.c
* harbour/source/rtl/hbgtcore.c
* harbour/source/rtl/langapi.c
* harbour/source/rtl/seconds.c
* harbour/source/rtl/set.c
* harbour/source/rtl/tobject.prg
* harbour/source/rtl/transfrm.c
* harbour/source/rtl/gtcrs/chrmap.c
* harbour/source/rtl/gtcrs/gtcrs.c
* harbour/source/rtl/gtcrs/gtcrs.h
* harbour/source/rtl/gtpca/gtpca.c
* harbour/source/rtl/gtwvt/gtwvt.c
* harbour/source/rtl/gtxwc/gtxwc.c
* harbour/source/vm/classes.c
* harbour/source/vm/cmdarg.c
* harbour/source/vm/debug.c
* harbour/source/vm/estack.c
* harbour/source/vm/fm.c
* harbour/source/vm/hvm.c
* harbour/source/vm/macro.c
* harbour/source/vm/proc.c
* harbour/source/vm/runner.c
* harbour/utils/hbmake/hbmlang.c
* harbour/utils/hbpp/hbpp.c
* harbour/utils/hbpp/hbppcomp.c
* harbour/utils/hbpp/hbppcore.c
* harbour/utils/hbpp/hbpplib.c
* harbour/utils/hbpp/pragma.c
* harbour/utils/hbver/hbverfix.c
* general code cleanup: all strcpy() and strcat() replaced hb strn*()
and hb_strn*(), sprintf() by snprintf(), etc.
It fixed some possible buffer overflow but it's also possible that
it will exploit some some hidden so far problems but I strongly
prefer to know about them ASAP to fix them before final 1.0 release.
! fixed bug I introduce in codeblock falgs which disabled early macro
evaluation in codeblocks.
! added missing protection against execution by bison destructor for
used CBSTART token on syntax error.
% use PP stringify logik added for FLEX support to remove all redundant
spaces in stringified for early macro evaluation codeblocks and add
spaces between operators if after preprocessing they were removed.
Now we are supporting also some code which cannot be compiled by
Clipper.
% cleaned and improved the speed of printer redirecting in console code.
Chen please check if CG still reports problems and if not ubdate
TODO/TOFIX or inform me about them.
* some cleanups in building process for different *nixes: MacOSX, SunOS,
*BSD, etc.
* removed not longer necessary (I hope) compiler flag to force default
'char' type as signed. Now Harbour should work with signed and unsigned
char without any problems. To other developers: please remember that
when you are using 'char' as 8 bytes signed integer then it's a bug.
Always explicitly use: 'signed char' in such case. On some platforms
it's not possible to set default type for 'char' so if you hardcode
that 'char' is signed or unsigned somewhere then code will not be
portable. Chen if you will find a while to also rebuild Harbour with
BCC and -K switch to make some tests with CG then I'll be thankful.
664 lines
21 KiB
C
664 lines
21 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Compiler Windows/DOS OBJ32 generation
|
|
*
|
|
* Copyright 1999 Antonio Linares <alinares@fivetech.com>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
|
|
* their web site at http://www.gnu.org/).
|
|
*
|
|
*/
|
|
|
|
#include "hbcomp.h"
|
|
|
|
static ULONG GetSymbolsSize( HB_COMP_DECL );
|
|
static PCOMSYMBOL GetFirstSymbol( HB_COMP_DECL );
|
|
static char * GetSymbolName( HB_COMP_DECL, ULONG ulPos );
|
|
static ULONG GetPCodesSize( HB_COMP_DECL );
|
|
static ULONG GetSymbolsAmount( HB_COMP_DECL );
|
|
static BOOL IsExternal( HB_COMP_DECL, ULONG ulSymbol );
|
|
static USHORT GetExternalPos( char * szExternal );
|
|
static void GenerateLocalNames( FILE * hObjFile );
|
|
static void GenerateSymbolsSegment( HB_COMP_DECL, FILE * hObjFile );
|
|
static void GenerateDataSegment( HB_COMP_DECL, FILE * hObjFile );
|
|
static void GenerateCodeSegment( HB_COMP_DECL, FILE * hObjFile );
|
|
static void GenerateExternals( HB_COMP_DECL, FILE * hObjFile );
|
|
static void putbyte( BYTE b, FILE * hObjFile, BYTE * pbChecksum );
|
|
static void putword( USHORT w, FILE * hObjFile, BYTE * pbChecksum );
|
|
static void CompiledFileName( FILE * hObjFile, char * szFileName );
|
|
static void CompilerVersion( FILE * hObjFile, char * szVersion );
|
|
static void LocalNames( FILE * hObjFile, char * szNames[] );
|
|
static void ExternalNames( FILE * hObjFile, char * szNames[] );
|
|
static void CodeSegment( HB_COMP_DECL, FILE * hObjFile, BYTE * prgCode, ULONG ulPrgLen, USHORT wFunctions );
|
|
static void DataSegment( HB_COMP_DECL, FILE * hObjFile, BYTE * symbol, ULONG wSymLen, ULONG wSymbols, ULONG ulTotalSize );
|
|
static void DefineSegment( FILE * hObjFile, BYTE bName, BYTE bClass, USHORT wLen );
|
|
static void PubDef( FILE * hObjFile, char * szName, USHORT wSegment, USHORT wOffset );
|
|
static void Fixup( FILE * hObjFile, BYTE bType, USHORT wOffset, BYTE bFlags, BYTE bSymbol );
|
|
static void EnumeratedData( FILE * hObjFile, BYTE bSegment, BYTE * pData, USHORT wLen, USHORT wOffset );
|
|
static void End( FILE * hObjFile );
|
|
static void GroupDef( FILE * hObjFile, BYTE bName, BYTE * aSegs );
|
|
|
|
static BYTE prgFunction[] = { 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
|
|
0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x83, 0xC4, 0x08, 0xC3 };
|
|
|
|
static char * * externNames = 0;
|
|
static USHORT wExternals = 1; /* _hb_vmExecute is always added */
|
|
static char * szPrefix = "_HB_FUN_";
|
|
|
|
void hb_compGenObj32( HB_COMP_DECL, PHB_FNAME pFileName )
|
|
{
|
|
char szFileName[ _POSIX_PATH_MAX ];
|
|
FILE * hObjFile; /* file handle for OBJ output */
|
|
char * szVer;
|
|
|
|
if( ! pFileName->szExtension )
|
|
pFileName->szExtension = ".obj";
|
|
hb_fsFNameMerge( szFileName, pFileName );
|
|
|
|
if( ( hObjFile = fopen( szFileName, "wb" ) ) == NULL )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_CREATE_OUTPUT, szFileName, NULL );
|
|
return;
|
|
}
|
|
|
|
if( ! HB_COMP_PARAM->fQuiet )
|
|
{
|
|
printf( "Generating Windows/DOS OBJ32 output to \'%s\'... ", szFileName );
|
|
fflush( stdout );
|
|
}
|
|
|
|
CompiledFileName( hObjFile, szFileName );
|
|
szVer = hb_verHarbour();
|
|
CompilerVersion( hObjFile, szVer );
|
|
hb_xfree( szVer );
|
|
GenerateLocalNames( hObjFile );
|
|
GenerateExternals( HB_COMP_PARAM, hObjFile );
|
|
GenerateCodeSegment( HB_COMP_PARAM, hObjFile );
|
|
GenerateDataSegment( HB_COMP_PARAM, hObjFile );
|
|
GenerateSymbolsSegment( HB_COMP_PARAM, hObjFile );
|
|
End( hObjFile );
|
|
|
|
fclose( hObjFile );
|
|
|
|
if( ! HB_COMP_PARAM->fQuiet )
|
|
printf( "Done.\n" );
|
|
}
|
|
|
|
static ULONG GetSymbolsSize( HB_COMP_DECL )
|
|
{
|
|
return HB_COMP_PARAM->symbols.iCount * sizeof( HB_SYMB );
|
|
}
|
|
|
|
static PCOMSYMBOL GetFirstSymbol( HB_COMP_DECL )
|
|
{
|
|
PCOMSYMBOL pSymbol = HB_COMP_PARAM->symbols.pFirst;
|
|
return pSymbol;
|
|
}
|
|
|
|
static char * GetSymbolName( HB_COMP_DECL, ULONG ulPos )
|
|
{
|
|
PCOMSYMBOL pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
ULONG ul = 0;
|
|
|
|
while( pSymbol && ( ul++ < ulPos ) )
|
|
pSymbol = pSymbol->pNext;
|
|
|
|
return pSymbol->szName;
|
|
}
|
|
|
|
static ULONG GetPCodesSize( HB_COMP_DECL )
|
|
{
|
|
ULONG ulTotal = 0;
|
|
PFUNCTION pFunction = HB_COMP_PARAM->functions.pFirst;
|
|
|
|
if( ! HB_COMP_PARAM->fStartProc )
|
|
pFunction = pFunction->pNext;
|
|
|
|
while( pFunction )
|
|
{
|
|
ulTotal += pFunction->lPCodePos;
|
|
pFunction = pFunction->pNext;
|
|
}
|
|
return ulTotal;
|
|
}
|
|
|
|
static ULONG GetSymbolsAmount( HB_COMP_DECL )
|
|
{
|
|
PCOMSYMBOL pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
ULONG ulAmount = 1;
|
|
|
|
while( pSymbol->pNext )
|
|
{
|
|
ulAmount++;
|
|
pSymbol = pSymbol->pNext;
|
|
}
|
|
return ulAmount;
|
|
}
|
|
|
|
static BOOL IsExternal( HB_COMP_DECL, ULONG ulSymbol )
|
|
{
|
|
PCOMSYMBOL pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
ULONG ul = 0;
|
|
|
|
while( ul++ < ulSymbol )
|
|
pSymbol = pSymbol->pNext;
|
|
|
|
return ! hb_compFunctionFind( HB_COMP_PARAM, pSymbol->szName );
|
|
}
|
|
|
|
static USHORT GetExternalPos( char * szExternal )
|
|
{
|
|
USHORT w = 0;
|
|
|
|
while( w < wExternals )
|
|
{
|
|
if( ! strcmp( szExternal, externNames[ w ] ) )
|
|
break;
|
|
w++;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
static void GenerateLocalNames( FILE * hObjFile )
|
|
{
|
|
char * localNames[] = { "_TEXT", "CODE",
|
|
"_NULL", "_DATA", "DATA",
|
|
"_BSS", "BSS", "DGROUP",
|
|
"HB_STARTSYMBOLS", "HB_SYMBOLS", "HB_ENDSYMBOLS", "HARBOUR",
|
|
"HB_STARTBORSYMBOLS", "_INIT_", "HB_ENDBORSYMBOLS", "INITDATA", "BORLAND",
|
|
0 };
|
|
|
|
LocalNames( hObjFile, localNames );
|
|
}
|
|
|
|
static void GenerateSymbolsSegment( HB_COMP_DECL, FILE * hObjFile )
|
|
{
|
|
BYTE symbolsData[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
BYTE groupDGroup[] = { 2, 3, 4, 0 }; /* segments defined order for DGROUP */
|
|
BYTE groupSymGroup[] = { 5, 6, 7, 0 }; /* segments defined order for SYMGROUP */
|
|
BYTE groupInitData[] = { 8, 9, 10, 0 }; /* segments defined order for INITDATA */
|
|
|
|
DefineSegment( hObjFile, 10, /* HB_STARTSYMBOLS position + 1 into localnames */
|
|
6, /* "DATA" position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
DefineSegment( hObjFile, 11, /* HB_SYMBOLS position + 1 into localNames */
|
|
6, /* "DATA" position + 1 into localNames */
|
|
8 ); /* segment length */
|
|
DefineSegment( hObjFile, 12, /* HB_ENDSYMBOLS position + 1 into localNames */
|
|
6, /* "DATA" position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
|
|
DefineSegment( hObjFile, 14, /* HB_STARTBORSYMBOLS position + 1 into localnames */
|
|
17, /* INITDATA position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
DefineSegment( hObjFile, 15, /* HB_STARTSYMBOLS position + 1 into localnames */
|
|
17, /* INITDATA position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
DefineSegment( hObjFile, 16, /* HB_ENDBORSYMBOLS position + 1 into localnames */
|
|
17, /* INITDATA position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
|
|
GroupDef( hObjFile, 8, groupDGroup ); /* "DGROUP" localNames position - 1 */
|
|
GroupDef( hObjFile, 12, groupSymGroup ); /* "SYMGROUP" localNames position - 1 */
|
|
GroupDef( hObjFile, 17, groupInitData ); /* "BORLAND" localNames position - 1 */
|
|
|
|
* ( USHORT * ) symbolsData = (USHORT) GetSymbolsAmount( HB_COMP_PARAM );
|
|
|
|
EnumeratedData( hObjFile, 6, symbolsData, sizeof( symbolsData ), 0 ); /* HB_SYMBOLS defined order segment */
|
|
|
|
Fixup( hObjFile, 0xE4, 4, /* offset into HB_SYMBOLS segment */
|
|
0x54,
|
|
4 ); /* DATA segment defined order */
|
|
}
|
|
|
|
static void GenerateDataSegment( HB_COMP_DECL, FILE * hObjFile )
|
|
{
|
|
HB_SYMB symbol;
|
|
ULONG ulSize = GetSymbolsSize( HB_COMP_PARAM );
|
|
PCOMSYMBOL pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
ULONG ulSymbols = GetSymbolsAmount( HB_COMP_PARAM ), ul;
|
|
|
|
while( pSymbol )
|
|
{
|
|
ulSize += strlen( pSymbol->szName ) + 1;
|
|
pSymbol = pSymbol->pNext;
|
|
}
|
|
|
|
ulSize += GetPCodesSize( HB_COMP_PARAM );
|
|
|
|
DefineSegment( hObjFile, 4, /* _NULL position + 1 into localnames */
|
|
6, /* "DATA" position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
DefineSegment( hObjFile, 7, /* _BSS position + 1 into localNames */
|
|
8, /* "BSS" position + 1 into localNames */
|
|
0 ); /* segment length */
|
|
DefineSegment( hObjFile, 5, /* "_DATA" position + 1 into localNames */
|
|
6, /* "DATA" position + 1 into localNames */
|
|
(USHORT) ulSize ); /* segment length */
|
|
|
|
memset( &symbol, 0, sizeof( symbol ) );
|
|
DataSegment( HB_COMP_PARAM, hObjFile, (BYTE *) &symbol,
|
|
sizeof( symbol ), GetSymbolsAmount( HB_COMP_PARAM ), ulSize );
|
|
|
|
pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
for( ul = 0; ul < ulSymbols; ul++ )
|
|
{
|
|
Fixup( hObjFile, 0xE4, (USHORT) ( ul * sizeof( HB_SYMB ) ), 0x54, 4 ); /* 4 = Data symbol name location */
|
|
|
|
if( IsExternal( HB_COMP_PARAM, ul ) )
|
|
{
|
|
if( ! ( pSymbol->cScope & HB_FS_MESSAGE ) )
|
|
Fixup( hObjFile, 0xE4, (USHORT) ( ul * sizeof( HB_SYMB ) ) + 8, 0x56,
|
|
GetExternalPos( GetSymbolName( HB_COMP_PARAM, ul ) ) + 1 );
|
|
}
|
|
else
|
|
{
|
|
/* if( ! ( pSymbol->cScope & HB_FS_MESSAGE ) ) */
|
|
Fixup( hObjFile, 0xE4, (USHORT) ( ul * sizeof( HB_SYMB ) ) + 8, 0x54, 1 ); /* function address location */
|
|
}
|
|
pSymbol = pSymbol->pNext;
|
|
}
|
|
}
|
|
|
|
static void GenerateCodeSegment( HB_COMP_DECL, FILE * hObjFile )
|
|
{
|
|
USHORT wFunctions = HB_COMP_PARAM->functions.iCount - ( HB_COMP_PARAM->fStartProc ? 0: 1 );
|
|
ULONG ulSize = wFunctions * sizeof( prgFunction );
|
|
PFUNCTION pFunc = ( HB_COMP_PARAM->fStartProc ? HB_COMP_PARAM->functions.pFirst: HB_COMP_PARAM->functions.pFirst->pNext );
|
|
USHORT w = 0;
|
|
|
|
DefineSegment( hObjFile, 2, /* "_TEXT" position + 1 into localNames */
|
|
3, /* "CODE" position + 1 into localNames */
|
|
(USHORT) ulSize ); /* segment length */
|
|
|
|
while( pFunc )
|
|
{
|
|
if( !( pFunc->cScope & ( HB_FS_STATIC | HB_FS_INIT | HB_FS_EXIT ) ) )
|
|
PubDef( hObjFile, pFunc->szName, 1, w * sizeof( prgFunction ) );
|
|
w++;
|
|
pFunc = pFunc->pNext;
|
|
}
|
|
|
|
CodeSegment( HB_COMP_PARAM, hObjFile, prgFunction, sizeof( prgFunction ), wFunctions );
|
|
|
|
for( w = 0; w < wFunctions; w++ )
|
|
{
|
|
/* prgFunction fixups */
|
|
Fixup( hObjFile, 0xE4, ( w * sizeof( prgFunction ) ) + 1,
|
|
0x54, 4 ); /* 4 = DATA segment defined order */
|
|
|
|
Fixup( hObjFile, 0xE4, ( w * sizeof( prgFunction ) ) + 6,
|
|
0x54, 4 ); /* DATA segment define order - pcode location */
|
|
|
|
Fixup( hObjFile, 0xA4, ( w * sizeof( prgFunction ) ) + 11,
|
|
0x56, 1 ); /* External: _hb_vmExecute */
|
|
}
|
|
}
|
|
|
|
static void GenerateExternals( HB_COMP_DECL, FILE * hObjFile )
|
|
{
|
|
USHORT w;
|
|
PFUNCTION pFunc, pFTemp;
|
|
|
|
/* calculate amount of externals */
|
|
pFunc = HB_COMP_PARAM->funcalls.pFirst;
|
|
while( pFunc )
|
|
{
|
|
if( ( pFTemp = hb_compFunctionFind( HB_COMP_PARAM, pFunc->szName ) ) == NULL || pFTemp == HB_COMP_PARAM->functions.pFirst )
|
|
wExternals++;
|
|
pFunc = pFunc->pNext;
|
|
}
|
|
if( wExternals )
|
|
{
|
|
externNames = ( char * * ) hb_xgrab( sizeof( char * ) * ( wExternals + 2 ) );
|
|
w = 1;
|
|
externNames[ 0 ] = "_hb_vmExecute";
|
|
|
|
pFunc = HB_COMP_PARAM->funcalls.pFirst;
|
|
while( pFunc )
|
|
{
|
|
if( ( pFTemp = hb_compFunctionFind( HB_COMP_PARAM, pFunc->szName ) ) == NULL || pFTemp == HB_COMP_PARAM->functions.pFirst )
|
|
externNames[ w++ ] = pFunc->szName;
|
|
pFunc = pFunc->pNext;
|
|
}
|
|
externNames[ w ] = 0;
|
|
ExternalNames( hObjFile, externNames );
|
|
}
|
|
}
|
|
|
|
static void putbyte( BYTE b, FILE * hObjFile, BYTE * pbChecksum )
|
|
{
|
|
fputc( b, hObjFile );
|
|
* pbChecksum += b;
|
|
}
|
|
|
|
static void putword( USHORT w, FILE * hObjFile, BYTE * pbChecksum )
|
|
{
|
|
putbyte( HB_LOBYTE( w ), hObjFile, pbChecksum );
|
|
putbyte( HB_HIBYTE( w ), hObjFile, pbChecksum );
|
|
}
|
|
|
|
static void CompiledFileName( FILE * hObjFile, char * szFileName )
|
|
{
|
|
USHORT wLen = strlen( szFileName );
|
|
BYTE bChk = 0; /* this is a checksum the linker will check to asure OBJ integrity */
|
|
BYTE bChar;
|
|
|
|
putbyte( 0x80, hObjFile, &bChk ); /* this tells the linker the kind of OBJ record this is */
|
|
putbyte( 1 + 1 + wLen, hObjFile, &bChk ); /* now it comes the total length of this OBJ record */
|
|
putbyte( 0, hObjFile, &bChk );
|
|
putbyte( (BYTE) wLen, hObjFile, &bChk ); /* szFileName length */
|
|
|
|
while( ( bChar = * szFileName++ ) != 0 )
|
|
putbyte( bChar, hObjFile, &bChk ); /* each of the szFileName characters */
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk ); /* a checksum that will be recalculated by the linker */
|
|
}
|
|
|
|
static void CompilerVersion( FILE * hObjFile, char * szVersion )
|
|
{
|
|
USHORT wLen = strlen( szVersion );
|
|
BYTE bChk = 0; /* this is a checksum the linker will check to asure OBJ integrity */
|
|
BYTE bChar;
|
|
|
|
putbyte( 0x88, hObjFile, &bChk ); /* this tells the linker the kind of OBJ record this is */
|
|
putword( 3 + wLen, hObjFile, &bChk ); /* now it comes the total length of this OBJ record */
|
|
putword( 0, hObjFile, &bChk );
|
|
|
|
while( ( bChar = * szVersion++ ) != 0 )
|
|
putbyte( bChar, hObjFile, &bChk ); /* each of the szFileName characters */
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk ); /* a checksum that will be recalculated by the linker */
|
|
}
|
|
|
|
static void LocalNames( FILE * hObjFile, char * szNames[] )
|
|
{
|
|
BYTE b = 0, c;
|
|
USHORT wTotalLen = 0;
|
|
BYTE bChk = 0;
|
|
|
|
while( szNames[ b ] )
|
|
wTotalLen += strlen( szNames[ b++ ] );
|
|
wTotalLen += 2 + b;
|
|
|
|
putbyte( 0x96, hObjFile, &bChk );
|
|
putword( wTotalLen, hObjFile, &bChk );
|
|
putbyte( 0, hObjFile, &bChk );
|
|
|
|
b = 0;
|
|
while( szNames[ b ] )
|
|
{
|
|
putbyte( strlen( szNames[ b ] ), hObjFile, &bChk );
|
|
|
|
c = 0;
|
|
while( szNames[ b ][ c ] )
|
|
putbyte( szNames[ b ][ c++ ], hObjFile, &bChk );
|
|
b++;
|
|
}
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void ExternalNames( FILE * hObjFile, char * szNames[] )
|
|
{
|
|
BYTE b = 0, c;
|
|
USHORT wTotalLen = 0;
|
|
BYTE bChk = 0;
|
|
|
|
while( szNames[ b ] )
|
|
{
|
|
if( b == 0 )
|
|
wTotalLen += strlen( szNames[ b++ ] ) + 1;
|
|
else
|
|
wTotalLen += strlen( szPrefix ) + strlen( szNames[ b++ ] ) + 1;
|
|
}
|
|
wTotalLen += 2 + b - 1;
|
|
|
|
putbyte( 0x8C, hObjFile, &bChk );
|
|
putword( wTotalLen, hObjFile, &bChk );
|
|
|
|
b = 0;
|
|
while( szNames[ b ] )
|
|
{
|
|
if( b == 0 )
|
|
putbyte( strlen( szNames[ b ] ), hObjFile, &bChk );
|
|
else
|
|
putbyte( strlen( szPrefix ) + strlen( szNames[ b ] ), hObjFile, &bChk );
|
|
|
|
c = 0;
|
|
|
|
if( b > 0 )
|
|
{
|
|
while( szPrefix[ c ] )
|
|
putbyte( szPrefix[ c++ ], hObjFile, &bChk );
|
|
c = 0;
|
|
}
|
|
|
|
while( szNames[ b ][ c ] )
|
|
putbyte( szNames[ b ][ c++ ], hObjFile, &bChk );
|
|
putbyte( 0, hObjFile, &bChk );
|
|
b++;
|
|
}
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void CodeSegment( HB_COMP_DECL, FILE * hObjFile, BYTE * prgCode, ULONG ulPrgLen, USHORT wFunctions )
|
|
{
|
|
BYTE bChk = 0;
|
|
USHORT y;
|
|
USHORT wTotalLen = (USHORT) ( ulPrgLen * wFunctions ) + 4;
|
|
ULONG ul;
|
|
PFUNCTION pFunction = HB_COMP_PARAM->functions.pFirst;
|
|
ULONG ulPCodeOffset = HB_COMP_PARAM->symbols.iCount * sizeof( HB_SYMB );
|
|
|
|
if( ! HB_COMP_PARAM->fStartProc )
|
|
pFunction = pFunction->pNext;
|
|
|
|
putbyte( 0xA0, hObjFile, &bChk );
|
|
putword( wTotalLen, hObjFile, &bChk );
|
|
putbyte( 1, hObjFile, &bChk ); /* 1 = _TEXT segment */
|
|
putword( 0, hObjFile, &bChk ); /* 0 = offset */
|
|
|
|
for( y = 0; y < wFunctions; y++ )
|
|
{
|
|
* ( ULONG * ) &prgCode[ 6 ] = ulPCodeOffset; /* function pcode offset */
|
|
for( ul = 0; ul < ulPrgLen; ul++ )
|
|
putbyte( * ( prgCode + ul ), hObjFile, &bChk );
|
|
ulPCodeOffset += pFunction->lPCodePos;
|
|
pFunction = pFunction->pNext;
|
|
}
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void DataSegment( HB_COMP_DECL, FILE * hObjFile, BYTE * symbol, ULONG wSymLen, ULONG wSymbols,
|
|
ULONG ulSize )
|
|
{
|
|
BYTE bChk = 0;
|
|
ULONG w, y;
|
|
USHORT wTotalLen = 4 + (USHORT) ulSize;
|
|
PCOMSYMBOL pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
PFUNCTION pFunction = HB_COMP_PARAM->functions.pFirst;
|
|
ULONG ulSymbolNameOffset = GetSymbolsSize( HB_COMP_PARAM ) + GetPCodesSize( HB_COMP_PARAM );
|
|
ULONG ulFunctionOffset;
|
|
|
|
if( ! HB_COMP_PARAM->fStartProc )
|
|
pFunction = pFunction->pNext;
|
|
|
|
putbyte( 0xA0, hObjFile, &bChk );
|
|
putword( wTotalLen, hObjFile, &bChk );
|
|
putbyte( 4, hObjFile, &bChk ); /* 2 = _DATA segment defined order */
|
|
putword( 0, hObjFile, &bChk ); /* 0 = offset */
|
|
|
|
for( y = 0; y < wSymbols; y++ )
|
|
{
|
|
* ( ULONG * ) symbol = ulSymbolNameOffset;
|
|
|
|
if( ! IsExternal( HB_COMP_PARAM, y ) )
|
|
{
|
|
ulFunctionOffset = ( hb_compFunctionGetPos( HB_COMP_PARAM, pSymbol->szName ) - 1 ) *
|
|
sizeof( prgFunction );
|
|
* ( ( ULONG * ) &symbol[ 8 ] ) = ulFunctionOffset; /* 8 offset of function pointer into symbol */
|
|
}
|
|
else
|
|
* ( ( ULONG * ) &symbol[ 8 ] ) = 0; /* 8 offset of function pointer into symbol */
|
|
|
|
if( pSymbol->cScope == HB_FS_MESSAGE )
|
|
symbol[ 4 ] = HB_FS_PUBLIC;
|
|
else
|
|
symbol[ 4 ] = pSymbol->cScope;
|
|
|
|
for( w = 0; w < wSymLen; w++ )
|
|
putbyte( * ( symbol + w ), hObjFile, &bChk );
|
|
|
|
ulSymbolNameOffset += strlen( pSymbol->szName ) + 1;
|
|
pSymbol = pSymbol->pNext;
|
|
}
|
|
|
|
while( pFunction )
|
|
{
|
|
w = 0;
|
|
while( w < pFunction->lPCodePos )
|
|
putbyte( pFunction->pCode[ w++ ], hObjFile, &bChk );
|
|
|
|
pFunction = pFunction->pNext;
|
|
}
|
|
|
|
pSymbol = GetFirstSymbol( HB_COMP_PARAM );
|
|
|
|
while( pSymbol )
|
|
{
|
|
for( w = 0; w < strlen( pSymbol->szName ); w++ )
|
|
putbyte( pSymbol->szName[ w ], hObjFile, &bChk );
|
|
|
|
putbyte( 0, hObjFile, &bChk );
|
|
pSymbol = pSymbol->pNext;
|
|
}
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void DefineSegment( FILE * hObjFile, BYTE bName, BYTE bClass, USHORT wLen )
|
|
{
|
|
BYTE bChk = 0;
|
|
|
|
putbyte( 0x98, hObjFile, &bChk );
|
|
putbyte( 7, hObjFile, &bChk ); /* SegDef records have always this length */
|
|
putbyte( 0, hObjFile, &bChk );
|
|
|
|
putbyte( 0xA9, hObjFile, &bChk );
|
|
putword( wLen, hObjFile, &bChk );
|
|
putbyte( bName, hObjFile, &bChk );
|
|
putbyte( bClass, hObjFile, &bChk );
|
|
putbyte( 0, hObjFile, &bChk );
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void PubDef( FILE * hObjFile, char * szName, USHORT wSegment, USHORT wOffset )
|
|
{
|
|
BYTE bChk = 0;
|
|
BYTE bChar;
|
|
USHORT wLen = 2 + 2 + strlen( szPrefix ) + strlen( szName ) + 2 + 1;
|
|
char * szTemp;
|
|
|
|
putbyte( 0x90, hObjFile, &bChk );
|
|
putword( wLen, hObjFile, &bChk );
|
|
putbyte( 0x00, hObjFile, &bChk );
|
|
putbyte( (BYTE) wSegment, hObjFile, &bChk );
|
|
putbyte( strlen( szPrefix ) + strlen( szName ), hObjFile, &bChk );
|
|
|
|
szTemp = szPrefix;
|
|
while( ( bChar = * szTemp++ ) != 0 )
|
|
putbyte( bChar, hObjFile, &bChk );
|
|
|
|
while( ( bChar = * szName++ ) != 0 )
|
|
putbyte( bChar, hObjFile, &bChk );
|
|
|
|
putword( wOffset, hObjFile, &bChk );
|
|
putbyte( 0x00, hObjFile, &bChk );
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void Fixup( FILE * hObjFile, BYTE bType, USHORT wOffset, BYTE bFlags, BYTE bSymbol )
|
|
{
|
|
BYTE bChk = 0;
|
|
|
|
putbyte( 0x9D, hObjFile, &bChk );
|
|
putword( 5, hObjFile, &bChk );
|
|
putbyte( bType + HB_HIBYTE( wOffset ), hObjFile, &bChk );
|
|
putbyte( HB_LOBYTE( wOffset ), hObjFile, &bChk );
|
|
putbyte( bFlags, hObjFile, &bChk );
|
|
putbyte( bSymbol, hObjFile, &bChk );
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void EnumeratedData( FILE * hObjFile, BYTE bSegment, BYTE * pData, USHORT wLen, USHORT wOffset )
|
|
{
|
|
BYTE bChk = 0;
|
|
USHORT w;
|
|
|
|
putbyte( 0xA0, hObjFile, &bChk );
|
|
putword( ( USHORT ) ( wLen + 4 ), hObjFile, &bChk );
|
|
putbyte( bSegment, hObjFile, &bChk );
|
|
putword( wOffset, hObjFile, &bChk );
|
|
|
|
for( w = 0; w < wLen; w++ )
|
|
putbyte( * ( pData + w ), hObjFile, &bChk );
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void End( FILE * hObjFile )
|
|
{
|
|
BYTE bChk = 0;
|
|
|
|
putbyte( 0x8A, hObjFile, &bChk );
|
|
putbyte( 0x02, hObjFile, &bChk );
|
|
putbyte( 0x00, hObjFile, &bChk );
|
|
putbyte( 0x00, hObjFile, &bChk );
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|
|
|
|
static void GroupDef( FILE * hObjFile, BYTE bName, BYTE * aSegs )
|
|
{
|
|
BYTE bChk = 0;
|
|
USHORT wRecLen = 2;
|
|
USHORT w = 0;
|
|
|
|
while( aSegs[ w++ ] )
|
|
wRecLen += 2;
|
|
|
|
putbyte( 0x9A, hObjFile, &bChk );
|
|
putword( wRecLen, hObjFile, &bChk );
|
|
putbyte( bName + 1, hObjFile, &bChk );
|
|
|
|
w = 0;
|
|
while( aSegs[ w ] )
|
|
{
|
|
putbyte( 0xFF, hObjFile, &bChk );
|
|
putbyte( aSegs[ w++ ], hObjFile, &bChk );
|
|
}
|
|
|
|
putbyte( 256 - bChk, hObjFile, &bChk );
|
|
}
|