Files correlati : cb6.dll Ricompilazione Demo : [ ] Commento : Modifiche per la compilazione Linux git-svn-id: svn://10.65.10.50/trunk@11080 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			2063 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2063 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* i4tag.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifdef __TURBOC__
 | 
						|
   #pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
/*#ifndef S4LANGUAGE */
 | 
						|
/*#ifndef u4memcmp */
 | 
						|
/*int S4CALL u4memcmp( S4CMP_PARM p1, S4CMP_PARM p2, size_t len ) */
 | 
						|
/*{ */
 | 
						|
/*   return memcmp( p1, p2, len ) ; */
 | 
						|
/*} */
 | 
						|
/*#endif */
 | 
						|
/*#endif */
 | 
						|
 | 
						|
#ifndef S4OFF_INDEX
 | 
						|
 | 
						|
#ifndef S4CLIENT
 | 
						|
int tfile4unique( TAG4FILE *tag, const short int errUnique )
 | 
						|
{
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( ( tag->header.typeCode & 0x01 ) || ( tag->header.typeCode & 0x04 ) )
 | 
						|
   #else
 | 
						|
      if ( tag->header.unique )
 | 
						|
   #endif
 | 
						|
         return errUnique ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4CLIENT */
 | 
						|
 | 
						|
short int S4FUNCTION t4unique( const TAG4 *tag )
 | 
						|
{
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      #ifdef S4CB51
 | 
						|
         if ( c4parm_check ( tag, 4, E40150 ) ) return 0 ;
 | 
						|
      #else
 | 
						|
         if ( c4parm_check ( tag, 4, E91639 ) ) return 0 ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( tag == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91639 ) ;
 | 
						|
      if ( tag->tagFile == 0 )
 | 
						|
         return error4( 0, e4parm, E91639 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4CLIENT
 | 
						|
      return tag->errUnique ;
 | 
						|
   #else
 | 
						|
      return tfile4unique( tag->tagFile, tag->errUnique ) ;
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4SERVER
 | 
						|
int t4uniqueSetLow( TAG4 *, const int, const int ) ;
 | 
						|
 | 
						|
int S4FUNCTION t4uniqueSet( TAG4 *t4, const int uniqueCode )
 | 
						|
{
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check ( t4, 4, E91601 ) ) return 0 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91601 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( uniqueCode == t4unique( t4 ) )  /* possibly both zero ok */
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   /* if not zero matches, then neither should be zero */
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      #ifdef S4CLIENT_OR_FOX
 | 
						|
         if ( t4unique( t4 ) == r4candidate )
 | 
						|
         {
 | 
						|
            if ( uniqueCode != e4candidate )
 | 
						|
               return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
            return t4uniqueSetLow( t4, uniqueCode, 1 ) ;
 | 
						|
         }
 | 
						|
         if ( t4unique( t4 ) == e4candidate )
 | 
						|
         {
 | 
						|
            if ( uniqueCode != r4candidate )
 | 
						|
               return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
            return t4uniqueSetLow( t4, uniqueCode, 1 ) ;
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
      if ( uniqueCode != e4unique && uniqueCode != r4unique && uniqueCode != r4uniqueContinue )
 | 
						|
         return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return t4uniqueSetLow( t4, uniqueCode, 1 ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif  /* S4OFF_INDEX */
 | 
						|
 | 
						|
#ifdef S4CLIENT
 | 
						|
#ifndef S4OFF_INDEX
 | 
						|
int t4uniqueSetLow( TAG4 *t4, const int uniqueCode, const int doZeroCheck )
 | 
						|
{
 | 
						|
   CONNECTION4 *connection ;
 | 
						|
   CONNECTION4UNIQUE_INFO_IN infoIn ;
 | 
						|
   CONNECTION4UNIQUE_TAG_INFO tagInfo ;
 | 
						|
   int rc ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      TRAN4 *trans ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = t4->index->data->codeBase ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      if ( code4transEnabled( c4 ) && doZeroCheck == 1 )  /* user cannot request from within transaction */
 | 
						|
      {
 | 
						|
         trans = code4trans( c4 ) ;
 | 
						|
         if ( trans->currentTranStatus == r4active )
 | 
						|
            return error4( c4, e4transViolation, E81608 ) ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( uniqueCode == t4unique( t4 ) )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   /* verify that the tag is unique before setting */
 | 
						|
   if ( doZeroCheck )
 | 
						|
      if ( t4unique( t4 ) == 0 )
 | 
						|
         return error4( c4, e4parm, E81609 ) ;
 | 
						|
 | 
						|
   connection = t4->index->data->dataFile->connection ;
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( connection == 0 )
 | 
						|
         return error4( c4, e4struct, E91601 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = connection4assign( connection, CON4UNIQUE_SET, data4clientId( t4->index->data ), data4serverId( t4->index->data ) ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( c4, rc, E91601 ) ;
 | 
						|
   infoIn.numTags = 1 ;
 | 
						|
   tagInfo.unique = uniqueCode ;
 | 
						|
   memcpy( tagInfo.alias, t4->tagFile->alias, LEN4TAG_ALIAS ) ;
 | 
						|
   tagInfo.alias[LEN4TAG_ALIAS] = 0 ;
 | 
						|
   connection4addData( connection, &infoIn, sizeof(CONNECTION4UNIQUE_INFO_IN), 0 ) ;
 | 
						|
   connection4addData( connection, &tagInfo, sizeof(CONNECTION4UNIQUE_TAG_INFO), 0 ) ;
 | 
						|
   connection4send( connection ) ;
 | 
						|
   rc = connection4receive( connection ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( c4, rc, E91601 ) ;
 | 
						|
 | 
						|
   rc = connection4status( connection ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return connection4error( connection, c4, rc, E91601 ) ;
 | 
						|
 | 
						|
   t4->errUnique = uniqueCode ;
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_INDEX */
 | 
						|
#else
 | 
						|
#ifndef S4OFF_INDEX
 | 
						|
#ifdef S4STAND_ALONE
 | 
						|
int t4uniqueSetLow( TAG4 *t4, const int uniqueCode, const int doZeroCheck )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91601 ) ;
 | 
						|
      #ifdef S4CLIENT_OR_FOX
 | 
						|
         if ( t4unique( t4 ) == r4candidate )  /* can't change a candidate setting */
 | 
						|
         {
 | 
						|
            if ( uniqueCode != e4candidate )
 | 
						|
               return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            if ( t4unique( t4 ) == e4candidate )  /* can't change a candidate setting */
 | 
						|
            {
 | 
						|
               if ( uniqueCode != r4candidate )
 | 
						|
                  return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
      #endif
 | 
						|
      if ( uniqueCode != e4unique && uniqueCode != r4unique && uniqueCode != r4uniqueContinue && uniqueCode != 0 )
 | 
						|
         return error4( t4->index->data->codeBase, e4parm, E91601 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   /* verify that the tag is unqiue before setting */
 | 
						|
   if ( doZeroCheck )
 | 
						|
      if ( t4unique( t4 ) == 0 )
 | 
						|
         return error4( t4->index->data->codeBase, e4parm, E81609 ) ;
 | 
						|
 | 
						|
   t4->errUnique = uniqueCode ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif  /* S4STAND_ALONE */
 | 
						|
 | 
						|
long tfile4dskip( TAG4FILE *t4, long numSkip )
 | 
						|
{
 | 
						|
   #ifdef S4HAS_DESCENDING
 | 
						|
      #ifdef E4PARM_LOW
 | 
						|
         if ( t4 == 0 )
 | 
						|
            return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      if ( t4->header.descending )
 | 
						|
         return -tfile4skip( t4, -numSkip ) ;
 | 
						|
      else
 | 
						|
   #endif /* S4HAS_DESCENDING */
 | 
						|
      return tfile4skip( t4, numSkip ) ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4outOfDate( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifndef S4SINGLE
 | 
						|
      time_t oldTime ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4SINGLE
 | 
						|
      return error4describe( t4->codeBase, e4index, E81605, tfile4alias( t4 ), 0, 0 ) ;
 | 
						|
   #else
 | 
						|
      /* first make sure we are at a potential read conflict situation (otherwise must be corrupt file) */
 | 
						|
      #ifdef N4OTHER
 | 
						|
         if ( tfile4lockTest( t4 ) )
 | 
						|
      #else
 | 
						|
         if ( index4lockTest( t4->indexFile ) )
 | 
						|
      #endif
 | 
						|
         return error4describe( t4->codeBase, e4index, E81606, tfile4alias( t4 ), 0, 0 ) ;
 | 
						|
 | 
						|
      /* wait a second and refresh */
 | 
						|
      time( &oldTime) ;
 | 
						|
      while ( time( (time_t *)0 ) <= oldTime) ;
 | 
						|
      tfile4freeAll( t4 ) ;
 | 
						|
      #ifdef N4OTHER
 | 
						|
         return file4refresh( &t4->file ) ;
 | 
						|
      #else
 | 
						|
         return file4refresh( &t4->indexFile->file ) ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
/* uses parent to determine if an inconsistancy has arisen */
 | 
						|
/* return <0 = error, 0 = success, 1 = inconsistant */
 | 
						|
int i4readBlock( FILE4 *file, const long blockNo, B4BLOCK *parent, B4BLOCK *b4 )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
   TAG4FILE *tag ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
   #ifndef N4OTHER
 | 
						|
      INDEX4FILE *i4file ;
 | 
						|
   #endif
 | 
						|
   #ifdef S4BYTE_SWAP
 | 
						|
      char *swapPtr ;
 | 
						|
      int i ;
 | 
						|
      S4LONG longVal ;
 | 
						|
      #ifdef S4FOX
 | 
						|
         short shortVal ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
   #ifdef S4MDX
 | 
						|
      int parOn, blkOn, eq ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( file == 0 || blockNo < 0 || b4 == 0 )
 | 
						|
         return error4( 0, e4parm, E91604 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   tag = b4->tag ;
 | 
						|
   #ifndef N4OTHER
 | 
						|
      i4file = tag->indexFile ;
 | 
						|
   #endif
 | 
						|
   c4 = tag->codeBase ;
 | 
						|
 | 
						|
   #ifdef S4MDX
 | 
						|
      /* i.e. if ndx or mdx */
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         i4file->readBlockTag = tag ;
 | 
						|
      #endif
 | 
						|
      rc = file4readAll( file, I4MULTIPLY * blockNo, &b4->nKeys, i4file->header.blockRw ) ;
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         i4file->readBlockTag = 0 ;
 | 
						|
      #endif
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         /* swap the numKeys value */
 | 
						|
         b4->nKeys = x4reverseShort( (void *)&b4->nKeys ) ;
 | 
						|
 | 
						|
         /* position swapPtr at beginning of B4KEY's */
 | 
						|
         swapPtr = (char *)&b4->nKeys ;
 | 
						|
         swapPtr += 6 + sizeof(short) ;
 | 
						|
 | 
						|
         /* move through all B4KEY's to swap 'long' */
 | 
						|
         for ( i = 0 ; i < (int)b4numKeys( b4 ) ; i++ )
 | 
						|
         {
 | 
						|
            longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
            memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
 | 
						|
            swapPtr += tag->header.groupLen ;
 | 
						|
         }
 | 
						|
 | 
						|
         /* mark lastPointer */
 | 
						|
         if ( !b4leaf( b4 ) )
 | 
						|
         {
 | 
						|
            longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
            memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
 | 
						|
         }
 | 
						|
      #endif  /* S4BYTE_SWAP */
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = 0 ;
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         i4file->readBlockTag = tag ;
 | 
						|
      #endif
 | 
						|
      rc = file4readAll( file, I4MULTIPLY * blockNo, &b4->header, B4BLOCK_SIZE ) ;
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         i4file->readBlockTag = 0 ;
 | 
						|
      #endif
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( c4, (short)rc, E91604 ) ;
 | 
						|
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            b4->header.nodeAttribute = x4reverseShort( (void *)&b4->header.nodeAttribute ) ;
 | 
						|
            b4->header.nKeys = x4reverseShort( (void *)&b4->header.nKeys ) ;
 | 
						|
            b4->header.leftNode = x4reverseLong( (void *)&b4->header.leftNode ) ;
 | 
						|
            b4->header.rightNode = x4reverseLong( (void *)&b4->header.rightNode ) ;
 | 
						|
 | 
						|
            /* if b4 is a leaf */
 | 
						|
            if (b4->header.nodeAttribute >= 2 )
 | 
						|
            {
 | 
						|
               b4->nodeHdr.freeSpace = x4reverseShort( (void *)&b4->nodeHdr.freeSpace ) ;
 | 
						|
               longVal = x4reverseLong( (void *)&b4->nodeHdr.recNumMask[0] ) ;
 | 
						|
               memcpy( (void *)&b4->nodeHdr.recNumMask[0], (void *)&longVal, sizeof(S4LONG) ) ;
 | 
						|
            }
 | 
						|
            else /* if b4 is a branch */
 | 
						|
            {
 | 
						|
               shortVal = tag->header.keyLen + sizeof(S4LONG) ;
 | 
						|
               /* position swapPtr to end of first key expression */
 | 
						|
               swapPtr = (char *) &b4->nodeHdr.freeSpace + tag->header.keyLen ;
 | 
						|
 | 
						|
               /* move through all B4KEY's to swap 'long's */
 | 
						|
               for ( i = 0 ; i < (int)b4numKeys( b4 ) ; i++ )
 | 
						|
               {
 | 
						|
                  longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
                  memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
 | 
						|
                  swapPtr += sizeof(S4LONG) ;
 | 
						|
                  longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
                  memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ;
 | 
						|
                  swapPtr += shortVal ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         tag->readBlockTag = tag ;
 | 
						|
      #endif
 | 
						|
      rc = file4readAll( file, blockNo, &b4->nKeys, B4BLOCK_SIZE ) ;
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         tag->readBlockTag = 0 ;
 | 
						|
      #endif
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( c4, rc, E91604 ) ;
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         b4->nKeys = x4reverseShort( (void *)&b4->nKeys ) ;
 | 
						|
      #endif
 | 
						|
      b4->fileBlock = blockNo/512 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( c4->doIndexVerify == 0 )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   if ( b4numKeys( b4 ) == 0 )   /* added to free list... therefore bad */
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         if ( tag->header.keysMax > 2 )  /* remote possibility of 0 keys if max = 2 and in a reindex mode */
 | 
						|
            if ( tag->header.root != b4->fileBlock * I4MULTIPLY )  /* b4 has no keys but is not the root, must be a problem... */
 | 
						|
      #else
 | 
						|
         if ( tag->header.root != blockNo )  /* b4 has no keys but is not the root, must be a problem... */
 | 
						|
      #endif
 | 
						|
      return 1 ;
 | 
						|
 | 
						|
   if ( parent != 0 )  /* check consistancy */
 | 
						|
   {
 | 
						|
      #ifdef S4MDX
 | 
						|
         eq = 0 ;
 | 
						|
         blkOn = b4numKeys( b4 ) - 1 ;
 | 
						|
         if ( parent->keyOn >= b4numKeys( parent ) )
 | 
						|
         {
 | 
						|
            parOn = b4numKeys( parent ) - 1 ;
 | 
						|
            eq = 1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            parOn = parent->keyOn ;
 | 
						|
         if ( !b4leaf( b4 ) )
 | 
						|
         {
 | 
						|
            blkOn = 0 ;
 | 
						|
            if ( eq != 1 )
 | 
						|
            {
 | 
						|
               if ( parOn == 0 )
 | 
						|
                  eq = 2 ;
 | 
						|
               else
 | 
						|
               {
 | 
						|
                  eq = 1 ;
 | 
						|
                  parOn-- ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
 | 
						|
         switch( eq )
 | 
						|
         {
 | 
						|
            case 0:
 | 
						|
               if ( tag->cmp( b4keyKey( parent, parOn ), b4keyKey( b4, blkOn ), tag->header.keyLen  ) != 0 )
 | 
						|
                  rc = 1 ;
 | 
						|
               break ;
 | 
						|
            case 1:
 | 
						|
               if ( tag->cmp( b4keyKey( parent, parOn ), b4keyKey( b4, blkOn ), tag->header.keyLen  ) > 0 )
 | 
						|
                  rc = 1 ;
 | 
						|
               break ;
 | 
						|
            case 2:
 | 
						|
               if ( tag->cmp( b4keyKey( parent, parOn ), b4keyKey( b4, blkOn ), tag->header.keyLen  ) < 0 )
 | 
						|
                  rc = 1 ;
 | 
						|
               break ;
 | 
						|
            #ifdef E4ANALYZE
 | 
						|
               default:
 | 
						|
                  return error4( c4, e4index, E81601 ) ;
 | 
						|
            #endif
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
 | 
						|
      #ifdef S4FOX
 | 
						|
         if ( rc == 0 )
 | 
						|
            if ( b4recNo( parent, parent->keyOn) != b4recNo( b4, b4numKeys( b4 ) - 1 ) )
 | 
						|
               rc = 1 ;
 | 
						|
      #endif
 | 
						|
      if ( rc == 0 )
 | 
						|
      {
 | 
						|
         #ifdef E4INDEX_VERIFY
 | 
						|
            if ( b4verify( b4 ) == -1 )
 | 
						|
               return error4describe( c4, e4index, E91604, tag->alias, 0, 0 ) ;
 | 
						|
            if ( b4verify( parent ) == -1 )
 | 
						|
               return error4describe( c4, e4index, E91604, tag->alias, 0, 0 ) ;
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         if ( rc == 0 )
 | 
						|
         {
 | 
						|
            if ( parent->keyOn < b4numKeys( parent ) )
 | 
						|
            {
 | 
						|
               if ( tag->cmp( b4keyKey( parent, parent->keyOn ), b4keyKey( b4, b4numKeys( b4 ) - 1 ), tag->header.keyLen  ) < 0 )
 | 
						|
                  rc = 1 ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               if ( b4numKeys( b4 ) != 0 && b4numKeys( parent ) != 0 )   /* again, special instance whereby no key to compare with, so assume correct */
 | 
						|
                  if ( tag->cmp( b4keyKey( parent, parent->keyOn - 1 ), b4keyKey( b4, 0 ), tag->header.keyLen  ) > 0 )
 | 
						|
                     rc = 1 ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
 | 
						|
   if ( rc == 1 )
 | 
						|
      #ifdef N4OTHER
 | 
						|
         if ( tfile4lockTest( tag ) == 1 )  /* corrupt */
 | 
						|
      #else
 | 
						|
         if ( index4lockTest( i4file ) == 1 )  /* corrupt */
 | 
						|
      #endif
 | 
						|
         return error4describe( c4, e4index, E81607, tag->alias, 0, 0 ) ;
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4exprKey( TAG4FILE *tag, unsigned char **ptrPtr )
 | 
						|
{
 | 
						|
   int len ;
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      int oldDec ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( tag == 0 || ptrPtr == 0)
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      oldDec = tag->codeBase->decimals ;
 | 
						|
      tag->codeBase->decimals = tag->header.keyDec ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   len = expr4key( tag->expr, (char **)ptrPtr ) ;
 | 
						|
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      tag->codeBase->decimals = oldDec ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return len ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4go( TAG4FILE *t4, const unsigned char *ptr, const long recNum, const int goAdd )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
   #ifdef S4HAS_DESCENDING
 | 
						|
      int oldDesc ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || ptr == 0 )
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
      if ( recNum <= 0L )
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4HAS_DESCENDING
 | 
						|
      oldDesc = t4->header.descending ;
 | 
						|
      t4->header.descending = 0 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = tfile4go2( t4, ptr, recNum, goAdd ) ;
 | 
						|
 | 
						|
   #ifdef S4HAS_DESCENDING
 | 
						|
      t4->header.descending = (short)oldDesc ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4empty( TAG4FILE *tag )
 | 
						|
{
 | 
						|
   B4BLOCK *b4 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( tag == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   b4 = tfile4block( tag ) ;
 | 
						|
   if ( b4 == 0 )
 | 
						|
      return 1 ;
 | 
						|
   if ( b4numKeys( b4 ) == 0L )
 | 
						|
      return 1 ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef N4OTHER
 | 
						|
#ifdef S4FOX
 | 
						|
#ifdef S4HAS_DESCENDING
 | 
						|
void tfile4descending( TAG4FILE *tag, const unsigned short int setting )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( tag == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E91642 ) ;
 | 
						|
         return ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   tag->header.descending = setting ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4VFP_KEY
 | 
						|
/* returns 1 (true) if tag uses double-length keys--otherwise 0 (false) is returned */
 | 
						|
int tfile4vfpKey( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   switch( t4->vfpInfo.sortType )
 | 
						|
   {
 | 
						|
      case sort4machine:
 | 
						|
         return 0 ;
 | 
						|
      case sort4general:
 | 
						|
         return 1 ;
 | 
						|
      default:
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
   } ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int tfile4setCollatingSeq( TAG4FILE *t4, const int type )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   switch ( type )
 | 
						|
   {
 | 
						|
      case sort4machine:
 | 
						|
         memset( t4->header.sortSeq, 0, 8 ) ;
 | 
						|
         t4->vfpInfo.tablePtr = 0 ;   /* the machine collating sequence isn't translated */
 | 
						|
         t4->vfpInfo.compPtr = 0 ;
 | 
						|
         break ;
 | 
						|
   #ifdef S4GENERAL
 | 
						|
      case sort4general:
 | 
						|
         memcpy( t4->header.sortSeq, "GENERAL\0", 8 ) ;
 | 
						|
         t4->vfpInfo.tablePtr = v4general ;
 | 
						|
         t4->vfpInfo.compPtr = v4generalComp ;
 | 
						|
         break ;
 | 
						|
   #endif
 | 
						|
      default:
 | 
						|
         return error4( t4->codeBase, e4parm, E91642 ) ;
 | 
						|
   } ;
 | 
						|
 | 
						|
   t4->vfpInfo.sortType = type ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4setCodePage( TAG4FILE *t4, const int type )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   /* only if the tag is general should we verify the codepage */
 | 
						|
   if ( t4->vfpInfo.sortType == sort4general )
 | 
						|
   {
 | 
						|
      switch ( type )
 | 
						|
      {
 | 
						|
         case cp0:
 | 
						|
            t4->vfpInfo.cpPtr = CodePage_1252 ;   /* set codepage 1252 as the default codepage */
 | 
						|
            break ;
 | 
						|
         #ifdef S4CODEPAGE_1252
 | 
						|
            case cp1252:
 | 
						|
               t4->vfpInfo.cpPtr = CodePage_1252 ;
 | 
						|
               break ;
 | 
						|
         #endif
 | 
						|
         #ifdef S4CODEPAGE_437
 | 
						|
            case cp437:
 | 
						|
               t4->vfpInfo.cpPtr = CodePage_437 ;
 | 
						|
               break ;
 | 
						|
         #endif
 | 
						|
         default:
 | 
						|
            return error4( t4->codeBase, e4parm, E81610 ) ;
 | 
						|
      }
 | 
						|
      t4->vfpInfo.codePage = type ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      t4->vfpInfo.cpPtr = 0 ;
 | 
						|
      t4->vfpInfo.codePage = cp0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
void t4strToFox( char *result, const char *inputPtr, const int inputPtrLen )
 | 
						|
{
 | 
						|
   t4dblToFox( result, c4atod( inputPtr, inputPtrLen ) ) ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef P4ARGS_USED
 | 
						|
   #pragma argsused
 | 
						|
#endif
 | 
						|
void t4dtstrToFox( char *result, const char *inputPtr, const int inputPtrLen )
 | 
						|
{
 | 
						|
   t4dblToFox( result, (double) date4long( inputPtr ) ) ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4rlBottom( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc, rc2 ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   do
 | 
						|
   {
 | 
						|
      rc = tfile4upToRoot( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         if ( b4numKeys( tfile4block( t4 ) ) != 0 )
 | 
						|
         {
 | 
						|
            rc2 = b4go( tfile4block( t4 ), (long)b4numKeys( tfile4block( t4 ) ) - 1L ) ;
 | 
						|
            if ( rc2 < 0 )
 | 
						|
               return error4stack( t4->codeBase, rc2, E91642 ) ;
 | 
						|
            do
 | 
						|
            {
 | 
						|
               rc = tfile4down( t4 ) ;
 | 
						|
               if ( rc < 0 )
 | 
						|
                  return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
               rc2 = b4go( tfile4block( t4 ), (long)b4numKeys( tfile4block( t4 ) ) - 1L ) ;
 | 
						|
               if ( rc2 < 0 )
 | 
						|
                  return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
            } while ( rc == 0 ) ;
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      {
 | 
						|
         rc2 = tfile4outOfDate( t4 ) ;
 | 
						|
         if ( rc2 < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
      }
 | 
						|
   } while ( rc == 2 ) ;
 | 
						|
 | 
						|
   blockOn = tfile4block( t4 ) ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         return error4( t4->codeBase, e4result, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( blockOn->keyOn > 0 )
 | 
						|
   {
 | 
						|
      b4goEof( blockOn ) ;
 | 
						|
      blockOn->keyOn-- ;  /* update keyOn after going to last spot */
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
S4EXPORT int S4FUNCTION tfile4bottom( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( t4->header.descending )   /* if descending, go bottom means go top */
 | 
						|
      return tfile4rlTop( t4 ) ;
 | 
						|
   else
 | 
						|
      return tfile4rlBottom( t4 ) ;
 | 
						|
}
 | 
						|
 | 
						|
#else /*  if not S4FOX  */
 | 
						|
 | 
						|
int tfile4bottom( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc, rc2 ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   rc = 2 ;
 | 
						|
 | 
						|
   while ( rc == 2 )
 | 
						|
   {
 | 
						|
      rc = tfile4upToRoot( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, rc, E91642 ) ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         b4goEof( tfile4block(t4) ) ;
 | 
						|
         do
 | 
						|
         {
 | 
						|
            rc = tfile4down( t4 ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return error4stack( t4->codeBase, rc, E91642 ) ;
 | 
						|
            b4goEof( tfile4block( t4 ) ) ;
 | 
						|
         } while ( rc == 0 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      {
 | 
						|
         rc2 = tfile4outOfDate( t4 ) ;
 | 
						|
         if ( rc2 < 0 )
 | 
						|
            return error4stack( t4->codeBase, rc2, E91642 ) ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   blockOn = tfile4block( t4 ) ;
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         return error4( t4->codeBase, e4result, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( blockOn->keyOn > 0 )
 | 
						|
      blockOn->keyOn = b4numKeys( blockOn ) - 1 ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* ifdef S4FOX */
 | 
						|
 | 
						|
B4BLOCK *tfile4block( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( t4->blocks.lastNode == 0 )
 | 
						|
      {
 | 
						|
         error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
}
 | 
						|
 | 
						|
/* Returns  2 - cannot go down due to out of date blocks 1 - Cannot move down; 0 - Success; -1 Error */
 | 
						|
int tfile4down( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   long blockDown ;
 | 
						|
   B4BLOCK *blockOn, *popBlock, *newBlock, *parent ;
 | 
						|
   INDEX4FILE *i4 ;
 | 
						|
   int rc ;
 | 
						|
   #ifdef S4ADVANCE_READ
 | 
						|
      long nextBlockDown ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   i4 = t4->indexFile ;
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
 | 
						|
   if ( blockOn == 0 )    /* Read the root block */
 | 
						|
   {
 | 
						|
      if ( t4->header.root <= 0L )
 | 
						|
      {
 | 
						|
         rc = file4readAll( &i4->file, t4->headerOffset, &t4->header.root,sizeof(t4->header.root)) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
      blockDown = t4->header.root ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if ( b4leaf( blockOn ) )
 | 
						|
         return 1 ;
 | 
						|
      #ifdef S4FOX
 | 
						|
         #ifdef S4DATA_ALIGN
 | 
						|
            memcpy( (void *)&blockDown,(void *)(((unsigned char *)&blockOn->nodeHdr)
 | 
						|
                    + (blockOn->keyOn+1)*(2*sizeof(S4LONG) + t4->header.keyLen) - sizeof(S4LONG)), sizeof(S4LONG) ) ;
 | 
						|
            blockDown = x4reverseLong( (void *)&blockDown ) ;
 | 
						|
 | 
						|
         #else
 | 
						|
            blockDown = x4reverseLong( (void *)( ((unsigned char *)&blockOn->nodeHdr)
 | 
						|
                    + (blockOn->keyOn+1)*(2*sizeof(S4LONG) + t4->header.keyLen) - sizeof(S4LONG) ) ) ;
 | 
						|
         #endif
 | 
						|
         #ifdef S4ADVANCE_READ
 | 
						|
            if ( b4numKeys( blockOn ) >= (blockOn->keyOn + 1) )
 | 
						|
            {
 | 
						|
               #ifdef S4DATA_ALIGN
 | 
						|
                  memcpy( (void *)&nextBlockDown,(void *)(((unsigned char *)&blockOn->nodeHdr)
 | 
						|
                          + (blockOn->keyOn+2)*(2*sizeof(S4LONG) + t4->header.keyLen) - sizeof(S4LONG)), sizeof(S4LONG) ) ;
 | 
						|
                  nextBlockDown = x4reverseLong( (void *)&blockDown ) ;
 | 
						|
               #else
 | 
						|
                  nextBlockDown = x4reverseLong( (void *)( ((unsigned char *)&blockOn->nodeHdr)
 | 
						|
                          + (blockOn->keyOn+2)*(2*sizeof(S4LONG) + t4->header.keyLen) - sizeof(S4LONG) ) ) ;
 | 
						|
               #endif
 | 
						|
            }
 | 
						|
            else
 | 
						|
               nextBlockDown = -1L ;
 | 
						|
         #endif
 | 
						|
      #else
 | 
						|
         blockDown = b4key(blockOn,blockOn->keyOn)->num ;
 | 
						|
         #ifdef S4ADVANCE_READ
 | 
						|
            if ( b4numKeys( blockOn ) >= (blockOn->keyOn + 1) )
 | 
						|
               nextBlockDown = b4key(blockOn,blockOn->keyOn+1)->num ;
 | 
						|
            else
 | 
						|
               nextBlockDown = -1L ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( blockDown <= 0L )
 | 
						|
            return error4( t4->codeBase, e4index, E81602 ) ;
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
 | 
						|
   /* Get memory for the new block */
 | 
						|
   popBlock = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
   if ( popBlock == 0 )
 | 
						|
   {
 | 
						|
      newBlock = b4alloc( t4, blockDown) ;
 | 
						|
      if ( newBlock == 0 )
 | 
						|
         return error4stack( t4->codeBase, e4memory, E91642 ) ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      newBlock = popBlock ;
 | 
						|
 | 
						|
   parent = (B4BLOCK *)l4last( &t4->blocks ) ;
 | 
						|
   l4add( &t4->blocks, newBlock ) ;
 | 
						|
 | 
						|
   if ( popBlock == 0 || newBlock->fileBlock != blockDown )
 | 
						|
   {
 | 
						|
      #ifndef S4OFF_WRITE
 | 
						|
         rc = b4flush( newBlock ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      rc = i4readBlock( &i4->file, blockDown, parent, newBlock ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
 | 
						|
      #ifndef S4OFF_OPTIMIZE
 | 
						|
         #ifdef S4ADVANCE_READ
 | 
						|
            if ( nextBlockDown != -1L )
 | 
						|
               if ( i4->dataFile->hiPrio == -2 )  /* tag-skipping */
 | 
						|
                  if ( b4leaf( newBlock ) )  /* pre-read the next one */
 | 
						|
                     #ifdef S4FOX
 | 
						|
                        opt4advanceReadBuf( &i4->file, I4MULTIPLY * nextBlockDown, B4BLOCK_SIZE ) ;
 | 
						|
                     #else
 | 
						|
                        opt4advanceReadBuf( &i4->file, I4MULTIPLY * nextBlockDown, i4->header.blockRw ) ;
 | 
						|
                     #endif
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
 | 
						|
      if ( rc == 1 )
 | 
						|
      {
 | 
						|
         l4remove( &t4->blocks, newBlock ) ;
 | 
						|
         l4add( &t4->saved, newBlock ) ;
 | 
						|
         return 2 ;
 | 
						|
      }
 | 
						|
 | 
						|
      newBlock->fileBlock = blockDown ;
 | 
						|
 | 
						|
      #ifdef S4FOX
 | 
						|
         newBlock->builtOn = -1 ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      /* flush blocks, don't delete */
 | 
						|
      for( blockOn = 0 ;; )
 | 
						|
      {
 | 
						|
         blockOn = (B4BLOCK *)l4next(&t4->saved,blockOn) ;
 | 
						|
         if ( blockOn == 0 )
 | 
						|
            break ;
 | 
						|
         #ifndef S4OFF_WRITE
 | 
						|
            rc = b4flush( blockOn ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
         #endif
 | 
						|
         blockOn->fileBlock = -1 ;   /* make it invalid */
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      return b4top( newBlock ) ;
 | 
						|
   #else
 | 
						|
      newBlock->keyOn = 0 ;
 | 
						|
      return 0 ;
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
S4EXPORT int S4FUNCTION tfile4eof( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *b4 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   b4 = tfile4block( t4 ) ;
 | 
						|
   if ( b4 == 0 )
 | 
						|
      return error4stack( 0, e4result, E91642 ) ;
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      return( (b4->keyOn >= b4numKeys( b4 ) ) || (b4numKeys( b4 ) == 0) ) ;
 | 
						|
   #else
 | 
						|
      return( b4->keyOn >= b4numKeys( b4 ) ) ;
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int tfile4update( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   for( blockOn = 0 ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4next(&t4->saved,blockOn) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         break ;
 | 
						|
      rc = b4flush( blockOn ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   for( blockOn = 0 ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4next(&t4->blocks,blockOn) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         break ;
 | 
						|
      rc = b4flush( blockOn ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( t4->rootWrite )
 | 
						|
   {
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      rc = file4write( &t4->indexFile->file, t4->headerOffset, &t4->header.root, sizeof(t4->header.root)) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      t4->rootWrite = 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
int tfile4freeAll( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   while ( tfile4up( t4 ) == 0 ) ;
 | 
						|
   return tfile4freeSaved( t4 ) ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4freeSaved( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4OFF_WRITE
 | 
						|
      rc = tfile4update( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   for ( ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         return 0 ;
 | 
						|
      #ifndef S4OFF_WRITE
 | 
						|
         rc = b4flush( blockOn ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
      #endif
 | 
						|
      rc = b4free( blockOn ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
/* addGo true if performing for add purposes instead of seek purposes */
 | 
						|
int tfile4go2( TAG4FILE *t4, const unsigned char *ptr, const long recNum, const int addGo )
 | 
						|
{
 | 
						|
   #ifdef S4FOX
 | 
						|
      B4BLOCK *blockOn ;
 | 
						|
      int rc, rc2, rc3, kLen ;
 | 
						|
      long rec ;
 | 
						|
      char hasSkipped ;
 | 
						|
   #else
 | 
						|
      int rc, rc3 ;
 | 
						|
      long rec, recSave, tagRec ;
 | 
						|
      B4BLOCK *blockOn ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || ptr == 0 )
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
      if ( recNum <= 0L )
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      kLen = t4->header.keyLen ;
 | 
						|
      rec = x4reverseLong( (void *)&recNum ) ;
 | 
						|
 | 
						|
      do
 | 
						|
      {
 | 
						|
         /* Do initial search, moving up only as far as necessary */
 | 
						|
         rc2 = tfile4upToRoot( t4 ) ;
 | 
						|
         if ( rc2 < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
 | 
						|
         if ( rc2 != 2 )
 | 
						|
         {
 | 
						|
            for(;;) /* Repeat until found */
 | 
						|
            {
 | 
						|
               blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
               #ifdef E4ANALYZE
 | 
						|
                  if ( blockOn == 0 )
 | 
						|
                     return error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
               #endif
 | 
						|
 | 
						|
               if ( b4leaf(blockOn) )
 | 
						|
               {
 | 
						|
                  rc = b4seek( blockOn, (char *)ptr, kLen ) ;
 | 
						|
 | 
						|
                  if ( rc )    /* leaf seek did not end in perfect find */
 | 
						|
                     return rc ;
 | 
						|
 | 
						|
                  /* now do the seek for recno on the leaf block */
 | 
						|
                  blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
 | 
						|
                  if ( addGo == 0 )
 | 
						|
                  {
 | 
						|
                     rec = tfile4recNo( t4 ) ;
 | 
						|
                     if ( rec < 0 )
 | 
						|
                        return error4stack( t4->codeBase, (short)rec, E91642 ) ;
 | 
						|
                     if ( rec == recNum )
 | 
						|
                        return 0 ;
 | 
						|
                  }
 | 
						|
 | 
						|
                  hasSkipped = 0 ;
 | 
						|
                  for(;;)
 | 
						|
                  {
 | 
						|
                     rec = tfile4recNo( t4 ) ;
 | 
						|
                     if ( rec < 0 )
 | 
						|
                        return error4stack( t4->codeBase, (short)rec, E91642 ) ;
 | 
						|
                     if ( addGo == 0 )
 | 
						|
                        if ( rec == recNum )
 | 
						|
                           return 0 ;
 | 
						|
                     if ( rec >= recNum )
 | 
						|
                     {
 | 
						|
                        if ( !hasSkipped )
 | 
						|
                           blockOn->curDupCnt = x4dupCnt( blockOn, blockOn->keyOn ) ;
 | 
						|
                        return r4found ;
 | 
						|
                     }
 | 
						|
 | 
						|
                     hasSkipped = 1 ;
 | 
						|
 | 
						|
                     rc = (int)tfile4skip(t4,1L) ;
 | 
						|
                     if ( rc == -1 )
 | 
						|
                        return -1 ;
 | 
						|
                     if ( rc == 0 )
 | 
						|
                     {
 | 
						|
                        b4goEof( tfile4block(t4) ) ;
 | 
						|
                        return r4found ;
 | 
						|
                     }
 | 
						|
 | 
						|
                     if ( x4dupCnt( blockOn, blockOn->keyOn ) + x4trailCnt( blockOn, blockOn->keyOn )
 | 
						|
                          != t4->header.keyLen )  /* case where key changed */
 | 
						|
                        return r4found ;
 | 
						|
                  }
 | 
						|
               }
 | 
						|
               else
 | 
						|
               {
 | 
						|
                  rc = b4rBrseek( blockOn, (char *)ptr, kLen, rec ) ;
 | 
						|
                  if ( rc == 0 && t4->header.typeCode & 0x01 )
 | 
						|
                     if ( b4recNo( tfile4block(t4), tfile4block(t4)->keyOn ) != recNum )
 | 
						|
                        return r4found ;
 | 
						|
               }
 | 
						|
 | 
						|
               rc2 = tfile4down( t4 ) ;
 | 
						|
               if ( rc2 < 0 )
 | 
						|
                  return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
               if ( rc2 == 2 )
 | 
						|
               {
 | 
						|
                  rc3 = tfile4outOfDate( t4 ) ;
 | 
						|
                  if ( rc3 < 0 )
 | 
						|
                     return error4stack( t4->codeBase, (short)rc3, E91642 ) ;
 | 
						|
                  break ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
      } while ( rc2 == 2 ) ;
 | 
						|
      return 0 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4FOX
 | 
						|
      rc = tfile4seek( t4, ptr, t4->header.keyLen ) ;
 | 
						|
      if ( rc )
 | 
						|
         return rc ;
 | 
						|
      recSave = tfile4recNo( t4 ) ;
 | 
						|
      if ( recSave == recNum )
 | 
						|
         return 0 ;
 | 
						|
 | 
						|
      /* else find the far end, and then skip back to where now or find */
 | 
						|
      tfile4upToRoot( t4 ) ;
 | 
						|
      for( ;; )
 | 
						|
      {
 | 
						|
         blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
         #ifdef E4ANALYZE
 | 
						|
            if ( blockOn == 0 )
 | 
						|
               return error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
         #endif
 | 
						|
         rc = b4seek( blockOn, (const char *)ptr, t4->header.keyLen ) ;
 | 
						|
         while( rc == 0 )  /* perfect find, check next */
 | 
						|
         {
 | 
						|
            if ( b4skip( blockOn, 1L ) == 0 )
 | 
						|
               break ;
 | 
						|
            if ( (*t4->cmp)( b4keyKey( blockOn, blockOn->keyOn ), ptr, t4->header.keyLen ) != 0 )
 | 
						|
               break ;
 | 
						|
         }
 | 
						|
 | 
						|
         if ( b4leaf( blockOn ) )
 | 
						|
         {
 | 
						|
            tagRec = tfile4recNo( t4 ) ;
 | 
						|
            if ( tagRec == recNum && rc == 0 )   /* found */
 | 
						|
               return 0 ;
 | 
						|
            if ( tagRec == recSave )   /* didn't move */
 | 
						|
               return r4found ;
 | 
						|
            break ;
 | 
						|
         }
 | 
						|
         rc3 = tfile4down( t4 ) ;
 | 
						|
         if ( rc3 < 0 )
 | 
						|
            return error4stack( t4->codeBase, rc3, E91642 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      for(;;)
 | 
						|
      {
 | 
						|
         rc = (int)b4skip( tfile4block( t4 ), -1L ) ;
 | 
						|
         if ( rc == 0 ) /* try previous tag */
 | 
						|
         {
 | 
						|
            if ( tfile4skip( t4, -1L ) == 0 )
 | 
						|
               return r4found ;
 | 
						|
         }
 | 
						|
         rec = tfile4recNo( t4 ) ;
 | 
						|
         if ( rec == recSave )   /* failed to find */
 | 
						|
            return r4found ;
 | 
						|
         if ( rec == recNum )
 | 
						|
            return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
B4KEY_DATA *tfile4keyData( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *b4 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   b4 = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( b4 == 0 )
 | 
						|
      {
 | 
						|
         error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return b4key( b4, b4->keyOn ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* returns 0 if tag is empty */
 | 
						|
S4EXPORT long S4FUNCTION tfile4recNo( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   if ( blockOn == 0 )
 | 
						|
      return -2L ;
 | 
						|
 | 
						|
   if ( b4numKeys( blockOn ) == 0 )
 | 
						|
      return 0 ;
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( blockOn->keyOn >= b4numKeys( blockOn ) )
 | 
						|
         return -1 ;
 | 
						|
   #else
 | 
						|
      if ( !b4leaf( blockOn ) )
 | 
						|
         return -2L ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return b4recNo( blockOn, blockOn->keyOn ) ;
 | 
						|
}
 | 
						|
 | 
						|
S4EXPORT int S4FUNCTION tfile4seek( TAG4FILE *t4, const void *ptr, const int lenIn )
 | 
						|
{
 | 
						|
   int rc, rc2, lenPtr  ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
   #ifdef S4FOX
 | 
						|
      int incPos = 0 ;
 | 
						|
      int dSet ;
 | 
						|
      unsigned char *cPtr ;
 | 
						|
      #ifdef S4VFP_KEY
 | 
						|
         int tmpLenPtr ;
 | 
						|
         int vfpKey = tfile4vfpKey( t4 ) ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      dSet = 0 ;
 | 
						|
      cPtr = (unsigned char *)ptr ;
 | 
						|
   #endif
 | 
						|
   lenPtr = lenIn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || ptr == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
      if ( lenPtr != t4->header.keyLen && tfile4type( t4 ) != r4str )
 | 
						|
         return error4( t4->codeBase, e4parm, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( lenPtr > t4->header.keyLen )
 | 
						|
      lenPtr = t4->header.keyLen ;
 | 
						|
   #ifdef S4VFP_KEY
 | 
						|
      tmpLenPtr = lenPtr ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( t4->header.descending )   /* look for current item less one: */
 | 
						|
      {
 | 
						|
         #ifdef S4VFP_KEY
 | 
						|
            if ( vfpKey && tfile4type( t4 ) == r4str )
 | 
						|
            {
 | 
						|
               for( incPos = lenPtr-1 ; cPtr[incPos] < 10 ; incPos-- ) ;
 | 
						|
               if ( incPos >= 0 )
 | 
						|
                  cPtr[incPos]++ ;
 | 
						|
               tmpLenPtr = incPos + 1 ;
 | 
						|
               incPos-- ;   /* allows cPtr to be reset correctly later on */
 | 
						|
               dSet = 1 ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
         #endif
 | 
						|
               for( incPos = lenPtr-1 ; dSet == 0 && incPos >=0 ; incPos-- )
 | 
						|
                  if ( cPtr[incPos] != 0xFF )
 | 
						|
                  {
 | 
						|
                     cPtr[incPos]++ ;
 | 
						|
                     dSet = 1 ;
 | 
						|
                  }
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = 3 ;
 | 
						|
   for( ;; ) /* Repeat until found */
 | 
						|
   {
 | 
						|
      while ( rc >= 2 )
 | 
						|
      {
 | 
						|
         if ( rc == 2 )
 | 
						|
         {
 | 
						|
            rc2 = tfile4outOfDate( t4 ) ;
 | 
						|
            if ( rc2 < 0 )
 | 
						|
               return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
         }
 | 
						|
         rc = tfile4upToRoot( t4 ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
      }
 | 
						|
      blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( blockOn == 0 )
 | 
						|
            return error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      #ifdef S4VFP_KEY
 | 
						|
         rc = b4seek( blockOn, (char *)ptr, tmpLenPtr ) ;
 | 
						|
      #else
 | 
						|
         rc = b4seek( blockOn, (char *)ptr, lenPtr ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
      if ( b4leaf( blockOn ) )
 | 
						|
         break ;
 | 
						|
 | 
						|
      rc = tfile4down( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( t4->header.descending )   /* must go back one! */
 | 
						|
      {
 | 
						|
         cPtr[incPos+1]-- ; /* reset the searchPtr ; */
 | 
						|
         if ( dSet )
 | 
						|
         {
 | 
						|
            if ( b4numKeys( blockOn ) == 0 )
 | 
						|
               rc = 0 ;
 | 
						|
            else
 | 
						|
            {
 | 
						|
               if ( blockOn->keyOn == 0 )   /* special case, must balance tree */
 | 
						|
               {
 | 
						|
                  rc = (int)tfile4skip( t4, -1L ) ;
 | 
						|
                  if ( rc == 0 )
 | 
						|
                     rc2 = tfile4top( t4 ) ;
 | 
						|
                  else
 | 
						|
                     rc2 = tfile4go( t4, tfile4keyData( t4 )->value, tfile4recNo( t4 ), 0 ) ;
 | 
						|
                  if ( rc2 < 0 )
 | 
						|
                     return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
               }
 | 
						|
               else
 | 
						|
                  rc = (int)tfile4skip( t4, -1L ) ;
 | 
						|
            }
 | 
						|
            if ( rc == 0L )  /* bof = eof condition */
 | 
						|
            {
 | 
						|
               b4goEof( blockOn ) ;
 | 
						|
               rc = r4eof ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               rc2 = b4go( tfile4block( t4 ), (long)tfile4block( t4 )->keyOn ) ;
 | 
						|
               if ( rc2 < 0 )
 | 
						|
                  return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
               rc2 = u4keycmp( (void *)b4keyKey( tfile4block( t4 ), tfile4block( t4 )->keyOn ), ptr, (unsigned)lenPtr, (unsigned)t4->header.keyLen, 0, &t4->vfpInfo ) ;
 | 
						|
               if ( rc2 )
 | 
						|
                  rc = r4after ;
 | 
						|
               else
 | 
						|
                  rc = 0 ;  /* successful find */
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            if ( rc == 0 )  /* the item was found, so go top, */
 | 
						|
            {
 | 
						|
               rc2 = tfile4top( t4 ) ;
 | 
						|
               if ( rc2 < 0 )
 | 
						|
                  return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
            }
 | 
						|
            else  /* otherwise want an eof type condition */
 | 
						|
            {
 | 
						|
               b4goEof( blockOn ) ;
 | 
						|
               rc = r4eof ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
 | 
						|
S4EXPORT long S4FUNCTION tfile4skip( TAG4FILE *t4, long numSkip )
 | 
						|
{
 | 
						|
   long numLeft ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
   int rc ;
 | 
						|
   #ifdef S4FOX
 | 
						|
      int saveDups ;
 | 
						|
      long goTo ;
 | 
						|
   #else
 | 
						|
      int sign ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E91642 ) ;
 | 
						|
         return -numSkip ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return -numSkip ;
 | 
						|
 | 
						|
   numLeft = numSkip ;
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   if ( blockOn == 0 )
 | 
						|
   {
 | 
						|
      if ( tfile4top( t4 ) < 0 )
 | 
						|
         return -numSkip ;
 | 
						|
      blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( ! b4leaf(blockOn) )
 | 
						|
      {
 | 
						|
         error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
         return -numSkip ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      for(;;)
 | 
						|
      {
 | 
						|
         numLeft -= b4skip( blockOn, numLeft ) ;
 | 
						|
         if ( numLeft == 0 )  /* Success */
 | 
						|
            return numSkip ;
 | 
						|
 | 
						|
         if ( numLeft > 0 )
 | 
						|
            goTo = blockOn->header.rightNode ;
 | 
						|
         else
 | 
						|
            goTo = blockOn->header.leftNode ;
 | 
						|
 | 
						|
         if ( goTo == -1 )
 | 
						|
         {
 | 
						|
            if ((numSkip > 0 && t4->header.descending == 0) ||
 | 
						|
                 (numSkip <= 0 && t4->header.descending == 1))
 | 
						|
            {
 | 
						|
               saveDups = tfile4block( t4 )->curDupCnt ;
 | 
						|
               rc = tfile4bottom( t4 ) ;
 | 
						|
               if ( rc < 0 )
 | 
						|
                  return -numSkip ;
 | 
						|
               tfile4block( t4 )->curDupCnt = saveDups ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
               if ( tfile4top(t4) < 0 )
 | 
						|
                 return -numSkip ;
 | 
						|
            return (numSkip - numLeft) ;
 | 
						|
         }
 | 
						|
 | 
						|
         #ifndef S4OFF_WRITE
 | 
						|
            if ( blockOn->changed )
 | 
						|
               if ( b4flush( blockOn ) < 0 )
 | 
						|
                  return -numSkip ;
 | 
						|
         #endif
 | 
						|
 | 
						|
         /* save the current key in case skip fails -- for leaf blocks only */
 | 
						|
         if ( b4leaf( blockOn ) )
 | 
						|
            memcpy( t4->codeBase->savedKey, (void *)b4keyKey( blockOn, b4numKeys( blockOn ) - 1 ), (unsigned int)t4->header.keyLen ) ;
 | 
						|
 | 
						|
         rc = i4readBlock( &t4->indexFile->file, goTo, 0, blockOn ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return -numSkip ;
 | 
						|
 | 
						|
         if ( rc == 1 )   /* failed on i/o, seek current spot to make valid */
 | 
						|
         {
 | 
						|
            #ifndef S4OPTIMIZE_OFF
 | 
						|
            #ifndef S4SINGLE
 | 
						|
               file4refresh( &t4->indexFile->file ) ;
 | 
						|
            #endif
 | 
						|
            #endif
 | 
						|
            rc = tfile4seek( t4, t4->codeBase->savedKey, t4->header.keyLen ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return -numSkip ;
 | 
						|
            if ( rc == r4after )   /* means skipped 1 ahead */
 | 
						|
               numLeft-- ;
 | 
						|
         }
 | 
						|
 | 
						|
         #ifdef S4READ_ADVANCE
 | 
						|
            #ifndef S4OFF_OPTIMIZE
 | 
						|
               if ( t4->indexFile->file.doBuffer )
 | 
						|
               {
 | 
						|
                  /* advance-read the next block since skipping */
 | 
						|
                  if ( numSkip > 0 )
 | 
						|
                     goTo = blockOn->header.rightNode ;
 | 
						|
                  else
 | 
						|
                     goTo = blockOn->header.leftNode ;
 | 
						|
                  if ( goTo != -1 )
 | 
						|
                     opt4advanceReadBuf( &t4->indexFile->file, I4MULTIPLY * goTo, B4BLOCK_SIZE ) ;
 | 
						|
               }
 | 
						|
            #endif
 | 
						|
         #endif
 | 
						|
 | 
						|
         blockOn->fileBlock = goTo ;
 | 
						|
         blockOn->builtOn = -1 ;
 | 
						|
         b4top( blockOn ) ;
 | 
						|
 | 
						|
         if ( numLeft < 0 )
 | 
						|
            numLeft += b4numKeys( blockOn ) ;
 | 
						|
         else
 | 
						|
            numLeft -= 1 ;  /* moved to the next entry */
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4FOX
 | 
						|
      if ( numSkip < 0)
 | 
						|
         sign = -1 ;
 | 
						|
      else
 | 
						|
         sign = 1 ;
 | 
						|
 | 
						|
      for(;;)
 | 
						|
      {
 | 
						|
         /* save the current key in case skip fails -- for leaf blocks only */
 | 
						|
         if ( b4leaf( blockOn ) )
 | 
						|
            memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn ), t4->header.keyLen ) ;
 | 
						|
 | 
						|
         while ( ( rc = tfile4down( t4 ) ) == 0 )
 | 
						|
            if ( sign < 0 )
 | 
						|
            {
 | 
						|
               blockOn = tfile4block( t4 ) ;
 | 
						|
               b4goEof( blockOn ) ;
 | 
						|
               if ( b4leaf( blockOn) )
 | 
						|
               {
 | 
						|
                  blockOn->keyOn-- ;
 | 
						|
                  #ifdef E4ANALYZE
 | 
						|
                     if ( blockOn->keyOn < 0 )
 | 
						|
                     {
 | 
						|
                        error4( t4->codeBase, e4index, E91642 ) ;
 | 
						|
                        return -numSkip ;
 | 
						|
                     }
 | 
						|
                  #endif
 | 
						|
               }
 | 
						|
            }
 | 
						|
 | 
						|
         if ( rc < 0 )
 | 
						|
            return -numSkip ;
 | 
						|
 | 
						|
         if ( rc == 2 )   /* failed on i/o, seek current spot to make valid */
 | 
						|
         {
 | 
						|
            tfile4outOfDate( t4 ) ;
 | 
						|
            rc = tfile4seek( t4, t4->codeBase->savedKey, t4->header.keyLen ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return -numSkip ;
 | 
						|
            if ( rc == r4after )   /* means skipped 1 ahead */
 | 
						|
               numLeft-- ;
 | 
						|
            continue ;
 | 
						|
         }
 | 
						|
 | 
						|
         blockOn = tfile4block( t4 ) ;
 | 
						|
         if ( rc < 0 || blockOn == 0 )
 | 
						|
            return -numSkip ;
 | 
						|
 | 
						|
         numLeft -= b4skip( blockOn, numLeft ) ;
 | 
						|
         if ( numLeft == 0 )      /* Success */
 | 
						|
            return numSkip ;
 | 
						|
 | 
						|
         do  /* Skip 1 to the next leaf block  */
 | 
						|
         {
 | 
						|
            if ( (B4BLOCK *)blockOn->link.p == blockOn )
 | 
						|
            {
 | 
						|
               if ( numSkip > 0 )
 | 
						|
               {
 | 
						|
                  if ( tfile4bottom( t4 ) < 0 )
 | 
						|
                     return -numSkip ;
 | 
						|
               }
 | 
						|
               else
 | 
						|
                  if ( tfile4top( t4 ) < 0 )
 | 
						|
                     return -numSkip ;
 | 
						|
 | 
						|
               return( numSkip - numLeft ) ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
               if ( tfile4up( t4 ) < 0 )
 | 
						|
                  return -numSkip ;
 | 
						|
 | 
						|
            blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
         }  while ( b4skip( blockOn, (long) sign) != sign) ;
 | 
						|
 | 
						|
         numLeft -= sign ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
B4BLOCK *tfile4split( TAG4FILE *t4, B4BLOCK *oldBlock )
 | 
						|
{
 | 
						|
   long newFileBlock ;
 | 
						|
   B4BLOCK *newBlock ;
 | 
						|
   #ifdef S4FOX
 | 
						|
      int rc ;
 | 
						|
   #else
 | 
						|
      int totLen, newLen ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || oldBlock == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   #ifdef E4INDEX_VERIFY
 | 
						|
      if ( b4verify( oldBlock ) == -1 )
 | 
						|
      {
 | 
						|
         error4describe( oldBlock->tag->codeBase, e4index, E91642, oldBlock->tag->alias, 0, 0 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   newFileBlock = index4extend( t4->indexFile ) ;
 | 
						|
 | 
						|
   newBlock = b4alloc( t4, newFileBlock ) ;
 | 
						|
   if ( newBlock == 0 )  return 0 ;
 | 
						|
 | 
						|
   newBlock->changed = 1 ;
 | 
						|
   oldBlock->changed = 1 ;
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( b4leaf( oldBlock ) )
 | 
						|
         rc = tfile4leafSplit( t4, oldBlock, newBlock ) ;
 | 
						|
      else
 | 
						|
         rc = tfile4branchSplit( t4, oldBlock, newBlock ) ;
 | 
						|
 | 
						|
      if ( rc < 0 )
 | 
						|
         return 0 ;
 | 
						|
 | 
						|
      newBlock->header.rightNode = oldBlock->header.rightNode ;
 | 
						|
      newBlock->header.leftNode = oldBlock->fileBlock ;
 | 
						|
      oldBlock->header.rightNode = newBlock->fileBlock ;
 | 
						|
 | 
						|
      if ( newBlock->header.rightNode != -1 )   /* must change left ptr for next block over */
 | 
						|
      {
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            newBlock->fileBlock = x4reverseLong( (void *)&newBlock->fileBlock ) ;
 | 
						|
         #endif
 | 
						|
         rc = file4write( &t4->indexFile->file, newBlock->header.rightNode + 2*sizeof(short),
 | 
						|
                  &newBlock->fileBlock, sizeof( newBlock->header.leftNode ) ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return 0 ;
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            newBlock->fileBlock = x4reverseLong( (void *)&newBlock->fileBlock ) ;
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
   #else
 | 
						|
      /* NNNNOOOO  N - New, O - Old */
 | 
						|
      newBlock->nKeys  = (short)( ( b4numKeys( oldBlock ) + 1 ) / 2 ) ;
 | 
						|
      oldBlock->nKeys -= b4numKeys( newBlock ) ;
 | 
						|
      newBlock->keyOn  = oldBlock->keyOn ;
 | 
						|
 | 
						|
      totLen = t4->indexFile->header.blockRw - sizeof(oldBlock->nKeys) - sizeof(oldBlock->dummy) ;
 | 
						|
      newLen = b4numKeys( newBlock ) * t4->header.groupLen ;
 | 
						|
 | 
						|
      memcpy( (void *)b4key( newBlock, 0 ), (void *)b4key( oldBlock, 0 ), newLen ) ;
 | 
						|
      c4memmove( b4key(oldBlock,0), b4key( oldBlock, b4numKeys( newBlock )), totLen - newLen ) ;
 | 
						|
      oldBlock->keyOn = oldBlock->keyOn - b4numKeys( newBlock ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return newBlock ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
int tfile4branchSplit( TAG4FILE *t4, B4BLOCK *oldBlock, B4BLOCK *newBlock )
 | 
						|
{
 | 
						|
   int newLen, nNewKeys ;
 | 
						|
   int gLen = t4->header.keyLen + 2*sizeof( long ) ;
 | 
						|
   char *oPos ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || oldBlock == 0 || newBlock == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   /* NNNNOOOO  N - New, O - Old */
 | 
						|
   nNewKeys = ( b4numKeys( oldBlock ) + 1 ) / 2 ;
 | 
						|
   if ( oldBlock->keyOn > nNewKeys )
 | 
						|
      nNewKeys-- ;
 | 
						|
   newBlock->header.nKeys = (short)nNewKeys ;
 | 
						|
   oldBlock->header.nKeys -= (short)nNewKeys ;
 | 
						|
 | 
						|
   newLen = b4numKeys( newBlock ) * gLen ;
 | 
						|
 | 
						|
   oPos = ((char *)&oldBlock->nodeHdr) + gLen * b4numKeys( oldBlock ) ;
 | 
						|
   memcpy( (void *)&newBlock->nodeHdr, oPos, (unsigned int)newLen ) ;
 | 
						|
   newBlock->header.nodeAttribute = 0 ;
 | 
						|
   oldBlock->header.nodeAttribute = 0 ;
 | 
						|
   newBlock->keyOn = oldBlock->keyOn - b4numKeys( oldBlock ) ;
 | 
						|
 | 
						|
   /* clear the old data */
 | 
						|
   memset( oPos, 0, (unsigned int)newLen ) ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4leafSplit( TAG4FILE *t4, B4BLOCK *oldBlock, B4BLOCK *newBlock )
 | 
						|
{
 | 
						|
   char *obdPos, *obiPos ;
 | 
						|
   unsigned char buffer[6] ;
 | 
						|
   int len, nKeys, rc, kLen, iLen, bLen, oldDup ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || oldBlock == 0 || newBlock == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   kLen = t4->header.keyLen ;
 | 
						|
   iLen = oldBlock->nodeHdr.infoLen ;
 | 
						|
   bLen = B4BLOCK_SIZE - (sizeof(oldBlock->header)) - (sizeof(oldBlock->nodeHdr))
 | 
						|
              - b4numKeys( oldBlock ) * iLen - oldBlock->nodeHdr.freeSpace ;
 | 
						|
   oldDup = oldBlock->curDupCnt ;
 | 
						|
 | 
						|
   b4top( oldBlock ) ;
 | 
						|
   nKeys = b4numKeys( oldBlock ) / 2 ;
 | 
						|
   for ( len = 0 ; len < b4numKeys( oldBlock ) - nKeys ; len++ )
 | 
						|
   {
 | 
						|
      rc = b4skip( oldBlock, 1L ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   /* build the key 1st key of the new block from one past new end of old block */
 | 
						|
   b4key( oldBlock, oldBlock->keyOn ) ;
 | 
						|
 | 
						|
   /* copy the general information */
 | 
						|
   memcpy( (void *)&newBlock->header, (void *)&oldBlock->header,
 | 
						|
           (sizeof( oldBlock->header)) + (sizeof(oldBlock->nodeHdr)) ) ;
 | 
						|
 | 
						|
   /* put 1st key of new block */
 | 
						|
   newBlock->curTrailCnt = b4calcBlanks( oldBlock->builtKey->value, kLen, t4->pChar ) ;
 | 
						|
   len = kLen - newBlock->curTrailCnt ;
 | 
						|
   newBlock->curPos = ((char *)&newBlock->header) + B4BLOCK_SIZE - len ;
 | 
						|
   memcpy( newBlock->curPos, oldBlock->builtKey->value, (unsigned int)len ) ;
 | 
						|
 | 
						|
   /* copy remaining key data */
 | 
						|
   obdPos = ((char *)&oldBlock->header) + B4BLOCK_SIZE - bLen ;
 | 
						|
   len = oldBlock->curPos - obdPos ;
 | 
						|
   newBlock->curPos -= len ;
 | 
						|
   memcpy( newBlock->curPos, obdPos, (unsigned int)len ) ;
 | 
						|
 | 
						|
   /* copy the info data */
 | 
						|
   obiPos = oldBlock->data + oldBlock->keyOn * iLen ;
 | 
						|
   memcpy( newBlock->data, obiPos, (unsigned int)nKeys * iLen ) ;
 | 
						|
 | 
						|
   /* clear the old data */
 | 
						|
   rc = b4skip( oldBlock, -1L ) ;  /* go to new last entry */
 | 
						|
   if ( rc == 0 )
 | 
						|
      if ( error4code( t4->codeBase ) < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)error4code( t4->codeBase ), E91642 ) ;
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( obdPos < obiPos )
 | 
						|
         return error4( t4->codeBase, e4info, E81603 ) ;
 | 
						|
   #endif
 | 
						|
   memset( obiPos, 0, (unsigned int)(oldBlock->curPos - obiPos) ) ;
 | 
						|
 | 
						|
   /* now reset the place new info data for the first key */
 | 
						|
   memset( newBlock->data, 0, (unsigned int)iLen ) ;
 | 
						|
   x4putInfo( &newBlock->nodeHdr, buffer, oldBlock->builtKey->num, newBlock->curTrailCnt, 0 ) ;
 | 
						|
   memcpy( newBlock->data, (void *)buffer, (unsigned int)iLen ) ;
 | 
						|
 | 
						|
   newBlock->header.nKeys = (short)nKeys ;
 | 
						|
   oldBlock->header.nKeys -= (short)nKeys ;
 | 
						|
   newBlock->header.nodeAttribute = 2 ;
 | 
						|
   oldBlock->header.nodeAttribute = 2 ;
 | 
						|
   newBlock->nodeHdr.freeSpace = (short) (newBlock->curPos - newBlock->data
 | 
						|
                                    - b4numKeys( newBlock ) * iLen) ;
 | 
						|
   oldBlock->nodeHdr.freeSpace = (short) (oldBlock->curPos - oldBlock->data
 | 
						|
                                    - b4numKeys( oldBlock ) * iLen) ;
 | 
						|
   oldBlock->builtOn = -1 ;
 | 
						|
   newBlock->builtOn = -1 ;
 | 
						|
 | 
						|
   rc = b4top( oldBlock ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
   rc = b4top( newBlock ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
 | 
						|
   /* make sure dupCnt is updated on blocks for insert */
 | 
						|
   newBlock->curDupCnt = oldDup ;
 | 
						|
   oldBlock->curDupCnt = oldDup ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
int tfile4rlTop( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc, rc2 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   do
 | 
						|
   {
 | 
						|
      rc = tfile4upToRoot( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         do
 | 
						|
         {
 | 
						|
            b4top( (B4BLOCK *)t4->blocks.lastNode ) ;
 | 
						|
            if ( (rc = tfile4down(t4)) < 0 )
 | 
						|
               return error4stack( t4->codeBase, (short)rc, E91642 ) ;
 | 
						|
         } while ( rc == 0 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      {
 | 
						|
         rc2 = tfile4outOfDate( t4 ) ;
 | 
						|
         return error4stack( t4->codeBase, (short)rc2, E91642 ) ;
 | 
						|
      }
 | 
						|
   } while ( rc == 2 ) ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4top( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( t4->header.descending )   /* if descending, go top means go bottom */
 | 
						|
      return tfile4rlBottom( t4 ) ;
 | 
						|
   else
 | 
						|
      return tfile4rlTop( t4 ) ;
 | 
						|
}
 | 
						|
#else
 | 
						|
int tfile4top( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc, rc2 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   do
 | 
						|
   {
 | 
						|
      rc = tfile4upToRoot( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return error4stack( t4->codeBase, rc, E91642 ) ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         ((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
 | 
						|
         do
 | 
						|
         {
 | 
						|
            if ( (rc = tfile4down(t4)) < 0 )
 | 
						|
               return error4stack( t4->codeBase, rc, E91642 ) ;
 | 
						|
            ((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
 | 
						|
         } while ( rc == 0 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      {
 | 
						|
         rc2 = tfile4outOfDate( t4 ) ;
 | 
						|
         return error4stack( t4->codeBase, rc2, E91642 ) ;
 | 
						|
      }
 | 
						|
   } while ( rc == 2 ) ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int tfile4up( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( t4->blocks.lastNode == 0 )
 | 
						|
      return 1 ;
 | 
						|
 | 
						|
   l4add( &t4->saved, l4pop( &t4->blocks ) ) ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4upToRoot( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   LINK4 *linkOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   for ( ;; )
 | 
						|
   {
 | 
						|
      linkOn = (LINK4 *)l4pop( &t4->blocks ) ;
 | 
						|
      if ( linkOn == 0 )
 | 
						|
         return tfile4down( t4 ) ;
 | 
						|
      l4add( &t4->saved, linkOn ) ;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
int tfile4goEof( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = tfile4bottom( t4 ) ;
 | 
						|
   if ( rc != 0 )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( tfile4block( t4 ) == 0 )
 | 
						|
         return error4( 0, e4info, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4FOX
 | 
						|
      if ( b4numKeys( tfile4block(t4) ) != 0 )
 | 
						|
         tfile4block(t4)->keyOn = b4numKeys( tfile4block(t4) ) ;
 | 
						|
   #else
 | 
						|
      tfile4block(t4)->keyOn++ ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* N4OTHER */
 | 
						|
#endif  /* S4OFF_INDEX */
 | 
						|
 | 
						|
#ifdef S4VB_DOS
 | 
						|
 | 
						|
int tfile4go_v( TAG4FILE *t4, char *key, long recNo )
 | 
						|
{
 | 
						|
   return tfile4go( t4, c4str(key), recNo, 0 ) ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4seekV( TAG4FILE *t4, char *seekVal, int keyLen )
 | 
						|
{
 | 
						|
   return tfile4seek( t4, v4str(seekVal), keyLen) ;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
#endif  /* S4CLIENT */
 |