2005-11-14 11:00 UTC+0100 Ryszard Glab <rglab@imid.med.pl>

* include/hbcomp.h
   * include/hberrors.h
   * include/hbexpra.c
   * include/hbexprb.c
   * include/hbexprop.h
   * include/hbhash.h
   * include/hbmacro.h
   * include/hbpcode.h
   * source/common/Makefile
   * source/common/expropt1.c
   * source/common/expropt2.c
   * source/common/hbhash.c
   * source/compiler/expropta.c
   * source/compiler/exproptb.c
   * source/compiler/genc.c
   * source/compiler/harbour.c
   * source/compiler/harbour.l
   * source/compiler/harbour.y
   * source/compiler/hbfix.c
   * source/compiler/hbgenerr.c
   * source/compiler/hbident.c
   * source/compiler/hbpcode.c
   * source/macro/macro.l
   * source/macro/macro.y
   * source/macro/macroa.c
   * source/macro/macrob.c
   * source/rtl/dates.c
   * source/vm/hvm.c
   * source/vm/macro.c
   + source/common/hbdate.c
   + tests/ddate.prg
   + tests/switch.prg
      +added support for DATE type constants in the following format:
         0dYYYYMMDD
      for example (see tests/ddate.prg for more):
      IF( dDate > 0d20051112 )

      +added support for SWITCH command (see tests/switch.prg)
         SWITCH <expr>
         CASE <integer_expression>
            ...
            [EXIT]
         CASE <string_expression>
            ...
            [EXIT]
         [OTHERWISE]
            ...
         END

   Notice:
      - Integer and string expressions can be mixed in a single
        SWITCH command with no runtime errors;
      - CASE expression have to be resolved at compile time and
        the result has to be either an integer or string constant
      - if there is no EXIT statement then next CASE is executed
        (or OTHERWISE for the last CASE)
      For example:
      CASE 1+32+2*4
      CASE CHR(64)
      CASE ASC('A')
      CASE "A"+CHR(13)

   Notice:
      The above changes apply only to FLEX version!
This commit is contained in:
Ryszard Glab
2005-11-14 09:47:46 +00:00
parent ae77dfc376
commit dde0793b53
33 changed files with 1098 additions and 198 deletions

View File

@@ -7,6 +7,74 @@
For example:
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
2005-11-14 11:00 UTC+0100 Ryszard Glab <rglab@imid.med.pl>
* include/hbcomp.h
* include/hberrors.h
* include/hbexpra.c
* include/hbexprb.c
* include/hbexprop.h
* include/hbhash.h
* include/hbmacro.h
* include/hbpcode.h
* source/common/Makefile
* source/common/expropt1.c
* source/common/expropt2.c
* source/common/hbhash.c
* source/compiler/expropta.c
* source/compiler/exproptb.c
* source/compiler/genc.c
* source/compiler/harbour.c
* source/compiler/harbour.l
* source/compiler/harbour.y
* source/compiler/hbfix.c
* source/compiler/hbgenerr.c
* source/compiler/hbident.c
* source/compiler/hbpcode.c
* source/macro/macro.l
* source/macro/macro.y
* source/macro/macroa.c
* source/macro/macrob.c
* source/rtl/dates.c
* source/vm/hvm.c
* source/vm/macro.c
+ source/common/hbdate.c
+ tests/ddate.prg
+ tests/switch.prg
+added support for DATE type constants in the following format:
0dYYYYMMDD
for example (see tests/ddate.prg for more):
IF( dDate > 0d20051112 )
+added support for SWITCH command (see tests/switch.prg)
SWITCH <expr>
CASE <integer_expression>
...
[EXIT]
CASE <string_expression>
...
[EXIT]
[OTHERWISE]
...
END
Notice:
- Integer and string expressions can be mixed in a single
SWITCH command with no runtime errors;
- CASE expression have to be resolved at compile time and
the result has to be either an integer or string constant
- if there is no EXIT statement then next CASE is executed
(or OTHERWISE for the last CASE)
For example:
CASE 1+32+2*4
CASE CHR(64)
CASE ASC('A')
CASE "A"+CHR(13)
Notice:
The above changes apply only to FLEX version!
2005-11-13 21:21 UTC+0100 Jacek Kubica (kubica/at/wssk.wroc.pl)
* harbour/contrib/ole/bldtest.bat
* harbour/contrib/ole/hbtest.prg

View File

@@ -380,6 +380,7 @@ extern void hb_compGenPushVarRef( char * szVarName ); /* generates the pcode
extern void hb_compGenPushInteger( int iNumber ); /* Pushes a integer number on the virtual machine stack */
extern void hb_compGenPushLogical( int iTrueFalse ); /* pushes a logical value on the virtual machine stack */
extern void hb_compGenPushLong( HB_LONG lNumber ); /* Pushes a long number on the virtual machine stack */
extern void hb_compGenPushDate( HB_LONG lNumber ); /* Pushes a date constant on the virtual machine stack */
extern void hb_compGenPushNil( void ); /* Pushes nil on the virtual machine stack */
extern void hb_compGenPushString( char * szText, ULONG ulLen ); /* Pushes a string on the virtual machine stack */
extern void hb_compGenPushSymbol( char * szSymbolName, BOOL bFunction, BOOL bAlias ); /* Pushes a symbol on to the Virtual machine stack */
@@ -534,6 +535,9 @@ extern USHORT hb_comp_wForCounter;
extern USHORT hb_comp_wIfCounter;
extern USHORT hb_comp_wWhileCounter;
extern USHORT hb_comp_wCaseCounter;
extern USHORT hb_comp_wSwitchCounter;
extern BOOL hb_comp_long_optimize;
extern BOOL hb_comp_bTextSubst;
extern char * hb_comp_szDeclaredFun;

View File

@@ -114,6 +114,9 @@ HB_EXTERN_BEGIN
#define HB_COMP_ERR_OPTIMIZEDLOCAL_OUT_OF_RANGE 52
#define HB_COMP_ERR_FORVAR_TOOMANY 53
#define HB_COMP_ERR_FORVAR_DIFF 54
#define HB_COMP_ERR_NOT_LITERAL_CASE 55
#define HB_COMP_ERR_INVALID_STR 56
#define HB_COMP_ERR_INVALID_DATE 57
#define HB_COMP_WARN_AMBIGUOUS_VAR 1
#define HB_COMP_WARN_MEMVAR_ASSUMED 2

View File

@@ -77,6 +77,7 @@ static BYTE s_PrecedTable[] = {
HB_ET_NIL, /* HB_ET_NONE = 0, */
HB_ET_NIL, /* HB_ET_NIL, */
HB_ET_NIL, /* HB_ET_NUMERIC, */
HB_ET_NIL, /* HB_ET_DATE, */
HB_ET_NIL, /* HB_ET_STRING, */
HB_ET_NIL, /* HB_ET_CODEBLOCK, */
HB_ET_NIL, /* HB_ET_LOGICAL, */

View File

@@ -123,6 +123,7 @@ HB_EXPR_PTR hb_compExprReduceIIF( HB_EXPR_PTR, HB_MACRO_DECL );
static HB_EXPR_FUNC( hb_compExprUseDummy );
static HB_EXPR_FUNC( hb_compExprUseNil );
static HB_EXPR_FUNC( hb_compExprUseNumeric );
static HB_EXPR_FUNC( hb_compExprUseDate );
static HB_EXPR_FUNC( hb_compExprUseString );
static HB_EXPR_FUNC( hb_compExprUseCodeblock );
static HB_EXPR_FUNC( hb_compExprUseLogical );
@@ -189,6 +190,7 @@ HB_EXPR_FUNC_PTR hb_comp_ExprTable[] = {
hb_compExprUseDummy,
hb_compExprUseNil,
hb_compExprUseNumeric,
hb_compExprUseDate,
hb_compExprUseString,
hb_compExprUseCodeblock,
hb_compExprUseLogical,
@@ -333,6 +335,38 @@ static HB_EXPR_FUNC( hb_compExprUseNumeric )
return pSelf;
}
/* actions for HB_ET_DATE expression
*/
static HB_EXPR_FUNC( hb_compExprUseDate )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
hb_compErrorType( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( pSelf ); /* Date cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE1( hb_compGenPushDate, pSelf->value.asNum.lVal );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_STRING expression
*/
static HB_EXPR_FUNC( hb_compExprUseString )
@@ -358,7 +392,10 @@ static HB_EXPR_FUNC( hb_compExprUseString )
szDupl = hb_strupr( hb_strdup( pSelf->value.asString.string ) );
HB_EXPR_PCODE2( hb_compGenPushString, pSelf->value.asString.string, pSelf->ulLength + 1 );
#if ! defined( HB_MACRO_SUPPORT )
if( hb_comp_bTextSubst )
{
#endif
bValidMacro = hb_compExprIsValidMacro( szDupl, &bUseTextSubst, HB_MACRO_PARAM );
if( bUseTextSubst )
{
@@ -383,6 +420,9 @@ static HB_EXPR_FUNC( hb_compExprUseString )
}
}
}
#if ! defined( HB_MACRO_SUPPORT )
}
#endif
hb_xfree( szDupl );
}
break;

