Files
harbour-core/harbour/source/vm/cmdarg.c
Viktor Szakats 92c93fdc95 2009-08-23 17:55 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* doc/linux1st.txt
    - Deleted Linux build instructions no more relevant.
    * Formatting. Probably this file should be moved into INSTALL.

  * doc/gmake.txt
    * Little updates.

  * harbour-win-spec
  * doc/gmake.txt
  * doc/linux1st.txt
  * doc/whatsnew.txt
  * harbour-wce-spec
  * INSTALL
  * bin/hb-mkdyn.sh
  * bin/postinst.cmd
  * bin/postinst.bat
  * bin/hb-func.sh
  * bin/postinst.sh
  * external/sqlite3/Makefile
  * external/libhpdf/Makefile
  * external/libpng/Makefile
  * mpkg_tgz.sh
  * harbour.spec
  * source/pp/hbpp.c
  * source/pp/Makefile
  * source/vm/Makefile
  * source/vm/cmdarg.c
  * source/vm/vmmt/Makefile
  * source/main/harbour.c
  * source/rtl/gtdos/Makefile
  * source/rtl/gtwin/Makefile
  * source/rtl/gtcrs/Makefile
  * source/rtl/gttrm/Makefile
  * source/rtl/Makefile
  * source/rtl/gtos2/Makefile
  * source/rtl/gtgui/Makefile
  * source/rtl/gtwvt/Makefile
  * source/rdd/Makefile
  * source/Makefile
  * contrib/hbodbc/Makefile
  * contrib/hbsqlit3/Makefile
  * contrib/hbblat/Makefile
  * contrib/hbqt/Makefile
  * contrib/hbxbp/Makefile
  * contrib/hbcurl/Makefile
  * contrib/gtqtc/Makefile
  * contrib/rddsql/sddodbc/Makefile
  * contrib/rddado/Makefile
  * contrib/gtwvg/Makefile
  * contrib/rddads/Makefile
  * contrib/hbfimage/Makefile
  * contrib/hbtip/Makefile
  * contrib/hbwin/Makefile
  * contrib/hbssl/Makefile
  * utils/hbmk2/hbmk2.pt_BR.po
  * utils/hbmk2/hbmk2.hu_HU.po
  * config/none.mk
  * config/global.mk
  * config/lib.mk
  * config/wce/mingw.mk
  * config/bin.mk
  * config/dir.mk
  * config/common/watcom.mk
  * config/win/msvc64.mk
  * config/win/iccia64.mk
  * config/win/mingw64.mk
  * config/win/gcc.mk
  * config/win/msvcia64.mk
  * config/win/pocc64.mk
  * config/header.mk
  * config/dyn.mk
  * config/doc.mk
    * HB_ARCHITECTURE -> HB_PLATFORM
    * hb_arch -> hb_plat (internal script variable)
    * ARCH_COMP -> PLAT_COMP (internal make variable)
    ; INCOMPATIBLE: Please update your environment, if you used this setting.
    ; NOTE: So now Harbour uses only two names for platforms: 'OS' and 'platform'.
            'Architecture' is nowhere used to refer to as an operating system
            anymore. 'Architecture' is only used to refer to CPU/hardware
            architecture.
2009-08-23 15:58:51 +00:00

