* harbour/source/codepage/cp_tpl.c
+ Added NOTE about the fact that hb_Translate()
(and hb_cdpTranslate()) would only work properly
if all codepages for the same language are using the
exact same number of lowercase/uppercase cp chars
in the exact same order.
* harbour/source/codepage/Makefile
* harbour/common.mak
* harbour/source/codepage/cphu852.c
* harbour/source/codepage/cphu852s.c
* harbour/source/codepage/cphuiso.c
+ harbour/source/codepage/cphuisos.c
* harbour/source/codepage/cphuwin.c
+ harbour/source/codepage/cphuwins.c
! Synced HU WIN and HU ISO codepage lower/uppercase
strings with HU 852, so that hb_Translate() works
properly. (this means there are now several duplicate
chars included in the WIN/ISO versions, along with
a non-HU char, all just needed to stay compatible with
original CA-Cl*pper HU/852 index ordering and keep
hb_Translate() working at the same time.)
IMO, we'd need to introduce a separate "collation"
string in each cp file to detach index ordering
from upper/lowercase and codepage translation without
any hacks, since as this example shows these two
are not always in sync. (or, as an alternative we might
want to make codepage translation more sophisticated,
like converting first to unicode and convert back to
the other codepage from unicode, but that leads a bit
further.). (If I'm missing something, pls don't hesitate
to clarify)
+ Added SixDriver compatible HU ISO/WIN codepage files
for the reasons described above.
* harbour/include/hbapicdp.h
* harbour/source/rtl/cdpapi.c
* harbour/source/codepage/cpbg866.c
* harbour/source/codepage/cpbgiso.c
* harbour/source/codepage/cpbgwin.c
* harbour/source/codepage/cpcs852.c
* harbour/source/codepage/cpcsiso.c
* harbour/source/codepage/cpcskam.c
* harbour/source/codepage/cpcswin.c
* harbour/source/codepage/cpeldos.c
* harbour/source/codepage/cpelwin.c
* harbour/source/codepage/cpesdos.c
* harbour/source/codepage/cpesmwi.c
* harbour/source/codepage/cpeswin.c
* harbour/source/codepage/cpfrdos.c
* harbour/source/codepage/cpgedos.c
* harbour/source/codepage/cpgewin.c
* harbour/source/codepage/cphr1250.c
* harbour/source/codepage/cphr437.c
* harbour/source/codepage/cphr852.c
* harbour/source/codepage/cphu852.c
* harbour/source/codepage/cphu852s.c
* harbour/source/codepage/cphuiso.c
* harbour/source/codepage/cphuwin.c
* harbour/source/codepage/cpit437.c
* harbour/source/codepage/cpit850.c
* harbour/source/codepage/cpitisb.c
* harbour/source/codepage/cpitiso.c
* harbour/source/codepage/cpltwin.c
* harbour/source/codepage/cppl852.c
* harbour/source/codepage/cppliso.c
* harbour/source/codepage/cpplmaz.c
* harbour/source/codepage/cpplwin.c
* harbour/source/codepage/cppt850.c
* harbour/source/codepage/cpptiso.c
* harbour/source/codepage/cpru866.c
* harbour/source/codepage/cprukoi.c
* harbour/source/codepage/cpruwin.c
* harbour/source/codepage/cpsl437.c
* harbour/source/codepage/cpsl852.c
* harbour/source/codepage/cpsliso.c
* harbour/source/codepage/cpslwin.c
* harbour/source/codepage/cpsrwin.c
* harbour/source/codepage/cptrdos.c
* harbour/source/codepage/cptrwin.c
* harbour/source/codepage/cpua866.c
* harbour/source/codepage/cpuakoi.c
* harbour/source/codepage/cpuawin.c
* harbour/source/codepage/uc1250.c
* harbour/source/codepage/uc1251.c
* harbour/source/codepage/uc1253.c
* harbour/source/codepage/uc1254.c
* harbour/source/codepage/uc1257.c
* harbour/source/codepage/uc737.c
* harbour/source/codepage/uc850.c
* harbour/source/codepage/uc852.c
* harbour/source/codepage/uc857.c
* harbour/source/codepage/uc866.c
* harbour/source/codepage/uc88591b.c
* harbour/source/codepage/uc8859_1.c
* harbour/source/codepage/uc8859_2.c
* harbour/source/codepage/uc8859_5.c
* harbour/source/codepage/uckam.c
* harbour/source/codepage/uckoi8.c
* harbour/source/codepage/uckoi8u.c
* harbour/source/codepage/ucmaz.c
! #define namespace issue in public API header file
corrected:
CPID_* -> HB_CPID_*
UNITB_* -> HB_UNITB_*
* harbour/source/compiler/gencobj.c
! Fixed warning.
309 lines
8.9 KiB
C
309 lines
8.9 KiB
C
/*
|
||
* $Id$
|
||
*/
|
||
|
||
/*
|
||
* Harbour Project source code:
|
||
* Native compiler object module generation from Harbour C output.
|
||
*
|
||
* Copyright 2001 Jos‚ Lal¡n <dezac@corevia.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"
|
||
#include "hb_io.h"
|
||
|
||
#define HB_CFG_FILENAME "harbour.cfg"
|
||
|
||
/* QUESTION: Allocate buffer dynamically ? */
|
||
#define HB_CFG_LINE_LEN ( _POSIX_PATH_MAX )
|
||
|
||
#if defined( HOST_OS_UNIX_COMPATIBLE )
|
||
#define HB_NULL_STR " > /dev/null"
|
||
#define HB_ACCESS_FLAG F_OK
|
||
#elif defined( OS_DOS_COMPATIBLE )
|
||
#define HB_NULL_STR " >nul"
|
||
#define HB_ACCESS_FLAG 0
|
||
#else
|
||
#define HB_ACCESS_FLAG 0
|
||
#endif
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
static char * hb_searchpath( const char * pszFile, char * pszEnv, char * pszCfg )
|
||
{
|
||
char * pszPath;
|
||
BOOL bFound = FALSE;
|
||
|
||
/* Check current dir first */
|
||
if( access( ( const char * ) pszFile, HB_ACCESS_FLAG ) == 0 )
|
||
{
|
||
snprintf( pszCfg, _POSIX_PATH_MAX + 1, "%s", pszFile );
|
||
return ( char * ) pszFile;
|
||
}
|
||
else
|
||
{
|
||
/* Check if pszFile exists somewhere in the path */
|
||
while( * pszEnv )
|
||
{
|
||
pszPath = pszEnv;
|
||
while( *pszEnv )
|
||
{
|
||
if( *pszEnv == OS_PATH_LIST_SEPARATOR )
|
||
{
|
||
*pszEnv++ = '\0';
|
||
break;
|
||
}
|
||
pszEnv++;
|
||
}
|
||
if( *pszPath )
|
||
{
|
||
snprintf( pszCfg, _POSIX_PATH_MAX + 1, "%s%c%s", pszPath, OS_PATH_DELIMITER, pszFile );
|
||
if( access( ( const char * ) pszCfg, HB_ACCESS_FLAG ) == 0 )
|
||
{
|
||
bFound = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* If not found, make sure to return a NULL string */
|
||
if( ! bFound )
|
||
*pszCfg = '\0';
|
||
|
||
return ( char * ) pszCfg;
|
||
}
|
||
|
||
/* Builds platform dependant object module from Harbour C output */
|
||
void hb_compGenCObj( HB_COMP_DECL, PHB_FNAME pFileName )
|
||
{
|
||
char szFileName[ _POSIX_PATH_MAX + 1 ];
|
||
char szLine[ HB_CFG_LINE_LEN ];
|
||
char szCompiler[ HB_CFG_LINE_LEN + 1 ] = "";
|
||
char szOptions[ HB_CFG_LINE_LEN + 1 ] = "";
|
||
char szCommandLine[ HB_CFG_LINE_LEN * 2 + 1 ];
|
||
char szOutPath[ _POSIX_PATH_MAX + 1 ] = "\0";
|
||
char pszTemp[ _POSIX_PATH_MAX + 1 ] = "";
|
||
#if defined( HOST_OS_UNIX_COMPATIBLE )
|
||
char * pszEnv = hb_strdup( "/etc:/usr/local/etc" );
|
||
#elif defined( OS_DOS_COMPATIBLE )
|
||
char * pszEnv = hb_getenv( "PATH" );
|
||
#else
|
||
char * pszEnv = NULL;
|
||
#endif
|
||
char * pszCfgFileName = hb_getenv( "HB_CFG_FILE" );
|
||
FILE * filecfg;
|
||
BOOL bVerbose = FALSE; /* Don't show C compiler messages (default). */
|
||
BOOL bDelTmp = TRUE; /* Delete intermediate C file (default). */
|
||
int iSuccess;
|
||
|
||
HB_SYMBOL_UNUSED( HB_COMP_PARAM );
|
||
|
||
/* First pass: build the C output */
|
||
|
||
/* Force file extension to avoid collisions when called from a make utility */
|
||
pFileName->szExtension = ".c";
|
||
hb_fsFNameMerge( szFileName, pFileName );
|
||
hb_compGenCCode( HB_COMP_PARAM, HB_COMP_PARAM->pFileName );
|
||
|
||
/* Begin second pass */
|
||
|
||
/* Set up things */
|
||
|
||
if( !pszCfgFileName )
|
||
{
|
||
pszCfgFileName = HB_CFG_FILENAME;
|
||
}
|
||
|
||
if( pszEnv && *hb_searchpath( pszCfgFileName, pszEnv, pszTemp ) )
|
||
{
|
||
filecfg = fopen( pszTemp, "rt" );
|
||
if( ! filecfg )
|
||
{
|
||
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_OPEN_CFG, szFileName, NULL );
|
||
if( pszEnv )
|
||
hb_xfree( ( void * ) pszEnv );
|
||
|
||
if( pszCfgFileName )
|
||
hb_xfree( ( void * ) pszCfgFileName );
|
||
|
||
return;
|
||
}
|
||
|
||
while( fgets( szLine, HB_CFG_LINE_LEN, filecfg ) != NULL )
|
||
{
|
||
ULONG ulLen;
|
||
char * szStr = szLine;
|
||
char * szToken;
|
||
|
||
/* Trim left */
|
||
while( HB_ISSPACE( *szStr ) )
|
||
szStr++;
|
||
|
||
/* Trim right */
|
||
ulLen = strlen( szStr );
|
||
while( ulLen && HB_ISSPACE( szStr[ ulLen - 1 ] ) )
|
||
ulLen--;
|
||
|
||
szStr[ ulLen ] = '\0';
|
||
/* TODO: Check for comments within macros, i.e: CC=bcc32 #comment */
|
||
|
||
if( *szStr )
|
||
{
|
||
szToken = strchr( szStr, '=' );
|
||
|
||
if( szToken )
|
||
{
|
||
*szToken++ = '\0';
|
||
if ( *szToken )
|
||
{
|
||
/* Checks compiler name */
|
||
if( ! hb_stricmp( szStr, "CC" ) )
|
||
{
|
||
snprintf( szCompiler, sizeof( szCompiler ), "%s", szToken );
|
||
}
|
||
/* Checks optional switches */
|
||
else if( ! hb_stricmp( szStr, "CFLAGS" ) )
|
||
{
|
||
snprintf( szOptions, sizeof( szCompiler ), "%s", szToken );
|
||
}
|
||
/* Wanna see C compiler output ? */
|
||
else if( ! hb_stricmp( szStr, "VERBOSE" ) )
|
||
{
|
||
if( ! hb_stricmp( szToken, "YES" ) )
|
||
bVerbose = TRUE;
|
||
}
|
||
/* Delete intermediate C file ? */
|
||
else if( ! hb_stricmp( szStr, "DELTMP" ) )
|
||
{
|
||
if( ! hb_stricmp( szToken, "NO" ) )
|
||
bDelTmp = FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fclose( filecfg );
|
||
|
||
} else {
|
||
|
||
printf( "\nError: Can't find %s file in %s.\n", pszCfgFileName, pszEnv );
|
||
printf( "%s should be a text file that contains:\n", pszCfgFileName );
|
||
printf( "CC=C compiler binary name eg. CC=gcc\n" );
|
||
printf( "CFLAGS=C compiler options eg. -c -I<includes>\n" );
|
||
printf( " ( 'compile only' and harbour include dir are mandatory )\n" );
|
||
printf( "VERBOSE=NO|YES to show steps messages default is NO\n" );
|
||
printf( "DELTMP=NO|YES to delete generated C source default is YES\n" );
|
||
printf( "remember also to properly set the C compiler env.\n" );
|
||
|
||
if( pszEnv )
|
||
hb_xfree( ( void * ) pszEnv );
|
||
|
||
if( pszCfgFileName )
|
||
hb_xfree( ( void * ) pszCfgFileName );
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
if( pszEnv )
|
||
hb_xfree( ( void * ) pszEnv );
|
||
|
||
if( pszCfgFileName )
|
||
hb_xfree( ( void * ) pszCfgFileName );
|
||
|
||
if( ! HB_COMP_PARAM->fQuiet )
|
||
{
|
||
printf( "\nBuilding object module for \'%s\'\nusing C compiler \'%s\' as defined in \'%s\'...\n", szFileName, szCompiler, pszCfgFileName );
|
||
fflush( stdout );
|
||
}
|
||
|
||
/* Check if -o<path> was used */
|
||
if( HB_COMP_PARAM->pOutPath )
|
||
{
|
||
PHB_FNAME pOut = hb_fsFNameSplit( ( char * ) szFileName );
|
||
|
||
if( HB_COMP_PARAM->pOutPath->szPath )
|
||
pOut->szPath = HB_COMP_PARAM->pOutPath->szPath;
|
||
|
||
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__WATCOMC__)
|
||
pOut->szExtension = ".obj";
|
||
#else
|
||
pOut->szExtension = ".o"; /* Don't know if we can hardcode it for Un*x */
|
||
#endif
|
||
hb_fsFNameMerge( pszTemp, pOut );
|
||
|
||
#if defined(_MSC_VER)
|
||
hb_strncat( szOutPath, "-Fo", sizeof( szOutPath ) - 1 );
|
||
#elif defined(__WATCOMC__)
|
||
hb_strncat( szOutPath, "-fo=", sizeof( szOutPath ) - 1 );
|
||
#else
|
||
hb_strncat( szOutPath, "-o", sizeof( szOutPath ) - 1 );
|
||
#endif
|
||
|
||
hb_strncat( szOutPath, pszTemp, sizeof( szOutPath ) - 1 );
|
||
|
||
hb_xfree( pOut );
|
||
}
|
||
|
||
if( *szCompiler )
|
||
{
|
||
snprintf( szCommandLine, sizeof( szCommandLine ), "%s %s %s %s", szCompiler, szOptions, szOutPath, szFileName );
|
||
|
||
if( bVerbose )
|
||
{
|
||
printf( "Exec: %s\n", szCommandLine ) ;
|
||
}
|
||
else
|
||
{
|
||
hb_strncat( szCommandLine, HB_NULL_STR, sizeof( szCommandLine ) - 1 );
|
||
}
|
||
|
||
/* Compile it! */
|
||
iSuccess = ( system( szCommandLine ) != -1 );
|
||
|
||
/* Delete intermediate .c file */
|
||
/* QUESTION: Leave this file if C compiler fails ? */
|
||
if( bDelTmp ) /* && iSuccess ) */
|
||
{
|
||
if( bVerbose )
|
||
{
|
||
printf( "Deleting: \"%s\"\n", szFileName );
|
||
}
|
||
|
||
remove( ( char * ) szFileName );
|
||
|
||
}
|
||
|
||
if( ! HB_COMP_PARAM->fQuiet )
|
||
{
|
||
if( iSuccess )
|
||
printf( "Done.\n" );
|
||
else
|
||
printf( "\nFailed to execute: \"%s\"\n", szCommandLine );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
printf( "\nError: No compiler defined in %s\n", pszCfgFileName );
|
||
}
|
||
}
|