diff --git a/harbour/ChangeLog b/harbour/ChangeLog index e6290400f0..ed544e33d7 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,51 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ + PHB_FUNC - and added translation for PHB_SYMB to not force using + [P]HB_SYMB in 3-rd party code + + + * added protection against possible GPF after executing + hb_stackBaseProcOffset() when first item on the stack + + cases. Probably some more general solution like leaving + first dummy item on HVM stack for breaking stack scan + loops will be better. I'll think about it. + + * harbour/source/vm/itemapi.c + ! fixed clearing enumerators + +2006-09-20 14:15 UTC+0100 Ryszard Glab + * include/hbpcode.h + + added new pcode HB_P_VFRAME + + * include/hbapi.h + + added USHORT paramdeclcnt to asSymbol structure + + * include/hbstack.h + + added support for variable number of parameters in + + added hb_stackLocalVariable() to acces local variables + + * source/compiler/genc.c + * source/compiler/gencc.c + * source/compiler/harbour.c + + * source/compiler/harbour.y + * source/compiler/hbdead.c + * source/compiler/hbfix.c + * source/compiler/hblbl.c + * source/compiler/hbpcode.c + * source/compiler/hbstripl.c + * source/vm/hvm.c + + added support for variable number of parameters in + functions/procedures + + + tests/varparam.prg + HB_PVALUE( iParamNum ) - returns parameter + parameters + + * source/vm/arrayshb.c + arguments are passed ( HB_APARAMS() == HB_APARAMS(0) ) SYNTAX for variable number of parameters diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 2571d74798..5b414a9152 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -322,7 +322,8 @@ struct hb_struSymbol PHB_SYMB value; PHB_STACK_STATE stackstate; /* function stack state */ USHORT lineno; - USHORT paramcnt; + USHORT paramcnt; /* number of passed parameters in function call */ + USHORT paramdeclcnt; /* number of declared parameters in function definition */ }; /* items hold at the virtual machine stack */ diff --git a/harbour/include/hbpcode.h b/harbour/include/hbpcode.h index e4fa995814..1d009ad219 100644 --- a/harbour/include/hbpcode.h +++ b/harbour/include/hbpcode.h @@ -220,8 +220,8 @@ typedef enum HB_P_MACROSEND, /* 146 send operator with macrlist params */ HB_P_PUSHOVARREF, /* 147 pushes reference to object variable */ HB_P_ARRAYPUSHREF, /* 148 pushes reference to array element */ -/* NOTE: This have to be the last definition */ - HB_P_LAST_PCODE /* 149 this defines the number of defined pcodes */ + HB_P_VFRAME, /* 149 frame with variable number of parameters */ + HB_P_LAST_PCODE /* 150 this defines the number of defined pcodes */ } HB_PCODE; #endif /* HB_PCODE_H_ */ diff --git a/harbour/include/hbstack.h b/harbour/include/hbstack.h index 26cec89460..f9ace3ea40 100644 --- a/harbour/include/hbstack.h +++ b/harbour/include/hbstack.h @@ -85,6 +85,7 @@ extern HB_STACK hb_stack; extern HB_ITEM_PTR hb_stackItemFromTop( int nFromTop ); extern HB_ITEM_PTR hb_stackItemFromBase( int nFromBase ); +extern HB_ITEM_PTR hb_stacklocalVariable( int *piFromBase ); extern LONG hb_stackTopOffset( void ); extern LONG hb_stackBaseOffset( void ); extern LONG hb_stackTotalItems( void ); @@ -183,6 +184,10 @@ extern void hb_stackClearMevarsBase( void ); if( ++hb_stack.pPos == hb_stack.pEnd ) \ hb_stackIncrease(); \ } while ( 0 ) +#define hb_stackLocalVariable( p ) ((((*hb_stack.pBase)->item.asSymbol.paramcnt > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt) && \ + (*(p)) > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt ) ? \ + (* ( hb_stack.pBase + ( int ) ((*(p))+=((*hb_stack.pBase)->item.asSymbol.paramcnt - (*hb_stack.pBase)->item.asSymbol.paramdeclcnt)) + 1 ) ) : \ + (* ( hb_stack.pBase + ( int ) (*(p)) + 1 ) ) ) #endif diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 79170c3215..78dcc47590 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -2009,6 +2009,16 @@ static HB_GENC_FUNC( hb_p_withobjectend ) return 1; } +static HB_GENC_FUNC( hb_p_vframe ) +{ + fprintf( cargo->yyc, "\tHB_P_VFRAME, %i, %i,", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 2 ] ); + if( cargo->bVerbose ) fprintf( cargo->yyc, "\t/* locals, params */" ); + fprintf( cargo->yyc, "\n" ); + return 3; +} + /* NOTE: The order of functions have to match the order of opcodes * mnemonics */ @@ -2166,7 +2176,8 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_withobjectend, hb_p_macrosend, hb_p_pushovarref, - hb_p_arraypushref + hb_p_arraypushref, + hb_p_vframe }; static void hb_compGenCReadable( PFUNCTION pFunc, FILE * yyc ) diff --git a/harbour/source/compiler/gencc.c b/harbour/source/compiler/gencc.c index 0db0229e40..213e300e98 100644 --- a/harbour/source/compiler/gencc.c +++ b/harbour/source/compiler/gencc.c @@ -1589,6 +1589,15 @@ static HB_GENC_FUNC( hb_p_withobjectmessage ) return 3; } +static HB_GENC_FUNC( hb_p_vframe ) +{ + HB_GENC_LABEL(); + + fprintf( cargo->yyc, "\thb_xvmVFrame( %hu, %hu );\n", + pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); + return 3; +} + /* NOTE: The order of functions have to match the order of opcodes * mnemonics @@ -1747,7 +1756,8 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_withobjectend, hb_p_macrosend, hb_p_pushovarref, - hb_p_arraypushref + hb_p_arraypushref, + hb_p_vframe }; void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index b4a281ed34..50cbfba00a 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -3682,7 +3682,7 @@ static void hb_compOptimizeFrames( PFUNCTION pFunc ) } } } - else if( pFunc->pCode[ 0 ] == HB_P_FRAME && + else if( (pFunc->pCode[ 0 ] == HB_P_FRAME || pFunc->pCode[ 0 ] == HB_P_VFRAME) && pFunc->pCode[ 3 ] == HB_P_SFRAME ) { PVAR pLocal; @@ -3713,7 +3713,7 @@ static void hb_compOptimizeFrames( PFUNCTION pFunc ) pFunc->pCode[ 2 ] = ( BYTE )( pFunc->wParamCount ); bSkipFRAME = FALSE; } - else + else if( pFunc->pCode[ 0 ] == HB_P_FRAME ) bSkipFRAME = TRUE; if( pFunc->bFlags & FUN_USES_STATICS ) diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 89203f43dc..6ecaea60c8 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -1691,6 +1691,7 @@ Separator {SpaceTab} ".or." hb_comp_iState =OPERATOR; return OR; "!"|".not." hb_comp_iState =OPERATOR; return NOT; "::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); +"..." hb_comp_iState = OPERATOR; return EPSILON; [,\|\#\&\.\:\<\>\@] hb_comp_iState =OPERATOR; return yytext[ 0 ]; [\{] hb_comp_iState =LARRAY; return yytext[ 0 ]; [\}] hb_comp_iState =RARRAY; return yytext[ 0 ]; diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 6e7cd6d7bd..179d15f240 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -231,6 +231,7 @@ static void hb_compDebugStart( void ) { }; %token FOREACH DESCEND %token DOSWITCH WITHOBJECT %token NUM_DATE +%token EPSILON /*the lowest precedence*/ /*postincrement and postdecrement*/ @@ -345,8 +346,10 @@ CompTimeStr: LITERAL { hb_compAutoOpenAdd( $1 ); } | LITERAL '+' LITERAL { char szFileName[ _POSIX_PATH_MAX ]; sprintf( szFileName, "%s%s", $1, $3 ); hb_compAutoOpenAdd( szFileName ); } ; -Function : FunScope FUNCTION IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Params Crlf {} - | FunScope PROCEDURE IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Params Crlf {} +Function : FunScope FUNCTION IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Crlf {} + | FunScope PROCEDURE IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Crlf {} + | FunScope FUNCTION IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); hb_comp_iVarScope = VS_PARAMETER; } '(' Params ')' Crlf {} + | FunScope PROCEDURE IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); hb_comp_iVarScope = VS_PARAMETER;} '(' Params ')' Crlf {} ; FunScope : { $$ = HB_FS_PUBLIC; } @@ -355,9 +358,10 @@ FunScope : { $$ = HB_FS_PUBLIC; } | EXIT { $$ = HB_FS_EXIT; } ; -Params : { $$ = 0; } - | '(' ')' { $$ = 0; } - | '(' { hb_comp_iVarScope = VS_PARAMETER; } ParamList ')' { $$ = $3; } +Params : /*no parameters */ { $$ = 0; } + | EPSILON { hb_comp_functions.pLast->pCode[0] = HB_P_VFRAME; $$ = 0; } + | ParamList { $$ = $1; } + | ParamList ',' EPSILON { hb_comp_functions.pLast->pCode[0] = HB_P_VFRAME; $$ = $1; } ; AsType : /* not specified */ { hb_comp_cVarType = ' '; } diff --git a/harbour/source/compiler/hbdead.c b/harbour/source/compiler/hbdead.c index b99f82ac88..f644e17684 100644 --- a/harbour/source/compiler/hbdead.c +++ b/harbour/source/compiler/hbdead.c @@ -458,7 +458,8 @@ static PHB_CODETRACE_FUNC s_codeTraceFuncTable[ HB_P_LAST_PCODE ] = hb_p_default, /* HB_P_WITHOBJECTEND */ hb_p_default, /* HB_P_MACROSEND */ hb_p_default, /* HB_P_PUSHOVARREF */ - hb_p_default /* HB_P_ARRAYPUSHREF */ + hb_p_default, /* HB_P_ARRAYPUSHREF */ + hb_p_default /* HB_P_VFRAME */ }; void hb_compCodeTraceMarkDead( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hbfix.c b/harbour/source/compiler/hbfix.c index 9abe8c0b2f..52065c637c 100644 --- a/harbour/source/compiler/hbfix.c +++ b/harbour/source/compiler/hbfix.c @@ -638,7 +638,8 @@ static HB_FIX_FUNC_PTR s_fixlocals_table[] = NULL, /* HB_P_WITHOBJECTEND */ NULL, /* HB_P_MACROSEND */ NULL, /* HB_P_PUSHOVARREF */ - NULL /* HB_P_ARRAYPUSHREF */ + NULL, /* HB_P_ARRAYPUSHREF */ + NULL /* HB_P_VFRAME */ }; void hb_compFixFuncPCode( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hblbl.c b/harbour/source/compiler/hblbl.c index eec7026dc8..21e473a716 100644 --- a/harbour/source/compiler/hblbl.c +++ b/harbour/source/compiler/hblbl.c @@ -322,7 +322,8 @@ static PHB_LABEL_FUNC s_GenLabelFuncTable[ HB_P_LAST_PCODE ] = NULL, /* HB_P_WITHOBJECTEND */ NULL, /* HB_P_MACROSEND */ NULL, /* HB_P_PUSHOVARREF */ - NULL /* HB_P_ARRAYPUSHREF */ + NULL, /* HB_P_ARRAYPUSHREF */ + NULL /* HB_P_VFRAME */ }; void hb_compGenLabelTable( PFUNCTION pFunc, PHB_LABEL_INFO label_info ) diff --git a/harbour/source/compiler/hbpcode.c b/harbour/source/compiler/hbpcode.c index 9f11466e52..36f38c93f5 100644 --- a/harbour/source/compiler/hbpcode.c +++ b/harbour/source/compiler/hbpcode.c @@ -255,7 +255,8 @@ const BYTE hb_comp_pcode_len[] = { 1, /* HB_P_WITHOBJECTEND, */ 3, /* HB_P_MACROSEND, */ 1, /* HB_P_PUSHOVARREF, */ - 1 /* HB_P_ARRAYPUSHREF */ + 1, /* HB_P_ARRAYPUSHREF */ + 3 /* HB_P_VFRAME */ }; /* @@ -415,7 +416,8 @@ static HB_PCODE_FUNC_PTR s_psize_table[] = NULL, /* HB_P_WITHOBJECTEND */ NULL, /* HB_P_MACROSEND */ NULL, /* HB_P_PUSHOVARREF */ - NULL /* HB_P_ARRAYPUSHREF */ + NULL, /* HB_P_ARRAYPUSHREF */ + NULL /* HB_P_VFRAME */ }; LONG hb_compPCodeSize( PFUNCTION pFunc, ULONG ulOffset ) diff --git a/harbour/source/compiler/hbstripl.c b/harbour/source/compiler/hbstripl.c index c8101a0bee..b75e7977be 100644 --- a/harbour/source/compiler/hbstripl.c +++ b/harbour/source/compiler/hbstripl.c @@ -227,7 +227,8 @@ static PHB_STRIP_FUNC s_stripLines_table[] = NULL, /* HB_P_WITHOBJECTEND */ NULL, /* HB_P_MACROSEND */ NULL, /* HB_P_PUSHOVARREF */ - NULL /* HB_P_ARRAYPUSHREF */ + NULL, /* HB_P_ARRAYPUSHREF */ + NULL /* HB_P_VFRAME */ }; void hb_compStripFuncLines( PFUNCTION pFunc ) diff --git a/harbour/source/vm/arrayshb.c b/harbour/source/vm/arrayshb.c index c7ca331e31..70e1aab50f 100644 --- a/harbour/source/vm/arrayshb.c +++ b/harbour/source/vm/arrayshb.c @@ -330,5 +330,8 @@ HB_FUNC( ACLONE ) HB_FUNC( HB_APARAMS ) { - hb_itemRelease( hb_itemReturn( hb_arrayFromParams( hb_parni( 1 ) + 1 ) ) ); + if( hb_pcount() == 0 ) + hb_itemRelease( hb_itemReturn( hb_arrayFromParams( 1 ) ) ); + else + hb_itemRelease( hb_itemReturn( hb_arrayFromParams( hb_parni( 1 ) + 1 ) ) ); } diff --git a/harbour/source/vm/estack.c b/harbour/source/vm/estack.c index 847a872adc..ca56679482 100644 --- a/harbour/source/vm/estack.c +++ b/harbour/source/vm/estack.c @@ -249,6 +249,10 @@ HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams ) pItem->item.asSymbol.stackstate = pStack; pItem->item.asSymbol.lineno = 0; pItem->item.asSymbol.paramcnt = uiParams; + /* set default value of 'paramdeclcnt' - it will be updated + * in hb_vmVFrame only + */ + pItem->item.asSymbol.paramdeclcnt = uiParams; hb_stack.pBase = pBase; return pItem; @@ -295,6 +299,28 @@ HB_ITEM_PTR hb_stackItemFromBase( int nFromBase ) return * ( hb_stack.pBase + nFromBase + 1 ); } +#undef hb_stackLocalVariable +HB_ITEM_PTR hb_stackLocalVariable( int *piFromBase ) +{ + HB_ITEM_PTR pBase = *hb_stack.pBase; + + if( *piFromBase <= 0 ) + hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); + + if( pBase->item.asSymbol.paramcnt > pBase->item.asSymbol.paramdeclcnt ) + { + /* function with variable number of parameters: + * FUNCTION foo( a,b,c,...) + * LOCAL x,y,z + * number of passed parameters is bigger then number of declared + * parameters - skip additional parameters only for local variables + */ + if( *piFromBase > pBase->item.asSymbol.paramdeclcnt ) + *piFromBase += pBase->item.asSymbol.paramcnt - pBase->item.asSymbol.paramdeclcnt; + } + return * ( hb_stack.pBase + *piFromBase + 1 ); +} + #undef hb_stackBaseItem HB_ITEM_PTR hb_stackBaseItem( void ) { diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 34066458c0..cdc43223c3 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -158,6 +158,7 @@ static void hb_vmLocalName( USHORT uiLocal, char * szLocalName ); /* locals a static void hb_vmStaticName( BYTE bIsGlobal, USHORT uiStatic, char * szStaticName ); /* statics vars information for the debugger */ static void hb_vmModuleName( char * szModuleName ); /* PRG and function name information for the debugger */ static void hb_vmFrame( BYTE bLocals, BYTE bParams ); /* increases the stack pointer for the amount of locals and params suplied */ +static void hb_vmVFrame( BYTE bLocals, BYTE bParams ); /* increases the stack pointer for the amount of locals and variable number of params suplied */ static void hb_vmSFrame( PHB_SYMB pSym ); /* sets the statics frame for a function */ static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ); /* increases the global statics array to hold a PRG statics */ static void hb_vmEndBlock( void ); /* copies the last codeblock pushed value into the return value */ @@ -1783,13 +1784,16 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) } case HB_P_LOCALNEARADDINT: + { + SHORT iLocal = pCode[ w + 1 ]; HB_TRACE( HB_TR_DEBUG, ("HB_P_LOCALNEARADDINT") ); - hb_vmAddInt( hb_stackItemFromBase( pCode[ w + 1 ] ), + hb_vmAddInt( hb_stackLocalVariable( &iLocal ), HB_PCODE_MKSHORT( &( pCode[ w + 2 ] ) ) ); w += 4; break; - + } + /* WITH OBJECT */ case HB_P_WITHOBJECTMESSAGE: @@ -1809,6 +1813,11 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) w += 1; break; + case HB_P_VFRAME: + hb_vmVFrame( pCode[ w + 1 ], pCode[ w + 2 ] ); + w += 3; + break; + /* misc */ case HB_P_NOOP: @@ -4432,21 +4441,45 @@ static void hb_vmModuleName( char * szModuleName ) /* PRG and function name info static void hb_vmFrame( BYTE bLocals, BYTE bParams ) { int iTotal, iExtra; + int ipcount = hb_pcount(); HB_TRACE(HB_TR_DEBUG, ("hb_vmFrame(%d, %d)", (int) bLocals, (int) bParams)); - iExtra = hb_pcount() - bParams; + iExtra = ipcount - bParams; - while( iExtra > 0 ) + if( iExtra > 0 ) { - hb_itemClear( hb_stackItemFromTop( -iExtra ) ); - iExtra--; + hb_stackBaseItem()->item.asSymbol.paramcnt = bParams; + while( iExtra > 0 ) + { + hb_itemClear( hb_stackItemFromTop( -iExtra ) ); + iExtra--; + } } iTotal = bLocals + bParams; if( iTotal ) { - iTotal -= hb_pcount(); + iTotal -= ipcount; + while( --iTotal >= 0 ) + hb_vmPushNil(); + } +} + +static void hb_vmVFrame( BYTE bLocals, BYTE bParams ) +{ + int iTotal; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmVFrame(%d, %d)", (int) bLocals, (int) bParams)); + + hb_stackBaseItem()->item.asSymbol.paramdeclcnt = bParams; + + if( hb_pcount() < bParams ) + iTotal = bLocals + bParams - hb_pcount(); + else + iTotal = bLocals; + if( iTotal ) + { while( --iTotal >= 0 ) hb_vmPushNil(); } @@ -4970,7 +5003,7 @@ static void hb_vmPushLocal( SHORT iLocal ) if( iLocal >= 0 ) { /* local variable or local parameter */ - pLocal = hb_stackItemFromBase( iLocal ); + pLocal = hb_stackLocalVariable( &iLocal ); } else { @@ -4997,6 +5030,7 @@ static void hb_vmPushLocalByRef( SHORT iLocal ) pTop->type = HB_IT_BYREF; /* we store its stack offset instead of a pointer to support a dynamic stack */ + hb_stackLocalVariable( &iLocal ); pTop->item.asRefer.value = iLocal; pTop->item.asRefer.offset = hb_stackBaseOffset(); if( iLocal >= 0 ) @@ -5332,7 +5366,7 @@ static void hb_vmPopLocal( SHORT iLocal ) if( iLocal >= 0 ) { /* local variable or local parameter */ - pLocal = hb_stackItemFromBase( iLocal ); + pLocal = hb_stackLocalVariable( &iLocal ); if( HB_IS_BYREF( pLocal ) ) pLocal = hb_itemUnRef( pLocal ); } @@ -6318,6 +6352,13 @@ HB_EXPORT void hb_xvmFrame( int iLocals, int iParams ) hb_vmFrame( ( BYTE ) iLocals, ( BYTE ) iParams ); } +HB_EXPORT void hb_xvmVFrame( int iLocals, int iParams ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_xvmVFrame(%d, %d)", iLocals, iParams)); + + hb_vmVFrame( ( BYTE ) iLocals, ( BYTE ) iParams ); +} + HB_EXPORT void hb_xvmSFrame( PHB_SYMB pSymbol ) { HB_TRACE(HB_TR_DEBUG, ("hb_xvmSFrame(%p)", pSymbol)); @@ -6615,7 +6656,7 @@ HB_EXPORT void hb_xvmLocalSetInt( int iLocal, LONG lValue ) if( iLocal >= 0 ) { /* local variable or local parameter */ - pLocal = hb_stackItemFromBase( iLocal ); + pLocal = hb_stackLocalVariable( &iLocal ); if( HB_IS_BYREF( pLocal ) ) pLocal = hb_itemUnRef( pLocal ); } @@ -6644,7 +6685,7 @@ HB_EXPORT BOOL hb_xvmLocalAddInt( int iLocal, LONG lAdd ) { HB_TRACE(HB_TR_DEBUG, ("hb_xvmLocalAddInt(%d,%ld)", iLocal, lAdd)); - hb_vmAddInt( hb_stackItemFromBase( iLocal ), lAdd ); + hb_vmAddInt( hb_stackLocalVariable( &iLocal ), lAdd ); HB_XVM_RETURN } @@ -6655,7 +6696,7 @@ HB_EXPORT BOOL hb_xvmLocalAdd( int iLocal ) HB_TRACE(HB_TR_DEBUG, ("hb_xvmLocalAdd(%d)", iLocal)); - pLocal = hb_stackItemFromBase( iLocal ); + pLocal = hb_stackLocalVariable( &iLocal ); if( HB_IS_BYREF( pLocal ) ) pLocal = hb_itemUnRef( pLocal ); hb_vmPlus( pLocal, hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), 2 ); diff --git a/harbour/tests/varparam.prg b/harbour/tests/varparam.prg new file mode 100644 index 0000000000..01f9b62e69 --- /dev/null +++ b/harbour/tests/varparam.prg @@ -0,0 +1,325 @@ +// +// $Id$ +// +/* TEST FOR USING VARIABLE NUMBER OF PARAMETERS */ + +MEMVAR iLoop +PROCEDURE MAIN(p1, p2) +LOCAL l1:=11,l2:=22,l3:=33,l4:=44,l5:=55,l6:=66 +PRIVATE iLoop + + ? 'passed 0: '; TEST_0_0( ) + ? 'passed 1: '; TEST_0_0( 1 ) + ? 'passed 2: '; TEST_0_0( 1, 2 ) + ? 'passed 3: '; TEST_0_0( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_0_0v( ) + ? 'passed 1: '; TEST_0_0v( 1 ) + ? 'passed 2: '; TEST_0_0v( 1, 2 ) + ? 'passed 3: '; TEST_0_0v( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_0( ) + ? 'passed 1: '; TEST_1_0( 1 ) + ? 'passed 2: '; TEST_1_0( 1, 2 ) + ? 'passed 3: '; TEST_1_0( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_0v( ) + ? 'passed 1: '; TEST_1_0v( 1 ) + ? 'passed 2: '; TEST_1_0v( 1, 2 ) + ? 'passed 3: '; TEST_1_0v( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_1( ) + ? 'passed 1: '; TEST_1_1( 1 ) + ? 'passed 2: '; TEST_1_1( 1, 2 ) + ? 'passed 3: '; TEST_1_1( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_1v( ) + ? 'passed 1: '; TEST_1_1v( 1 ) + ? 'passed 2: '; TEST_1_1v( 1, 2 ) + ? 'passed 3: '; TEST_1_1v( 1, 2, 3 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_3( ) + ? 'passed 1: '; TEST_1_3( 1 ) + ? 'passed 2: '; TEST_1_3( 1, 2 ) + ? 'passed 3: '; TEST_1_3( 1, 2, 3 ) + ? 'passed 4: '; TEST_1_3( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_1_3( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_1_3( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_1_3v( ) + ? 'passed 1: '; TEST_1_3v( 1 ) + ? 'passed 2: '; TEST_1_3v( 1, 2 ) + ? 'passed 3: '; TEST_1_3v( 1, 2, 3 ) + ? 'passed 4: '; TEST_1_3v( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_1_3v( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_1_3v( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_3_0( ) + ? 'passed 1: '; TEST_3_0( 1 ) + ? 'passed 2: '; TEST_3_0( 1, 2 ) + ? 'passed 3: '; TEST_3_0( 1, 2, 3 ) + ? 'passed 4: '; TEST_3_0( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_3_0( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_3_0( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_3_0v( ) + ? 'passed 1: '; TEST_3_0v( 1 ) + ? 'passed 2: '; TEST_3_0v( 1, 2 ) + ? 'passed 3: '; TEST_3_0v( 1, 2, 3 ) + ? 'passed 4: '; TEST_3_0v( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_3_0v( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_3_0v( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_3_3( ) + ? 'passed 1: '; TEST_3_3( 1 ) + ? 'passed 2: '; TEST_3_3( 1, 2 ) + ? 'passed 3: '; TEST_3_3( 1, 2, 3 ) + ? 'passed 4: '; TEST_3_3( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_3_3( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_3_3( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'passed 0: '; TEST_3_3v( ) + ? 'passed 1: '; TEST_3_3v( 1 ) + ? 'passed 2: '; TEST_3_3v( 1, 2 ) + ? 'passed 3: '; TEST_3_3v( 1, 2, 3 ) + ? 'passed 4: '; TEST_3_3v( 1, 2, 3, 4 ) + ? 'passed 5: '; TEST_3_3v( 1, 2, 3, 4, 5 ) + ? 'passed 6: '; TEST_3_3v( 1, 2, 3, 4, 5, 6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_0_0( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_0_0v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_1_0( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_1_0v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_1_1( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_1_1v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_1_3( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_1_3v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_3_0( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_3_0v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + ? '---------------------------------------' + ? 'Passed 6 by ref: '; TEST_3_3( @l1, @l2, @l3, @l4, @l5, @l6 ) + ? 'Passed 6 by ref: '; TEST_3_3v( @l1, @l2, @l3, @l4, @l5, @l6 ) + + RETURN + +PROCEDURE TEST_0_0v( ... ) + + ?? PROCNAME(0), ' received: ', PCOUNT() + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_0_0( ) + + ?? PROCNAME(0), ' received: ', PCOUNT() + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_1_0v( ... ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_1_0( ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_1_3v( a,b,c, ... ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + ? 'a=',a + ? 'b=',b + ? 'c=',c + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + FOR EACH i IN HB_APARAMS() + ? i:__enumindex, "-", i + NEXT + + inkey(0) + +RETURN + + +PROCEDURE TEST_1_3( a,b,c ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + ? 'a=',a + ? 'b=',b + ? 'c=',c + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + FOR EACH i IN HB_APARAMS() + ? i:__enumindex, "-", i + NEXT + + inkey(0) + +RETURN + + +PROCEDURE TEST_1_1( a ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + ? 'a=',a + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_1_1v( a, ... ) +LOCAL i:='i' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'i=',i + ? 'a=',a + FOR i:=1 TO PCOUNT() + ? i, "=", HB_PVALUE( i ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_3_3v( a,b,c, ... ) +LOCAL x:='x', y:='y', z:='z' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'x=',x + ? 'y=',y + ? 'z=',z + ? 'a=',a + ? 'b=',b + ? 'c=',c + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + test_ref( @a, @b, @c, @x, @y, @z ) + + inkey(0) + +RETURN + +PROCEDURE TEST_3_3( a,b,c ) +LOCAL x:='x', y:='y', z:='z' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'x=',x + ? 'y=',y + ? 'z=',z + ? 'a=',a + ? 'b=',b + ? 'c=',c + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + test_ref( @a, @b, @c, @x, @y, @z ) + + inkey(0) + +RETURN + +PROCEDURE TEST_3_0( ) +LOCAL x:='x', y:='y', z:='z' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'x=',x + ? 'y=',y + ? 'z=',z + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_3_0v( ... ) +LOCAL x:='x', y:='y', z:='z' + + ?? PROCNAME(0), ' received: ', PCOUNT() + ? 'x=',x + ? 'y=',y + ? 'z=',z + FOR m->iLoop:=1 TO PCOUNT() + ? m->iLoop, "=", HB_PVALUE( m->iLoop ) + NEXT + + inkey(0) + +RETURN + +PROCEDURE TEST_REF( a, ... ) +LOCAL b + + ? '@@@' + ? PROCNAME(0), ' received: ', PCOUNT() + ? 'a= ', a + ? 'b= ', b + FOR EACH b IN HB_APARAMS(0) + ? b:__enumindex, "-", b + NEXT + +RETURN \ No newline at end of file