619 lines
16 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Command line and environment argument management
*
* Copyright 1999-2001 Viktor Szakats (harbour.01 syenar.hu)
* 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, 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. 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.
*
*/
#define HB_OS_WIN_USED
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapifs.h"
#include "hbvm.h"
#include "hbmemory.ch"
#include "hbstack.h"
#include "hbverbld.h"
/* 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
static char s_szAppName[ MAX_PATH ];
static TCHAR s_lpAppName[ MAX_PATH ];
static HANDLE s_hInstance = 0;
static HANDLE s_hPrevInstance = 0;
static int s_iCmdShow = 0;
static BOOL s_WinMainParam = FALSE;
void hb_winmainArgInit( HANDLE hInstance, HANDLE hPrevInstance, int iCmdShow )
{
s_hInstance = hInstance;
s_hPrevInstance = hPrevInstance;
s_iCmdShow = iCmdShow;
s_WinMainParam = TRUE;
}
BOOL hb_winmainArgGet( HANDLE * phInstance, HANDLE * phPrevInstance, int * piCmdShow )
{
if( phInstance )
*phInstance = s_hInstance;
if( phPrevInstance )
*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( 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;
}
void hb_cmdargUpdate( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_cmdargUpdate()"));
if( s_argc > 0 )
{
#if defined( HB_OS_WIN )
/* 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, s_lpAppName, MAX_PATH ) != 0 )
{
HB_TCHAR_GETFROM( s_szAppName, s_lpAppName, MAX_PATH );
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 ] );
BOOL fInPath = FALSE;
if( !pFName->szPath )
{
char * pszPATH = hb_getenv( "PATH" );
if( pszPATH && *pszPATH )
{
HB_PATHNAMES * pSearchPath = NULL, * pNextPath;
hb_fsAddSearchPath( pszPATH, &pSearchPath );
pNextPath = pSearchPath;
# ifdef HB_OS_OS2
if( !pFName->szExtension )
pFName->szExtension = ".exe";
# endif
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 = 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
}
}
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 TRUE;
}
else if( strlen( szArg ) >= 2 &&
szArg[ 0 ] == '/' &&
szArg[ 1 ] == '/' )
{
if( piLen )
*piLen = 2;
return TRUE;
}
return FALSE;
}
static char * hb_cmdargGet( const char * pszName, 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 )
{
char * pszPos = s_argv[ i ] + iPrefixLen + strlen( pszName );
if( *pszPos == ':' )
pszPos++;
return hb_strdup( pszPos );
}
else
return ( char * ) "";
}
}
/* Check the environment variable */
pszEnvVar = hb_getenv( "HARBOUR" );
if( !pszEnvVar || pszEnvVar[ 0 ] == '\0' )
{
if( pszEnvVar )
hb_xfree( ( void * ) 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 = 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 )
{
ULONG ulLen;
pszNext += i;
/* Skip value separator colon. */
if( *pszNext == ':' )
pszNext++;
ulLen = pszEnd > pszNext ? pszEnd - pszNext : 0;
pszRetVal = ( char * ) hb_xgrab( ulLen + 1 );
hb_strncpy( pszRetVal, pszNext, ulLen );
}
else
pszRetVal = ( char * ) "";
break;
}
/* Step to the next switch */
pszNext = pszEnd;
}
}
if( pszEnvVar )
hb_xfree( ( void * ) pszEnvVar );
return pszRetVal;
}
BOOL hb_cmdargCheck( const char * pszName )
{
return hb_cmdargGet( pszName, FALSE ) != NULL;
}
/* NOTE: Pointer must be freed with hb_xfree() if not NULL */
char * hb_cmdargString( const char * pszName )
{
return hb_cmdargGet( pszName, TRUE );
}
int hb_cmdargNum( const char * pszName )
{
char * pszValue;
HB_TRACE(HB_TR_DEBUG, ("hb_cmdargNum(%s)", pszName));
pszValue = hb_cmdargGet( pszName, TRUE );
if( pszValue )
{
int iValue = atoi( pszValue );
hb_xfree( pszValue );
return iValue;
}
else
return -1;
}
/* Check if an internal switch has been set */
HB_FUNC( HB_ARGCHECK )
{
hb_retl( HB_ISCHAR( 1 ) ? hb_cmdargCheck( hb_parc( 1 ) ) : FALSE );
}
/* Returns the value of an internal switch */
HB_FUNC( HB_ARGSTRING )
{
if( HB_ISCHAR( 1 ) )
{
char * pszValue = hb_cmdargString( hb_parc( 1 ) );
if( pszValue )
{
/* Convert from OS codepage */
hb_retc_buffer( ( char * ) hb_osDecode( pszValue, NULL ) );
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 )
{
int argc = hb_parni( 1 );
hb_retc( ( argc >= 0 && argc < s_argc ) ? s_argv[ argc ] : NULL );
}
HB_FUNC( HB_CMDLINE )
{
char** argv = hb_cmdargARGV();
int argc = hb_cmdargARGC();
char * pszBuffer, * ptr;
ULONG ulLen;
int iArg;
ulLen = 0;
for( iArg = 1; iArg < argc; iArg++ )
ulLen += ( ULONG ) strlen( argv[ iArg ] ) + 1;
if( ulLen )
{
ptr = pszBuffer = ( char * ) hb_xgrab( ulLen );
for( iArg = 1; iArg < argc; iArg++ )
{
ulLen = ( ULONG ) strlen( argv[ iArg ] );
memcpy( ptr, argv[ iArg ], ulLen );
ptr += ulLen;
*ptr++ = ' ';
}
*--ptr = '\0';
/* Convert from OS codepage */
hb_retc_buffer( ( char * ) hb_osDecode( pszBuffer, NULL ) );
}
else
hb_retc_null();
}
/* Check for command line internal arguments */
ULONG hb_cmdargProcessVM( int *pCancelKey, int *pCancelKeyEx )
{
char * cFlags;
ULONG ulFlags = HB_VMFLAG_HARBOUR;
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_C52_STRICT )
hb_snprintf( buffer, sizeof( buffer ), "DS avail=%luKB OS avail=%luKB EMM avail=%luKB", hb_xquery( HB_MEM_BLOCK ), hb_xquery( HB_MEM_VM ), hb_xquery( HB_MEM_EMS ) );
#else
hb_snprintf( buffer, sizeof( buffer ), "DS avail=%luKB OS avail=%luKB EMM avail=%luKB 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();
if( ( cFlags = hb_cmdargString( "FLAGS" ) ) != NULL )
{
int i = 0;
while( cFlags[ i ] )
{
switch( cFlags[ i++ ] )
{
case 'c':
/* clear all flags - minimal set of features */
ulFlags = 0;
break;
case 'h':
/* default Harbour mode */
ulFlags |= HB_VMFLAG_HARBOUR;
break;
/*
case 'x':
ulFlags |= HB_VMFLAG_XBASE;
break;
case 'r':
ulFlags |= HB_VMFLAG_RT_MACRO;
break;
*/
case 's':
ulFlags |= HB_VMFLAG_ARRSTR;
break;
}
}
hb_xfree( cFlags );
}
if( ( cFlags = hb_cmdargString( "CANCEL" ) ) != NULL )
{
int iVal = atoi( cFlags );
if( iVal )
*pCancelKey = iVal;
hb_xfree( cFlags );
}
if( ( cFlags = hb_cmdargString( "CANCELEX" ) ) != NULL )
{
int iVal = atoi( cFlags );
if( iVal )
*pCancelKeyEx = iVal;
hb_xfree( cFlags );
}
return ulFlags;
}
/* ChangeLog SVN revision number */
int hb_verSvnID( void )
{
return HB_VER_SVNID;
}
/* 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;
}
/* 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
}