ChangeLog 2001-08-17 20:15 UTC+0100

This commit is contained in:
Ryszard Glab
2001-08-17 18:26:37 +00:00
parent 32b9bec01f
commit f047a9927f
9 changed files with 66 additions and 233 deletions

View File

@@ -1,3 +1,23 @@
2001-08-17 20:15 UTC+0100 Ryszard Glab <rglab@imid.med.pl>
*doc/en/compiler.txt
*source/compiler/hbusage.c
*updated to keep current state of compiler switches
*include/hbexprc.c
*fixed support for "&macro" syntax (macro was not expanded in
cases: "&macro.&(macro)"
*include/hbapi.h
*include/hbexprb.c
*source/vm/hvm.c
*source/vm/macro.c
*optimized support for compile time switches synchronization
*source/compiler/harbour.y
*fixed support for #line directive
2001-08-17 15:09 GMT+2 Maurilio Longo <maurilio.longo@libero.it>
* source/rtl/tbrowse.prg
! fixed ::DispCell() cursor positioning (broken with latest changes to

View File

@@ -62,15 +62,15 @@
*
* /kc clear all flags (strict Clipper compatibility)
*
* /kh Harbour extensions
* /kh Harbour extensions (default)
*
* /ki HB_INLINE support enabled (default)
* /ki HB_INLINE support enabled (default)
*
* /ks synchronize compile and runtime modes (default)
* /kr use runtime settings for the macro compiler
*
* /kx other xbase dialects extensions (default)
*
* /k? invoke help information
* /k? invoke help information
*
* /l suppress line number information </par>
* ================= </par>

View File

@@ -528,8 +528,8 @@ typedef struct HB_MACRO_ /* a macro compiled pcode container */
int iListElements;
} HB_MACRO, * HB_MACRO_PTR;
extern void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext ); /* retrieve results of a macro expansion */
extern void hb_macroSetValue( HB_ITEM_PTR pItem ); /* assign a value to a macro-expression item */
extern void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext, BYTE flags ); /* retrieve results of a macro expansion */
extern void hb_macroSetValue( HB_ITEM_PTR pItem, BYTE flags ); /* assign a value to a macro-expression item */
extern void hb_macroTextValue( HB_ITEM_PTR pItem ); /* macro text substitution */
extern void hb_macroPushSymbol( HB_ITEM_PTR pItem ); /* handle a macro function calls, e.g. var := &macro() */
extern void hb_macroRun( HB_MACRO_PTR pMacro ); /* executes pcode compiled by macro compiler */
@@ -537,8 +537,8 @@ extern HB_MACRO_PTR hb_macroCompile( char * szString ); /* compile a string and
extern void hb_macroDelete( HB_MACRO_PTR pMacro ); /* release all memory allocated for macro evaluation */
extern char * hb_macroTextSubst( char * szString, ULONG *pulStringLen ); /* substitute macro variables occurences within a given string */
extern BOOL hb_macroIsIdent( char * szString ); /* determine if a string is a valid function or variable name */
extern void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar ); /* compiles and evaluates an aliased macro expression */
extern void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar ); /* compiles and evaluates an aliased macro expression */
extern void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, BYTE flags ); /* compiles and evaluates an aliased macro expression */
extern void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, BYTE flags ); /* compiles and evaluates an aliased macro expression */
extern char * hb_macroGetType( HB_ITEM_PTR pItem ); /* determine the type of an expression */
extern char * hb_macroExpandString( char *szString, ULONG ulLength, BOOL *pbNewString ); /* expands valid '&' operator */

View File

@@ -338,30 +338,8 @@ static HB_EXPR_FUNC( hb_compExprUseString )
case HB_EA_PUSH_PCODE:
{
HB_EXPR_PCODE2( hb_compGenPushString, pSelf->value.asString.string, pSelf->ulLength );
#if !defined( HB_MACRO_SUPPORT )
/* only memvar variables are allowed in macro compilation - there is no
* need to check for locals or static variables
*/
if( hb_compExprCheckMacroVar( pSelf->value.asString.string ) )
{
HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_MACROTEXT );
/* Always add add byte to pcode indicating requested macro compiler flag. */
#if defined( HB_MACRO_SUPPORT )
HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_COMPFLAG_RT_MACRO );
#else
HB_EXPR_GENPCODE1( hb_compGenPData1,
(
( hb_comp_Supported & HB_COMPFLAG_HARBOUR ? HB_SM_HARBOUR : 0 ) |
( hb_comp_Supported & HB_COMPFLAG_XBASE ? HB_SM_XBASE : 0 ) |
( hb_comp_bShortCuts ? HB_SM_SHORTCUTS : 0 ) |
( hb_comp_Supported & HB_COMPFLAG_RT_MACRO ? HB_SM_RT_MACRO : 0 )
)
);
#endif
}
#endif
if( hb_compExprCheckMacroVar( pSelf->value.asString.string ) )
HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_MACROTEXT );
}
break;
case HB_EA_POP_PCODE:

