2014-11-04 01:54 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* ChangeLog.txt
  * doc/xhb-diff.txt
    ! typos

  * doc/clipper.txt
    ! removed completely false information about 'LIST &cMacro'
    * updated information about FOR EACH
    ; in general information in this file are outdated and does not
      correctly describe current Harbour behavior. I strongly suggest
      to not use it in any other documentation. In some spare time
      I'll update this file or remove.

  * doc/cmpopt.txt
    + added information about unsupported by Clipper syntax extension:
         iif( <expr1>, <expr2>, <expr3> ) <op>= <expr4>

  * include/hbrddnsx.h
    * minor modification in comment

  * src/macro/macrolex.c
    * accept unconditionally hash 'key => value' operator

  * src/rdd/dbfnsx/dbfnsx1.c
    ! fixed very bad bug in leaf key compression. This problem could be
      exploited by keys containing containing CHR( 255 ) in encoded keys
      just before trailing empty key characters.
      This bug could cause index corruption.
    * use hb_xgrabz()
    * formatting
This commit is contained in:
Przemysław Czerpak
2014-11-04 01:54:04 +01:00
parent 67722a56d0
commit ff1288dc3f
7 changed files with 149 additions and 112 deletions

View File

@@ -10,6 +10,37 @@
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
*/
2014-11-04 01:54 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* ChangeLog.txt
* doc/xhb-diff.txt
! typos
* doc/clipper.txt
! removed completely false information about 'LIST &cMacro'
* updated information about FOR EACH
; in general information in this file are outdated and does not
correctly describe current Harbour behavior. I strongly suggest
to not use it in any other documentation. In some spare time
I'll update this file or remove.
* doc/cmpopt.txt
+ added information about unsupported by Clipper syntax extension:
iif( <expr1>, <expr2>, <expr3> ) <op>= <expr4>
* include/hbrddnsx.h
* minor modification in comment
* src/macro/macrolex.c
* accept unconditionally hash 'key => value' operator
* src/rdd/dbfnsx/dbfnsx1.c
! fixed very bad bug in leaf key compression. This problem could be
exploited by keys containing containing CHR( 255 ) in encoded keys
just before trailing empty key characters.
This bug could cause index corruption.
* use hb_xgrabz()
* formatting
2014-10-28 16:06 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* doc/xhb-diff.txt
* updated information about extended CDX format and defined by user
@@ -22555,7 +22586,7 @@
+ added new harbour compiler switch:
-kd => accept macros with declared symbols
This switch allows to use declared symbols like LOCALs, STATICs
and FIELDs in macros and macrocodeblocks (every evaluated).
and FIELDs in macros and macrocodeblocks (early evaluated).
; Please do not confuse different things. Above modification
does not mean to that such variables are visible for macro
compiler. It only allows to write code like:

View File

@@ -30,23 +30,6 @@ Both these extra layers are activated by default.
* See also -k Compiler switch.
LIST Command
------------
LIST &cMacro
LIST in CA-Cl*pper [superficially] supports macros of lists expressions.
No error will be produced, and all expressions in the list will be
evaluated, but *only* the *last* expression will be displayed. This is
not documented in either the LIST Command or the Macro Operator
descriptions, but is the de-facto behavior in all CA-Cl*pper 5.x versions.
Harbour instead will not only evaluate all of the expressions in
such list macro, but will also display all such values. This default
behavior may be disabled with hb_SetMacro( HB_SM_XBASE, .F. )*
* See also -k Compiler switch.
INIT/EXIT and startup procedures
--------------------------------
@@ -67,17 +50,37 @@ Harbour has support enumeration loop with the following syntax:
NEXT
Note:
- expr can be a string or an array
- expr can be a string, an array, an hash array or an object with
custom FOR EACH action
- enumerator variable 'var<n>' stores a reference to the element of
an array or a string specified by 'expr<n>' thus assigments to the
enumerator changes the value of given array element
- after the loop the controlling variable(s) store the value which
an hash, array or a string specified by 'expr<n>' thus assignments
to the enumerator changes the value of given element of iterated
item. If FOR EACH is used to iterate string items them assignment
to enumerator item changes the original string only if it was passed
to FOR EACH statement by reference, i.e.:
FOR EACH c IN @string
IF ! isAlpha( c )
c := "*"
ELSE
c := upper( c )
ENDIF
NEXT
- after the loop the controlling variable(s) restore the value which
they had before entering the loop
- the enumeraqtor variable supports the following properties
:__enumindex - the loop counter for variable
:__enumbase - the value that is being traversed
:__enumvalue - the value of variable
- the enumerator variable supports the following properties
:__enumIndex - the loop counter for variable
:__enumKey - the hash key value of traversed hash item pair
:__enumBase - the value that is being traversed
:__enumValue - the value of variable
:__enumIsFirst - is it the first enumerated item?
:__enumIsLast - is it the last enumerated item?
- defining new class or overloading existing one user can define
his own behavior of FOR EACH iterating overloading chosen of above
methods and/or the following ones:
:__enumStart
:__enumSkip
:__enumStop
By default FOR EACH iterate all object instance variables
for example:
a := 'A'

