2013-04-18 14:58 UTC+0200 Przemysław Czerpak (druzus/at/poczta.onet.pl)

* .gitignore
    ! removed executable file permission

  * package/mpkg_src.sh
    ! added executable file permission

  * contrib/hbct/screen2.c
    % use STR API for parameters instead of using local conversions

  * contrib/hbct/token1.c
    % small simplification

  * contrib/hbnetio/netiosrv.c
    + respect timeout parameter also in send operation

  * contrib/make.hb
    ! moved project name normalization and directory verification to
      AddProject() function. It fixes HB_BUILD_ADDONS envvar functionality.

  * doc/xhb-diff.txt
    + added new paragraph: DECLARATION AND INITIALIZATION OF VARIABLES

  * src/rtl/hbcom.c
    * added 3-rd parameter to TIOCEXCL and TIOCNXCL ioctl() codes
      to pacify valgrind warnings

  * include/hbexpra.c
    ! fixed compilation with HB_USE_ENUM_FUNCTIONS macro

  * include/hbapicls.h
  * include/hbcompdf.h
  * include/hbexpra.c
  * src/compiler/harbour.y
  * src/vm/classes.c
    + added support for :__enumIsFirst() iterator message. It's opposite
      to recently added :__enumIsLast()
    + added support for overloading :__enumIsFirst() and :__enumIsLast()
      functionality in custom FOR EACH implementations

  * include/hbcompdf.h
  * include/hbexpra.c
  * src/compiler/harbour.y
    + added support for reverting :__enumIsFirst() and :__enumIsLast()
      messages in descendant FOR EACH loops. It's disabled now by 2 #if 0
      but I think it should be discussed. Should we keep it enable it?
      The answer is not trivial when FOR EACH is used to iterate some
      objects. In general such names are confusing.

  * src/compiler/harbour.yyc
  * src/compiler/harbour.yyh
    * regenerated using bison 2.5

  * tests/foreach.prg
    + added :__enumIsFirst() to test code

  * tests/foreach2.prg
    ! typo in comment
This commit is contained in:
Przemysław Czerpak
2013-04-18 14:58:40 +02:00
parent 6ad5bb4355
commit 877ddb4a06
18 changed files with 890 additions and 664 deletions

0
.gitignore vendored Executable file → Normal file
View File

View File

@@ -10,6 +10,65 @@
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
*/ */
2013-04-18 14:58 UTC+0200 Przemysław Czerpak (druzus/at/poczta.onet.pl)
* .gitignore
! removed executable file permission
* package/mpkg_src.sh
! added executable file permission
* contrib/hbct/screen2.c
% use STR API for parameters instead of using local conversions
* contrib/hbct/token1.c
% small simplification
* contrib/hbnetio/netiosrv.c
+ respect timeout parameter also in send operation
* contrib/make.hb
! moved project name normalization and directory verification to
AddProject() function. It fixes HB_BUILD_ADDONS envvar functionality.
* doc/xhb-diff.txt
+ added new paragraph: DECLARATION AND INITIALIZATION OF VARIABLES
* src/rtl/hbcom.c
* added 3-rd parameter to TIOCEXCL and TIOCNXCL ioctl() codes
to pacify valgrind warnings
* include/hbexpra.c
! fixed compilation with HB_USE_ENUM_FUNCTIONS macro
* include/hbapicls.h
* include/hbcompdf.h
* include/hbexpra.c
* src/compiler/harbour.y
* src/vm/classes.c
+ added support for :__enumIsFirst() iterator message. It's opposite
to recently added :__enumIsLast()
+ added support for overloading :__enumIsFirst() and :__enumIsLast()
functionality in custom FOR EACH implementations
* include/hbcompdf.h
* include/hbexpra.c
* src/compiler/harbour.y
+ added support for reverting :__enumIsFirst() and :__enumIsLast()
messages in descendant FOR EACH loops. It's disabled now by 2 #if 0
but I think it should be discussed. Should we keep it enable it?
The answer is not trivial when FOR EACH is used to iterate some
objects. In general such names are confusing.
* src/compiler/harbour.yyc
* src/compiler/harbour.yyh
* regenerated using bison 2.5
* tests/foreach.prg
+ added :__enumIsFirst() to test code
* tests/foreach2.prg
! typo in comment
2013-04-18 00:15 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) 2013-04-18 00:15 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt)
* contrib/sddfb/core.c * contrib/sddfb/core.c
* removed unused assignment * removed unused assignment

View File