View File

@@ -437,6 +437,7 @@ BOOL hb_compExprCheckMacroVar( char * szText )
{
char * pTmp = szText;
BOOL bTextSubst = FALSE;
BOOL bMacroText = FALSE;
while( ( pTmp = strchr( pTmp, '&' ) ) != NULL )
{
@@ -453,9 +454,12 @@ BOOL hb_compExprCheckMacroVar( char * szText )
/* NOTE: All variables are assumed memvars in macro compiler -
* there is no need to check for a valid name
*/
#if !defined( HB_MACRO_SUPPORT )
if( bTextSubst )
{
#if defined( HB_MACRO_SUPPORT )
HB_SYMBOL_UNUSED( bMacroText );
return TRUE; /*there is no need to check all '&' occurences */
#else
/* There is a valid character after '&' that can be used in
* variable name - check if the whole variable name is valid
* (local, static and field variable names are invalid because
@@ -474,10 +478,11 @@ BOOL hb_compExprCheckMacroVar( char * szText )
*pTmp = '\0';
hb_compVariableMacroCheck( pStart );
*pTmp = cSave;
}
bMacroText = TRUE;
#endif
}
}
return bTextSubst;
return bMacroText;
}
/* Reduces the list of expressions

View File

@@ -414,6 +414,7 @@ CrlfStmnt : { hb_compLinePushIfInside(); } Crlf
LineStat : Crlf { $<lNumber>$ = 0; hb_comp_bDontGenLineNum = TRUE; }
| Statement { $<lNumber>$ = 1; }
| Declaration { $<lNumber>$ = 1; }
| Line { $<lNumber>$ = 1; }
;
Statements : LineStat { $<lNumber>$ = $<lNumber>1; }

View File

@@ -113,7 +113,7 @@ void hb_compPrintModes( void )
"\nOptions: c clear all flags (strict Clipper mode)",
"\n h Harbour mode (default)",
"\n i enable support for HB_INLINE",
"\n s synchronize compile and runtime modes",
"\n r runtime settings enabled",
"\n x extended xbase mode",
"\n ? this info",
"\n"

View File

@@ -264,12 +264,6 @@ int hb_vm_aiExtraElements[HB_MAX_MACRO_ARGS], hb_vm_iExtraElementsIndex = 0, hb_
int hb_vm_iExtraIndex;
#ifdef __cplusplus
extern "C" ULONG hb_macroAutoSetMacro( ULONG ulFlag );
#else
extern ULONG hb_macroAutoSetMacro( ULONG ulFlag );
#endif
/* Request for some action - stop processing of opcodes
*/
static USHORT s_uiActionRequest;
@@ -446,8 +440,6 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
BOOL bCanRecover = FALSE;
ULONG ulPrivateBase;
LONG lOffset;
BOOL bSetMacro;
ULONG ulMacroFlags;
HB_TRACE(HB_TR_DEBUG, ("hb_vmExecute(%p, %p)", pCode, pSymbols));
@@ -1228,96 +1220,32 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
/* macro creation */
case HB_P_MACROPOP:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - pop a value from the stack */
hb_macroSetValue( hb_stackItemFromTop( -1 ) );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroSetValue( hb_stackItemFromTop( -1 ), pCode[ ++w ] );
w++;
break;
case HB_P_MACROPOPALIASED:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - pop an aliased variable from the stack */
hb_macroPopAliasedValue( hb_stackItemFromTop( - 2 ), hb_stackItemFromTop( -1 ) );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroPopAliasedValue( hb_stackItemFromTop( - 2 ), hb_stackItemFromTop( -1 ), pCode[ ++w ] );
w++;
break;
case HB_P_MACROPUSH:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave the result on the stack */
/* the topmost element on the stack contains a macro
* string for compilation
*/
hb_macroGetValue( hb_stackItemFromTop( -1 ), 0 );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroGetValue( hb_stackItemFromTop( -1 ), 0, pCode[ ++w ] );
w++;
break;
case HB_P_MACROPUSHARG:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave the result on the stack */
/* the topmost element on the stack contains a macro
* string for compilation
*/
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHARG );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHARG, pCode[ ++w ] );
w++;
if( hb_vm_iExtraParamsIndex && hb_vm_apExtraParamsSymbol[hb_vm_iExtraParamsIndex - 1] == NULL )
@@ -1363,27 +1291,11 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
break;
case HB_P_MACROPUSHLIST:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave the result on the stack */
/* the topmost element on the stack contains a macro
* string for compilation
*/
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHLIST );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHLIST, pCode[ ++w ] );
w++;
break;
@@ -1393,27 +1305,11 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
break;
case HB_P_MACROPUSHINDEX:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave the result on the stack */
/* the topmost element on the stack contains a macro
* string for compilation
*/
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHINDEX );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHINDEX, pCode[ ++w ] );
if( hb_vm_iExtraIndex )
{
HB_ITEM *aExtraItems = (HB_ITEM *) hb_xgrab( sizeof( HB_ITEM ) * hb_vm_iExtraIndex );
@@ -1445,95 +1341,31 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
break;
case HB_P_MACROPUSHPARE:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave the result on the stack */
/* the topmost element on the stack contains a macro
* string for compilation
*/
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHPARE );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroGetValue( hb_stackItemFromTop( -1 ), HB_P_MACROPUSHPARE, pCode[ ++w ] );
w++;
break;
case HB_P_MACROPUSHALIASED:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile and run - leave an aliased variable on the stack */
hb_macroPushAliasedValue( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ) );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
hb_macroPushAliasedValue( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), pCode[ ++w ] );
w++;
break;
case HB_P_MACROSYMBOL:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* compile into a symbol name (used in function calls) */
hb_macroPushSymbol( hb_stackItemFromTop( -1 ) );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
w++;
break;
case HB_P_MACROTEXT:
if( ! ( pCode[ ++w ] & HB_SM_RT_MACRO ) )
{
bSetMacro = TRUE;
ulMacroFlags = hb_macroAutoSetMacro( (ULONG) pCode[ w ] );
}
else
{
bSetMacro = FALSE;
}
/* macro text substitution
* "text &macro.other text"
*/
hb_macroTextValue( hb_stackItemFromTop( -1 ) );
if( bSetMacro )
{
hb_macroAutoSetMacro( ulMacroFlags );
}
w++;
break;

