ChangeLog: 19990711-20:25

This commit is contained in:
Ryszard Glab
1999-07-11 19:34:43 +00:00
parent 70ffe0bb1d
commit 4aaed33907
28 changed files with 1082 additions and 480 deletions

View File

@@ -1,3 +1,78 @@
19990711-20:25 Ryszard Glab <rglab@imid.med.pl>
* include/extend.h
+ added HB_VALUE structure for storing memvars and detached locals
+ added hb_struMemvar used in HB_ITEM structure
* include/hbdefs.h
+ added IT_MEMVAR constant for values stored as memvar reference
+ added IS_MEMVAR macro
* source/vm/hvm.c
* corrected support for detached local variables
+ added support for static variables passed by reference
* variables passed by reference can be now chained and a reference to
static variable can be mixed with a reference to local variable
(this should work for memvar variables too)
* source/rtl/codebloc.c
* corrected support for detached local variables
+ added copyright info
+ source/rtl/memvars.c
+ new file for PUBLIC and PRIVATE variables handling
(it supports detached locals currently)
* source/rtl/classes.c
* updated to use 'ItemUnRef()' function instead of direct stack access
* source/rtl/extend.c
* updated to use 'ItemUnRef()' function instead of direct stack access
* removed all if( pItem->type & IT_BYREF ) and replaced with the *only*
correct if( IS_BYREF(pItem) )
* source/rtl/Makefile
+ added memvars.c file
- tests/working/codebl2.c
- removed this file because its code is now in codebl.prg file
* tests/working/codebl.prg
* added new code to test detached locals (donated by David Pearson)
* tests/working/byref.prg
* added new code to test if Harbour handles variables passed by
reference correctly
* tests/working/Makefile
- removed codebl2.prg
* doc/codebloc.txt
* updated information to reflect current implementation of codeblocks
+ config/win32/bcc32.cf
+ new file for Borland C/C++ Builder
(This file is NOT TESTED yet)
+ config/win32/icc.cf
+ new file for IBM Visual Age C++
(This file is NOT TESTED yet)
* makefile.b16
* makefile.b32
* makefile.icc
* makefile.vc
+ added source/rtl/memvars.c
* makedos.env
* added '-I.' switch for compiler flags
* source/compiler/harbour.l
- removed #include "./harboury.h" (it is now handled by makedos.env)
* source/tools/stringp.prg
* corrected bug in line 101 (':=' should be here instead of '+='
19990710-23:15 Alexander Kresin
* source\hbpp\hbpp.c
* fixed some bugs - now we can use classes.ch

View File

@@ -1,6 +1,8 @@
#
# $Id$
#
# The Harbour project
# GNU MAKE file for Watcom C/C++ 10.x
include $(TOP)$(ROOT)config/$(HB_ARCHITECTURE)/global.cf
@@ -33,7 +35,7 @@ $(COMSPEC) /E:2048 /Cecho $(LINKLIBS) >> __link__.tmp
endef
LD = wlink
LDFLAGS = debug all OP osn=DOS4G OP stack=16384
LDFLAGS = debug all OP osn=DOS4G OP stack=65536
LINKLIBS := LIBP $(subst /,\,$(HB_LIB_DIR)) $(foreach lib, $(LIBS), LIB $(lib))
LD_RULE = $(link_exe_file)

View File

@@ -0,0 +1,69 @@
#
# $Id$
#
# The Harbour Project
# GNU MAKE file for Borland C/C++ Builder
#
# This code is NOT TESTED yet! (19990711)
include $(TOP)$(ROOT)config/$(HB_ARCHITECTURE)/global.cf
OBJ_EXT = .obj
EXE_EXT = .exe
LIB_PREF =
LIB_EXT = .lib
$(HB_ARCHITECTURE)_$(HB_COMPILER)_GRANDP = $(subst /,\\,$(GRANDP))
_HB_INC_DIR = $(subst /,\\,$(HB_INC_DIR))
_HL = $(notdir $(HB_LIB_DIR))
ifeq ($(_HL),)
#there is an ending slash
_HB_LIB_DIR = $(subst /,\,$(HB_LIB_DIR))
else
_HB_LIB_DIR = $(subst /,\,$(HB_LIB_DIR)/)
endif
CC = bcc32
CC_IN = -c
CC_OUT = -o
CPPFLAGS = -O2
CFLAGS = -i. -i$(_HB_INC_DIR)
#Note: The empty line below HAVE TO exist!
define link_file
$(COMSPEC) /E:2048 /Cecho $(file) >> __link__.tmp
endef
define link_exe_file
$(COMSPEC) /E:2048 /Cecho $(LDFLAGS) -e$@ > __link__.tmp
$(foreach file, $^, $(link_file))
$(COMSPEC) /E:2048 /Cecho $(LINKLIBS) >> __link__.tmp
-$(LD) @__link__.tmp
endef
LD = bcc32
LDFLAGS = -O2
LINKLIBS = $(foreach lib, $(LIBS), $(_HB_LIB_DIR)$(lib))
LD_RULE = $(link_exe_file)
#Note: The empty line below HAVE TO exist!
define lib_object
echo -+$(file) >> __lib__.tmp
endef
define create_library
echo $@ > __lib__.tmp
$(foreach file, $^, $(lib_object))
$(AR) @__lib__.tmp
del __lib__.tmp
endef
AR = tlib
ARFLAGS =
AR_RULE = $(create_library)
include $(TOP)$(ROOT)config/rules.cf

View File

@@ -0,0 +1,68 @@
#
# $Id$
#
# The Harbour Project
# GNU MAKE file for IBM Visual Age for C++
#
# This code is NOT TESTED yet! (19990711)
include $(TOP)$(ROOT)config/$(HB_ARCHITECTURE)/global.cf
OBJ_EXT = .obj
EXE_EXT = .exe
LIB_PREF =
LIB_EXT = .lib
$(HB_ARCHITECTURE)_$(HB_COMPILER)_GRANDP = $(subst /,\\,$(GRANDP))
_HB_INC_DIR = $(subst /,\\,$(HB_INC_DIR))
_HL = $(notdir $(HB_LIB_DIR))
ifeq ($(_HL),)
#there is an ending slash
_HB_LIB_DIR = $(subst /,\,$(HB_LIB_DIR))
else
_HB_LIB_DIR = $(subst /,\,$(HB_LIB_DIR)/)
endif
CC = icc
CC_IN = /Tp
CC_OUT = /Fo
CPPFLAGS = /C+
CFLAGS = /W2 /Sd /Se+ /Ti+ /i. /i$(_HB_INC_DIR)
#Note: The empty line below HAVE TO exist!
define link_file
echo /fo$(file) >> __link__.tmp
endef
define link_exe_file
echo $(LDFLAGS) -Fe$@ > __link__.tmp
$(foreach file, $^, $(link_file))
echo $(LINKLIBS) >> __link__.tmp
-$(LD) @__link__.tmp
endef
LD = icc
LDFLAGS = $(CFLAGS)
LINKLIBS = $(foreach lib, $(LIBS), $(_HB_LIB_DIR)$(lib))
LD_RULE = $(link_exe_file)
#Note: The empty line below HAVE TO exist!
define lib_object
echo -+$(file) >> __lib__.tmp
endef
define create_library
echo $@ > __lib__.tmp
$(foreach file, $^, $(lib_object))
$(AR) @__lib__.tmp
del __lib__.tmp
endef
AR = ilib
ARFLAGS =
AR_RULE = $(create_library)
include $(TOP)$(ROOT)config/rules.cf

View File

@@ -3,7 +3,7 @@ Ryszard Glab <rglab@imid.med.pl>
The compilation of a codeblock.
During compile the codeblock is stored in the following form:
During compile time the codeblock is stored in the following form:
- the header
- the stream of pcode bytes
@@ -29,15 +29,14 @@ the table of local variables positions (copied from the header) is used.
The negative value is used as an index to distinguish it from the reference
to a codeblock parameter. The table of local variables positions is created
during creation of a codeblock (in PushBlock() function).
Detached locals.
If the codeblock is returned from a function and this codeblock refers to
local variables defined in that function then the position of local variable
stored in a codeblock is replaced with the current value of the variable.
In this way the value of local variable can be accessed even outside of the
function where the variable was declared. This proccess is also called
'detaching local variables'
During a codeblock creation, values of all local variables defined in a
procedure and accessed in a codeblock are replaced with a reference to
a value stored in a global memory variables pool. This allows to correct
access for detached local variables in a codeblock returned from this
function either directly (in RETURN statement) or indirectly (by assigning
it to a static or memvar variable). This automatic and unconditional
replace is required because there is no safe method to find if a codeblock
will be accessed from an outside of a function where it is created.
Incompatbility with the Clipper.

View File

@@ -64,14 +64,21 @@ void ProcessSymbols( SYMBOL *, WORD );
#define IT_MEMO ( IT_MEMOFLAG & IT_STRING )
#define IT_BLOCK 0x1000
#define IT_BYREF 0x2000
#define IT_MEMVAR 0x4000
#define IT_ARRAY 0x8000
#define IT_OBJECT IT_ARRAY
#define IT_NUMERIC ( IT_INTEGER | IT_LONG | IT_DOUBLE )
#define IT_ANY 0xFFFF
struct _HB_CODEBLOCK; /* forward declaration */
struct _HB_BASEARRAY; /* forward declaration */
/* forward declarations
*/
struct _HB_CODEBLOCK;
struct _HB_BASEARRAY;
struct _HB_ITEM;
struct _HB_VALUE;
/* Internal structures that holds data
*/
struct hb_struArray
{
struct _HB_BASEARRAY * value;
@@ -79,7 +86,7 @@ struct hb_struArray
struct hb_struBlock
{
LONG stackbase;
LONG statics;
WORD lineno;
WORD paramcnt;
struct _HB_CODEBLOCK * value;
@@ -118,14 +125,22 @@ struct hb_struLong
long value;
};
struct hb_struMemvar
{
struct _HB_VALUE * *itemsbase;
LONG offset;
LONG value;
};
struct hb_struPointer
{
void *value;
PVOID value;
};
struct hb_struRefer
{
LONG stackbase;
struct _HB_ITEM * *itemsbase;
LONG offset;
LONG value;
};
@@ -143,7 +158,7 @@ struct hb_struSymbol
PSYMBOL value;
};
typedef struct /* items hold at the virtual machine stack */
typedef struct _HB_ITEM /* items hold at the virtual machine stack */
{
WORD type;
union
@@ -155,6 +170,7 @@ typedef struct /* items hold at the virtual machine stack */
struct hb_struInteger asInteger;
struct hb_struLogical asLogical;
struct hb_struLong asLong;
struct hb_struMemvar asMemvar;
struct hb_struPointer asPointer;
struct hb_struRefer asRefer;
struct hb_struString asString;
@@ -162,6 +178,7 @@ typedef struct /* items hold at the virtual machine stack */
} item;
}
HB_ITEM, *PHB_ITEM;
typedef PHB_ITEM HB_ITEM_PTR;
typedef struct _HB_BASEARRAY
{
@@ -196,15 +213,19 @@ typedef struct
typedef struct _HB_CODEBLOCK
{
BYTE * pCode; /* codeblock pcode */
PHB_ITEM pItems; /* table with referenced local variables */
PHB_ITEM pLocals; /* table with referenced local variables */
WORD wLocals; /* number of referenced local variables */
WORD wDetached; /* holds if pItems table variables values */
PSYMBOL pSymbols; /* codeblocks symbols */
WORD wRefBase; /* stack frame position for referenced local variables */
int iStatBase; /* static base for function where CB was created */
long lCounter; /* numer of references to this codeblock */
ULONG lCounter; /* numer of references to this codeblock */
} HB_CODEBLOCK, * HB_CODEBLOCK_PTR;
typedef struct _HB_VALUE
{
HB_ITEM item;
ULONG counter;
PDYNSYM symbol;
} HB_VALUE, * HB_VALUE_PTR;
PHB_ITEM hb_param( int iParam, WORD wType ); /* retrieve a generic parameter */
char * hb_parc( int iParam, ... ); /* retrieve a string parameter */
@@ -232,11 +253,15 @@ void hb_retni( int iNumber ); /* returns a integer number */
void hb_retnl( long lNumber ); /* returns a long number */
void hb_retnd( double dNumber ); /* returns a double */
void hb_reta( ULONG ulLen ); /* returns an array with a specific length */
void * hb_xgrab( ULONG lSize ); /* allocates memory */
void * hb_xrealloc( void * pMem, ULONG lSize ); /* reallocates memory */
void hb_xfree( void * pMem ); /* frees memory */
void ItemCopy( PHB_ITEM pDest, PHB_ITEM pSource );
void ItemRelease( PHB_ITEM pItem );
PHB_ITEM ItemUnRef( PHB_ITEM pItem ); /* de-references passed variable */
void hb_arrayNew( PHB_ITEM pItem, ULONG ulLen ); /* creates a new array */
void hb_arrayGet( PHB_ITEM pArray, ULONG ulIndex, PHB_ITEM pItem ); /* retrieves an item */
ULONG hb_arrayLen( PHB_ITEM pArray ); /* retrives the array len */
@@ -266,4 +291,10 @@ PDYNSYM GetDynSym( char * szName ); /* finds and creates a dynamic symbol if
PDYNSYM NewDynSym( PSYMBOL pSymbol ); /* creates a new dynamic symbol based on a local one */
PDYNSYM FindDynSym( char * szName ); /* finds a dynamic symbol */
/* functions for memvar variables */
HANDLE hb_GlobalValueNew( PHB_ITEM );
void hb_GlobalValueIncRef( HANDLE );
void hb_GlobalValueDecRef( HANDLE );
HB_VALUE_PTR * hb_GlobalValueBaseAddress( void );
#endif /* HB_EXTEND_H_ */

View File

@@ -43,6 +43,9 @@ typedef int BOOL;
#undef PVOID
typedef void * PVOID;
#undef HANDLE
typedef USHORT HANDLE;
#define LOBYTE(w) ((BYTE)(w))
#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
#define LOWORD(l) ((WORD)(l))
@@ -87,6 +90,7 @@ typedef HARBOUR ( * HARBOURFUNC )( void );
#define IS_OBJECT( p ) IS_OF_TYPE( p, IT_ARRAY )
#define IS_STRING( p ) IS_OF_TYPE( p, IT_STRING )
#define IS_SYMBOL( p ) IS_OF_TYPE( p, IT_SYMBOL )
#define IS_MEMVAR( p ) IS_OF_TYPE( p, IT_MEMVAR )
#define PCOUNT hb_parinfo( 0 )

View File

@@ -32,7 +32,7 @@ void ProcessSymbols( SYMBOL * pSymbols, WORD wSymbols );
#ifdef HARBOUR_STRICT_ANSI_C
#define HB_INIT_SYMBOLS_BEGIN( func ) \
static SYMBOL symbols[] = {
static SYMBOL symbols[] = {
#define HB_INIT_SYMBOLS_END( func ) }; }; \
void func( void ) \
@@ -50,14 +50,14 @@ static SYMBOL symbols[] = {
static SYMBOL symbols[] = {
#define HB_INIT_SYMBOLS_END( func ) }; \
void __attribute__ ((constructor)) func( void ) \
static void __attribute__ ((constructor)) func( void ) \
{ \
ProcessSymbols( symbols, sizeof( symbols ) / sizeof( SYMBOL ) ); \
}
#define HB_CALL_ON_STARTUP_BEGIN( func ) \
void __attribute__ ((constructor)) func( void ) {
static void __attribute__ ((constructor)) func( void ) {
#define HB_CALL_ON_STARTUP_END( func ) }
#endif
@@ -68,13 +68,13 @@ static SYMBOL symbols[] = {
static SYMBOL symbols[] = {
#define HB_INIT_SYMBOLS_END( func ) }; \
void func( void ) \
static void func( void ) \
{ \
ProcessSymbols( symbols, sizeof( symbols ) / sizeof( SYMBOL ) ); \
}
#define HB_CALL_ON_STARTUP_BEGIN( func ) \
void func( void ) {
static void func( void ) {
#define HB_CALL_ON_STARTUP_END( func ) }
#endif
@@ -84,37 +84,37 @@ static SYMBOL symbols[] = {
static SYMBOL symbols[] = {
#define HB_INIT_SYMBOLS_END( func ) }; \
int func( void ) \
static int func( void ) \
{ \
ProcessSymbols( symbols, sizeof( symbols ) / sizeof( SYMBOL ) ); \
return 1; \
}; \
int static_int_##func = func()
static int static_int_##func = func()
#define HB_CALL_ON_STARTUP_BEGIN( func ) \
int func( void ) {
static int func( void ) {
#define HB_CALL_ON_STARTUP_END( func ) return 1; } \
int static_int_##func = func()
static int static_int_##func = func()
#endif
#ifdef __WATCOMC__
#define HB_INIT_SYMBOLS_BEGIN( func ) \
SYMBOL symbols[] = {
static SYMBOL symbols[] = {
#define HB_INIT_SYMBOLS_END( func ) }; \
int func( void ) \
static int func( void ) \
{ \
ProcessSymbols( symbols, sizeof( symbols ) / sizeof( SYMBOL ) ); \
return 1; \
}; \
int static_int_##func = func()
static int static_int_##func = func()
#define HB_CALL_ON_STARTUP_BEGIN( func ) \
int func( void ) {
static int func( void ) {
#define HB_CALL_ON_STARTUP_END( func ) return 1; }; \
int static_int_##func = func()
static int static_int_##func = func()
#endif
#endif /*HARBOUR_STRICT_ANSI_C */

View File

@@ -16,7 +16,7 @@ HARBOURLIB=$(HARBOURDIR)/libs/libharb.a
# compiler macros for DOS DJGPP
CC=gcc
CFLAGS=-Wall -g -DDEBUG -I$(HARBOURDIR)/include -x c
CFLAGS=-Wall -g -DDEBUG -I. -I$(HARBOURDIR)/include -x c
%.c : %.prg
../../bin/harbour -n -i$(HARBOURDIR)/include $<

View File

@@ -14,7 +14,7 @@ PROJECT: harbour.lib libs\b16\terminal.lib libs\win16\terminal.lib harbour.exe
harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj dates.obj datesx.obj \
debug.obj descend.obj devoutp.obj dynsym.obj environ.obj error.obj \
errorapi.obj errorsys.obj extend.obj files.obj \
hardcr.obj initsymb.obj itemapi.obj math.obj \
hardcr.obj initsymb.obj itemapi.obj math.obj memvars.obj \
mathx.obj mtran.obj objfunc.obj set.obj stringp.obj strings.obj \
stringsx.obj strcmp.obj tclass.obj transfrm.obj
@@ -49,6 +49,7 @@ initsymb.obj : initsymb.c extend.h hbdefs.h
itemapi.obj : itemapi.c extend.h hbdefs.h
math.obj : math.c extend.h hbdefs.h
mathx.obj : mathx.c extend.h hbdefs.h
memvars.obj : memvars.c extend.h hbdefs.h
mtran.obj : mtran.c extend.h hbdefs.h
objfunc.obj : objfunc.c extend.h hbdefs.h
set.obj : set.c extend.h hbdefs.h

View File

@@ -18,7 +18,7 @@ harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj copyfile.obj \
dates.obj descend.obj devoutp.obj dir.obj dynsym.obj environ.obj \
error.obj errorapi.obj errorsys.obj extend.obj \
files.obj gtapi.obj hardcr.obj initsymb.obj itemapi.obj \
math.obj mtran.obj msguk.obj objfunc.obj \
math.obj memvars.obj mtran.obj msguk.obj objfunc.obj \
set.obj strings.obj strcmp.obj symbols.obj tclass.obj \
transfrm.obj
@@ -60,6 +60,7 @@ gtapi.obj : gtapi.c extend.h hbdefs.h gtapi.h
hardcr.obj : hardcr.c extend.h hbdefs.h
itemapi.obj : itemapi.c extend.h hbdefs.h ctoharb.h itemapi.h set.h dates.h
math.obj : math.c extend.h hbdefs.h
memvars.obj : memvars.c extend.h hbdefs.h
mtran.obj : mtran.c extend.h hbdefs.h
objfunc.obj : objfunc.prg extend.h hbdefs.h init.h pcode.h
set.obj : set.c extend.h hbdefs.h set.h

View File

@@ -16,7 +16,7 @@ harbour.lib : arrays.obj asort.obj classes.obj codebloc.obj \
dates.obj datesx.obj debug.obj descend.obj devoutp.obj \
dir.obj dynsym.obj environ.obj error.obj \
errorapi.obj errorsys.obj extend.obj files.obj \
hardcr.obj hb_f.obj initsymb.obj itemapi.obj \
hardcr.obj hb_f.obj initsymb.obj itemapi.obj memvars.obj \
math.obj mathx.obj msguk.obj mtran.obj objfunc.obj set.obj \
symbols.obj strings.obj stringp.obj \
stringsx.obj strcmp.obj tclass.obj transfrm.obj copyfile.obj
@@ -46,6 +46,7 @@ hb_f.obj : hb_f.c extend.h hbdefs.h
initsymb.obj : initsymb.c extend.h hbdefs.h
itemapi.obj : itemapi.c extend.h hbdefs.h
math.obj : math.c extend.h hbdefs.h
memvars.obj : memvars.c extend.h hbdefs.h
mathx.obj : mathx.c extend.h hbdefs.h
msguk.obj : msguk.c extend.h hbdefs.h
mtran.obj : mtran.c extend.h hbdefs.h

View File

@@ -38,6 +38,7 @@ $(path_lib)\harbour.lib : \
$(path_obj)\initsymb.obj \
$(path_obj)\itemapi.obj \
$(path_obj)\math.obj \
$(path_obj)\memvars.obj \
$(path_obj)\msguk.obj \
$(path_obj)\mtran.obj \
$(path_obj)\objfunc.obj \
@@ -107,6 +108,7 @@ $(path_obj)\io.obj : {$(path_c)}io.c $(path_h)\extend.h $(path_h)\hb
$(path_obj)\initsymb.obj : {$(path_c)}initsymb.c $(path_h)\extend.h $(path_h)\hbdefs.h
$(path_obj)\itemapi.obj : {$(path_c)}itemapi.c $(path_h)\extend.h $(path_h)\hbdefs.h $(path_h)\itemapi.h $(path_h)\set.h $(path_h)\ctoharb.h $(path_h)\dates.h
$(path_obj)\math.obj : {$(path_c)}math.c $(path_h)\extend.h $(path_h)\hbdefs.h $(path_h)\errorapi.h $(path_h)\error.ch
$(path_obj)\memvars.obj : {$(path_c)}memvars.c $(path_h)\extend.h $(path_h)\hbdefs.h
$(path_obj)\mathx.obj : {$(path_c)}mathx.c $(path_h)\extend.h $(path_h)\hbdefs.h
$(path_obj)\mtran.obj : {$(path_c)}mtran.c $(path_h)\extend.h $(path_h)\hbdefs.h
$(path_obj)\set.obj : {$(path_c)}set.c $(path_h)\extend.h $(path_h)\hbdefs.h $(path_h)\set.h $(path_h)\errorapi.h $(path_h)\error.ch

View File

@@ -68,6 +68,7 @@ HARBOUR_LIB_OBJS = \
$(OBJ_DIR)\initsymb.obj \
$(OBJ_DIR)\itemapi.obj \
$(OBJ_DIR)\math.obj \
$(OBJ_DIR)\memvars.obj \
$(OBJ_DIR)\msguk.obj \
$(OBJ_DIR)\mtran.obj \
$(OBJ_DIR)\objfunc.obj \
@@ -243,6 +244,9 @@ $(OBJ_DIR)\itemapi.obj : $(RTL_DIR)\itemapi.c
$(OBJ_DIR)\math.obj : $(RTL_DIR)\math.c
$(CC) $(CLIBFLAGS) -Fo$@ $**
$(OBJ_DIR)\memvars.obj : $(RTL_DIR)\memvars.c
$(CC) $(CLIBFLAGS) -Fo$@ $**
$(OBJ_DIR)\msguk.obj : $(RTL_DIR)\natmsg\msguk.c
$(CC) $(CLIBFLAGS) -Fo$@ $**

View File

@@ -35,11 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#if __DJGPP__
#include "./harboury.h"
#else
#include "harboury.h"
#endif
#include "harboury.h"
#include "hbsetup.h" /* main configuration file */
#include "hberrors.h"
#include "hbdefs.h"

View File

@@ -22,6 +22,7 @@ C_SOURCES=\
hardcr.c \
itemapi.c \
math.c \
memvars.c \
mtran.c \
set.c \
strcmp.c \

View File

@@ -212,13 +212,13 @@ HARBOUR HB_CLASSADD(void)
pClass->wMethods++; /* One more message */
}
else
printf("\nOld %i\n",(long) pNewMeth->pFunction);
printf("\nOld %li\n",(long) pNewMeth->pFunction);
switch( wType )
{
case MET_METHOD:
pNewMeth->pFunction = ( HARBOURFUNC ) hb_parnl( 3 );
printf("\nPointer=%i\n",hb_parnl( 3 ));
printf("\nPointer=%li\n",hb_parnl( 3 ));
break;
case MET_DATA:
@@ -502,7 +502,7 @@ static HARBOUR ClassName( void )
PHB_ITEM pItemRef;
if( IS_BYREF( stack.pBase + 1 ) ) /* Variables by reference */
pItemRef = stack.pItems + ( stack.pBase + 1 )->item.asRefer.value;
pItemRef = ItemUnRef( stack.pBase + 1 );
else
pItemRef = stack.pBase + 1;
@@ -558,7 +558,7 @@ static HARBOUR ClassSel(void)
/* Variables by reference */
if( ( ! wClass ) && IS_BYREF( stack.pBase + 1 ) )
{
pItemRef = stack.pItems + ( stack.pBase + 1 )->item.asRefer.value;
pItemRef = ItemUnRef( stack.pBase + 1 );
if( IS_ARRAY( pItemRef ) )
wClass = pItemRef->item.asArray.value->wClass;
}

View File

@@ -1,6 +1,37 @@
/*
* $Id$
*/
*
Harbour Project source code
This file is a part of Harbour Runtime Library and it contains code
that handles codeblocks
Copyright (C) 1999 Ryszard Glab
www - http://www.harbour-project.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version, with one exception:
The exception is that if you link the Harbour Runtime Library (HRL)
and/or the Harbour Virtual Machine (HVM) with other files to produce
an executable, this does not by itself cause the resulting executable
to be covered by the GNU General Public License. Your use of that
executable is in no way restricted on account of linking the HRL
and/or HVM code into it.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
their web site at http://www.gnu.org/).
*/
/* The Harbour implementation of codeblocks */
@@ -18,177 +49,176 @@ extern STACK stack;
/* Creates the codeblock structure
*
* The buffer should contain:
* +0 bytes -> number of referenced local variables
* +2 bytes -> table of referenced local variables
* +2 + 2 *(number of referenced variables) -> codeblock pcode
* pBuffer -> the buffer with pcodes (without HB_P_PUSHBLOCK)
* wLocals -> number of local variables referenced in a codeblock
* pLocalPosTable -> a table with positions on eval stack for referenced variables
* pSymbols -> a pointer to the module symbol table
*
* Note: pLocalPosTable cannot be used if wLocals is ZERO
*
*/
HB_CODEBLOCK_PTR CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols,
int iStaticsBase, WORD wStackBase )
HB_CODEBLOCK_PTR hb_CodeblockNew( BYTE * pBuffer,
WORD wLocals,
WORD *pLocalPosTable,
PSYMBOL pSymbols )
{
HB_CODEBLOCK_PTR pCBlock;
WORD wVars;
pCBlock =( HB_CODEBLOCK_PTR ) hb_xgrab( sizeof(HB_CODEBLOCK) );
/* Check the number of referenced local variables
/* Store the number of referenced local variables
*/
wVars = * ( (WORD *) pBuffer );
wSize -= ( wVars + 1 ) * 2;
pBuffer +=2;
pCBlock->wLocals =wVars;
if( wVars )
pCBlock->wLocals =wLocals;
if( wLocals )
{
WORD w = 0;
/* Create the table with references to local variables
* If this codeblock will be exported from a function then
* all references will be replaced with current values of
* these variables
/* NOTE: if a codeblock will be created by macro compiler then
* wLocal have to be ZERO
*/
pCBlock->pItems =(PHB_ITEM) hb_xgrab( sizeof(HB_ITEM) * wVars );
WORD w = 0;
PHB_ITEM pLocal;
HANDLE hGlobal;
while( wVars-- )
/* Create a table that will store the values of local variables
* accessed in a codeblock
*/
pCBlock->pLocals =(PHB_ITEM) hb_xgrab( wLocals * sizeof(HB_ITEM) );
while( wLocals-- )
{
pCBlock->pItems[ w ].type =IT_BYREF; /* not really integer */
pCBlock->pItems[ w ].item.asRefer.value = * ( (WORD*) pBuffer );
/* Swap the current value of local variable with the reference to this
* value.
* TODO: If Harbour will support threads in the future then we need
* to implement some kind of semaphores here.
*/
pLocal =stack.pBase +1 +(*pLocalPosTable++);
if( ! IS_MEMVAR( pLocal ) )
{
/* Change the value only if this variable is not referenced
* by another codeblock yet.
* In this case we have to copy the current value to a global memory
* pool so it can be shared by codeblocks
*/
hGlobal =hb_GlobalValueNew( pLocal );
pLocal->type =IT_BYREF | IT_MEMVAR;
pLocal->item.asMemvar.itemsbase =hb_GlobalValueBaseAddress();
pLocal->item.asMemvar.offset =0;
pLocal->item.asMemvar.value =hGlobal;
hb_GlobalValueIncRef( pLocal->item.asMemvar.value );
memcpy( pCBlock->pLocals + w, pLocal, sizeof(HB_ITEM) );
}
else
{
/* This variable is already detached (by another codeblock)
* - copy the reference to a value
*/
/* Increment the reference counter so this value will not be
* released if other codeblock will be deleted
*/
hb_GlobalValueIncRef( pLocal->item.asMemvar.value );
memcpy( pCBlock->pLocals + w, pLocal, sizeof(HB_ITEM) );
}
++w;
pBuffer +=2;
}
}
else
pCBlock->pItems =NULL;
pCBlock->pLocals =NULL;
/* the codeblock initally contains references to local variables
*/
pCBlock->wDetached =FALSE;
/*
* pcode is stored in static segment now.
* The codeblock pcode is stored in static segment.
* The only allowed operation on a codeblock is evaluating it then
* there is no need to duplicate its pcode -just store the pointer to it
* there is no need to duplicate its pcode - just store the pointer to it
*/
pCBlock->pCode = pBuffer;
pCBlock->pSymbols =pSymbols;
pCBlock->wDetached =FALSE;
pCBlock->lCounter =1;
pCBlock->iStatBase =iStaticsBase;
/*
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
* at the time of codeblock evaluation.
*/
pCBlock->wRefBase =wStackBase;
#ifdef CODEBLOCKDEBUG
printf( "codeblock created (%li) %lx\n", pCBlock->lCounter, pCBlock );
printf( "\ncodeblock created (%li) %lx", pCBlock->lCounter, pCBlock );
#endif
return pCBlock;
}
/* Delete a codeblock
*/
void CodeblockDelete( HB_CODEBLOCK_PTR pCBlock )
void hb_CodeblockDelete( HB_ITEM_PTR pItem )
{
HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value;
#ifdef CODEBLOCKDEBUG
printf( "delete a codeblock (%li) %lx\n", pCBlock->lCounter, pCBlock );
printf( "\ndelete a codeblock (%li) %lx", pCBlock->lCounter, pCBlock );
#endif
if( --pCBlock->lCounter == 0 )
{
WORD w = 0;
if( --pCBlock->lCounter == 0 )
{
/* free space allocated for local variables
*/
if( pCBlock->pLocals )
{
WORD w = 0;
while( w < pCBlock->wLocals )
{
hb_GlobalValueDecRef( pCBlock->pLocals[ w ].item.asMemvar.value );
++w;
}
hb_xfree( pCBlock->pLocals );
}
/* free space allocated for local variables
*/
if( pCBlock->pItems )
{
while( w < pCBlock->wLocals )
ItemRelease( &pCBlock->pItems[ w++ ] );
hb_xfree( pCBlock->pItems );
}
/* free space allocated for a CODEBLOCK structure
*/
hb_xfree( pCBlock );
#ifdef CODEBLOCKDEBUG
printf( "codeblock deleted (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
}
}
/* Function to unlink variables referenced in a codeblock from a function
* where this codeblock was created
*/
void CodeblockDetach( HB_CODEBLOCK_PTR pCBlock )
{
if( pCBlock->wLocals && !pCBlock->wDetached )
{
/* this codeblock refers to local variables */
WORD w = 0;
PHB_ITEM pItem;
while( w < pCBlock->wLocals )
{
/* replace the position of local variable on the stack with
* it's current value
* stack.pBase still points to a stack frame of function
* where this codeblock was defined
*/
pItem =pCBlock->pItems + w;
pItem =stack.pBase +pItem->item.asRefer.value + 1;
if( IS_BYREF( pItem ) )
pItem =stack.pItems +pItem->item.asRefer.value;
ItemCopy( pCBlock->pItems + w, pItem );
++w;
}
pCBlock->wDetached =TRUE;
}
#ifdef CODEBLOCKDEBUG
printf( "codeblock detached(%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
/* free space allocated for a CODEBLOCK structure
*/
hb_xfree( pCBlock );
#ifdef CODEBLOCKDEBUG
printf( "\ncodeblock deleted (%li) %lx", pCBlock->lCounter, pCBlock );
#endif
}
}
/* Evaluate passed codeblock
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
* Before evaluation we have to switch to a static variable base that
* was defined when the codeblock was created.
* (The codeblock can only see the static variables defined in a module
* where the codeblock was created)
*/
void CodeblockEvaluate( HB_CODEBLOCK_PTR pCBlock )
void hb_CodeblockEvaluate( HB_ITEM_PTR pItem )
{
int iStatics = stack.iStatics;
stack.iStatics = pCBlock->iStatBase;
VirtualMachine( pCBlock->pCode, pCBlock->pSymbols );
stack.iStatics = pItem->item.asBlock.statics;
VirtualMachine( pItem->item.asBlock.value->pCode, pItem->item.asBlock.value->pSymbols );
stack.iStatics = iStatics;
}
/* Get local variable referenced in a codeblock
*/
PHB_ITEM CodeblockGetVar( PHB_ITEM pItem, LONG iItemPos )
PHB_ITEM hb_CodeblockGetVar( PHB_ITEM pItem, LONG iItemPos )
{
HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value;
/* local variables accessed in a codeblock are always stored as reference */
return ItemUnRef( pCBlock->pLocals -iItemPos -1 );
}
/* Get local variable passed by reference
*/
PHB_ITEM hb_CodeblockGetRef( PHB_ITEM pItem, PHB_ITEM pRefer )
{
HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value;
PHB_ITEM pLocalVar;
pLocalVar =&pCBlock->pItems[ -iItemPos -1 ];
/* if a codeblock have detached local variables then it stores their value */
if( !pCBlock->wDetached )
{
/* when variables are not detached then a codeblock stores the variable's
* position on the stack
*/
pLocalVar =stack.pItems +pCBlock->wRefBase +pLocalVar->item.asRefer.value + 1;
}
return pLocalVar;
return pCBlock->pLocals -pRefer->item.asRefer.value -1;
}
/* Copy the codeblock
* TODO: check if such simple pointer coping will allow to evaluate
* codeblocks recursively
*/
void CodeblockCopy( PHB_ITEM pDest, PHB_ITEM pSource )
void hb_CodeblockCopy( PHB_ITEM pDest, PHB_ITEM pSource )
{
pDest->item.asBlock.value =pSource->item.asBlock.value;
pDest->item.asBlock.value->lCounter++;
#ifdef CODEBLOCKDEBUG
printf( "copy a codeblock (%li) %lx\n", pDest->item.asBlock.valuevalue->lCounter, pDest->item.asBlock.valuevalue);
printf( "\ncopy a codeblock (%li) %lx", pSource->item.asBlock.value->lCounter, pSource->item.asBlock.value );
#endif
}

View File

@@ -44,28 +44,28 @@ PHB_ITEM hb_param( int iParam, WORD wMask )
if( ( iParam <= hb_pcount() ) || ( iParam == -1 ) )
{
if( iParam == -1 )
wType = stack.Return.type;
wType = stack.Return.type;
else if( iParam < -1 )
return 0;
return 0;
else
wType = ( stack.pBase + 1 + iParam )->type;
wType = ( stack.pBase + 1 + iParam )->type;
if( ( wType & wMask ) || ( wType == IT_NIL && wMask == IT_ANY ) )
{
if( iParam == -1 )
pLocal = &stack.Return;
else if( iParam < -1 )
return 0;
else
pLocal = stack.pBase + 1 + iParam;
if( iParam == -1 )
pLocal = &stack.Return;
else if( iParam < -1 )
return 0;
else
pLocal = stack.pBase + 1 + iParam;
if( wType & IT_BYREF )
return stack.pItems + pLocal->item.asRefer.value;
else
return pLocal;
if( wType & IT_BYREF )
return ItemUnRef( pLocal );
else
return pLocal;
}
else
return 0;
return 0;
}
return 0;
}
@@ -83,27 +83,27 @@ char * hb_parc( int iParam, ... )
if( ( iParam <= hb_pcount() ) || ( iParam == -1 ) )
{
if( iParam == -1 )
pItem = &stack.Return;
pItem = &stack.Return;
else if( iParam < -1 )
return "";
return "";
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
if( wArrayIndex )
return hb_arrayGetString( pItem, wArrayIndex );
else
return "";
if( wArrayIndex )
return hb_arrayGetString( pItem, wArrayIndex );
else
return "";
}
else if( IS_STRING( pItem ) )
return pItem->item.asString.value;
return pItem->item.asString.value;
else
return "";
return "";
}
return "";
}
@@ -127,8 +127,8 @@ ULONG hb_parclen( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
@@ -166,8 +166,8 @@ char * hb_pards( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
@@ -175,7 +175,7 @@ char * hb_pards( int iParam, ... )
return strcpy( stack.szDate, hb_arrayGetDate( pItem, wArrayIndex ) );
else
return " ";
}
}
else if( IS_DATE( pItem ) && pItem->item.asDate.value > 0 )
{
@@ -220,8 +220,8 @@ int hb_parl( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
@@ -230,7 +230,7 @@ int hb_parl( int iParam, ... )
else
return 0;
}
else if( IS_LOGICAL( pItem ) )
return pItem->item.asLogical.value;
@@ -259,8 +259,8 @@ double hb_parnd( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
@@ -303,9 +303,9 @@ int hb_parni( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
if( wArrayIndex )
@@ -348,8 +348,8 @@ long hb_parnl( int iParam, ... )
else
pItem = stack.pBase + 1 + iParam;
if( pItem->type & IT_BYREF )
pItem = stack.pItems + pItem->item.asRefer.value;
if( IS_BYREF( pItem ) )
pItem = ItemUnRef( pItem );
if( IS_ARRAY( pItem ) )
{
@@ -526,39 +526,39 @@ void hb_storc( char * szText, int iParam, ... )
{
if( iParam == -1 )
{
pItem = &stack.Return;
ulLen = strlen( szText );
ItemRelease( pItem );
pItem->type = IT_STRING;
pItem->item.asString.length = ulLen;
pItem->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItem->item.asString.value, szText );
pItem = &stack.Return;
ulLen = strlen( szText );
ItemRelease( pItem );
pItem->type = IT_STRING;
pItem->item.asString.length = ulLen;
pItem->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItem->item.asString.value, szText );
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
ulLen = strlen( szText );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = ulLen;
pItemRef->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItemRef->item.asString.value, szText );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
ulLen = strlen( szText );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = ulLen;
pItemRef->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItemRef->item.asString.value, szText );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
ulLen = strlen( szText );
pItemRef = stack.pItems + pItem->item.asRefer.value;
ItemRelease( pItemRef );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = ulLen;
pItemRef->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItemRef->item.asString.value, szText );
ulLen = strlen( szText );
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = ulLen;
pItemRef->item.asString.value = ( char * ) hb_xgrab( ulLen + 1 );
strcpy( pItemRef->item.asString.value, szText );
}
}
}
@@ -577,39 +577,39 @@ void hb_storclen( char * fixText, WORD wLength, int iParam, ... )
{
if( iParam == -1 )
{
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_STRING;
pItem->item.asString.length = wLength;
pItem->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItem->item.asString.value, fixText, wLength );
pItem->item.asString.value[ wLength ] = '\0';
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_STRING;
pItem->item.asString.length = wLength;
pItem->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItem->item.asString.value, fixText, wLength );
pItem->item.asString.value[ wLength ] = '\0';
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = wLength;
pItemRef->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItemRef->item.asString.value, fixText, wLength );
pItemRef->item.asString.value[ wLength ] = '\0';
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = wLength;
pItemRef->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItemRef->item.asString.value, fixText, wLength );
pItemRef->item.asString.value[ wLength ] = '\0';
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
ItemRelease( pItemRef );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = wLength;
pItemRef->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItemRef->item.asString.value, fixText, wLength );
pItemRef->item.asString.value[ wLength ] = '\0';
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_STRING;
pItemRef->item.asString.length = wLength;
pItemRef->item.asString.value = ( char * ) hb_xgrab( wLength + 1 );
memcpy( pItemRef->item.asString.value, fixText, wLength );
pItemRef->item.asString.value[ wLength ] = '\0';
}
}
}
@@ -640,33 +640,33 @@ void hb_stords( char * szDate, int iParam, ... ) /* szDate must have yyyymmdd fo
{
if( iParam == -1 )
{
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_DATE;
pItem->item.asDate.length = 8;
pItem->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_DATE;
pItem->item.asDate.length = 8;
pItem->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_DATE;
pItemRef->item.asDate.length = 8;
pItemRef->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_DATE;
pItemRef->item.asDate.length = 8;
pItemRef->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
ItemRelease( pItemRef );
pItemRef->type = IT_DATE;
pItemRef->item.asDate.length = 8;
pItemRef->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_DATE;
pItemRef->item.asDate.length = 8;
pItemRef->item.asDate.value = hb_dateEncode( lDay, lMonth, lYear );
}
}
}
@@ -698,20 +698,20 @@ void hb_storl( int iLogical, int iParam, ... )
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_LOGICAL;
pItemRef->item.asLogical.length = 3;
pItemRef->item.asLogical.value = iLogical;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_LOGICAL;
pItemRef->item.asLogical.length = 3;
pItemRef->item.asLogical.value = iLogical;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
ItemRelease( pItemRef );
pItemRef->type = IT_LOGICAL;
pItemRef->item.asLogical.length = 3;
pItemRef->item.asLogical.value = iLogical;
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_LOGICAL;
pItemRef->item.asLogical.length = 3;
pItemRef->item.asLogical.value = iLogical;
}
}
}
@@ -730,31 +730,31 @@ void hb_storni( int iValue, int iParam, ... )
{
if( iParam == -1 )
{
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_INTEGER;
pItem->item.asInteger.length = 10;
pItem->item.asInteger.decimal = 0;
pItem->item.asInteger.value = iValue;
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_INTEGER;
pItem->item.asInteger.length = 10;
pItem->item.asInteger.decimal = 0;
pItem->item.asInteger.value = iValue;
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_INTEGER;
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_INTEGER;
pItemRef->item.asInteger.length = 10;
pItemRef->item.asInteger.decimal = 0;
pItemRef->item.asInteger.value = iValue;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_INTEGER;
pItemRef->item.asInteger.length = 10;
@@ -778,32 +778,32 @@ void hb_stornl( long lValue, int iParam, ... )
{
if( iParam == -1 )
{
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_LONG;
pItem->item.asLong.length = 10;
pItem->item.asLong.decimal = 0;
pItem->item.asLong.value = lValue;
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_LONG;
pItem->item.asLong.length = 10;
pItem->item.asLong.decimal = 0;
pItem->item.asLong.value = lValue;
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_LONG;
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_LONG;
pItemRef->item.asLong.length = 10;
pItemRef->item.asLong.decimal = 0;
pItemRef->item.asLong.value = lValue;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
ItemRelease( pItemRef );
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_LONG;
pItemRef->item.asLong.length = 10;
pItemRef->item.asLong.decimal = 0;
@@ -826,37 +826,37 @@ void hb_stornd( double dValue, int iParam, ... )
{
if( iParam == -1 )
{
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_DOUBLE;
if( dValue > 10000000000.0 )
pItem->item.asDouble.length = 20;
else
pItem->item.asDouble.length = 10;
pItem->item.asDouble.decimal = hb_set.HB_SET_DECIMALS;
pItem->item.asDouble.value = dValue;
pItem = &stack.Return;
ItemRelease( pItem );
pItem->type = IT_DOUBLE;
if( dValue > 10000000000.0 )
pItem->item.asDouble.length = 20;
else
pItem->item.asDouble.length = 10;
pItem->item.asDouble.decimal = hb_set.HB_SET_DECIMALS;
pItem->item.asDouble.value = dValue;
}
else if( iParam < -1 )
return;
return;
else
pItem = stack.pBase + 1 + iParam;
pItem = stack.pBase + 1 + iParam;
if( IS_ARRAY( pItem ) && wArrayIndex )
{
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_DOUBLE;
if( dValue > 10000000000.0 )
pItemRef->item.asDouble.length = 20;
else
pItemRef->item.asDouble.length = 10;
pItemRef->item.asDouble.decimal = hb_set.HB_SET_DECIMALS;
pItemRef->item.asDouble.value = dValue;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
pItemRef = hb_itemNew( NULL );
pItemRef->type = IT_DOUBLE;
if( dValue > 10000000000.0 )
pItemRef->item.asDouble.length = 20;
else
pItemRef->item.asDouble.length = 10;
pItemRef->item.asDouble.decimal = hb_set.HB_SET_DECIMALS;
pItemRef->item.asDouble.value = dValue;
hb_arraySet( pItem, wArrayIndex, pItemRef );
hb_itemRelease( pItemRef );
}
else if( IS_BYREF( pItem ) )
{
pItemRef = stack.pItems + pItem->item.asRefer.value;
pItemRef = ItemUnRef( pItem );
ItemRelease( pItemRef );
pItemRef->type = IT_DOUBLE;
if( dValue > 10000000000.0 )

View File

@@ -0,0 +1,209 @@
/*
* $Id$
*
Harbour Project source code
This file is a part of Harbour Runtime Library and it contains code
that handles memory variables.
Copyright (C) 1999 Ryszard Glab
www - http://www.harbour-project.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version, with one exception:
The exception is that if you link the Harbour Runtime Library (HRL)
and/or the Harbour Virtual Machine (HVM) with other files to produce
an executable, this does not by itself cause the resulting executable
to be covered by the GNU General Public License. Your use of that
executable is in no way restricted on account of linking the HRL
and/or HVM code into it.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
their web site at http://www.gnu.org/).
*/
#include <extend.h>
#include <string.h>
/* static HB_VALUE_PTR _privateTable = NULL; */
static ULONG _globalTableSize = 0;
static ULONG _globalFirstFree = 0;
static ULONG _globalLastFree = 0;
static ULONG _globalFreeCnt = 0;
static HB_VALUE_PTR _globalTable = NULL;
#define TABLE_INITHB_VALUE 10
#define TABLE_EXPANDHB_VALUE 5
/* Uncomment this to trace codeblocks activity
#define MEMVARDEBUG
*/
void hb_MemvarInit( void )
{
}
void hb_MemvarRelease( void )
{
if( _globalTable )
hb_xfree( _globalTable );
}
HB_VALUE_PTR *hb_GlobalValueBaseAddress( void )
{
return &_globalTable;
}
/*
* This function creates new global value.
*
* pSource = item value that have to be stored or NULL
* pOwner = the name of PUBLIC variable or NULL
*
* Returns:
* handle to variable memory or fails
*
*/
HANDLE hb_GlobalValueNew( HB_ITEM_PTR pSource )
{
HB_VALUE_PTR pValue;
HANDLE hValue;
if( ! _globalTable )
{
_globalTable = (HB_VALUE_PTR) hb_xgrab( sizeof(HB_VALUE) * TABLE_INITHB_VALUE );
_globalTableSize = TABLE_INITHB_VALUE;
_globalFreeCnt = 0;
_globalFirstFree = _globalLastFree = 1;
hValue = 0;
}
else
{
if( _globalFreeCnt )
{
/* There are holes in the table
* Get a first available hole
*/
hValue =_globalFirstFree;
--_globalFreeCnt;
/* Now find the next hole
*/
if( _globalFreeCnt )
{
while( _globalTable[ ++_globalFirstFree ].counter );
}
else
/* No more holes
*/
_globalFirstFree =_globalLastFree;
}
else
{
/* Allocate the value from the end of table
*/
if( _globalFirstFree < _globalTableSize )
{
hValue =_globalFirstFree;
_globalFirstFree = ++_globalLastFree;
}
else
{
/* No more free values in the table - expand the table
*/
hValue = _globalTableSize;
_globalFirstFree =_globalLastFree = _globalTableSize +1;
_globalTableSize += TABLE_EXPANDHB_VALUE;
_globalTable =(HB_VALUE_PTR) hb_xrealloc( _globalTable, sizeof(HB_VALUE) * _globalTableSize );
}
}
}
pValue =_globalTable + hValue;
if( pSource )
memcpy( &pValue->item, pSource, sizeof(HB_ITEM) );
else
pValue->item.type =IT_NIL;
pValue->counter =1;
#ifdef MEMVARDEBUG
printf( "\n>>>>>Global item created with handle =%i", hValue );
#endif
return hValue;
}
/*
* This function increases the number of references to passed global value
*
*/
void hb_GlobalValueIncRef( HANDLE hValue )
{
#ifdef MEMVARDEBUG
if( hValue < 0 || hValue > _globalTableSize )
{
printf( "\nInvalid MEMVAR handle %i (max %li)\n", hValue, _globalTableSize );
exit( 1 );
}
#endif
_globalTable[ hValue ].counter++;
#ifdef MEMVARDEBUG
printf( "\n+++Global item (%i) increment refCounter=%li", hValue, _globalTable[ hValue ].counter );
#endif
}
/*
* This function decreases the number of references to passed global value.
* If it is the last reference then this value is deleted.
*
*/
void hb_GlobalValueDecRef( HANDLE hValue )
{
HB_VALUE_PTR pValue;
#ifdef MEMVARDEBUG
if( hValue < 0 || hValue > _globalTableSize )
{
printf( "\nInvalid MEMVAR handle %i (max %li)\n", hValue, _globalTableSize );
exit( 1 );
}
#endif
pValue =_globalTable + hValue;
#ifdef MEMVARDEBUG
printf( "\n---Global item (%i) decrement refCounter=%li", hValue, pValue->counter-1 );
#endif
if( --pValue->counter == 0 )
{
ItemRelease( &pValue->item );
if( _globalFirstFree > hValue )
_globalFirstFree = hValue;
if( (_globalLastFree - hValue) == 1 )
_globalLastFree =hValue;
if( _globalFirstFree != _globalLastFree )
++_globalFreeCnt;
#ifdef MEMVARDEBUG
printf( "\n<<<<<Global item (%i) deleted", hValue );
#endif
}
}

View File

@@ -98,7 +98,7 @@ function ToChar( xTxt, cSeparator, lDebug )
case cValTxt=="A" // Array
if lDebug
cOut += "{"
cOut := "{"
else
cOut := ""
endif

View File

@@ -79,6 +79,7 @@ void GreaterEqual( void ); /* checks if the latest - 1 value is greater than
void Inc( void ); /* increment the latest numeric value on the stack */
void Instring( void ); /* check whether string 1 is contained in string 2 */
void ItemCopy( PHB_ITEM pDest, PHB_ITEM pSource ); /* copies an item to one place to another respecting its containts */
PHB_ITEM ItemUnRef( PHB_ITEM pItem ); /* de-references passed variable */
void Less( void ); /* checks if the latest - 1 value is less than the latest, removes both and leaves result */
void LessEqual( void ); /* checks if the latest - 1 value is less than or equal the latest, removes both and leaves result */
void Line( WORD wLine ); /* keeps track of the currently processed PRG line */
@@ -101,7 +102,7 @@ double PopNumber( void ); /* pops the stack latest value and returns it
void PopStatic( WORD wStatic ); /* pops the stack latest value onto a static */
void Power( void ); /* power the latest two values on the stack, removes them and leaves the result */
void Push( PHB_ITEM pItem ); /* pushes a generic item onto the stack */
void PushBlock( BYTE * pCode, WORD wSize, WORD wParam, PSYMBOL pSymbols ); /* creates a codeblock */
void PushBlock( BYTE * pCode, PSYMBOL pSymbols ); /* creates a codeblock */
void PushDate( LONG lDate ); /* pushes a long date onto the stack */
void PushDouble( double lNumber, WORD wDec ); /* pushes a double number onto the stack */
void PushLocal( SHORT iLocal ); /* pushes the containts of a local onto the stack */
@@ -111,6 +112,7 @@ void PushLong( long lNumber ); /* pushes a long number onto the stack */
void PushNil( void ); /* in this case it places nil at self */
void PushNumber( double dNumber, WORD wDec ); /* pushes a number on to the stack and decides if it is integer, long or double */
void PushStatic( WORD wStatic ); /* pushes the containts of a static onto the stack */
void PushStaticByRef( WORD iLocal ); /* pushes a static by refrence onto the stack */
void PushString( char * szText, ULONG length ); /* pushes a string on to the stack */
void PushSymbol( PSYMBOL pSym ); /* pushes a function pointer onto the stack */
void PushInteger( int iNumber ); /* pushes a integer number onto the stack */
@@ -140,12 +142,16 @@ void StackPush( void ); /* pushes an item on to the stack */
void StackInit( void ); /* initializes the stack */
void StackShow( void ); /* show the types of the items on the stack for debugging purposes */
HB_CODEBLOCK_PTR CodeblockNew( BYTE *, WORD, PSYMBOL, int, WORD );
void CodeblockDelete( HB_CODEBLOCK_PTR );
PHB_ITEM CodeblockGetVar( PHB_ITEM, LONG );
void CodeblockEvaluate( HB_CODEBLOCK_PTR );
void CodeblockCopy( PHB_ITEM, PHB_ITEM );
void CodeblockDetach( HB_CODEBLOCK_PTR );
HB_CODEBLOCK_PTR hb_CodeblockNew( BYTE *, WORD, WORD *, PSYMBOL );
void hb_CodeblockDelete( PHB_ITEM );
PHB_ITEM hb_CodeblockGetVar( PHB_ITEM, LONG );
PHB_ITEM hb_CodeblockGetRef( PHB_ITEM, PHB_ITEM );
void hb_CodeblockEvaluate( PHB_ITEM );
void hb_CodeblockCopy( PHB_ITEM, PHB_ITEM );
/* Initialisation and closing memvars subsystem */
void hb_MemvarInit( void );
void hb_MemvarRelease( void );
void InitSymbolTable( void ); /* initialization of runtime support symbols */
@@ -179,8 +185,9 @@ extern POBJSYMBOLS HB_FIRSTSYMBOL, HB_LASTSYMBOL;
#endif
#endif
STACK stack;
int iHB_DEBUG = 0; /* if 1 traces the virtual machine activity */
STACK stack;
SYMBOL symEval = { "__EVAL", FS_PUBLIC, DoBlock, 0 }; /* symbol to evaluate codeblocks */
PSYMBOL pSymStart; /* start symbol of the application. MAIN() is not required */
HB_ITEM aStatics; /* Harbour array to hold all application statics variables */
@@ -216,6 +223,7 @@ BYTE bErrorLevel = 0; /* application exit errorlevel */
StackInit();
NewDynSym( &symEval ); /* initialize dynamic symbol for evaluating codeblocks */
hb_setInitialize(); /* initialize Sets */
hb_MemvarInit();
/* InitializeConsole(); initialize Console */
#ifdef HARBOUR_OBJ_GENERATION
ProcessObjSymbols(); /* initialize Harbour generated OBJs symbols */
@@ -257,6 +265,7 @@ BYTE bErrorLevel = 0; /* application exit errorlevel */
ReleaseLocalSymbols(); /* releases the local modules linked list */
ReleaseDynamicSymbols(); /* releases the dynamic symbol table */
hb_setRelease(); /* releases Sets */
hb_MemvarRelease();
StackFree();
/* LogSymbols(); */
HB_DEBUG( "Done!\n" );
@@ -476,11 +485,6 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols )
w++;
break;
case HB_P_POPDEFSTAT:
PopDefStat( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) );
w += 3;
break;
case HB_P_POPLOCAL:
PopLocal( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) );
w += 3;
@@ -503,12 +507,8 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols )
* +5 +6 -> number of referenced local variables
* +7 -> start of table with referenced local variables
*/
wSize = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 );
PushBlock( pCode + w + 5,
wSize - 5,
pCode[ w + 3 ] + ( pCode[ w + 4 ] * 256 ),
pSymbols );
w += wSize;
PushBlock( pCode + w, pSymbols );
w += (pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ));
break;
case HB_P_PUSHDOUBLE:
@@ -551,6 +551,11 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols )
w += 3;
break;
case HB_P_PUSHSTATICREF:
PushStaticByRef( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) );
w += 3;
break;
case HB_P_PUSHSTR:
wSize =*( (WORD *) &( pCode[ w + 1 ] ) );
PushString( (char*)pCode + w + 3, wSize );
@@ -779,7 +784,7 @@ HARBOUR DoBlock( void )
*/
stack.pBase->item.asSymbol.lineno =pBlock->item.asBlock.lineno;
CodeblockEvaluate( pBlock->item.asBlock.value );
hb_CodeblockEvaluate( pBlock );
/* restore stack pointers */
stack.pBase = stack.pItems + wStackBase;
@@ -1101,8 +1106,11 @@ void ItemRelease( PHB_ITEM pItem )
}
else if( IS_BLOCK( pItem ) )
{
CodeblockDelete( pItem->item.asBlock.value );
hb_CodeblockDelete( pItem );
}
else if( IS_MEMVAR( pItem ) )
hb_GlobalValueDecRef( pItem->item.asMemvar.value );
pItem->type = IT_NIL;
}
@@ -1154,10 +1162,48 @@ void ItemCopy( PHB_ITEM pDest, PHB_ITEM pSource )
else if( IS_BLOCK( pSource ) )
{
CodeblockCopy( pDest, pSource );
hb_CodeblockCopy( pDest, pSource );
}
else if( IS_MEMVAR( pSource ) )
{
hb_GlobalValueIncRef( pSource->item.asMemvar.value );
}
}
/* De-references item passed by the reference
*
*/
PHB_ITEM ItemUnRef( PHB_ITEM pItem )
{
while( IS_BYREF( pItem ) )
{
if( IS_MEMVAR( pItem ) )
{
HB_VALUE_PTR pValue;
pValue =*(pItem->item.asMemvar.itemsbase) + pItem->item.asMemvar.offset +
pItem->item.asMemvar.value;
pItem =&pValue->item;
}
else
{
if( pItem->item.asRefer.value >= 0 )
pItem =*(pItem->item.asRefer.itemsbase) + pItem->item.asRefer.offset +
pItem->item.asRefer.value;
else
{
/* local variable referenced in a codeblock
*/
pItem =hb_CodeblockGetRef( *(pItem->item.asRefer.itemsbase) + pItem->item.asRefer.offset,
pItem );
}
}
}
return pItem;
}
void Less( void )
{
double dNumber1, dNumber2;
@@ -1469,6 +1515,9 @@ void Plus( void )
else if( IS_OBJECT( pItem1 ) && hb_isMessage( pItem2, "+" ) )
OperatorCall( pItem1, pItem2, "+" );
else
hb_errorRT_BASE( 1081, 1081, "Types of arguments do not match", "+" );
/* TODO: Generate an error if types don't match */
HB_DEBUG( "Plus\n" );
}
@@ -1487,27 +1536,6 @@ long PopDate( void )
}
}
void PopDefStat( WORD wStatic ) /* Pops a default value to a STATIC */
{
PHB_ITEM pStatic;
StackPop();
pStatic = aStatics.item.asArray.value->pItems + stack.iStatics +
wStatic - 1;
if( IS_BYREF( pStatic ) )
{
if( ( stack.pItems + pStatic->item.asRefer.value )->type == IT_NIL )
/* Only initialize when NIL */
ItemCopy( stack.pItems + pStatic->item.asRefer.value, stack.pPos );
}
else
if( pStatic->type == IT_NIL ) /* Only initialize when NIL */
ItemCopy( pStatic, stack.pPos );
ItemRelease( stack.pPos );
HB_DEBUG( "PopDefStat\n" );
}
double PopDouble( WORD *pwDec )
{
@@ -1552,19 +1580,15 @@ void PopLocal( SHORT iLocal )
/* local variable or local parameter */
pLocal = stack.pBase + 1 + iLocal;
if( IS_BYREF( pLocal ) )
{
if( pLocal->item.asRefer.value >= 0)
ItemCopy( stack.pItems + pLocal->item.asRefer.value, stack.pPos );
else
/* local variable referenced in a codeblock */
ItemCopy( CodeblockGetVar( stack.pItems +pLocal->item.asRefer.stackbase +1, pLocal->item.asRefer.value ), stack.pPos );
}
ItemCopy( ItemUnRef( pLocal ), stack.pPos );
else
ItemCopy( pLocal, stack.pPos );
ItemCopy( pLocal, stack.pPos );
}
else
/* local variable referenced in a codeblock */
ItemCopy( CodeblockGetVar( stack.pBase + 1, iLocal ), stack.pPos );
/* local variable referenced in a codeblock
* stack.pBase+1 points to a codeblock that is currently evaluated
*/
ItemCopy( hb_CodeblockGetVar( stack.pBase + 1, iLocal ), stack.pPos );
ItemRelease( stack.pPos );
HB_DEBUG( "PopLocal\n" );
@@ -1622,11 +1646,10 @@ void PopStatic( WORD wStatic )
PHB_ITEM pStatic;
StackPop();
pStatic = aStatics.item.asArray.value->pItems + stack.iStatics +
wStatic - 1;
pStatic = aStatics.item.asArray.value->pItems + stack.iStatics + wStatic - 1;
if( IS_BYREF( pStatic ) )
ItemCopy( stack.pItems + pStatic->item.asRefer.value, stack.pPos );
ItemCopy( ItemUnRef( pStatic ), stack.pPos );
else
ItemCopy( pStatic, stack.pPos );
@@ -1654,26 +1677,23 @@ void PushLogical( int iTrueFalse )
void PushLocal( SHORT iLocal )
{
PHB_ITEM pLocal;
if( iLocal >= 0 )
{
PHB_ITEM pLocal;
/* local variable or local parameter */
pLocal = stack.pBase + 1 + iLocal;
if( IS_BYREF( pLocal ) )
{
if( pLocal->item.asRefer.value >= 0 )
ItemCopy( stack.pPos, stack.pItems + pLocal->item.asRefer.value );
else
/* local variable referenced in a codeblock */
ItemCopy( stack.pPos, CodeblockGetVar( stack.pItems + pLocal->item.asRefer.stackbase +1, pLocal->item.asRefer.value) );
}
ItemCopy( stack.pPos, ItemUnRef( pLocal ) );
else
ItemCopy( stack.pPos, pLocal );
}
else
/* local variable referenced in a codeblock */
ItemCopy( stack.pPos, CodeblockGetVar( stack.pBase + 1, (LONG)iLocal ) );
/* local variable referenced in a codeblock
* stack.pBase+1 points to a codeblock that is currently evaluated
*/
ItemCopy( stack.pPos, hb_CodeblockGetVar( stack.pBase + 1, (LONG)iLocal ) );
StackPush();
HB_DEBUG2( "PushLocal %i\n", iLocal );
}
@@ -1683,16 +1703,9 @@ void PushLocalByRef( SHORT iLocal )
ItemRelease( stack.pPos );
stack.pPos->type = IT_BYREF;
/* we store its stack offset instead of a pointer to support a dynamic stack */
if( iLocal >= 0 )
/* local variable or local parameter */
/* store the position of referenced local variable on the eval stack */
stack.pPos->item.asRefer.value = stack.pBase + 1 + iLocal - stack.pItems;
else
{
/* local variable referenced in a codeblock */
stack.pPos->item.asRefer.value = iLocal;
stack.pPos->item.asRefer.stackbase = stack.pBase - stack.pItems;
}
stack.pPos->item.asRefer.value = iLocal;
stack.pPos->item.asRefer.offset = stack.pBase - stack.pItems +1;
stack.pPos->item.asRefer.itemsbase = &stack.pItems;
StackPush();
HB_DEBUG2( "PushLocalByRef %i\n", iLocal );
@@ -1722,12 +1735,30 @@ void PushNumber( double dNumber, WORD wDec )
void PushStatic( WORD wStatic )
{
ItemCopy( stack.pPos, aStatics.item.asArray.value->pItems +
stack.iStatics + wStatic - 1 );
PHB_ITEM pStatic;
pStatic = aStatics.item.asArray.value->pItems + stack.iStatics + wStatic - 1;
if( IS_BYREF(pStatic) )
ItemCopy( stack.pPos, ItemUnRef(pStatic) );
else
ItemCopy( stack.pPos, pStatic );
StackPush();
HB_DEBUG2( "PushStatic %i\n", wStatic );
}
void PushStaticByRef( WORD wStatic )
{
ItemRelease( stack.pPos );
stack.pPos->type = IT_BYREF;
/* we store the offset instead of a pointer to support a dynamic stack */
stack.pPos->item.asRefer.value = wStatic -1;
stack.pPos->item.asRefer.offset = stack.iStatics;
stack.pPos->item.asRefer.itemsbase = &aStatics.item.asArray.value->pItems;
StackPush();
HB_DEBUG2( "PushStaticByRef %i\n", wStatic );
}
void PushString( char * szText, ULONG length )
{
char * szTemp = ( char * ) hb_xgrab( length + 1 );
@@ -1760,18 +1791,35 @@ void Push( PHB_ITEM pItem )
HB_DEBUG( "Push\n" );
}
void PushBlock( BYTE * pCode, WORD wSize, WORD wParam, PSYMBOL pSymbols )
/* +0 -> HB_P_PUSHBLOCK
* +1 +2 -> size of codeblock
* +3 +4 -> number of expected parameters
* +5 +6 -> number of referenced local variables
* +7 -> start of table with referenced local variables
*/
void PushBlock( BYTE * pCode, PSYMBOL pSymbols )
{
WORD wLocals;
ItemRelease( stack.pPos );
stack.pPos->type = IT_BLOCK;
stack.pPos->item.asBlock.value = CodeblockNew( pCode, wSize, pSymbols,
stack.iStatics, stack.pBase - stack.pItems );
/* store the stack base of function where the codeblock was defined */
stack.pPos->item.asBlock.stackbase = stack.pBase - stack.pItems;
/* store the number of expected parameters */
stack.pPos->item.asBlock.paramcnt = wParam;
/* store the line number where the codeblock was defined */
stack.pPos->item.asBlock.lineno = stack.pBase->item.asSymbol.lineno;
wLocals =pCode[ 5 ] + ( pCode[ 6 ] * 256 );
stack.pPos->item.asBlock.value =
hb_CodeblockNew( pCode + 7 + wLocals*2, /* pcode buffer */
wLocals, /* number of referenced local variables */
(WORD *)(pCode +7), /* table with referenced local variables */
pSymbols );
/* store the statics base of function where the codeblock was defined
*/
stack.pPos->item.asBlock.statics = stack.iStatics;
/* store the number of expected parameters
*/
stack.pPos->item.asBlock.paramcnt = pCode[ 3 ] + ( pCode[ 4 ] * 256 );
/* store the line number where the codeblock was defined
*/
stack.pPos->item.asBlock.lineno = stack.pBase->item.asSymbol.lineno;
StackPush();
HB_DEBUG( "PushBlock\n" );
}
@@ -1823,8 +1871,6 @@ void RetValue( void )
{
StackPop();
ItemCopy( &stack.Return, stack.pPos );
if( stack.Return.type == IT_BLOCK )
CodeblockDetach( stack.Return.item.asBlock.value );
HB_DEBUG( "RetValue\n" );
}

