Files
harbour-core/harbour/source/compiler/genhrb.c
Przemyslaw Czerpak 388dcfbd18 2009-09-02 14:08 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbcomp.h
  * harbour/include/hbcompdf.h
  * harbour/source/compiler/hbmain.c
  * harbour/source/compiler/genc.c
  * harbour/source/compiler/genhrb.c
    + added support for compiling multiple .prg modules into single
      compilation unit with repeated static or init/exit functions
      with the same name.
      Now Harbour compiler compiling .prg code from different .prg modules
      included by @<name>.clp or by SET PROCEDURE TO ... / DO ... [ WITH ... ]
      works exactly like Clipper. It supports separated file wide definitions
      for each compiled .prg module when -n switch is used and allows to
      use static or init/exit functions/procedures with the same names but
      in different modules.
      It resolves incompatibility often reported by [x]Harbour users.
      Now it's not longer necessary to update existing Clipper code.
      @.clp files and SET PROCEDURE TO ... / DO ... [ WITH ... ] are
      fully functional like in Clipper.
      AFAIR it was the last unintentional incompatibility with Clipper.

      TODO: add support for multiple static functions with the same name
            in .HRB files - it's necessary to change used format so I'll
            probably to that with .HRL support. Now when -gh switch is used
            harbour and such functions exists then compiler generates:
               Error E0002  Redefinition of procedure or function ...
      TODO: modify hbmk2 to pass @<name>.clp files directly to Harbour
            compiler so it can compile them just like Clipper does and
            generate single output file: <name>.<ext>

  * harbour/config/instsh.mk
    * disabled install command echo
2009-09-02 12:08:30 +00:00

178 lines
5.5 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Compiler Harbour Portable Object (.hrb) generation
*
* Copyright 1999 Eddie Runia <eddie@runia.com>
* www - http://www.harbour-project.org
*
* Copyright 2007 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* rewritten to work on memory buffers and with new compiler code
*
* 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"
#define SYM_NOLINK 0 /* symbol does not have to be linked */
#define SYM_FUNC 1 /* function defined in this module */
#define SYM_EXTERN 2 /* function defined in other module */
#define SYM_DEFERRED 3 /* lately bound function */
static ULONG hb_compHrbSize( HB_COMP_DECL, ULONG * pulSymbols, ULONG * pulFunctions )
{
PFUNCTION pFunc;
PCOMSYMBOL pSym;
ULONG ulSize;
* pulSymbols = * pulFunctions = 0;
/* count total size */
ulSize = 10; /* signature[4] + version[2] + symbols_number[4] */
pSym = HB_COMP_PARAM->symbols.pFirst;
while( pSym )
{
( * pulSymbols )++;
ulSize += strlen( pSym->szName ) + 3; /* \0 + symscope[1] + symtype[1] */
pSym = pSym->pNext;
}
ulSize += 4; /* functions_number[4] */
/* Generate functions data */
pFunc = HB_COMP_PARAM->functions.pFirst;
while( pFunc )
{
if( ( pFunc->funFlags & FUN_FILE_DECL ) == 0 )
{
( * pulFunctions )++;
ulSize += strlen( pFunc->szName ) + 5 + pFunc->lPCodePos; /* \0 + func_size[4] + function_body */
}
pFunc = pFunc->pNext;
}
return ulSize;
}
void hb_compGenBufPortObj( HB_COMP_DECL, BYTE ** pBufPtr, ULONG * pulSize )
{
PFUNCTION pFunc;
PCOMSYMBOL pSym;
ULONG ulSymbols, ulFunctions, ulLen;
BYTE * ptr;
* pulSize = hb_compHrbSize( HB_COMP_PARAM, &ulSymbols, &ulFunctions );
/* additional 0 byte is for passing buffer directly as string item */
ptr = * pBufPtr = ( BYTE * ) hb_xgrab( * pulSize + 1 );
/* signature */
*ptr++ = 0xC0;
*ptr++ = 'H';
*ptr++ = 'R';
*ptr++ = 'B';
HB_PUT_LE_UINT16( ptr, 2 ); /* version number */
ptr += 2;
HB_PUT_LE_UINT32( ptr, ulSymbols ); /* number of symbols */
ptr += 4;
/* generate the symbol table */
pSym = HB_COMP_PARAM->symbols.pFirst;
while( pSym )
{
ulLen = strlen( pSym->szName ) + 1;
memcpy( ptr, pSym->szName, ulLen );
ptr += ulLen;
/* TOFIX: this conversion strips upper byte from symbol scope
* Now we added workaround for it by using some strict
* bit order and restoring some others at runtime when
* .hrb file is loaded but we should create new format
* for .hrb files in which this field will have at least
* 16bit [druzus]
*/
*ptr++ = ( BYTE ) pSym->cScope;
/* symbol type */
if( pSym->cScope & HB_FS_LOCAL )
*ptr++ = SYM_FUNC; /* function defined in this module */
else if( pSym->cScope & HB_FS_DEFERRED )
*ptr++ = SYM_DEFERRED; /* lately bound function */
else if( pSym->iFunc )
*ptr++ = SYM_EXTERN; /* external function */
else
*ptr++ = SYM_NOLINK; /* other symbol */
pSym = pSym->pNext;
}
HB_PUT_LE_UINT32( ptr, ulFunctions ); /* number of functions */
ptr += 4;
/* generate functions data */
pFunc = HB_COMP_PARAM->functions.pFirst;
while( pFunc )
{
if( ( pFunc->funFlags & FUN_FILE_DECL ) == 0 )
{
ulLen = strlen( pFunc->szName ) + 1;
memcpy( ptr, pFunc->szName, ulLen );
ptr += ulLen;
HB_PUT_LE_UINT32( ptr, pFunc->lPCodePos ); /* function size */
ptr += 4;
memcpy( ptr, pFunc->pCode, pFunc->lPCodePos ); /* function body */
ptr += pFunc->lPCodePos;
}
pFunc = pFunc->pNext;
}
}
void hb_compGenPortObj( HB_COMP_DECL, PHB_FNAME pFileName )
{
char szFileName[ HB_PATH_MAX ];
ULONG ulSize;
BYTE * pHrbBody;
FILE * yyc;
if( ! pFileName->szExtension )
pFileName->szExtension = ".hrb";
hb_fsFNameMerge( szFileName, pFileName );
yyc = hb_fopen( szFileName, "wb" );
if( ! yyc )
{
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 Harbour Portable Object source output to \'%s\'... ", szFileName );
hb_compOutStd( HB_COMP_PARAM, buffer );
}
hb_compGenBufPortObj( HB_COMP_PARAM, &pHrbBody, &ulSize );
if( fwrite( pHrbBody, ulSize, 1, yyc ) != 1 )
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FILE_WRITE, szFileName, NULL );
hb_xfree( pHrbBody );
fclose( yyc );
if( ! HB_COMP_PARAM->fQuiet )
hb_compOutStd( HB_COMP_PARAM, "Done.\n" );
}