View File

@@ -70,6 +70,7 @@ HB_EXTERN_BEGIN
#define HB_EV_SYMBOL 128
#define HB_EV_VARREF 256
#define HB_EV_FUNREF 512
#define HB_EV_DATE 1024
/* messages sent to expressions
*/
@@ -114,6 +115,7 @@ typedef enum
HB_ET_NONE = 0,
HB_ET_NIL,
HB_ET_NUMERIC,
HB_ET_DATE,
HB_ET_STRING,
HB_ET_CODEBLOCK,
HB_ET_LOGICAL,
@@ -308,6 +310,7 @@ HB_EXPR_PTR hb_compExprNewEmpty( void );
HB_EXPR_PTR hb_compExprNewNil( void );
HB_EXPR_PTR hb_compExprNewDouble( double, BYTE, BYTE );
HB_EXPR_PTR hb_compExprNewLong( HB_LONG );
HB_EXPR_PTR hb_compExprNewDate( HB_LONG );
HB_EXPR_PTR hb_compExprNewString( char * );
HB_EXPR_PTR hb_compExprNewLogical( int );
HB_EXPR_PTR hb_compExprNewSelf( void );
@@ -371,8 +374,12 @@ void hb_compExprClear( HB_EXPR_PTR );
char * hb_compExprDescription( HB_EXPR_PTR );
int hb_compExprType( HB_EXPR_PTR );
int hb_compExprIsInteger( HB_EXPR_PTR );
int hb_compExprIsLong( HB_EXPR_PTR );
int hb_compExprAsInteger( HB_EXPR_PTR );
int hb_compExprIsString( HB_EXPR_PTR );
int hb_compExprAsStringLen( HB_EXPR_PTR );
char *hb_compExprAsString( HB_EXPR_PTR );
char *hb_compExprAsSymbol( HB_EXPR_PTR );
void hb_compExprFree( HB_EXPR_PTR, HB_MACRO_DECL );
void hb_compExprErrorType( HB_EXPR_PTR, HB_MACRO_DECL );

View File

@@ -57,13 +57,16 @@
HB_EXTERN_BEGIN
#define HB_HASH_FUNC( hbfunc ) ULONG hbfunc( void *Value, void *Cargo )
struct HB_HASH_TABLE_;
#define HB_HASH_FUNC( hbfunc ) ULONG hbfunc( struct HB_HASH_TABLE_ *HashPtr, void *Value, void *Cargo )
typedef HB_HASH_FUNC( HB_HASH_FUNC_ );
typedef HB_HASH_FUNC_ *HB_HASH_FUNC_PTR;
typedef struct HB_HASH_ITEM_
{
void *cargo; /* value stored in the hash table */
void *ValPtr; /* value stored in the hash table */
void *KeyPtr;
ULONG key;
struct HB_HASH_ITEM_ *next;
} HB_HASH_ITEM, *HB_HASH_ITEM_PTR;
@@ -79,13 +82,14 @@ typedef struct HB_HASH_TABLE_
HB_HASH_FUNC_PTR pCompFunc; /* ptr to func that compares two itmes */
} HB_HASH_TABLE, *HB_HASH_TABLE_PTR;
extern HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize,
HB_HASH_FUNC_PTR pHashFunc,
HB_HASH_FUNC_PTR pDelete,
HB_HASH_FUNC_PTR pComp );
extern void hb_hashTableKill( HB_HASH_TABLE_PTR pTable ); /* release all items and the hash table */
extern BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue ); /* add a new item into the table */
extern void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pValue ); /* return the pointer to item's value or NULL if not found */
extern BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pKey, void *pValue ); /* add a new item into the table */
extern void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pKey ); /* return the pointer to item's value or NULL if not found */
extern HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize ); /* resize the hash table */
HB_EXTERN_END

View File

@@ -133,6 +133,7 @@ extern ULONG hb_compGenJumpTrue( LONG lOffset, HB_BISON_PTR pMacro );
extern void hb_compMemvarGenPCode( BYTE bPCode, char * szVarName, HB_BISON_PTR pMacro );
extern void hb_compGenPushSymbol( char * szSymbolName, BOOL bFunction, BOOL bAlias, HB_BISON_PTR pMacro );
extern void hb_compGenPushLong( HB_LONG lNumber, HB_BISON_PTR pMacro );
extern void hb_compGenPushDate( HB_LONG lNumber, HB_BISON_PTR pMacro );
extern void hb_compGenMessage( char * szMsgName, HB_BISON_PTR pMacro );
extern void hb_compGenMessageData( char * szMsg, HB_BISON_PTR pMacro );
extern void hb_compGenPopVar( char * szVarName, HB_BISON_PTR pMacro );

View File

@@ -196,8 +196,10 @@ typedef enum
HB_P_ENUMNEXT, /* 129 Next item of FOR EACH loop */
HB_P_ENUMPREV, /* 130 Previous item of FOR EACH loop */
HB_P_ENUMEND, /* 131 End of FOR EACH loop */
HB_P_SWITCH, /* 132 SWITCH using long values */
HB_P_PUSHDATE, /* 133 SWITCH using long values */
/* NOTE: This have to be the last definition */
HB_P_LAST_PCODE /* 132 this defines the number of defined pcodes */
HB_P_LAST_PCODE /* 134 this defines the number of defined pcodes */
} HB_PCODE;
#endif /* HB_PCODE_H_ */

View File

@@ -10,6 +10,7 @@ C_SOURCES=\
hbgete.c \
hbhash.c \
hbstr.c \
hbdate.c \
hbtrace.c \
hbver.c \
hbverdsp.c \

View File