View File

@@ -153,6 +153,7 @@ void InitSymbolTable( void )
/*
* The symbol tables from runtime support modules start here
*/
#ifdef HARBOUR_STRICT_ANSI_C
Arrays__InitSymbols();
Classes__InitSymbols();
Console__InitSymbols();
@@ -170,6 +171,7 @@ void InitSymbolTable( void )
Strings__InitInfinity();
#endif
Transfrm__InitSymbols();
#endif
/*
* The system symbol table with runtime functions HAVE TO be called last

View File

@@ -1,26 +0,0 @@
Function Main()
Local a := TestBlocks()
qout( eval( a[ 1 ] ) ) // 23
qout( eval( a[ 2 ], 42 ) ) // 42
qout( eval( a[ 1 ] ) ) // 42
qout( eval( a[ 2 ], 15 ) ) // 15
mqout( 15, eval( a[ 1 ] ) ) // 15 15
mqout( 14, eval( a[ 1 ] ) ) // 14 15
mqout( 42, eval( a[ 2 ], 42 ) ) // 42 42
mqout( 14, eval( a[ 2 ], 42 ) ) // 14 42
mqout( 42, eval( a[ 1 ] ) ) // 42 42
mqout( 14, eval( a[ 1 ] ) ) // 14 42
Return( NIL )
Static Function TestBlocks()
Local nFoo := 23
Return( { {|| nFoo }, {|n| nFoo := n } } )
Static Function mqout( nExpected, nGot )
qout( nExpected, nGot )
Return( NIL )

View File

@@ -20,7 +20,6 @@ PRG_SOURCES=\
classes.prg \
cmphello.prg \
codebl.prg \
codebl2.prg \
codebloc.prg \
comments.prg \
dates.prg \

View File

@@ -1,20 +1,55 @@
// Managing variables by reference
function Main()
STATIC s:=10
local x := 0
QOut( "Managing variables by reference" )
QOut( "Managing LOCAL variables by reference" )
Qout( 'In main before ref1 x=', x )
ref1( @x )
Qout( ' In main after ref1 x=', x )
ref( @x )
QOut( x )
QOut( "Managing STATIC variables by reference" )
Qout( 'In main before ref1 s=', s )
ref1( @s )
Qout( ' In main after ref1 s=', s )
return nil
function ref( x )
function ref1( x )
x := 999
x++
Qout( ' In ref1 before ref2 =', x )
Ref2( @x )
Qout( ' In ref1 after ref2 =', x )
return nil
function ref2( x )
x++
Qout( ' In ref2 before ref3 =', x )
Ref3( @x )
Qout( ' In ref2 after ref3 =', x )
return nil
function ref3( x )
STATIC a
x++
Qout( ' In ref3 before ref4 =', x )
a ={ x, x }
Ref4( @a )
Qout( ' In ref3 after ref4 =', x )
return nil
function ref4( a )
a[ 1 ]++
Qout( ' In ref4 =', a[ 1 ] )
return nil

View File

@@ -1,4 +1,78 @@
STATIC cbStatic
Function Main()
Local a := TestBlocks()
LOCAL cb
qout( eval( a[ 1 ] ) ) // 23
qout( eval( a[ 2 ], 42 ) ) // 42
qout( eval( a[ 1 ] ) ) // 42
qout( eval( a[ 2 ], 15 ) ) // 15
mqout( 15, eval( a[ 1 ] ) ) // 15 15
mqout( 14, eval( a[ 1 ] ) ) // 14 15
mqout( 42, eval( a[ 2 ], 42 ) ) // 42 42
mqout( 14, eval( a[ 2 ], 42 ) ) // 14 42
mqout( 42, eval( a[ 1 ] ) ) // 42 42
mqout( 14, eval( a[ 1 ] ) ) // 14 42
GetArray( @a )
PrintArray( @a )
qout( "Test for variables passed by reference in a codeblock" )
DetachWithRefer()
qout( "Test for indirect detaching of local variables" )
DetachToStatic( 1 )
mqout( 2, EVAL( cbStatic, 1 ) )
mqout( 3, EVAL( cbStatic, 2 ) )
cb :=cbStatic
DetachToStatic( 100 )
mqout( 200, EVAL( cbStatic, 100 ) )
mqout( 300, EVAL( cbStatic, 200 ) )
mqout( 4, EVAL( cb, 3 ) )
Return( NIL )
Static Function TestBlocks()
LOCAL nFoo := 23
Return( { {|| nFoo }, {|n| nFoo := n } } )
Static Function mqout( nExpected, nGot )
qout( nExpected, nGot )
Return( NIL )
/////////////////////////////////////////////////////////////////
PROCEDURE GetArray( a )
LOCAL i
a :=ARRAY( 100 )
FOR i:=1 TO 100
IF( (i % 6) == 0 )
a[ i-2 ] =NIL
a[ i-4 ] =NIL
ENDIF
a[ i ] := TestBlocks()
NEXT
RETURN
PROCEDURE PrintArray( a )
LOCAL i
FOR i:=1 TO 100
IF( a[i] != NIL )
EVAL( a[ i ][ 2 ], i )
mqout( i, EVAL( a[ i ][ 1 ] ) )
ENDIF
NEXT
RETURN
//////////////////////////////////////////////////////////////////
Function DetachWithRefer()
Local nTest
Local bBlock1 := MakeBlock()
Local bBlock2 := {|| DoThing( @nTest ), qout( nTest ) }
@@ -10,10 +84,17 @@ Return( NIL )
Function MakeBlock()
Local nTest
Return( {|| DoThing( @nTest ), qout( nTest ) } )
RETURN( {|| DoThing( @nTest ), qout( nTest ) } )
Function DoThing( n )
n := 42
Return( NIL )
//////////////////////////////////////////////////////////////////////
FUNCTION DetachToStatic( n )
cbStatic ={|x| n+x}
RETURN NIL

View File

@@ -1,28 +0,0 @@
FUNCTION MAIN()
LOCAL a, b, c
c =2
b =Detach( 5, @c )
OUTSTD( EVAL( b, 6, 1 ) )
QOUT("")
b =Detach( c, 15 )
OUTSTD( EVAL( b, 8 ) )
QOUT("")
b =Call1( b )
QOUT( EVAL( b, 10 ) )
RETURN nil
FUNCTION Detach( x, y )
RETURN( {|z| OutStd("z="),OutStd(z), OutStd(" x="),OutStd(x), OutStd(" y="),Outstd(y), Outstd(" z*y+x="), z*x+y} )
FUNCTION Call1( cb )
RETURN( Call2( cb ) )
FUNCTION Call2( cb )
RETURN( Call3( cb ) )
FUNCTION Call3( cb )
RETURN( {|x| EVAL(cb,2) *x} )