diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 42f4afc19a..3beec928c8 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,54 @@ +19990919-06:21 GMT+1 Victor Szel + + * source/vm/hvm.c + + Added support for CA-Clipper undocumented _APPMAIN starting function, + if this is defined, Harbour will start it first, overriding the default + starting proc. + ! Fixed the case when no PUBLIC functions were declared with no + explicit starting procedure. Now it will silently exit (STRICT mode) + or show a proper unrecoverable error message, instead of a possible GPF, + * __XHELP() - hb_dynsymFindName() changed to hb_dynsymFind() + * source/rtl/environ.c + include/extend.h + + hb_version() added, separated from HB_VERSION(), to make it callable + from C, too. //INFO needed it. + * source/rtl/console.c + + Added undocumented //STDERR feature, when specified it will redirect + all stderr output to stdout. + * source/rtl/alert.prg + + ALERT() now handles the //NOALERT switch. + The NOALERT feature is now always turned on, not only in STRICT mode. + + __NONOALERT() undocumented Clipper function added. + * source/rtl/hvm.c + + source/rtl/cmdarg.c + source/rtl/Makefile + include/extend.h + makefile.* + makefile.vc (with extra care taken to retain the alphabetical order :-)) + + Internal command line and environment variable support added. + //INFO //F:30 //TEMPPATH:"C:\TEMP", SET HARBOUR=F30;X00, + SET CLIPPER=E0 INFO, now can be queried from Harbour runtime. + + API added to reach the above functionality. + + Harbour argument handling functions added: + __ARGC() + __ARGV() + __ARGCHECK() + __ARGGET() + ! Now the internal parameters (//INFO) are no more passed to the Harbour + MAIN and INIT functions. + + Harbour now prints the version when //INFO switch is speficied. + * source/rtl/fm.c + + Will always print some memory info when the //INFO switch was specified. + * include/clipdefs.h + + Added WORD, DWORD typedefs. + * source/rtl/strings.c + include/extend.h + + hb_strnicmp() added. + % hb_stricmp() formatted, variable scopes adjusted, int type changed to + char. + * source/rtl/classes.c + * Small modification. + 19990918-17:42 GMT+1 Victor Szel * source/rtl/set.c diff --git a/harbour/include/clipdefs.h b/harbour/include/clipdefs.h index e9e93d6a22..e70a0a1dd1 100644 --- a/harbour/include/clipdefs.h +++ b/harbour/include/clipdefs.h @@ -62,6 +62,7 @@ typedef SHORTP PSHORT; typedef USHORT* USHORTP; typedef USHORTP PUSHORT; +typedef unsigned int WORD; typedef WORD* WORDP; typedef WORDP PWORD; @@ -71,6 +72,7 @@ typedef LONGP PLONG; typedef ULONG* ULONGP; typedef ULONGP PULONG; +typedef unsigned long DWORD; typedef DWORD* DWORDP; typedef DWORDP PDWORD; diff --git a/harbour/include/extend.h b/harbour/include/extend.h index 1a8f44c1b7..2d806e0309 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -317,6 +317,7 @@ extern PHB_ITEM hb_arrayClone( PHB_ITEM pArray ); #define HB_STRGREATER_RIGHT 2 extern int hb_stricmp( const char * s1, const char * s2 ); +extern int hb_strnicmp( const char * s1, const char * s2, ULONG ulLen ); extern int hb_strgreater( char * szText1, char * szText2 ); extern void hb_strupr( char * szText ); extern BOOL hb_strMatchRegExp( char * szString, char * szMask ); @@ -346,6 +347,15 @@ extern void hb_dynsymLog( void ); /* displays all dynamic symbol extern void hb_dynsymRelease( void ); /* releases the memory of the dynamic symbol table */ extern void hb_dynsymEval( PHB_DYNS_FUNC, void * ); /* enumerates all dynamic symbols */ +/* Command line and environment argument management */ +extern void hb_cmdargInit( int argc, char * argv[] ); +extern int hb_cmdargARGC( void ); +extern char ** hb_cmdargARGV( void ); +extern BOOL hb_cmdargIsInternal( const char * szArg ); +extern BOOL hb_cmdargCheck( const char * pszName ); /* Check if a given internal switch (like //INFO) was set */ +extern char * hb_cmdargString( const char * pszName ); /* Returns the string value of an internal switch (like //TEMPPATH:"C:\") */ +extern int hb_cmdargNum( const char * pszName ); /* Returns the numeric value of an internal switch (like //F:90) */ + /* Symbol management */ extern PHB_SYMB hb_symbolNew( char * szName ); @@ -378,6 +388,9 @@ extern char * hb_consoleGetNewLine( void ); extern void hb_tone( double dFrequency, double dDuration ); extern char * hb_setColor( char * ); +/* misc */ +extern char * hb_version( USHORT uiMode ); + /* Please leave these at the bottom of this file */ #ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY diff --git a/harbour/makefile.b16 b/harbour/makefile.b16 index 8219b5c295..bc4a351608 100644 --- a/harbour/makefile.b16 +++ b/harbour/makefile.b16 @@ -16,7 +16,7 @@ PROJECT: harbour.lib libs\b16\terminal.lib libs\win16\terminal.lib harbour.exe harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj dates.obj \ - dates2.obj datesx.obj \ + dates2.obj datesx.obj cmdarg.obj \ debug.obj descend.obj devoutp.obj dynsym.obj environ.obj terror.obj \ errorapi.obj errorsys.obj harbinit.obj extend.obj files.obj fm.obj \ hardcr.obj initsymb.obj itemapi.obj math.obj memofile.obj memvars.obj \ @@ -36,6 +36,7 @@ console.obj : console.c extend.h hbdefs.h arrays.obj : arrays.c extend.h hbdefs.h asort.obj : asort.c extend.h hbdefs.h classes.obj : classes.c extend.h hbdefs.h +cmdarg.obj : cmdarg.c extend.h hbdefs.h codebloc.obj : codebloc.c extend.h hbdefs.h dates.obj : dates.c extend.h hbdefs.h dates2.obj : dates2.c extend.h hbdefs.h diff --git a/harbour/makefile.b31 b/harbour/makefile.b31 index f7a240f403..10f6eb8add 100644 --- a/harbour/makefile.b31 +++ b/harbour/makefile.b31 @@ -18,7 +18,7 @@ c_opt = -mh -O2 -I.\include -DHARBOUR_USE_GTAPI PROJECT: harbour.lib hbtools.lib terminal.lib libs\win16\terminal.lib -harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj copyfile.obj \ +harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj copyfile.obj cmdarg.obj \ dates.obj descend.obj devoutp.obj dir.obj dynsym.obj environ.obj \ terror.obj errorapi.obj errorsys.obj harbinit.obj extend.obj \ filesys.obj gtapi.obj hardcr.obj initsymb.obj itemapi.obj \ @@ -79,6 +79,7 @@ transfrm.obj : transfrm.c extend.h hbdefs.h ctoharb.h set.h dates.h gtdos.obj : source\rtl\gt\gtdos.c extend.h hbdefs.h gtapi.h msguk.obj : source\rtl\natmsg\msguk.c extend.h hbdefs.h +cmdarg.obj : source\vm\cmdarg.c extend.h hbdefs.h debug.obj : source\vm\debug.c extend.h hbdefs.h ctoharb.h itemapi.h dynsym.obj : source\vm\dynsym.c extend.h hbdefs.h initsymb.obj : source\vm\initsymb.c extend.h hbdefs.h diff --git a/harbour/makefile.b32 b/harbour/makefile.b32 index ce2288bf70..b199084115 100644 --- a/harbour/makefile.b32 +++ b/harbour/makefile.b32 @@ -20,7 +20,7 @@ harbour.lib : achoice.obj adir.obj alert.obj arrays.obj asort.obj \ browdb.obj \ classes.obj codebloc.obj copyfile.obj \ dates.obj dates2.obj datesx.obj debug.obj debugger.obj descend.obj devoutp.obj \ - dir.obj do.obj dynsym.obj environ.obj terror.obj \ + dir.obj do.obj dynsym.obj environ.obj terror.obj cmdarg.obj \ errorapi.obj errorsys.obj harbinit.obj extend.obj fileread.obj filesys.obj fm.obj \ hardcr.obj hb_f.obj hvm.obj initsymb.obj inkey.obj itemapi.obj \ langapi.obj math.obj mathx.obj memofile.obj memvars.obj menuto.obj mtran.obj msges.obj \ @@ -35,6 +35,7 @@ arrays.obj : arrays.c extend.h hbdefs.h asort.obj : asort.c extend.h hbdefs.h browdb.obj : browdb.c extend.h hbdefs.h classes.obj : classes.c extend.h hbdefs.h +cmdarg.obj : cmdarg.c extend.h hbdefs.h codebloc.obj : codebloc.c extend.h hbdefs.h copyfile.obj : copyfile.c extend.h hbdefs.h dates.obj : dates.c extend.h hbdefs.h diff --git a/harbour/makefile.b40 b/harbour/makefile.b40 index dfd40186e8..ef8c103a2e 100644 --- a/harbour/makefile.b40 +++ b/harbour/makefile.b40 @@ -18,7 +18,7 @@ PROJECT: harbour.exe harbour.lib libs\b32\terminal.lib libs\win32\terminal.lib harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj alert.obj \ dates.obj dates2.obj datesx.obj debug.obj descend.obj devoutp.obj \ - dir.obj dynsym.obj environ.obj terror.obj menu.obj \ + dir.obj dynsym.obj environ.obj terror.obj menu.obj cmdarg.obj \ errorapi.obj errorsys.obj harbinit.obj extend.obj files.obj \ hardcr.obj hb_f.obj initsymb.obj inkey.obj itemapi.obj memvars.obj \ memofile.obj math.obj mathx.obj msguk.obj mtran.obj objfunc.obj \ @@ -31,6 +31,7 @@ copyfile.obj : copyfile.c extend.h hbdefs.h arrays.obj : arrays.c extend.h hbdefs.h asort.obj : asort.c extend.h hbdefs.h classes.obj : classes.c extend.h hbdefs.h +cmdarg.obj : cmdarg.c extend.h hbdefs.h codebloc.obj : codebloc.c extend.h hbdefs.h dates.obj : dates.c extend.h hbdefs.h dates2.obj : dates2.c extend.h hbdefs.h diff --git a/harbour/makefile.vc b/harbour/makefile.vc index b034e23229..285a00ba40 100644 --- a/harbour/makefile.vc +++ b/harbour/makefile.vc @@ -64,6 +64,7 @@ HARBOUR_LIB_OBJS = \ $(OBJ_DIR)\asort.obj \ $(OBJ_DIR)\browdb.obj \ $(OBJ_DIR)\classes.obj \ + $(OBJ_DIR)\cmdarg.obj \ $(OBJ_DIR)\codebloc.obj \ $(OBJ_DIR)\console.obj \ $(OBJ_DIR)\copyfile.obj \ @@ -531,6 +532,9 @@ $(OBJ_DIR)\tbrwtext.obj : $(DEBUG_DIR)\tbrwtext.c # VM source dependencies below. Add as needed # +$(OBJ_DIR)\cmdarg.obj : $(VM_DIR)\cmdarg.c + $(CC) $(CLIBFLAGS) -Fo$@ $** + $(OBJ_DIR)\debug.obj : $(VM_DIR)\debug.c $(CC) $(CLIBFLAGS) -Fo$@ $** diff --git a/harbour/source/rtl/alert.prg b/harbour/source/rtl/alert.prg index fa32bdba4e..5406fc8ea3 100644 --- a/harbour/source/rtl/alert.prg +++ b/harbour/source/rtl/alert.prg @@ -37,6 +37,8 @@ // This is fixed. // ; nDelay parameter is a Harbour addition. +STATIC s_lNoAlert := NIL + FUNCTION Alert( xMessage, aOptions, cColorNorm, nDelay ) LOCAL nChoice LOCAL aSay, nPos, nWidth, nOpWidth, nInitRow, nInitCol, iEval @@ -55,13 +57,11 @@ FUNCTION Alert( xMessage, aOptions, cColorNorm, nDelay ) /* if it is not, the console mode is choosed here */ LOCAL lConsole := .F. -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY -// TODO: Enable this when we have a function for querying the command line -// parameters. -// IF "//NOALERT" $ /* Upper( cCommandLine ) */ -// QUIT -// ENDIF -#endif + DEFAULT s_lNoAlert TO __argCheck( "NOALERT" ) + + IF s_lNoAlert + QUIT + ENDIF aSay := {} @@ -277,3 +277,11 @@ FUNCTION Alert( xMessage, aOptions, cColorNorm, nDelay ) ENDIF RETURN nChoice + +/* Undocumented CA-Clipper functions */ + +PROCEDURE __NONOALERT() + + s_lNoAlert := .F. + + RETURN diff --git a/harbour/source/rtl/classes.c b/harbour/source/rtl/classes.c index 82f6cd13ed..febb879388 100644 --- a/harbour/source/rtl/classes.c +++ b/harbour/source/rtl/classes.c @@ -756,7 +756,7 @@ HARBOUR HB___CLSINSTSUPER( void ) for( uiClass = 0; ! bFound && uiClass < s_uiClasses; uiClass++ ) { /* Locate the entry */ - if( !hb_stricmp( pString->item.asString.value, s_pClasses[ uiClass ].szName ) ) + if( hb_stricmp( pString->item.asString.value, s_pClasses[ uiClass ].szName ) == 0 ) { hb_retni( uiClass + 1 ); /* Entry + 1 = hb___msgClsH */ bFound = TRUE; diff --git a/harbour/source/rtl/console.c b/harbour/source/rtl/console.c index cb33a0b028..2b281bc5ad 100644 --- a/harbour/source/rtl/console.c +++ b/harbour/source/rtl/console.c @@ -124,7 +124,10 @@ void hb_consoleInitialize( void ) s_iFilenoStdout = fileno( stdout ); hb_fsSetDevMode( s_iFilenoStdout, FM_BINARY ); - s_iFilenoStderr = fileno( stderr ); + if( hb_cmdargCheck( "STDERR" ) ) /* Undocumented CA-Clipper switch */ + s_iFilenoStderr = s_iFilenoStdout; + else + s_iFilenoStderr = fileno( stderr ); hb_fsSetDevMode( s_iFilenoStderr, FM_BINARY ); #ifdef HARBOUR_USE_GTAPI diff --git a/harbour/source/rtl/environ.c b/harbour/source/rtl/environ.c index f27c28f677..5b2bd43b64 100644 --- a/harbour/source/rtl/environ.c +++ b/harbour/source/rtl/environ.c @@ -281,17 +281,21 @@ HARBOUR HB_OS( void ) #endif /* __MPW__ */ } -HARBOUR HB_VERSION( void ) -{ - char hb_ver[ 80 ]; +/* The caller must free the returned buffer. */ - sprintf( hb_ver, "Harbour %d.%d Intl. (Build %d%s) (%04d.%02d.%02d)", +#define HB_VERSION_BUFFER_LEN 80 + +char * hb_version( USHORT uiMode ) +{ + char * pszVersion = hb_xgrab( HB_VERSION_BUFFER_LEN ); + + sprintf( pszVersion, "Harbour %d.%d Intl. (Build %d%s) (%04d.%02d.%02d)", hb_major, hb_minor, hb_build, hb_revision, hb_year, hb_month, hb_day ); - if( hb_pcount() == 1 ) + if( uiMode != 0 ) { /* Optionally include the Compiler name and version, if available. */ - char * compiler = (char *) 0; + char * compiler = ( char * ) NULL; int version = 0; #if defined(__IBMCPP__) @@ -327,21 +331,28 @@ HARBOUR HB_VERSION( void ) #endif if( compiler ) { - strncat( hb_ver, " (", sizeof( hb_ver ) ); - strncat( hb_ver, compiler, sizeof( hb_ver ) ); + strncat( pszVersion, " (", HB_VERSION_BUFFER_LEN ); + strncat( pszVersion, compiler, HB_VERSION_BUFFER_LEN ); if( version ) { char buf[ 40 ]; sprintf( buf, "(%d)", version ); - strncat( hb_ver, " ", sizeof( hb_ver ) ); - strncat( hb_ver, buf, sizeof( hb_ver ) ); + strncat( pszVersion, " ", HB_VERSION_BUFFER_LEN ); + strncat( pszVersion, buf, HB_VERSION_BUFFER_LEN ); } - strncat( hb_ver, ")", sizeof( hb_ver ) ); - hb_ver[ sizeof( hb_ver ) - 1 ] = '\0'; + strncat( pszVersion, ")", HB_VERSION_BUFFER_LEN ); + pszVersion[ HB_VERSION_BUFFER_LEN - 1 ] = '\0'; } } - hb_retc( hb_ver ); + return pszVersion; +} + +HARBOUR HB_VERSION( void ) +{ + char * pszVersion = hb_version( hb_pcount() > 0 ? 1 : 0 ); + hb_retc( pszVersion ); + hb_xfree( pszVersion ); } HARBOUR HB_GETENV( void ) diff --git a/harbour/source/rtl/fm.c b/harbour/source/rtl/fm.c index 219f32a6f9..03a420aa42 100644 --- a/harbour/source/rtl/fm.c +++ b/harbour/source/rtl/fm.c @@ -147,12 +147,20 @@ void hb_xinit( void ) /* Initialize fixed memory subsystem */ void hb_xexit( void ) /* Deinitialize fixed memory subsystem */ { #ifdef HB_FM_STATISTICS - if( s_ulMemoryBlocks ) + if( s_ulMemoryBlocks || hb_cmdargCheck( "INFO" ) ) { - printf( "\n\ntotal memory blocks allocated: %lu\n", s_ulMemoryMaxBlocks ); - printf( "memory maximum size consumed: %ld\n", s_ulMemoryMaxConsumed ); - printf( "memory blocks not released: %ld\n", s_ulMemoryBlocks ); - printf( "memory size not released: %ld\n", s_ulMemoryConsumed ); + printf( hb_consoleGetNewLine() ); + printf( "total memory blocks allocated: %lu", s_ulMemoryMaxBlocks ); + printf( hb_consoleGetNewLine() ); + printf( "memory maximum size consumed: %ld", s_ulMemoryMaxConsumed ); + if( s_ulMemoryBlocks ) + { + printf( hb_consoleGetNewLine() ); + printf( "memory blocks not released: %ld", s_ulMemoryBlocks ); + printf( hb_consoleGetNewLine() ); + printf( "memory size not released: %ld", s_ulMemoryConsumed ); + } + printf( hb_consoleGetNewLine() ); } #endif } diff --git a/harbour/source/rtl/strings.c b/harbour/source/rtl/strings.c index fbc287fc2d..4d1dd130cd 100644 --- a/harbour/source/rtl/strings.c +++ b/harbour/source/rtl/strings.c @@ -44,6 +44,7 @@ * hb_strEmpty() * hb_strMatchDOS() * hb_STRZERO() + * hb_strnicmp() * * See doc/license.txt for licensing terms. * @@ -99,27 +100,73 @@ BOOL hb_strEmpty( char * szText, ULONG ulLen ) return bRetVal; } -int hb_stricmp( const char *s1, const char *s2 ) +int hb_stricmp( const char * s1, const char * s2 ) { - int rc = 0, c1, c2; - ULONG l1, l2, count; + int rc = 0; + ULONG l1 = strlen( s1 ); + ULONG l2 = strlen( s2 ); + ULONG count; + + if( l1 < l2 ) + count = l1; + else + count = l2; - l1 = strlen( s1 ); - l2 = strlen( s2 ); - if( l1 < l2 ) count = l1; - else count = l2; while( rc == 0 && count > 0 ) { + char c1 = toupper( *s1++ ); + char c2 = toupper( *s2++ ); + + if( c1 != c2 ) + rc = ( c1 < c2 ? -1 : 1 ); + count--; - c1 = toupper( *s1++ ); - c2 = toupper( *s2++ ); - if( c1 != c2 ) rc = ( c1 < c2 ? -1 : 1 ); } + if( rc == 0 && l1 != l2 ) { - if( l1 < l2 ) rc = -1; - else rc = 1; + if( l1 < l2 ) + rc = -1; + else + rc = 1; } + + return rc; +} + +int hb_strnicmp( const char * s1, const char * s2, ULONG count ) +{ + int rc = 0; + ULONG l1 = strlen( s1 ); + ULONG l2 = strlen( s2 ); + + if( l1 > count ) + l1 = count; + + if( l1 < l2 ) + count = l1; + else + count = l2; + + while( rc == 0 && count > 0 ) + { + char c1 = toupper( *s1++ ); + char c2 = toupper( *s2++ ); + + if( c1 != c2 ) + rc = ( c1 < c2 ? -1 : 1 ); + + count--; + } + + if( rc == 0 && l1 != l2 ) + { + if( l1 < l2 ) + rc = -1; + else + rc = 1; + } + return rc; } @@ -512,7 +559,7 @@ HARBOUR HB_PADC( void ) hb_retc( "" ); } -ULONG hb_strAt( char *szSub, ULONG ulSubLen, char *szText, ULONG ulLen ) +ULONG hb_strAt( char * szSub, ULONG ulSubLen, char * szText, ULONG ulLen ) { if( ulSubLen ) { diff --git a/harbour/source/vm/Makefile b/harbour/source/vm/Makefile index 0ec7442951..2efa075c3d 100644 --- a/harbour/source/vm/Makefile +++ b/harbour/source/vm/Makefile @@ -5,6 +5,7 @@ ROOT = ../../ C_SOURCES=\ + cmdarg.c \ debug.c \ dynsym.c \ hvm.c \ diff --git a/harbour/source/vm/cmdarg.c b/harbour/source/vm/cmdarg.c new file mode 100644 index 0000000000..43de69e616 --- /dev/null +++ b/harbour/source/vm/cmdarg.c @@ -0,0 +1,261 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Command line and environment argument management + * + * Copyright 1999 Victor Szel + * 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, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) 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 HRL + * and/or HVM code into it. + * + * 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 "extend.h" + +/* Command line argument management */ +static int s_argc = 0; +static char ** s_argv = NULL; + +static char * hb_cmdargGet( const char * pszName, BOOL bRetValue ); + +void hb_cmdargInit( int argc, char * argv[] ) +{ + s_argc = argc; + s_argv = argv; +} + +int hb_cmdargARGC( void ) +{ + return s_argc; +} + +char ** hb_cmdargARGV( void ) +{ + return s_argv; +} + +BOOL hb_cmdargIsInternal( const char * szArg ) +{ + return strlen( szArg ) >= 2 && + szArg[ 0 ] == '/' && + szArg[ 1 ] == '/'; +} + +static char * hb_cmdargGet( const char * pszName, BOOL bRetValue ) +{ + int i; + char * pszEnvVar; + + /* Check the command line first */ + + for( i = 1; i < s_argc; i++ ) + { + if( hb_cmdargIsInternal( s_argv[ i ] ) && + hb_strnicmp( s_argv[ i ] + 2, pszName, strlen( pszName ) ) == 0 ) + { + if( bRetValue ) + { + char * pszPos = s_argv[ i ] + 2 + strlen( pszName ); + char * pszRetVal; + + if( *pszPos == ':' ) + pszPos++; + + pszRetVal = ( char * ) hb_xgrab( strlen( pszPos ) + 1 ); + strcpy( pszRetVal, pszPos ); + + return pszRetVal; + } + else + return s_argv[ i ] + 2; + } + } + + /* Check the environment variable */ + + pszEnvVar = getenv( "HARBOUR" ); + + if( pszEnvVar == NULL ) + pszEnvVar = getenv( "CLIPPER" ); + + if( pszEnvVar != NULL ) + { + static const char * szSeparator = " ;,\t"; + char * pszNext; + + /* Step through all envvar switches. */ + + /* NOTE: CA-Clipper don'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. */ + + pszNext = pszEnvVar; + + while( *pszNext ) + { + char * pszEnd; + + /* Search for the end of this switch */ + while( *pszNext && strchr( szSeparator, *pszNext ) == NULL ) + pszNext++; + + pszEnd = pszNext; + + /* Skip the separators after the switch */ + while( *pszNext && strchr( szSeparator, *pszNext ) ) + pszNext++; + + /* Check the switch */ + + /* The // is optional in the envvar */ + if( hb_cmdargIsInternal( pszEnvVar ) ) + pszEnvVar += 2; + + if( hb_strnicmp( pszEnvVar, pszName, strlen( pszName ) ) == 0 ) + { + if( bRetValue ) + { + char * pszPos = pszEnvVar + strlen( pszName ); + char * pszRetVal; + + /* Skip value separator colon. */ + if( *pszPos == ':' ) + pszPos++; + + pszRetVal = ( char * ) hb_xgrab( pszEnd - pszPos + 1 ); + strncpy( pszRetVal, pszPos, pszEnd - pszPos ); + pszRetVal[ pszEnd - pszPos ] = '\0'; + + return pszRetVal; + } + else + return pszEnvVar; + } + + /* Step to the next switch */ + pszEnvVar = pszNext; + } + } + + return NULL; +} + +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_cmdargGet( pszName, TRUE ); + + if( pszValue ) + { + int iValue = strlen( pszValue ) > 0 ? atoi( pszValue ) : -1; + + hb_xfree( pszValue ); + + return iValue; + } + else + return -1; +} + +/* Check if an internal switch has been set */ + +HARBOUR HB___ARGCHECK( void ) +{ + hb_retl( ISCHAR( 1 ) ? hb_cmdargCheck( hb_parc( 1 ) ) : FALSE ); +} + +/* Returns the value of an internal switch */ + +HARBOUR HB___ARGSTRING( void ) +{ + if( ISCHAR( 1 ) ) + { + char * pszValue = hb_cmdargString( hb_parc( 1 ) ); + + if( pszValue ) + { + hb_retc( pszValue ); + hb_xfree( pszValue ); + } + } + else + hb_retc( "" ); +} + +/* Returns the number of command line arguments passed to the application, this + also includes the internal arguments. */ + +HARBOUR HB___ARGC( void ) +{ + hb_retni( s_argc - 1 ); +} + +/* Returns a command line argument passed to the application. Calling it with + the parameter zero, it will return the name of the executable, as written + in the command line. */ + +HARBOUR HB___ARGV( void ) +{ + if( ISNUM( 1 ) ) + { + int argc = hb_parni( 1 ); + + hb_retc( ( argc >= 0 && argc < s_argc ) ? s_argv[ argc ] : "" ); + } + else + hb_retc( "" ); +} + +#ifdef TEST + +void hb_cmdargTEST( void ) +{ + char * pszArg; + + printf("INFO: %i\n", hb_cmdargCheck( "INFO" ) ); + printf(" F: %s\n", pszArg = hb_cmdargString( "F" ) ); if( pszArg ) hb_xfree( pszArg ); + printf(" Fn: %i\n", hb_cmdargNum( "F" ) ); + printf("TEMP: %s\n", pszArg = hb_cmdargString( "TEMP" ) ); if( pszArg ) hb_xfree( pszArg ); + + printf("INFO: %i\n", hb_cmdargCheck( "INFO" ) ); + printf(" F: %s\n", pszArg = hb_cmdargString( "F" ) ); if( pszArg ) hb_xfree( pszArg ); + printf(" Fn: %i\n", hb_cmdargNum( "F" ) ); + printf("TEMP: %s\n", pszArg = hb_cmdargString( "TEMP" ) ); if( pszArg ) hb_xfree( pszArg ); +} + +#endif + diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 9d4f75c75a..12285e3ba9 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -33,6 +33,18 @@ * */ +/* + * The following parts are Copyright of the individual authors. + * www - http://www.harbour-project.org + * + * Copyright 1999 Victor Szel + * HB_WORD() + * HB___XHELP() + * + * See doc/license.txt for licensing terms. + * + */ + #ifndef __MPW__ #include #endif @@ -68,7 +80,7 @@ static void hb_vmSwapAlias( void ); /* swaps items on the eval stack an static ERRCODE hb_vmSelectWorkarea( PHB_ITEM ); /* select the workarea using a given item or a substituted value */ static void hb_vmDoInitStatics( void ); /* executes all _INITSTATICS functions */ -static void hb_vmDoInitFunctions( int argc, char * argv[] ); /* executes all defined PRGs INIT functions */ +static void hb_vmDoInitFunctions( void ); /* executes all defined PRGs INIT functions */ static void hb_vmDoExitFunctions( void ); /* executes all defined PRGs EXIT functions */ static void hb_vmReleaseLocalSymbols( void ); /* releases the memory of the local symbols linked list */ @@ -145,10 +157,10 @@ static USHORT s_uiActionRequest = 0; int main( int argc, char * argv[] ) { - int i; - HB_DEBUG( "main\n" ); + hb_cmdargInit( argc, argv ); + /* initialize internal data structures */ aStatics.type = IT_NIL; stack.Return.type = IT_NIL; @@ -165,29 +177,71 @@ int main( int argc, char * argv[] ) #endif hb_vmSymbolInit_RT(); /* initialize symbol table with runtime support functions */ + /* Check for some internal switches */ + + if( hb_cmdargCheck( "INFO" ) ) + { + char * pszVersion = hb_version( 1 ); + + printf( pszVersion ); + printf( hb_consoleGetNewLine() ); + + hb_xfree( pszVersion ); + } + /* Call functions that initializes static variables * Static variables have to be initialized before any INIT functions * because INIT function can use static variables */ hb_vmDoInitStatics(); - hb_vmDoInitFunctions( argc, argv ); /* process defined INIT functions */ + hb_vmDoInitFunctions(); /* process defined INIT functions */ -#ifdef HARBOUR_START_PROCEDURE + /* This is undocumented CA-Clipper, if there's a function called _APPMAIN + it will be executed first. */ { - PHB_DYNS pDynSym = hb_dynsymFind( HARBOUR_START_PROCEDURE ); + PHB_DYNS pDynSym = hb_dynsymFind( "_APPMAIN" ); if( pDynSym ) s_pSymStart = pDynSym->pSymbol; +#ifdef HARBOUR_START_PROCEDURE else - hb_errInternal( 9999, "Can\'t locate the starting procedure: \'%s\'", HARBOUR_START_PROCEDURE, NULL ); - } -#endif + { + pDynSym = hb_dynsymFind( HARBOUR_START_PROCEDURE ); - hb_vmPushSymbol( s_pSymStart ); /* pushes first FS_PUBLIC defined symbol to the stack */ - hb_vmPushNil(); /* places NIL at self */ - for( i = 1; i < argc; i++ ) /* places application parameters on the stack */ - hb_vmPushString( argv[ i ], strlen( argv[ i ] ) ); - hb_vmDo( argc - 1 ); /* invoke it with number of supplied parameters */ + if( pDynSym ) + s_pSymStart = pDynSym->pSymbol; + else + hb_errInternal( 9999, "Can\'t locate the starting procedure: \'%s\'", HARBOUR_START_PROCEDURE, NULL ); + } +#else +#ifndef HARBOUR_STRICT_CLIPPER_COMPATIBLE + else + hb_errInternal( 9999, "Starting procedure not found", NULL, NULL ); +#endif +#endif + } + + if( s_pSymStart ) + { + int i; + int iArgCount; + + hb_vmPushSymbol( s_pSymStart ); /* pushes first FS_PUBLIC defined symbol to the stack */ + hb_vmPushNil(); /* places NIL at self */ + + iArgCount = 0; + for( i = 1; i < argc; i++ ) /* places application parameters on the stack */ + { + /* Filter out any parameters beginning with //, like //INFO */ + if( ! hb_cmdargIsInternal( argv[ i ] ) ) + { + hb_vmPushString( argv[ i ], strlen( argv[ i ] ) ); + iArgCount++; + } + } + + hb_vmDo( iArgCount ); /* invoke it with number of supplied parameters */ + } hb_vmQuit(); @@ -2849,7 +2903,7 @@ static void hb_vmDoExitFunctions( void ) } while( pLastSymbols ); } -static void hb_vmDoInitFunctions( int argc, char * argv[] ) +static void hb_vmDoInitFunctions( void ) { PSYMBOLS pLastSymbols = s_pSymbols; @@ -2866,15 +2920,27 @@ static void hb_vmDoInitFunctions( int argc, char * argv[] ) if( scope == FS_INIT ) { + int argc = hb_cmdargARGC(); + char ** argv = hb_cmdargARGV(); + int i; + int iArgCount; hb_vmPushSymbol( pLastSymbols->pModuleSymbols + ui ); hb_vmPushNil(); + iArgCount = 0; for( i = 1; i < argc; i++ ) /* places application parameters on the stack */ - hb_vmPushString( argv[ i ], strlen( argv[ i ] ) ); + { + /* Filter out any parameters beginning with //, like //INFO */ + if( ! hb_cmdargIsInternal( argv[ i ] ) ) + { + hb_vmPushString( argv[ i ], strlen( argv[ i ] ) ); + iArgCount++; + } + } - hb_vmDo( argc - 1 ); + hb_vmDo( iArgCount ); } } } @@ -3181,7 +3247,7 @@ void hb_vmRequestCancel( void ) HARBOUR HB___XHELP( void ) { - PHB_DYNS pDynSym = hb_dynsymFindName( "HELP" ); + PHB_DYNS pDynSym = hb_dynsymFind( "HELP" ); if( pDynSym ) {