See changelog 2000-07-27 00:15 GMT -3

This commit is contained in:
Luiz Rafael Culik
2000-07-27 03:20:12 +00:00
parent c016b322a6
commit 6f01c79dd4
6 changed files with 391 additions and 343 deletions

View File

@@ -1,3 +1,15 @@
2000-07-27 00:15 GMT -3 Luiz Rafael Culik <culik@sl.conex.net>
*source/lang/msgit.c
*Renamed TPL to IT
*source/lang/msgko.c
*Renamed TPL to KR
-doc/garbage.txt
+doc/en/garbage.txt
*Some formating
*Removed spaces between see alsos
*doc/genhtm.rsp
+en/garbage.txt added to hbdoc responde file
20000726-22:50 GMT+2 Maurilio Longo <maurilio.longo@libero.it>
* contrib/mysql/makefile
* changed to be harbour gnu make system compatible

370
harbour/doc/en/garbage.txt Normal file
View File

@@ -0,0 +1,370 @@
//
// $Id$
//
/* $DOC$
* $FUNCNAME$
* The Garbage Collector
* $CATEGORY$
* Document
* $ONELINER$
* Readme for Harbour Garbage Collect Feature
* $DESCRIPTION$
* The garbage collector uses the following logic:
* - first collect all memory allocations that can cause the garbage;
* - next scan all variables if these memory blocks are still referenced.
*
* Notice that only arrays, objects and codeblocks are collected because
* these are the only datatypes that can cause self-references (a[1]:=a)
* or circual references (a[1]:=b; b[1]:=c; c[1]:=a) that cannot be
* properly deallocated by simple reference counting.
*
* Since all variables in harbour are stored inside some available tables
* (the eval stack, memvars table and array of static variables) then checking
* if the reference is still alive is quite easy and don't require any
* special treatment during memory allocation. Additionaly the garbage
* collector is scanning some internal data used by harbour objects
* implementation that stores also some values that can contain memory
* references. These data are used to initialize class instance variables
* and are stored in class shared variables.
*
* In special cases when the value of harbour variable is stored internally
* in some static area (at C or assembler level), for example SETKEY()
* stores codeblocks that will be evaluated when a key is pressed,
* the garbage collector will be not able to scan such values since it
* doesn't know their location. This can cause that some memory blocks will be
* released prematurely. To prevent the premature deallocation of such memory
* blocks they have to be locked for the garbage collector. The memory block
* can be locked with hb_gcLockItem() function (recommendeed method) if
* harbour item structure is used or hb_gcLock() function if direct memory
* pointer is used. The memory block can be unlocked by hb_gcUnlockItem() or
* hb_gcUnlock() functions.
* Notice however that all variables passed to a low level function are
* passed via the eval stack then they don't require locking during the
* function call. The locking will be required if passed value is copied
* into some static area to make it available for other low-level functions
* called after the exit from function that stored the value. This is required
* because the value is removed from the eval stack after function call and
* it can be no longer referenced by other variables.
*
* However scanning of all variables can be a time consuming operation. It
* requires that all allocated arrays have to be traversed through all its
* elements to find more arrays. Also all codeblocks are scanned for detached
* local variables they are reffering. For this reason looking for unreferenced
* memory blocks is performed during the idle states.
*
* The idle state is a state when there is no real application code
* executed,for example, the user code is stopped for 0.1 of a second
* during INKEY(0.1) call - the harbour is checking the keyboard only
* during this time. It leaves however quite enough amount of time for
* many other background tasks. One of such background task can be looking
* for unreferenced memory blocks.
*
* Allocating memory </par>
* -----------------
*
* The garbage collector collects memory blocks allocated with hb_gcAlloc()
* function calls. Memory allocated by hb_gcAlloc() should be released with
* hb_gcFree() function.
*
* Locking memory </par>
* --------------
*
* The memory allocated with hb_gcAlloc() should be locked to prevent the
* automatic releasing if such memory pointer is not stored within a
* harbour level variable. All harbour values (items) stored internally
* in static C area have to be locked.
* See hb_gcLockItem() and hb_gcUnlockItem() for more information.
*
* The garbage collecting </par>
* ----------------------
*
* During scanning of unreferenced memory the GC is using mark & sweep
* algorithm. This is done in three steps:
*
* 1) mark all memory blocks allocated by the GC with unused flag;
*
* 2) sweep (scan) all known places and clear unused flag for memory
* blocks that are referenced there;
*
* 3) finalize collecting by deallocation of all memory blocks that are
* still marked as unused and that are not locked.
*
* To speed things the mark step is simplified by swapping the meaning
* of unused flag. After deallocation of unused blocks all still alive
* memory blocks are marked with the same 'used' flag so we can reverse
* the meaning of this flag to 'unused' state in the next collecting.
* All new or unlocked memory blocks are automatically marked as 'unused'
* using the current flag, which assures that all memory blocks are marked
* with the same flag before the sweep step will start.
* See hb_gcCollectAll() and hb_gcItemRef()
*
* Calling the garbage collector from harbour code </par>
* -----------------------------------------------
*
* The garbage collector can be called directly from the harbour code.
* This is usefull in situations where there is no idle states available
* or the application is working in the loop with no user interaction
* and there is many memory allocations.
* See HB_GCALL() for explanation of how to call this function from your
* harbour code.
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem(),hb_gcCollectAll(),hb_gcItemRef(),HB_GCALL()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcAlloc()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Allocates memory that will be collected by the garbage collector.
* $SYNTAX$
* void *hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc );
* $ARGUMENTS$
* ulSize = requested size of memory block
* pCleanupFunc = pointer to HB_GARBAGE_FUNC function that will be called
* directly before releasing the garbage memory block or NULL. This
* function should release all other memory allocated and stored inside
* the memory block. For example, it releases all items stored inside
* the array. The functions receives a single parameter: the pointer
* to memory allocated by hb_gcAlloc().
* $RETURNS$
* The pointer to allocated memory or it generates an internal
* unrecoverable error.
* $DESCRIPTION$
* hb_gcAlloc() is used to allocate the memory that will be tracked
* by the garbage collector. It allows to properly release memory
* in case of self-referencing or cross-referencing harbour level
* variables.
* Memory allocated with this function should be released with
* hb_gcFree() function or it will be automatically deallocated
* by the GC if it is not locked or if it is not referenced by some
* harbour level variable.
* $EXAMPLES$
* See source/vm/arrays.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcFree()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Releases the memory that was allocated with hb_gcAlloc().
* $SYNTAX$
* void hb_gcFree( void *pMemoryPtr );
* $ARGUMENTS$
* pMemoryPtr = the pointer to memory for release. This memory
* pointer have to be allocated with hb_gcAlloc() function.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcFree() is used to deallocate the memory that was
* allocated with the hb_gcAlloc() function.
* $EXAMPLES$
* See source/vm/arrays.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcLockItem(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcLockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Locks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcLockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* <pItem> The pointer to item structure that will be locked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are locked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcLockItem() is used to lock the memory pointer stored in
* the passed item structure. It suppres the memory releasing
* if the garbage collector will not find any reference to this
* pointer. The garbage collector is storing the lock counter -
* every call of this function increases the counter. The item is
* locked if this counter is greather then 0.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcUnlockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Unlocks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcUnlockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* <pItem> The pointer to item structure that will be unlocked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are unlocked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcUnlockItem() is used to unlock the memory pointer stored in
* the passed item structure that was previously locked with
* hb_gcLockItem() call. It allows to release the memory during
* garbage collecting if the garbage collector will not find any
* reference to this pointer. The garbage collector is storing the
* lock counter - every call of this function decreases the counter.
* This function doesn't deallocate memory stored inside the item -
* the memory can be deallocated however during the closest garbage
* collecting if the lock counter is equal to 0 and the memory pointer
* is not referenced by any harbour level variable.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcCollectAll()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Scans all memory blocks and releases the garbage memory.
* $SYNTAX$
* void hb_gcCollectAll( void );
* $ARGUMENTS$
* None.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* This function scans the eval stack, the memvars table, the array
* of static variables and table of created classes for referenced
* memory blocks. After scanning all unused memory blocks and blocks
* that are not locked are released.
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcItemRef()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Marks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcItemRef( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* <pItem> The pointer to item structure that will be scanned. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are scanned only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* The garbage collector uses hb_gcItemRef() function during
* scanning of referenced memory pointers. This function checks the
* type of passed item and scans recursively all other memory blocks
* referenced by this item if it is an array, an object or a codeblock.
*
* NOTE: This function is reserved for the garbage collector only. It
* cannot be called from the user code - calling it can cause
* unpredicted results (memory blocks referenced by the
* passed item can be released prematurely during the closest
* garbage collection).
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* HB_GCALL()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Scans the memory and releases all garbage memory blocks.
* $SYNTAX$
* HB_GCALL()
* $ARGUMENTS$
* None
* $RETURNS$
* NIL
* $DESCRIPTION$
* This function releases all memory blocks that are considered
* as the garbage.
* $STATUS$
* Harbour
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcCollectAll()
* $END$
*/