@@ -76,6 +76,7 @@ static char * s_OperTable[] = {
"",
"NIL",
"Numeric",
"Date",
"String",
"Codeblock",
"Logical",
@@ -192,12 +193,50 @@ HB_EXPR_PTR hb_compExprNewLong( HB_LONG lValue )
return pExpr;
}
HB_EXPR_PTR hb_compExprNewDate( HB_LONG lValue )
{
HB_EXPR_PTR pExpr;
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewDate(%" PFHL "d)", lValue));
pExpr = hb_compExprNew( HB_ET_DATE );
pExpr->value.asNum.lVal = lValue;
pExpr->ValType = HB_EV_DATE;
return pExpr;
}
int hb_compExprIsInteger( HB_EXPR_PTR pExpr )
{
return ( pExpr->ExprType == HB_ET_NUMERIC && pExpr->value.asNum.NumType == HB_ET_LONG &&
HB_LIM_INT16( pExpr->value.asNum.lVal ) );
}
int hb_compExprIsLong( HB_EXPR_PTR pExpr )
{
return ( pExpr->ExprType == HB_ET_NUMERIC && pExpr->value.asNum.NumType == HB_ET_LONG );
}
int hb_compExprIsString( HB_EXPR_PTR pExpr )
{
return ( pExpr->ExprType == HB_ET_STRING );
}
char * hb_compExprAsString( HB_EXPR_PTR pExpr )
{
if( pExpr->ExprType == HB_ET_STRING )
return pExpr->value.asString.string;
return NULL;
}
int hb_compExprAsStringLen( HB_EXPR_PTR pExpr )
{
if( pExpr->ExprType == HB_ET_STRING )
return pExpr->ulLength;
return 0;
}
int hb_compExprAsInteger( HB_EXPR_PTR pExpr )
{
if( pExpr->ExprType == HB_ET_NUMERIC && pExpr->value.asNum.NumType == HB_ET_LONG )
@@ -206,7 +245,15 @@ int hb_compExprAsInteger( HB_EXPR_PTR pExpr )
return 0;
}
char *hb_compExprAsString( HB_EXPR_PTR pExpr )
long hb_compExprAsLong( HB_EXPR_PTR pExpr )
{
if( pExpr->ExprType == HB_ET_NUMERIC && pExpr->value.asNum.NumType == HB_ET_LONG )
return pExpr->value.asNum.lVal;
else
return 0;
}
char *hb_compExprAsSymbol( HB_EXPR_PTR pExpr )
{
switch( pExpr->ExprType )
{

View File

@@ -335,6 +335,31 @@ HB_EXPR_PTR hb_compExprReduceMinus( HB_EXPR_PTR pSelf, HB_MACRO_DECL )
hb_compExprFree( pLeft, HB_MACRO_PARAM );
hb_compExprFree( pRight, HB_MACRO_PARAM );
}
else if( pLeft->ExprType == HB_ET_DATE && pRight->ExprType == HB_ET_DATE )
{
pSelf->value.asNum.lVal = pLeft->value.asNum.lVal - pRight->value.asNum.lVal;
pSelf->value.asNum.bDec = 0;
pSelf->value.asNum.NumType = HB_ET_LONG;
pSelf->ExprType = HB_ET_NUMERIC;
pSelf->ValType = HB_EV_NUMERIC;
hb_compExprFree( pLeft, HB_MACRO_PARAM );
hb_compExprFree( pRight, HB_MACRO_PARAM );
}
else if( pLeft->ExprType == HB_ET_DATE && pRight->ExprType == HB_ET_NUMERIC )
{
if( pRight->value.asNum.NumType == HB_ET_LONG )
{
pSelf->value.asNum.lVal = pLeft->value.asNum.lVal - pRight->value.asNum.lVal;
}
else
{
pSelf->value.asNum.lVal = pLeft->value.asNum.lVal - pRight->value.asNum.dVal;
}
pSelf->ExprType = HB_ET_DATE;
pSelf->ValType = HB_EV_DATE;
hb_compExprFree( pLeft, HB_MACRO_PARAM );
hb_compExprFree( pRight, HB_MACRO_PARAM );
}
else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING )
{
/* TODO:
@@ -445,6 +470,21 @@ HB_EXPR_PTR hb_compExprReducePlus( HB_EXPR_PTR pSelf, HB_MACRO_DECL )
}
}
}
else if( pLeft->ExprType == HB_ET_DATE && pRight->ExprType == HB_ET_NUMERIC )
{
if( pRight->value.asNum.NumType == HB_ET_LONG )
{
pSelf->value.asNum.lVal = pLeft->value.asNum.lVal + pRight->value.asNum.lVal;
}
else
{
pSelf->value.asNum.lVal = pLeft->value.asNum.lVal + pRight->value.asNum.dVal;
}
pSelf->ExprType = HB_ET_DATE;
pSelf->ValType = HB_EV_DATE;
hb_compExprFree( pLeft, HB_MACRO_PARAM );
hb_compExprFree( pRight, HB_MACRO_PARAM );
}
else
{
/* TODO: Check for incompatible types e.g. "txt" + 3

View File

@@ -0,0 +1,170 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
* The Date conversion module
*
* Copyright 1999 Antonio Linares <alinares@fivetech.com>
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
* Copyright 1999-2001 Viktor Szakats <viktor.szakats@syenar.hu>
* hb_dateEncStr()
* hb_dateDecStr()
* hb_dateStrPut()
* hb_dateStrGet()
*
*/
#include "hbapi.h"
#include "hbdate.h"
#ifdef HB_C52_STRICT
#define HB_DATE_YEAR_LIMIT 2999
#else
#define HB_DATE_YEAR_LIMIT 9999
#endif
LONG HB_EXPORT hb_dateEncode( int iYear, int iMonth, int iDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateEncode(%d, %d, %d)", iYear, iMonth, iDay));
/* Perform date validation */
if( iYear >= 1 && iYear <= HB_DATE_YEAR_LIMIT &&
iMonth >= 1 && iMonth <= 12 &&
iDay >= 1 )
{
/* Month, year, and lower day limits are simple,
but upper day limit is dependent upon month and leap year */
int auiDayLimit[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if( ( ( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ) )
auiDayLimit[ 1 ] = 29;
if( iDay <= auiDayLimit[ iMonth - 1 ] )
{
int iFactor = ( iMonth < 3 ) ? -1 : 0;
return ( ( LONG )( iFactor + 4800 + iYear ) * 1461 / 4 ) +
( ( LONG )( iMonth - 2 - ( iFactor * 12 ) ) * 367 ) / 12 -
( ( LONG )( ( iFactor + 4900 + iYear ) / 100 ) * 3 / 4 ) +
( LONG ) iDay - 32075;
}
}
return 0;
}
void HB_EXPORT hb_dateDecode( LONG lJulian, int *piYear, int *piMonth, int *piDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateDecode(%ld, %p, %p, %p)", lJulian, piYear, piMonth, piDay));
if( lJulian > 0 )
{
LONG U, V, W, X;
lJulian += 68569;
W = ( lJulian * 4 ) / 146097;
lJulian -= ( ( 146097 * W ) + 3 ) / 4;
X = 4000 * ( lJulian + 1 ) / 1461001;
lJulian -= ( ( 1461 * X ) / 4 ) - 31;
V = 80 * lJulian / 2447;
U = V / 11;
*piYear = (int) ( X + U + ( W - 49 ) * 100 );
*piMonth = (int) ( V + 2 - ( U * 12 ) );
*piDay = (int) ( lJulian - ( 2447 * V / 80 ) );
}
else
{
*piYear =
*piMonth =
*piDay = 0;
}
}
void HB_EXPORT hb_dateStrPut( char * szDate, int iYear, int iMonth, int iDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateStrPut(%p, %d, %d, %d)", szDate, iYear, iMonth, iDay));
if( iYear >= 0 && iMonth && iDay )
{
szDate[ 0 ] = ( ( iYear % 10000 ) / 1000 ) + '0';
szDate[ 1 ] = ( ( iYear % 1000 ) / 100 ) + '0';
szDate[ 2 ] = ( ( iYear % 100 ) / 10 ) + '0';
szDate[ 3 ] = ( iYear % 10 ) + '0';
szDate[ 4 ] = ( iMonth / 10 ) + '0';
szDate[ 5 ] = ( iMonth % 10 ) + '0';
szDate[ 6 ] = ( iDay / 10 ) + '0';
szDate[ 7 ] = ( iDay % 10 ) + '0';
}
else if ( iYear || iMonth || iDay )
memset( szDate, '0', 8 );
else
memset( szDate, ' ', 8 );
}
void HB_EXPORT hb_dateStrGet( const char * szDate, int * piYear, int * piMonth, int * piDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateStrGet(%s, %p, %p, %p)", szDate, piYear, piMonth, piDay));
if( szDate && szDate[ 8 ] == '\0' )
{
/* Date string has correct length, so attempt to convert */
*piYear = ( ( USHORT ) ( szDate[ 0 ] - '0' ) * 1000 ) +
( ( USHORT ) ( szDate[ 1 ] - '0' ) * 100 ) +
( ( USHORT ) ( szDate[ 2 ] - '0' ) * 10 ) +
( USHORT ) ( szDate[ 3 ] - '0' );
*piMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
*piDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
}
else
{
/* Date string missing or bad length, so force an empty date */
*piYear =
*piMonth =
*piDay = 0;
}
}

View File

@@ -52,12 +52,13 @@
#include "hbhash.h"
static HB_HASH_ITEM_PTR hb_hashItemNew( ULONG ulKey, void * pValue )
static HB_HASH_ITEM_PTR hb_hashItemNew( ULONG ulKey, void *pKey, void * pValue )
{
HB_HASH_ITEM_PTR pItem = (HB_HASH_ITEM_PTR) hb_xgrab( sizeof( HB_HASH_ITEM ) );
pItem->key = ulKey;
pItem->cargo = pValue;
pItem->KeyPtr = pKey;
pItem->ValPtr = pValue;
pItem->next = NULL;
return pItem;
@@ -113,7 +114,7 @@ void hb_hashTableKill( HB_HASH_TABLE_PTR pTable )
while( pItem )
{
if( pTable->pDeleteItemFunc )
( pTable->pDeleteItemFunc )( pItem->cargo, NULL );
( pTable->pDeleteItemFunc )( pTable, pItem->KeyPtr, pItem->ValPtr );
pNext = pItem->next;
hb_xfree( ( void * ) pItem );
pItem = pNext;
@@ -151,7 +152,7 @@ HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize
HB_HASH_ITEM_PTR pNewItem, pNext;
pNext = pItem->next;
ulKey = ( pTable->pKeyFunc )( pItem->cargo, NULL );
ulKey = ( pTable->pKeyFunc )( pNew, pItem->KeyPtr, pItem->ValPtr );
pNewItem = pNew->pItems[ ulKey ];
if( pNewItem )
{
@@ -179,22 +180,22 @@ HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize
}
/* add a new value into th ehash table */
BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue )
BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pKey, void *pValue )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
ulKey = ( pTable->pKeyFunc )( pValue, NULL );
ulKey = ( pTable->pKeyFunc )( pTable, pKey, pValue );
pItem = pTable->pItems[ ulKey ];
if( pItem )
{
while( pItem->next )
pItem = pItem->next;
pItem->next = hb_hashItemNew( ulKey, pValue );
pItem->next = hb_hashItemNew( ulKey, pKey, pValue );
}
else
{
pTable->pItems[ ulKey ] = hb_hashItemNew( ulKey, pValue );
pTable->pItems[ ulKey ] = hb_hashItemNew( ulKey, pKey, pValue );
++pTable->ulUsed;
}
++pTable->ulCount;
@@ -204,21 +205,21 @@ BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue )
/* return the pointer to item's value or NULL if not found
*/
void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pValue )
void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pKey )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
void * pFound = NULL;
ulKey = ( pTable->pKeyFunc )( pValue, NULL );
ulKey = ( pTable->pKeyFunc )( pTable, pKey, NULL );
pItem = pTable->pItems[ ulKey ];
if( pItem )
{
while( pItem && (( pTable->pCompFunc )( pItem->cargo, pValue ) != 0) )
while( pItem && (( pTable->pCompFunc )( pTable, pItem->KeyPtr, pKey ) != 0) )
pItem = pItem->next;
if( pItem )
pFound = pItem->cargo;
pFound = pItem->ValPtr;
}
return pFound;
@@ -228,28 +229,38 @@ void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pValue )
* Returns TRUE if item was found and returns FALSE when passed item
* is not stored in the table
*/
BOOL hb_hashTableDel( HB_HASH_TABLE_PTR pTable, void *pValue )
BOOL hb_hashTableDel( HB_HASH_TABLE_PTR pTable, void *pKey )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
HB_HASH_ITEM_PTR pPrev = NULL;
BOOL bFound = FALSE;
ulKey = ( pTable->pKeyFunc )( pValue, NULL );
ulKey = ( pTable->pKeyFunc )( pTable, pKey, NULL );
if( ulKey > pTable->ulTableSize )
return FALSE;
pItem = pTable->pItems[ ulKey ];
while( pItem && !bFound )
{
if( ( pTable->pCompFunc )( pItem->cargo, pValue ) == 0 )
if( ( pTable->pCompFunc )( pTable, pItem->KeyPtr, pKey ) == 0 )
{
if( pPrev )
{
pPrev->next = pItem->next;
}
else
{
pTable->pItems[ ulKey ] = pItem->next;
if( !pItem->next )
{
--pTable->ulUsed;
pTable->pItems[ ulKey ] = NULL;
}
}
if( pTable->pDeleteItemFunc )
( pTable->pDeleteItemFunc )( pTable, pItem->KeyPtr, pItem->ValPtr );
hb_hashItemDelete( pItem );
bFound = TRUE;
--pTable->ulCount;

View File

@@ -5,6 +5,6 @@
/* hbexpra.c is also included from ../macro/macro.c
* However it produces a slighty different code if used in
* macro compiler (there is an additional parameter passed to some functions)
* 1.16 - ignore this magic number - this is used to force compilation
* 1.17 - ignore this magic number - this is used to force compilation
*/
#include "hbexpra.c"

View File

@@ -5,6 +5,6 @@
/* hbexprb.c is also included from ../macro/macro.c
* However it produces a slighty different code if used in
* macro compiler (there is an additional parameter passed to some functions)
* 1.13 - ignore this magic number - this is used to force compilation
* 1.14 - ignore this magic number - this is used to force compilation
*/
#include "hbexprb.c"

View File

@@ -29,6 +29,7 @@
#include <assert.h>
#include "hbcomp.h"
#include "hbdate.h"
static void hb_compGenCReadable( PFUNCTION pFunc, FILE * yyc );
static void hb_compGenCCompact( PFUNCTION pFunc, FILE * yyc );
@@ -1867,6 +1868,47 @@ static HB_GENC_FUNC( hb_p_enumend )
return 1;
}
static HB_GENC_FUNC( hb_p_switch )
{
if( cargo->bVerbose )
fprintf( cargo->yyc, "/* %05li */ ", lPCodePos );
else
fprintf( cargo->yyc, "\t" );
fprintf( cargo->yyc, "HB_P_SWITCH, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] );
if( cargo->bVerbose )
{
fprintf( cargo->yyc, "\t/* %i*/", HB_PCODE_MKSHORT( &( pFunc->pCode[ lPCodePos + 2 ] ) ) );
}
fprintf( cargo->yyc, "\n" );
return 3;
}
static HB_GENC_FUNC( hb_p_pushdate )
{
fprintf( cargo->yyc, "\tHB_P_PUSHDATE, %i, %i, %i, %i,",
pFunc->pCode[ lPCodePos + 1 ],
pFunc->pCode[ lPCodePos + 2 ],
pFunc->pCode[ lPCodePos + 3 ],
pFunc->pCode[ lPCodePos + 4 ] );
if( cargo->bVerbose )
{
int year, month, day;
char date[9];
hb_dateDecode( HB_PCODE_MKLONG( &( pFunc->pCode[ lPCodePos + 1 ] ) ), &year, &month, &day );
hb_dateStrPut( date, year, month, day );
date[8] = '\0';
fprintf( cargo->yyc, "\t/* %s */", date );
}
fprintf( cargo->yyc, "\n" );
return 5;
}
static HB_GENC_FUNC( hb_p_localnearaddint )
{
@@ -2025,7 +2067,9 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = {
hb_p_enumstart,
hb_p_enumnext,
hb_p_enumprev,
hb_p_enumend
hb_p_enumend,
hb_p_switch,
hb_p_pushdate
};
static void hb_compGenCReadable( PFUNCTION pFunc, FILE * yyc )

View File

@@ -2393,35 +2393,6 @@ void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo )
{
switch( pCode[ ( ULONG ) ( ulFrom - 1 ) ] )
{
/*
case HB_P_JUMPNEAR :
break;
case HB_P_JUMPTRUENEAR :
break;
case HB_P_JUMPFALSENEAR :
break;
case HB_P_JUMP :
pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPNEAR;
pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP;
pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP;
break;
case HB_P_JUMPTRUE :
pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPTRUENEAR;
pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP;
pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP;
break;
case HB_P_JUMPFALSE :
pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPFALSENEAR;
pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP;
pCode[ ( ULONG ) ( ulFrom + 2 ) ] = HB_P_NOOP;
break;
*/
case HB_P_JUMPFAR :
pCode[ ( ULONG ) ( ulFrom - 1 ) ] = HB_P_JUMPNEAR;
pCode[ ( ULONG ) ( ulFrom + 1 ) ] = HB_P_NOOP;
@@ -3211,30 +3182,59 @@ void hb_compGenPushFunCall( char * szFunName )
/* generates the pcode to push a long number on the virtual machine stack */
void hb_compGenPushLong( HB_LONG lNumber )
{
if( lNumber == 0 )
hb_compGenPCode1( HB_P_ZERO );
else if( lNumber == 1 )
hb_compGenPCode1( HB_P_ONE );
else if( HB_LIM_INT8( lNumber ) )
hb_compGenPCode2( HB_P_PUSHBYTE, (BYTE) lNumber, TRUE );
else if( HB_LIM_INT16( lNumber ) )
hb_compGenPCode3( HB_P_PUSHINT, HB_LOBYTE( lNumber ), HB_HIBYTE( lNumber ), TRUE );
else if( HB_LIM_INT32( lNumber ) )
if( hb_comp_long_optimize )
{
BYTE pBuffer[ 5 ];
pBuffer[ 0 ] = HB_P_PUSHLONG;
HB_PUT_LE_UINT32( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
if( lNumber == 0 )
hb_compGenPCode1( HB_P_ZERO );
else if( lNumber == 1 )
hb_compGenPCode1( HB_P_ONE );
else if( HB_LIM_INT8( lNumber ) )
hb_compGenPCode2( HB_P_PUSHBYTE, (BYTE) lNumber, TRUE );
else if( HB_LIM_INT16( lNumber ) )
hb_compGenPCode3( HB_P_PUSHINT, HB_LOBYTE( lNumber ), HB_HIBYTE( lNumber ), TRUE );
else if( HB_LIM_INT32( lNumber ) )
{
BYTE pBuffer[ 5 ];
pBuffer[ 0 ] = HB_P_PUSHLONG;
HB_PUT_LE_UINT32( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
}
else
{
BYTE pBuffer[ 9 ];
pBuffer[ 0 ] = HB_P_PUSHLONGLONG;
HB_PUT_LE_UINT64( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
}
}
else
{
BYTE pBuffer[ 9 ];
pBuffer[ 0 ] = HB_P_PUSHLONGLONG;
HB_PUT_LE_UINT64( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
if( HB_LIM_INT32( lNumber ) )
{
BYTE pBuffer[ 5 ];
pBuffer[ 0 ] = HB_P_PUSHLONG;
HB_PUT_LE_UINT32( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
}
else
{
BYTE pBuffer[ 9 ];
pBuffer[ 0 ] = HB_P_PUSHLONGLONG;
HB_PUT_LE_UINT64( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
}
}
}
void hb_compGenPushDate( HB_LONG lNumber )
{
BYTE pBuffer[ 5 ];
pBuffer[ 0 ] = HB_P_PUSHDATE;
HB_PUT_LE_UINT32( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), TRUE );
}
/* generates the pcode to push a string on the virtual machine stack */
void hb_compGenPushString( char * szText, ULONG ulStrLen )
{

View File

@@ -41,9 +41,11 @@
#include "hbsetup.h" /* main configuration file */
#include "hberrors.h"
#include "hbdefs.h"
#include "hbdate.h"
/* helper functions */
static int yy_ConvertNumber( char * szBuffer );
static int yy_ConvertDate( char * szBuffer );
extern int hb_ppInsideTextBlock;
extern BOOL hb_ppNestedLiteralString;
@@ -102,6 +104,7 @@ SpaceTab [ \t]+
Number ([0-9]+)|([0-9]*\.[0-9]+)|(0x[0-9A-Fa-f]+)
InvalidNumber [0-9]+\.
Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+))
Date 0d[0-9]{8}
MacroVar \&{Identifier}[\.]?
MacroEnd \&{Identifier}\.([_a-zA-Z0-9]*)
@@ -122,6 +125,7 @@ Separator {SpaceTab}
%x NEXT_ BREAK_ CASE_ DO_ DOIDENT_ WHILE_ WITH_ END_ FIELD_
%x FOR_ FOREACH_ FUNCTION_ IIF_ IF_ IN_ INIT_
%x RETURN_ RECOVER_
%x SWITCH_
%x INVALIDNUM_ OTHERWISE_ PROCEDURE_
%x DECLARE_ DECLARE_ID_
@@ -465,7 +469,7 @@ Separator {SpaceTab}
BEGIN 0;
unput( yytext[ yyleng-1 ] );
unput( yytext[ yyleng-2 ] );
if( hb_comp_wCaseCounter == 0 )
if( hb_comp_wCaseCounter == 0 && hb_comp_wSwitchCounter == 0 )
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_CASE, NULL, NULL );
hb_comp_iState =CASE;
return CASE;
@@ -475,7 +479,7 @@ Separator {SpaceTab}
unput( yytext[ yyleng-1 ] );
if( hb_comp_iState == LOOKUP )
{ /* it is first item in the line */
if( hb_comp_wCaseCounter == 0 )
if( hb_comp_wCaseCounter == 0 && hb_comp_wSwitchCounter == 0 )
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_CASE, NULL, NULL );
hb_comp_iState =CASE;
return CASE;
@@ -1208,7 +1212,7 @@ Separator {SpaceTab}
unput( yytext[ yyleng-1 ] );
if( hb_comp_iState == LOOKUP )
{ /* it is the first item in the line */
if( hb_comp_wCaseCounter == 0 )
if( hb_comp_wCaseCounter == 0 && hb_comp_wSwitchCounter == 0 )
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_CASE, NULL, NULL );
hb_comp_iState = OTHERWISE;
return OTHERWISE;
@@ -1384,6 +1388,51 @@ Separator {SpaceTab}
/* ************************************************************************ */
%}
"step" { hb_comp_iState = IDENTIFIER; return STEP; }
%{
/* ************************************************************************ */
%}
"switch" BEGIN SWITCH_;
<SWITCH_>{Separator}* ;
<SWITCH_>[\:\=\|\$\%\*\,\/\]\)\}\^] { /* there is an operator after "switch" */
BEGIN 0;
yylval.string = hb_compIdentifierNew( "SWITCH", TRUE );
hb_comp_iState =IDENTIFIER;
unput( yytext[ yyleng-1 ] );
return IDENTIFIER;
}
<SWITCH_>("+="|"-="|"->") { /* operators */
BEGIN 0;
yylval.string = hb_compIdentifierNew( "SWITCH", TRUE );
hb_comp_iState =IDENTIFIER;
unput( yytext[ yyleng-1 ] );
unput( yytext[ yyleng-2 ] );
return IDENTIFIER;
}
<SWITCH_>("::") { /* send operators */
BEGIN 0;
unput( yytext[ yyleng-1 ] );
unput( yytext[ yyleng-2 ] );
hb_comp_iState =DOSWITCH;
return DOSWITCH;
}
<SWITCH_>(\n|.) { /* not operator */
BEGIN 0;
unput( yytext[ yyleng-1 ] );
if( hb_comp_iState == LOOKUP )
{ /* it is first item in the line */
hb_comp_iState =DOSWITCH;
return DOSWITCH;
}
else
{ /* there is another item in line already */
yylval.string = hb_compIdentifierNew( "SWITCH", TRUE );
hb_comp_iState =IDENTIFIER;
return IDENTIFIER;
}
}
%{
/* ************************************************************************ */
%}
"to" { hb_comp_iState = IDENTIFIER; return TO; }
%{
/* ************************************************************************ */
@@ -1684,6 +1733,8 @@ Separator {SpaceTab}
{TrueValue} { hb_comp_iState =RSEPARATOR; return TRUEVALUE; }
{FalseValue} { hb_comp_iState =RSEPARATOR; return FALSEVALUE; }
{Date} { return yy_ConvertDate( yytext ); }
{MacroVar} {
if( yytext[ yyleng-1 ] == '.' )
yytext[ yyleng-1 ] = '\0';
@@ -1765,3 +1816,14 @@ static int yy_ConvertNumber( char * szBuffer )
return NUM_LONG;
}
}
static int yy_ConvertDate( char * szBuffer )
{
int year, month, day;
hb_dateStrGet( szBuffer+2, &year, &month, &day );
yylval.valLong.lNumber = hb_dateEncode( year, month, day );
yylval.valLong.szValue = szBuffer;
return NUM_DATE;
}

View File

@@ -94,6 +94,11 @@ static void hb_compEnumStart( HB_EXPR_PTR pVars, HB_EXPR_PTR pExprs, int descend
static void hb_compEnumNext( HB_EXPR_PTR pExpr, int descend );
static void hb_compEnumEnd( HB_EXPR_PTR pExpr );
static void hb_compSwitchStart( void );
static void hb_compSwitchAdd( HB_EXPR_PTR );
static void hb_compSwitchEnd( void );
#ifdef HARBOUR_YYDEBUG
#define YYDEBUG 1 /* Parser debug information support */
#endif
@@ -114,6 +119,24 @@ typedef struct _LOOPEXIT
struct _LOOPEXIT * pNext;
} LOOPEXIT, * PTR_LOOPEXIT; /* support structure for EXIT and LOOP statements */
/* support structure for SWITCH statement */
typedef struct _SWITCHCASE
{
ULONG ulOffset;
HB_EXPR_PTR pExpr;
struct _SWITCHCASE *pNext;
} SWITCHCASE, * SWITCHCASE_PTR;
typedef struct _SWITCHCMD
{
ULONG ulOffset;
int iCount;
SWITCHCASE_PTR pCases;
SWITCHCASE_PTR pLast;
ULONG ulDefault;
struct _SWITCHCMD *pPrev;
} SWITCHCMD, *SWITCHCMD_PTR;
typedef struct HB_RTVAR_
{
HB_EXPR_PTR pVar;
@@ -127,11 +150,15 @@ USHORT hb_comp_wForCounter = 0;
USHORT hb_comp_wIfCounter = 0;
USHORT hb_comp_wWhileCounter = 0;
USHORT hb_comp_wCaseCounter = 0;
USHORT hb_comp_wSwitchCounter= 0;
BOOL hb_comp_long_optimize = TRUE;
BOOL hb_comp_bTextSubst = TRUE;
char * hb_comp_buffer; /* yacc input buffer */
static PTR_LOOPEXIT hb_comp_pLoops = NULL;
static HB_RTVAR_PTR hb_comp_rtvars = NULL;
static SWITCHCMD_PTR hb_comp_pSwitch = NULL;
extern int hb_compLocalGetPos( char * szVarName ); /* returns the order + 1 of a local variable */
@@ -188,6 +215,8 @@ static void hb_compDebugStart( void ) { };
%token PROCREQ GET
%token CBSTART DOIDENT
%token FOREACH DESCEND
%token DOSWITCH
%token NUM_DATE
/*the lowest precedence*/
/*postincrement and postdecrement*/
@@ -220,6 +249,7 @@ static void hb_compDebugStart( void ) { };
%type <valDouble> NUM_DOUBLE
%type <valInteger> NUM_INTEGER
%type <valLong> NUM_LONG
%type <valLong> NUM_DATE
%type <iNumber> FunScope
%type <iNumber> Params ParamList
%type <iNumber> IfBegin VarList ExtVarList
@@ -260,6 +290,8 @@ static void hb_compDebugStart( void ) { };
%type <asExpr> PostOp
%type <asExpr> ForVar ForList ForExpr
%type <asCodeblock> CBSTART
%type <asExpr> SwitchCases SwitchStart SwitchBegin SwitchDefault
%type <asExpr> DateValue
%%
@@ -482,6 +514,14 @@ NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bWi
| NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber ); }
;
DateValue : NUM_DATE { $$ = hb_compExprNewDate( $1.lNumber );
if( $1.lNumber == 0 )
{
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_DATE, $1.szValue, NULL );
}
}
;
NumAlias : NUM_INTEGER ALIASOP { $$ = hb_compExprNewLong( $1.iNumber ); }
| NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber ); }
| NUM_DOUBLE ALIASOP { $$ = hb_compErrorAlias( hb_compExprNewDouble( $1.dNumber, $1.bWidth, $1.bDec ) ); }
@@ -682,6 +722,7 @@ SendId : IdentName { $$ = $1; }
ObjectData : NumValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
| NilValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
| DateValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
| LiteralValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
| CodeBlock ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
| Logical ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); }
@@ -719,6 +760,7 @@ ObjectMethodAlias : ObjectMethod ALIASOP { $$ = $1; }
SimpleExpression :
NumValue
| NilValue { $$ = $1; }
| DateValue { $$ = $1; }
| LiteralValue { $$ = $1; }
| CodeBlock { $$ = $1; }
| Logical { $$ = $1; }
@@ -836,6 +878,7 @@ ExprAssign : NumValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $
ExprEqual : NumValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
| NilValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
| DateValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
| LiteralValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
| CodeBlock '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
| Logical '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); }
@@ -1364,6 +1407,7 @@ ExecFlow : IfEndif
| ForNext
| BeginSeq
| ForEach
| DoSwitch
;
IfEndif : IfBegin EndIf { hb_compGenJumpHere( $1 ); }
@@ -1531,9 +1575,9 @@ ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
hb_compDebugStart();
++hb_comp_wForCounter; /* 5 */
$<asExpr>$ = hb_compExprGenStatement( hb_compExprAssign( $2, $4 ) );
if( hb_compExprAsString($<asExpr>2) )
if( hb_compExprAsSymbol($<asExpr>2) )
{
hb_compForStart( hb_compExprAsString($<asExpr>2), FALSE );
hb_compForStart( hb_compExprAsSymbol($<asExpr>2), FALSE );
}
}
TO Expression StepExpr /* 6 7 8 */
@@ -1571,7 +1615,7 @@ ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
iStep = 1;
}
if( iStep && ( iLocal = hb_compLocalGetPos( hb_compExprAsString($<asExpr>2) ) ) > 0 && iLocal < 256 )
if( iStep && ( iLocal = hb_compLocalGetPos( hb_compExprAsSymbol($<asExpr>2) ) ) > 0 && iLocal < 256 )
{
hb_compGenPCode4( HB_P_LOCALNEARADDINT, ( BYTE ) iLocal, HB_LOBYTE( iStep ), HB_HIBYTE( iStep ), ( BOOL ) 0 );
}
@@ -1587,9 +1631,9 @@ ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
hb_compGenJump( $<lNumber>9 - hb_comp_functions.pLast->lPCodePos );
hb_compGenJumpHere( $<lNumber>11 );
hb_compLoopEnd();
if( hb_compExprAsString($<asExpr>2) )
if( hb_compExprAsSymbol($<asExpr>2) )
{
hb_compForEnd( hb_compExprAsString($<asExpr>2) );
hb_compForEnd( hb_compExprAsSymbol($<asExpr>2) );
}
hb_compExprDelete( $7 );
hb_compExprDelete( $<asExpr>5 ); /* deletes $5, $2, $4 */
@@ -1665,6 +1709,68 @@ Descend : /* default up */ { $$ = 1; }
| DESCEND { $$ = -1; }
;
DoSwitch : SwitchBegin
{
hb_compLoopStart();
hb_compSwitchStart();
hb_compGenJump( 0 );
}
SwitchCases
EndSwitch
{
hb_compSwitchEnd();
hb_compLoopEnd();
}
| SwitchBegin
EndSwitch
{
hb_compGenPData1( HB_P_POP );
}
;
EndSwitch : END
{
--hb_comp_wSwitchCounter;
hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
}
;
SwitchStart : DOSWITCH
{ ++hb_comp_wSwitchCounter;
hb_compLinePush();
}
Expression Crlf
{
hb_compExprDelete( hb_compExprGenPush( $3 ) );
}
;
SwitchBegin : SwitchStart { }
| SwitchStart Statements {
if( $<lNumber>2 > 0 )
{
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL );
}
}
;
SwitchCases : CASE Expression { hb_compSwitchAdd( $2 ); hb_compLinePush(); } Crlf
EmptyStats
| SwitchCases CASE Expression { hb_compSwitchAdd( $3 ); hb_compLinePush(); }Crlf
EmptyStats
| SwitchDefault
| SwitchCases SwitchDefault
;
SwitchDefault : OTHERWISE {hb_compSwitchAdd(NULL); hb_compLinePush(); } Crlf { hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; }
EmptyStats
;
BeginSeq : BEGINSEQ { ++hb_comp_wSeqCounter; $<lNumber>$ = hb_compSequenceBegin(); } Crlf
EmptyStats
{
@@ -2296,7 +2402,7 @@ static void hb_compForEnd( char *szVar )
static HB_CARGO2_FUNC( hb_compEnumEvalStart )
{
char * szName = hb_compExprAsString( (HB_EXPR_PTR)cargo );
char * szName = hb_compExprAsSymbol( (HB_EXPR_PTR)cargo );
if( szName )
hb_compForStart( szName, TRUE );
@@ -2342,7 +2448,7 @@ static void hb_compEnumNext( HB_EXPR_PTR pExpr, int descend )
static HB_CARGO_FUNC( hb_compEnumEvalEnd )
{
char * szName = hb_compExprAsString( (HB_EXPR_PTR)cargo );
char * szName = hb_compExprAsSymbol( (HB_EXPR_PTR)cargo );
if( szName )
hb_compForEnd( szName );
@@ -2354,3 +2460,126 @@ static void hb_compEnumEnd( HB_EXPR_PTR pExpr )
hb_compGenPCode1( HB_P_ENUMEND );
}
static void hb_compSwitchStart()
{
SWITCHCMD_PTR pLast = hb_comp_pSwitch;
hb_comp_pSwitch = (SWITCHCMD_PTR) hb_xgrab( sizeof(SWITCHCMD) );
hb_comp_pSwitch->pPrev = pLast;
hb_comp_pSwitch->pCases = NULL;
hb_comp_pSwitch->pLast = NULL;
hb_comp_pSwitch->ulDefault = 0;
hb_comp_pSwitch->ulOffset = hb_comp_functions.pLast->lPCodePos;
hb_comp_pSwitch->iCount = 0;
}
static void hb_compSwitchAdd( HB_EXPR_PTR pExpr )
{
SWITCHCASE_PTR pCase;
if( pExpr )
{
/* normal CASE */
pCase = (SWITCHCASE_PTR) hb_xgrab( sizeof(SWITCHCASE) );
pCase->ulOffset = hb_comp_functions.pLast->lPCodePos;
pCase->pNext = NULL;
pExpr = hb_compExprReduce( pExpr );
if( !(hb_compExprIsLong(pExpr) || hb_compExprIsString(pExpr)) )
{
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_NOT_LITERAL_CASE, NULL, NULL );
}
pCase->pExpr = pExpr;
if( hb_comp_pSwitch->pLast )
{
hb_comp_pSwitch->pLast->pNext = pCase;
hb_comp_pSwitch->pLast = pCase;
}
else
{
hb_comp_pSwitch->pCases = hb_comp_pSwitch->pLast = pCase;
}
hb_comp_pSwitch->iCount++;
if( hb_compExprIsString( pExpr ) && hb_compExprAsStringLen(pExpr) > 255 )
{
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_STR, NULL, NULL );
}
}
else
{
/* DEFAULT */
if( hb_comp_pSwitch->ulDefault )
{
/* more than one default clause */
hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL );
}
else
{
hb_comp_pSwitch->ulDefault = hb_comp_functions.pLast->lPCodePos;
hb_comp_pSwitch->iCount++;
}
}
}
static void hb_compSwitchEnd( void )
{
BOOL longOptimize = hb_comp_long_optimize;
BOOL bTextSubst = hb_comp_bTextSubst;
SWITCHCASE_PTR pCase = hb_comp_pSwitch->pCases;
SWITCHCASE_PTR pTmp;
SWITCHCMD_PTR pTmpSw;
ULONG ulExitPos;
ULONG ulDef;
/* skip switch pcode if there was no EXIT in the last CASE
* or in the DEFAULT case
*/
ulExitPos = hb_compGenJump( 0 );
hb_compGenJumpHere( hb_comp_pSwitch->ulOffset + 1 );
hb_compGenPCode3( HB_P_SWITCH, HB_LOBYTE(hb_comp_pSwitch->iCount), HB_HIBYTE(hb_comp_pSwitch->iCount), FALSE );
hb_comp_long_optimize = FALSE;
hb_comp_bTextSubst = FALSE;
while( pCase )
{
if( pCase->pExpr )
{
if( hb_compExprIsLong(pCase->pExpr) || hb_compExprIsString(pCase->pExpr) )
{
hb_compExprDelete( hb_compExprGenPush( pCase->pExpr ) );
hb_compGenJumpThere( hb_compGenJump( 0 ), pCase->ulOffset );
}
else
{
hb_compExprDelete( pCase->pExpr );
}
}
pCase = pCase->pNext;
}
hb_compGenPData1( HB_P_PUSHNIL ); /* end of cases */
ulDef = hb_compGenJump( 0 );
if( hb_comp_pSwitch->ulDefault )
{
hb_compGenJumpThere( ulDef, hb_comp_pSwitch->ulDefault );
}
else
hb_compGenJumpHere( ulDef );
hb_comp_long_optimize = longOptimize;
hb_comp_bTextSubst = bTextSubst;
hb_compGenJumpHere( ulExitPos );
pCase = hb_comp_pSwitch->pCases;
while( pCase )
{
pTmp = pCase->pNext;
hb_xfree( (void *)pCase );
pCase = pTmp;
}
pTmpSw = hb_comp_pSwitch;
hb_comp_pSwitch = hb_comp_pSwitch->pPrev;
hb_xfree( pTmpSw );
}