@@ -50,6 +50,7 @@
*/ */
#include "hbapigt.h" #include "hbapigt.h"
#include "hbapistr.h"
#include "hbdate.h" #include "hbdate.h"
HB_FUNC( SAYDOWN ) HB_FUNC( SAYDOWN )
@@ -107,23 +108,11 @@ HB_FUNC( SAYDOWN )
hb_retc_null(); hb_retc_null();
} }
static HB_WCHAR * ct_TextToWChar( const char * szText, HB_SIZE * pnLen )
{
HB_WCHAR wc;
PHB_CODEPAGE cdp = hb_gtHostCP();
HB_SIZE nIndex = 0, nI = 0;
HB_WCHAR * pwc = ( HB_WCHAR * ) hb_xgrab( *pnLen * sizeof( HB_WCHAR ) );
while( HB_CDPCHAR_GET( cdp, szText, *pnLen, &nIndex, &wc ) )
pwc[ nI ++ ] = wc;
*pnLen = nI;
return pwc;
}
HB_FUNC( SAYSPREAD ) HB_FUNC( SAYSPREAD )
{ {
HB_SIZE nLen = hb_parclen( 1 ); HB_SIZE nLen;
void * hText;
const HB_WCHAR * pwText = hb_parstr_u16( 1, HB_CDP_ENDIAN_NATIVE, &hText, &nLen );
if( nLen ) if( nLen )
{ {
@@ -144,9 +133,6 @@ HB_FUNC( SAYSPREAD )
if( iRow >= 0 && iCol >= 0 && iRow <= iMaxRow && iCol <= iMaxCol ) if( iRow >= 0 && iCol >= 0 && iRow <= iMaxRow && iCol <= iMaxCol )
{ {
const char * szText = hb_parc( 1 );
HB_WCHAR * pwc = ct_TextToWChar( szText, &nLen );
int iColor = hb_gtGetCurrColor(); int iColor = hb_gtGetCurrColor();
nPos = nLen >> 1; nPos = nLen >> 1;
@@ -161,7 +147,7 @@ HB_FUNC( SAYSPREAD )
do do
{ {
for( ul = 0; ul < nLen && iCol + ( int ) ul <= iMaxCol; ++ul ) for( ul = 0; ul < nLen && iCol + ( int ) ul <= iMaxCol; ++ul )
hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pwc[ nPos + ul ] ); hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pwText[ nPos + ul ] );
nLen += 2; nLen += 2;
if( lDelay ) if( lDelay )
{ {
@@ -173,16 +159,18 @@ HB_FUNC( SAYSPREAD )
while( nPos-- && iCol-- ); while( nPos-- && iCol-- );
/* CT3 does not respect iCol in the above condition */ /* CT3 does not respect iCol in the above condition */
hb_gtEndWrite(); hb_gtEndWrite();
hb_xfree( pwc );
} }
} }
hb_strfree( hText );
hb_retc_null(); hb_retc_null();
} }
HB_FUNC( SAYMOVEIN ) HB_FUNC( SAYMOVEIN )
{ {
HB_SIZE nLen = hb_parclen( 1 ); HB_SIZE nLen;
void * hText;
const HB_WCHAR * pwText = hb_parstr_u16( 1, HB_CDP_ENDIAN_NATIVE, &hText, &nLen );
if( nLen ) if( nLen )
{ {
@@ -204,17 +192,13 @@ HB_FUNC( SAYMOVEIN )
if( iRow >= 0 && iCol >= 0 && iRow <= iMaxRow && iCol <= iMaxCol ) if( iRow >= 0 && iCol >= 0 && iRow <= iMaxRow && iCol <= iMaxCol )
{ {
const char * szText = hb_parc( 1 );
HB_WCHAR * pwc = ct_TextToWChar( szText, &nLen );
HB_WCHAR * pText = pwc;
int iColor = hb_gtGetCurrColor(); int iColor = hb_gtGetCurrColor();
iNewCol = iCol + nLen; iNewCol = iCol + ( int ) nLen;
if( fBack ) if( fBack )
iCol += nLen - 1; iCol += ( int ) nLen - 1;
else else
pText += nLen - 1; pwText += ( int ) nLen - 1;
nChars = 1; nChars = 1;
hb_gtBeginWrite(); hb_gtBeginWrite();
@@ -225,15 +209,15 @@ HB_FUNC( SAYMOVEIN )
if( iCol <= iMaxCol ) if( iCol <= iMaxCol )
{ {
for( ul = 0; ul < nChars; ++ul ) for( ul = 0; ul < nChars; ++ul )
hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pText[ ul ] ); hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pwText[ ul ] );
} }
--iCol; --iCol;
} }
else else
{ {
for( ul = 0; ul < nChars; ++ul ) for( ul = 0; ul < nChars; ++ul )
hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pText[ ul ] ); hb_gtPutChar( iRow, iCol + ( int ) ul, iColor, 0, pwText[ ul ] );
--pText; --pwText;
} }
if( ( int ) nChars + iCol <= iMaxCol ) if( ( int ) nChars + iCol <= iMaxCol )
++nChars; ++nChars;
@@ -248,9 +232,9 @@ HB_FUNC( SAYMOVEIN )
while( --nLen ); while( --nLen );
hb_gtSetPos( iRow, iNewCol ); hb_gtSetPos( iRow, iNewCol );
hb_gtEndWrite(); hb_gtEndWrite();
hb_xfree( pwc );
} }
} }
hb_strfree( hText );
hb_retc_null(); hb_retc_null();
} }
@@ -435,8 +419,7 @@ HB_FUNC( STRSCREEN ) /* TODO: Unicode support */
HB_FUNC( __HBCT_DSPTIME ) HB_FUNC( __HBCT_DSPTIME )
{ {
int iRow, iCol; int iRow, iCol;
int iColor; int iColor, iLen;
HB_SIZE nLen;
char szTime[ 10 ]; char szTime[ 10 ];
iRow = hb_parni( 1 ); iRow = hb_parni( 1 );
@@ -453,17 +436,17 @@ HB_FUNC( __HBCT_DSPTIME )
iColor = hb_gtGetClearColor(); iColor = hb_gtGetClearColor();
hb_dateTimeStr( szTime ); hb_dateTimeStr( szTime );
nLen = 8; iLen = 8;
if( hb_parl( 3 ) ) if( hb_parl( 3 ) )
nLen -= 3; iLen -= 3;
if( hb_parl( 5 ) ) if( hb_parl( 5 ) )
{ {
int iHour = ( szTime[ 0 ] - '0' ) * 10 + ( szTime[ 1 ] - '0' ); int iHour = ( szTime[ 0 ] - '0' ) * 10 + ( szTime[ 1 ] - '0' );
if( hb_parl( 6 ) ) if( hb_parl( 6 ) )
szTime[ nLen++ ] = iHour >= 12 ? 'p' : 'a'; szTime[ iLen++ ] = iHour >= 12 ? 'p' : 'a';
if( iHour > 12 ) if( iHour > 12 )
iHour -= 12; iHour -= 12;
else if( iHour == 0 ) else if( iHour == 0 )
@@ -475,5 +458,5 @@ HB_FUNC( __HBCT_DSPTIME )
if( szTime[ 0 ] == '0' ) if( szTime[ 0 ] == '0' )
szTime[ 0 ] = ' '; szTime[ 0 ] = ' ';
hb_gtPutText( iRow, iCol, szTime, nLen, iColor ); hb_gtPutText( iRow, iCol, szTime, iLen, iColor );
} }

View File

@@ -136,27 +136,23 @@ static void do_token1( int iSwitch )
sSeparatorStrLen = sc_sSeparatorStrLen; sSeparatorStrLen = sc_sSeparatorStrLen;
} }
/* token counter */
if( iSwitch != DO_TOKEN1_NUMTOKEN )
nTokenCounter = hb_parns( 3 );
if( nTokenCounter == 0 )
nTokenCounter = HB_SIZE_MAX;
/* skip width */
if( iSwitch == DO_TOKEN1_NUMTOKEN ) if( iSwitch == DO_TOKEN1_NUMTOKEN )
{ {
if( HB_ISNUM( 3 ) ) /* token counter */
nTokenCounter = HB_SIZE_MAX;
/* skip width */
nSkip = hb_parns( 3 ); nSkip = hb_parns( 3 );
else
nSkip = HB_SIZE_MAX;
} }
else else
{ {
if( HB_ISNUM( 4 ) ) /* HB_EXTENSION for AtToken()/TokenLower()/TokenUpper() */ /* token counter */
nSkip = hb_parns( 4 ); nTokenCounter = hb_parns( 3 );
else /* skip width */
nSkip = HB_SIZE_MAX; nSkip = hb_parns( 4 ); /* HB_EXTENSION for AtToken()/TokenLower()/TokenUpper() */
} }
if( nTokenCounter == 0 )
nTokenCounter = HB_SIZE_MAX;
if( nSkip == 0 ) if( nSkip == 0 )
nSkip = HB_SIZE_MAX; nSkip = HB_SIZE_MAX;