View File

@@ -1,335 +0,0 @@
//
// $Id$
//
The Garbage Collector
=====================
The garbage collector uses the following logic:
- first collect all memory allocations that can cause the garbage;
- next scan all variables if these memory blocks are still referenced.
Notice that only arrays, objects and codeblocks are collected because
these are the only datatypes that can cause self-references (a[1]:=a)
or circual references (a[1]:=b; b[1]:=c; c[1]:=a) that cannot be
properly deallocated by simple reference counting.
Since all variables in harbour are stored inside some available tables
(the eval stack, memvars table and array of static variables) then checking
if the reference is still alive is quite easy and don't require any
special treatment during memory allocation. Additionaly the garbage
collector is scanning some internal data used by harbour objects
implementation that stores also some values that can contain memory
references. These data are used to initialize class instance variables
and are stored in class shared variables.
In special cases when the value of harbour variable is stored internally
in some static area (at C or assembler level), for example SETKEY()
stores codeblocks that will be evaluated when a key is pressed,
the garbage collector will be not able to scan such values since it
doesn't know their location. This can cause that some memory blocks will be
released prematurely. To prevent the premature deallocation of such memory
blocks they have to be locked for the garbage collector. The memory block
can be locked with hb_gcLockItem() function (recommendeed method) if
harbour item structure is used or hb_gcLock() function if direct memory
pointer is used. The memory block can be unlocked by hb_gcUnlockItem() or
hb_gcUnlock() functions.
Notice however that all variables passed to a low level function are
passed via the eval stack then they don't require locking during the
function call. The locking will be required if passed value is copied
into some static area to make it available for other low-level functions
called after the exit from function that stored the value. This is required
because the value is removed from the eval stack after function call and
it can be no longer referenced by other variables.
However scanning of all variables can be a time consuming operation. It
requires that all allocated arrays have to be traversed through all its
elements to find more arrays. Also all codeblocks are scanned for detached
local variables they are reffering. For this reason looking for unreferenced
memory blocks is performed during the idle states.
The idle state is a state when there is no real application code executed,
for example, the user code is stopped for 0.1 of a second during INKEY(0.1)
call - the harbour is checking the keyboard only during this time. It
leaves however quite enough amount of time for many other background tasks.
One of such background task can be looking for unreferenced memory blocks.
Allocating memory
-----------------
The garbage collector collects memory blocks allocated with hb_gcAlloc()
function calls. Memory allocated by hb_gcAlloc() should be released with
hb_gcFree() function.
/* $DOC$
* $FUNCNAME$
* hb_gcAlloc()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Allocates memory that will be collected by the garbage collector.
* $SYNTAX$
* void *hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc );
* $ARGUMENTS$
* ulSize = requested size of memory block
* pCleanupFunc = pointer to HB_GARBAGE_FUNC function that will be called
* directly before releasing the garbage memory block or NULL. This
* function should release all other memory allocated and stored inside
* the memory block. For example, it releases all items stored inside
* the array. The functions receives a single parameter: the pointer
* to memory allocated by hb_gcAlloc().
* $RETURNS$
* The pointer to allocated memory or it generates an internal
* unrecoverable error.
* $DESCRIPTION$
* hb_gcAlloc() is used to allocate the memory that will be tracked
* by the garbage collector. It allows to properly release memory
* in case of self-referencing or cross-referencing harbour level
* variables.
* Memory allocated with this function should be released with
* hb_gcFree() function or it will be automatically deallocated
* by the GC if it is not locked or if it is not referenced by some
* harbour level variable.
* $EXAMPLES$
* See source/vm/arrays.c
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcFree(), hb_gcLockItem(), hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcFree()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Releases the memory that was allocated with hb_gcAlloc().
* $SYNTAX$
* void hb_gcFree( void *pMemoryPtr );
* $ARGUMENTS$
* pMemoryPtr = the pointer to memory for release. This memory
* pointer have to be allocated with hb_gcAlloc() function.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcFree() is used to deallocate the memory that was
* allocated with the hb_gcAlloc() function.
* $EXAMPLES$
* See source/vm/arrays.c
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(), hb_gcLockItem(), hb_gcUnlockItem()
* $END$
*/
Locking memory
--------------
The memory allocated with hb_gcAlloc() should be locked to prevent the
automatic releasing if such memory pointer is not stored within a harbour
level variable. All harbour values (items) stored internally in static
C area have to be locked.
/* $DOC$
* $FUNCNAME$
* hb_gcLockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Locks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcLockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* pItem = the pointer to item structure that will be locked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are locked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcLockItem() is used to lock the memory pointer stored in
* the passed item structure. It suppres the memory releasing
* if the garbage collector will not find any reference to this
* pointer. The garbage collector is storing the lock counter -
* every call of this function increases the counter. The item is
* locked if this counter is greather then 0.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(), hb_gcFree(), hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcUnlockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Unlocks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcUnlockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* pItem = the pointer to item structure that will be unlocked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are unlocked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcUnlockItem() is used to unlock the memory pointer stored in
* the passed item structure that was previously locked with
* hb_gcLockItem() call. It allows to release the memory during
* garbage collecting if the garbage collector will not find any
* reference to this pointer. The garbage collector is storing the
* lock counter - every call of this function decreases the counter.
* This function doesn't deallocate memory stored inside the item -
* the memory can be deallocated however during the closest garbage
* collecting if the lock counter is equal to 0 and the memory pointer
* is not referenced by any harbour level variable.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(), hb_gcFree(), hb_gcLockItem()
* $END$
*/
The garbage collecting
----------------------
During scanning of unreferenced memory the GC is using mark & sweep
algorithm. This is done in three steps:
1) mark all memory blocks allocated by the GC with unused flag;
2) sweep (scan) all known places and clear unused flag for memory
blocks that are referenced there;
3) finalize collecting by deallocation of all memory blocks that are
still marked as unused and that are not locked.
To speed things the mark step is simplified by swapping the meaning of
unused flag. After deallocation of unused blocks all still alive memory
blocks are marked with the same 'used' flag so we can reverse the
meaning of this flag to 'unused' state in the next collecting. All new
or unlocked memory blocks are automatically marked as 'unused' using the
current flag, which assures that all memory blocks are marked with the
same flag before the sweep step will start.
/* $DOC$
* $FUNCNAME$
* hb_gcCollectAll()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Scans all memory blocks and releases the garbage memory.
* $SYNTAX$
* void hb_gcCollectAll( void );
* $ARGUMENTS$
* None.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* This function scans the eval stack, the memvars table, the array
* of static variables and table of created classes for referenced
* memory blocks. After scanning all unused memory blocks and blocks
* that are not locked are released.
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(), hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcItemRef()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Marks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcItemRef( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* pItem = the pointer to item structure that will be scanned. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are scanned only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* The garbage collector uses hb_gcItemRef() function during
* scanning of referenced memory pointers. This function checks the
* type of passed item and scans recursively all other memory blocks
* referenced by this item if it is an array, an object or a codeblock.
*
* NOTE: This function is reserved for the garbage collector only. It
* cannot be called from the user code - calling it can cause
* unpredicted results (memory blocks referenced by the
* passed item can be released prematurely during the closest
* garbage collection).
* $STATUS$
* C
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(), hb_gcFree(), hb_gcLockItem(), hb_gcUnlockItem()
* $END$
*/
Calling the garbage collector from harbour code
-----------------------------------------------
The garbage collector can be called directly from the harbour code. This
is usefull in situations where there is no idle states available or the
application is working in the loop with no user interaction and there
is many memory allocations.
/* $DOC$
* $FUNCNAME$
* HB_GCALL()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Scans the memory and releases all garbage memory blocks.
* $SYNTAX$
* HB_GCALL()
* $ARGUMENTS$
* None
* $RETURNS$
* NIL
* $DESCRIPTION$
* This function releases all memory blocks that are considered
* as the garbage.
* $STATUS$
* Harbour
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcCollectAll()
* $END$
*/

