2008-12-11 19:48 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbthread.h
* harbour/source/vm/thread.c
+ added hb_atomic_set(), hb_atomic_get(), hb_atomic_inc() and
hb_atomic_dec() functions which operates on HB_COUNTER or smaller
type if it's necessary for some platforms which can be access/assign
increment/decrement in MT safe atom operations.
hb_atomic_dec() returns true if counter is 0 after decrementation
* harbour/include/hbatomic.h
! fixed compilation in Linux and OpenWatcom
* harbour/include/hbapiitm.h
* harbour/source/rtl/itemseri.c
+ make hb_itemSerialize() and hb_itemDeserialize() public functions
! fixed serialization items with internal item references
* harbour/source/vm/hvm.c
* release memvars after closing RDDs
* harbour/source/debug/dbgentry.c
! fixed buffer overflow reported by Rodrigo
* harbour/source/vm/macro.c
* harbour/source/compiler/hbmain.c
* formatting
* harbour/include/hbexprb.c
! fixed wrongly recognized functions with HB_I18N_ prefix as
HB_I18N_GETTEXT()
* harbour/include/hbapi.h
* harbour/include/hbstack.h
* harbour/include/hbthread.h
* harbour/source/vm/estack.c
* harbour/source/vm/thread.c
* harbour/source/vm/hvm.c
+ added support for I18N in HVM.
Each thread can have it's own i18n set.
When new thread is created then it inherits i18n set from parent
thread and both uses the same set (please remember about it if you
will want to make some direct modifications on active i18n set
internals).
When thread change active i18n set then it effects only this thread
and new threads which will be create later. It does not change i18n
in other existing threads.
+ added functions to set/get pointer to active i18n set in HVM
void * hb_vmI18N( void )
void hb_vmSetI18N( void * )
* harbour/include/hbapi.h
* harbour/source/rtl/hbi18n.c
+ added i18n module. Now only for internal Harbour usage without support
for optional switching to alternative implementations.
I'll add such functionality later when I will work on native gettext
support.
The following public .prg functions has been added:
HB_I18N_GETTEXT[_STRICT]( <cMsgID> [, <cContext> ] )
-> <cTranslatedMsgID> | <cMsgID>
HB_I18N_NGETTEXT[_STRICT]( <nValue>, <cMsgID> | <acMsgID> ;
[, <cContext> ] )
-> <cTranslatedMsgID> | <cMsgID> | <acMsgID>[ <nIndex> ]
This is minimal support necessary for .prg code which has to exists
in each i18n module working with Harbour.
The following functions had been added as public C API:
PHB_ITEM hb_i18n_gettext( PHB_ITEM pMsgID, PHB_ITEM pContext )
PHB_ITEM hb_i18n_ngettext( PHB_ITEM pNum,
PHB_ITEM pMsgID, PHB_ITEM pContext )
The following functions had been added as private HVM C API:
void hb_i18n_init( void )
void hb_i18n_exit( void )
void hb_i18n_release( void * cargo )
void * hb_i18n_alloc( void * cargo )
They have to be supported by alternative i18n modules
The following functions has been added to manage Harbour i18n
translations sets:
HB_I18N_CREATE()
-> <pI18N>
Creates new empty I18N translation set
HB_I18N_CODEPAGE( [<pI18N>,] [<cNewCP>], [<lBase>], [<lTranslate>] )
-> <cOldCP>
Gets or sets Harbour codepage used by translation set
<pI18N> - I18N translation set,
if it's not given then currently active I18N set is used
<cNewCP> - new CP ID. Must be linked with application
<lBase> - when it's .T. then get/set base massages CP instead of
translated massages CP
<lTranslate> - if it's .T. then translate base (<lBase>==.T.) or
final messages in I18N set from previous CP to
given one. Base messages translation in synced
with context ID translation.
HB_I18N_PLURALFORM( [<pI18N>,] [<cNewForm>|<bNewForm>], [<lBase>] )
-> <cOldForm>|<bOldForm>
Gets or sets plural form used for final or base messages
<pI18N> - I18N translation set,
if it's not given then currently active I18N set is used
<cNewForm> - language ID of plural form, f.e.: "EN", "PL", "LT".
Now only three above are supported. Please add rules
for other languages to source/rtl/hbi18n.c.
<bNewForm> - codeblock used to calculate plural form indexes.
can be used instead of character representation but
it's not storred in serialized I18N set
<lBase> - when it's .T. then get/set base massages plural form
instead of translated massages one.
HB_I18N_DESCRIPTION( [<pI18N>,] [<cNewDescription>] )
-> <cOldDescription>
Gets or sets translation set description. After serialization
up to 32 bytes is stored in header which can be easy used to
determinate type of translation file.
<pI18N> - I18N translation set,
if it's not given then currently active I18N set is used
<cNewDescription> - new description
HB_I18N_ADDTEXT( <pI18N>, <cMsgID>, <cTrans> | <acTrans> [, <cContext> ] )
-> NIL
Adds new message with translation to i18n translation set
<pI18N> - I18N translation set
<cMsgID> - original message
<cTrans> - translated message
<acTrans> - array with translated messages used for plural forms
<cContext> - message context
HB_I18N_SET( [ <pI18N> | NIL ] )
-> <lActive>
Sets given I18N translation set as default one used by
HB_I18N_[N]GETTEXT[_STRICT]() functions or remove translation
set for calling thread when passed parameter is NIL
<pI18N> - I18N translation set
Returns logical value which is .T. when i18n set is active
HB_I18N_SAVETABLE( [<pI18N>] )
-> <cTable>
Returns I18N translation as string item which can be stored
in file or database
<pI18N> - I18N translation set, if it's not given then currently
active I18N set is used
HB_I18N_RESTORETABLE( <cTable> )
-> <pI18N> | NIL
Restores I18N translation set from strin item.
<cTable> - I18N translation set in string representation
On success it returns new <pI18N> set otherwise NIL if <cTable>
is not valid item created by HB_I18N_SAVETABLE() or it's corrupted.
HB_I18N_HEADERSIZE()
-> <nHeaderSize>
Returns size of header used by i18n serialized version
HB_I18N_CHEK( <cTable> | <cHeader> [, @<cDescription> ] )
-> <lValid>
<cTable> - i18n translation set serialized by HB_I18N_SAVETABLE
<cHeader> - header of i18n translation set
( LEFT( <cTable>, HB_I18N_HEADERSIZE() )
<cDescription> - optional parameter passed by reference where
will be sored i18n translation set description
extracted from valid header
Returns logical value indicating if given table or header is
valid serialized by HB_I18N_SAVETABLE() data. It does not
decode the table though it validates size and control sums.
These functions are optional and some future alternative implementations
may not support all of them and/or may provide some other functions.
+ added unofficial .prg function __I18N_HASHTABLE() which allows to
access hash table used by i18n translation set or create new translation
set with given hash table. It's helper functions for developers which
will work on Harbour i18n tools and should not be used by Harbour users.
Unlike original gettext Harbour allows to use language with many
plural forms as base one. In such case programmer should activate
at application startup default i18n translation set with base plural
form valid for base application language, f.e. by:
pI18N := hb_i18n_create()
hb_i18n_pluralForm( pI18N, <cLangID> | <bForm>, .t. )
hb_i18n_set( pI18N )
.prg code example:
#xtranslate _( <x,...> ) => hb_i18n_gettext_strict( <x> )
#xtranslate _N( <x,...> ) => hb_i18n_ngettext_strict( <x> )
proc main()
local pI18N, i
pI18N := hb_i18n_create()
hb_i18n_pluralForm( pI18N, "PL", .t. )
hb_i18n_set( pI18N )
for i := 0 to 30
? i, _N( i, {"grosz", "grosze", "groszy"} )
if i > 0 .and. i % 10 == 0
wait
endif
next
return
In .pot files created during compilation by Harbour with -j option
for above code we have the following entries for message with plural
forms:
msgid "grosz"
msgid_plural "grosze"
msgid_plural2 "groszy"
msgstr[0] ""
The msgid_plural2 (and others if language has more plural forms)
is Harbour extension which is not gettext compatible.
The above implementation is base version but should be fully functional.
Now we will need functions to safe/read i18n files and tools to mange
.pot files: merge them, edit translations, create final binary i18n
translation sets. Because we are using gettext compatible .pot files
then for some of such jobs we can use original gettext tools but we
need at least function which will create translation set from one or
more .pot files.
We should also agree some default localization(s) for files containing
translated data, their name convention and environment variable(s)
to set default language. It's not strictly necessary and each user
can have his own implementation but it would help in adding new
translations by final users to any Harbour application which will
respect them. We can use LANG envvar to extract preferred language
and use the same path as executed application looking for files
<appname>-<lang>.hil files though it may create some problems for
OSes which support only 8.3 file names so we can also define that
HB_I18N envvar has higher priority and points to expected translation
file.
* harbour/include/hbextern.ch
- removed old __i18n_*() functions
+ added current i18n functions
This commit is contained in:
@@ -8,6 +8,243 @@
|
||||
2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org)
|
||||
*/
|
||||
|
||||
2008-12-11 19:48 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/include/hbthread.h
|
||||
* harbour/source/vm/thread.c
|
||||
+ added hb_atomic_set(), hb_atomic_get(), hb_atomic_inc() and
|
||||
hb_atomic_dec() functions which operates on HB_COUNTER or smaller
|
||||
type if it's necessary for some platforms which can be access/assign
|
||||
increment/decrement in MT safe atom operations.
|
||||
hb_atomic_dec() returns true if counter is 0 after decrementation
|
||||
|
||||
* harbour/include/hbatomic.h
|
||||
! fixed compilation in Linux and OpenWatcom
|
||||
|
||||
* harbour/include/hbapiitm.h
|
||||
* harbour/source/rtl/itemseri.c
|
||||
+ make hb_itemSerialize() and hb_itemDeserialize() public functions
|
||||
! fixed serialization items with internal item references
|
||||
|
||||
* harbour/source/vm/hvm.c
|
||||
* release memvars after closing RDDs
|
||||
|
||||
* harbour/source/debug/dbgentry.c
|
||||
! fixed buffer overflow reported by Rodrigo
|
||||
|
||||
* harbour/source/vm/macro.c
|
||||
* harbour/source/compiler/hbmain.c
|
||||
* formatting
|
||||
|
||||
* harbour/include/hbexprb.c
|
||||
! fixed wrongly recognized functions with HB_I18N_ prefix as
|
||||
HB_I18N_GETTEXT()
|
||||
|
||||
* harbour/include/hbapi.h
|
||||
* harbour/include/hbstack.h
|
||||
* harbour/include/hbthread.h
|
||||
* harbour/source/vm/estack.c
|
||||
* harbour/source/vm/thread.c
|
||||
* harbour/source/vm/hvm.c
|
||||
+ added support for I18N in HVM.
|
||||
Each thread can have it's own i18n set.
|
||||
When new thread is created then it inherits i18n set from parent
|
||||
thread and both uses the same set (please remember about it if you
|
||||
will want to make some direct modifications on active i18n set
|
||||
internals).
|
||||
When thread change active i18n set then it effects only this thread
|
||||
and new threads which will be create later. It does not change i18n
|
||||
in other existing threads.
|
||||
+ added functions to set/get pointer to active i18n set in HVM
|
||||
void * hb_vmI18N( void )
|
||||
void hb_vmSetI18N( void * )
|
||||
|
||||
* harbour/include/hbapi.h
|
||||
* harbour/source/rtl/hbi18n.c
|
||||
+ added i18n module. Now only for internal Harbour usage without support
|
||||
for optional switching to alternative implementations.
|
||||
I'll add such functionality later when I will work on native gettext
|
||||
support.
|
||||
|
||||
The following public .prg functions has been added:
|
||||
HB_I18N_GETTEXT[_STRICT]( <cMsgID> [, <cContext> ] )
|
||||
-> <cTranslatedMsgID> | <cMsgID>
|
||||
HB_I18N_NGETTEXT[_STRICT]( <nValue>, <cMsgID> | <acMsgID> ;
|
||||
[, <cContext> ] )
|
||||
-> <cTranslatedMsgID> | <cMsgID> | <acMsgID>[ <nIndex> ]
|
||||
This is minimal support necessary for .prg code which has to exists
|
||||
in each i18n module working with Harbour.
|
||||
|
||||
The following functions had been added as public C API:
|
||||
PHB_ITEM hb_i18n_gettext( PHB_ITEM pMsgID, PHB_ITEM pContext )
|
||||
PHB_ITEM hb_i18n_ngettext( PHB_ITEM pNum,
|
||||
PHB_ITEM pMsgID, PHB_ITEM pContext )
|
||||
|
||||
The following functions had been added as private HVM C API:
|
||||
void hb_i18n_init( void )
|
||||
void hb_i18n_exit( void )
|
||||
void hb_i18n_release( void * cargo )
|
||||
void * hb_i18n_alloc( void * cargo )
|
||||
They have to be supported by alternative i18n modules
|
||||
|
||||
The following functions has been added to manage Harbour i18n
|
||||
translations sets:
|
||||
|
||||
HB_I18N_CREATE()
|
||||
-> <pI18N>
|
||||
Creates new empty I18N translation set
|
||||
|
||||
HB_I18N_CODEPAGE( [<pI18N>,] [<cNewCP>], [<lBase>], [<lTranslate>] )
|
||||
-> <cOldCP>
|
||||
Gets or sets Harbour codepage used by translation set
|
||||
<pI18N> - I18N translation set,
|
||||
if it's not given then currently active I18N set is used
|
||||
<cNewCP> - new CP ID. Must be linked with application
|
||||
<lBase> - when it's .T. then get/set base massages CP instead of
|
||||
translated massages CP
|
||||
<lTranslate> - if it's .T. then translate base (<lBase>==.T.) or
|
||||
final messages in I18N set from previous CP to
|
||||
given one. Base messages translation in synced
|
||||
with context ID translation.
|
||||
|
||||
HB_I18N_PLURALFORM( [<pI18N>,] [<cNewForm>|<bNewForm>], [<lBase>] )
|
||||
-> <cOldForm>|<bOldForm>
|
||||
Gets or sets plural form used for final or base messages
|
||||
<pI18N> - I18N translation set,
|
||||
if it's not given then currently active I18N set is used
|
||||
<cNewForm> - language ID of plural form, f.e.: "EN", "PL", "LT".
|
||||
Now only three above are supported. Please add rules
|
||||
for other languages to source/rtl/hbi18n.c.
|
||||
<bNewForm> - codeblock used to calculate plural form indexes.
|
||||
can be used instead of character representation but
|
||||
it's not storred in serialized I18N set
|
||||
<lBase> - when it's .T. then get/set base massages plural form
|
||||
instead of translated massages one.
|
||||
|
||||
HB_I18N_DESCRIPTION( [<pI18N>,] [<cNewDescription>] )
|
||||
-> <cOldDescription>
|
||||
Gets or sets translation set description. After serialization
|
||||
up to 32 bytes is stored in header which can be easy used to
|
||||
determinate type of translation file.
|
||||
<pI18N> - I18N translation set,
|
||||
if it's not given then currently active I18N set is used
|
||||
<cNewDescription> - new description
|
||||
|
||||
HB_I18N_ADDTEXT( <pI18N>, <cMsgID>, <cTrans> | <acTrans> [, <cContext> ] )
|
||||
-> NIL
|
||||
Adds new message with translation to i18n translation set
|
||||
<pI18N> - I18N translation set
|
||||
<cMsgID> - original message
|
||||
<cTrans> - translated message
|
||||
<acTrans> - array with translated messages used for plural forms
|
||||
<cContext> - message context
|
||||
|
||||
HB_I18N_SET( [ <pI18N> | NIL ] )
|
||||
-> <lActive>
|
||||
Sets given I18N translation set as default one used by
|
||||
HB_I18N_[N]GETTEXT[_STRICT]() functions or remove translation
|
||||
set for calling thread when passed parameter is NIL
|
||||
<pI18N> - I18N translation set
|
||||
Returns logical value which is .T. when i18n set is active
|
||||
|
||||
HB_I18N_SAVETABLE( [<pI18N>] )
|
||||
-> <cTable>
|
||||
Returns I18N translation as string item which can be stored
|
||||
in file or database
|
||||
<pI18N> - I18N translation set, if it's not given then currently
|
||||
active I18N set is used
|
||||
|
||||
HB_I18N_RESTORETABLE( <cTable> )
|
||||
-> <pI18N> | NIL
|
||||
Restores I18N translation set from strin item.
|
||||
<cTable> - I18N translation set in string representation
|
||||
On success it returns new <pI18N> set otherwise NIL if <cTable>
|
||||
is not valid item created by HB_I18N_SAVETABLE() or it's corrupted.
|
||||
|
||||
HB_I18N_HEADERSIZE()
|
||||
-> <nHeaderSize>
|
||||
Returns size of header used by i18n serialized version
|
||||
|
||||
HB_I18N_CHEK( <cTable> | <cHeader> [, @<cDescription> ] )
|
||||
-> <lValid>
|
||||
<cTable> - i18n translation set serialized by HB_I18N_SAVETABLE
|
||||
<cHeader> - header of i18n translation set
|
||||
( LEFT( <cTable>, HB_I18N_HEADERSIZE() )
|
||||
<cDescription> - optional parameter passed by reference where
|
||||
will be sored i18n translation set description
|
||||
extracted from valid header
|
||||
Returns logical value indicating if given table or header is
|
||||
valid serialized by HB_I18N_SAVETABLE() data. It does not
|
||||
decode the table though it validates size and control sums.
|
||||
|
||||
These functions are optional and some future alternative implementations
|
||||
may not support all of them and/or may provide some other functions.
|
||||
|
||||
+ added unofficial .prg function __I18N_HASHTABLE() which allows to
|
||||
access hash table used by i18n translation set or create new translation
|
||||
set with given hash table. It's helper functions for developers which
|
||||
will work on Harbour i18n tools and should not be used by Harbour users.
|
||||
|
||||
Unlike original gettext Harbour allows to use language with many
|
||||
plural forms as base one. In such case programmer should activate
|
||||
at application startup default i18n translation set with base plural
|
||||
form valid for base application language, f.e. by:
|
||||
pI18N := hb_i18n_create()
|
||||
hb_i18n_pluralForm( pI18N, <cLangID> | <bForm>, .t. )
|
||||
hb_i18n_set( pI18N )
|
||||
.prg code example:
|
||||
|
||||
#xtranslate _( <x,...> ) => hb_i18n_gettext_strict( <x> )
|
||||
#xtranslate _N( <x,...> ) => hb_i18n_ngettext_strict( <x> )
|
||||
|
||||
proc main()
|
||||
local pI18N, i
|
||||
|
||||
pI18N := hb_i18n_create()
|
||||
hb_i18n_pluralForm( pI18N, "PL", .t. )
|
||||
hb_i18n_set( pI18N )
|
||||
|
||||
for i := 0 to 30
|
||||
? i, _N( i, {"grosz", "grosze", "groszy"} )
|
||||
if i > 0 .and. i % 10 == 0
|
||||
wait
|
||||
endif
|
||||
next
|
||||
return
|
||||
|
||||
In .pot files created during compilation by Harbour with -j option
|
||||
for above code we have the following entries for message with plural
|
||||
forms:
|
||||
msgid "grosz"
|
||||
msgid_plural "grosze"
|
||||
msgid_plural2 "groszy"
|
||||
msgstr[0] ""
|
||||
The msgid_plural2 (and others if language has more plural forms)
|
||||
is Harbour extension which is not gettext compatible.
|
||||
|
||||
|
||||
The above implementation is base version but should be fully functional.
|
||||
Now we will need functions to safe/read i18n files and tools to mange
|
||||
.pot files: merge them, edit translations, create final binary i18n
|
||||
translation sets. Because we are using gettext compatible .pot files
|
||||
then for some of such jobs we can use original gettext tools but we
|
||||
need at least function which will create translation set from one or
|
||||
more .pot files.
|
||||
We should also agree some default localization(s) for files containing
|
||||
translated data, their name convention and environment variable(s)
|
||||
to set default language. It's not strictly necessary and each user
|
||||
can have his own implementation but it would help in adding new
|
||||
translations by final users to any Harbour application which will
|
||||
respect them. We can use LANG envvar to extract preferred language
|
||||
and use the same path as executed application looking for files
|
||||
<appname>-<lang>.hil files though it may create some problems for
|
||||
OSes which support only 8.3 file names so we can also define that
|
||||
HB_I18N envvar has higher priority and points to expected translation
|
||||
file.
|
||||
|
||||
* harbour/include/hbextern.ch
|
||||
- removed old __i18n_*() functions
|
||||
+ added current i18n functions
|
||||
|
||||
2008-12-09 12:46 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com)
|
||||
* harbour/contrib/gtwvg/makefile
|
||||
* harbour/contrib/gtwvg/common.mak
|
||||
|
||||
@@ -1001,6 +1001,19 @@ extern void hb_idleState( void ); /* services a single idle state */
|
||||
extern void hb_idleReset( void ); /* services a single idle state */
|
||||
extern void hb_idleSleep( double dSeconds ); /* sleep for a given time serving idle task */
|
||||
|
||||
/* I18N public API */
|
||||
extern PHB_ITEM hb_i18n_ngettext( PHB_ITEM pNum, PHB_ITEM pMsgID, PHB_ITEM pContext );
|
||||
extern PHB_ITEM hb_i18n_gettext( PHB_ITEM pMsgID, PHB_ITEM pContext );
|
||||
/* I18N internal HVM API */
|
||||
#if defined( _HB_API_INTERNAL_ ) || defined( _HB_I18N_INTERNAL_ )
|
||||
extern void * hb_vmI18N( void );
|
||||
extern void hb_vmSetI18N( void * );
|
||||
extern void hb_i18n_init( void );
|
||||
extern void hb_i18n_exit( void );
|
||||
extern void hb_i18n_release( void * cargo );
|
||||
extern void * hb_i18n_alloc( void * cargo );
|
||||
#endif /* _HB_API_INTERNAL_ || _HB_I18N_INTERNAL_ */
|
||||
|
||||
/* misc */
|
||||
extern HB_EXPORT char * hb_verPlatform( void ); /* retrieves a newly allocated buffer containing platform version */
|
||||
extern HB_EXPORT char * hb_verCompiler( void ); /* retrieves a newly allocated buffer containing compiler version */
|
||||
|
||||
@@ -178,6 +178,9 @@ extern HB_EXPORT PHB_ITEM hb_itemValToStr ( PHB_ITEM pItem ); /* Convert any
|
||||
extern HB_EXPORT char * hb_itemPadConv ( PHB_ITEM pItem, ULONG * pulSize, BOOL * bFreeReq );
|
||||
extern HB_EXPORT void hb_itemSwap ( PHB_ITEM pItem1, PHB_ITEM pItem2 );
|
||||
|
||||
extern HB_EXPORT char * hb_itemSerialize( PHB_ITEM pItem, BOOL fNumSize, ULONG *pulSize );
|
||||
extern HB_EXPORT PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, ULONG * pulSize );
|
||||
|
||||
#if defined( _HB_API_INTERNAL_ )
|
||||
|
||||
# define hb_itemSetNil( item ) do { \
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
#if defined( __SVR4 )
|
||||
# include <thread.h>
|
||||
#endif
|
||||
#if defined( HB_OS_UNIX )
|
||||
#if defined( HB_OS_UNIX ) && !defined( __WATCOMC__ )
|
||||
# include <sched.h>
|
||||
#endif
|
||||
|
||||
@@ -258,7 +258,7 @@ HB_EXTERN_BEGIN
|
||||
|
||||
# endif /* ???CPU?? */
|
||||
|
||||
#endif
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
||||
#if defined( HB_OS_WIN_32 )
|
||||
@@ -332,7 +332,7 @@ HB_EXTERN_BEGIN
|
||||
# define HB_SPINLOCK_RELEASE(l) OSSpinLockUnlock(l)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
#endif /* HB_OS_??? */
|
||||
|
||||
HB_EXTERN_END
|
||||
|
||||
|
||||
@@ -1770,10 +1770,10 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall )
|
||||
else if( strncmp( "HB_I18N_", pName->value.asSymbol, 8 ) == 0 )
|
||||
{
|
||||
HB_EXPR_PTR pArg = pParms->value.asList.pExprList, pCount = NULL;
|
||||
BOOL fStrict, fNoop, fPlural, fUnknown;
|
||||
BOOL fStrict, fNoop, fPlural, fI18nFunc;
|
||||
ULONG ulPos = 8;
|
||||
|
||||
fStrict = fNoop = fPlural = fUnknown = FALSE;
|
||||
fStrict = fNoop = fPlural = fI18nFunc = FALSE;
|
||||
if( pName->value.asSymbol[ ulPos ] == 'N' )
|
||||
{
|
||||
fPlural = TRUE;
|
||||
@@ -1786,16 +1786,14 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall )
|
||||
{
|
||||
++ulPos;
|
||||
if( strcmp( "STRICT", &pName->value.asSymbol[ ulPos ] ) == 0 )
|
||||
fStrict = TRUE;
|
||||
fI18nFunc = fStrict = TRUE;
|
||||
else if( strcmp( "NOOP", &pName->value.asSymbol[ ulPos ] ) == 0 )
|
||||
fNoop = TRUE;
|
||||
else
|
||||
fUnknown = TRUE;
|
||||
fI18nFunc = fNoop = TRUE;
|
||||
}
|
||||
else if( pName->value.asSymbol[ ulPos ] )
|
||||
fUnknown = TRUE;
|
||||
else if( !pName->value.asSymbol[ ulPos ] )
|
||||
fI18nFunc = TRUE;
|
||||
}
|
||||
if( !fUnknown )
|
||||
if( fI18nFunc )
|
||||
{
|
||||
int iWarning = 0;
|
||||
HB_EXPR_PTR pBadParam = NULL;
|
||||
|
||||
@@ -543,10 +543,23 @@ EXTERNAL __MVXRELEASE
|
||||
EXTERNAL __EINSTVAR52
|
||||
EXTERNAL __EINSTVAR53
|
||||
|
||||
EXTERNAL __I18N_SAVE
|
||||
EXTERNAL __I18N_LOAD
|
||||
EXTERNAL __I18N_LOADFROMMEMORY
|
||||
EXTERNAL __I18N_GETTEXT
|
||||
/* i18n */
|
||||
EXTERNAL HB_I18N_GETTEXT
|
||||
EXTERNAL HB_I18N_GETTEXT_STRICT
|
||||
EXTERNAL HB_I18N_NGETTEXT
|
||||
EXTERNAL HB_I18N_NGETTEXT_STRICT
|
||||
|
||||
EXTERNAL HB_I18N_CREATE
|
||||
EXTERNAL HB_I18N_CODEPAGE
|
||||
EXTERNAL HB_I18N_PLURALFORM
|
||||
EXTERNAL HB_I18N_DESCRIPTION
|
||||
EXTERNAL HB_I18N_ADDTEXT
|
||||
EXTERNAL HB_I18N_SET
|
||||
EXTERNAL HB_I18N_SAVETABLE
|
||||
EXTERNAL HB_I18N_RESTORETABLE
|
||||
EXTERNAL HB_I18N_HEADERSIZE
|
||||
EXTERNAL HB_I18N_CHECK
|
||||
EXTERNAL __I18N_HASHTABLE
|
||||
|
||||
/* The debugger interface */
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ typedef struct
|
||||
char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */
|
||||
void * pCDP; /* current codepage module */
|
||||
void * pLang; /* current language module */
|
||||
void * pI18N; /* current I18N module */
|
||||
void * hGT; /* current GT module */
|
||||
int iTSD; /* number of allocated TSD holders */
|
||||
PHB_TSD_HOLDER pTSD; /* thread specific data holder */
|
||||
@@ -322,6 +323,8 @@ extern void * hb_stackGetCDP( void );
|
||||
extern void hb_stackSetCDP( void * );
|
||||
extern void * hb_stackGetLang( void );
|
||||
extern void hb_stackSetLang( void * );
|
||||
extern void * hb_stackGetI18N( void );
|
||||
extern void hb_stackSetI18N( void * );
|
||||
|
||||
extern void hb_stackIsStackRef( void *, PHB_TSD_FUNC );
|
||||
|
||||
@@ -369,6 +372,8 @@ extern void hb_stackIsStackRef( void *, PHB_TSD_FUNC );
|
||||
#define hb_stackSetCDP( p ) do { hb_stack.pCDP = ( p ); } while ( 0 )
|
||||
#define hb_stackGetLang( ) ( hb_stack.pLang )
|
||||
#define hb_stackSetLang( p ) do { hb_stack.pLang = ( p ); } while ( 0 )
|
||||
#define hb_stackGetI18N( ) ( hb_stack.pI18N )
|
||||
#define hb_stackSetI18N( p ) do { hb_stack.pI18N = ( p ); } while ( 0 )
|
||||
|
||||
#define hb_stackId( ) ( ( void * ) &hb_stack )
|
||||
#if defined( HB_MT_VM )
|
||||
|
||||
@@ -275,6 +275,7 @@ typedef struct _HB_THREADSTATE
|
||||
const char * pszLang;
|
||||
const char * pszDefRDD;
|
||||
PHB_SET_STRUCT pSet;
|
||||
void * pI18N;
|
||||
void * hGT;
|
||||
void * pStackId;
|
||||
BOOL fActive;
|
||||
@@ -295,10 +296,17 @@ extern void hb_threadExit( void );
|
||||
|
||||
extern PHB_THREADSTATE hb_threadStateNew( void );
|
||||
|
||||
/* atomic oprtations */
|
||||
void hb_atomic_set( volatile HB_COUNTER * pCounter, HB_COUNTER value );
|
||||
HB_COUNTER hb_atomic_get( volatile HB_COUNTER * pCounter );
|
||||
void hb_atomic_inc( volatile HB_COUNTER * pCounter );
|
||||
BOOL hb_atomic_dec( volatile HB_COUNTER * pCounter ); /* returns TRUE when counter reach after decrementation */
|
||||
|
||||
/* Critical sections or fast non recursive MUTEXes */
|
||||
extern void hb_threadEnterCriticalSection( HB_CRITICAL_T * critical );
|
||||
extern void hb_threadLeaveCriticalSection( HB_CRITICAL_T * critical );
|
||||
|
||||
/* conditional variables */
|
||||
extern BOOL hb_threadCondSignal( HB_COND_T * cond );
|
||||
extern BOOL hb_threadCondBroadcast( HB_COND_T * cond );
|
||||
extern BOOL hb_threadCondWait( HB_COND_T * cond, HB_CRITICAL_T * mutex );
|
||||
|
||||
@@ -2388,7 +2388,7 @@ void hb_compGenStaticName( const char *szVarName, HB_COMP_DECL )
|
||||
BYTE bGlobal = 0;
|
||||
PFUNCTION pFunc;
|
||||
int iVar;
|
||||
|
||||
|
||||
if( ! HB_COMP_PARAM->fStartProc && HB_COMP_PARAM->functions.iCount <= 1 )
|
||||
{
|
||||
/* Variable declaration is outside of function/procedure body.
|
||||
|
||||
@@ -1014,7 +1014,7 @@ static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT *watch, char *szWord, int nSta
|
||||
t[ nStart + 6 ] = '0' + ( char ) ( ( j + 1 ) / 10 );
|
||||
t[ nStart + 7 ] = '0' + ( char ) ( ( j + 1 ) % 10 );
|
||||
t[ nStart + 8 ] = ']';
|
||||
hb_strncpy( t + nStart + 9, watch->szExpr + nStart + nLen, strlen( watch->szExpr ) - nLen + 1 - nStart );
|
||||
hb_strncpy( t + nStart + 9, watch->szExpr + nStart + nLen, strlen( watch->szExpr ) - nLen - nStart );
|
||||
FREE( watch->szExpr );
|
||||
watch->szExpr = t;
|
||||
return nStart + 9;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -153,7 +153,7 @@ typedef struct _HB_CYCLIC_REF
|
||||
struct _HB_CYCLIC_REF * pNext;
|
||||
} HB_CYCLIC_REF, * PHB_CYCLIC_REF;
|
||||
|
||||
static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer,
|
||||
static ULONG hb_deserializeItem( PHB_ITEM pItem, const UCHAR * pBuffer,
|
||||
ULONG ulOffset, PHB_CYCLIC_REF pRef );
|
||||
|
||||
static BOOL hb_itemSerialValueRef( PHB_CYCLIC_REF * pRefPtr, void * value,
|
||||
@@ -276,6 +276,9 @@ static ULONG hb_itemSerialSize( PHB_ITEM pItem, BOOL fNumSize, PHB_CYCLIC_REF *
|
||||
USHORT uiClass;
|
||||
const char * szVal;
|
||||
|
||||
if( HB_IS_BYREF( pItem ) )
|
||||
pItem = hb_itemUnRef( pItem );
|
||||
|
||||
switch( hb_itemType( pItem ) )
|
||||
{
|
||||
case HB_IT_NIL:
|
||||
@@ -409,6 +412,9 @@ static ULONG hb_serializeItem( PHB_ITEM pItem, BOOL fNumSize, UCHAR * pBuffer,
|
||||
const char * szVal;
|
||||
ULONG ulRef, ulLen, u;
|
||||
|
||||
if( HB_IS_BYREF( pItem ) )
|
||||
pItem = hb_itemUnRef( pItem );
|
||||
|
||||
switch( hb_itemType( pItem ) )
|
||||
{
|
||||
case HB_IT_NIL:
|
||||
@@ -701,7 +707,8 @@ static ULONG hb_serializeItem( PHB_ITEM pItem, BOOL fNumSize, UCHAR * pBuffer,
|
||||
return ulOffset;
|
||||
}
|
||||
|
||||
static ULONG hb_deserializeHash( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffset,
|
||||
static ULONG hb_deserializeHash( PHB_ITEM pItem,
|
||||
const UCHAR * pBuffer, ULONG ulOffset,
|
||||
ULONG ulLen, PHB_CYCLIC_REF pRef )
|
||||
{
|
||||
hb_hashNew( pItem );
|
||||
@@ -740,7 +747,8 @@ static ULONG hb_deserializeHash( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffset
|
||||
return ulOffset;
|
||||
}
|
||||
|
||||
static ULONG hb_deserializeArray( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffset,
|
||||
static ULONG hb_deserializeArray( PHB_ITEM pItem,
|
||||
const UCHAR * pBuffer, ULONG ulOffset,
|
||||
ULONG ulLen, PHB_CYCLIC_REF pRef )
|
||||
{
|
||||
ULONG u;
|
||||
@@ -753,7 +761,7 @@ static ULONG hb_deserializeArray( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffse
|
||||
return ulOffset;
|
||||
}
|
||||
|
||||
static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer,
|
||||
static ULONG hb_deserializeItem( PHB_ITEM pItem, const UCHAR * pBuffer,
|
||||
ULONG ulOffset, PHB_CYCLIC_REF pRef )
|
||||
{
|
||||
ULONG ulLen, ulPad;
|
||||
@@ -953,8 +961,8 @@ static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer,
|
||||
|
||||
case HB_SERIAL_OBJ:
|
||||
{
|
||||
char * szClass, * szFunc;
|
||||
szClass = ( char * ) &pBuffer[ ulOffset ];
|
||||
const char * szClass, * szFunc;
|
||||
szClass = ( const char * ) &pBuffer[ ulOffset ];
|
||||
ulLen = strlen( szClass );
|
||||
szFunc = szClass + ulLen + 1;
|
||||
ulOffset = hb_deserializeItem( pItem, pBuffer,
|
||||
@@ -971,10 +979,10 @@ static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer,
|
||||
return ulOffset;
|
||||
}
|
||||
|
||||
static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize,
|
||||
static BOOL hb_deserializeTest( const UCHAR ** pBufferPtr, ULONG * pulSize,
|
||||
ULONG ulOffset, PHB_CYCLIC_REF * pRefPtr )
|
||||
{
|
||||
UCHAR * pBuffer = * pBufferPtr;
|
||||
const UCHAR * pBuffer = * pBufferPtr;
|
||||
ULONG ulSize = * pulSize, ulLen = 0;
|
||||
|
||||
if( ulSize == 0 )
|
||||
@@ -1153,9 +1161,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize,
|
||||
}
|
||||
|
||||
/*
|
||||
* These function will be public in the future [druzus]
|
||||
* public API functions
|
||||
*/
|
||||
static char * hb_itemSerial( PHB_ITEM pItem, BOOL fNumSize, ULONG *pulSize )
|
||||
char * hb_itemSerialize( PHB_ITEM pItem, BOOL fNumSize, ULONG *pulSize )
|
||||
{
|
||||
PHB_CYCLIC_REF pRef = NULL;
|
||||
ULONG ulSize = hb_itemSerialSize( pItem, fNumSize, &pRef, 0 );
|
||||
@@ -1172,16 +1180,13 @@ static char * hb_itemSerial( PHB_ITEM pItem, BOOL fNumSize, ULONG *pulSize )
|
||||
return ( char * ) pBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* These function will be public in the future [druzus]
|
||||
*/
|
||||
static PHB_ITEM hb_itemDeserial( char ** pBufferPtr, ULONG * pulSize )
|
||||
PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, ULONG * pulSize )
|
||||
{
|
||||
PHB_CYCLIC_REF pRef = NULL;
|
||||
UCHAR * pBuffer = ( UCHAR * ) *pBufferPtr;
|
||||
const UCHAR * pBuffer = ( const UCHAR * ) *pBufferPtr;
|
||||
PHB_ITEM pItem = NULL;
|
||||
|
||||
if( !pulSize || hb_deserializeTest( ( UCHAR ** ) pBufferPtr, pulSize, 0, &pRef ) )
|
||||
if( !pulSize || hb_deserializeTest( ( const UCHAR ** ) pBufferPtr, pulSize, 0, &pRef ) )
|
||||
{
|
||||
pItem = hb_itemNew( NULL );
|
||||
hb_deserializeItem( pItem, pBuffer, 0, pRef );
|
||||
@@ -1198,7 +1203,7 @@ HB_FUNC( HB_SERIALIZE )
|
||||
if( pItem )
|
||||
{
|
||||
ULONG ulSize;
|
||||
char * pBuffer = hb_itemSerial( pItem, ISLOG( 2 ) && hb_parl( 2 ), &ulSize );
|
||||
char * pBuffer = hb_itemSerialize( pItem, ISLOG( 2 ) && hb_parl( 2 ), &ulSize );
|
||||
hb_retclen_buffer( pBuffer, ulSize );
|
||||
}
|
||||
}
|
||||
@@ -1210,9 +1215,9 @@ HB_FUNC( HB_DESERIALIZE )
|
||||
|
||||
if( ulSize )
|
||||
{
|
||||
char * pBuffer = hb_parc( 1 );
|
||||
const char * pBuffer = hb_parc( 1 );
|
||||
|
||||
pItem = hb_itemDeserial( &pBuffer, &ulSize );
|
||||
pItem = hb_itemDeserialize( &pBuffer, &ulSize );
|
||||
if( pItem )
|
||||
{
|
||||
hb_itemReturn( pItem );
|
||||
|
||||
@@ -945,6 +945,20 @@ void hb_stackSetLang( void * pLang )
|
||||
hb_stack.pLang = pLang;
|
||||
}
|
||||
|
||||
#undef hb_stackGetI18N
|
||||
void * hb_stackGetI18N( void )
|
||||
{
|
||||
HB_STACK_TLS_PRELOAD
|
||||
return hb_stack.pI18N;
|
||||
}
|
||||
|
||||
#undef hb_stackSetI18N
|
||||
void hb_stackSetI18N( void * pI18N )
|
||||
{
|
||||
HB_STACK_TLS_PRELOAD
|
||||
hb_stack.pI18N = pI18N;
|
||||
}
|
||||
|
||||
#undef hb_stackItemBasePtr
|
||||
PHB_ITEM ** hb_stackItemBasePtr( void )
|
||||
{
|
||||
|
||||
@@ -752,6 +752,9 @@ void hb_vmThreadInit( void * Cargo )
|
||||
hb_cdpSelectID( pState->pszCDP );
|
||||
hb_langSelectID( pState->pszLang );
|
||||
|
||||
hb_vmSetI18N( pState->pI18N );
|
||||
pState->pI18N = NULL;
|
||||
|
||||
if( pState->pSet )
|
||||
{
|
||||
/* TODO: add set sharing */
|
||||
@@ -814,6 +817,7 @@ void hb_vmThreadQuit( void )
|
||||
hb_rddCloseAll(); /* close all workareas */
|
||||
hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */
|
||||
hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */
|
||||
hb_vmSetI18N( NULL ); /* remove i18n translation table */
|
||||
#ifndef HB_NO_DEBUG
|
||||
hb_vmDebuggerExit( FALSE ); /* deactivate debugger */
|
||||
#endif
|
||||
@@ -885,6 +889,8 @@ void hb_vmInit( BOOL bStartMainProc )
|
||||
s_VMFlags = hb_cmdargProcessVM( &s_VMCancelKey, &s_VMCancelKeyEx );
|
||||
hb_inkeySetCancelKeys( s_VMCancelKey, s_VMCancelKeyEx );
|
||||
|
||||
hb_i18n_init(); /* initialize i18n module */
|
||||
|
||||
#ifndef HB_NO_PROFILER
|
||||
/* Initialize opcodes profiler support arrays */
|
||||
{
|
||||
@@ -1021,8 +1027,6 @@ int hb_vmQuit( void )
|
||||
hb_itemClear( hb_stackReturnItem() );
|
||||
hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */
|
||||
|
||||
hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */
|
||||
|
||||
/* intentionally here to allow executing object destructors for all
|
||||
* cross referenced items before we release classy subsystem
|
||||
*/
|
||||
@@ -1034,7 +1038,12 @@ int hb_vmQuit( void )
|
||||
hb_stackSetActionRequest( 0 );
|
||||
hb_rddCloseAll(); /* close all workareas */
|
||||
hb_rddShutDown(); /* remove all registered RDD drivers */
|
||||
hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */
|
||||
hb_vmSetI18N( NULL ); /* remove i18n translation table */
|
||||
hb_i18n_exit(); /* unregister i18n module */
|
||||
|
||||
hb_itemClear( hb_stackReturnItem() );
|
||||
hb_gcCollectAll( TRUE );
|
||||
#ifndef HB_NO_DEBUG
|
||||
/* deactivate debugger */
|
||||
hb_vmDebuggerExit( TRUE );
|
||||
@@ -8020,6 +8029,21 @@ void hb_vmSetLang( PHB_LANG pLang )
|
||||
hb_stackSetLang( ( void * ) pLang );
|
||||
}
|
||||
|
||||
void * hb_vmI18N( void )
|
||||
{
|
||||
HB_STACK_TLS_PRELOAD
|
||||
|
||||
return hb_stackGetI18N();
|
||||
}
|
||||
|
||||
void hb_vmSetI18N( void * pI18N )
|
||||
{
|
||||
HB_STACK_TLS_PRELOAD
|
||||
|
||||
hb_i18n_release( hb_stackGetI18N() );
|
||||
hb_stackSetI18N( pI18N );
|
||||
}
|
||||
|
||||
#if defined( HB_MT_VM )
|
||||
# define HB_XVM_RETURN \
|
||||
if( hb_vmThreadRequest ) \
|
||||
|
||||
@@ -939,7 +939,7 @@ char * hb_macroGetType( HB_ITEM_PTR pItem )
|
||||
if( struMacro.pError )
|
||||
{
|
||||
ULONG ulGenCode;
|
||||
|
||||
|
||||
ulGenCode = hb_errGetGenCode( struMacro.pError );
|
||||
if( ulGenCode == EG_NOVAR || ulGenCode == EG_NOALIAS )
|
||||
{
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
#include "hbvmopt.h"
|
||||
#include "hbthread.h"
|
||||
#include "hbatomic.h"
|
||||
#include "hbapiitm.h"
|
||||
#include "hbapierr.h"
|
||||
#include "hbapicdp.h"
|
||||
@@ -196,6 +197,87 @@ ULONG _hb_gettid( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* atomic increment/decrement operations
|
||||
*/
|
||||
#if !defined( HB_MT_VM )
|
||||
void hb_atomic_set( volatile HB_COUNTER * pCounter, HB_COUNTER value )
|
||||
{
|
||||
*pCounter = value;
|
||||
}
|
||||
|
||||
HB_COUNTER hb_atomic_get( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
return *pCounter;
|
||||
}
|
||||
|
||||
void hb_atomic_inc( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
++( *pCounter );
|
||||
}
|
||||
|
||||
BOOL hb_atomic_dec( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
return --( *pCounter ) == 0;
|
||||
}
|
||||
#elif defined( HB_ATOM_INC ) && defined( HB_ATOM_DEC ) && \
|
||||
defined( HB_ATOM_GET ) && defined( HB_ATOM_SET )
|
||||
void hb_atomic_set( volatile HB_COUNTER * pCounter, HB_COUNTER value )
|
||||
{
|
||||
HB_ATOM_SET( pCounter, value );
|
||||
}
|
||||
|
||||
HB_COUNTER hb_atomic_get( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
return HB_ATOM_GET( pCounter );
|
||||
}
|
||||
|
||||
void hb_atomic_inc( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
HB_ATOM_INC( pCounter );
|
||||
}
|
||||
|
||||
BOOL hb_atomic_dec( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
return HB_ATOM_DEC( pCounter ) == 0;
|
||||
}
|
||||
#else
|
||||
static HB_CRITICAL_NEW( s_atomicMtx );
|
||||
void hb_atomic_set( volatile HB_COUNTER * pCounter, HB_COUNTER value )
|
||||
{
|
||||
/* NOTE: on some platforms it may be necessary to protect this
|
||||
* by cirtical section, f.e. when HB_COUNTER cannot be accessed
|
||||
* using single memory access by CPU.
|
||||
*/
|
||||
*pCounter = value;
|
||||
}
|
||||
|
||||
HB_COUNTER hb_atomic_get( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
/* NOTE: on some platforms it may be necessary to protect this
|
||||
* by cirtical section, f.e. when HB_COUNTER cannot be accessed
|
||||
* using single memory access by CPU.
|
||||
*/
|
||||
return *pCounter;
|
||||
}
|
||||
|
||||
void hb_atomic_inc( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
hb_threadEnterCriticalSection( &s_atomicMtx );
|
||||
++( *pCounter );
|
||||
hb_threadLeaveCriticalSection( &s_atomicMtx );
|
||||
}
|
||||
|
||||
BOOL hb_atomic_dec( volatile HB_COUNTER * pCounter )
|
||||
{
|
||||
BOOL fResult;
|
||||
hb_threadEnterCriticalSection( &s_atomicMtx );
|
||||
fResult = --( *pCounter ) == 0;
|
||||
hb_threadLeaveCriticalSection( &s_atomicMtx );
|
||||
return fResult;
|
||||
}
|
||||
#endif
|
||||
|
||||
void hb_threadEnterCriticalSection( HB_CRITICAL_T * critical )
|
||||
{
|
||||
#if !defined( HB_MT_VM )
|
||||
@@ -480,6 +562,11 @@ static HB_GARBAGE_FUNC( hb_threadDestructor )
|
||||
hb_itemRelease( pThread->pResult );
|
||||
pThread->pResult = NULL;
|
||||
}
|
||||
if( pThread->pI18N )
|
||||
{
|
||||
hb_i18n_release( pThread->pI18N );
|
||||
pThread->pI18N = NULL;
|
||||
}
|
||||
if( pThread->pSet )
|
||||
{
|
||||
hb_setRelease( pThread->pSet );
|
||||
@@ -657,6 +744,7 @@ HB_FUNC( HB_THREADSTART )
|
||||
|
||||
pThread->pszCDP = hb_cdpID();
|
||||
pThread->pszLang = hb_langID();
|
||||
pThread->pI18N = hb_i18n_alloc( hb_vmI18N() );
|
||||
pThread->pszDefRDD = hb_stackRDD()->szDefaultRDD;
|
||||
pThread->pSet = hb_setClone( hb_stackSetStruct() );
|
||||
pThread->pParams = hb_arrayBaseParams();
|
||||
|
||||
Reference in New Issue
Block a user