/* 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 */