1974 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1974 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* i4ntag.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifdef __TURBOC__
 | 
						|
   #pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4CLIENT
 | 
						|
TAG4 *S4FUNCTION t4openLow( DATA4 *d4, INDEX4 *i4ndx, const char *fileName, const char *indexName )
 | 
						|
{
 | 
						|
   CODE4 *c4 ;
 | 
						|
   CONNECTION4OPEN_TAG_INFO_IN dataIn ;
 | 
						|
   CONNECTION4OPEN_TAG_INFO_OUT *out ;
 | 
						|
   CONNECTION4 *connection ;
 | 
						|
   int rc ;
 | 
						|
   TAG4 *returnTag ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( d4, 2, E94903 ) )
 | 
						|
         return 0 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( d4 == 0 || fileName == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E94903 ) ;
 | 
						|
         return 0 ; ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = d4->codeBase ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   switch( code4indexFormat( c4 ) )
 | 
						|
   {
 | 
						|
      case r4ndx:
 | 
						|
      case r4ntx:
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
      {
 | 
						|
         error4( c4, e4notSupported, E81719 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( strlen( fileName ) > LEN4PATH )
 | 
						|
   {
 | 
						|
      error4( c4, e4name, E94903 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   memset( &dataIn, 0, sizeof( CONNECTION4OPEN_TAG_INFO_IN ) ) ;
 | 
						|
   connection = d4->dataFile->connection ;
 | 
						|
   if ( connection == 0 )
 | 
						|
   {
 | 
						|
      error4( c4, e4connection, E81704 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   connection4assign( connection, CON4TAG_OPEN, data4clientId( d4 ), data4serverId( d4 ) ) ;
 | 
						|
   dataIn.openForCreate = c4->openForCreate ;
 | 
						|
 | 
						|
   #ifdef S4SINGLE
 | 
						|
      dataIn.exclusiveClient = 1 ;
 | 
						|
   #else
 | 
						|
      if ( c4->singleOpen == OPEN4DENY_RW )
 | 
						|
         dataIn.accessMode = OPEN4DENY_RW ;
 | 
						|
      else
 | 
						|
         dataIn.accessMode = c4->accessMode ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   dataIn.readOnly = c4->readOnly ;
 | 
						|
   dataIn.safety = c4->safety ;  /* for catalog */
 | 
						|
   dataIn.errDefaultUnique = c4->errDefaultUnique ;
 | 
						|
   u4ncpy( dataIn.tagName, fileName, sizeof( dataIn.tagName ) ) ;
 | 
						|
   if ( i4ndx != 0 )
 | 
						|
      dataIn.hasIndex = 1 ;
 | 
						|
 | 
						|
   if ( indexName != 0 )
 | 
						|
      u4ncpy( dataIn.indexName, indexName, sizeof( dataIn.indexName ) ) ;
 | 
						|
 | 
						|
   if ( i4ndx != 0 )
 | 
						|
      dataIn.nameLen = strlen( i4ndx->indexFile->accessName ) + 1 ;
 | 
						|
   connection4addData( connection, &dataIn, sizeof( CONNECTION4OPEN_TAG_INFO_IN ), 0 ) ;
 | 
						|
   if ( i4ndx != 0 )
 | 
						|
      connection4addData( connection, i4ndx->indexFile->accessName, dataIn.nameLen, 0 ) ;
 | 
						|
   connection4send( connection ) ;
 | 
						|
   rc = connection4receive( connection ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
   {
 | 
						|
      error4( c4, rc, E81701 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   rc = connection4status( connection ) ;
 | 
						|
   if ( rc != 0 )
 | 
						|
   {
 | 
						|
      if ( rc < 0 )
 | 
						|
      {
 | 
						|
         if ( c4->errOpen == 0 )
 | 
						|
         {
 | 
						|
            if ( error4code( c4 ) >= 0 )
 | 
						|
               error4set( c4, r4noOpen ) ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            connection4error( connection, c4, rc, E94903 ) ;
 | 
						|
      }
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   out = (CONNECTION4OPEN_TAG_INFO_OUT *)connection4data( connection ) ;
 | 
						|
 | 
						|
   if ( client4indexSetup( c4, d4, d4->dataFile, 1, connection4data( connection ) + sizeof(CONNECTION4OPEN_TAG_INFO_OUT),
 | 
						|
        (unsigned int)connection4len( connection ), (char*)fileName, i4ndx ) < 0 )
 | 
						|
   {
 | 
						|
      error4( c4, e4connection, E94903 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   i4setup( c4, d4, (char *)fileName, out->autoOpened, i4ndx ) ;
 | 
						|
 | 
						|
   returnTag = d4tag( d4, fileName ) ;
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      returnTag->isValid = 1 ;
 | 
						|
   #endif
 | 
						|
   return returnTag ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4close( TAG4 *t4 )
 | 
						|
{
 | 
						|
   INDEX4 *i4 ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( t4, 4, E91637 ) )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   i4 = t4->index ;
 | 
						|
   c4 = i4->codeBase ;
 | 
						|
 | 
						|
   if ( code4indexFormat( c4 ) != r4ntx )  /* function not supported */
 | 
						|
      return error4( c4, e4notSupported, E81719 ) ;
 | 
						|
 | 
						|
   if ( l4numNodes( &i4->tags ) == 1 )   /* only the one tag, so remove index */
 | 
						|
      return i4close( i4 ) ;
 | 
						|
   else /* just free up the one tag so it is no longer available */
 | 
						|
   {
 | 
						|
      l4remove( &i4->tags, t4 ) ;
 | 
						|
      mem4free( c4->tagMemory, t4 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#else
 | 
						|
#ifndef S4INDEX_OFF
 | 
						|
 | 
						|
int tfile4type( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
 #ifdef S4FOX
 | 
						|
    return t4->expr->type ;
 | 
						|
 #endif
 | 
						|
 #ifdef S4CLIPPER
 | 
						|
    return t4->expr->type ;
 | 
						|
 #endif
 | 
						|
 #ifdef S4NDX
 | 
						|
    return t4->header.type ;
 | 
						|
 #endif
 | 
						|
 #ifdef S4MDX
 | 
						|
    return t4->header.type ;
 | 
						|
 #endif
 | 
						|
}
 | 
						|
 | 
						|
#ifdef N4OTHER
 | 
						|
 | 
						|
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( 0, e4struct, E91642 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int tfile4rlBottom( TAG4FILE *t4 )
 | 
						|
#else
 | 
						|
int tfile4bottom( TAG4FILE *t4 )
 | 
						|
#endif
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   do
 | 
						|
   {
 | 
						|
      rc = tfile4upToRoot( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         b4goEof( tfile4block( t4 ) ) ;
 | 
						|
         do
 | 
						|
         {
 | 
						|
            rc = tfile4down( t4 ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return -1 ;
 | 
						|
            b4goEof( tfile4block( t4 ) ) ;
 | 
						|
         } while ( rc == 0 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
         tfile4outOfDate( t4 ) ;
 | 
						|
   } while ( rc == 2 ) ;
 | 
						|
 | 
						|
   blockOn = tfile4block(t4) ;
 | 
						|
   if ( blockOn->keyOn > 0 )
 | 
						|
      blockOn->keyOn = blockOn->nKeys-1 ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( blockOn->keyOn < 0 )
 | 
						|
         return error4( t4->codeBase, e4info, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int 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 ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4HAS_DESCENDING
 | 
						|
void tfile4descending( TAG4FILE *tag, const unsigned short int setting )
 | 
						|
{
 | 
						|
   tag->header.descending = setting ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
/* Returns  1 - Cannot move down; 0 - Success; -1 Error */
 | 
						|
int tfile4down( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   long blockDown ;
 | 
						|
   B4BLOCK *blockOn, *popBlock, *newBlock, *parent ;
 | 
						|
   int rc ;
 | 
						|
   #ifdef S4BYTE_SWAP
 | 
						|
      char *swapPtr ;
 | 
						|
      int i ;
 | 
						|
      short shortVal ;
 | 
						|
      long longVal ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
 | 
						|
   if ( blockOn == 0 )    /* Read the root block */
 | 
						|
   {
 | 
						|
      if ( t4->header.root <= 0L )
 | 
						|
      {
 | 
						|
         #ifdef S4NDX
 | 
						|
            if ( file4readAll( &t4->file, t4->header.headerOffset, &t4->header.root, 2*sizeof(long)) < 0 )
 | 
						|
               return -1 ;
 | 
						|
         #else
 | 
						|
            #ifdef S4CLIPPER
 | 
						|
               if ( file4readAll( &t4->file, t4->header.headerOffset + 2*sizeof(short), &t4->header.root, 2*sizeof(long)) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
            #endif
 | 
						|
         #endif
 | 
						|
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
            t4->header.eof  = x4reverseLong( (void *)&t4->header.eof ) ;
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
      blockDown = t4->header.root ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if ( b4leaf( blockOn ) )
 | 
						|
         return 1 ;
 | 
						|
      blockDown = b4key( blockOn, blockOn->keyOn )->pointer ;
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( blockDown <= 0L )
 | 
						|
            error4( t4->codeBase, e4info, E81602 ) ;
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
 | 
						|
   /* Get memory for the new block */
 | 
						|
   popBlock = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
   newBlock = popBlock ;
 | 
						|
   if ( newBlock == 0 )
 | 
						|
      newBlock = b4alloc( t4, blockDown ) ;
 | 
						|
   if ( newBlock == 0 )
 | 
						|
      return -1 ;
 | 
						|
   parent = (B4BLOCK *)l4last( &t4->blocks ) ;
 | 
						|
   l4add( &t4->blocks, newBlock ) ;
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      if ( popBlock == 0  ||  newBlock->fileBlock != blockDown )
 | 
						|
   #else
 | 
						|
      if ( popBlock == 0  ||  newBlock->fileBlock*I4MULTIPLY != blockDown )
 | 
						|
   #endif
 | 
						|
   {
 | 
						|
      #ifndef S4OFF_WRITE
 | 
						|
         if ( newBlock->changed == 1 )
 | 
						|
            if ( b4flush(newBlock) < 0 )
 | 
						|
               return -1 ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      rc = i4readBlock( &t4->file, blockDown, parent, newBlock ) ;
 | 
						|
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
      if ( rc == 1 )
 | 
						|
      {
 | 
						|
         l4remove( &t4->blocks, newBlock ) ;
 | 
						|
         l4add( &t4->saved, newBlock ) ;
 | 
						|
         return 2 ;
 | 
						|
      }
 | 
						|
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         #ifdef S4NDX
 | 
						|
            swapPtr = (void *)&newBlock->nKeys ;
 | 
						|
 | 
						|
            shortVal = x4reverseShort( (void *)swapPtr ) ;
 | 
						|
            memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | 
						|
 | 
						|
            swapPtr += 2 + sizeof(short) ;
 | 
						|
 | 
						|
            for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | 
						|
            {
 | 
						|
               longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
               memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | 
						|
               longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | 
						|
               memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | 
						|
               swapPtr += r4->groupLen ;
 | 
						|
            }
 | 
						|
 | 
						|
            longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
            memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | 
						|
         #endif
 | 
						|
 | 
						|
         #ifdef S4CLIPPER
 | 
						|
            swapPtr = (void *)&newBlock->nKeys ;
 | 
						|
 | 
						|
            shortVal = x4reverseShort( (void *)swapPtr ) ;
 | 
						|
            memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | 
						|
 | 
						|
            swapPtr += 2 ;
 | 
						|
            /* swap the short pointers to B4KEY_DATA */
 | 
						|
            for ( i = 0 ; i <= t4->header.keysMax ; i++ )
 | 
						|
            {
 | 
						|
               shortVal = x4reverseShort( (void *)swapPtr ) ;
 | 
						|
               memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ;
 | 
						|
               swapPtr += sizeof(short) ;
 | 
						|
            }
 | 
						|
                            /* swap the B4KEY_DATA's */
 | 
						|
            for ( i = 0 ; i < t4->header.keysMax ; i++ )
 | 
						|
            {
 | 
						|
               longVal = x4reverseLong( (void *)swapPtr ) ;
 | 
						|
               memcpy( swapPtr, (void *) &longVal, sizeof(long) ) ;
 | 
						|
               longVal = x4reverseLong( (void *)(swapPtr+sizeof(long)) ) ;
 | 
						|
               memcpy( swapPtr+sizeof(long), (void *) &longVal, sizeof(long) ) ;
 | 
						|
               swapPtr += t4->header.groupLen ;
 | 
						|
            }
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
 | 
						|
      for ( ;; )
 | 
						|
      {
 | 
						|
         blockOn = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
         if ( blockOn == 0 )
 | 
						|
            break ;
 | 
						|
         #ifndef S4OFF_WRITE
 | 
						|
            if ( b4flush(blockOn) < 0 )
 | 
						|
               return -1 ;
 | 
						|
         #endif
 | 
						|
         b4free( blockOn ) ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   newBlock->keyOn = 0 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4eof( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *b4 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   b4 = tfile4block( t4 ) ;
 | 
						|
   return ( b4->keyOn >= b4->nKeys ) ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int tfile4flush( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E94901 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = tfile4update( t4 ) ;
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      if ( rc )
 | 
						|
         rc = file4flush( &t4->file ) ;
 | 
						|
   #endif
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
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 ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4OFF_WRITE
 | 
						|
      if ( tfile4update( t4 ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   for ( ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         return 0 ;
 | 
						|
      #ifndef S4OFF_WRITE
 | 
						|
         if ( b4flush( blockOn ) < 0 )
 | 
						|
            return -1 ;
 | 
						|
      #endif
 | 
						|
      b4free( blockOn ) ;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
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 ;
 | 
						|
   return b4key( b4, b4->keyOn ) ;
 | 
						|
}
 | 
						|
 | 
						|
long tfile4recNo( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return (long)error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   if ( blockOn == 0 )
 | 
						|
      return -2L ;
 | 
						|
   #ifdef S4NDX
 | 
						|
      if ( !b4leaf( blockOn ) )
 | 
						|
         return -2L ;
 | 
						|
   #else
 | 
						|
      if ( blockOn->keyOn >= blockOn->nKeys )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return b4recNo( blockOn, blockOn->keyOn ) ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4seek( TAG4FILE *t4, const void *ptr, const int lenPtrIn )
 | 
						|
{
 | 
						|
   int rc, lenPtr ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      int upperFnd, upperAft, incPos, dSet ;
 | 
						|
      unsigned char *cPtr ;
 | 
						|
      dSet = 0 ;
 | 
						|
      cPtr = (unsigned char *)ptr ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || ptr == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      #ifndef S4CLIPPER
 | 
						|
         /* clipper stores all keys as strings, so length-mismatches are
 | 
						|
            ok */
 | 
						|
         if ( lenPtrIn != t4->header.keyLen && tfile4type( t4 ) != r4str )
 | 
						|
            return error4( t4->codeBase, e4struct, E91642 ) ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
   lenPtr = lenPtrIn ;
 | 
						|
 | 
						|
   if ( lenPtr > t4->header.keyLen )
 | 
						|
      lenPtr = t4->header.keyLen ;
 | 
						|
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      if ( t4->header.descending )   /* look for current item less one: */
 | 
						|
      {
 | 
						|
         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 )
 | 
						|
            tfile4outOfDate( t4 ) ;
 | 
						|
         rc = tfile4upToRoot( t4 ) ;
 | 
						|
         #ifdef S4CLIPPER
 | 
						|
            upperFnd = 0 ;
 | 
						|
            upperAft = 0 ;
 | 
						|
         #endif
 | 
						|
 | 
						|
         if ( rc < 0 )
 | 
						|
            return -1 ;
 | 
						|
      }
 | 
						|
      blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( blockOn == 0 )
 | 
						|
            return error4( t4->codeBase, e4info, E91642 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      rc = b4seek( blockOn, (char *)ptr, lenPtr ) ;
 | 
						|
      #ifdef S4NDX
 | 
						|
         if ( b4leaf( blockOn ) )
 | 
						|
            break ;
 | 
						|
      #else
 | 
						|
         #ifdef S4CLIPPER
 | 
						|
            if ( b4leaf( blockOn ) )
 | 
						|
            {
 | 
						|
               if ( rc == r4after && upperAft && blockOn->keyOn >= blockOn->nKeys )
 | 
						|
                   while( upperAft-- > 1 )
 | 
						|
                      tfile4up( t4 ) ;
 | 
						|
               if ( rc == 0 || !upperFnd )
 | 
						|
                  break ;
 | 
						|
 | 
						|
               while( upperFnd-- > 1 )
 | 
						|
                   tfile4up( t4 ) ;
 | 
						|
               rc = 0 ;
 | 
						|
               break ;
 | 
						|
            }
 | 
						|
            if ( rc == 0 )
 | 
						|
            {
 | 
						|
               upperFnd = 1 ;
 | 
						|
               upperAft = 0 ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
               if ( rc == r4after && !upperFnd && !( blockOn->keyOn >= blockOn->nKeys ) )
 | 
						|
                  upperAft = 1 ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
 | 
						|
      rc = tfile4down( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         if ( upperFnd )
 | 
						|
            upperFnd++ ;
 | 
						|
         if ( upperAft )
 | 
						|
            upperAft++ ;
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      if ( t4->header.descending )   /* must go back one! */
 | 
						|
      {
 | 
						|
         cPtr[incPos+1]-- ; /* reset the search_ptr ; */
 | 
						|
         if ( dSet )
 | 
						|
         {
 | 
						|
            rc = (int)tfile4skip( t4, -1L ) ;
 | 
						|
            if ( rc == 0L )  /* bof = eof condition */
 | 
						|
            {
 | 
						|
               b4goEof( blockOn ) ;
 | 
						|
               rc = r4eof ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               if ( (u4memcmp)( b4keyKey( tfile4block( t4 ), tfile4block( t4 )->keyOn ), ptr, lenPtr ) )
 | 
						|
                  rc = r4after ;
 | 
						|
               else
 | 
						|
                  rc = 0 ;  /* successful find */
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            if ( rc == 0 )  /* the item was found, so go top, */
 | 
						|
               tfile4top( t4 ) ;
 | 
						|
            else  /* otherwise want an eof type condition */
 | 
						|
            {
 | 
						|
               b4goEof( blockOn ) ;
 | 
						|
               rc = r4eof ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
 | 
						|
long tfile4skip( TAG4FILE *t4, long numSkip )
 | 
						|
{
 | 
						|
   int rc, sign, seekSpecial ;
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      long numLeft = numSkip ;
 | 
						|
   #endif
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      long j ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return (long)error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( numSkip < 0)
 | 
						|
      sign = -1 ;
 | 
						|
   else
 | 
						|
      sign = 1 ;
 | 
						|
 | 
						|
   blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   if ( blockOn == 0 )
 | 
						|
   {
 | 
						|
      rc = tfile4top( t4 ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -numSkip ;
 | 
						|
      blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( !b4leaf( blockOn ) )
 | 
						|
            return (long)error4( t4->codeBase, e4info, E91642 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      for(;;)
 | 
						|
      {
 | 
						|
         /* save the current key in case skip fails */
 | 
						|
         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 )
 | 
						|
                        return (long)error4( t4->codeBase, e4info, E91642 ) ;
 | 
						|
                  #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 )  /* Error */
 | 
						|
            return( -numSkip ) ;
 | 
						|
 | 
						|
         numLeft -= b4skip( blockOn, numLeft ) ;
 | 
						|
         if ( numLeft == 0 )  /* Success */
 | 
						|
            return( numSkip ) ;
 | 
						|
 | 
						|
         do  /* Skip 1 to the next leaf block  */
 | 
						|
         {
 | 
						|
            #ifdef E4ANALYZE
 | 
						|
               if ( t4->blocks.lastNode == 0 )
 | 
						|
                  return (long)error4( t4->codeBase, e4result, E91642 ) ;
 | 
						|
            #endif
 | 
						|
            if ( l4prev( &t4->blocks, t4->blocks.lastNode ) == 0 )  /* root block */
 | 
						|
            {
 | 
						|
               if ( numSkip > 0 )
 | 
						|
               {
 | 
						|
                  if ( tfile4bottom( t4 ) < 0 )
 | 
						|
                     return -numSkip ;
 | 
						|
               }
 | 
						|
               else
 | 
						|
                  if ( tfile4top( t4 ) < 0 )
 | 
						|
                     return -numSkip ;
 | 
						|
 | 
						|
               return( numSkip - numLeft ) ;
 | 
						|
            }
 | 
						|
            tfile4up( t4 ) ;
 | 
						|
            blockOn = (B4BLOCK *)t4->blocks.lastNode ;
 | 
						|
         }  while ( b4skip( blockOn, (long) sign) != sign) ;
 | 
						|
         numLeft -= sign ;
 | 
						|
      }
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         for( j = numSkip; j != 0; j -= sign )  /* skip 1 * numSkip */
 | 
						|
         {
 | 
						|
            if ( b4leaf(blockOn) )
 | 
						|
            {
 | 
						|
               if ( b4skip( blockOn, (long) sign) != sign )  /* go up */
 | 
						|
               {
 | 
						|
                  int go_on = 1 ;
 | 
						|
                  while ( go_on )
 | 
						|
                  {
 | 
						|
                     if ( l4prev( &t4->blocks, t4->blocks.lastNode ) == 0 )  /* root block */
 | 
						|
                     {
 | 
						|
                        if ( numSkip > 0 && t4->header.descending == 0 ||
 | 
						|
                             numSkip <= 0 && t4->header.descending == 1 )
 | 
						|
/*                        if ( numSkip > 0 )*/
 | 
						|
                        {
 | 
						|
                           if ( tfile4bottom( t4 ) < 0 )
 | 
						|
                              return -numSkip ;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                           if ( tfile4top( t4 ) < 0 )
 | 
						|
                              return -numSkip ;
 | 
						|
 | 
						|
                        return ( numSkip - j ) ;
 | 
						|
                     }
 | 
						|
 | 
						|
                     rc = tfile4up( t4 ) ;
 | 
						|
                     blockOn = tfile4block( t4 ) ;
 | 
						|
                     if ( rc != 0 ) return -1 ;
 | 
						|
 | 
						|
                     if ( sign > 0 )  /* forward skipping */
 | 
						|
                     {
 | 
						|
                        if ( !( blockOn->keyOn >= blockOn->nKeys ) )
 | 
						|
                           go_on = 0 ;
 | 
						|
                     }
 | 
						|
                     else   /* backward skipping */
 | 
						|
                     {
 | 
						|
                        if ( ! (blockOn->keyOn == 0) )
 | 
						|
                        {
 | 
						|
                           b4skip( blockOn, -1L ) ;
 | 
						|
                           go_on = 0 ;
 | 
						|
                        }
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
               }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               if ( sign > 0 )
 | 
						|
                  b4skip( blockOn, 1L ) ;
 | 
						|
 | 
						|
               /* save the current key in case skip fails */
 | 
						|
               if ( blockOn->keyOn >= blockOn->nKeys )  /* case where no proper key to copy exists */
 | 
						|
               {
 | 
						|
                  if ( blockOn->nKeys == 0 )   /* invalid, so must discard this block */
 | 
						|
                  {
 | 
						|
                     /* codeBase can't recover from this gracefully, so just go back up saying
 | 
						|
                        that couldn't skip */
 | 
						|
                     return 0 ;
 | 
						|
                  }
 | 
						|
 | 
						|
                  /* not on a true key, so instead just go to the old position, and then try the skip again (unless r4after)*/
 | 
						|
                  memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn - 1 ), t4->header.keyLen ) ;
 | 
						|
                  seekSpecial = 1 ;
 | 
						|
               }
 | 
						|
               else
 | 
						|
               {
 | 
						|
                  memcpy( t4->codeBase->savedKey, b4keyKey( blockOn, blockOn->keyOn ), t4->header.keyLen ) ;
 | 
						|
                  seekSpecial = 0 ;
 | 
						|
               }
 | 
						|
 | 
						|
               while ( (rc = tfile4down( t4 ) ) == 0 )
 | 
						|
               {
 | 
						|
                  if ( sign < 0 )
 | 
						|
                  {
 | 
						|
                     blockOn = tfile4block( t4 ) ;
 | 
						|
                     b4goEof( blockOn ) ;
 | 
						|
                     if ( b4leaf( blockOn ) )
 | 
						|
                        blockOn->keyOn-- ;
 | 
						|
                  }
 | 
						|
               }
 | 
						|
               if ( rc < 0 )
 | 
						|
                  return -numSkip ;
 | 
						|
 | 
						|
               if ( rc == 2 )   /* failed on i/o, seek current spot to make valid */
 | 
						|
               {
 | 
						|
                  #ifndef S4OPTIMIZE_OFF
 | 
						|
                  #ifndef S4SINGLE
 | 
						|
                     file4refresh( &t4->file ) ;
 | 
						|
                  #endif
 | 
						|
                  #endif
 | 
						|
                  rc = tfile4seek( t4, t4->codeBase->savedKey, t4->header.keyLen ) ;
 | 
						|
                  if ( rc < 0 )
 | 
						|
                     return -numSkip ;
 | 
						|
                  if ( rc == r4after )   /* means skipped 1 ahead */
 | 
						|
                     if ( j != 1 )
 | 
						|
                        j-- ;
 | 
						|
                  if ( seekSpecial == 1 )  /* means we are actually on wrong pos, need to skip one */
 | 
						|
                     j += sign ;   /* pre-increment # of skip times */
 | 
						|
               }
 | 
						|
 | 
						|
               blockOn = tfile4block( t4 ) ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         return numSkip ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4NDX
 | 
						|
B4BLOCK *tfile4split( TAG4FILE *t4, B4BLOCK *oldBlock )
 | 
						|
{
 | 
						|
   long newFileBlock ;
 | 
						|
   B4BLOCK *newBlock ;
 | 
						|
   int newLen ;
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   #ifdef E4INDEX_VERIFY
 | 
						|
      if ( b4verify( oldBlock ) == -1 )
 | 
						|
         error4describe( oldBlock->tag->codeBase, e4index, E91622, oldBlock->tag->alias, 0, 0 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   newFileBlock = tfile4extend( t4 ) ;
 | 
						|
   newBlock = b4alloc( t4, newFileBlock ) ;
 | 
						|
   if ( newBlock == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   newBlock->changed = 1 ;
 | 
						|
   oldBlock->changed = 1 ;
 | 
						|
 | 
						|
   /* NNNNOOOO  N - New, O - Old */
 | 
						|
   newBlock->nKeys = ( oldBlock->nKeys )/2 ;
 | 
						|
   oldBlock->nKeys -= newBlock->nKeys ;
 | 
						|
 | 
						|
   newLen = newBlock->nKeys * t4->header.groupLen ;
 | 
						|
 | 
						|
   c4memmove( b4key(newBlock,0), b4key(oldBlock, oldBlock->nKeys ), newLen+ (sizeof(long)*(!(b4leaf( oldBlock )) ) ) ) ;
 | 
						|
   newBlock->keyOn = oldBlock->keyOn - oldBlock->nKeys ;
 | 
						|
 | 
						|
   oldBlock->nKeys -= !( b4leaf( oldBlock ) ) ;
 | 
						|
 | 
						|
   return newBlock ;
 | 
						|
}
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
/* NTX only needs to do a copy and adjust the index pointers */
 | 
						|
/* if extraOld is true then the extra key is placed in old, otherwise in new */
 | 
						|
B4BLOCK *tfile4split( TAG4FILE *t4, B4BLOCK *oldBlock, const int extraOld )
 | 
						|
{
 | 
						|
   long  newFileBlock ;
 | 
						|
   B4BLOCK *newBlock ;
 | 
						|
   int isBranch ;
 | 
						|
 | 
						|
   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 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   newFileBlock = tfile4extend( t4 ) ;
 | 
						|
   newBlock = b4alloc( t4, newFileBlock ) ;
 | 
						|
   if ( newBlock == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   newBlock->changed = 1 ;
 | 
						|
   oldBlock->changed = 1 ;
 | 
						|
 | 
						|
   memcpy( newBlock->data, oldBlock->data, B4BLOCK_SIZE - ( t4->header.keysMax + 2 ) * sizeof(short) ) ;
 | 
						|
 | 
						|
   if ( extraOld )
 | 
						|
   {
 | 
						|
      newBlock->nKeys = oldBlock->nKeys / 2 ;
 | 
						|
      oldBlock->nKeys -= newBlock->nKeys ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      newBlock->nKeys = oldBlock->nKeys ;
 | 
						|
      oldBlock->nKeys = oldBlock->nKeys / 2 ;
 | 
						|
      newBlock->nKeys -= oldBlock->nKeys ;
 | 
						|
      if ( oldBlock->nKeys == newBlock->nKeys )
 | 
						|
      {
 | 
						|
         newBlock->nKeys++ ;
 | 
						|
         oldBlock->nKeys-- ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   isBranch = !b4leaf( oldBlock ) ;
 | 
						|
 | 
						|
   memcpy( newBlock->pointers, &oldBlock->pointers[oldBlock->nKeys + isBranch], newBlock->nKeys * sizeof(short) ) ;
 | 
						|
   memcpy( &newBlock->pointers[newBlock->nKeys], oldBlock->pointers, (oldBlock->nKeys + isBranch) * sizeof(short) ) ;
 | 
						|
 | 
						|
   if ( isBranch == 0 )  /* leaf blocks need one more copy */
 | 
						|
      newBlock->pointers[t4->header.keysMax] = oldBlock->pointers[t4->header.keysMax] ;
 | 
						|
 | 
						|
   newBlock->keyOn = oldBlock->keyOn - oldBlock->nKeys - isBranch ;
 | 
						|
   newBlock->nKeys -= isBranch ;
 | 
						|
 | 
						|
   return newBlock ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int tfile4rlTop( TAG4FILE *t4 )
 | 
						|
#else
 | 
						|
int tfile4top( TAG4FILE *t4 )
 | 
						|
#endif
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #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 -1 ;
 | 
						|
 | 
						|
      if ( rc != 2 )
 | 
						|
      {
 | 
						|
         ((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
 | 
						|
         do
 | 
						|
         {
 | 
						|
            if ( (rc = tfile4down(t4)) < 0 )
 | 
						|
               return -1 ;
 | 
						|
            ((B4BLOCK *)t4->blocks.lastNode)->keyOn = 0 ;
 | 
						|
         } while ( rc == 0 ) ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
         tfile4outOfDate( t4 ) ;
 | 
						|
   } while ( rc == 2 ) ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
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 ) ;
 | 
						|
}
 | 
						|
#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 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int tfile4update( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   B4BLOCK *blockOn ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( tfile4updateHeader( t4 ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   for( blockOn = 0 ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4next( &t4->saved ,blockOn ) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         break ;
 | 
						|
      if ( b4flush(blockOn) < 0 )
 | 
						|
         return -1 ;
 | 
						|
   }
 | 
						|
 | 
						|
   for( blockOn = 0 ;; )
 | 
						|
   {
 | 
						|
      blockOn = (B4BLOCK *)l4next( &t4->blocks, blockOn ) ;
 | 
						|
      if ( blockOn == 0 )
 | 
						|
         break ;
 | 
						|
      if ( b4flush( blockOn ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( t4->rootWrite )
 | 
						|
   {
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
         t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
 | 
						|
      #endif
 | 
						|
      #ifdef S4NDX
 | 
						|
         if ( file4write( &t4->file, t4->headerOffset, &t4->header.root, 2 * sizeof(long) ) < 0 )
 | 
						|
            return -1 ;
 | 
						|
      #else
 | 
						|
         #ifdef S4CLIPPER
 | 
						|
            if ( file4write( &t4->file, t4->headerOffset + 2*sizeof( short ),
 | 
						|
                 &t4->header.root, 2*sizeof(long) ) < 0 )  return -1 ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
         t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
 | 
						|
      #endif
 | 
						|
      t4->rootWrite = 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
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 tfile4close( TAG4FILE *t4, DATA4FILE *d4 )
 | 
						|
{
 | 
						|
   CODE4 *c4 ;
 | 
						|
   int finalRc ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91638 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = t4->codeBase ;
 | 
						|
   finalRc = 0 ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( t4->userCount <= 0 )
 | 
						|
         return error4( c4, e4struct, E91638 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   t4->userCount-- ;
 | 
						|
   #ifdef S4SERVER
 | 
						|
      if ( c4->server->keepOpen != 2 || t4->file.isTemp != 1 )
 | 
						|
   #endif
 | 
						|
   if ( t4->userCount == 0 )
 | 
						|
   {
 | 
						|
      if ( tfile4freeAll( t4 ) < 0 )
 | 
						|
         finalRc = error4set( c4, 0) ;
 | 
						|
      expr4free( t4->expr ) ;
 | 
						|
      expr4free( t4->filter ) ;
 | 
						|
      mem4release( t4->blockMemory ) ;
 | 
						|
      t4->blockMemory = 0 ;
 | 
						|
      if ( file4openTest( &t4->file ) )
 | 
						|
      {
 | 
						|
         if ( c4->doRemove == 1 )
 | 
						|
            t4->file.isTemp = 1 ;
 | 
						|
         if ( file4close( &t4->file ) < 0 )
 | 
						|
            finalRc = error4set( c4, 0 ) ;
 | 
						|
      }
 | 
						|
      if ( t4->link.n != (LINK4 *)0 )
 | 
						|
         l4remove( &d4->tagfiles, t4 ) ;
 | 
						|
      mem4free( c4->tagFileMemory, t4 ) ;
 | 
						|
      error4set( c4, finalRc ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return finalRc ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4close( TAG4 *t4 )
 | 
						|
{
 | 
						|
   int finalRc ;
 | 
						|
   DATA4 *d4 ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( t4, 4, E91637 ) )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( t4 == 0 )
 | 
						|
         return error4( 0, e4parm_null, E91637 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( l4seek( &t4->index->tags, t4 ) == 1 )  /* i4close removes the tag, so if still there, was not called from i4close() */
 | 
						|
   {
 | 
						|
      if ( l4numNodes( &t4->index->tags ) == 1 )   /* only the one tag, so remove index */
 | 
						|
         return i4close( t4->index ) ;
 | 
						|
      else  /* must remove from the list manually */
 | 
						|
         l4remove( &t4->index->tags, t4 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   c4 = t4->tagFile->codeBase ;
 | 
						|
   d4 = t4->index->data ;
 | 
						|
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      if ( t4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
 | 
						|
         if ( code4transEnabled( c4 ) )
 | 
						|
            if ( code4trans( c4 )->currentTranStatus == r4active )  /* disallow on current active only */
 | 
						|
               return error4( c4, e4transViolation, E81522 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   finalRc = error4set( c4, 0 ) ;
 | 
						|
 | 
						|
   #ifndef S4OFF_WRITE
 | 
						|
      #ifndef S4OFF_TRAN
 | 
						|
         if ( t4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
 | 
						|
      #endif
 | 
						|
            if ( d4 )
 | 
						|
               if ( d4update( d4 ) < 0 )
 | 
						|
                  finalRc = error4set( c4, 0 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4SINGLE
 | 
						|
      if ( tfile4unlock( t4->tagFile, data4serverId( t4->index->data ) ) < 0 )
 | 
						|
         finalRc = error4set( c4, 0 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( tfile4close( t4->tagFile, d4->dataFile ) < 0 )
 | 
						|
      finalRc = error4set( c4, 0 ) ;
 | 
						|
   mem4free( c4->tagMemory, t4 ) ;
 | 
						|
 | 
						|
   error4set( c4, finalRc ) ;
 | 
						|
 | 
						|
   return finalRc ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
long tfile4extend( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   long oldEof ;
 | 
						|
   CODE4 *c4 = t4->codeBase ;
 | 
						|
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( t4->header.version == t4->header.oldVersion )
 | 
						|
         return (long)error4( c4, e4info, E91636 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   oldEof = t4->header.eof ;
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
        if ( oldEof <= 0L )
 | 
						|
           return (long)error4( c4, e4info, E91636 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      t4->header.eof += B4BLOCK_SIZE / I4MULTIPLY ;
 | 
						|
      t4->rootWrite = 1 ;
 | 
						|
      return oldEof ;
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         #ifdef S4SINGLE
 | 
						|
            if ( oldEof != 0 )   /* case where free-list exists */
 | 
						|
               t4->header.eof = 0L ;
 | 
						|
            else
 | 
						|
            {
 | 
						|
         #endif
 | 
						|
            oldEof = file4len( &t4->file ) ;
 | 
						|
            #ifdef E4ANALYZE
 | 
						|
               if ( oldEof <= t4->checkEof )
 | 
						|
                  return (long)error4( c4, e4info, E91636 ) ;
 | 
						|
               t4->checkEof = oldEof ;
 | 
						|
            #endif
 | 
						|
            file4lenSet( &t4->file, file4len( &t4->file ) + 1024 ) ; /* and extend the file */
 | 
						|
         #ifdef S4SINGLE
 | 
						|
            }
 | 
						|
         #endif
 | 
						|
         return oldEof/512 ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifdef P4ARGS_USED
 | 
						|
   #pragma argsused
 | 
						|
#endif
 | 
						|
int tfile4go2( TAG4FILE *t4, const unsigned char *ptr, const long recNum, const int goAdd )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
   long rec ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( t4 == 0 || ptr == 0 || recNum < 1 )
 | 
						|
         return error4( 0, e4parm, E91642 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   rc = tfile4seek( t4, ptr, t4->header.keyLen ) ;
 | 
						|
   if ( rc )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   for(;;)
 | 
						|
   {
 | 
						|
      rec = tfile4recNo( t4 ) ;
 | 
						|
      if (rec == recNum )
 | 
						|
         return 0 ;
 | 
						|
 | 
						|
      rc = (int)tfile4skip( t4, 1L ) ;
 | 
						|
      if ( rc == -1 )
 | 
						|
         return -1 ;
 | 
						|
      if ( rc == 0 )
 | 
						|
      {
 | 
						|
         b4goEof( tfile4block( t4 ) ) ;
 | 
						|
         return r4found ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( (*t4->cmp)( tfile4keyData( t4 )->value, ptr, t4->header.keyLen ) )
 | 
						|
         return r4found ;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
static TAG4FILE *tfile4open( DATA4 *d4, const char *fileName )
 | 
						|
{
 | 
						|
   TAG4FILE *tfile ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
   char buf[258], buffer[1024] ;
 | 
						|
   char exprBuf[I4MAX_EXPR_SIZE + 1] ;
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      char *ptr, garbage ;
 | 
						|
   #endif
 | 
						|
   FILE4SEQ_READ seqRead ;
 | 
						|
   int rc, len, oldTagNameError ;
 | 
						|
 | 
						|
   c4 = d4->codeBase ;
 | 
						|
 | 
						|
   u4ncpy( buf, fileName, sizeof( buf ) ) ;
 | 
						|
   c4upper(buf) ;
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      #ifdef S4CASE_SEN
 | 
						|
         u4nameExt( buf, sizeof(buf), "ndx", 0 ) ;
 | 
						|
      #else
 | 
						|
         u4nameExt( buf, sizeof(buf), "NDX", 0 ) ;
 | 
						|
      #endif
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         #ifdef S4CASE_SEN
 | 
						|
            u4nameExt( buf, sizeof(buf), "ntx", 0 ) ;
 | 
						|
         #else
 | 
						|
            u4nameExt( buf, sizeof(buf), "NTX", 0 ) ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   oldTagNameError = c4->errTagName ;
 | 
						|
   c4->errTagName = 0 ;
 | 
						|
   tfile = dfile4tag( d4->dataFile, buf ) ;
 | 
						|
   c4->errTagName = oldTagNameError ;
 | 
						|
   if ( tfile != 0 ) /* because t4open() verifies no duplicates, this must be a duplicate data4 instance */
 | 
						|
   {
 | 
						|
      /* changed 09/19/95 - test program t4skip.c */
 | 
						|
      tfile->userCount++ ;
 | 
						|
      return tfile ;
 | 
						|
      /* only one instance ever allowed */
 | 
						|
/*      error4( c4, e4instance, E94906 ) ;*/
 | 
						|
/*      return 0 ; */
 | 
						|
 | 
						|
      /*
 | 
						|
      #ifndef S4SERVER
 | 
						|
         if ( c4->singleOpen != OPEN4SPECIAL )   only one instance allowed...
 | 
						|
         {
 | 
						|
            error4( c4, e4instance, E94906 ) ;
 | 
						|
            return 0 ;
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
 | 
						|
      tfile->userCount++ ;
 | 
						|
      return tfile ;
 | 
						|
      */
 | 
						|
   }
 | 
						|
 | 
						|
   if ( c4->tagFileMemory == 0 )
 | 
						|
   {
 | 
						|
      c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof(TAG4FILE), c4->memExpandTagFile, 0 ) ;
 | 
						|
      if ( c4->tagFileMemory == 0 )
 | 
						|
         return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   tfile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
 | 
						|
   if ( tfile == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   tfile->file.hand = -1 ;
 | 
						|
   tfile->codeBase = c4 ;
 | 
						|
   tfile->userCount = 1 ;
 | 
						|
   if ( tfile->blockMemory == 0 )
 | 
						|
      tfile->blockMemory = mem4create( c4, c4->memStartBlock, (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
 | 
						|
                                     (sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])),
 | 
						|
                                     c4->memExpandBlock, 0 ) ;
 | 
						|
 | 
						|
   if ( tfile->blockMemory == 0 )
 | 
						|
   {
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   rc = file4open( &tfile->file, c4, buf, 1 ) ;
 | 
						|
   if ( rc != 0 )
 | 
						|
   {
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      file4optimizeLow( &tfile->file, c4->optimize, OPT4INDEX, 0, tfile ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   file4seqReadInit( &seqRead, &tfile->file, 0, buffer, 1024 ) ;
 | 
						|
   #ifdef S4NDX
 | 
						|
      if ( file4seqReadAll( &seqRead, &tfile->header.root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
      {
 | 
						|
         tfile4close( tfile, d4->dataFile ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         tfile->header.root = x4reverseLong( (void *)&tfile->header.root ) ;
 | 
						|
         tfile->header.eof = x4reverseLong( (void *)&tfile->header.eof ) ;
 | 
						|
         tfile->header.keyLen = x4reverseShort( (void *)&tfile->header.keyLen ) ;
 | 
						|
         tfile->header.keysMax = x4reverseShort( (void *)&tfile->header.keysMax ) ;
 | 
						|
         tfile->header.int_or_date = x4reverseShort( (void *)&tfile->header.int_or_date ) ;
 | 
						|
         tfile->header.groupLen = x4reverseShort( (void *)&tfile->header.groupLen ) ;
 | 
						|
         tfile->header.dummy = x4reverseShort( (void *)&tfile->header.dummy ) ;
 | 
						|
         tfile->header.unique = x4reverseShort( (void *)&tfile->header.unique ) ;
 | 
						|
      #endif
 | 
						|
      t4->header.type = 0 ;
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         if ( file4seqReadAll( &seqRead, &tfile->header.sign, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
         {
 | 
						|
            tfile4close( tfile, d4->dataFile ) ;
 | 
						|
            return 0 ;
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         tfile->header.sign = x4reverseShort( (void *)&tfile->header.sign ) ;
 | 
						|
         tfile->header.version = x4reverseShort( (void *)&tfile->header.version ) ;
 | 
						|
         tfile->header.root = x4reverseLong( (void *)&tfile->header.root ) ;
 | 
						|
         tfile->header.eof = x4reverseLong( (void *)&tfile->header.eof ) ;
 | 
						|
         tfile->header.groupLen = x4reverseShort( (void *)&tfile->header.groupLen ) ;
 | 
						|
         tfile->header.keyLen = x4reverseShort( (void *)&tfile->header.keyLen ) ;
 | 
						|
         tfile->header.keyDec = x4reverseShort( (void *)&tfile->header.keyDec ) ;
 | 
						|
         tfile->header.keysMax = x4reverseShort( (void *)&tfile->header.keysMax ) ;
 | 
						|
         tfile->header.keysHalf = x4reverseShort( (void *)&tfile->header.keysHalf ) ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
   tfile->header.headerOffset = 0 ;
 | 
						|
 | 
						|
   /* Perform some checks */
 | 
						|
   if ( tfile->header.keyLen > I4MAX_KEY_SIZE || tfile->header.keyLen <= 0 ||
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         tfile->header.keysMax != 2* tfile->header.keysHalf || tfile->header.keysHalf <= 0 ||
 | 
						|
         tfile->header.groupLen != tfile->header.keyLen+ 8 ||
 | 
						|
         (tfile->header.sign != 0x6 && tfile->header.sign != 0x106 ) )
 | 
						|
      #else
 | 
						|
        tfile->header.keyLen+8 > tfile->header.groupLen ||
 | 
						|
        tfile->header.keysMax < 4 || tfile->header.keysMax > 50 ||
 | 
						|
        tfile->header.eof <= 0L )
 | 
						|
      #endif
 | 
						|
   {
 | 
						|
      error4describe( c4, e4index, E84904, buf, 0, 0 ) ;
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   tfile->cmp = (S4CMP_FUNCTION *)u4memcmp ;
 | 
						|
   tfile->header.root = -1 ;
 | 
						|
   tfile->header.oldVersion = tfile->header.version ;
 | 
						|
 | 
						|
   u4namePiece( tfile->alias, sizeof( tfile->alias ), fileName, 0, 0 ) ;
 | 
						|
   #ifndef S4CASE_SEN
 | 
						|
      c4upper( tfile->alias ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   file4seqReadAll( &seqRead, exprBuf, sizeof( exprBuf ) - 1 ) ;
 | 
						|
   c4trimN( exprBuf, sizeof( exprBuf ) ) ;
 | 
						|
   tfile->expr = expr4parseLow( d4, exprBuf, tfile ) ;
 | 
						|
   if ( tfile->expr == 0 )
 | 
						|
   {
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      tfile->expr->keyLen = tfile->header.keyLen ;
 | 
						|
      tfile->expr->keyDec = tfile->header.keyDec ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( expr4context( tfile->expr, d4 ) < 0 )
 | 
						|
   {
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   len = expr4keyLen( tfile->expr ) ;
 | 
						|
   if ( len < 0 )
 | 
						|
   {
 | 
						|
      error4describe( c4, e4info, 84906, exprBuf, 0, 0 ) ;
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      tfile->header.type = (char) expr4type(tfile->expr) ;
 | 
						|
      if ( t4->header.keyLen != (short) len )
 | 
						|
      {
 | 
						|
         error4describe( c4, e4index, E84905, i4->file.name, 0 ) ;
 | 
						|
         tfile4close( tfile, d4->dataFile ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         file4seqReadAll( &seqRead, &tfile->header.unique, sizeof( tfile->header.unique ) ) ;
 | 
						|
         file4seqReadAll( &seqRead, &garbage, sizeof( garbage ) ) ;
 | 
						|
         file4seqReadAll( &seqRead, &tfile->header.descending, sizeof( tfile->header.descending ) ) ;
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            t4->header.unique = x4reverseShort( (void *)&tfile->header.unique ) ;
 | 
						|
            t4->header.descending = x4reverseShort( (void *)&tfile->header.descending ) ;
 | 
						|
         #endif
 | 
						|
         file4seqReadAll( &seqRead, exprBuf, sizeof( exprBuf ) - 1 ) ;
 | 
						|
         c4trimN( exprBuf, sizeof( exprBuf ) ) ;
 | 
						|
         if ( exprBuf[0] != 0 )
 | 
						|
         {
 | 
						|
            tfile->filter = expr4parseLow( d4, exprBuf, tfile ) ;
 | 
						|
            if ( tfile->filter != 0 )
 | 
						|
            {
 | 
						|
               if ( expr4context( tfile->filter, d4 ) < 0 )
 | 
						|
               {
 | 
						|
                  tfile4close( tfile, d4->dataFile ) ;
 | 
						|
                  return 0 ;
 | 
						|
               }
 | 
						|
               len = expr4key( tfile->filter, &ptr ) ;
 | 
						|
               if ( len < 0 )
 | 
						|
               {
 | 
						|
                  tfile4close( tfile, d4->dataFile ) ;
 | 
						|
                  return 0 ;
 | 
						|
               }
 | 
						|
               if ( expr4type( tfile->filter ) != 'L' )
 | 
						|
               {
 | 
						|
                  tfile4close( tfile, d4->dataFile ) ;
 | 
						|
                  return 0 ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
/*   if( tfile->header.unique )
 | 
						|
      tfile->uniqueError = c4->errDefaultUnique ;
 | 
						|
*/
 | 
						|
   l4add( &d4->dataFile->tagfiles, tfile ) ;   /* add the tag to its index list */
 | 
						|
 | 
						|
   #ifdef S4NDX
 | 
						|
      tfile4initSeekConv( tfile, tfile->header.type) ;
 | 
						|
   #else
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         tfile4initSeekConv( tfile, (char)expr4type( tfile->expr ) ) ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( tfile->blockMemory == 0 )
 | 
						|
      tfile->blockMemory = mem4create( c4, c4->memStartBlock, (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
 | 
						|
                           (sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])), c4->memExpandBlock, 0 ) ;
 | 
						|
 | 
						|
   if ( tfile->blockMemory == 0 )
 | 
						|
   {
 | 
						|
      #ifdef E4STACK
 | 
						|
         error4stack( c4, e4memory, E94906 ) ;
 | 
						|
      #endif
 | 
						|
      tfile4close( tfile, d4->dataFile ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( d4->dataFile->indexLocked == 1 )   /* index locked, so lock this tag as well */
 | 
						|
      tfile4lock( tfile, data4serverId( d4 ) ) ;
 | 
						|
   return tfile ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef P4ARGS_USED
 | 
						|
   #pragma argsused
 | 
						|
#endif
 | 
						|
TAG4 *S4FUNCTION t4openLow( DATA4 *d4, INDEX4 *i4ndx, const char *fileName, const char *dummy )
 | 
						|
{
 | 
						|
   CODE4 *c4 ;
 | 
						|
   INDEX4 *i4 ;
 | 
						|
   TAG4 *t4 ;
 | 
						|
   int oldTagErr ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( d4, 2, E94903 ) )
 | 
						|
         return 0 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( d4 == 0 || fileName == 0 )
 | 
						|
      {
 | 
						|
         error4( 0, e4parm_null, E94903 ) ;
 | 
						|
         return 0 ; ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = d4->codeBase ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   oldTagErr = c4->errTagName ;
 | 
						|
   c4->errTagName = 0 ;
 | 
						|
   if ( d4tag( d4, fileName ) )
 | 
						|
   {
 | 
						|
      error4describe( c4, e4instance, E85308, fileName, 0, 0 ) ;
 | 
						|
      c4->errTagName = oldTagErr ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   c4->errTagName = oldTagErr ;
 | 
						|
   error4set( c4, 0 ) ;
 | 
						|
 | 
						|
   if ( i4ndx == 0 )   /* must create an index for the tag */
 | 
						|
   {
 | 
						|
      if ( c4->indexMemory == 0 )
 | 
						|
      {
 | 
						|
         c4->indexMemory = mem4create( c4, c4->memStartIndex, sizeof( INDEX4 ), c4->memExpandIndex, 0 ) ;
 | 
						|
         if ( c4->indexMemory == 0 )
 | 
						|
            return 0 ;
 | 
						|
      }
 | 
						|
 | 
						|
      i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
 | 
						|
      if ( i4 == 0 )
 | 
						|
      {
 | 
						|
         #ifdef E4STACK
 | 
						|
            error4stack( c4, e4memory, E94903 ) ;
 | 
						|
         #endif
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
 | 
						|
      i4->codeBase = c4 = d4->codeBase ;
 | 
						|
      /* 09/22/95 AS - changed last parm to 0 for t4group (c/s access name needs extension if provided) */
 | 
						|
      u4namePiece( i4->accessName, sizeof( i4->accessName ), fileName, 0, 1 ) ;
 | 
						|
    }
 | 
						|
   else
 | 
						|
      i4 = i4ndx ;
 | 
						|
 | 
						|
   if ( c4->tagMemory == 0 )
 | 
						|
   {
 | 
						|
      c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
 | 
						|
      if ( c4->tagMemory == 0 )
 | 
						|
      {
 | 
						|
         if ( i4ndx == 0 )
 | 
						|
            mem4free( c4->indexMemory, i4 ) ;
 | 
						|
         return 0 ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   t4 = (TAG4 *)mem4alloc( c4->tagMemory ) ;
 | 
						|
   if ( t4 == 0 )
 | 
						|
   {
 | 
						|
      #ifdef E4STACK
 | 
						|
         error4stack( c4, e4memory, E94903 ) ;
 | 
						|
      #endif
 | 
						|
      if ( i4ndx == 0 )
 | 
						|
         mem4free( c4->indexMemory, i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   t4->tagFile = tfile4open( d4, fileName ) ;
 | 
						|
   if ( t4->tagFile == 0 )
 | 
						|
   {
 | 
						|
      #ifdef E4STACK
 | 
						|
         error4stack( c4, e4memory, E94903 ) ;
 | 
						|
      #endif
 | 
						|
      mem4free( c4->tagMemory, t4 ) ;
 | 
						|
      if ( i4ndx == 0 )
 | 
						|
         mem4free( c4->indexMemory, i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( t4->tagFile->header.unique )
 | 
						|
      t4->errUnique = c4->errDefaultUnique ;
 | 
						|
   t4->index = i4 ;
 | 
						|
   if ( i4ndx == 0 )
 | 
						|
   {
 | 
						|
      i4->data = d4 ;
 | 
						|
      l4add( &d4->indexes, i4 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   l4add( &t4->index->tags, t4 ) ;
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      t4->isValid = 1 ;
 | 
						|
   #endif
 | 
						|
   return t4 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef P4ARGS_USED
 | 
						|
   #pragma argsused
 | 
						|
#endif
 | 
						|
int tfile4shrink( TAG4FILE *t4, long blockNo )
 | 
						|
{
 | 
						|
   #ifdef S4SINGLE
 | 
						|
      t4->header.eof = blockNo * 512 ;
 | 
						|
   #endif
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4CLIPPER */
 | 
						|
 | 
						|
int tfile4updateHeader( TAG4FILE *t4 )
 | 
						|
{
 | 
						|
   T4HEADER *header ;
 | 
						|
   FILE4 *file ;
 | 
						|
 | 
						|
   #ifdef S4BYTE_SWAP
 | 
						|
      I4IND_HEAD_WRITE swap ;
 | 
						|
   #endif
 | 
						|
   if ( error4code( t4->codeBase ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   header = &t4->header ;
 | 
						|
   file = &t4->file ;
 | 
						|
/*   header->version = header->oldVersion + 2 ; */
 | 
						|
 | 
						|
   if ( header->oldVersion != header->version )
 | 
						|
   {
 | 
						|
      #ifdef S4NDX
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            swap.root = x4reverseLong( (void *)&header->root ) ;
 | 
						|
            swap.eof = x4reverseLong( (void *)&header->eof ) ;
 | 
						|
            swap.keyLen = x4reverseShort( (void *)&header->keyLen ) ;
 | 
						|
            swap.keysMax = x4reverseShort( (void *)&header->keysMax ) ;
 | 
						|
            swap.int_or_date = x4reverseShort( (void *)&header->int_or_date ) ;
 | 
						|
            swap.groupLen = x4reverseShort( (void *)&header->groupLen ) ;
 | 
						|
            swap.dummy = x4reverseShort( (void *)&header->dummy ) ;
 | 
						|
            swap.unique = x4reverseShort( (void *)&header->unique ) ;
 | 
						|
 | 
						|
            if ( file4write( file, 0L, &swap, sizeof(I4IND_HEAD_WRITE)) < 0 )
 | 
						|
               return -1 ;
 | 
						|
 | 
						|
            header->version = x4reverseLong( (void *)&header->version ) ;
 | 
						|
            if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->version, sizeof(header->version)) < 0 )
 | 
						|
               return -1 ;
 | 
						|
            header->version = x4reverseLong( (void *)&header->version ) ;
 | 
						|
         #else
 | 
						|
            if ( file4write( file, 0L, &header->root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
               return -1 ;
 | 
						|
            if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->version, sizeof(header->version)) < 0 )
 | 
						|
               return -1 ;
 | 
						|
         #endif
 | 
						|
      #else
 | 
						|
         #ifdef S4CLIPPER
 | 
						|
            #ifdef S4BYTE_SWAP
 | 
						|
               swap.sign = x4reverseShort( (void *)&header->sign ) ;
 | 
						|
               swap.version = x4reverseShort( (void *)&header->version ) ;
 | 
						|
               swap.root = x4reverseLong( (void *)&header->root ) ;
 | 
						|
               swap.eof = x4reverseLong( (void *)&header->eof ) ;
 | 
						|
               swap.groupLen = x4reverseShort( (void *)&header->groupLen ) ;
 | 
						|
               swap.keyLen = x4reverseShort( (void *)&header->keyLen ) ;
 | 
						|
               swap.keyDec = x4reverseShort( (void *)&header->keyDec ) ;
 | 
						|
               swap.keysMax = x4reverseShort( (void *)&header->keysMax ) ;
 | 
						|
               swap.keysHalf = x4reverseShort( (void *)&header->keysHalf ) ;
 | 
						|
 | 
						|
               if ( file4write( file, 0L, &swap, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0)
 | 
						|
                  return -1 ;
 | 
						|
 | 
						|
               header->unique = x4reverseShort( (void *)&header->unique ) ;
 | 
						|
               if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->unique, sizeof(header->unique)) < 0 )
 | 
						|
                       return -1 ;
 | 
						|
               header->unique = x4reverseShort( (void *)&header->unique ) ;
 | 
						|
 | 
						|
               header->descending = x4reverseShort( (void *)&header->descending ) ;
 | 
						|
               if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(header->unique) + 1, &header->descending, sizeof(header->descending)) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
               header->descending = x4reverseShort( (void *)&header->descending ) ;
 | 
						|
            #else
 | 
						|
               if ( file4write( file, 0L, &header->sign, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
               if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &header->unique, sizeof(header->unique)) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
               if ( file4write( file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(header->unique) + 1, &header->descending, sizeof(header->descending)) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
            #endif
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
      header->oldVersion = header->version ;
 | 
						|
   }
 | 
						|
   return 0;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
   tfile4block(t4)->keyOn++ ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4doVersionCheck( TAG4FILE *t4, int doSeek, int updateVersion )
 | 
						|
{
 | 
						|
   #ifndef S4SINGLE
 | 
						|
      int rc, needSeek ;
 | 
						|
      B4BLOCK *b4 ;
 | 
						|
      CODE4 *c4 ;
 | 
						|
 | 
						|
      #ifdef E4PARM_LOW
 | 
						|
         if ( t4 == 0 )
 | 
						|
            return error4( 0, e4parm_null, E91635 ) ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      c4 = t4->codeBase ;
 | 
						|
 | 
						|
      if ( error4code( c4 ) < 0 )
 | 
						|
         return e4codeBase ;
 | 
						|
 | 
						|
      if ( tfile4lockTest( t4 ) )
 | 
						|
         return 0 ;
 | 
						|
 | 
						|
      #ifndef S4OPTIMIZE_OFF
 | 
						|
         /* make sure read from disk */
 | 
						|
         if ( t4->file.doBuffer )
 | 
						|
            c4->opt.forceCurrent = 1 ;
 | 
						|
      #endif
 | 
						|
 | 
						|
      #ifdef S4NDX
 | 
						|
         rc = file4readAll( &t4->file,  sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE,
 | 
						|
                             &t4->header.version, sizeof(t4->header.version ) ) ;
 | 
						|
         #ifndef S4OPTIMIZE_OFF
 | 
						|
            if ( t4->file.doBuffer )
 | 
						|
               c4->opt.forceCurrent = 0 ;
 | 
						|
         #endif
 | 
						|
         if ( rc < 0 )
 | 
						|
            return rc ;
 | 
						|
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            t4->header.version = x4reverseLong( (void *)&t4->header.version ) ;
 | 
						|
         #endif
 | 
						|
      #else
 | 
						|
         rc = file4readAll( &t4->file, 0L, &t4->header.sign , 2 * sizeof( short ) + 2 * sizeof( long ) ) ;
 | 
						|
         #ifndef S4OPTIMIZE_OFF
 | 
						|
            if ( t4->file.doBuffer )
 | 
						|
               c4->opt.forceCurrent = 0 ;
 | 
						|
         #endif
 | 
						|
         if ( rc < 0 )
 | 
						|
            return rc ;
 | 
						|
         #ifdef S4BYTE_SWAP
 | 
						|
            t4->header.sign = x4reverseShort( (void *)&t4->header.sign ) ;
 | 
						|
            t4->header.version = x4reverseShort( (void *)&t4->header.version ) ;
 | 
						|
            t4->header.root = x4reverseLong( (void *)&t4->header.root ) ;
 | 
						|
            t4->header.eof = x4reverseLong( (void *)&t4->header.eof ) ;
 | 
						|
            t4->header.groupLen = x4reverseShort( (void *)&t4->header.groupLen ) ;
 | 
						|
            t4->header.keyLen = x4reverseShort( (void *)&t4->header.keyLen ) ;
 | 
						|
            t4->header.keyDec = x4reverseShort( (void *)&t4->header.keyDec ) ;
 | 
						|
            t4->header.keysMax = x4reverseShort( (void *)&t4->header.keysMax ) ;
 | 
						|
            t4->header.keysHalf = x4reverseShort( (void *)&t4->header.keysHalf ) ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
 | 
						|
      if ( t4->header.version == t4->header.oldVersion )
 | 
						|
         return 0 ;
 | 
						|
 | 
						|
      if ( updateVersion == 1 )
 | 
						|
         t4->header.oldVersion = t4->header.version ;
 | 
						|
      else
 | 
						|
         t4->header.version = t4->header.oldVersion ;
 | 
						|
 | 
						|
      /* remember the old position */
 | 
						|
      needSeek = 0 ;
 | 
						|
      if ( doSeek )
 | 
						|
      {
 | 
						|
         b4 = (B4BLOCK *)t4->blocks.lastNode ;  /* can't use tfile4block( t4 ) since might be null */
 | 
						|
         if ( b4 != 0 )
 | 
						|
         {
 | 
						|
            if ( tfile4eof( t4 ) )
 | 
						|
               needSeek = 2 ;
 | 
						|
            else
 | 
						|
/*               if ( b4leaf( b4 ) && b4->nKeys != 0 )
 | 
						|
                 changed line 04/09/96 AS --> if on a branch, and no seek is performed, a gpf or general
 | 
						|
                 error can later occur (in d4seek) --> this should be ok for S4CLIPPER */
 | 
						|
               if ( b4->nKeys != 0 )
 | 
						|
               {
 | 
						|
                  memcpy( c4->savedKey, b4key( b4, b4->keyOn ), t4->header.keyLen + 2 * sizeof( long ) ) ;
 | 
						|
                  needSeek = 1 ;
 | 
						|
               }
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      if ( tfile4freeAll( t4 ) < 0 )  /* Should be a memory operation only */
 | 
						|
         #ifdef E4ANALYZE
 | 
						|
            return error4( c4, e4result, E91635 ) ;
 | 
						|
         #else
 | 
						|
            return e4result ;
 | 
						|
         #endif
 | 
						|
 | 
						|
      switch( needSeek )
 | 
						|
      {
 | 
						|
         case 1:
 | 
						|
            #ifdef E4ANALYZE_ALL
 | 
						|
               if ( tfile4go( t4, ((B4KEY_DATA *)c4->savedKey)->value, ((B4KEY_DATA *)c4->savedKey)->num, 0 ) != 0 )
 | 
						|
                  return error4( c4, e4index, E91635 ) ;
 | 
						|
            #else
 | 
						|
               tfile4go( t4, ((B4KEY_DATA *)c4->savedKey)->value, ((B4KEY_DATA *)c4->savedKey)->num, 0 ) ;
 | 
						|
            #endif
 | 
						|
            break ;
 | 
						|
         case 2:
 | 
						|
            tfile4goEof( t4 ) ;
 | 
						|
            break ;
 | 
						|
      }
 | 
						|
 | 
						|
   #endif
 | 
						|
   return 0;
 | 
						|
}
 | 
						|
 | 
						|
int tfile4versionCheck( TAG4FILE *t4, const int doSeek, const int updateVersion )
 | 
						|
{
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      if ( t4->file.doBuffer == 0 )
 | 
						|
   #endif
 | 
						|
   #ifndef S4SINGLE
 | 
						|
      if ( tfile4lockTest( t4 ) == 0 )
 | 
						|
   #endif
 | 
						|
      return tfile4doVersionCheck( t4, doSeek, updateVersion ) ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* N4OTHER */
 | 
						|
#endif  /* S4INDEX_OFF */
 | 
						|
 | 
						|
#ifdef S4VB_DOS
 | 
						|
#ifdef N4OTHER
 | 
						|
 | 
						|
TAG4 *S4FUNCTION tfile4open_v(DATA4 *d4, char *name)
 | 
						|
   {
 | 
						|
      return tfile4open( d4, 0, c4str(name) ) ;
 | 
						|
   }
 | 
						|
 | 
						|
#endif  /* N4OTHER */
 | 
						|
#endif  /* S4VB_DOS */
 | 
						|
#endif  /* S4CLIENT */
 |