Files
harbour-core/harbour/src/compiler/genobj32.c
Viktor Szakats 1b080a03f9 2009-10-09 16:53 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
- source
  + src
  * src/Makefile
  * src/dynlib/mt/Makefile
  * src/dynlib/Makefile
  * INSTALL
  * Makefile
  * ChangeLog
  * harbour.spec
  * mpkg_tgz.sh
    * Renamed 'source' dir to 'src' to move closer to other FOSS 
      projects. It's also easier to type, plus it has the side 
      effect that some cmdlines will be shorter in the 
      build process.
2009-10-09 14:54:14 +00:00

660 lines
20 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 BYTE s_prgFunction[] = { 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x83, 0xC4, 0x08, 0xC3 };
static char * * s_externNames = NULL;
static USHORT s_wExternals = 1; /* _hb_vmExecute is always added */
static const char * s_szPrefix = "_HB_FUN_";
static USHORT hb_compFunctionGetPos( HB_COMP_DECL, char * szFunctionName ) /* return 0 if not found or order + 1 */
{
PFUNCTION pFunc = HB_COMP_PARAM->functions.pFirst;
USHORT wFunction = HB_COMP_PARAM->fStartProc ? 1 : 0;
while( pFunc )
{
if( ! strcmp( pFunc->szName, szFunctionName ) && pFunc != HB_COMP_PARAM->functions.pFirst )
return wFunction;
wFunction++;
pFunc = pFunc->pNext;
}
return 0;
}
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 < s_wExternals )
{
if( ! strcmp( szExternal, s_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( s_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( s_prgFunction ) );
w++;
pFunc = pFunc->pNext;
}
CodeSegment( HB_COMP_PARAM, hObjFile, s_prgFunction, sizeof( s_prgFunction ), wFunctions );
for( w = 0; w < wFunctions; w++ )
{
/* s_prgFunction fixups */
Fixup( hObjFile, 0xE4, ( w * sizeof( s_prgFunction ) ) + 1,
0x54, 4 ); /* 4 = DATA segment defined order */
Fixup( hObjFile, 0xE4, ( w * sizeof( s_prgFunction ) ) + 6,
0x54, 4 ); /* DATA segment define order - pcode location */
Fixup( hObjFile, 0xA4, ( w * sizeof( s_prgFunction ) ) + 11,
0x56, 1 ); /* External: _hb_vmExecute */
}
}
static void GenerateExternals( HB_COMP_DECL, FILE * hObjFile )
{
USHORT w;
PFUNCALL pFunc;
PFUNCTION 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 )
s_wExternals++;
pFunc = pFunc->pNext;
}
if( s_wExternals )
{
s_externNames = ( char * * ) hb_xgrab( sizeof( char * ) * ( s_wExternals + 2 ) );
w = 1;
s_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 )
s_externNames[ w++ ] = pFunc->szName;
pFunc = pFunc->pNext;
}
s_externNames[ w ] = 0;
ExternalNames( hObjFile, s_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( s_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( s_szPrefix ) + strlen( szNames[ b ] ), hObjFile, &bChk );
c = 0;
if( b > 0 )
{
while( s_szPrefix[ c ] )
putbyte( s_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( s_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( s_szPrefix ) + strlen( szName ) + 2 + 1;
const char * szTemp;
putbyte( 0x90, hObjFile, &bChk );
putword( wLen, hObjFile, &bChk );
putbyte( 0x00, hObjFile, &bChk );
putbyte( (BYTE) wSegment, hObjFile, &bChk );
putbyte( strlen( s_szPrefix ) + strlen( szName ), hObjFile, &bChk );
szTemp = s_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 );
}
void hb_compGenObj32( HB_COMP_DECL, PHB_FNAME pFileName )
{
char szFileName[ HB_PATH_MAX ];
FILE * hObjFile; /* file handle for OBJ output */
char * szVer;
if( ! pFileName->szExtension )
pFileName->szExtension = ".obj";
hb_fsFNameMerge( szFileName, pFileName );
if( ( hObjFile = hb_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 )
{
char buffer[ 80 + HB_PATH_MAX - 1 ];
hb_snprintf( buffer, sizeof( buffer ),
"Generating Windows/DOS OBJ32 output to \'%s\'... ", szFileName );
hb_compOutStd( HB_COMP_PARAM, buffer );
}
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 );
if( s_externNames )
{
hb_xfree( s_externNames );
s_externNames = NULL;
}
fclose( hObjFile );
if( ! HB_COMP_PARAM->fQuiet )
hb_compOutStd( HB_COMP_PARAM, "Done.\n" );
}