View File

@@ -432,7 +432,9 @@ static HB_FIX_FUNC_PTR s_fixlocals_table[] =
NULL, /* HB_P_ENUMSTART */
NULL, /* HB_P_ENUMNEXT */
NULL, /* HB_P_ENUMPREV */
NULL /* HB_P_ENUMEND */
NULL, /* HB_P_ENUMEND */
NULL, /* HB_P_SWITCH */
NULL /* HB_P_PUSHDATE */
};
void hb_compFixFuncPCode( PFUNCTION pFunc )

View File

@@ -86,7 +86,10 @@ char * hb_comp_szErrors[] =
"Inline C requires C output generation, use -gc[n]",
"Too many local variables [%s] or parameters [%s]",
"Too many enumerate variables in FOR EACH loop",
"Incorrect number of enumerate variables"
"Incorrect number of enumerate variables",
"CASE requires either numeric or string constant",
"String too long for SWITCH",
"Invalid date constant \'%s\'"
};
/* Table with parse warnings */

View File

@@ -49,7 +49,7 @@ char * hb_compIdentifierNew( char * szName, BOOL bCopy )
else
szIdent = szName;
hb_hashTableAdd( s_comp_Identifiers, (void *)szIdent );
hb_hashTableAdd( s_comp_Identifiers, (void *)szIdent, (void *)szIdent );
}
return szIdent;
@@ -64,6 +64,7 @@ HB_HASH_FUNC( hb_comp_IdentKey ) /* ULONG func (void *Value, void *Cargo) */
while( *szName )
ulSum += *szName++;
HB_SYMBOL_UNUSED( HashPtr );
HB_SYMBOL_UNUSED( Cargo );
return ulSum % HB_IDENT_TABLE_SIZE;
@@ -73,6 +74,7 @@ HB_HASH_FUNC( hb_comp_IdentKey ) /* ULONG func (void *Value, void *Cargo) */
HB_HASH_FUNC( hb_comp_IdentDel )
{
hb_xfree( Value );
HB_SYMBOL_UNUSED( HashPtr );
HB_SYMBOL_UNUSED( Cargo );
return 1;
}
@@ -80,6 +82,7 @@ HB_HASH_FUNC( hb_comp_IdentDel )
/* compares two identifiers */
HB_HASH_FUNC( hb_comp_IdentComp )
{
HB_SYMBOL_UNUSED( HashPtr );
return strcmp( (char *)Value, (char *)Cargo );
}

