Files
harbour-core/src/vm/cmdarg.c
2013-10-09 20:08:24 +02:00

942 lines
23 KiB
C

/*
* Harbour Project source code:
* Command line and environment argument management
*
* Copyright 1999-2001 Viktor Szakats (vszakats.net/harbour)
* www - http://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, 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 software; see the file COPYING.txt. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
/* NOTE: Need to have these before Harbour headers,
because in MT mode, they will automatically #include <os2.h>. */
#define INCL_DOSPROCESS
#define INCL_DOSERRORS
#define INCL_DOSMODULEMGR
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapifs.h"
#include "hbapicdp.h"
#include "hbvm.h"
#include "hbmemory.ch"
#include "hbstack.h"
#include "hbverbld.h"
#if defined( HB_OS_OS2 )
#include <os2.h>
#endif
/* Command line argument management */
static int s_argc = 0;
static char ** s_argv = NULL;
#if ! defined( HB_OS_WIN )
static char s_szAppName[ HB_PATH_MAX ];
#else
#include "hbwinuni.h"
#include <windows.h>
static LPTSTR * s_lpArgV = NULL;
#if defined( UNICODE )
static LPSTR * s_lpArgVStr = NULL;
#endif
static HANDLE s_hInstance = 0;
static HANDLE s_hPrevInstance = 0;
static int s_iCmdShow = 0;
static HB_BOOL s_WinMainParam = HB_FALSE;
#define HB_WINARG_ALLOC( n ) HeapAlloc( GetProcessHeap(), 0, ( n ) )
#define HB_WINARG_FREE( p ) HeapFree( GetProcessHeap(), 0, ( p ) )
void hb_winmainArgVBuild( void )
{
LPCTSTR lpCmdLine, lpSrc;
LPTSTR * lpArgV;
LPTSTR lpDst, lpArg, lpModuleName;
HB_SIZE nSize, nModuleName;
int iArgC;
HB_BOOL fQuoted;
/* NOTE: MAX_PATH used intentionally instead of HB_MAX_PATH */
lpModuleName = ( LPTSTR ) HB_WINARG_ALLOC( ( MAX_PATH + 1 ) * sizeof( TCHAR ) );
nModuleName = GetModuleFileName( NULL, lpModuleName, MAX_PATH + 1 );
if( nModuleName )
nModuleName++;
HB_WINARG_FREE( lpModuleName );
lpCmdLine = GetCommandLine();
lpArgV = NULL;
nSize = 0;
iArgC = -1;
while( lpCmdLine && ! lpArgV && iArgC != 0 )
{
if( nSize != 0 )
{
lpArgV = ( LPTSTR * ) HB_WINARG_ALLOC( iArgC * sizeof( LPTSTR ) +
nSize * sizeof( TCHAR ) );
lpDst = ( LPTSTR ) ( lpArgV + iArgC );
lpArgV[ 0 ] = lpDst;
lpDst += nModuleName;
}
else
{
lpDst = ( LPTSTR ) lpCmdLine;
nSize = nModuleName;
}
lpSrc = lpCmdLine;
lpArg = NULL;
iArgC = 0;
fQuoted = HB_FALSE;
while( *lpSrc != 0 )
{
if( *lpSrc == TEXT( '"' ) )
{
if( lpArg == NULL )
lpArg = lpDst;
fQuoted = ! fQuoted;
}
else if( fQuoted || ! HB_ISSPACE( *lpSrc ) )
{
if( lpArg == NULL )
lpArg = lpDst;
if( iArgC > 0 || nModuleName == 0 )
{
if( lpArgV )
*lpDst++ = *lpSrc;
else
nSize++;
}
}
else
{
if( lpArg )
{
if( iArgC > 0 || nModuleName == 0 )
{
if( lpArgV )
{
*lpDst++ = '\0';
lpArgV[ iArgC ] = lpArg;
}
else
nSize++;
}
iArgC++;
lpArg = NULL;
}
}
++lpSrc;
}
if( lpArg )
{
if( iArgC > 0 || nModuleName == 0 )
{
if( lpArgV )
{
*lpDst = '\0';
lpArgV[ iArgC ] = lpArg;
}
else
nSize++;
}
iArgC++;
}
}
if( iArgC <= 0 )
{
if( nModuleName != 0 )
{
iArgC = 1;
lpArgV = ( LPTSTR * ) HB_WINARG_ALLOC( iArgC * sizeof( LPTSTR ) +
nModuleName * sizeof( TCHAR ) );
lpArgV[ 0 ] = ( LPTSTR ) ( lpArgV + iArgC );
}
else
iArgC = 0;
}
if( iArgC > 0 && nModuleName != 0 )
{
/* NOTE: Manually setup the executable name in Windows,
because in console apps the name may be truncated
in some cases, and in GUI apps it's not filled
at all. [vszakats] */
if( GetModuleFileName( NULL, lpArgV[ 0 ], nModuleName ) != 0 )
{
/* Windows XP does not set trailing 0 if buffer is not large enough [druzus] */
lpArgV[ 0 ][ nModuleName - 1 ] = 0;
}
}
hb_winmainArgVFree();
if( iArgC > 0 )
{
s_lpArgV = lpArgV;
s_argc = iArgC;
#if defined( UNICODE )
{
LPSTR lpStr;
nSize = 0;
for( iArgC = 0; iArgC < s_argc; ++iArgC )
nSize += hb_wctomblen( s_lpArgV[ iArgC ] ) + 1;
s_lpArgVStr = ( LPSTR * ) HB_WINARG_ALLOC( s_argc * sizeof( LPSTR ) +
nSize * sizeof( char ) );
lpStr = ( LPSTR ) ( s_lpArgVStr + s_argc );
for( iArgC = 0; iArgC < s_argc; ++iArgC )
{
nSize = hb_wctomblen( s_lpArgV[ iArgC ] ) + 1;
hb_wcntombcpy( lpStr, s_lpArgV[ iArgC ], nSize - 1 );
s_lpArgVStr[ iArgC ] = lpStr;
lpStr += nSize;
}
s_argv = s_lpArgVStr;
}
#else
s_argv = s_lpArgV;
#endif
}
}
void hb_winmainArgVFree( void )
{
if( s_lpArgV )
{
#if defined( UNICODE )
if( s_lpArgVStr )
{
if( s_argv == s_lpArgVStr )
s_argv = NULL;
HB_WINARG_FREE( s_lpArgVStr );
s_lpArgVStr = NULL;
}
#else
if( s_argv == s_lpArgV )
s_argv = NULL;
#endif
HB_WINARG_FREE( s_lpArgV );
s_lpArgV = NULL;
s_argc = 0;
}
}
void hb_winmainArgInit( void * hInstance, void * hPrevInstance, int iCmdShow )
{
s_hInstance = ( HANDLE ) hInstance;
s_hPrevInstance = ( HANDLE ) hPrevInstance;
s_iCmdShow = iCmdShow;
s_WinMainParam = HB_TRUE;
}
HB_BOOL hb_winmainArgGet( void * phInstance, void * phPrevInstance, int * piCmdShow )
{
if( phInstance )
*( ( HANDLE * ) phInstance ) = s_hInstance;
if( phPrevInstance )
*( ( HANDLE * ) phPrevInstance ) = s_hPrevInstance;
if( piCmdShow )
*piCmdShow = s_iCmdShow;
return s_WinMainParam;
}
#endif
void hb_cmdargInit( int argc, char * argv[] )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_cmdargInit(%d, %p)", argc, argv ) );
#if defined( HB_OS_WIN )
if( s_lpArgV )
return;
#endif
if( argc == 0 || argv == NULL )
{
s_argc = 0;
s_argv = NULL;
}
else
{
s_argc = argc;
s_argv = argv;
}
}
int hb_cmdargARGC( void )
{
return s_argc;
}
char ** hb_cmdargARGV( void )
{
return s_argv;
}
const char * hb_cmdargARGVN( int argc )
{
return argc >= 0 && argc < s_argc ? s_argv[ argc ] : NULL;
}
/* NOTE: Pointer must be freed with hb_xfree() if not NULL */
static char * hb_cmdargDup( int argc )
{
#if defined( HB_OS_WIN )
if( s_lpArgV )
return argc >= 0 && argc < s_argc ? HB_OSSTRDUP( s_lpArgV[ argc ] ) : NULL;
#endif
return argc >= 0 && argc < s_argc ? hb_osStrDecode( s_argv[ argc ] ) : NULL;
}
void hb_cmdargUpdate( void )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_cmdargUpdate()" ) );
#if ! defined( HB_OS_WIN )
if( s_argc > 0 )
{
# if defined( HB_OS_OS2 )
{
PPIB ppib = NULL;
APIRET ulrc;
ulrc = DosGetInfoBlocks( NULL, &ppib );
if( ulrc == NO_ERROR )
{
ulrc = DosQueryModuleName( ppib->pib_hmte,
HB_SIZEOFARRAY( s_szAppName ),
s_szAppName );
if( ulrc == NO_ERROR )
s_argv[ 0 ] = s_szAppName;
}
}
# else
/* NOTE: try to create absolute path from s_argv[ 0 ] if necessary */
{
PHB_FNAME pFName = hb_fsFNameSplit( s_argv[ 0 ] );
HB_BOOL fInPath = HB_FALSE;
if( ! pFName->szPath )
{
char * pszPATH = hb_getenv( "PATH" );
if( pszPATH && *pszPATH )
{
HB_PATHNAMES * pSearchPath = NULL, * pNextPath;
hb_fsAddSearchPath( pszPATH, &pSearchPath );
pNextPath = pSearchPath;
while( pNextPath )
{
pFName->szPath = pNextPath->szPath;
hb_fsFNameMerge( s_szAppName, pFName );
if( hb_fsFileExists( s_szAppName ) )
{
/* even if the file is located using PATH then it does
* not mean we will have absolute path here. It's not
* good idea but PATH envvar can also contain relative
* directories, f.e. "." or "bin" so we should add
* current directory if necessary in code below.
*/
hb_xfree( pFName );
pFName = hb_fsFNameSplit( s_szAppName );
fInPath = HB_TRUE;
break;
}
pNextPath = pNextPath->pNext;
}
hb_fsFreeSearchPath( pSearchPath );
if( ! fInPath )
pFName->szPath = NULL;
}
if( pszPATH )
hb_xfree( pszPATH );
}
if( pFName->szPath )
{
# if defined( HB_OS_HAS_DRIVE_LETTER )
if( pFName->szPath[ 0 ] != HB_OS_PATH_DELIM_CHR && ! pFName->szDrive )
# else
if( pFName->szPath[ 0 ] != HB_OS_PATH_DELIM_CHR )
# endif
{
if( pFName->szPath[ 0 ] == '.' &&
pFName->szPath[ 1 ] == HB_OS_PATH_DELIM_CHR )
pFName->szPath += 2;
s_szAppName[ 0 ] = HB_OS_PATH_DELIM_CHR;
hb_fsCurDirBuff( 0, s_szAppName + 1, HB_PATH_MAX - 1 );
if( s_szAppName[ 1 ] != 0 )
{
hb_strncat( s_szAppName, HB_OS_PATH_DELIM_CHR_STRING, HB_PATH_MAX - 1 );
hb_strncat( s_szAppName, pFName->szPath, HB_PATH_MAX - 1 );
pFName->szPath = hb_strdup( s_szAppName );
hb_fsFNameMerge( s_szAppName, pFName );
hb_xfree( ( void * ) pFName->szPath );
s_argv[ 0 ] = s_szAppName;
}
}
else if( fInPath )
s_argv[ 0 ] = s_szAppName;
}
hb_xfree( pFName );
}
# endif
}
#endif
}
/* places application parameters on the HVM stack */
int hb_cmdargPushArgs( void )
{
int iArgCount = 0, i;
for( i = 1; i < s_argc; i++ )
{
/* Filter out any parameters beginning with //, like //INFO */
if( ! hb_cmdargIsInternal( s_argv[ i ], NULL ) )
{
#if defined( HB_OS_WIN )
if( s_lpArgV )
HB_ITEMPUTSTR( hb_stackAllocItem(), s_lpArgV[ i ] );
else
#endif
hb_vmPushString( s_argv[ i ], strlen( s_argv[ i ] ) );
iArgCount++;
}
}
return iArgCount;
}
HB_BOOL hb_cmdargIsInternal( const char * szArg, int * piLen )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_cmdargIsInternal(%s, %p)", szArg, piLen ) );
/* NOTE: Not checking for '--' here, as it would filter out
valid command line options used by applications. [vszakats] */
if( hb_strnicmp( szArg, "--hb:", 5 ) == 0 ||
hb_strnicmp( szArg, "//hb:", 5 ) == 0 )
{
if( piLen )
*piLen = 5;
return HB_TRUE;
}
else if( strlen( szArg ) >= 2 &&
szArg[ 0 ] == '/' &&
szArg[ 1 ] == '/' )
{
if( piLen )
*piLen = 2;
return HB_TRUE;
}
return HB_FALSE;
}
static char * hb_cmdargGet( const char * pszName, HB_BOOL bRetValue )
{
char * pszRetVal = NULL;
char * pszEnvVar;
int i;
int iPrefixLen;
HB_TRACE( HB_TR_DEBUG, ( "hb_cmdargGet(%s, %d)", pszName, ( int ) bRetValue ) );
/* Check the command line first */
for( i = 1; i < s_argc; i++ )
{
if( hb_cmdargIsInternal( s_argv[ i ], &iPrefixLen ) &&
hb_strnicmp( s_argv[ i ] + iPrefixLen, pszName, strlen( pszName ) ) == 0 )
{
if( bRetValue )
{
#if defined( HB_OS_WIN )
if( s_lpArgV )
{
LPCTSTR lpPos = s_lpArgV[ i ] + iPrefixLen + strlen( pszName );
if( *lpPos == TEXT( ':' ) )
lpPos++;
return HB_OSSTRDUP( lpPos );
}
else
#endif
{
char * pszPos = s_argv[ i ] + iPrefixLen + strlen( pszName );
if( *pszPos == ':' )
pszPos++;
return hb_osStrDecode( pszPos );
}
}
else
return ( char * ) "";
}
}
/* Check the environment variable */
pszEnvVar = hb_getenv( "HARBOUR" );
if( ! pszEnvVar || pszEnvVar[ 0 ] == '\0' )
{
if( pszEnvVar )
hb_xfree( pszEnvVar );
pszEnvVar = hb_getenv( "CLIPPER" );
}
if( pszEnvVar && pszEnvVar[ 0 ] != '\0' )
{
char * pszNext = pszEnvVar;
/* Step through all envvar switches. */
/* NOTE: CA-Cl*pper doesn't need the switches to be separated by any
chars at all, Harbour is more strict/standard in this respect,
it requires the switches to be separated. */
i = ( int ) strlen( pszName );
while( *pszNext )
{
static const char * s_szSeparator = " ;,\t";
char * pszEnd;
/* Skip the separators */
while( *pszNext && strchr( s_szSeparator, *pszNext ) )
pszNext++;
/* The // is optional in the envvar */
if( hb_cmdargIsInternal( pszNext, &iPrefixLen ) )
pszNext += iPrefixLen;
pszEnd = pszNext;
/* Search for the end of this switch */
while( *pszEnd && strchr( s_szSeparator, *pszEnd ) == NULL )
pszEnd++;
/* Check the switch */
if( hb_strnicmp( pszNext, pszName, i ) == 0 )
{
if( bRetValue )
{
HB_SIZE nLen;
pszNext += i;
/* Skip value separator colon. */
if( *pszNext == ':' )
pszNext++;
nLen = pszEnd > pszNext ? pszEnd - pszNext : 0;
pszRetVal = ( char * ) hb_xgrab( nLen + 1 );
hb_strncpy( pszRetVal, pszNext, nLen );
}
else
pszRetVal = ( char * ) "";
break;
}
/* Step to the next switch */
pszNext = pszEnd;
}
}
if( pszEnvVar )
hb_xfree( pszEnvVar );
return pszRetVal;
}
HB_BOOL hb_cmdargCheck( const char * pszName )
{
return hb_cmdargGet( pszName, HB_FALSE ) != NULL;
}
/* NOTE: Pointer must be freed with hb_xfree() if not NULL */
char * hb_cmdargString( const char * pszName )
{
return hb_cmdargGet( pszName, HB_TRUE );
}
int hb_cmdargNum( const char * pszName )
{
char * pszValue;
HB_TRACE( HB_TR_DEBUG, ( "hb_cmdargNum(%s)", pszName ) );
pszValue = hb_cmdargGet( pszName, HB_TRUE );
if( pszValue )
{
int iValue = atoi( pszValue );
hb_xfree( pszValue );
return iValue;
}
else
return -1;
}
/* NOTE: Pointer must be freed with hb_xfree() if not NULL */
char * hb_cmdargProgName( void )
{
return hb_cmdargDup( 0 );
}
/* NOTE: Pointer must be freed with hb_xfree() if not NULL */
char * hb_cmdargBaseProgName( void )
{
char * pszProgName, * pszBaseProgName = NULL;
pszProgName = hb_cmdargProgName();
if( pszProgName )
{
PHB_FNAME pFileName = hb_fsFNameSplit( pszProgName );
pszBaseProgName = hb_strdup( pFileName->szName );
hb_xfree( pFileName );
hb_xfree( pszProgName );
}
return pszBaseProgName;
}
/* Check if an internal switch has been set */
HB_FUNC( HB_ARGCHECK )
{
hb_retl( HB_ISCHAR( 1 ) ? hb_cmdargCheck( hb_parc( 1 ) ) : HB_FALSE );
}
/* Returns the value of an internal switch */
HB_FUNC( HB_ARGSTRING )
{
const char * pszName = hb_parc( 1 );
if( pszName )
{
char * pszValue = hb_cmdargString( pszName );
if( pszValue )
{
hb_retc_buffer( pszValue );
return;
}
}
hb_retc_null();
}
/* Returns the number of command line arguments passed to the application, this
also includes the internal arguments. */
HB_FUNC( HB_ARGC )
{
hb_retni( s_argc - 1 );
}
/* Returns a command line argument passed to the application. Calling it with
the parameter zero or no parameter, it will return the name of the executable,
as written in the command line. */
HB_FUNC( HB_ARGV )
{
char * pszArg = hb_cmdargDup( hb_parni( 1 ) );
if( pszArg )
hb_retc_buffer( pszArg );
else
hb_retc_null();
}
HB_FUNC( HB_ARGSHIFT )
{
int iArg = 1;
if( hb_parl( 1 ) )
{
while( iArg < s_argc )
{
if( ! hb_cmdargIsInternal( s_argv[ iArg ], NULL ) )
{
s_argv[ 0 ] = s_argv[ iArg ];
#if defined( HB_OS_WIN )
if( s_lpArgV )
s_lpArgV[ 0 ] = s_lpArgV[ iArg ];
#endif
break;
}
++iArg;
}
}
if( iArg < s_argc )
{
--s_argc;
while( iArg < s_argc )
{
s_argv[ iArg ] = s_argv[ iArg + 1 ];
#if defined( HB_OS_WIN )
if( s_lpArgV )
s_lpArgV[ iArg ] = s_lpArgV[ iArg + 1 ];
#endif
++iArg;
}
}
}
HB_FUNC( HB_CMDLINE )
{
if( s_argc > 1 )
{
HB_SIZE nLen = 0;
int iArg;
#if defined( HB_OS_WIN )
if( s_lpArgV )
{
LPTSTR lpBuffer, ptr;
for( iArg = 1; iArg < s_argc; iArg++ )
nLen += HB_STRLEN( s_lpArgV[ iArg ] ) + 1;
ptr = lpBuffer = ( LPTSTR ) hb_xgrab( nLen * sizeof( TCHAR ) );
for( iArg = 1; iArg < s_argc; iArg++ )
{
nLen = HB_STRLEN( s_lpArgV[ iArg ] );
memcpy( ptr, s_lpArgV[ iArg ], nLen * sizeof( TCHAR ) );
ptr += nLen;
*ptr++ = TEXT( ' ' );
}
*--ptr = TEXT( '\0' );
/* Convert from OS codepage */
#if defined( UNICODE )
HB_RETSTR( lpBuffer );
hb_xfree( lpBuffer );
#else
hb_retc_buffer( ( char * ) hb_osDecodeCP( lpBuffer, NULL, NULL ) );
#endif
}
else
#endif
{
char * pszBuffer, * ptr;
for( iArg = 1; iArg < s_argc; iArg++ )
nLen += strlen( s_argv[ iArg ] ) + 1;
ptr = pszBuffer = ( char * ) hb_xgrab( nLen );
for( iArg = 1; iArg < s_argc; iArg++ )
{
nLen = strlen( s_argv[ iArg ] );
memcpy( ptr, s_argv[ iArg ], nLen );
ptr += nLen;
*ptr++ = ' ';
}
*--ptr = '\0';
/* Convert from OS codepage */
hb_retc_buffer( ( char * ) hb_osDecodeCP( pszBuffer, NULL, NULL ) );
}
}
else
hb_retc_null();
}
/* Check for command line internal arguments */
void hb_cmdargProcess( void )
{
int iHandles;
if( hb_cmdargCheck( "INFO" ) )
{
{
char * pszVersion = hb_verHarbour();
hb_conOutErr( pszVersion, 0 );
hb_conOutErr( hb_conNewLine(), 0 );
hb_xfree( pszVersion );
}
{
char * pszVersion = hb_verPlatform();
hb_conOutErr( pszVersion, 0 );
hb_conOutErr( hb_conNewLine(), 0 );
hb_xfree( pszVersion );
}
{
char buffer[ 128 ];
#if defined( HB_CLP_STRICT )
hb_snprintf( buffer, sizeof( buffer ), "DS avail=%" HB_PFS "uKB OS avail=%" HB_PFS "uKB EMM avail=%" HB_PFS "uKB", hb_xquery( HB_MEM_BLOCK ), hb_xquery( HB_MEM_VM ), hb_xquery( HB_MEM_EMS ) );
#else
hb_snprintf( buffer, sizeof( buffer ), "DS avail=%" HB_PFS "uKB OS avail=%" HB_PFS "uKB EMM avail=%" HB_PFS "uKB MemStat:%s MT:%s", hb_xquery( HB_MEM_BLOCK ), hb_xquery( HB_MEM_VM ), hb_xquery( HB_MEM_EMS ), hb_xquery( HB_MEM_USEDMAX ) ? "On" : "Off", hb_vmIsMt() ? "On" : "Off" );
#endif
hb_conOutErr( buffer, 0 );
hb_conOutErr( hb_conNewLine(), 0 );
}
}
if( hb_cmdargCheck( "BUILD" ) )
hb_verBuildInfo();
iHandles = hb_cmdargNum( "F" );
if( iHandles > 20 )
{
#if defined( __WATCOMC__ )
#if defined( HB_OS_OS2 )
DosSetMaxFH( iHandles );
#elif defined( HB_OS_DOS )
_grow_handles( iHandles );
#endif
#endif
}
}
/* Source repository revision number */
int hb_verRevision( void )
{
return HB_VER_REVID;
}
/* ChangeLog ID string */
const char * hb_verChangeLogID( void )
{
return HB_VER_CHLID;
}
/* ChangeLog last entry string */
const char * hb_verChangeLogLastEntry( void )
{
return HB_VER_LENTRY;
}
#if defined( HB_LEGACY_LEVEL4 )
/* Source repository revision number */
int hb_verSvnID( void )
{
return HB_VER_REVID;
}
/* ChangeLog ID string */
const char * hb_verSvnChangeLogID( void )
{
return HB_VER_CHLID;
}
/* ChangeLog last entry string */
const char * hb_verSvnLastEntry( void )
{
return HB_VER_LENTRY;
}
#endif
/* build time C compiler flags in HB_USER_CFLAGS envvar */
const char * hb_verFlagsC( void )
{
#ifdef HB_VER_HB_USER_CFLAGS
return HB_VER_HB_USER_CFLAGS;
#else
return "";
#endif
}
/* build time linker flags in HB_USER_LDFLAGS envvar */
const char * hb_verFlagsL( void )
{
#ifdef HB_VER_HB_USER_LDFLAGS
return HB_VER_HB_USER_LDFLAGS;
#else
return "";
#endif
}
/* build time Harbour compiler flags in HB_USER_PRGFLAGS envvar */
const char * hb_verFlagsPRG( void )
{
#ifdef HB_VER_HB_USER_PRGFLAGS
return HB_VER_HB_USER_PRGFLAGS;
#else
return "";
#endif
}
/* build time Harbour platform setting */
const char * hb_verHB_PLAT( void )
{
#ifdef HB_PLATFORM
return HB_PLATFORM;
#else
return "";
#endif
}
/* build time Harbour compiler setting */
const char * hb_verHB_COMP( void )
{
#ifdef HB_COMPILER
return HB_COMPILER;
#else
return "";
#endif
}