View File

@@ -71,7 +71,7 @@ BOOL hb_comp_bShortCuts = TRUE;
/* various flags for macro compiler */
static ULONG s_macroFlags = HB_SM_SHORTCUTS;
static void hb_macroUseAliased( HB_ITEM_PTR, HB_ITEM_PTR, int );
static void hb_macroUseAliased( HB_ITEM_PTR, HB_ITEM_PTR, int, BYTE );
static void hb_compMemvarCheck( char * szVarName, HB_MACRO_DECL );
/* ************************************************************************* */
@@ -87,13 +87,12 @@ static void hb_compMemvarCheck( char * szVarName, HB_MACRO_DECL );
static int hb_macroParse( HB_MACRO_PTR pMacro, char * szString )
{
/* update the current status for logical shortcuts */
hb_comp_bShortCuts = s_macroFlags & HB_SM_SHORTCUTS;
hb_comp_bShortCuts = pMacro->supported & HB_SM_SHORTCUTS;
/* initialize the input buffer - it will be scanned by lex */
pMacro->string = szString;
pMacro->length = strlen( szString );
pMacro->pos = 0;
pMacro->supported = s_macroFlags;
pMacro->bShortCuts = hb_comp_bShortCuts;
HB_TRACE(HB_TR_DEBUG, ("hb_macroParse(%p, %s)", pMacro, szString));
@@ -443,7 +442,7 @@ char * hb_macroTextSubst( char * szString, ULONG *pulStringLen )
* EVAL( {|| &macro} )
*
*/
void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext )
void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext, BYTE flags )
{
/* TODO: remove these externals */
extern int hb_vm_aiExtraParams[HB_MAX_MACRO_ARGS], hb_vm_iExtraParamsIndex;
@@ -467,6 +466,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext )
struMacro.uiNameLen = HB_SYMBOL_NAME_LEN;
struMacro.status = HB_MACRO_CONT;
struMacro.iListElements = 0;
struMacro.supported = (flags & HB_SM_RT_MACRO) ? s_macroFlags : flags;
if( iContext != 0 )
{
@@ -491,7 +491,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext )
}
#ifdef HB_MACRO_STATEMENTS
if( s_macroFlags & HB_SM_PREPROC )
if( struMacro.supported & HB_SM_PREPROC )
{
char * ptr;
int slen;
@@ -524,7 +524,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext )
}
#ifdef HB_MACRO_STATEMENTS
if( s_macroFlags & HB_SM_PREPROC )
if( struMacro.supported & HB_SM_PREPROC )
{
hb_xfree( pText );
hb_xfree( pOut );
@@ -563,7 +563,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem, BYTE iContext )
* placed on the left side of the assignment
* POP operation
*/
void hb_macroSetValue( HB_ITEM_PTR pItem )
void hb_macroSetValue( HB_ITEM_PTR pItem, BYTE flags )
{
HB_TRACE(HB_TR_DEBUG, ("hb_macroSetValue(%p)", pItem));
@@ -576,6 +576,7 @@ void hb_macroSetValue( HB_ITEM_PTR pItem )
struMacro.Flags = HB_MACRO_GEN_POP;
struMacro.uiNameLen = HB_SYMBOL_NAME_LEN;
struMacro.status = HB_MACRO_CONT;
struMacro.supported = (flags & HB_SM_RT_MACRO) ? s_macroFlags : flags;
iStatus = hb_macroParse( &struMacro, szString );
hb_stackPop(); /* remove compiled string */
@@ -593,11 +594,11 @@ void hb_macroSetValue( HB_ITEM_PTR pItem )
* &alias->var := any
* alias->&var := any
*/
void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar )
void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, BYTE flags )
{
HB_TRACE(HB_TR_DEBUG, ("hb_macroPopAliasedValue(%p, %p)", pAlias, pVar));
hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_POP );
hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_POP, flags );
}
/* Compiles and run an aliased macro expression - generated pcode
@@ -605,11 +606,11 @@ void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar )
* any := &alias->var
* any := alias->&var
*/
void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar )
void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, BYTE flags )
{
HB_TRACE(HB_TR_DEBUG, ("hb_macroPushAliasedValue(%p, %p)", pAlias, pVar));
hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_PUSH );
hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_PUSH, flags );
}
/*
@@ -626,7 +627,7 @@ void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar )
* instead of
* &( "M + M" ) -> &( "M + M" )
*/
static void hb_macroUseAliased( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, int iFlag )
static void hb_macroUseAliased( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, int iFlag, BYTE bSupported )
{
if( HB_IS_STRING( pAlias ) && HB_IS_STRING( pVar ) )
{
@@ -645,6 +646,7 @@ static void hb_macroUseAliased( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, int iFlag
struMacro.Flags = iFlag;
struMacro.uiNameLen = HB_SYMBOL_NAME_LEN;
struMacro.status = HB_MACRO_CONT;
struMacro.supported = (bSupported & HB_SM_RT_MACRO) ? s_macroFlags : bSupported;
iStatus = hb_macroParse( &struMacro, szString );
hb_xfree( szString );
struMacro.string = NULL;
@@ -671,6 +673,7 @@ static void hb_macroUseAliased( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, int iFlag
struMacro.Flags = iFlag | HB_MACRO_GEN_ALIASED;
struMacro.uiNameLen = HB_SYMBOL_NAME_LEN;
struMacro.status = HB_MACRO_CONT;
struMacro.supported = (bSupported & HB_SM_RT_MACRO) ? s_macroFlags : bSupported;
iStatus = hb_macroParse( &struMacro, szString );
hb_stackPop(); /* remove compiled string */
@@ -717,6 +720,8 @@ HB_MACRO_PTR hb_macroCompile( char * szString )
pMacro->Flags = HB_MACRO_DEALLOCATE | HB_MACRO_GEN_PUSH;
pMacro->uiNameLen = HB_SYMBOL_NAME_LEN;
pMacro->status = HB_MACRO_CONT;
pMacro->supported = s_macroFlags;
iStatus = hb_macroParse( pMacro, szString );
if( ! ( iStatus == HB_MACRO_OK && ( pMacro->status & HB_MACRO_CONT ) ) )
{
@@ -814,6 +819,7 @@ char * hb_macroGetType( HB_ITEM_PTR pItem )
struMacro.Flags = HB_MACRO_GEN_PUSH | HB_MACRO_GEN_TYPE;
struMacro.uiNameLen = HB_SYMBOL_NAME_LEN;
struMacro.status = HB_MACRO_CONT;
struMacro.supported = s_macroFlags;
iStatus = hb_macroParse( &struMacro, szString );
if( iStatus == HB_MACRO_OK )
@@ -906,15 +912,6 @@ ULONG hb_macroSetMacro( BOOL bSet, ULONG flag )
return ulCurrentFlags;
}
ULONG hb_macroAutoSetMacro( ULONG flags )
{
ULONG ulCurrentFlags = s_macroFlags;
s_macroFlags = flags;
return ulCurrentFlags;
}
HB_FUNC( HB_SETMACRO )
{
int iPrmCnt = hb_pcount();