View File

@@ -176,7 +176,9 @@ static BYTE s_pcode_len[] = {
3, /* HB_P_ENUMSTART */
1, /* HB_P_ENUMNEXT */
1, /* HB_P_ENUMPREV */
1 /* HB_P_ENUMEND */
1, /* HB_P_ENUMEND */
3, /* HB_P_SWITCH */
5 /* HB_P_PUSHDATE, */
};
#if defined(HB_COMP_STRONG_TYPES)

View File

@@ -73,6 +73,7 @@ NOTE: -C controls the speed/size ratio of generated scanner
#include "hbmacro.h"
#include "hbcomp.h"
#include "hbdate.h"
#include "macroy.h"
#include "hbsetup.h" /* main configuration file */
@@ -117,6 +118,7 @@ SpaceTab [ \t]+
Number ([0-9]+)|([0-9]*\.[0-9]+)|(0x[0-9A-Fa-f]+)
InvalidNumber [0-9]+\.
Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+))
Date 0d[0-9]{8}
MacroVar \&{Identifier}[\.]?
MacroEnd \&{Identifier}\.({Identifier})|([0-9]+)
@@ -268,6 +270,15 @@ MacroTxt ({MacroVar}|{MacroEnd}|{MacroId})+
}
}
{Date} {
int year, month, day;
hb_dateStrGet( yytext+2, &year, &month, &day );
yylval_ptr->valLong.lNumber = hb_dateEncode( year, month, day );
return NUM_DATE;
}
{MacroVar} {
HB_TRACE(HB_TR_DEBUG, ("{MacroVar}(%s)", yytext));
if( yytext[ yyleng-1 ] == '.' )

View File

@@ -64,6 +64,7 @@
#include "hbmacro.h"
#include "hbcomp.h"
#include "hbdate.h"
/* Compile using: bison -d -p hb_comp macro.y */
@@ -159,7 +160,7 @@ int yylex( YYSTYPE *, HB_MACRO_PTR );
#endif
%}
%token IDENTIFIER NIL NUM_DOUBLE INASSIGN NUM_LONG
%token IDENTIFIER NIL NUM_DOUBLE INASSIGN NUM_LONG NUM_DATE
%token IIF IF LITERAL TRUEVALUE FALSEVALUE
%token AND OR NOT EQ NE1 NE2 INC DEC ALIASOP SELF
%token LE GE FIELD MACROVAR MACROTEXT
@@ -194,6 +195,7 @@ int yylex( YYSTYPE *, HB_MACRO_PTR );
%type <string> IDENTIFIER LITERAL MACROVAR MACROTEXT
%type <valDouble> NUM_DOUBLE
%type <valLong> NUM_LONG
%type <valLong> NUM_DATE
%type <asExpr> Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar
%type <asExpr> NumValue NumAlias
%type <asExpr> NilValue
@@ -221,6 +223,7 @@ int yylex( YYSTYPE *, HB_MACRO_PTR );
%type <asExpr> ArrayIndex IndexList
%type <asExpr> FieldAlias FieldVarAlias
%type <asExpr> PostOp
%type <asExpr> DateValue
%%
@@ -267,6 +270,9 @@ NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bWidth,
| NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber ); }
;
DateValue : NUM_DATE { $$ = hb_compExprNewDate( $1.lNumber ); }
;
NumAlias : NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber ); }
;
@@ -431,6 +437,7 @@ Argument : EmptyExpression { $$ = $1; }
*/
ObjectData : NumValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
| NilValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
| DateValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
| LiteralValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
| CodeBlock ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
| Logical ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); }
@@ -458,6 +465,7 @@ ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1
SimpleExpression :
NumValue
| NilValue { $$ = $1; }
| DateValue { $$ = $1; }
| LiteralValue { $$ = $1; }
| CodeBlock { $$ = $1; }
| Logical { $$ = $1; }

