2370 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2370 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* i4index.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifdef __TURBOC__
 | |
|    #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #ifndef S4INDEX_OFF
 | |
| 
 | |
| #ifdef S4CLIENT
 | |
| /* if i4old is set to a value, then it is used instead of creating a new i4 */
 | |
| /* if doFull is set to false and i4old is valid, a tag update between i4file
 | |
|    and i4 are done only */
 | |
| 
 | |
| static INDEX4 *i4setup2( CODE4 *c4, INDEX4FILE *i4file, DATA4 *d4, const char *name, INDEX4 *i4old, int doFull )
 | |
| {
 | |
|    INDEX4 *i4 ;
 | |
|    TAG4FILE *tagOn ;
 | |
|    TAG4 *tag, *tag2 ;
 | |
|    int doUpdate ;
 | |
| 
 | |
|    if ( i4old == 0 )
 | |
|    {
 | |
|       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 ) ;
 | |
|       i4->codeBase = c4 ;
 | |
|       i4->data = d4 ;
 | |
|       i4->indexFile = i4file ;
 | |
|       l4add( &d4->indexes, i4 ) ;
 | |
|       u4ncpy( i4->alias, name, sizeof( i4->alias ) - 1 ) ;
 | |
|    }
 | |
|    else
 | |
|       i4 = i4old ;
 | |
| 
 | |
|    for ( tagOn = 0 ;; )
 | |
|    {
 | |
|       tagOn = (TAG4FILE *)l4next( &i4file->tags, tagOn ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       if ( doFull == 0 )   /* check that tag doesn't already exit */
 | |
|       {
 | |
|          doUpdate = 1 ;
 | |
|          for ( tag2 = 0 ;; )
 | |
|          {
 | |
|             tag2 = (TAG4 *)l4next( &i4->tags, tag2 ) ;
 | |
|             if ( tag2 == 0 )
 | |
|                break ;
 | |
|             if ( tag2->tagFile == tagOn )
 | |
|             {
 | |
|                doUpdate = 0 ;
 | |
|                break ;
 | |
|             }
 | |
|          }
 | |
|          if ( doUpdate == 0 )
 | |
|             continue ;
 | |
|       }
 | |
|       tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
 | |
|       if ( tag == 0 )
 | |
|          return 0 ;
 | |
|       tag->tagFile = tagOn ;
 | |
|       tag->index = i4 ;
 | |
|       tag->errUnique = tagOn->errUniqueHold ;
 | |
|       l4add( &i4->tags, tag ) ;
 | |
|    }
 | |
| 
 | |
|    return i4 ;
 | |
| }
 | |
| 
 | |
| /* if i4old is set to a value, then it is used instead of creating a new i4 */
 | |
| int i4setup( CODE4 *c4, DATA4 *d4, const char *name, int autoOpened, INDEX4 *i4old )
 | |