View File

@@ -146,6 +146,20 @@ arguments are well known and can be calculated at compile time:
( <expr> ) => <expr> // it allows to optimize
// expresions like: 1+(2)
- Harbour syntax extensions not supported by Clipper, enabled by -ko
compiler switch:
iif( <expr1>, <expr2>, <expr3> ) <op>= <expr4> => ;
IF <expr1> ;
<expr2> <op>= <expr4> ;
ELSE ;
<expr3> <op>= <expr4> ;
ENDIF
i.e.:
iif( dData == NIL, dDate, aVal[ 1 ] ) := date()
iif( empty( x ), aVal[ 2 ], nTmp ) += 10
? iif( f1(), nVal1, nVal2 ) ++
? -- iif( f2(), aVal[ 1 ], hVal[ "abc" ] )
- Harbour extensions which may disable RT errors in wrong expressions
or can change used operators using basic math rules. Enabled by -ko
compiler switch:

View File

@@ -121,7 +121,7 @@ file system(s) and with different OS(s).
"=>", x:__enumBase()[ x:__enumKey() ]
NEXT
f) it gives very flexible OOP mechanism to overload FOR EACH behavior
for user define objects adding to above enumerator methods also
for user defined classes adding to above enumerator methods also
__enumStart(), __enumStop(), __enumSkip() methods what allows to
implement many different enumeration algorithms depending on used
data

View File