View File

@@ -5,7 +5,7 @@
/* hbexpra.c is also included from ../compiler/expropta.c
* However it produces a slighty different code if used in
* macro compiler (there is an additional parameter passed to some functions)
* 1.16 - ignore this magic number - this is used to force compilation
* 1.17 - ignore this magic number - this is used to force compilation
*/
#define HB_MACRO_SUPPORT

View File

@@ -5,7 +5,7 @@
/* hbexprb.c is also included from ../compiler/exproptb.c
* However it produces a slighty different code if used in
* macro compiler (there is an additional parameter passed to some functions)
* 1.12 - ignore this magic number - this is used to force compilation
* 1.13 - ignore this magic number - this is used to force compilation
*/
#define HB_MACRO_SUPPORT

View File

@@ -78,115 +78,6 @@
#include "hbapi.h"
#include "hbdate.h"
#ifdef HB_C52_STRICT
#define HB_DATE_YEAR_LIMIT 2999
#else
#define HB_DATE_YEAR_LIMIT 9999
#endif
LONG HB_EXPORT hb_dateEncode( int iYear, int iMonth, int iDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateEncode(%d, %d, %d)", iYear, iMonth, iDay));
/* Perform date validation */
if( iYear >= 1 && iYear <= HB_DATE_YEAR_LIMIT &&
iMonth >= 1 && iMonth <= 12 &&
iDay >= 1 )
{
/* Month, year, and lower day limits are simple,
but upper day limit is dependent upon month and leap year */
int auiDayLimit[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if( ( ( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ) )
auiDayLimit[ 1 ] = 29;
if( iDay <= auiDayLimit[ iMonth - 1 ] )
{
int iFactor = ( iMonth < 3 ) ? -1 : 0;
return ( ( LONG )( iFactor + 4800 + iYear ) * 1461 / 4 ) +
( ( LONG )( iMonth - 2 - ( iFactor * 12 ) ) * 367 ) / 12 -
( ( LONG )( ( iFactor + 4900 + iYear ) / 100 ) * 3 / 4 ) +
( LONG ) iDay - 32075;
}
}
return 0;
}
void HB_EXPORT hb_dateDecode( LONG lJulian, int *piYear, int *piMonth, int *piDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateDecode(%ld, %p, %p, %p)", lJulian, piYear, piMonth, piDay));
if( lJulian > 0 )
{
LONG U, V, W, X;
lJulian += 68569;
W = ( lJulian * 4 ) / 146097;
lJulian -= ( ( 146097 * W ) + 3 ) / 4;
X = 4000 * ( lJulian + 1 ) / 1461001;
lJulian -= ( ( 1461 * X ) / 4 ) - 31;
V = 80 * lJulian / 2447;
U = V / 11;
*piYear = (int) ( X + U + ( W - 49 ) * 100 );
*piMonth = (int) ( V + 2 - ( U * 12 ) );
*piDay = (int) ( lJulian - ( 2447 * V / 80 ) );
}
else
{
*piYear =
*piMonth =
*piDay = 0;
}
}
void HB_EXPORT hb_dateStrPut( char * szDate, int iYear, int iMonth, int iDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateStrPut(%p, %d, %d, %d)", szDate, iYear, iMonth, iDay));
if( iYear >= 0 && iMonth && iDay )
{
szDate[ 0 ] = ( ( iYear % 10000 ) / 1000 ) + '0';
szDate[ 1 ] = ( ( iYear % 1000 ) / 100 ) + '0';
szDate[ 2 ] = ( ( iYear % 100 ) / 10 ) + '0';
szDate[ 3 ] = ( iYear % 10 ) + '0';
szDate[ 4 ] = ( iMonth / 10 ) + '0';
szDate[ 5 ] = ( iMonth % 10 ) + '0';
szDate[ 6 ] = ( iDay / 10 ) + '0';
szDate[ 7 ] = ( iDay % 10 ) + '0';
}
else if ( iYear || iMonth || iDay )
memset( szDate, '0', 8 );
else
memset( szDate, ' ', 8 );
}
void HB_EXPORT hb_dateStrGet( const char * szDate, int * piYear, int * piMonth, int * piDay )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dateStrGet(%s, %p, %p, %p)", szDate, piYear, piMonth, piDay));
if( szDate && szDate[ 8 ] == '\0' )
{
/* Date string has correct length, so attempt to convert */
*piYear = ( ( USHORT ) ( szDate[ 0 ] - '0' ) * 1000 ) +
( ( USHORT ) ( szDate[ 1 ] - '0' ) * 100 ) +
( ( USHORT ) ( szDate[ 2 ] - '0' ) * 10 ) +
( USHORT ) ( szDate[ 3 ] - '0' );
*piMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
*piDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
}
else
{
/* Date string missing or bad length, so force an empty date */
*piYear =
*piMonth =
*piDay = 0;
}
}
/* This function always closes the date with a zero byte, so it needs a
9 character long buffer. */

View File

@@ -131,6 +131,7 @@ static LONG hb_vmEnumStart( BYTE, BYTE, LONG ); /* prepare FOR EACH loop */
static void hb_vmEnumNext( void ); /* increment FOR EACH loop counter */
static void hb_vmEnumPrev( void ); /* decrement FOR EACH loop counter */
static LONG hb_vmEnumEnd( void ); /* rewind the stack after FOR EACH loop counter */
static LONG hb_vmSwitch( const BYTE * pCode, LONG, USHORT ); /* make a SWITCH statement */
/* Operators (logical) */
static void hb_vmNot( void ); /* changes the latest logical value on the stack */
@@ -628,7 +629,7 @@ void HB_EXPORT hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
if( ! --uiPolls )
{
hb_inkeyPoll();
//uiPolls = 255;
uiPolls = 255;
/* IMHO we should have a _SET_ controlled by user
* sth like:
@@ -770,6 +771,10 @@ void HB_EXPORT hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
w++;
break;
case HB_P_SWITCH:
w = hb_vmSwitch( pCode, w+3, HB_PCODE_MKUSHORT( &( pCode[ w + 1 ] ) ) );
break;
/* Operators (logical) */
case HB_P_NOT:
@@ -1251,6 +1256,12 @@ void HB_EXPORT hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
w += ( 2 + pCode[ w + 1 ] );
break;
case HB_P_PUSHDATE:
HB_TRACE( HB_TR_DEBUG, ("(HB_P_PUSHDATE)") );
hb_vmPushDate( ( long ) HB_PCODE_MKLONG( &pCode[ w + 1 ] ) );
w += 5;
break;
case HB_P_PUSHBLOCK:
/* +0 -> _pushblock
* +1 +2 -> size of codeblock
@@ -3263,6 +3274,85 @@ static LONG hb_vmEnumEnd( void )
return lOldBase;
}
static LONG hb_vmSwitch( const BYTE * pCode, LONG offset, USHORT casesCnt )
{
HB_ITEM_PTR pSwitch = hb_stackItemFromTop( -1 );
if( !(HB_IS_NUMINT(pSwitch) || HB_IS_STRING(pSwitch)) )
{
HB_ITEM_PTR pResult = hb_errRT_BASE_Subst( EG_ARG, 3104, NULL, "SWITCH", 1, pSwitch );
if( pResult )
{
hb_stackPop();
hb_vmPush( pResult );
hb_itemRelease( pResult );
pSwitch = hb_stackItemFromTop( -1 );
}
else
return offset;
}
while( casesCnt-- )
{
switch( pCode[ offset ] )
{
case HB_P_PUSHLONG:
{
if( HB_IS_NUMINT(pSwitch) )
{
if( HB_ITEM_GET_NUMINTRAW(pSwitch) == HB_PCODE_MKLONG( &pCode[ offset + 1 ] ) )
{
hb_stackPop();
return offset + 5;
}
}
offset += 5;
}
break;
case HB_P_PUSHSTRSHORT:
{
if( HB_IS_STRING(pSwitch) )
{
// int i = hb_itemStrCmp( pItem1, pItem2, bExact );
if( strcmp( pSwitch->item.asString.value, ( char * ) pCode + offset + 2 ) == 0 )
{
hb_stackPop();
return offset + 2 + pCode[ offset + 1 ];
}
}
offset += ( 2 + pCode[ offset + 1 ] );
}
break;
case HB_P_PUSHNIL:
{
/* default clause */
hb_stackPop();
return offset + 1;
}
break;
}
switch( pCode[ offset ] )
{
case HB_P_JUMP:
offset += 3;
break;
case HB_P_JUMPNEAR:
offset += 2;
break;
default:
offset += 4;
break;
}
}
hb_stackPop();
return offset;
}
/* ------------------------------- */
/* Operators (logical) */
/* ------------------------------- */