| {
 | |
|    INDEX4FILE *i4file ;
 | |
|    INDEX4 *i4 ;
 | |
|    int addIndex, addTags ;
 | |
| 
 | |
|    /* now set up the tags */
 | |
|    if ( c4->tagMemory == 0 )
 | |
|    {
 | |
|       c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
 | |
|       if ( c4->tagMemory == 0 )
 | |
|       {
 | |
|          d4close( d4 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    for ( i4file = 0 ;; )
 | |
|    {
 | |
|       i4file = (INDEX4FILE *)l4next( &d4->dataFile->indexes, i4file ) ;
 | |
|       if ( i4file == 0 )
 | |
|          break ;
 | |
|       addIndex = 1 ;
 | |
|       addTags = 0 ;
 | |
|       for ( i4 = 0 ;; )   /* only set up for i4file's not in i4's of d4 */
 | |
|       {
 | |
|          i4 = (INDEX4 *)l4next( &d4->indexes, i4 ) ;
 | |
|          if ( i4 == 0 )
 | |
|             break ;
 | |
|          if ( i4->indexFile == i4file )
 | |
|          {
 | |
|             if ( l4numNodes( &i4->tags ) < l4numNodes( &i4file->tags ) )
 | |
|                addTags = 1 ;
 | |
|             addIndex = 0 ;
 | |
|             break ;
 | |
|          }
 | |
|       }
 | |
|       if ( addIndex == 0 )
 | |
|       {
 | |
|          if ( addTags == 0 )
 | |
|             continue ;
 | |
|       }
 | |
|       else
 | |
|          i4file->userCount++ ;
 | |
|       i4 = i4setup2( c4, i4file, d4, name, i4old, addIndex ) ;
 | |
|       if ( i4 == 0 )
 | |
|       {
 | |
|          d4close( d4 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       i4file->autoOpened = autoOpened ;    /* if in i4open, must be a manual open */
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #else
 | |
| #ifdef S4CLIPPER
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int i4setup( CODE4 *c4, DATA4 *d4, const char *name, int autoOpened )
 | |
| {
 | |
|    TAG4FILE *tagFile ;
 | |
|    TAG4 *tag ;
 | |
|    DATA4FILE *dfile ;
 | |
|    INDEX4 *i4 = 0 ;
 | |
| 
 | |
|    dfile = d4->dataFile ;
 | |
| 
 | |
|    for ( tagFile = 0 ;; )
 | |
|    {
 | |
|       tagFile = (TAG4FILE *)l4next( &dfile->tagfiles, tagFile ) ;
 | |
|       if ( tagFile == 0 )
 | |
|          break ;
 | |
|       if ( i4 == 0 )
 | |
|       {
 | |
|          i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
 | |
|          i4->codeBase = c4 ;
 | |
|          i4->data = d4 ;
 | |
|          l4add( &d4->indexes, i4 ) ;
 | |
|          u4ncpy( i4->accessName, name, sizeof( i4->accessName ) - 1 ) ;
 | |
|       }
 | |
|       tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
 | |
|       if ( tag == 0 )
 | |
|          return 0 ;
 | |
|       tag->tagFile = tagFile ;
 | |
|       tag->tagFile->userCount++ ;
 | |
|       tag->index = i4 ;
 | |
|       #ifdef S4SERVER
 | |
|          tag->errUnique = tfile4unique( tag->tagFile, (short int)d4->codeBase->errDefaultUnique ) ;
 | |
|       #endif
 | |
|       l4add( &i4->tags, tag ) ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif
 | |
| #endif /* S4CLIENT */
 | |
| 
 | |
| #ifdef S4CLIENT
 | |
| int index4close( INDEX4FILE *i4 )
 | |
| {
 | |
|    CONNECTION4 *connection ;
 | |
|    CODE4 *c4 ;
 | |
|    TAG4FILE *tagOn ;
 | |
|    int finalRc, rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91702 ) ;
 | |
|    #endif
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( i4->userCount <= 0 )
 | |
|          return error4( i4->codeBase, e4struct, E81702 ) ;
 | |
|       if ( i4->codeBase == 0 )
 | |
|          return error4( i4->codeBase, e4struct, E91702 ) ;
 | |
|    #endif
 | |
| 
 | |
|    i4->userCount-- ;
 | |
|    finalRc = 0 ;
 | |
|    if ( i4->userCount == 0 )
 | |
|    {
 | |
|       c4 = i4->codeBase ;
 | |
|       if ( i4->autoOpened == 0 )   /* must manually close ... */
 | |
|       {
 | |
|          #ifndef S4OFF_TRAN
 | |
|             if ( code4transEnabled( c4 ) )
 | |
|                if ( code4trans( c4 )->currentTranStatus == r4active )  /* disallow on current active only */
 | |
|                   return error4( c4, e4transViolation, E81522 ) ;
 | |
|          #endif
 | |
|          connection = i4->dataFile->connection ;
 | |
|          #ifdef E4ANALYZE
 | |
|             if ( connection == 0 )
 | |
|                finalRc = error4( c4, e4struct, E91702 ) ;
 | |
|             else
 | |
|             {
 | |
|          #endif
 | |
|             connection4assign( connection, CON4INDEX_CLOSE, i4->clientId, i4->serverId ) ;
 | |
|             connection4addData( connection, i4->accessName, strlen( i4->accessName ) + 1, 0 ) ;
 | |
|             connection4send( connection ) ;
 | |
|             rc = connection4receive( connection ) ;
 | |
|             if ( rc != 0 )
 | |
|                finalRc = error4( c4, rc, E81701 ) ;
 | |
|             else
 | |
|             {
 | |
|                rc = connection4status( connection ) ;
 | |
|                if ( rc != 0 )
 | |
|                   finalRc = connection4error( connection, c4, rc, E91702 ) ;
 | |
|             }
 | |
|          #ifdef E4ANALYZE
 | |
|             }
 | |
|          #endif
 | |
|       }
 | |
|       for( ;; )
 | |
|       {
 | |
|          tagOn = (TAG4FILE *)l4pop( &i4->tags ) ;
 | |
|          if ( tagOn == 0 )
 | |
|             break ;
 | |
|          if ( tagOn->exprPtr != 0 )
 | |
|          {
 | |
|             u4free( tagOn->exprPtr ) ;
 | |
|             tagOn->exprPtr = 0 ;
 | |
|          }
 | |
|          if ( tagOn->filterPtr != 0 )
 | |
|          {
 | |
|             u4free( tagOn->filterPtr ) ;
 | |
|             tagOn->filterPtr = 0 ;
 | |
|          }
 | |
|          mem4free( c4->tagFileMemory, tagOn ) ;
 | |
|          tagOn = 0 ;
 | |
|       }
 | |
|       l4remove( &i4->dataFile->indexes, i4 ) ;
 | |
|       mem4free( c4->index4fileMemory, i4 ) ;
 | |
|       i4 = 0 ;
 | |
|       return finalRc ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION i4close( INDEX4 *i4 )
 | |
| {
 | |
|    int rc, finalRc ;
 | |
|    TAG4 *tagOn ;
 | |
|    CODE4 *c4 ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E91701 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91701 ) ;
 | |
|       if ( i4->codeBase == 0 )
 | |
|          return error4( 0, e4parm, E91701 ) ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = i4->codeBase ;
 | |
| 
 | |
|    finalRc = 0 ;
 | |
| 
 | |
|    #ifndef S4OFF_WRITE
 | |
|       if ( i4->data )
 | |
|          if ( d4update( i4->data ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( i4->data == 0 )
 | |
|          return error4( 0, e4struct, E91701 ) ;
 | |
|       if ( i4->data->dataFile == 0 )
 | |
|          return error4( 0, e4struct, E91701 ) ;
 | |
|    #endif
 | |
|    if ( i4->data->tagSelected != 0 )
 | |
|       if ( i4->data->tagSelected->index == i4 )
 | |
|          i4->data->tagSelected = 0 ;
 | |
|    for( ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4pop( &i4->tags ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       mem4free( c4->tagMemory, tagOn ) ;
 | |
|       tagOn = 0 ;
 | |
|    }
 | |
|    l4remove( &i4->data->indexes, i4 ) ;
 | |
|    rc = index4close( i4->indexFile ) ;
 | |
|    mem4free( c4->indexMemory, i4 ) ;
 | |
|    i4 = 0 ;
 | |
|    if ( rc < 0 )
 | |
|       return rc ;
 | |
|    return finalRc ;
 | |
| }
 | |
| 
 | |
| #endif /* S4CLIENT */
 | |
| 
 | |
| const char *S4FUNCTION i4fileName( INDEX4 *i4 )
 | |
| {
 | |
|    #ifdef S4CLIENT
 | |
|       CONNECTION4 *connection ;
 | |
|       int rc ;
 | |
|    #else
 | |
|       #ifdef S4CLIPPER
 | |
|          TAG4FILE *tag ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91720 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       if ( error4code( i4->codeBase ) < 0 )
 | |
|          return 0 ;
 | |
| 
 | |
|       connection = i4->data->dataFile->connection ;
 | |
|       connection4assign( connection, CON4INDEX_FNAME, data4clientId( i4->data ), data4serverId( i4->data ) ) ;
 | |
|       connection4addData( connection, i4->indexFile->accessName, strlen( i4->indexFile->accessName ) + 1, 0 ) ;
 | |
|       connection4send( connection ) ;
 | |
|       rc = connection4receive( connection ) ;
 | |
|       if ( rc < 0 )
 | |
|       {
 | |
|          #ifdef E4STACK
 | |
|             error4stack( i4->codeBase, rc, E95501 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       rc = connection4status( connection ) ;
 | |
|       if ( rc < 0 )
 | |
|       {
 | |
|          connection4error( connection, i4->codeBase, rc, E95501 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       return connection4data( connection ) ;
 | |
|    #else
 | |
|       #ifdef S4CLIPPER
 | |
|          if ( i4->path != 0 )
 | |
|             return i4->path ;
 | |
|          if ( l4numNodes( &i4->tags ) == 1 )
 | |
|          {
 | |
|             tag = (TAG4FILE *)(((TAG4 *)(i4->tags.lastNode))->tagFile) ;
 | |
|             return tag->alias ;
 | |
|          }
 | |
|          else
 | |
|             return d4fileName( i4->data ) ;
 | |
|       #else
 | |
|          return i4->indexFile->file.name ;
 | |
|       #endif /* S4CLIPPER */
 | |
|    #endif /* S4CLIENT */
 | |
| }
 | |
| 
 | |
| #ifndef S4CLIPPER
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| int S4FUNCTION i4close( INDEX4 *i4 )
 | |
| {
 | |
|    int rc, finalRc ;
 | |
|    TAG4 *tagOn ;
 | |
|    CODE4 *c4 ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E91701 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91701 ) ;
 | |
|       if ( i4->codeBase == 0 )
 | |
|          return error4( 0, e4parm, E91701 ) ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = i4->codeBase ;
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       if ( i4->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 = 0 ;
 | |
| 
 | |
|    #ifndef S4OFF_WRITE
 | |
|       #ifndef S4OFF_TRAN
 | |
|          if ( i4->isValid == 1 ) /* if invalid (failed create/open) then allow close */
 | |
|       #endif
 | |
|       if ( i4->data )
 | |
|          if ( d4update( i4->data ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for( ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4pop( &i4->tags ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       #ifndef S4OFF_TRAN
 | |
|          #ifdef E4ANALYZE
 | |
|             if ( tagOn->removedKeys.nLink != 0 )
 | |
|                return error4( c4, e4info, E91701 ) ;
 | |
|          #endif
 | |
|       #endif
 | |
|       if ( i4->data->tagSelected == tagOn )  /* can't have a tag selected from a closed index */
 | |
|          i4->data->tagSelected = 0 ;
 | |
|       mem4free( c4->tagMemory, tagOn ) ;
 | |
|       tagOn = 0 ;
 | |
|    }
 | |
|    if ( i4->indexFile != 0 )
 | |
|    {
 | |
|       rc = index4close( i4->indexFile ) ;
 | |
|       if ( rc != 0 )
 | |
|          finalRc = rc ;
 | |
|    }
 | |
|    if ( i4->link.n != 0 )
 | |
|       l4remove( &i4->data->indexes, i4 ) ;
 | |
|    mem4free( c4->indexMemory, i4 ) ;
 | |
|    i4 = 0 ;
 | |
| 
 | |
|    if ( finalRc != 0 )
 | |
|    {
 | |
|       error4set( c4, finalRc ) ;
 | |
|       return finalRc ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int index4close( INDEX4FILE *i4 )
 | |
| {
 | |
|    int finalRc, isProduction ;
 | |
|    CODE4 *c4 ;
 | |
|    TAG4FILE *tagOn ;
 | |
|    #ifndef S4SINGLE
 | |
|       int saveAttempts ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91702 ) ;
 | |
|    #endif
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( i4->userCount < 0 )
 | |
|          return error4( i4->codeBase, e4struct, E81702 ) ;
 | |
|    #endif
 | |
| 
 | |
|    isProduction = index4isProduction( i4 ) ;
 | |
|    if ( ( i4->userCount <= 1 && isProduction == 0 ) || ( i4->userCount == 0 && i4->dataFile->userCount == 0 ) )
 | |
|    {
 | |
|       c4 = i4->codeBase ;
 | |
| 
 | |
|       finalRc = error4code( c4 ) ;
 | |
|       #ifndef S4SINGLE
 | |
|          saveAttempts = c4->lockAttempts ;
 | |
|          c4->lockAttempts = WAIT4EVER ;
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4OFF_WRITE
 | |
|          if ( index4update( i4 ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4SINGLE
 | |
|          if ( index4unlock( i4, 0UL ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|       #endif
 | |
| 
 | |
|       #ifdef S4FOX
 | |
|          if ( i4->tagIndex )
 | |
|             if ( i4->tagIndex->header.typeCode >= 64 )  /* compound index */
 | |
|       #endif
 | |
|       for( ;; )
 | |
|       {
 | |
|          tagOn = (TAG4FILE *)l4pop( &i4->tags ) ;
 | |
|          if ( tagOn == 0 )
 | |
|             break ;
 | |
|          if ( tfile4freeAll( tagOn ) < 0 )
 | |
|          {
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|             break ;
 | |
|          }
 | |
|          expr4free( tagOn->expr ) ;
 | |
|          expr4free( tagOn->filter ) ;
 | |
|          #ifdef S4FOX
 | |
|             mem4release( tagOn->builtKeyMemory ) ;
 | |
|          #endif
 | |
|          mem4free( c4->tagFileMemory, tagOn ) ;
 | |
|          tagOn = 0 ;
 | |
|       }
 | |
| 
 | |
|       #ifdef S4FOX
 | |
|          if ( i4->tagIndex != 0 )
 | |
|          {
 | |
|             if ( tfile4freeAll( i4->tagIndex ) < 0 )
 | |
|                finalRc = error4set( c4, 0 ) ;
 | |
|             else
 | |
|             {
 | |
|                expr4free( i4->tagIndex->expr ) ;
 | |
|                expr4free( i4->tagIndex->filter ) ;
 | |
|                #ifdef S4FOX
 | |
|                   mem4release( i4->tagIndex->builtKeyMemory ) ;
 | |
|                #endif
 | |
|                mem4free( c4->tagFileMemory, i4->tagIndex ) ;
 | |
|                i4->tagIndex = 0 ;
 | |
|             }
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       mem4release( i4->blockMemory ) ;
 | |
| 
 | |
|       if ( file4openTest( &i4->file ) )
 | |
|       {
 | |
|          if ( i4->dataFile )
 | |
|             l4remove( &i4->dataFile->indexes, i4 ) ;
 | |
|          #ifndef S4CLIPPER
 | |
|             #ifndef S4SERVER
 | |
|                if ( c4->doRemove == 1 )
 | |
|                   i4->file.isTemp = 1 ;
 | |
|             #endif
 | |
|          #endif
 | |
|          if ( file4close( &i4->file ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|       }
 | |
| 
 | |
|       mem4free( c4->index4fileMemory, i4 ) ;
 | |
|       i4 = 0 ;
 | |
|       #ifndef S4SINGLE
 | |
|          c4->lockAttempts = saveAttempts ;
 | |
|       #endif
 | |
|       error4set( c4, (short)finalRc ) ;
 | |
|       return finalRc ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       i4->userCount-- ;
 | |
|       return 0 ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| long index4extend( INDEX4FILE *i4 )
 | |
| {
 | |
|    long oldEof ;
 | |
|    unsigned len ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91703 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    #ifndef S4FOX
 | |
|       oldEof = i4->header.freeList ;
 | |
| 
 | |
|       if( i4->header.freeList == 0L )  /* case where no free list */
 | |
|       {
 | |
|          oldEof = i4->header.eof ;
 | |
|          i4->header.eof = i4->header.eof + i4->header.blockRw/I4MULTIPLY ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          len = file4read( &i4->file, i4->header.freeList*I4MULTIPLY + sizeof(S4LONG),
 | |
|                (char *)&i4->header.freeList, sizeof(i4->header.freeList)) ;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
 | |
|          #endif
 | |
| 
 | |
|          if ( error4code( i4->codeBase ) < 0 )  return -1 ;
 | |
| 
 | |
|          switch( len )
 | |
|          {
 | |
|             case 0:
 | |
|                #ifdef E4ANALYZE
 | |
|                   return error4( i4->codeBase, e4index, E91703 ) ;
 | |
|                #else   /* try to fix up */
 | |
|                   i4->header.freeList = 0L ;
 | |
|                   oldEof = i4->header.eof ;
 | |
|                   i4->header.eof = i4->header.eof + i4->header.blockRw/I4MULTIPLY ;
 | |
|                   break ;
 | |
|                #endif
 | |
|             case sizeof(i4->header.freeList):
 | |
|                break ;
 | |
|             default:
 | |
|                return file4readError( &i4->file, i4->header.freeList*I4MULTIPLY + sizeof(S4LONG), sizeof(i4->header.freeList), "index4extend" ) ;
 | |
|          }
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4FOX
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( i4->tagIndex->header.version == i4->versionOld )
 | |
|             return error4( i4->codeBase, e4index, E91703 ) ;
 | |
|       #endif
 | |
| 
 | |
|       oldEof = i4->tagIndex->header.freeList ;
 | |
| 
 | |
|       if( oldEof == 0L )  /* case where no free list */
 | |
|       {
 | |
|          oldEof = i4->eof ;
 | |
|          i4->eof += B4BLOCK_SIZE ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          len = file4read( &i4->file, i4->tagIndex->header.freeList*I4MULTIPLY,
 | |
|                (char *)&i4->tagIndex->header.freeList, sizeof(i4->tagIndex->header.freeList)) ;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->tagIndex->header.freeList = x4reverseLong( &i4->tagIndex->header.freeList ) ;
 | |
|          #endif
 | |
| 
 | |
|          if ( error4code( i4->codeBase ) < 0 )  return -1 ;
 | |
| 
 | |
|          switch( len )
 | |
|          {
 | |
|             case 0:
 | |
|                #ifdef E4ANALYZE
 | |
|                   return error4( i4->codeBase, e4index, E91703 ) ;
 | |
|                #else  /* else fix up */
 | |
|                   i4->tagIndex->header.freeList = 0L ;
 | |
|                   oldEof = i4->eof ;
 | |
|                   i4->eof += B4BLOCK_SIZE ;
 | |
|                   break ;
 | |
|                #endif
 | |
|             case sizeof(i4->tagIndex->header.freeList):
 | |
|                break ;
 | |
|             default:
 | |
|                return file4readError( &i4->file, i4->tagIndex->header.freeList*I4MULTIPLY, sizeof(i4->tagIndex->header.freeList), "index4extend" ) ;
 | |
|          }
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return oldEof ;
 | |
| }
 | |
| 
 | |
| int index4flush( INDEX4FILE *i4 )
 | |
| {
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91704 ) ;
 | |
|    #endif
 | |
| 
 | |
|    rc = index4update( i4 ) ;
 | |
|    if ( file4flush( &i4->file ) < 0 )
 | |
|       rc = -1 ;
 | |
| 
 | |
|    return rc ;
 | |
| }
 | |
| 
 | |
| int index4update( INDEX4FILE *i4 )
 | |
| {
 | |
|    TAG4FILE *tagOn ;
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91705 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       if ( i4->fileLocked != 0 )
 | |
|       {
 | |
|    #endif
 | |
|    rc = index4updateHeader( i4 ) ;
 | |
|    if ( rc < 0 )
 | |
|       return error4stack( i4->codeBase, (short)rc, E91705 ) ;
 | |
|    #ifdef S4FOX
 | |
|       rc = tfile4update(i4->tagIndex) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( i4->codeBase, (short)rc, E91705 ) ;
 | |
|       if ( i4->tagIndex->header.typeCode >= 64 )  /* compound index */
 | |
|    #endif
 | |
| 
 | |
|    for ( tagOn = 0 ;; )
 | |
|    {
 | |
|       tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       rc = tfile4update( tagOn ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( i4->codeBase, (short)rc, E91705 ) ;
 | |
|       tagOn->header.root = -1L ;
 | |
|    }
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4OFF_WRITE */
 | |
| #endif  /* S4CLIENT */
 | |
| 
 | |
| INDEX4 *S4FUNCTION i4open( DATA4 *d4, const char *fileName )
 | |
| {
 | |
|    CODE4  *c4 ;
 | |
|    INDEX4 *i4 ;
 | |
|    #ifdef S4CLIENT
 | |
|       INDEX4FILE *i4file ;
 | |
|       unsigned char buf[258] ;
 | |
|    #else
 | |
|       TAG4 *tag ;
 | |
|       TAG4FILE *tagFile ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( d4 == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91706 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( d4, 2, E91706 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = d4->codeBase ;
 | |
|    if ( error4code( c4 ) < 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       if ( fileName == 0 )
 | |
|          u4ncpy( (char *)buf, d4->dataFile->accessName, sizeof( buf ) - 1 ) ;
 | |
|       else
 | |
|       {
 | |
|          if ( strlen( fileName ) > sizeof( buf ) - 1 )
 | |
|          {
 | |
|             error4( c4, e4name, E91706 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|          strcpy( (char*)buf, fileName ) ;
 | |
|       }
 | |
|       c4upper( (char*)buf ) ;
 | |
|       i4 = d4index( d4, (char S4PTR*)buf ) ;
 | |
|       if ( i4 != 0 )   /* duplicates not allowed */
 | |
|          error4( c4, e4instance, E91706 ) ;
 | |
|       i4file = index4open( d4, (char S4PTR*)buf, 0 ) ;
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return 0 ;
 | |
|       i4 = d4index( d4, (char S4PTR*)buf ) ;
 | |
|       if ( i4file == 0 )
 | |
|       {
 | |
|          if ( i4 == 0 )
 | |
|             return 0 ;
 | |
|          #ifdef E4ANALZE
 | |
|             if ( i4->indexFile == 0 )
 | |
|             {
 | |
|                error4( c4, e4info, E91706 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          #endif
 | |
|          i4file = i4->indexFile ;
 | |
|          i4file->clientId = data4clientId( d4 ) ;
 | |
|          i4file->serverId = data4serverId( d4 ) ;
 | |
|       }
 | |
|       else  /* indexfile already exists so set up another index4 structure */
 | |
|       {
 | |
|          i4 = i4setup2( c4, i4file, d4, (char S4PTR*)buf, 0, 1 ) ;
 | |
|          if ( i4 == 0 )
 | |
|          {
 | |
|             index4close( i4file ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       }
 | |
|       #ifdef E4ANALZE
 | |
|          else
 | |
|          {
 | |
|             if ( i4->indexFile != i4file )
 | |
|             {
 | |
|                error4( c4, e4info, E91706 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|       #endif
 | |
|       i4->codeBase = c4 ;
 | |
|       #ifndef S4OFF_TRAN
 | |
|          i4->isValid = 1 ;
 | |
|       #endif
 | |
|       return i4 ;
 | |
|    #else
 | |
|       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 ERROR4STACK
 | |
|             error4stack( c4, e4memory, E91706 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       i4->data = d4 ;
 | |
|       i4->codeBase = c4 ;
 | |
| 
 | |
|       if ( fileName != 0 )
 | |
|       {
 | |
|          #ifdef E4MISC
 | |
|             if ( strlen( fileName ) > sizeof( i4->accessName ) )
 | |
|             {
 | |
|                error4describe( c4, e4name, E91706, fileName, 0, 0 ) ;
 | |
|                i4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          #endif
 | |
|          u4ncpy( i4->accessName, fileName, sizeof( i4->accessName ) - 1 ) ;
 | |
|       }
 | |
|       #ifdef S4STAND_ALONE
 | |
|          else
 | |
|          {
 | |
|             u4namePiece( i4->accessName, sizeof( i4->accessName ), d4->alias, 0, 0 ) ;
 | |
|          }
 | |
|          #ifndef S4CASE_SEN
 | |
|             c4upper( i4->accessName ) ;
 | |
|          #endif
 | |
|       #endif
 | |
| 
 | |
|       i4->indexFile = index4open( d4, fileName, i4 ) ;
 | |
|       if ( i4->indexFile == 0 )
 | |
|       {
 | |
|          i4close( i4 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       l4add( &d4->indexes, i4 ) ;
 | |
| 
 | |
|       for ( tagFile = 0 ;; )
 | |
|       {
 | |
|          tagFile = (TAG4FILE *)l4next( &i4->indexFile->tags, tagFile ) ;
 | |
|          if ( tagFile == 0 )
 | |
|             break ;
 | |
| 
 | |
|          tag = (TAG4 *)mem4alloc( c4->tagMemory ) ;
 | |
|          if ( tag == 0 )
 | |
|          {
 | |
|             i4close( i4 ) ;
 | |
|             error4( c4, e4memory, E91706 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|          tag->index = i4 ;
 | |
|          tag->tagFile = tagFile ;
 | |
| 
 | |
|          #ifdef S4FOX
 | |
|             if ( tag->tagFile->header.typeCode & 0x04 )  /* r4/e4 candidate */
 | |
|             {
 | |
|                if ( c4->errDefaultUnique == e4unique )
 | |
|                   tag->errUnique = e4candidate ;
 | |
|                else
 | |
|                   tag->errUnique = r4candidate ;
 | |
|             }
 | |
|             else
 | |
|                if ( tag->tagFile->header.typeCode & 0x01 )
 | |
|          #else
 | |
|             if ( tag->tagFile->header.unique )
 | |
|          #endif
 | |
|                tag->errUnique = c4->errDefaultUnique ;
 | |
| 
 | |
| 
 | |
|          l4add( &i4->tags, tag ) ;
 | |
|       }
 | |
| 
 | |
|       #ifndef S4OFF_TRAN
 | |
|          i4->isValid = 1 ;
 | |
|       #endif
 | |
|       return i4 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| /* for the client, if index is not null, then the function only verifies the
 | |
|    existance of the index file and does not actually open it */
 | |
| INDEX4FILE *index4open( DATA4 *d4, const char *fileName, INDEX4 *index )
 | |
| {
 | |
|    CODE4  *c4 ;
 | |
|    int    rc ;
 | |
|    INDEX4FILE *i4 ;
 | |
|    #ifdef S4CLIENT
 | |
|       CONNECTION4OPEN_INDEX_INFO_OUT *info ;
 | |
|       CONNECTION4OPEN_INDEX_INFO_IN dataIn ;
 | |
|       CONNECTION4 *connection ;
 | |
|    #else
 | |
|       char buf[258] ;
 | |
|       TAG4FILE *tagFile ;
 | |
|       DATA4FILE *dfile ;
 | |
|       #ifdef E4MISC
 | |
|          INDEX4FILE *i4ptr ;
 | |
|       #endif
 | |
|       #ifdef S4FOX
 | |
|          B4BLOCK *b4 ;
 | |
|          #ifndef S4SINGLE
 | |
|             long oldFileLock ;
 | |
|          #endif
 | |
|       #else
 | |
|          T4DESC tagInfo[47] ;
 | |
|          int iTag ;
 | |
|       #endif
 | |
|    #endif
 | |
|    #ifndef S4SERVER
 | |
|       INDEX4 *indexLoop ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( d4 == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91707 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       #ifndef S4CLIENT
 | |
|          if ( index == 0 )
 | |
|          {
 | |
|             error4( 0, e4parm_null, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    c4 = d4->codeBase ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       i4 = dfile4index( d4->dataFile, fileName ) ;
 | |
|    #else
 | |
|       dfile = d4->dataFile ;
 | |
|       #ifdef E4ANALYZE
 | |
|          if ( code4indexExtension( c4 ) == 0 )
 | |
|          {
 | |
|             error4( c4, e4struct, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       #endif
 | |
|       if ( fileName == 0 )
 | |
|          u4ncpy( (char *)buf, dfile->file.name, sizeof( buf ) - 1 ) ;
 | |
|       else
 | |
|       {
 | |
|          rc = u4nameCurrent( (char *)buf, sizeof( buf ), fileName ) ;
 | |
|          if ( rc < 0 )
 | |
|          {
 | |
|             error4( c4, rc, E94509 ) ;  /* from u4nameCurrent */
 | |
|             return 0 ;
 | |
|          }
 | |
|       }
 | |
|       u4nameExt( (char *)buf, sizeof( buf ), code4indexExtension( c4 ), ( fileName == 0 ? 1 : 0 ) ) ;
 | |
|       #ifndef S4CASE_SEN
 | |
|          c4upper( (char *)buf ) ;
 | |
|       #endif
 | |
|       i4 = dfile4index( dfile, (char *)buf ) ;
 | |
|    #endif
 | |
|    if ( i4 != 0 )
 | |
|    {
 | |
|       #ifndef S4SERVER
 | |
|          /* allowed if current data4 does not have a pointer to index */
 | |
|          for ( indexLoop = 0 ;; )
 | |
|          {
 | |
|             indexLoop = (INDEX4 *)l4next( &d4->indexes, indexLoop ) ;
 | |
|             if ( indexLoop == 0 )
 | |
|                break ;
 | |
|             if ( indexLoop->indexFile == i4 )
 | |
|             {
 | |
|                error4( c4, e4instance, E91707 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|          #ifdef S4OFF_FOR_NOW
 | |
|          if ( i4->userCount > 0 && c4->singleOpen != OPEN4SPECIAL )   /* only one instance allowed unless performing additional d4open */
 | |
|          {
 | |
|             #ifdef S4STAND_ALONE
 | |
|                #ifndef S4OFF_TRAN
 | |
|                   /* verify that index4 not on the closed data list if within a
 | |
|                      transaction (which is allowed) */
 | |
|                   if ( code4tranStatus( c4 ) == r4active )
 | |
|                   {
 | |
|                      list = tran4dataList( (&(c4->c4trans.trans)) ) ;
 | |
|                      for ( data4 = 0 ;; )
 | |
|                      {
 | |
|                         data4 = (DATA4 *)l4next( list, data4 ) ;
 | |
|                         if ( data4 == 0 )
 | |
|                            break ;
 | |
|                         for ( indexLoop = 0 ;; )
 | |
|                         {
 | |
|                            indexLoop = (INDEX4 *)l4next( &data4->indexes, indexLoop ) ;
 | |
|                            if ( indexLoop == 0 )
 | |
|                               break ;
 | |
|                            if ( indexLoop->indexFile == i4 )
 | |
|                            {
 | |
|                               error4( c4, e4instance, E91707 ) ;
 | |
|                               return 0 ;
 | |
|                            }
 | |
|                         }
 | |
|                      }
 | |
|                   }
 | |
|                   else
 | |
|                #endif /* S4OFF_TRAN */
 | |
|             #endif /* S4STAND_ALONE */
 | |
|             {
 | |
|                error4( c4, e4instance, E91707 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|          #endif /* OFF_FOR_NOW */
 | |
|       #endif
 | |
|       i4->userCount++ ;
 | |
|       return i4 ;
 | |
|    }
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( d4, 2, E91707 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       if ( index != 0 )   /* just wanted to verify existance of... */
 | |
|          return 0 ;
 | |
|       c4 = d4->dataFile->c4 ;
 | |
|    #else
 | |
|       c4 = dfile->c4 ;
 | |
|    #endif
 | |
|    if ( error4code( c4 ) < 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( c4->index4fileMemory == 0 )
 | |
|       c4->index4fileMemory = mem4create( c4, c4->memStartIndexFile, sizeof(INDEX4FILE), c4->memExpandIndexFile, 0 ) ;
 | |
|    if ( c4->index4fileMemory == 0 )
 | |
|        return 0 ;
 | |
| 
 | |
|    if ( c4->tagMemory == 0 )
 | |
|    {
 | |
|       c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof(TAG4), c4->memExpandTag, 0 ) ;
 | |
|       if ( c4->tagMemory == 0 )
 | |
|          return 0 ;
 | |
|    }
 | |
| 
 | |
|    if ( c4->tagFileMemory == 0 )
 | |
|    {
 | |
|       c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof(TAG4FILE), c4->memExpandTagFile, 0 ) ;
 | |
|       if ( c4->tagFileMemory == 0 )
 | |
|          return 0 ;
 | |
|    }
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       memset( &dataIn, 0, sizeof( CONNECTION4OPEN_INDEX_INFO_IN ) ) ;
 | |
|       connection = d4->dataFile->connection ;
 | |
|       if ( connection == 0 )
 | |
|       {
 | |
|          error4( c4, e4connection, E81704 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       connection4assign( connection, CON4INDEX_OPEN, data4clientId( d4 ), data4serverId( d4 ) ) ;
 | |
| 
 | |
|       dataIn.nameLen = strlen( (char*)fileName ) + 1 ;
 | |
|       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 ;
 | |
| 
 | |
|       connection4addData( connection, &dataIn, sizeof( CONNECTION4OPEN_INDEX_INFO_IN ), 0 ) ;
 | |
|       connection4addData( connection, fileName, 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, E91707 ) ;
 | |
|          }
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       #ifdef E4MISC
 | |
|          if ( connection4len( connection ) < sizeof( info ) )
 | |
|          {
 | |
|             error4( c4, e4packetLen, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       info = (CONNECTION4OPEN_INDEX_INFO_OUT *)connection4data( connection ) ;
 | |
|       if ( client4indexSetup( c4, d4, d4->dataFile, info->numTags, connection4data( connection ) + sizeof(CONNECTION4OPEN_INDEX_INFO_OUT),
 | |
|            (unsigned int)connection4len( connection ) - sizeof(CONNECTION4OPEN_INDEX_INFO_OUT), (char*)fileName, 0 ) < 0 )
 | |
|       {
 | |
|          error4( c4, e4connection, E91707 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       /* in the client case, a null is a valid return code as the index is
 | |
|          later extracted */
 | |
|       i4setup( c4, d4, (char*)fileName, 0, 0 ) ;
 | |
|       return 0 ;
 | |
|    #else
 | |
|       i4 = (INDEX4FILE *)mem4alloc( c4->index4fileMemory ) ;
 | |
|       if ( i4 == 0 )
 | |
|       {
 | |
|          #ifdef ERROR4STACK
 | |
|             error4stack( c4, e4memory, E91707 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       /* next line for this function duration only since the return of this
 | |
|          function is assigned into index->indexFile but upper level.
 | |
|          Therefore, we still must clean up ourselves if failure */
 | |
|       index->indexFile = i4 ;
 | |
|       i4->dataFile = dfile ;
 | |
|       i4->codeBase = c4 ;
 | |
|       #ifdef S4FOX
 | |
|          #ifdef E4MISC
 | |
|             for ( i4ptr = 0 ;; )
 | |
|             {
 | |
|                i4ptr = (INDEX4FILE *)l4next( &dfile->indexes, i4ptr ) ;
 | |
|                if ( i4ptr == 0 )
 | |
|                   break ;
 | |
|                if ( !c4memcmp( i4ptr->file.name, buf, (size_t)strlen( (char *)buf ) ) )
 | |
|                {
 | |
|                   mem4free( c4->index4fileMemory, i4 ) ;
 | |
|                   index->indexFile = 0 ;
 | |
|                   error4( c4, e4parm, E81703 ) ;
 | |
|                   return 0 ;
 | |
|                }
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          rc = file4open( &i4->file, c4, (char *)buf, 1 ) ;
 | |
|          if ( rc )
 | |
|          {
 | |
|             index->indexFile = 0 ;
 | |
|             mem4free( c4->index4fileMemory, i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          i4->eof = file4len( &i4->file ) ;
 | |
| 
 | |
|          i4->tagIndex = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
 | |
|          if ( i4->tagIndex == 0 )
 | |
|          {
 | |
|             file4close( &i4->file ) ;
 | |
|             index->indexFile = 0 ;
 | |
|             mem4free( c4->index4fileMemory, i4 ) ;
 | |
|             error4( c4, e4memory, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          l4add( &dfile->indexes, i4 ) ;
 | |
|          if ( fileName == 0 )
 | |
|          {
 | |
|             if ( tfile4init( i4->tagIndex, index, 0L, (unsigned char *)"" ) < 0 )
 | |
|             {
 | |
|                index4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             u4namePiece( (char *)buf, 258, fileName, 0, 0 ) ;  /* get the tagName based on the fileName */
 | |
|             if ( tfile4init( i4->tagIndex, index, 0L, (unsigned char *)buf) < 0 )
 | |
|             {
 | |
|                index4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|          if ( tfile4setCodePage( i4->tagIndex, d4->codePage ) < 0 )
 | |
|          {
 | |
|             error4( c4, e4index, E91642 ) ;
 | |
|             index4close( i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          /* Perform some checks */
 | |
|          if ( i4->tagIndex->header.root <= 0L || i4->tagIndex->header.typeCode < 32 )
 | |
|          {
 | |
|             #ifdef E4ANALYZE_ALL
 | |
|                error4describe( c4, e4index, E81714, buf, 0, 0 ) ;
 | |
|             #endif
 | |
|             index4close( i4 ) ;
 | |
|             #ifndef E4ANALYZE_ALL
 | |
|                error4describe( c4, e4index, E81714, (char *)buf, 0, 0 ) ;
 | |
|             #endif
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          i4->versionOld = i4->tagIndex->header.version ;
 | |
|          i4->blockMemory = mem4create( c4, c4->memStartBlock, sizeof(B4BLOCK) + B4BLOCK_SIZE
 | |
|                          - sizeof(B4STD_HEADER) - sizeof(B4NODE_HEADER), c4->memExpandBlock, 0 ) ;
 | |
|          if ( i4->blockMemory == 0 )
 | |
|          {
 | |
|             index4close( i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          /* do an initial block allocation to make sure minimal is allocated while optimization is suspended */
 | |
|          b4 = (B4BLOCK *)mem4alloc2( i4->blockMemory, c4 ) ;
 | |
|          if ( b4 == 0 )
 | |
|          {
 | |
|             index4close( i4  ) ;
 | |
|             error4( c4, e4memory, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             mem4free( i4->blockMemory, b4 ) ;
 | |
|             b4 = 0 ;
 | |
|          }
 | |
| 
 | |
|          #ifndef S4SINGLE
 | |
|             /* disable locking */
 | |
|             oldFileLock = i4->fileLocked ;
 | |
|             i4->fileLocked = data4serverId( d4 ) ;
 | |
|          #endif
 | |
| 
 | |
|          rc = tfile4top( i4->tagIndex ) ;
 | |
|          if ( rc < 0 )
 | |
|          {
 | |
|             #ifndef S4SINGLE
 | |
|                i4->fileLocked = oldFileLock ;
 | |
|             #endif
 | |
|             index4close( i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          /* if we have a compound index, then load the tags, otherwise this is the only tag */
 | |
|          if ( i4->tagIndex->header.typeCode >= 64 )
 | |
|          {
 | |
|             if ( b4numKeys( tfile4block( i4->tagIndex ) ) )
 | |
|                do
 | |
|                {
 | |
|                   tagFile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
 | |
|                   if ( tagFile == 0 )
 | |
|                   {
 | |
|                      index4close( i4 ) ;
 | |
|                      error4( c4, e4memory, E91707 ) ;
 | |
|                      #ifndef S4SINGLE
 | |
|                         i4->fileLocked = oldFileLock ;
 | |
|                      #endif
 | |
|                      return 0 ;
 | |
|                   }
 | |
| 
 | |
|                   if ( tfile4init( tagFile, index, b4recNo( tfile4block(i4->tagIndex), tfile4block(i4->tagIndex)->keyOn ), tfile4keyData( i4->tagIndex )->value ) < 0 )
 | |
|                   {
 | |
|                      #ifndef S4SINGLE
 | |
|                         i4->fileLocked = oldFileLock ;
 | |
|                      #endif
 | |
|                      index4close( i4 ) ;
 | |
|                      return 0 ;
 | |
|                   }
 | |
|                   if ( tfile4setCodePage( tagFile, d4->codePage ) < 0 )
 | |
|                   {
 | |
|                      error4( c4, e4index, E91642 ) ;
 | |
|                      index4close( i4 ) ;
 | |
|                      return 0 ;
 | |
|                   }
 | |
| 
 | |
|                   l4add( &i4->tags, tagFile ) ;
 | |
|                } while ( tfile4skip( i4->tagIndex, 1L ) == 1L ) ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             #ifdef E4MISC
 | |
|                if ( fileName == 0 )
 | |
|                {
 | |
|                   index4close( i4 ) ;
 | |
|                   error4( c4, e4index, E81715 ) ;
 | |
|                }
 | |
|             #endif
 | |
|             tagFile = i4->tagIndex ;
 | |
|             l4add( &i4->tags, i4->tagIndex ) ;   /* if an .idx, add single tag */
 | |
|          }
 | |
|          #ifndef S4SINGLE
 | |
|             i4->fileLocked = oldFileLock ;
 | |
|          #endif
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4FOX
 | |
|          #ifdef E4MISC
 | |
|             for ( i4ptr = 0 ;; )
 | |
|             {
 | |
|                i4ptr = (INDEX4FILE *)l4next(&dfile->indexes, i4ptr) ;
 | |
|                if ( i4ptr == 0 )
 | |
|                   break ;
 | |
|                if ( !c4memcmp( i4ptr->file.name, buf, (size_t) strlen(buf) ) )
 | |
|                {
 | |
|                   error4( c4, e4parm, E81703 ) ;
 | |
|                   return 0 ;
 | |
|                }
 | |
|             }
 | |
|          #endif
 | |
| 
 | |
|          rc = file4open( &i4->file, c4, buf, 1 ) ;
 | |
|          if ( rc )
 | |
|          {
 | |
|             index->indexFile = 0 ;
 | |
|             mem4free( c4->index4fileMemory, i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          if ( file4readAll( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) < 0 )
 | |
|          {
 | |
|             file4close( &i4->file ) ;
 | |
|             index->indexFile = 0 ;
 | |
|             mem4free( c4->index4fileMemory, i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->header.blockChunks = x4reverseShort( (void *)&i4->header.blockChunks ) ;
 | |
|             i4->header.blockRw = x4reverseShort( (void *)&i4->header.blockRw ) ;
 | |
|             i4->header.slotSize = x4reverseShort( (void *)&i4->header.slotSize ) ;
 | |
|             i4->header.numTags = x4reverseShort( (void *)&i4->header.numTags ) ;
 | |
|             i4->header.eof = x4reverseLong( (void *)&i4->header.eof ) ;
 | |
|             i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
 | |
|          #endif
 | |
| 
 | |
|          l4add( &dfile->indexes, i4 ) ;
 | |
| 
 | |
|          /* Perform some checks */
 | |
|          if ( i4->header.blockRw != i4->header.blockChunks*512  ||
 | |
|               i4->header.blockChunks <= 0 ||
 | |
|               i4->header.blockChunks > 63 ||
 | |
|               i4->header.numTags < 0  || i4->header.numTags > 47 ||
 | |
|               i4->header.eof <= 0L )
 | |
|          {
 | |
|             index4close( i4 ) ;
 | |
|             error4describe( c4, e4index, E81716, buf, 0, 0 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          if ( file4readAll( &i4->file, 544L, tagInfo, sizeof(tagInfo)) < 0 )
 | |
|          {
 | |
|             index4close( i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          for ( iTag = 0; iTag < (int) i4->header.numTags; iTag++ )
 | |
|          {
 | |
|             tagFile = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
 | |
|             if ( tagFile == 0 )
 | |
|             {
 | |
|                index4close( i4 ) ;
 | |
|                #ifdef E4STACK
 | |
|                   error4stack( c4, e4memory, E91707 ) ;
 | |
|                #endif
 | |
|                return 0 ;
 | |
|             }
 | |
| 
 | |
|             #ifdef S4BYTE_SWAP
 | |
|                tagInfo[iTag].headerPos = x4reverseLong( (void *)&tagInfo[iTag].headerPos ) ;
 | |
|                tagInfo[iTag].x1000 = 0x1000 ;
 | |
|             #endif
 | |
| 
 | |
|             if ( tfile4init( tagFile, index, tagInfo + iTag ) < 0 )
 | |
|             {
 | |
|                index4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
| 
 | |
|             l4add( &i4->tags, tagFile ) ;
 | |
|          }
 | |
| 
 | |
|          i4->blockMemory = mem4create( c4, c4->memStartBlock, sizeof(B4BLOCK) + i4->header.blockRw -
 | |
|                            sizeof(B4KEY_DATA) - sizeof(short) - sizeof(char[6]), c4->memExpandBlock, 0 ) ;
 | |
|          if ( i4->blockMemory == 0 )
 | |
|          {
 | |
|             index4close( i4 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       #endif
 | |
| 
 | |
|       #ifndef S4OPTIMIZE_OFF
 | |
|          file4optimize( &i4->file, c4->optimize, OPT4INDEX ) ;
 | |
|       #endif
 | |
| 
 | |
|       i4->userCount++ ;
 | |
|       return i4 ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| TAG4 *S4FUNCTION i4tag( INDEX4 *i4, const char *tagName )
 | |
| {
 | |
|    char tagLookup[LEN4TAG_ALIAS+1] ;
 | |
|    TAG4 *tagOn ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E91709 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91709 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|       if ( tagName == 0 )
 | |
|       {
 | |
|          error4( i4->codeBase, e4parm_null, E91709 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    u4ncpy( tagLookup, tagName, sizeof( tagLookup ) - 1 ) ;
 | |
|    c4upper( tagLookup ) ;
 | |
| 
 | |
|    for( tagOn = 0 ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       if ( strcmp( tagOn->tagFile->alias, tagLookup ) == 0 )
 | |
|          return tagOn ;
 | |
|    }
 | |
| 
 | |
|    if ( i4->codeBase->errTagName )
 | |
|       error4describe( i4->codeBase, e4tagName, E91709, tagName, 0, 0 ) ;
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifndef S4CLIENT
 | |
| #ifndef S4OFF_WRITE
 | |
| int index4shrink( INDEX4FILE *i4, long blockNo )
 | |
| {
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91708 ) ;
 | |
|       if ( blockNo < 0 )
 | |
|          return error4( i4->codeBase, e4parm, E91708 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    #ifdef S4FOX
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
 | |
|       #endif
 | |
|       rc = file4write( &i4->file, blockNo, (char *)&i4->tagIndex->header.freeList,
 | |
|            sizeof(i4->tagIndex->header.freeList) ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( i4->codeBase, (short)rc, E91708 ) ;
 | |
|       i4->tagIndex->header.freeList = blockNo ;
 | |
|    #else
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
 | |
|       #endif
 | |
|       rc = file4write( &i4->file, blockNo*I4MULTIPLY + sizeof(S4LONG),
 | |
|            (char *)&i4->header.freeList, sizeof(i4->header.freeList) ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( i4->codeBase, rc, E91708 ) ;
 | |
|       i4->header.freeList = blockNo ;
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4OFF_WRITE */
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| /* Updates the header if the version has changed */
 | |
| int i4updateHeader( INDEX4 *i4 )
 | |
| {
 | |
|    return index4updateHeader( i4->indexFile ) ;
 | |
| }
 | |
| 
 | |
| int index4updateHeader( INDEX4FILE *i4 )
 | |
| {
 | |
|    #ifdef S4MDX
 | |
|       int rc ;
 | |
|       TAG4FILE *tagOn ;
 | |
|       #ifdef S4BYTE_SWAP
 | |
|          I4HEADER swap ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91710 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    #ifdef S4FOX
 | |
|       if ( i4->tagIndex == 0 )   /* index file not complete */
 | |
|          return 0 ;
 | |
| 
 | |
|       if ( i4->versionOld != i4->tagIndex->header.version )
 | |
|       {
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
 | |
|             i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
 | |
|             i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
 | |
|          #else
 | |
|             i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
 | |
|          #endif
 | |
| 
 | |
|          if ( file4write( &i4->file,0L, (char *)&i4->tagIndex->header, LEN4HEADER_WR ) < 0 )
 | |
|             return -1;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
 | |
|             i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
 | |
|             i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
 | |
|          #else
 | |
|             i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
 | |
|          #endif
 | |
|          i4->versionOld = i4->tagIndex->header.version ;
 | |
|       }
 | |
|    #else
 | |
|       if ( i4->changed )
 | |
|       {
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             memcpy( (void *)&swap, (void *)&i4->header, sizeof(I4HEADER) ) ;
 | |
| 
 | |
|             swap.blockChunks = x4reverseShort( (void *)&swap.blockChunks ) ;
 | |
|             swap.blockRw = x4reverseShort( (void *)&swap.blockRw ) ;
 | |
|             swap.slotSize = x4reverseShort( (void *)&swap.slotSize ) ;
 | |
|             swap.numTags = x4reverseShort( (void *)&swap.numTags ) ;
 | |
|             swap.eof = x4reverseLong( (void *)&swap.eof ) ;
 | |
|             swap.freeList = x4reverseLong( (void *)&swap.freeList ) ;
 | |
| 
 | |
|             rc = file4write( &i4->file, 0L, (char *)&swap, sizeof( I4HEADER ) ) ;
 | |
|             if ( rc < 0 )
 | |
|                return error4stack( i4->codeBase, rc, E91710 ) ;
 | |
|          #else
 | |
|             rc = file4write( &i4->file, 0L, (char *)&i4->header, sizeof( I4HEADER ) ) ;
 | |
|             if ( rc < 0 )
 | |
|                return error4stack( i4->codeBase, rc, E91710 ) ;
 | |
|          #endif
 | |
|          i4->changed = 0 ;
 | |
|          for( tagOn = 0 ;; )
 | |
|          {
 | |
|             tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
 | |
|             if ( tagOn == 0 )
 | |
|                break ;
 | |
|             if ( tagOn->changed == 1 )
 | |
|             {
 | |
|                tagOn->header.version++ ;
 | |
|                tagOn->changed = 0 ;
 | |
|                rc = file4write( &i4->file, tagOn->headerOffset + 20L, &tagOn->header.version, sizeof(char) ) ;
 | |
|                if ( rc < 0 )
 | |
|                   return error4stack( i4->codeBase, rc, E91710 ) ;
 | |
|                if ( tagOn->hadKeys != tagOn->hasKeys )
 | |
|                {
 | |
|                   /* just update the tag to record that it has keys (no other update yet) */
 | |
|                   rc = file4write( &i4->file, tagOn->headerOffset + 222 + sizeof( T4HEADER ), &tagOn->hasKeys, sizeof(char) ) ;
 | |
|                   if ( rc < 0 )
 | |
|                      return error4stack( i4->codeBase, rc, E91710 ) ;
 | |
|                   tagOn->hadKeys = tagOn->hasKeys ;
 | |
|                }
 | |
|             }
 | |
|          }
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif  /* S4OFF_WRITE */
 | |
| 
 | |
| int t4versionCheck( TAG4 *t4, const int doSeek, const int updateVersion )
 | |
| {
 | |
|    #ifndef S4OPTIMIZE_OFF
 | |
|       if ( t4->index->indexFile->file.doBuffer == 0 )
 | |
|          return i4versionCheck( t4->index, doSeek, updateVersion ) ;
 | |
|       else
 | |
|          return 0 ;
 | |
|    #else
 | |
|       return i4versionCheck( t4->index, doSeek, updateVersion ) ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int i4versionCheck( INDEX4 *i4, const int doSeek, const int updateVersion )
 | |
| {
 | |
|    #ifndef S4SINGLE
 | |
|       TAG4 *saveTag ;
 | |
|       TAG4FILE *tagOn ;
 | |
|       int needSeek ;
 | |
|       B4BLOCK *b4 ;
 | |
|       int rc ;
 | |
| 
 | |
|       #ifdef E4PARM_LOW
 | |
|          if ( i4 == 0 )
 | |
|             return error4( 0, e4parm_null, E91711 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( i4->codeBase ) < 0 )
 | |
|          return e4codeBase ;
 | |
| 
 | |
|       rc = index4versionCheck( i4->indexFile, updateVersion ) ;
 | |
|       if ( rc < 0 )
 | |
|          return error4stack( 0, (short)rc, E91711 ) ;
 | |
|       if ( rc == 0 )   /* version did not change */
 | |
|          return 0 ;
 | |
| 
 | |
|       needSeek = 0 ;
 | |
|       saveTag = d4tagSelected( i4->data ) ;
 | |
|       if ( saveTag != 0 )
 | |
|       {
 | |
|          /* remember the old position */
 | |
|          if ( doSeek )
 | |
|          {
 | |
|             b4 = (B4BLOCK *)saveTag->tagFile->blocks.lastNode ;
 | |
|             if ( b4 != 0 )
 | |
|             {
 | |
|                if ( tfile4eof( saveTag->tagFile ) )
 | |
|                   needSeek = 2 ;
 | |
|                else
 | |
|                   #ifdef S4FOX
 | |
|                      if ( b4leaf( b4 ) && b4numKeys( b4 ) != 0 )
 | |
|                   #else
 | |
|                      if ( b4leaf( b4 ) && b4numKeys( b4 ) != 0 && b4->keyOn < b4numKeys( b4 ) )
 | |
|                   #endif
 | |
|                      {
 | |
|                         #ifdef S4FOX
 | |
|                            memcpy( i4->codeBase->savedKey, (void *)(b4key( b4, b4->keyOn )), saveTag->tagFile->header.keyLen + sizeof(long) ) ;
 | |
|                         #else
 | |
|                            memcpy( i4->codeBase->savedKey, (void *)(b4key( b4, b4->keyOn )), saveTag->tagFile->header.keyLen + 2 * sizeof(S4LONG) ) ;
 | |
|                         #endif
 | |
|                         needSeek = 1 ;
 | |
|                      }
 | |
|             }
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       for ( tagOn = 0 ;; )
 | |
|       {
 | |
|          tagOn = (TAG4FILE *)l4next( &i4->indexFile->tags, tagOn ) ;
 | |
|          if ( tagOn == 0 )
 | |
|             break ;
 | |
|          if ( tfile4freeAll( tagOn ) < 0 )  /* Should be a memory operation only */
 | |
|             return error4( i4->codeBase, e4result, E91711 ) ;
 | |
|       }
 | |
| 
 | |
|       switch ( needSeek )
 | |
|       {
 | |
|          case 1:
 | |
|             tfile4go( saveTag->tagFile, ((B4KEY_DATA *)i4->codeBase->savedKey)->value, ((B4KEY_DATA *)i4->codeBase->savedKey)->num, 0 ) ;
 | |
|             break ;
 | |
|          case 2:
 | |
|             tfile4goEof( saveTag->tagFile ) ;
 | |
|             break ;
 | |
|          default:
 | |
|             break ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* Reads the header, checks the version to see if the blocks need to be freed. */
 | |
| /* returns 1 if version needs to be updated, else 0 */
 | |
| #ifdef P4ARGS_USED
 | |
|    #pragma argsused
 | |
| #endif
 | |
| int index4versionCheck( INDEX4FILE *i4, const int updateVersion )
 | |
| {
 | |
|    #ifdef S4SINGLE
 | |
|       return 0 ;
 | |
|    #else
 | |
|       #ifndef S4FOX
 | |
|          TAG4FILE *tagOn ;
 | |
|       #endif
 | |
|       int rc ;
 | |
| 
 | |
|       #ifdef E4PARM_LOW
 | |
|          if ( i4 == 0 )
 | |
|             return error4( 0, e4parm_null, E91712 ) ;
 | |
|       #endif
 | |
| 
 | |
|       if ( error4code( i4->codeBase ) < 0 )
 | |
|          return e4codeBase ;
 | |
| 
 | |
|       if ( index4lockTest( i4 ) )
 | |
|          return 0 ;
 | |
| 
 | |
|       #ifndef S4OPTIMIZE_OFF
 | |
|          /* make sure read from disk unless file locked, etc. */
 | |
|          if ( i4->file.doBuffer )  /* also makes sure 'opt' should exist */
 | |
|             i4->codeBase->opt.forceCurrent = 1 ;
 | |
|       #endif
 | |
| 
 | |
|       #ifdef S4FOX
 | |
|          rc = file4readAll( &i4->file, 0L, &i4->tagIndex->header, LEN4HEADER_WR ) ;
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->tagIndex->header.root = x4reverseLong( (void *)&i4->tagIndex->header.root ) ;
 | |
|             i4->tagIndex->header.freeList = x4reverseLong( (void *)&i4->tagIndex->header.freeList ) ;
 | |
|             i4->tagIndex->header.version = x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
 | |
|             i4->tagIndex->header.keyLen = x4reverseShort( (void *)&i4->tagIndex->header.keyLen ) ;
 | |
|          #endif
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             if ( i4->file.doBuffer )
 | |
|                i4->codeBase->opt.forceCurrent = 0 ;
 | |
|          #endif
 | |
|          if ( rc < 0 )
 | |
|             return error4stack( i4->codeBase, (short)rc, E91712 ) ;
 | |
|          i4->tagIndex->header.version = (unsigned long)x4reverseLong( (void *)&i4->tagIndex->header.version ) ;
 | |
|          if ( i4->tagIndex->header.version == i4->versionOld )
 | |
|             return 0 ;
 | |
| 
 | |
|          if ( updateVersion == 1 )
 | |
|             i4->versionOld = i4->tagIndex->header.version ;
 | |
|          else
 | |
|             i4->tagIndex->header.version = i4->versionOld ;
 | |
|          return 1 ;
 | |
|       #else
 | |
|          rc = file4readAll( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) ;
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             if ( i4->file.doBuffer )
 | |
|                i4->codeBase->opt.forceCurrent = 0 ;
 | |
|          #endif
 | |
|          if ( rc < 0 )
 | |
|             return error4stack( i4->codeBase, rc, E91712 ) ;
 | |
| 
 | |
|          #ifdef S4BYTE_SWAP
 | |
|             i4->header.blockChunks = x4reverseShort( (void *)&i4->header.blockChunks ) ;
 | |
|             i4->header.blockRw = x4reverseShort( (void *)&i4->header.blockRw ) ;
 | |
|             i4->header.slotSize = x4reverseShort( (void *)&i4->header.slotSize ) ;
 | |
|             i4->header.numTags = x4reverseShort( (void *)&i4->header.numTags ) ;
 | |
|             i4->header.eof = x4reverseLong( (void *)&i4->header.eof ) ;
 | |
|             i4->header.freeList = x4reverseLong( (void *)&i4->header.freeList ) ;
 | |
|          #endif
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             /* make sure read from disk unless file locked, etc. */
 | |
|             if ( i4->file.doBuffer )  /* also makes sure 'opt' should exist */
 | |
|               i4->codeBase->opt.forceCurrent = 1 ;
 | |
|          #endif
 | |
|          for( tagOn = 0 ;; )
 | |
|          {
 | |
|             tagOn = (TAG4FILE *)l4next( &i4->tags, tagOn ) ;
 | |
|             if ( tagOn == 0 )
 | |
|                break ;
 | |
|             rc = file4readAll( &i4->file, tagOn->headerOffset + 20L, &tagOn->header.version, sizeof(char) ) ;
 | |
|             if ( rc < 0 )
 | |
|             {
 | |
|                #ifndef S4OPTIMIZE_OFF
 | |
|                   if ( i4->file.doBuffer )
 | |
|                      i4->codeBase->opt.forceCurrent = 0 ;
 | |
|                #endif
 | |
|                return error4stack( i4->codeBase, rc, E91712 ) ;
 | |
|             }
 | |
|             rc = file4readAll( &i4->file, tagOn->headerOffset + 222 + sizeof( T4HEADER ), &tagOn->hasKeys, sizeof(char) ) ;
 | |
|             if ( rc < 0 )
 | |
|             {
 | |
|                #ifndef S4OPTIMIZE_OFF
 | |
|                   if ( i4->file.doBuffer )
 | |
|                      i4->codeBase->opt.forceCurrent = 0 ;
 | |
|                #endif
 | |
|                return error4stack( i4->codeBase, rc, E91712 ) ;
 | |
|             }
 | |
|             tagOn->hadKeys = tagOn->hasKeys ;
 | |
|          }
 | |
| 
 | |
|          #ifndef S4OPTIMIZE_OFF
 | |
|             if ( i4->file.doBuffer )
 | |
|                i4->codeBase->opt.forceCurrent = 0 ;
 | |
|          #endif
 | |
|          return 1 ;
 | |
|       #endif
 | |
|    #endif
 | |
| }
 | |
| #endif /* S4CLIENT */
 | |
| #endif /* S4CLIPPER */
 | |
| 
 | |
| 
 | |
| #ifdef S4CLIPPER
 | |
| 
 | |
| /* This function closes all the tags corresponding with the index */
 | |
| int S4FUNCTION i4close( INDEX4 *i4 )
 | |
| {
 | |
|    int finalRc ;
 | |
|    CODE4 *c4 ;
 | |
|    TAG4 *tagOn ;
 | |
|    int oldOpenErr, rc ;
 | |
|    char buf[258] ;
 | |
|    #ifndef S4SINGLE
 | |
|       int saveAttempts ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E91701 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91701 ) ;
 | |
|    #endif
 | |
| 
 | |
|    c4 = i4->codeBase ;
 | |
| 
 | |
|    finalRc = error4code( c4 ) ;
 | |
|    #ifndef S4OFF_WRITE
 | |
|       if ( i4->data )
 | |
|          if ( d4update( i4->data ) < 0 )
 | |
|             finalRc = error4set( c4, 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       saveAttempts = c4->lockAttempts ;
 | |
|       c4->lockAttempts = WAIT4EVER ;
 | |
|       if ( i4unlock(i4) < 0 )
 | |
|          finalRc = error4set( c4, 0 ) ;
 | |
|    #endif
 | |
| 
 | |
|    for( ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4pop( &i4->tags ) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       if ( i4->data->tagSelected == tagOn )   /* can't have a non-existant tag selected */
 | |
|          i4->data->tagSelected = 0 ;
 | |
|       t4close( tagOn ) ;
 | |
|       tagOn = 0 ;
 | |
|    }
 | |
| 
 | |
|    if ( c4->doRemove == 1 )
 | |
|    {
 | |
|       oldOpenErr = c4->errOpen ;
 | |
|       c4->errOpen = 0 ;
 | |
|       u4ncpy( buf, i4->accessName, sizeof( buf ) - 1 ) ;
 | |
|       u4nameExt( buf, sizeof( buf ), "CGP", 1 ) ;
 | |
|       rc = file4open( &i4->file, c4, buf, 0 ) ;
 | |
|       if ( rc == 0 )
 | |
|       {
 | |
|          i4->file.isTemp = 1 ;
 | |
|          file4close( &i4->file ) ;
 | |
|       }
 | |
|       c4->errOpen = oldOpenErr ;
 | |
|    }
 | |
| 
 | |
|    if ( i4->data )
 | |
|       l4remove( &i4->data->indexes, i4 ) ;
 | |
| 
 | |
|    mem4free( c4->indexMemory, i4 ) ;
 | |
|    i4 = 0 ;
 | |
|    #ifndef S4SINGLE
 | |
|       c4->lockAttempts = saveAttempts ;
 | |
|    #endif
 | |
|    error4set( c4, finalRc ) ;
 | |
|    return  finalRc ;
 | |
| }
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| /* This function flushes all the tags corresponding with the index */
 | |
| int i4flush( INDEX4 *i4 )
 | |
| {
 | |
|    TAG4 *tagOn ;
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91713 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       if ( i4->data->dataFile->indexLocked == 1 )
 | |
|    #endif
 | |
|       for ( tagOn = 0 ;; )
 | |
|       {
 | |
|          tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
 | |
|          if ( tagOn == 0 )
 | |
|             break ;
 | |
|          rc = tfile4flush( tagOn->tagFile ) ;
 | |
|          if ( rc < 0 )
 | |
|             return error4stack( i4->codeBase, rc, E91713 ) ;
 | |
|          tagOn->tagFile->header.root = -1L ;
 | |
|       }
 | |
|       return 0 ;
 | |
| }
 | |
| 
 | |
| int i4update( INDEX4 *i4 )
 | |
| {
 | |
|    TAG4 *tagOn ;
 | |
|    int rc ;
 | |
| 
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91705 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( i4->codeBase ) < 0 )
 | |
|       return e4codeBase ;
 | |
| 
 | |
|    #ifndef S4SINGLE
 | |
|       if ( i4->data->dataFile->indexLocked == 1 )
 | |
|    #endif
 | |
|       for ( tagOn = 0 ;; )
 | |
|       {
 | |
|          tagOn = (TAG4 *)l4next( &i4->tags, tagOn ) ;
 | |
|          if ( tagOn == 0 )
 | |
|             break ;
 | |
|          rc = tfile4update( tagOn->tagFile ) ;
 | |
|          if ( rc < 0 )
 | |
|             return error4stack( i4->codeBase, rc, E91705 ) ;
 | |
|          tagOn->tagFile->header.root = -1L ;
 | |
|       }
 | |
|       return 0 ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| INDEX4 *S4FUNCTION i4open( DATA4 *d4, const char *fileName )
 | |
| {
 | |
|    INDEX4 *i4 ;
 | |
|    CODE4 *c4 ;
 | |
|    TAG4 *tag ;
 | |
|    int len, rc, i ;
 | |
|    char buf[258], tagBuf[258], ext[3] ;
 | |
|    int numFiles ;
 | |
|    FILE4SEQ_READ seqread ;
 | |
|    char buffer[1024], tNames[258], firstByte ;
 | |
|    int pos, iPos, saveLen, tempLen ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( d4, 2, E91706 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( d4 == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91706 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    c4 = d4->codeBase ;
 | |
|    if ( error4code( c4 ) < 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       if ( fileName == 0 )
 | |
|          u4ncpy( (char *)buf, d4->dataFile->accessName, sizeof( buf ) - 1 ) ;
 | |
|       else
 | |
|       {
 | |
|          if ( strlen( fileName ) > sizeof( buf ) - 1 )
 | |
|          {
 | |
|             error4( c4, e4name, E91707 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|          strcpy( (char*)buf, fileName ) ;
 | |
|       }
 | |
|       c4upper( (char*)buf ) ;
 | |
|       i4file = index4open( d4, (char S4PTR*)buf, 0 ) ;
 | |
|       if ( error4code( c4 ) < 0 )
 | |
|          return 0 ;
 | |
|       i4 = d4index( d4, (char S4PTR*)buf ) ;
 | |
|       if ( i4file == 0 )
 | |
|       {
 | |
|          if ( i4 == 0 )
 | |
|             return 0 ;
 | |
|          #ifdef E4ANALZE
 | |
|             if ( i4->indexFile == 0 )
 | |
|             {
 | |
|                error4( c4, e4info, E91706 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          #endif
 | |
|          i4file = i4->indexFile ;
 | |
|          i4file->clientId = data4clientId( d4 ) ;
 | |
|          i4file->serverId = data4serverId( d4 ) ;
 | |
|       }
 | |
|       else  /* indexfile already exists so set up another index4 structure */
 | |
|       {
 | |
|          i4 = i4setup2( c4, i4file, d4, (char S4PTR*)buf ) ;
 | |
|          if ( i4 == 0 )
 | |
|          {
 | |
|             index4close( i4file ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       }
 | |
|       #ifdef E4ANALZE
 | |
|          else
 | |
|          {
 | |
|             if ( i4->indexFile != i4file )
 | |
|             {
 | |
|                error4( c4, e4info, E91706 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|       #endif
 | |
|       i4->codeBase = c4 ;
 | |
|    #else
 | |
|       if ( fileName == 0 )
 | |
|       {
 | |
|          u4ncpy( buf, d4->dataFile->file.name, sizeof( buf ) - 1 ) ;
 | |
|          u4nameExt( buf, sizeof( buf ), "CGP", 1 ) ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          u4ncpy( buf, fileName, sizeof( buf ) - 1 ) ;
 | |
|          c4upper( buf ) ;
 | |
|          rc = u4nameRetExt( ext, 3, buf ) ;
 | |
|          if ( rc )  /* extension provided */
 | |
|          {
 | |
|             if ( rc == 3 )
 | |
|                if ( c4memcmp( ext, "NTX", 3 ) == 0 )
 | |
|                {
 | |
|                   tag = t4open( d4, (INDEX4 *)0, fileName ) ;
 | |
|                   if ( tag == 0 )
 | |
|                      return 0 ;
 | |
|                   #ifndef S4OFF_TRAN
 | |
|                      tag->index->isValid = 1 ;
 | |
|                   #endif
 | |
|                   return tag->index ;
 | |
|                }
 | |
|          }
 | |
|          else
 | |
|             u4nameExt( buf, sizeof(buf), "CGP", 0 ) ;
 | |
|       }
 | |
| 
 | |
|       if ( c4->indexMemory == 0 )
 | |
|       {
 | |
|          c4->indexMemory = mem4create( c4, c4->memStartIndex, sizeof( INDEX4 ), c4->memExpandIndex, 0 ) ;
 | |
|          if ( c4->indexMemory == 0 )
 | |
|             return 0 ;
 | |
|       }
 | |
| 
 | |
|       if ( c4->tagMemory == 0 )
 | |
|       {
 | |
|          c4->tagMemory = mem4create( c4, c4->memStartTag, sizeof( TAG4 ), c4->memExpandTag, 0 ) ;
 | |
|          if ( c4->tagMemory == 0 )
 | |
|             return 0 ;
 | |
|       }
 | |
| 
 | |
|       if ( c4->tagFileMemory == 0 )
 | |
|       {
 | |
|          c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof( TAG4FILE ), c4->memExpandTagFile, 0 ) ;
 | |
|          if ( c4->tagFileMemory == 0 )
 | |
|             return 0 ;
 | |
|       }
 | |
| 
 | |
|       i4 = (INDEX4 *)mem4alloc( c4->indexMemory ) ;
 | |
|       if ( i4 == 0 )
 | |
|          return 0 ;
 | |
| 
 | |
|       i4->codeBase = c4 ;
 | |
|       i4->data = d4 ;
 | |
|       l4add( &d4->indexes, i4 ) ;
 | |
|       if ( fileName == 0 )
 | |
|          u4namePiece( i4->accessName, sizeof( i4->accessName ), buf, 0, 0 ) ;
 | |
|       else
 | |
|          strcpy( i4->accessName, fileName ) ;
 | |
|       c4upper( i4->accessName ) ;
 | |
| 
 | |
|       if ( file4open( &i4->file, c4, buf, 1 ) )
 | |
|       {
 | |
|          i4close( i4 ) ;
 | |
|          if ( c4->errOpen )
 | |
|             error4( c4, e4open, E81708 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       file4seqReadInit( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
 | |
| 
 | |
|       pos = 0L ;
 | |
|       rc = file4seqReadAll( &seqread, &firstByte, sizeof( firstByte ) ) ;
 | |
|       if ( rc )
 | |
|       {
 | |
|          i4close( i4 ) ;
 | |
|          if ( c4->errOpen )
 | |
|             error4( c4, e4info, E81709 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
| 
 | |
|       if ( firstByte < 65 )   /* old format - potential problem if >= 65 files in an old format file. */
 | |
|       {
 | |
|          numFiles = firstByte ;
 | |
|          if ( file4seqReadAll( &seqread, &firstByte, sizeof( firstByte ) ) )
 | |
|          {
 | |
|             i4close( i4 ) ;
 | |
|             if ( c4->errOpen )
 | |
|                error4( c4, e4info, E81709 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
| 
 | |
|          for ( i = 0 ; i < numFiles ; i++ )
 | |
|          {
 | |
|             if ( file4seqReadAll( &seqread, &len, sizeof( len ) ) )
 | |
|             {
 | |
|                file4close( &i4->file ) ;
 | |
|                i4close( i4 ) ;
 | |
|                if ( c4->errOpen )
 | |
|                   error4( c4, e4info, E81709 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|             pos += sizeof( len ) ;
 | |
|             rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
 | |
|             tagBuf[rc+len] = '\0' ;
 | |
|             if ( sizeof( tagBuf ) > rc + len ) /* make sure room to read */
 | |
|                rc = file4seqReadAll( &seqread, tagBuf+rc, len ) ;
 | |
|             else
 | |
|                rc = -1 ;
 | |
| 
 | |
|             if ( rc )
 | |
|             {
 | |
|                if ( c4->errOpen )
 | |
|                   error4( c4, e4info, E81709 ) ;
 | |
|                file4close( &i4->file ) ;
 | |
|                i4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
| 
 | |
|             pos += len ;
 | |
|             if  ( t4open( d4, i4, tagBuf ) == 0 )
 | |
|             {
 | |
|                file4close( &i4->file ) ;
 | |
|                i4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
| 
 | |
|          file4close( &i4->file ) ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          file4seqReadInit( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
 | |
|          saveLen = 0 ;
 | |
| 
 | |
|          for( len = sizeof( tNames ) ; len == sizeof( tNames ) ; )
 | |
|          {
 | |
|             len = file4seqRead( &seqread, tNames, sizeof( tNames )) ;
 | |
|             if ( len < sizeof( tNames ) ) /* case where all read in now - free up this file handle for use */
 | |
|             {
 | |
|                if ( file4close ( &i4->file ) )
 | |
|                {
 | |
|                   i4close( i4 ) ;
 | |
|                   if ( c4->errOpen )
 | |
|                      error4( c4, e4info, E81710 ) ;
 | |
|                   return 0 ;
 | |
|                }
 | |
|                if ( len == 0 )
 | |
|                   break ;
 | |
|             }
 | |
|             for( iPos = 0, pos = 0 ; pos < len ; )
 | |
|             {
 | |
|                switch( tNames[pos] )
 | |
|                {
 | |
|                   /* cases where the values are ignored, or found name */
 | |
|                   case ' ':
 | |
|                   case '\r':
 | |
|                   case '\n':
 | |
|                   case '\t':
 | |
|                   case '\x1A':
 | |
|                      if ( iPos < pos )  /* try to open the file */
 | |
|                      {
 | |
|                         tempLen = pos - iPos ;
 | |
|                         if ( saveLen == 0 )
 | |
|                         {
 | |
|                            rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
 | |
|                            tagBuf[rc + tempLen] = '\0' ;
 | |
|                         }
 | |
|                         else
 | |
|                            rc = saveLen ;
 | |
|                         memcpy( tagBuf + rc, &tNames[iPos], tempLen ) ;
 | |
| 
 | |
|                         if  ( t4open( d4, i4, tagBuf ) == 0 )
 | |
|                         {
 | |
|                            file4close( &i4->file ) ;
 | |
|                            i4close( i4 ) ;
 | |
|                            return 0 ;
 | |
|                         }
 | |
|                      }
 | |
|                      iPos = ++pos ;
 | |
|                      break ;
 | |
| 
 | |
|                   /* case where a name is attempted to be read in */
 | |
|                   default:
 | |
|                      pos++ ;
 | |
|                }
 | |
|             }
 | |
|             tempLen = pos - iPos ;
 | |
|             rc = u4namePath( tagBuf, sizeof( tagBuf ), buf ) ;
 | |
|             tagBuf[rc+tempLen] = '\0' ;
 | |
|             memcpy( tagBuf + rc, &tNames[iPos], tempLen ) ;
 | |
|             saveLen = rc + tempLen ;
 | |
|          }
 | |
| 
 | |
|          if ( ( saveLen - rc ) > 0 )  /* try to open the file */
 | |
|          {
 | |
|             if  ( t4open( d4, i4, tagBuf ) == 0 )
 | |
|             {
 | |
|                file4close( &i4->file ) ;
 | |
|                i4close( i4 ) ;
 | |
|                return 0 ;
 | |
|             }
 | |
|          }
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifndef S4OFF_TRAN
 | |
|       i4->isValid = 1 ;
 | |
|    #endif
 | |
| 
 | |
|    return i4 ;
 | |
| }
 | |
| 
 | |
| TAG4 *S4FUNCTION i4tag( INDEX4 *i4, const char *tagName )
 | |
| {
 | |
|    char tagLookup[LEN4TAG_ALIAS+1] ;
 | |
|    TAG4 *tagOn ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( i4, 0, E91709 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( i4 == 0 || tagName == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E91709 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    u4ncpy( tagLookup, tagName, sizeof( tagLookup ) - 1 ) ;
 | |
|    c4upper( tagLookup ) ;
 | |
| 
 | |
|    for( tagOn = 0 ;; )
 | |
|    {
 | |
|       tagOn = (TAG4 *)l4next( &i4->tags, tagOn) ;
 | |
|       if ( tagOn == 0 )
 | |
|          break ;
 | |
|       if ( strcmp( tagOn->tagFile->alias, tagLookup) == 0 )
 | |
|          return tagOn ;
 | |
|    }
 | |
| 
 | |
|    if ( i4->codeBase->errTagName )
 | |
|       error4describe( i4->codeBase, e4tagName, E91709, tagName, 0, 0 ) ;
 | |
|    return 0 ;
 | |
| }
 | |
| #endif   /*  ifdef S4CLIPPER  */
 | |
| 
 | |
| #ifndef S4CLIPPER
 | |
| #ifndef S4CLIENT
 | |
| int index4isProduction( INDEX4FILE *i4 )
 | |
| {
 | |
|    #ifdef S4FOX
 | |
|       int l1, l2, count ;
 | |
|    #endif
 | |
|    #ifdef E4PARM_LOW
 | |
|       if ( i4 == 0 )
 | |
|          return error4( 0, e4parm_null, E91714 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4MDX
 | |
|       #ifdef S4SERVER
 | |
|          return i4->header.isProduction ;
 | |
|       #else
 | |
|          return i4->dataFile->openMdx ;
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4FOX
 | |
|       #ifdef S4SERVER
 | |
|          if ( i4->dataFile->hasMdxMemo )
 | |
|       #else
 | |
|          if ( i4->dataFile->openMdx )
 | |
|       #endif
 | |
|       {
 | |
|          if ( i4->file.name == 0 )   /* most likely a failure during open/create now closing */
 | |
|             return 0 ;
 | |
|          l1 = strlen( i4->file.name ) ;
 | |
|          if ( l1 == 0 )
 | |
|             return 0 ;
 | |
|          for ( count = l1 - 1 ;; count-- )
 | |
|          {
 | |
|             if ( count <= 0 )
 | |
|                break ;
 | |
|             if ( i4->file.name[count] == '.' )
 | |
|             {
 | |
|                l1 = count ;
 | |
|                break ;
 | |
|             }
 | |
|          }
 | |
|          l2 = strlen( i4->dataFile->file.name ) ;
 | |
|          if ( l2 == 0 )
 | |
|             return 0 ;
 | |
|          for ( count = l2 - 1 ;; count-- )
 | |
|          {
 | |
|             if ( count <= 0 )
 | |
|                break ;
 | |
|             if ( i4->dataFile->file.name[count] == '.' )
 | |
|             {
 | |
|                l2 = count ;
 | |
|                break ;
 | |
|             }
 | |
|          }
 | |
|          if ( l1 == l2 )
 | |
|             return( c4memcmp( i4->file.name, i4->dataFile->file.name, (unsigned)l1 ) ? 0 : 1 ) ;
 | |
|       }
 | |
|       return 0 ;
 | |
|    #endif
 | |
| }
 | |
| #endif /* S4CLIENT */
 | |
| #endif /* S4CLIPPER */
 | |
| #endif /* S4INDEX_OFF */
 | |
| 
 | |
| #ifdef S4VB_DOS
 | |
| INDEX4 * i4open_v( DATA4 *d4, char *name )
 | |
| {
 | |
|    char *namePtr ;
 | |
| 
 | |
|    namePtr = c4str(name) ;
 | |
| 
 | |
|    if (namePtr[0] == '\0' )
 | |
|       return i4open( d4, 0 ) ;
 | |
| 
 | |
|    return i4open( d4, namePtr ) ;
 | |
| }
 | |
| 
 | |
| TAG4 *i4tag_v( INDEX4 *ind, char *tagName )
 | |
| {
 | |
|  return i4tag( ind, c4str(tagName) ) ;
 | |
| }
 | |
| 
 | |
| #endif  /* S4VB_DOS */
 |