View File

@@ -358,8 +358,8 @@ static PHB_CONSRV s_consrvNew( HB_SOCKET connsd, const char * szRootPath, HB_BOO
static long s_srvRecvAll( PHB_CONSRV conn, void * buffer, long len ) static long s_srvRecvAll( PHB_CONSRV conn, void * buffer, long len )
{ {
HB_BYTE * ptr = ( HB_BYTE * ) buffer; HB_BYTE * ptr = ( HB_BYTE * ) buffer;
HB_MAXUINT end_timer;
long lRead = 0, l; long lRead = 0, l;
HB_MAXUINT end_timer;
end_timer = conn->timeout > 0 ? hb_dateMilliSeconds() + conn->timeout : 0; end_timer = conn->timeout > 0 ? hb_dateMilliSeconds() + conn->timeout : 0;
@@ -390,15 +390,18 @@ static long s_srvSendAll( PHB_CONSRV conn, void * buffer, long len )
{ {
HB_BYTE * ptr = ( HB_BYTE * ) buffer; HB_BYTE * ptr = ( HB_BYTE * ) buffer;
long lSent = 0, lLast = 1, l; long lSent = 0, lLast = 1, l;
HB_MAXUINT end_timer;
if( ! conn->mutex || hb_threadMutexLock( conn->mutex ) ) if( ! conn->mutex || hb_threadMutexLock( conn->mutex ) )
{ {
end_timer = conn->timeout > 0 ? hb_dateMilliSeconds() + conn->timeout : 0;
while( lSent < len && ! conn->stop ) while( lSent < len && ! conn->stop )
{ {
if( conn->zstream ) if( conn->zstream )
l = hb_znetWrite( conn->zstream, conn->sd, ptr + lSent, len - lSent, -1, &lLast ); l = hb_znetWrite( conn->zstream, conn->sd, ptr + lSent, len - lSent, 1000, &lLast );
else else
l = lLast = hb_socketSend( conn->sd, ptr + lSent, len - lSent, 0, -1 ); l = lLast = hb_socketSend( conn->sd, ptr + lSent, len - lSent, 0, 1000 );
if( l > 0 ) if( l > 0 )
{ {
lSent += l; lSent += l;
@@ -407,13 +410,15 @@ static long s_srvSendAll( PHB_CONSRV conn, void * buffer, long len )
if( lLast <= 0 ) if( lLast <= 0 )
{ {
if( hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT || if( hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT ||
hb_vmRequestQuery() != 0 ) hb_vmRequestQuery() != 0 ||
( end_timer != 0 && end_timer <= hb_dateMilliSeconds() ) )
break; break;
} }
} }
if( conn->zstream && lLast > 0 && ! conn->stop ) if( conn->zstream && lLast > 0 && ! conn->stop )
{ {
if( hb_znetFlush( conn->zstream, conn->sd, -1 ) != 0 ) if( hb_znetFlush( conn->zstream, conn->sd,
conn->timeout > 0 ? conn->timeout : -1 ) != 0 )
lSent = -1; lSent = -1;
} }

View File

@@ -399,13 +399,10 @@ STATIC PROCEDURE build_projects( nAction, hProjectList, hProjectReqList, cOption
/* Add referenced project not present in our list and featuring an .hbp file */ /* Add referenced project not present in our list and featuring an .hbp file */
FOR EACH cProject IN aSortedList FOR EACH cProject IN aSortedList
IF !( cProject $ hProjectList ) IF AddProject( hProjectList, @cProject )
IF hb_FileExists( s_cBase + s_cHome + cProject )
AddProject( hProjectList, cProject )
call_hbmk2_hbinfo( s_cBase + s_cHome + cProject, hProjectList[ cProject ] ) call_hbmk2_hbinfo( s_cBase + s_cHome + cProject, hProjectList[ cProject ] )
hProjectList[ cProject ][ "lFromContainer" ] := NIL hProjectList[ cProject ][ "lFromContainer" ] := NIL
ENDIF ENDIF
ENDIF
NEXT NEXT
/* Load project information for dependencies too /* Load project information for dependencies too
@@ -725,7 +722,7 @@ STATIC FUNCTION TopoSort( aEdgeList )
RETURN aList RETURN aList
PROCEDURE AddProject( hProjectList, cFileName ) FUNCTION AddProject( hProjectList, cFileName )
LOCAL cDir LOCAL cDir
LOCAL cName LOCAL cName
@@ -737,11 +734,10 @@ PROCEDURE AddProject( hProjectList, cFileName )
hb_FNameSplit( cFileName, @cDir, @cName, @cExt ) hb_FNameSplit( cFileName, @cDir, @cName, @cExt )
IF ! Empty( cName ) .AND. Empty( cDir )
cDir := cName
ENDIF
IF Empty( cName ) IF Empty( cName )
cName := DirGetName( cDir ) cName := DirGetName( cDir )
ELSEIF Empty( cDir )
cDir := cName
ENDIF ENDIF
IF Empty( cExt ) IF Empty( cExt )
cExt := ".hbp" cExt := ".hbp"
@@ -749,10 +745,17 @@ PROCEDURE AddProject( hProjectList, cFileName )
cFileName := hb_FNameMerge( cDir, cName, cExt ) cFileName := hb_FNameMerge( cDir, cName, cExt )
hProjectList[ StrTran( cFileName, "\", "/" ) ] := { => } IF hb_FileExists( s_cBase + s_cHome + cFileName )
cFileName := StrTran( cFileName, "\", "/" )
IF ! cFileName $ hProjectList
hProjectList[ cFileName ] := { => }
RETURN .T.
ENDIF
ENDIF ENDIF
RETURN ENDIF
RETURN .F.
PROCEDURE LoadProjectListFromFile( hProjectList, cFileName ) PROCEDURE LoadProjectListFromFile( hProjectList, cFileName )
@@ -762,9 +765,7 @@ PROCEDURE LoadProjectListFromFile( hProjectList, cFileName )
IF "#" $ cItem IF "#" $ cItem
cItem := Left( cItem, At( "#", cItem ) - 1 ) cItem := Left( cItem, At( "#", cItem ) - 1 )
ENDIF ENDIF
IF hb_FileExists( s_cBase + s_cHome + hb_DirSepToOS( AllTrim( cItem ) ) )
AddProject( hProjectList, cItem ) AddProject( hProjectList, cItem )
ENDIF
NEXT NEXT
RETURN RETURN
@@ -774,9 +775,7 @@ PROCEDURE LoadProjectListFromString( hProjectList, cString )
LOCAL cItem LOCAL cItem
FOR EACH cItem IN hb_ATokens( cString,, .T. ) FOR EACH cItem IN hb_ATokens( cString,, .T. )
IF hb_FileExists( s_cBase + s_cHome + cItem )
AddProject( hProjectList, cItem ) AddProject( hProjectList, cItem )
ENDIF
NEXT NEXT
RETURN RETURN

View File

@@ -521,6 +521,105 @@ references by detached locals and add workarounds for it if necessary.
### DECLARATION AND INITIALIZATION OF VARIABLES ###
=========================================================
Clipper parses variable declaration in a little bit different way then
Harbour and xHarbour. It makes it in two passes. In first pass it collects
names and scope of all declared variables and then in second pass this
information is available during variable initialization. This can be
illustrated by the following example:
/*** tst.prg ***/
proc main()
local cb := {|| qout( n + 5 ), qout( f ) } // (*)
field f in table
local n := 10
eval( cb )
return
In the line which initialize cb code (*) we are using local variable n
and field f. Both are declared below the line in which codeblock is
initialized anyhow Clipper does not recognize it as undeclared variables
and use their later declarations. If you compile above code using Clipper
with -n -w -es2 switches, i.e.
cl tst -n -w -es2
then it's compiled without any compile time warnings or errors. Then
during execution it shows 15 for the first QOUT() function call and
generate runtime error
Error BASE/1002 Alias does not exist: TABLE
for the second QOUT() call. It means that it correctly recognized scope
of both variables and also bound alias TABLE with field F though it was
declared two lines below codeblock initialization.
In fact Clipper probably does not make two passes but parsing declarations
which have to be at the beginning of function or module it stores names of
variables which should be initialized with the initialization expressions.
Then when all declarations are processed for each line with declared and
initialized variables it generates code which pushes on VM stack results
of initialization expressions and then code which pops it initializing
variables. As result in Clipper this code cannot work:
local x := 10, y := x + 2
because Clipper generate PCODE like:
push 10
push x
push 2
add
pop y
pop x
but this code:
local x := 10
local y := x + 2
works correctly because declarations were in separated lines and in such
case Clipper generates PCODE like:
push 10
pop x
push x
push 2
add
pop y
In Harbour and xHarbour all variables are declared in the moment when they
are processed. It means that during compilation of above example using
harbour tst -n -w -es2
both compilers generate compile time warnings:
tst.prg(2) Warning W0001 Ambiguous reference 'N'
tst.prg(2) Warning W0001 Ambiguous reference 'F'
but it also means that in Harbour and xHarbour it's possible to write code
like:
proc main()
local x := 10, y := x + 2
? x, y
return
and unlike Clipper both compilers generates correct PCODE which shows
10 12
Maybe in the future we add support for Clipper compatible local variable
initialization covered by -kc Harbor compiler switch.
xBase++ uses mixed behavior. Just like Clipper it stores variables with
initialization expressions but then it generates slightly different code
initializing variables one by one without line groping like in Clipper.
Please also note that in Clipper PRIVATE and PUBLIC declarations are
executable statements so they are not used used as declarations by
Clipper compiler even if -a compiler switch is used. So when we talk
about initialization then it means that we are talking about LOCAL
variables. STATIC variables are initialized in different way at
application startup so cannot use local variables though due to but
in Clipper in some cases compiler can accept local variables and then
it may cause VM crash or runtime error, i.e. this code:
proc main()
local n
static s := {|| n }
eval( s )
return
is cleanly compiled by Clipper and xBase++ but it causes RTE in
Clipper and FATAL ERROR LOG in xBase++.
Harbour and xHarbour correctly report compile time error for it.
### FUNCTIONS WITH VARIABLE NUMBER OF PARAMETERS ### ### FUNCTIONS WITH VARIABLE NUMBER OF PARAMETERS ###
========================================================== ==========================================================
Both compilers supports them though xHarbour is limited to all parameters Both compilers supports them though xHarbour is limited to all parameters

View File

@@ -83,8 +83,10 @@ HB_EXTERN_BEGIN
#define HB_OO_OP_ENUMSTART 25 #define HB_OO_OP_ENUMSTART 25
#define HB_OO_OP_ENUMSKIP 26 #define HB_OO_OP_ENUMSKIP 26
#define HB_OO_OP_ENUMSTOP 27 #define HB_OO_OP_ENUMSTOP 27
#define HB_OO_OP_ENUMISFIRST 28
#define HB_OO_OP_ENUMISLAST 29
#define HB_OO_MAX_OPERATOR 27 #define HB_OO_MAX_OPERATOR 29
extern void hb_clsInit( void ); /* initialize Classy/OO system at HVM startup */ extern void hb_clsInit( void ); /* initialize Classy/OO system at HVM startup */
extern void hb_clsDoInit( void ); /* initialize Classy/OO system .prg functions */ extern void hb_clsDoInit( void ); /* initialize Classy/OO system .prg functions */

View File

@@ -437,7 +437,7 @@ typedef struct HB_EXPR_
typedef struct HB_ENUMERATOR_ typedef struct HB_ENUMERATOR_
{ {
const char * szName; const char * szName;
HB_BOOL bForEach; int iForEachDir; /* 0 - standard FOR/NEXT, 1(-1) FOR EACH(descendant) */
struct HB_ENUMERATOR_ *pNext; struct HB_ENUMERATOR_ *pNext;
} HB_ENUMERATOR, * PHB_ENUMERATOR; /* support structure for FOR EACH statements */ } HB_ENUMERATOR, * PHB_ENUMERATOR; /* support structure for FOR EACH statements */
@@ -822,6 +822,7 @@ typedef struct _HB_COMP
HB_BOOL fBuildInfo; /* print build info */ HB_BOOL fBuildInfo; /* print build info */
HB_BOOL fLogo; /* print logo */ HB_BOOL fLogo; /* print logo */
HB_BOOL fSwitchCase; /* generate PCODE for CASE value of SWITCH statement */ HB_BOOL fSwitchCase; /* generate PCODE for CASE value of SWITCH statement */
HB_BOOL fDescend; /* add descendant FOR EACH iterators */
HB_BOOL fSingleModule; /* do not automatically compile DO...[WITH...] external modules (-m) */ HB_BOOL fSingleModule; /* do not automatically compile DO...[WITH...] external modules (-m) */
HB_BOOL fError; /* error appeared during compilation */ HB_BOOL fError; /* error appeared during compilation */
HB_BOOL fNoArchDefs; /* do not define architecture dependent macros: __PLATFORM__*, __ARCH??BIT__, __*_ENDIAN__ */ HB_BOOL fNoArchDefs; /* do not define architecture dependent macros: __PLATFORM__*, __ARCH??BIT__, __*_ENDIAN__ */

View File

@@ -144,7 +144,7 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL )
#if ! defined( HB_MACRO_SUPPORT ) && defined( HB_USE_ENUM_FUNCTIONS ) #if ! defined( HB_MACRO_SUPPORT ) && defined( HB_USE_ENUM_FUNCTIONS )
{ {
int iLen = strlen( pName->value.asSymbol.name ); int iLen = strlen( pName->value.asSymbol.name );
if( iLen >= 10 && i <= 12 && memcmp( "HB_ENUM", pName->value.asSymbol.name, 7 ) == 0 ) if( iLen >= 10 && iLen <= 14 && memcmp( "HB_ENUM", pName->value.asSymbol.name, 7 ) == 0 )
{ {
const char * szMessage = pName->value.asSymbol.name + 7; const char * szMessage = pName->value.asSymbol.name + 7;
@@ -156,6 +156,8 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL )
szMessage = "__ENUMBASE"; szMessage = "__ENUMBASE";
else if( iLen == 10 && memcmp( "KEY", szMessage, 3 ) == 0 ) else if( iLen == 10 && memcmp( "KEY", szMessage, 3 ) == 0 )
szMessage = "__ENUMKEY"; szMessage = "__ENUMKEY";
else if( iLen == 14 && memcmp( "ISFIRST", szMessage, 7 ) == 0 )
szMessage = "__ENUMISFIRST";
else if( iLen == 13 && memcmp( "ISLAST", szMessage, 6 ) == 0 ) else if( iLen == 13 && memcmp( "ISLAST", szMessage, 6 ) == 0 )
szMessage = "__ENUMISLAST"; szMessage = "__ENUMISLAST";
else else
@@ -164,42 +166,59 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL )
if( szMessage ) if( szMessage )
{ {
int iCount = ( int ) hb_compExprParamListLen( pParms ); int iCount = ( int ) hb_compExprParamListLen( pParms );
const char * szName = NULL; PHB_ENUMERATOR pForVar, pEnumVar = NULL;
pForVar = HB_COMP_PARAM->functions.pLast->pEnum;
if( iCount == 0 ) if( iCount == 0 )
{
PHB_ENUMERATOR pForVar, pEnumVar = NULL;
pForVar = HB_COMP_PARAM->functions.pLast->pEnum;
if( pForVar )
{ {
while( pForVar ) while( pForVar )
{ {
if( pForVar->bForEach ) if( pForVar->iForEachDir != 0 )
pEnumVar = pForVar; pEnumVar = pForVar;
pForVar = pForVar->pNext; pForVar = pForVar->pNext;
} }
if( pEnumVar )
szName = pEnumVar->szName;
}
} }
else if( iCount == 1 ) else if( iCount == 1 )
{ {
if( pParms->value.asList.pExprList->ExprType == HB_ET_VARIABLE || if( pParms->value.asList.pExprList->ExprType == HB_ET_VARIABLE ||
pParms->value.asList.pExprList->ExprType == HB_ET_VARREF ) pParms->value.asList.pExprList->ExprType == HB_ET_VARREF )
szName = pParms->value.asList.pExprList->value.asSymbol.name;
}
if( szName )
{ {
const char * szName = pParms->value.asList.pExprList->value.asSymbol.name;
while( pForVar )
{
if( pForVar->iForEachDir != 0 &&
strcmp( pEnumVar->szName, szName ) == 0 )
{
pEnumVar = pForVar;
break;
}
pForVar = pForVar->pNext;
}
}
}
if( pEnumVar )
{
#if 0
if( pEnumVar->iForEachDir < 0 )
{
if( strcmp( "__ENUMISFIRST", szMessage ) == 0 )
szMessage = "__ENUMISLAST";
else if( strcmp( "__ENUMISLAST", szMessage ) == 0 )
szMessage = "__ENUMISFIRST";
}
#endif
if( pParms ) if( pParms )
HB_COMP_EXPR_FREE( pParms ); HB_COMP_EXPR_FREE( pParms );
HB_COMP_EXPR_FREE( pName ); HB_COMP_EXPR_FREE( pName );
return hb_compExprNewMethodObject( return hb_compExprNewMethodObject(
hb_compExprNewSend( szMessage, HB_COMP_PARAM ), hb_compExprNewSend( szMessage, HB_COMP_PARAM ),
hb_compExprNewVar( szName, HB_COMP_PARAM ) ); hb_compExprNewVar( pEnumVar->szName, HB_COMP_PARAM ) );
}
} }
} }
} }
else
#endif #endif
if( pName->value.asSymbol.funcid == HB_F_EVAL && if( pName->value.asSymbol.funcid == HB_F_EVAL &&
hb_compExprParamListLen( pParms ) != 0 ) hb_compExprParamListLen( pParms ) != 0 )

0
package/mpkg_src.sh Normal file → Executable file
View File

View File

@@ -91,7 +91,7 @@ static void hb_compRTVariableGen( HB_COMP_DECL, const char * );
static PHB_EXPR hb_compArrayDimPush( PHB_EXPR pInitValue, HB_COMP_DECL ); static PHB_EXPR hb_compArrayDimPush( PHB_EXPR pInitValue, HB_COMP_DECL );
static void hb_compVariableDim( const char *, PHB_EXPR, HB_COMP_DECL ); static void hb_compVariableDim( const char *, PHB_EXPR, HB_COMP_DECL );
static void hb_compForStart( HB_COMP_DECL, const char *szVarName, HB_BOOL bForEach ); static void hb_compForStart( HB_COMP_DECL, const char *szVarName, int iForEachDir );
static void hb_compForEnd( HB_COMP_DECL, const char *szVarName ); static void hb_compForEnd( HB_COMP_DECL, const char *szVarName );
static void hb_compEnumStart( HB_COMP_DECL, PHB_EXPR pVars, PHB_EXPR pExprs, int descend ); static void hb_compEnumStart( HB_COMP_DECL, PHB_EXPR pVars, PHB_EXPR pExprs, int descend );
static void hb_compEnumNext( HB_COMP_DECL, PHB_EXPR pExpr, int descend ); static void hb_compEnumNext( HB_COMP_DECL, PHB_EXPR pExpr, int descend );
@@ -1551,7 +1551,7 @@ ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
$<asExpr>$ = hb_compExprGenPush( hb_compExprAssign( $2, $4, HB_COMP_PARAM ), HB_COMP_PARAM ); $<asExpr>$ = hb_compExprGenPush( hb_compExprAssign( $2, $4, HB_COMP_PARAM ), HB_COMP_PARAM );
if( hb_compExprAsSymbol( $2 ) ) if( hb_compExprAsSymbol( $2 ) )
{ {
hb_compForStart( HB_COMP_PARAM, hb_compExprAsSymbol( $2 ), HB_FALSE ); hb_compForStart( HB_COMP_PARAM, hb_compExprAsSymbol( $2 ), 0 );
} }
} }
TO ExpList StepExpr /* 6 7 8 */ TO ExpList StepExpr /* 6 7 8 */
@@ -2416,7 +2416,7 @@ static void hb_compVariableDim( const char * szName, PHB_EXPR pInitValue, HB_COM
} }
} }
static void hb_compForStart( HB_COMP_DECL, const char *szVarName, HB_BOOL bForEach ) static void hb_compForStart( HB_COMP_DECL, const char *szVarName, int iForEachDir )
{ {
PHB_ENUMERATOR pEnumVar; PHB_ENUMERATOR pEnumVar;
@@ -2449,11 +2449,11 @@ static void hb_compForStart( HB_COMP_DECL, const char *szVarName, HB_BOOL bForEa
pEnumVar = pLast->pNext; pEnumVar = pLast->pNext;
} }
pEnumVar->szName = szVarName; pEnumVar->szName = szVarName;
pEnumVar->bForEach = bForEach; pEnumVar->iForEachDir = iForEachDir;
pEnumVar->pNext = NULL; pEnumVar->pNext = NULL;
} }
static HB_BOOL hb_compForEachVarError( HB_COMP_DECL, const char *szVarName ) static HB_BOOL hb_compForEachVarError( HB_COMP_DECL, const char *szVarName, int * piDir )
{ {
PHB_ENUMERATOR pEnumVar; PHB_ENUMERATOR pEnumVar;
@@ -2464,7 +2464,8 @@ static HB_BOOL hb_compForEachVarError( HB_COMP_DECL, const char *szVarName )
{ {
if( strcmp( pEnumVar->szName, szVarName ) == 0 ) if( strcmp( pEnumVar->szName, szVarName ) == 0 )
{ {
if( pEnumVar->bForEach ) * piDir = pEnumVar->iForEachDir;
if( * piDir != 0 )
{ {
/* only if it is FOR EACH enumerator /* only if it is FOR EACH enumerator
* generate warning if it is FOR/NEXT loop * generate warning if it is FOR/NEXT loop
@@ -2502,7 +2503,7 @@ static HB_COMP_CARGO2_FUNC( hb_compEnumEvalStart )
const char * szName = hb_compExprAsSymbol( ( PHB_EXPR ) cargo ); const char * szName = hb_compExprAsSymbol( ( PHB_EXPR ) cargo );
if( szName ) if( szName )
hb_compForStart( HB_COMP_PARAM, szName, HB_TRUE ); hb_compForStart( HB_COMP_PARAM, szName, HB_COMP_PARAM->fDescend ? -1 : 1 );
hb_compExprGenPush( ( PHB_EXPR ) dummy, HB_COMP_PARAM ); /* expression */ hb_compExprGenPush( ( PHB_EXPR ) dummy, HB_COMP_PARAM ); /* expression */
hb_compExprGenPush( ( PHB_EXPR ) cargo, HB_COMP_PARAM ); /* variable */ hb_compExprGenPush( ( PHB_EXPR ) cargo, HB_COMP_PARAM ); /* variable */
@@ -2517,6 +2518,7 @@ static void hb_compEnumStart( HB_COMP_DECL, PHB_EXPR pVars, PHB_EXPR pExprs, int
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FORVAR_DIFF, NULL, NULL ); hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FORVAR_DIFF, NULL, NULL );
} }
HB_COMP_PARAM->fDescend = descend < 0;
ulLen = hb_compExprListEval2( HB_COMP_PARAM, pVars, pExprs, hb_compEnumEvalStart ); ulLen = hb_compExprListEval2( HB_COMP_PARAM, pVars, pExprs, hb_compEnumEvalStart );
if( ulLen > 255 ) if( ulLen > 255 )
@@ -2815,10 +2817,23 @@ static PHB_EXPR hb_compCheckMethod( HB_COMP_DECL, PHB_EXPR pExpr )
strcmp( "KEY", szMessage ) == 0 || strcmp( "KEY", szMessage ) == 0 ||
strcmp( "BASE", szMessage ) == 0 || strcmp( "BASE", szMessage ) == 0 ||
strcmp( "VALUE", szMessage ) == 0 || strcmp( "VALUE", szMessage ) == 0 ||
strcmp( "ISFIRST", szMessage ) == 0 ||
strcmp( "ISLAST", szMessage ) == 0 ) strcmp( "ISLAST", szMessage ) == 0 )
{ {
if( ! hb_compForEachVarError( HB_COMP_PARAM, pExpr->value.asMessage.pObject->value.asSymbol.name ) ) int iDir = 0;
if( ! hb_compForEachVarError( HB_COMP_PARAM, pExpr->value.asMessage.pObject->value.asSymbol.name, &iDir ) )
{
pExpr->value.asMessage.pObject->ExprType = HB_ET_VARREF; pExpr->value.asMessage.pObject->ExprType = HB_ET_VARREF;
#if 0
if( iDir < 0 )
{
if( strcmp( "ISFIRST", szMessage ) == 0 )
pExpr->value.asMessage.szMessage = "__ENUMISLAST";
else if( strcmp( "ISLAST", szMessage ) == 0 )
pExpr->value.asMessage.szMessage = "__ENUMISFIRST";
}
#endif
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -156,7 +156,7 @@ typedef union YYSTYPE
{ {
/* Line 2068 of yacc.c */ /* Line 2068 of yacc.c */
#line 125 "harbour.y" #line 121 "harbour.y"
const char * string; /* to hold a string returned by lex */ const char * string; /* to hold a string returned by lex */
int iNumber; /* to hold a temporary integer number */ int iNumber; /* to hold a temporary integer number */

View File

@@ -1272,7 +1272,7 @@ int hb_comClose( int iPort )
{ {
hb_vmUnlock(); hb_vmUnlock();
#if defined( TIOCNXCL ) #if defined( TIOCNXCL )
ioctl( pCom->fd, TIOCNXCL ); ioctl( pCom->fd, TIOCNXCL, 0 );
#endif #endif
do do
{ {
@@ -1314,7 +1314,7 @@ int hb_comOpen( int iPort )
if( pCom->fd != -1 ) if( pCom->fd != -1 )
{ {
#if defined( TIOCEXCL ) /* TIOCNXCL */ #if defined( TIOCEXCL ) /* TIOCNXCL */
iResult = ioctl( pCom->fd, TIOCEXCL ); iResult = ioctl( pCom->fd, TIOCEXCL, 0 );
if( iResult != 0 ) if( iResult != 0 )
{ {
close( pCom->fd ); close( pCom->fd );

View File

@@ -304,7 +304,9 @@ static HB_SYMB s_opSymbols[ HB_OO_MAX_OPERATOR + 1 ] = {
{ "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 24 */ { "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 24 */
{ "__ENUMSTART", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 25 */ { "__ENUMSTART", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 25 */
{ "__ENUMSKIP", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 26 */ { "__ENUMSKIP", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 26 */
{ "__ENUMSTOP", {HB_FS_MESSAGE}, {NULL}, NULL } /* 27 */ { "__ENUMSTOP", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 27 */
{ "__ENUMISFIRST", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 28 */
{ "__ENUMISLAST", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 29 */
}; };
static HB_SYMB s___msgDestructor = { "__msgDestructor", {HB_FS_MESSAGE}, {NULL}, NULL }; static HB_SYMB s___msgDestructor = { "__msgDestructor", {HB_FS_MESSAGE}, {NULL}, NULL };
@@ -348,6 +350,7 @@ static HB_SYMB s___msgEnumIndex = { "__ENUMINDEX", {HB_FS_MESSAGE}, {HB_FUN
static HB_SYMB s___msgEnumBase = { "__ENUMBASE", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL }; static HB_SYMB s___msgEnumBase = { "__ENUMBASE", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL };
static HB_SYMB s___msgEnumKey = { "__ENUMKEY", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL }; static HB_SYMB s___msgEnumKey = { "__ENUMKEY", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL };
static HB_SYMB s___msgEnumValue = { "__ENUMVALUE", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL }; static HB_SYMB s___msgEnumValue = { "__ENUMVALUE", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL };
static HB_SYMB s___msgEnumIsFirst = { "__ENUMISFIRST", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL };
static HB_SYMB s___msgEnumIsLast = { "__ENUMISLAST", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL }; static HB_SYMB s___msgEnumIsLast = { "__ENUMISLAST", {HB_FS_MESSAGE}, {HB_FUNCNAME( msgNull )}, NULL };
/* WITH OBJECT base value access/asign methods (:__withobject) */ /* WITH OBJECT base value access/asign methods (:__withobject) */
@@ -1180,6 +1183,7 @@ void hb_clsInit( void )
s___msgEnumBase.pDynSym = hb_dynsymGetCase( s___msgEnumBase.szName ); s___msgEnumBase.pDynSym = hb_dynsymGetCase( s___msgEnumBase.szName );
s___msgEnumKey.pDynSym = hb_dynsymGetCase( s___msgEnumKey.szName ); s___msgEnumKey.pDynSym = hb_dynsymGetCase( s___msgEnumKey.szName );
s___msgEnumValue.pDynSym = hb_dynsymGetCase( s___msgEnumValue.szName ); s___msgEnumValue.pDynSym = hb_dynsymGetCase( s___msgEnumValue.szName );
s___msgEnumIsFirst.pDynSym = hb_dynsymGetCase( s___msgEnumIsFirst.szName );
s___msgEnumIsLast.pDynSym = hb_dynsymGetCase( s___msgEnumIsLast.szName ); s___msgEnumIsLast.pDynSym = hb_dynsymGetCase( s___msgEnumIsLast.szName );
s___msgWithObjectPush.pDynSym = hb_dynsymGetCase( s___msgWithObjectPush.szName ); s___msgWithObjectPush.pDynSym = hb_dynsymGetCase( s___msgWithObjectPush.szName );
@@ -2010,14 +2014,34 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage,
hb_itemCopy( pEnum, hb_itemUnRef( hb_stackItemFromBase( 1 ) ) ); hb_itemCopy( pEnum, hb_itemUnRef( hb_stackItemFromBase( 1 ) ) );
return &s___msgEnumValue; return &s___msgEnumValue;
} }
else if( pMsg == s___msgEnumIsFirst.pDynSym )
{
PHB_ITEM pBase = HB_IS_BYREF( pEnum->item.asEnum.basePtr ) ?
hb_itemUnRef( pEnum->item.asEnum.basePtr ) :
pEnum->item.asEnum.basePtr;
if( HB_IS_OBJECT( pBase ) &&
hb_objHasOperator( pBase, HB_OO_OP_ENUMISFIRST ) )
return hb_objGetMethod( pBase, pMessage, pStack );
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset <= 1 );
return &s___msgEnumIsFirst;
}
else if( pMsg == s___msgEnumIsLast.pDynSym ) else if( pMsg == s___msgEnumIsLast.pDynSym )
{ {
if( HB_IS_ARRAY( pEnum->item.asEnum.basePtr ) ) PHB_ITEM pBase = HB_IS_BYREF( pEnum->item.asEnum.basePtr ) ?
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_arrayLen( pEnum->item.asEnum.basePtr ) ); hb_itemUnRef( pEnum->item.asEnum.basePtr ) :
else if( HB_IS_HASH( pEnum->item.asEnum.basePtr ) ) pEnum->item.asEnum.basePtr;
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_hashLen( pEnum->item.asEnum.basePtr ) ); if( HB_IS_ARRAY( pBase ) )
else if( HB_IS_STRING( pEnum->item.asEnum.basePtr ) ) {
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_itemGetCLen( pEnum->item.asEnum.basePtr ) ); if( HB_IS_OBJECT( pBase ) &&
hb_objHasOperator( pBase, HB_OO_OP_ENUMISLAST ) )
return hb_objGetMethod( pBase, pMessage, pStack );
else
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_arrayLen( pBase ) );
}
else if( HB_IS_HASH( pBase ) )
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_hashLen( pBase ) );
else if( HB_IS_STRING( pBase ) )
hb_itemPutL( hb_stackReturnItem(), ( HB_SIZE ) pEnum->item.asEnum.offset >= hb_itemGetCLen( pBase ) );
return &s___msgEnumIsLast; return &s___msgEnumIsLast;
} }

View File

@@ -28,6 +28,7 @@ PROCEDURE Main()
"| index:", enum:__enumIndex(), ; "| index:", enum:__enumIndex(), ;
"| value:", enum:__enumValue(), ; "| value:", enum:__enumValue(), ;
"| base:", ValType( enum:__enumBase() ), ; "| base:", ValType( enum:__enumBase() ), ;
"| isfirst:", enum:__enumIsFirst(), ;
"| islast:", enum:__enumIsLast() "| islast:", enum:__enumIsLast()
NEXT NEXT
? "after loop ENUM=", enum ? "after loop ENUM=", enum
@@ -47,12 +48,14 @@ PROCEDURE Main()
"| index:", enum:__enumIndex(), ; "| index:", enum:__enumIndex(), ;
"| value:", enum:__enumValue(), ; "| value:", enum:__enumValue(), ;
"| base:", ValType( enum:__enumBase() ), ; "| base:", ValType( enum:__enumBase() ), ;
"| isfirst:", enum:__enumIsFirst(), ;
"| islast:", enum:__enumIsLast() "| islast:", enum:__enumIsLast()
testBYREF( @enum ) testBYREF( @enum )
? " after passing by @ | ENUM=", enum, ; ? " after passing by @ | ENUM=", enum, ;
"| index:", enum:__enumIndex(), ; "| index:", enum:__enumIndex(), ;
"| value:", enum:__enumValue(), ; "| value:", enum:__enumValue(), ;
"| base:", ValType( enum:__enumBase() ), ; "| base:", ValType( enum:__enumBase() ), ;
"| isfirst:", enum:__enumIsFirst(), ;
"| islast:", enum:__enumIsLast() "| islast:", enum:__enumIsLast()
ENDIF ENDIF
NEXT NEXT
@@ -70,6 +73,7 @@ PROCEDURE Main()
"| index:", enum:__enumIndex(), ; "| index:", enum:__enumIndex(), ;
"| value:", enum:__enumValue(), ; "| value:", enum:__enumValue(), ;
"| base:", ValType( enum:__enumBase() ), ; "| base:", ValType( enum:__enumBase() ), ;
"| isfirst:", enum:__enumIsFirst(), ;
"| islast:", enum:__enumIsLast() "| islast:", enum:__enumIsLast()
TESTbreak( enum ) TESTbreak( enum )
NEXT NEXT
@@ -95,6 +99,7 @@ PROCEDURE Main()
"| index:", enum:__enumIndex(), ; "| index:", enum:__enumIndex(), ;
"| value:", enum:__enumValue(), ; "| value:", enum:__enumValue(), ;
"| base:", ValType( enum:__enumBase() ), ; "| base:", ValType( enum:__enumBase() ), ;
"| isfirst:", enum:__enumIsFirst(), ;
"| islast:", enum:__enumIsLast() "| islast:", enum:__enumIsLast()
NEXT NEXT
RECOVER USING i RECOVER USING i

View File

@@ -97,7 +97,7 @@ METHOD __enumSkip( enum, lDescend ) CLASS myclass2
/* set enumerator value */ /* set enumerator value */
(@enum):__enumValue( ::value / 10.0 ) (@enum):__enumValue( ::value / 10.0 )
/* the index is updated automatically but if we want some noncontinuous /* the index is updated automatically but if we want some noncontinuous
* indexes then here we van set it using (@enum):__enumIndex( nNeIndex ) * indexes then here we can set it using (@enum):__enumIndex( nNeIndex )
* message * message
*/ */
return .T. /* continue iteration */ return .T. /* continue iteration */