View File

@@ -1284,6 +1284,15 @@ void hb_compGenPushLong( HB_LONG lNumber, HB_MACRO_DECL )
}
}
/* generates the pcode to push a date on the virtual machine stack */
void hb_compGenPushDate( HB_LONG lNumber, HB_MACRO_DECL )
{
BYTE pBuffer[ 5 ];
pBuffer[ 0 ] = HB_P_PUSHDATE;
HB_PUT_LE_UINT32( pBuffer + 1, lNumber );
hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_MACRO_PARAM );
}
/* sends a message to an object */
void hb_compGenMessage( char * szMsgName, HB_MACRO_DECL )

31
harbour/tests/ddate.prg Normal file
View File

@@ -0,0 +1,31 @@
PROCEDURE MAIN()
LOCAL dDate
LOCAL A
SET DATE FORMAT TO "YYYY.MM.DD"
SET CENTURY ON
dDate = 0d20051112
? "Should be '2005.11.12' :", dDate
dDate = 0d18341112
? "Should be '1834.11.12' :", dDate
dDate = 0d20040229 + 1
? "Should be '2004.03.01' :", dDate
dDate = 0d20040229 - 1
? "Should be '2004.02.28' :", dDate
? "Should be '4' :", 0d20040229 - 0d20040225
? "Should be '0' :", 0d20040229 - 0d20040229
dDate = 0d20000229
? "Should be '2000.02.29' :", dDate
a := '0d20040229+1'
? "Should be '2004.03.01' :", &a
a :="DATE() - 0d20051112"
? "Number of days from 2005.11.12:", &a

