Files
harbour-core/harbour/source/vm/cmdarg.c
Viktor Szakats 8e15abc1bd 2009-10-07 11:22 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* tests/transtst.prg
  * doc/pp.txt
  * doc/en-EN/string.txt
  * doc/en-EN/terminal.txt
  * doc/en-EN/dbstrux.txt
  * include/hbpp.h
  * include/std.ch
  * include/hbclass.ch
  * include/hbsetup.ch
  * include/hbdefs.h
  * include/dbedit.ch
  * include/hbapigt.h
  * include/hbextern.ch
  * include/hbexprb.c
  * ChangeLog
  * source/pp/ppcore.c
  * source/vm/macro.c
  * source/vm/hvm.c
  * source/vm/cmdarg.c
  * source/vm/arrays.c
  * source/vm/proc.c
  * source/vm/memvars.c
  * source/vm/arrayshb.c
  * source/vm/memvclip.c
  * source/common/hbverdsp.c
  * source/common/hbstr.c
  * source/common/hbdate.c
  * source/rtl/setposbs.c
  * source/rtl/round.c
  * source/rtl/oldbox.c
  * source/rtl/trim.c
  * source/rtl/tpopup.prg
  * source/rtl/einstvau.prg
  * source/rtl/setta.prg
  * source/rtl/transfrm.c
  * source/rtl/browse.prg
  * source/rtl/tget.prg
  * source/rtl/setfunc.prg
  * source/rtl/achoice.prg
  * source/rtl/strzero.c
  * source/rtl/natmsgu.c
  * source/rtl/strtran.c
  * source/rtl/errapiu.c
  * source/rtl/einstvar.prg
  * source/rtl/dbedit.prg
  * source/rtl/einstv52.prg
  * source/rtl/console.c
  * source/rtl/mousehb.c
  * source/rtl/chrasc.c
  * source/rtl/dircmd.prg
  * source/rtl/oldclear.c
  * source/rtl/hbgtcore.c
  * source/rtl/dirdrive.c
  * source/rtl/mlcfunc.c
  * source/rtl/datesx.c
  * source/rtl/accept.c
  * source/rtl/defpathu.c
  * source/rtl/tgetlist.prg
  * source/rtl/input.prg
  * source/rtl/alert.prg
  * source/rtl/tmenuitm.prg
  * source/rtl/shadowu.c
  * source/rtl/tbrowse.prg
  * source/rdd/dbfntx/dbfntx1.c
  * source/rdd/dbdelim.prg
  * source/rdd/rddordu.prg
  * source/rdd/workarea.c
  * source/rdd/dbnubs.c
  * source/rdd/rddinfo.c
  * source/rdd/dbstruxu.prg
  * source/rdd/sdf1.c
  * source/rdd/dbfnsx/dbfnsx1.c
  * source/rdd/dbcmd.c
  * source/rdd/dbfcdx/dbfcdx1.c
  * source/rdd/dbdrop.c
  * source/rdd/delim1.c
  * source/rdd/dbf1.c
  * source/rdd/dbrename.c
  * source/rdd/dbexists.c
  * source/rdd/fieldhb.c
  * contrib/hbct/ctwin.c
  * contrib/hbct/cursor.c
  * contrib/xhb/xhbver.prg
  * contrib/xhb/xhbtrim.c
  * utils/hbtest/rt_main.ch
  * utils/hbtest/rt_trans.prg
  * utils/hbtest/rt_misc.prg
  * utils/hbtest/rt_stra.prg
  * utils/hbtest/rt_array.prg
  * examples/hbdoc/examples/core_es/dbstrux.txt
  *  examples/hbdoc2/hbdoc2.prg
    * HB_C52_STRICT -> HB_CLP_STRICT
      We use it cover strict Clipper compatibility in general, not 
      just for C5.2.
    * HB_C52_UNDOC -> HB_CLP_UNDOC
      We use it cover Clipper undocumented stuff in general, not 
      just C5.2 version specific ones.
2009-10-07 09:35:33 +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_osDecodeCP( pszValue, NULL, 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_osDecodeCP( pszBuffer, NULL, 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_CLP_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
}