@@ -335,11 +335,11 @@ typedef struct _NSXLEAFKEY
* if Size == n + 1 then key is fully duplicated
*/
HB_UCHAR DupCount[1]; /* number of bytes from previous key */
HB_UCHAR KeyData[l]; /* rest of key value with RLE compression:
HB_UCHAR KeyData[m]; /* rest of key value with RLE compression:
* FF xx yy => Replicate(yy, xx)
* FF 01 => FF
* l = Size - n - 2
* if l == KEY_SIZE - DupCount then key value
* m = Size - n - 2
* if m == KEY_SIZE - DupCount then key value
* is stored as raw data and can be copied as is
* if after decompression size of key value is
* smaller then KEY_SIZE then rest if filled with

View File

@@ -338,7 +338,7 @@ int hb_macro_yylex( YYSTYPE * yylval_ptr, PHB_MACRO pMacro )
pLex->nSrc++;
return EQ;
}
else if( pLex->pString[ pLex->nSrc ] == '>' && HB_SUPPORT_HARBOUR )
else if( pLex->pString[ pLex->nSrc ] == '>' )
{
pLex->nSrc++;
return HASHOP;

View File

@@ -341,9 +341,9 @@ static HB_USHORT hb_nsxLeafPutKey( LPTAGINFO pTag, LPPAGEINFO pPage, HB_USHORT u
HB_UCHAR * bPrevValue, HB_UCHAR * pKeyValue, HB_ULONG ulRecNo )
{
HB_UCHAR * ptr = ( HB_UCHAR * ) hb_nsxPageBuffer( pPage ) + uiOffset,
* pDst, * pSrc, * pEnd;
* pDst, * pSrc, * pEnd;
HB_UCHAR ucSize = hb_nsxGetKeyRecSize( pPage ), ucDupCount = 0,
ucLen = ( HB_UCHAR ) pTag->KeyLength;
ucLen = ( HB_UCHAR ) pTag->KeyLength;
int iMax;
if( uiOffset + ucSize >= NSX_PAGELEN )
@@ -401,70 +401,68 @@ static HB_USHORT hb_nsxLeafPutKey( LPTAGINFO pTag, LPPAGEINFO pPage, HB_USHORT u
}
pDst = ptr + 2;
iMax = NSX_PAGELEN - uiOffset - ucSize;
if( iMax >= ( int ) ucLen )
iMax = ucLen - 1;
while( iMax > 0 && pSrc < pEnd )
iMax = NSX_PAGELEN - uiOffset - ucSize + 1;
if( iMax > ( int ) ucLen )
iMax = ucLen;
if( iMax > 0 )
{
HB_UCHAR uc = *pSrc++;
if( pSrc < pEnd - 2 && uc == *pSrc && uc == pSrc[ 1 ] )
while( pSrc < pEnd )
{
HB_UCHAR ucRepl = 3;
iMax -= 3;
if( iMax < 0 )
break;
pSrc += 2;
while( pSrc < pEnd && *pSrc == uc )
HB_UCHAR uc = *pSrc++;
if( uc == NSX_RLE_CHAR )
{
++pSrc;
++ucRepl;
if( pSrc < pEnd && *pSrc == NSX_RLE_CHAR )
{
HB_UCHAR ucRepl = 2;
if( ( iMax -= 3 ) <= 0 )
break;
++pSrc;
while( pSrc < pEnd && *pSrc == NSX_RLE_CHAR )
{
++pSrc;
++ucRepl;
}
*pDst++ = NSX_RLE_CHAR;
*pDst++ = ucRepl;
*pDst++ = NSX_RLE_CHAR;
}
else
{
if( ( iMax -= 2 ) <= 0 )
break;
*pDst++ = NSX_RLE_CHAR;
*pDst++ = 1;
}
}
*pDst++ = NSX_RLE_CHAR;
*pDst++ = ucRepl;
*pDst++ = uc;
}
else if( uc == NSX_RLE_CHAR )
{
if( pSrc < pEnd && uc == *pSrc )
else if( pEnd - pSrc > 2 &&
*pSrc == uc && pSrc[ 1 ] == uc && pSrc[ 2 ] == uc )
{
HB_UCHAR ucRepl = 2;
iMax -= 3;
if( iMax < 0 )
HB_UCHAR ucRepl = 4;
if( ( iMax -= 3 ) <= 0 )
break;
++pSrc;
if( pSrc < pEnd && uc == pSrc[ 1 ] )
pSrc += 3;
while( pSrc < pEnd && *pSrc == uc )
{
++pSrc;
++ucRepl;
}
*pDst++ = NSX_RLE_CHAR;
*pDst++ = ucRepl;
*pDst++ = NSX_RLE_CHAR;
*pDst++ = uc;
}
else if( --iMax == 0 )
break;
else
{
iMax -= 2;
if( iMax < 0 )
break;
*pDst++ = NSX_RLE_CHAR;
*pDst++ = 1;
}
*pDst++ = uc;
}
else
if( iMax > 0 )
{
iMax--;
*pDst++ = uc;
ucSize += ( HB_UCHAR ) ( pDst - ( ptr + 2 ) );
*ptr = ucSize;
return uiOffset + ucSize;
}
}
if( pSrc == pEnd )
{
ucSize += ( HB_UCHAR ) ( pDst - ( ptr + 2 ) );
*ptr = ucSize;
return uiOffset + ucSize;
}
uiOffset += ucSize + ucLen;
if( uiOffset > NSX_PAGELEN )
return 0;
@@ -1293,7 +1291,7 @@ static HB_BOOL hb_nsxTagHeaderCheck( LPTAGINFO pTag )
{
if( header.Signature[ 0 ] == NSX_SIGNATURE )
{
pTag->TagFlags = header.TagFlags[0];
pTag->TagFlags = header.TagFlags[ 0 ];
pTag->RootBlock = HB_GET_LE_UINT32( header.RootPage );
hb_nsxTagUpdateFlags( pTag );
}
@@ -1414,9 +1412,8 @@ static LPPAGEINFO hb_nsxPageGetBuffer( LPTAGINFO pTag, HB_ULONG ulPage )
pIndex->ulPages = 1;
pIndex->ulPageLast = 0;
pIndex->ulPagesDepth = NSX_PAGE_BUFFER;
pIndex->pages = ( LPPAGEINFO * ) hb_xgrab( sizeof( LPPAGEINFO ) * NSX_PAGE_BUFFER );
memset( pIndex->pages, 0, sizeof( LPPAGEINFO ) * NSX_PAGE_BUFFER );
pPagePtr = &pIndex->pages[0];
pIndex->pages = ( LPPAGEINFO * ) hb_xgrabz( sizeof( LPPAGEINFO ) * NSX_PAGE_BUFFER );
pPagePtr = &pIndex->pages[ 0 ];
}
else
{
@@ -1449,14 +1446,12 @@ static LPPAGEINFO hb_nsxPageGetBuffer( LPTAGINFO pTag, HB_ULONG ulPage )
if( ! *pPagePtr )
{
*pPagePtr = ( LPPAGEINFO ) hb_xgrab( sizeof( HB_PAGEINFO ) );
memset( *pPagePtr, 0, sizeof( HB_PAGEINFO ) );
*pPagePtr = ( LPPAGEINFO ) hb_xgrabz( sizeof( HB_PAGEINFO ) );
}
#ifdef HB_NSX_EXTERNAL_PAGEBUFFER
if( ! hb_nsxPageBuffer( *pPagePtr ) )
{
hb_nsxPageBuffer( *pPagePtr ) = ( HB_UCHAR * ) hb_xgrab( NSX_PAGELEN );
memset( hb_nsxPageBuffer( *pPagePtr ), 0, NSX_PAGELEN );
hb_nsxPageBuffer( *pPagePtr ) = ( HB_UCHAR * ) hb_xgrabz( NSX_PAGELEN );
}
#endif
( *pPagePtr )->pPrev = NULL;
@@ -1695,8 +1690,7 @@ static LPTAGINFO hb_nsxTagNew( LPNSXINDEX pIndex, const char * szTagName,
{
LPTAGINFO pTag;
pTag = ( LPTAGINFO ) hb_xgrab( sizeof( TAGINFO ) );
memset( pTag, 0, sizeof( TAGINFO ) );
pTag = ( LPTAGINFO ) hb_xgrabz( sizeof( TAGINFO ) );
pTag->TagName = hb_strndup( szTagName, NSX_TAGNAME );
pTag->pIndex = pIndex;
if( szKeyExpr )
@@ -1930,12 +1924,12 @@ static HB_ERRCODE hb_nsxTagHeaderSave( LPTAGINFO pTag )
hb_nsxIndexTagAdd( pIndex, pTag );
}
Header.Signature[0] = NSX_SIGNATURE;
Header.TagFlags[0] = ( pTag->Partial ? NSX_TAG_PARTIAL : 0 ) |
( pTag->Template ? NSX_TAG_TEMPLATE : 0 ) |
( pTag->ChgOnly ? NSX_TAG_CHGONLY : 0 ) |
( pTag->Custom ? NSX_TAG_NOUPDATE : 0 ) |
( pTag->MultiKey ? NSX_TAG_MULTIKEY : 0 );
Header.Signature[ 0 ] = NSX_SIGNATURE;
Header.TagFlags[ 0 ] = ( pTag->Partial ? NSX_TAG_PARTIAL : 0 ) |
( pTag->Template ? NSX_TAG_TEMPLATE : 0 ) |
( pTag->ChgOnly ? NSX_TAG_CHGONLY : 0 ) |
( pTag->Custom ? NSX_TAG_NOUPDATE : 0 ) |
( pTag->MultiKey ? NSX_TAG_MULTIKEY : 0 );
HB_PUT_LE_UINT32( Header.RootPage, pTag->RootBlock );
if( pIndex->Update )
@@ -1948,8 +1942,8 @@ static HB_ERRCODE hb_nsxTagHeaderSave( LPTAGINFO pTag )
HB_PUT_LE_UINT16( Header.KeyType, type );
HB_PUT_LE_UINT16( Header.KeySize, pTag->KeyLength );
Header.Unique[0] = pTag->UniqueKey ? 1 : 0;
Header.Descend[0] = pTag->AscendKey ? 0 : 1;
Header.Unique[ 0 ] = pTag->UniqueKey ? 1 : 0;
Header.Descend[ 0 ] = pTag->AscendKey ? 0 : 1;
iLen = ( int ) strlen( pTag->KeyExpr );
if( iLen > NSX_MAXEXPLEN )
@@ -1981,8 +1975,7 @@ static LPNSXINDEX hb_nsxIndexNew( NSXAREAP pArea )
{
LPNSXINDEX pIndex;
pIndex = ( LPNSXINDEX ) hb_xgrab( sizeof( NSXINDEX ) );
memset( pIndex, 0, sizeof( NSXINDEX ) );
pIndex = ( LPNSXINDEX ) hb_xgrabz( sizeof( NSXINDEX ) );
pIndex->pFile = NULL;
pIndex->pArea = pArea;
@@ -2027,9 +2020,9 @@ static HB_ERRCODE hb_nsxIndexHeaderSave( LPNSXINDEX pIndex )
pIndex->Version++;
pIndex->Version &= 0xFFFF;
pIndex->HeaderBuff.Signature[0] = pIndex->LargeFile ?
NSX_SIGNATURE_LARGE : NSX_SIGNATURE;
pIndex->HeaderBuff.IndexFlags[0] = 0;
pIndex->HeaderBuff.Signature[ 0 ] = pIndex->LargeFile ?
NSX_SIGNATURE_LARGE : NSX_SIGNATURE;
pIndex->HeaderBuff.IndexFlags[ 0 ] = 0;
HB_PUT_LE_UINT16( pIndex->HeaderBuff.TagCount, pIndex->iTags );
HB_PUT_LE_UINT16( pIndex->HeaderBuff.Version, pIndex->Version );
HB_PUT_LE_UINT32( pIndex->HeaderBuff.FreePage, pIndex->NextAvail );
@@ -2487,8 +2480,7 @@ static void hb_nsxTagSetPageStack( LPTAGINFO pTag, LPPAGEINFO pPage, HB_USHORT u
if( pTag->stackSize == 0 )
{
pTag->stackSize = NSX_STACKSIZE;
pTag->stack = ( LPTREESTACK ) hb_xgrab( sizeof( TREE_STACK ) * NSX_STACKSIZE );
memset( pTag->stack, 0, sizeof( TREE_STACK ) * NSX_STACKSIZE );
pTag->stack = ( LPTREESTACK ) hb_xgrabz( sizeof( TREE_STACK ) * NSX_STACKSIZE );
}
else
{
@@ -2556,8 +2548,7 @@ static LPPAGEINFO hb_nsxPageBottomMove( LPTAGINFO pTag, HB_ULONG ulPage )
return NULL;
if( hb_nsxIsLeaf( pPage ) )
{
hb_nsxTagSetPageStack( pTag, pPage, pPage->uiKeys -
( pPage->uiKeys == 0 ? 0 : 1 ) );
hb_nsxTagSetPageStack( pTag, pPage, ( pPage->uiKeys > 0 ? pPage->uiKeys - 1 : 0 ) );
if( pPage->uiKeys == 0 && pTag->stackLevel > 1 && ! pTag->pIndex->pArea->pSort )
{
hb_nsxPageRelease( pTag, pPage );
@@ -5440,8 +5431,7 @@ static LPNSXSORTINFO hb_nsxSortNew( LPTAGINFO pTag, HB_ULONG ulRecCount )
if( ulRecCount == 0 )
ulRecCount = 1;
pSort = ( LPNSXSORTINFO ) hb_xgrab( sizeof( NSXSORTINFO ) );
memset( pSort, 0, sizeof( NSXSORTINFO ) );
pSort = ( LPNSXSORTINFO ) hb_xgrabz( sizeof( NSXSORTINFO ) );
ulMin = ( HB_ULONG ) ceil( sqrt( ( double ) ulRecCount ) );
ulMax = ( ( HB_ULONG ) ceil( sqrt( ( double ) ulRecCount / ( iLen + 4 ) ) ) ) << 7;
@@ -5512,8 +5502,7 @@ static LPNSXSORTINFO hb_nsxSortNew( LPTAGINFO pTag, HB_ULONG ulRecCount )
/* check for overflow on 32 bit machines when number of records is nearly 2^32 */
if( ! pSort->ulPages )
pSort->ulPages = ulRecCount / pSort->ulPgKeys + 1;
pSort->pSwapPage = ( LPNSXSWAPPAGE ) hb_xgrab( sizeof( NSXSWAPPAGE ) * pSort->ulPages );
memset( pSort->pSwapPage, 0, sizeof( NSXSWAPPAGE ) * pSort->ulPages );
pSort->pSwapPage = ( LPNSXSWAPPAGE ) hb_xgrabz( sizeof( NSXSWAPPAGE ) * pSort->ulPages );
return pSort;
}
@@ -8272,8 +8261,8 @@ HB_CALL_ON_STARTUP_BEGIN( _hb_dbfnsx_rdd_init_ )
HB_CALL_ON_STARTUP_END( _hb_dbfnsx_rdd_init_ )
#if defined( HB_PRAGMA_STARTUP )
# pragma startup dbfnsx1__InitSymbols
# pragma startup _hb_dbfnsx_rdd_init_
#pragma startup dbfnsx1__InitSymbols
#pragma startup _hb_dbfnsx_rdd_init_
#elif defined( HB_DATASEG_STARTUP )
#define HB_DATASEG_BODY HB_DATASEG_FUNC( dbfnsx1__InitSymbols ) \
HB_DATASEG_FUNC( _hb_dbfnsx_rdd_init_ )