116
harbour/tests/switch.prg Normal file
View File

@@ -0,0 +1,116 @@
#ifdef __XHARBOUR__
#define OTHERWISE DEFAULT
#endif
PROCEDURE MAIN
LOCAL a:=1
PRIVATE b:="b"
#ifndef __XHARBOUR__
SWITCH a
END
#endif
?
? "1111111111111111111111111111111"
SWITCH a
CASE 1
? "FOUND: 1"
END
?
? "2222222222222222222222222222222"
SWITCH a
CASE 1
? "FOUND: 1"
EXIT
CASE "2"
? a
END
?
? "3333333333333333333333333333333"
SWITCH a
CASE 1
? "FOUND: 1"
CASE "2"
? "FOUND: 2"
OTHERWISE
? "other"
END
#ifndef __XHARBOUR__
?
? "44444444444444444444444444444444444"
SWITCH a
OTHERWISE
? "OTHERWISE"
END
#endif
?
? "55555555555555555555555555555555555"
a := 'EE'
#ifndef __XHARBOUR__
SWITCH a
CASE 11
? "11"
exit
CASE 'CCCC'+'DDDD'
? a+a
EXIT
CASE "a&b"
CASE 1+1
CASE {11111111,22222222222}[1]
CASE 1+1+1
? "3"
EXIT
CASE 1+1*3
CASE 123+12*4-1*4+2
CASE 1-4
? "4"
EXIT
CASE 123456789
CASE 0
EXIT
CASE 'AAAA'
CASE 'BBBBB'
? a
EXIT
CASE CHR(12)+CHR(15)
? "CHR()"
EXIT
OTHERWISE
? "NOT FOUND: running OTHER"
END
#endif
?
? "666666666666666666666666666666666666666666"
a := "2"
SWITCH a
CASE 1
? "FOUND: 1"
? a
EXIT
CASE "2"
SWITCH a+a
CASE 1
? "Nested FOUND 1"
EXIT
CASE "22"
? "Nested FOUND: 22"
EXIT
OTHERWISE
? "Nested OTHERWISE"
END
?? "In CASE 1"
? a
END
? "========================================="
RETURN