View File

@@ -39,3 +39,4 @@ en\setmode.txt
en\eval.txt
en\sayget.txt
en\strotype.txt
en\garbage.txt

View File

@@ -179,12 +179,12 @@ static HB_LANG s_lang =
}
};
HB_LANG_ANNOUNCE( TPL );
HB_LANG_ANNOUNCE( IT );
HB_CALL_ON_STARTUP_BEGIN( hb_lang_Init_TPL )
HB_CALL_ON_STARTUP_BEGIN( hb_lang_Init_IT )
hb_langRegister( &s_lang );
HB_CALL_ON_STARTUP_END( hb_lang_Init_TPL )
HB_CALL_ON_STARTUP_END( hb_lang_Init_IT )
#if ! defined(__GNUC__) && ! defined(_MSC_VER)
#pragma startup hb_lang_Init_TPL
#pragma startup hb_lang_Init_IT
#endif

View File

@@ -179,12 +179,12 @@ static HB_LANG s_lang =
}
};
HB_LANG_ANNOUNCE( TPL );
HB_LANG_ANNOUNCE( KR );
HB_CALL_ON_STARTUP_BEGIN( hb_lang_Init_TPL )
HB_CALL_ON_STARTUP_BEGIN( hb_lang_Init_KR )
hb_langRegister( &s_lang );
HB_CALL_ON_STARTUP_END( hb_lang_Init_TPL )
HB_CALL_ON_STARTUP_END( hb_lang_Init_KR )
#if ! defined(__GNUC__) && ! defined(_MSC_VER)
#pragma startup hb_lang_Init_TPL
#pragma startup hb_lang_Init_KR
#endif