which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@976 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1381 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1381 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* i4index.c   (c)Copyright Sequiter Software Inc., 1990-1994.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifndef S4UNIX
 | 
						|
#ifdef __TURBOC__
 | 
						|
#pragma hdrstop
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4INDEX_OFF
 | 
						|
#ifndef N4OTHER
 | 
						|
 | 
						|
int S4FUNCTION i4close( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  int final_rc, save_attempts ;
 | 
						|
  CODE4 *c4 ;
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( i4, 0, E4_I4CLOSE ) )
 | 
						|
    return -1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4 == 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  c4 = i4->code_base ;
 | 
						|
 | 
						|
  final_rc = c4->error_code ;
 | 
						|
#ifndef S4SINGLE
 | 
						|
  save_attempts = c4->lock_attempts ;
 | 
						|
  c4->lock_attempts = -1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
  if ( i4->data )
 | 
						|
    if ( d4update( i4->data ) < 0 )
 | 
						|
      final_rc = e4set( c4, 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4update( i4 ) < 0 )
 | 
						|
    final_rc = e4set( c4, 0 ) ;
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( i4unlock( i4 ) < 0 )
 | 
						|
    final_rc = e4set( c4, 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  if ( i4->tag_index )
 | 
						|
    if ( i4->tag_index->header.type_code >= 64 )  /* compound index */
 | 
						|
#endif
 | 
						|
 | 
						|
      for( ;; )
 | 
						|
      {
 | 
						|
        tag_on = (TAG4 *)l4pop( &i4->tags ) ;
 | 
						|
        if ( tag_on == 0 )
 | 
						|
          break ;
 | 
						|
        if ( t4free_all( tag_on ) < 0 )
 | 
						|
        {
 | 
						|
          final_rc = e4set( c4, 0 ) ;
 | 
						|
          break ;
 | 
						|
        }
 | 
						|
        expr4free( tag_on->expr ) ;
 | 
						|
        expr4free( tag_on->filter ) ;
 | 
						|
        mem4free( c4->tag_memory, tag_on ) ;
 | 
						|
      }
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  if ( i4->tag_index != 0 )
 | 
						|
  {
 | 
						|
    if ( t4free_all( i4->tag_index ) < 0 )
 | 
						|
      final_rc = e4set( c4, 0 ) ;
 | 
						|
    else
 | 
						|
    {
 | 
						|
      expr4free( i4->tag_index->expr ) ;
 | 
						|
      expr4free( i4->tag_index->filter ) ;
 | 
						|
      mem4free( c4->tag_memory, i4->tag_index ) ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  mem4release( i4->block_memory ) ;
 | 
						|
 | 
						|
  if ( file4open_test( &i4->file ) )
 | 
						|
  {
 | 
						|
    if ( i4->data )
 | 
						|
      l4remove( &i4->data->indexes, i4 ) ;
 | 
						|
    if ( file4close( &i4->file ) < 0 )
 | 
						|
      final_rc = e4set( c4, 0 ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  mem4free( c4->index_memory, i4 ) ;
 | 
						|
#ifndef S4SINGLE
 | 
						|
  c4->lock_attempts = save_attempts ;
 | 
						|
#endif
 | 
						|
  e4set( c4, final_rc ) ;
 | 
						|
  return final_rc ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
long S4FUNCTION i4extend( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  long old_eof ;
 | 
						|
  unsigned len ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifndef S4FOX
 | 
						|
  old_eof = i4->header.free_list ;
 | 
						|
 | 
						|
  if( i4->header.free_list == 0L )  /* case where no free list */
 | 
						|
  {
 | 
						|
    old_eof = i4->header.eof ;
 | 
						|
    i4->header.eof = i4->header.eof + i4->header.block_rw/I4MULTIPLY ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    len = file4read( &i4->file, i4->header.free_list*I4MULTIPLY + sizeof(S4LONG),
 | 
						|
                    (char *)&i4->header.free_list, sizeof(i4->header.free_list)) ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    i4->header.free_list = x4reverse_long( (void *)&i4->header.free_list ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( i4->code_base->error_code < 0 )  return -1 ;
 | 
						|
 | 
						|
    switch( len )
 | 
						|
    {
 | 
						|
    case 0:
 | 
						|
#ifdef S4DEBUG
 | 
						|
      e4severe( e4info, E4_I4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
      /* else fix up */
 | 
						|
      i4->header.free_list = 0L ;
 | 
						|
      old_eof = i4->header.eof ;
 | 
						|
      i4->header.eof = i4->header.eof + i4->header.block_rw/I4MULTIPLY ;
 | 
						|
      break ;
 | 
						|
 | 
						|
    case sizeof(i4->header.free_list):
 | 
						|
      break ;
 | 
						|
 | 
						|
    default:
 | 
						|
      return file4read_error( &i4->file ) ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4->tag_index->header.version == i4->version_old )
 | 
						|
    e4severe( e4info, E4_I4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  old_eof = i4->tag_index->header.free_list ;
 | 
						|
 | 
						|
  if( old_eof == 0L )  /* case where no free list */
 | 
						|
  {
 | 
						|
    old_eof = i4->eof ;
 | 
						|
    i4->eof += B4BLOCK_SIZE ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    len = file4read( &i4->file, i4->tag_index->header.free_list*I4MULTIPLY,
 | 
						|
                    (char *)&i4->tag_index->header.free_list, sizeof(i4->tag_index->header.free_list)) ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    i4->tag_index->header.free_list = x4reverse_long( (void *)&i4->tag_index->header.free_list ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( i4->code_base->error_code < 0 )  return -1 ;
 | 
						|
 | 
						|
    switch( len )
 | 
						|
    {
 | 
						|
    case 0:
 | 
						|
#ifdef S4DEBUG
 | 
						|
      e4severe( e4info, E4_I4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
      /* else fix up */
 | 
						|
      i4->tag_index->header.free_list = 0L ;
 | 
						|
      old_eof = i4->eof ;
 | 
						|
      i4->eof += B4BLOCK_SIZE ;
 | 
						|
      break ;
 | 
						|
 | 
						|
    case sizeof(i4->tag_index->header.free_list):
 | 
						|
      break ;
 | 
						|
 | 
						|
    default:
 | 
						|
      return file4read_error( &i4->file ) ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  return old_eof ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION i4flush( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4FLUSH ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = i4update( i4 ) ;
 | 
						|
  if ( file4flush( &i4->file ) < 0 )
 | 
						|
    rc = -1 ;
 | 
						|
 | 
						|
  return rc ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION i4update( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4UPDATE ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( i4lock_test( i4 ) )
 | 
						|
  {
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( i4update_header( i4 ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
#ifdef S4FOX
 | 
						|
    if ( t4update(i4->tag_index) < 0 )
 | 
						|
      return -1 ;
 | 
						|
    if ( i4->tag_index->header.type_code >= 64 )  /* compound index */
 | 
						|
#endif
 | 
						|
 | 
						|
      for ( tag_on = 0 ;; )
 | 
						|
      {
 | 
						|
        tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
        if ( tag_on == 0 )
 | 
						|
          break ;
 | 
						|
        if ( t4update( tag_on ) < 0 )
 | 
						|
          return -1 ;
 | 
						|
        tag_on->header.root = -1L ;
 | 
						|
      }
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
INDEX4 *S4FUNCTION i4open( DATA4 *d4, char *file_name )
 | 
						|
{
 | 
						|
  INDEX4 *i4 ;
 | 
						|
  CODE4  *c4 ;
 | 
						|
  char   buf[258] ;
 | 
						|
  int    rc ;
 | 
						|
  TAG4 *tag_ptr ;
 | 
						|
#ifdef S4FOX
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
  int old_file_lock ;
 | 
						|
#else
 | 
						|
  T4DESC tag_info[47] ;
 | 
						|
  int i_tag ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  T4DESC swap_tag ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  INDEX4 *i4_ptr ;
 | 
						|
  if ( d4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4OPEN ) ;
 | 
						|
 | 
						|
  if ( file_name )
 | 
						|
    u4name_piece( buf, sizeof( buf ), file_name, 0, 0 ) ;
 | 
						|
  else
 | 
						|
    u4name_piece( buf, sizeof( buf ), d4->file.name, 0, 0 ) ;
 | 
						|
  if ( d4index( d4, buf ) )
 | 
						|
  {
 | 
						|
    e4( d4->code_base, e4info, E4_INFO_IAO ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( d4, 2, E4_I4OPEN ) )
 | 
						|
    return 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  c4 = d4->code_base ;
 | 
						|
  if ( c4->error_code < 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  if ( c4->index_memory == 0 )
 | 
						|
    c4->index_memory = mem4create( c4, c4->mem_start_index, sizeof(INDEX4),
 | 
						|
                                  c4->mem_expand_index, 0 ) ;
 | 
						|
 | 
						|
  if ( c4->index_memory == 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  if ( c4->tag_memory == 0 )
 | 
						|
  {
 | 
						|
    c4->tag_memory = mem4create( c4, c4->mem_start_tag, sizeof(TAG4),
 | 
						|
                                c4->mem_expand_tag, 0 ) ;
 | 
						|
    if ( c4->tag_memory == 0 )
 | 
						|
      return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  i4 = (INDEX4 *)mem4alloc( c4->index_memory ) ;
 | 
						|
  if ( i4 == 0 )
 | 
						|
  {
 | 
						|
    e4( c4, e4memory, 0 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  i4->data = d4 ;
 | 
						|
  i4->code_base = c4 ;
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  if ( file_name == 0 )
 | 
						|
  {
 | 
						|
    u4ncpy( buf, d4->file.name, sizeof(buf) ) ;
 | 
						|
#ifdef S4UNIX
 | 
						|
    u4name_ext( buf, sizeof(buf), "cdx", 1 ) ;
 | 
						|
#else
 | 
						|
    u4name_ext( buf, sizeof(buf), "CDX", 1 ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    u4ncpy( buf, file_name, sizeof(buf) ) ;
 | 
						|
#ifdef S4UNIX
 | 
						|
    u4name_ext( buf, sizeof(buf), "cdx", 0 ) ;
 | 
						|
#else
 | 
						|
    u4name_ext( buf, sizeof(buf), "CDX", 0 ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  for ( i4_ptr = 0 ;; )
 | 
						|
  {
 | 
						|
    i4_ptr = (INDEX4 *)l4next( &d4->indexes, i4_ptr ) ;
 | 
						|
    if ( i4_ptr == 0 )
 | 
						|
      break ;
 | 
						|
    if ( !memcmp(i4_ptr->file.name, buf, (size_t)strlen( buf ) ) )
 | 
						|
      e4severe( e4parm, E4_PARM_IND ) ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = file4open( &i4->file, c4, buf, 1 ) ;
 | 
						|
  if ( rc )
 | 
						|
    return 0 ;
 | 
						|
  l4add( &d4->indexes, i4 ) ;
 | 
						|
 | 
						|
  i4->eof = file4len( &i4->file ) ;
 | 
						|
 | 
						|
  i4->tag_index = (TAG4 *)mem4alloc( c4->tag_memory ) ;
 | 
						|
  if ( i4->tag_index == 0 )
 | 
						|
  {
 | 
						|
    file4close( &i4->file ) ;
 | 
						|
    e4( c4, e4memory, 0 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( file_name == 0 )
 | 
						|
  {
 | 
						|
    if ( t4init( i4->tag_index, i4, 0L, "") < 0 )
 | 
						|
    {
 | 
						|
      i4close( i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    u4name_piece( buf, 258, file_name, 0, 0 ) ;  /* get the tag_name based on the file_name */
 | 
						|
    if ( t4init( i4->tag_index, i4, 0L, buf) < 0 )
 | 
						|
    {
 | 
						|
      i4close( i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* Perform some checks */
 | 
						|
  if ( i4->tag_index->header.root <= 0L ||
 | 
						|
      i4->tag_index->header.type_code < 32 )
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
    e4describe( c4, e4index, buf, "i4open()", "Root <= 0L or type_code < 32" ) ;
 | 
						|
#endif
 | 
						|
    i4close( i4 ) ;
 | 
						|
    e4( c4, e4index, buf ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  i4->tag_index->header.version = x4reverse_long( (void *)&i4->tag_index->header.version ) ;
 | 
						|
  i4->version_old = i4->tag_index->header.version ;
 | 
						|
  i4->block_memory = mem4create( c4, c4->mem_start_block,
 | 
						|
                                sizeof(B4BLOCK) + B4BLOCK_SIZE - sizeof(B4STD_HEADER) - sizeof(B4NODE_HEADER),
 | 
						|
                                c4->mem_expand_block, 0 ) ;
 | 
						|
  if ( i4->block_memory == 0 )
 | 
						|
  {
 | 
						|
    i4close(i4) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  /* do an initial block allocation to make sure minimal is allocated while optimization is suspended */
 | 
						|
  b4 = (B4BLOCK *)mem4alloc2( i4->block_memory, c4 ) ;
 | 
						|
  if ( b4 == 0 )
 | 
						|
  {
 | 
						|
    i4close( i4 ) ;
 | 
						|
    e4( c4, e4memory, E4_I4OPEN ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    mem4free( i4->block_memory, b4 ) ;
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  /* disable locking */
 | 
						|
  old_file_lock = i4->file_locked ;
 | 
						|
  i4->file_locked = 1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  t4top( i4->tag_index ) ;
 | 
						|
 | 
						|
  /* if we have a compound index, then load the tags, otherwise this is the only tag */
 | 
						|
  if ( i4->tag_index->header.type_code >= 64 )
 | 
						|
  {
 | 
						|
    if ( t4block( i4->tag_index )->header.n_keys )
 | 
						|
      do
 | 
						|
      {
 | 
						|
        tag_ptr = (TAG4 *)mem4alloc( c4->tag_memory ) ;
 | 
						|
        if ( tag_ptr == 0 )
 | 
						|
        {
 | 
						|
          i4close( i4 ) ;
 | 
						|
          e4( c4, e4memory, 0 ) ;
 | 
						|
#ifndef S4SINGLE
 | 
						|
          i4->file_locked = old_file_lock ;
 | 
						|
#endif
 | 
						|
          return 0 ;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( t4init( tag_ptr, i4, b4recno( t4block(i4->tag_index), t4block(i4->tag_index)->key_on ), t4key_data( i4->tag_index )->value ) < 0 )
 | 
						|
        {
 | 
						|
#ifndef S4SINGLE
 | 
						|
          i4->file_locked = old_file_lock ;
 | 
						|
#endif
 | 
						|
          i4close( i4 ) ;
 | 
						|
          return 0 ;
 | 
						|
        }
 | 
						|
 | 
						|
        l4add( &i4->tags, tag_ptr ) ;
 | 
						|
      } while ( t4skip( i4->tag_index, 1L ) == 1L ) ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( file_name == 0 )
 | 
						|
    {
 | 
						|
      i4close( i4 ) ;
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
      e4describe( c4, e4index, E4_INDEX_EXP, "i4open()", "file_name == 0 invalid" ) ;
 | 
						|
#endif
 | 
						|
      e4( c4, e4index, E4_INDEX_EXP ) ;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    l4add( &i4->tags, i4->tag_index ) ;   /* if an .idx, add single tag */
 | 
						|
  }
 | 
						|
#ifndef S4SINGLE
 | 
						|
  i4->file_locked = old_file_lock ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4FOX
 | 
						|
  if ( file_name == 0 )
 | 
						|
  {
 | 
						|
    u4ncpy( buf, d4->file.name, sizeof(buf) ) ;
 | 
						|
#ifdef S4UNIX
 | 
						|
    u4name_ext( buf, sizeof(buf), "mdx", 1 ) ;
 | 
						|
#else
 | 
						|
    u4name_ext( buf, sizeof(buf), "MDX", 1 ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    u4ncpy( buf, file_name, sizeof(buf) ) ;
 | 
						|
#ifdef S4UNIX
 | 
						|
    u4name_ext( buf, sizeof(buf), "mdx", 0 ) ;
 | 
						|
#else
 | 
						|
    u4name_ext( buf, sizeof(buf), "MDX", 0 ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  for ( i4_ptr = 0 ;; )
 | 
						|
  {
 | 
						|
    i4_ptr = (INDEX4 *)l4next(&d4->indexes, i4_ptr) ;
 | 
						|
    if ( i4_ptr == 0 )
 | 
						|
      break ;
 | 
						|
    if ( !memcmp(i4_ptr->file.name, buf, (size_t) strlen(buf) ) )
 | 
						|
      e4severe( e4parm, E4_PARM_IND ) ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = file4open( &i4->file, c4, buf, 1 ) ;
 | 
						|
  if ( rc )
 | 
						|
    return 0 ;
 | 
						|
  l4add( &d4->indexes, i4 ) ;
 | 
						|
 | 
						|
  if ( file4read_all( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) < 0 )
 | 
						|
  {
 | 
						|
    file4close( &i4->file ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  i4->header.block_chunks = x4reverse_short( (void *)&i4->header.block_chunks ) ;
 | 
						|
  i4->header.block_rw = x4reverse_short( (void *)&i4->header.block_rw ) ;
 | 
						|
  i4->header.slot_size = x4reverse_short( (void *)&i4->header.slot_size ) ;
 | 
						|
  i4->header.num_tags = x4reverse_short( (void *)&i4->header.num_tags ) ;
 | 
						|
  i4->header.eof = x4reverse_long( (void *)&i4->header.eof ) ;
 | 
						|
  i4->header.free_list = x4reverse_long( (void *)&i4->header.free_list ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  /* Perform some checks */
 | 
						|
  if ( i4->header.block_rw != i4->header.block_chunks*512  ||
 | 
						|
      i4->header.block_chunks <= 0 ||
 | 
						|
      i4->header.block_chunks > 63 ||
 | 
						|
      i4->header.num_tags < 0  || i4->header.num_tags > 47 ||
 | 
						|
      i4->header.eof <= 0L )
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
    e4describe( c4, e4index, buf, "i4open()", "checks failed" ) ;
 | 
						|
#endif
 | 
						|
    i4close( i4 ) ;
 | 
						|
    e4( c4, e4index, buf ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( file4read_all( &i4->file, 544L, tag_info, sizeof(tag_info)) < 0 )
 | 
						|
  {
 | 
						|
    i4close( i4 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  for ( i_tag = 0; i_tag < (int) i4->header.num_tags; i_tag++ )
 | 
						|
  {
 | 
						|
    tag_ptr = (TAG4 *)mem4alloc( c4->tag_memory ) ;
 | 
						|
    if ( tag_ptr == 0 )
 | 
						|
    {
 | 
						|
      i4close( i4 ) ;
 | 
						|
      e4( c4, e4memory, 0 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    tag_info[i_tag].header_pos = x4reverse_long( (void *)&tag_info[i_tag].header_pos ) ;
 | 
						|
    tag_info[i_tag].x1000 = 0x1000 ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( t4init( tag_ptr, i4, tag_info + i_tag ) < 0 )
 | 
						|
    {
 | 
						|
      i4close( i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
 | 
						|
    l4add( &i4->tags, tag_ptr ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  i4->block_memory = mem4create( c4, c4->mem_start_block,
 | 
						|
                                sizeof(B4BLOCK) + i4->header.block_rw -
 | 
						|
                                sizeof(B4KEY_DATA) - sizeof(short) - sizeof(char[6]),
 | 
						|
                                c4->mem_expand_block, 0 ) ;
 | 
						|
  if ( i4->block_memory == 0 )
 | 
						|
  {
 | 
						|
    i4close(i4) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  file4optimize( &i4->file, c4->optimize, OPT4INDEX ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  return i4 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION i4shrink( INDEX4 *i4, long block_no )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 || block_no < 0 )
 | 
						|
    e4severe( e4parm, E4_I4SHRINK ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  i4->tag_index->header.free_list = x4reverse_long( (void *)&i4->tag_index->header.free_list ) ;
 | 
						|
#endif
 | 
						|
  if ( file4write( &i4->file, block_no, (char *)&i4->tag_index->header.free_list,
 | 
						|
                  sizeof(i4->tag_index->header.free_list)) < 0) return -1 ;
 | 
						|
  i4->tag_index->header.free_list = block_no ;
 | 
						|
#else
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  i4->header.free_list = x4reverse_long( (void *)&i4->header.free_list ) ;
 | 
						|
#endif
 | 
						|
  if ( file4write( &i4->file, block_no*I4MULTIPLY + sizeof(S4LONG),
 | 
						|
                  (char *)&i4->header.free_list, sizeof(i4->header.free_list)) < 0) return -1 ;
 | 
						|
  i4->header.free_list = block_no ;
 | 
						|
#endif
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
TAG4 *S4FUNCTION i4tag( INDEX4 *i4, char *tag_name )
 | 
						|
{
 | 
						|
  char tag_lookup[11] ;
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( i4, 0, E4_I4TAG ) )
 | 
						|
    return 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 || tag_name == 0 )
 | 
						|
    e4severe( e4parm, E4_I4TAG ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  u4ncpy( tag_lookup, tag_name, sizeof( tag_lookup ) ) ;
 | 
						|
  c4upper( tag_lookup ) ;
 | 
						|
 | 
						|
  for( tag_on = 0 ;; )
 | 
						|
  {
 | 
						|
    tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
    if ( tag_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( strcmp( tag_on->alias, tag_lookup ) == 0 )
 | 
						|
      return tag_on ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( i4->code_base->tag_name_error )
 | 
						|
    e4( i4->code_base, e4tag_name, tag_name ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
/* Updates the header if the version has changed */
 | 
						|
int S4FUNCTION i4update_header( INDEX4 *i4 )
 | 
						|
{
 | 
						|
#ifdef S4MDX
 | 
						|
  TAG4 *tag_on ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  I4HEADER swap ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4UPDATE_HDR ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  /*
 | 
						|
     #ifndef S4SINGLE
 | 
						|
     i4->tag_index->header.version = i4->version_old + 2 ;
 | 
						|
     #endif
 | 
						|
     */
 | 
						|
  if ( i4->version_old != i4->tag_index->header.version )
 | 
						|
  {
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    i4->tag_index->header.root = x4reverse_long( (void *)&i4->tag_index->header.root ) ;
 | 
						|
    i4->tag_index->header.free_list = x4reverse_long( (void *)&i4->tag_index->header.free_list ) ;
 | 
						|
    i4->tag_index->header.key_len = x4reverse_short( (void *)&i4->tag_index->header.key_len ) ;
 | 
						|
#else
 | 
						|
    i4->tag_index->header.version = x4reverse_long( (void *)&i4->tag_index->header.version ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (file4write(&i4->file,0L, (char *)&i4->tag_index->header, T4HEADER_WR_LEN) < 0) return -1;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    i4->tag_index->header.root = x4reverse_long( (void *)&i4->tag_index->header.root ) ;
 | 
						|
    i4->tag_index->header.free_list = x4reverse_long( (void *)&i4->tag_index->header.free_list ) ;
 | 
						|
    i4->tag_index->header.key_len = x4reverse_short( (void *)&i4->tag_index->header.key_len ) ;
 | 
						|
#else
 | 
						|
    i4->tag_index->header.version = x4reverse_long( (void *)&i4->tag_index->header.version ) ;
 | 
						|
#endif
 | 
						|
    i4->version_old = i4->tag_index->header.version ;
 | 
						|
  }
 | 
						|
#else
 | 
						|
  /*
 | 
						|
     #ifndef S4SINGLE
 | 
						|
     i4->changed = 1 ;
 | 
						|
     #endif
 | 
						|
     */
 | 
						|
  if ( i4->changed )
 | 
						|
  {
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    memcpy( (void *)&swap, (void *)&i4->header, sizeof(I4HEADER) ) ;
 | 
						|
 | 
						|
    swap.block_chunks = x4reverse_short( (void *)&swap.block_chunks ) ;
 | 
						|
    swap.block_rw = x4reverse_short( (void *)&swap.block_rw ) ;
 | 
						|
    swap.slot_size = x4reverse_short( (void *)&swap.slot_size ) ;
 | 
						|
    swap.num_tags = x4reverse_short( (void *)&swap.num_tags ) ;
 | 
						|
    swap.eof = x4reverse_long( (void *)&swap.eof ) ;
 | 
						|
    swap.free_list = x4reverse_long( (void *)&swap.free_list ) ;
 | 
						|
 | 
						|
    if ( file4write(&i4->file,0L, (char *)&swap, sizeof(I4HEADER)) < 0 )
 | 
						|
      return -1;
 | 
						|
#else
 | 
						|
    if ( file4write(&i4->file,0L, (char *)&i4->header, sizeof(I4HEADER) ) < 0)
 | 
						|
      return -1;
 | 
						|
#endif
 | 
						|
    i4->changed = 0 ;
 | 
						|
    for( tag_on = 0 ;; )
 | 
						|
    {
 | 
						|
      tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
      if ( tag_on == 0 )
 | 
						|
        break ;
 | 
						|
      if ( tag_on->changed == 1 )
 | 
						|
      {
 | 
						|
        tag_on->header.version++ ;
 | 
						|
        tag_on->changed = 0 ;
 | 
						|
        if ( file4write( &i4->file, tag_on->header_offset + 20L, &tag_on->header.version, sizeof(char) ) < 0)
 | 
						|
          return -1;
 | 
						|
        if ( tag_on->had_keys != tag_on->has_keys )
 | 
						|
        {
 | 
						|
          if ( file4write( &i4->file, tag_on->header_offset + 222 + sizeof( T4HEADER ), &tag_on->has_keys, sizeof(char) ) < 0)
 | 
						|
            return -1;
 | 
						|
          tag_on->had_keys = tag_on->has_keys ;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int S4FUNCTION t4version_check( TAG4 *t4, int do_seek, int update_version )
 | 
						|
{
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( t4->index->file.do_buffer == 0 )
 | 
						|
    return i4version_check( t4->index, do_seek, update_version ) ;
 | 
						|
  else
 | 
						|
    return 0 ;
 | 
						|
#else
 | 
						|
  return i4version_check( t4->index, do_seek, update_version ) ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/* Reads the header, checks the version to see if the blocks need to be freed. */
 | 
						|
int S4FUNCTION i4version_check( INDEX4 *i4, int do_seek, int update_version )
 | 
						|
{
 | 
						|
#ifndef S4SINGLE
 | 
						|
  TAG4 *tag_on, *save_tag ;
 | 
						|
  int rc, need_seek ;
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4VERSION_CHK ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  if ( i4lock_test( i4 ) )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  /* make sure read from disk unless file locked, etc. */
 | 
						|
  if ( i4->file.do_buffer )  /* also makes sure 'opt' should exist */
 | 
						|
    i4->code_base->opt.force_current = 1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  rc = file4read_all( &i4->file, 0L, &i4->tag_index->header, T4HEADER_WR_LEN ) ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  i4->tag_index->header.root = x4reverse_long( (void *)&i4->tag_index->header.root ) ;
 | 
						|
  i4->tag_index->header.free_list = x4reverse_long( (void *)&i4->tag_index->header.free_list ) ;
 | 
						|
  i4->tag_index->header.version = x4reverse_long( (void *)&i4->tag_index->header.version ) ;
 | 
						|
  i4->tag_index->header.key_len = x4reverse_short( (void *)&i4->tag_index->header.key_len ) ;
 | 
						|
#endif
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( i4->file.do_buffer )
 | 
						|
    i4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
  if ( rc < 0 )
 | 
						|
    return rc ;
 | 
						|
  i4->tag_index->header.version = x4reverse_long( (void *)&i4->tag_index->header.version ) ;
 | 
						|
  if ( i4->tag_index->header.version == i4->version_old )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  if ( update_version == 1 )
 | 
						|
    i4->version_old = i4->tag_index->header.version ;
 | 
						|
  else
 | 
						|
    i4->tag_index->header.version = i4->version_old ;
 | 
						|
#else
 | 
						|
  rc = file4read_all( &i4->file, 0L, &i4->header, sizeof(I4HEADER) ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( i4->file.do_buffer )
 | 
						|
    i4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
  if ( rc < 0 )
 | 
						|
    return rc ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  i4->header.block_chunks = x4reverse_short( (void *)&i4->header.block_chunks ) ;
 | 
						|
  i4->header.block_rw = x4reverse_short( (void *)&i4->header.block_rw ) ;
 | 
						|
  i4->header.slot_size = x4reverse_short( (void *)&i4->header.slot_size ) ;
 | 
						|
  i4->header.num_tags = x4reverse_short( (void *)&i4->header.num_tags ) ;
 | 
						|
  i4->header.eof = x4reverse_long( (void *)&i4->header.eof ) ;
 | 
						|
  i4->header.free_list = x4reverse_long( (void *)&i4->header.free_list ) ;
 | 
						|
#endif
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  /* make sure read from disk unless file locked, etc. */
 | 
						|
  if ( i4->file.do_buffer )  /* also makes sure 'opt' should exist */
 | 
						|
    i4->code_base->opt.force_current = 1 ;
 | 
						|
#endif
 | 
						|
  for( tag_on = 0 ;; )
 | 
						|
  {
 | 
						|
    tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
    if ( tag_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( file4read_all( &i4->file, tag_on->header_offset + 20L, &tag_on->header.version, sizeof(char) ) < 0 )
 | 
						|
    {
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
      if ( i4->file.do_buffer )
 | 
						|
        i4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    if ( file4read_all( &i4->file, tag_on->header_offset + 222 + sizeof( T4HEADER ), &tag_on->has_keys, sizeof(char) ) < 0 )
 | 
						|
    {
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
      if ( i4->file.do_buffer )
 | 
						|
        i4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    tag_on->had_keys = tag_on->has_keys ;
 | 
						|
    tag_on->header.root = -1 ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( i4->file.do_buffer )
 | 
						|
    i4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  need_seek = 0 ;
 | 
						|
  save_tag = d4tag_selected( i4->data ) ;
 | 
						|
  if ( save_tag != 0 )
 | 
						|
  {
 | 
						|
    /* remember the old position */
 | 
						|
    if ( do_seek )
 | 
						|
    {
 | 
						|
      b4 = (B4BLOCK *)save_tag->blocks.last_node ;
 | 
						|
      if ( b4 != 0 )
 | 
						|
      {
 | 
						|
#ifdef S4FOX
 | 
						|
        if ( b4->header.n_keys != 0 )
 | 
						|
#else
 | 
						|
          if ( b4->n_keys != 0 )
 | 
						|
#endif
 | 
						|
          {
 | 
						|
            if ( t4eof( save_tag ) )
 | 
						|
              need_seek = 2 ;
 | 
						|
            else
 | 
						|
#ifdef S4FOX
 | 
						|
              if ( b4leaf( b4 ) && b4->header.n_keys != 0 )
 | 
						|
#else
 | 
						|
                if ( b4leaf( b4 ) && b4->n_keys != 0 && b4->key_on < b4->n_keys )
 | 
						|
#endif
 | 
						|
                {
 | 
						|
#ifdef S4FOX
 | 
						|
                  memcpy( save_tag->code_base->saved_key, (void *)(b4key( b4, b4->key_on )), save_tag->header.key_len + sizeof(long) ) ;
 | 
						|
#else
 | 
						|
                  memcpy( save_tag->code_base->saved_key, (void *)(b4key( b4, b4->key_on )), save_tag->header.key_len + 2 * sizeof(S4LONG) ) ;
 | 
						|
#endif
 | 
						|
                  need_seek = 1 ;
 | 
						|
                }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for ( tag_on = 0 ;; )
 | 
						|
  {
 | 
						|
    tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
    if ( tag_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( t4free_all(tag_on) < 0 )  /* Should be a memory operation only */
 | 
						|
#ifdef S4DEBUG
 | 
						|
      e4severe( e4result, E4_I4VERSION_CHK ) ;
 | 
						|
#else
 | 
						|
    return -1 ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  switch ( need_seek )
 | 
						|
  {
 | 
						|
  case 1:
 | 
						|
    t4go( save_tag, ((B4KEY_DATA *)save_tag->code_base->saved_key)->value, ((B4KEY_DATA *)save_tag->code_base->saved_key)->num ) ;
 | 
						|
    break ;
 | 
						|
  case 2:
 | 
						|
    t4go_eof( save_tag ) ;
 | 
						|
    break ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /*  ifndef  N4OTHER  */
 | 
						|
 | 
						|
 | 
						|
#ifdef N4OTHER
 | 
						|
 | 
						|
/* This function closes all the tags corresponding with the index */
 | 
						|
int S4FUNCTION i4close( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  int final_rc, save_attempts ;
 | 
						|
  CODE4 *c4 ;
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( i4, 0, E4_I4CLOSE ) )
 | 
						|
    return -1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4CLOSE ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  c4 = i4->code_base ;
 | 
						|
 | 
						|
  final_rc = c4->error_code ;
 | 
						|
#ifndef S4SINGLE
 | 
						|
  save_attempts = c4->lock_attempts ;
 | 
						|
#endif
 | 
						|
  c4->lock_attempts = -1 ;
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
  if ( i4->data )
 | 
						|
    if ( d4update( i4->data ) < 0 )
 | 
						|
      final_rc = e4set( c4, 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( i4unlock(i4) < 0 )
 | 
						|
    final_rc = e4set( c4, 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  for( ;; )
 | 
						|
  {
 | 
						|
    tag_on = (TAG4 *)l4pop( &i4->tags ) ;
 | 
						|
    if ( tag_on == 0 )
 | 
						|
      break ;
 | 
						|
    t4close( tag_on ) ;
 | 
						|
    if ( t4free_all(tag_on) < 0 )
 | 
						|
    {
 | 
						|
      final_rc = e4set( c4, 0) ;
 | 
						|
      break ;
 | 
						|
    }
 | 
						|
 | 
						|
    expr4free( tag_on->expr ) ;
 | 
						|
    expr4free( tag_on->filter ) ;
 | 
						|
    mem4free( c4->tag_memory, tag_on ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  mem4release( i4->block_memory ) ;
 | 
						|
  i4->block_memory = 0 ;
 | 
						|
 | 
						|
  if ( i4->data )
 | 
						|
    l4remove( &i4->data->indexes, i4 ) ;
 | 
						|
 | 
						|
  mem4free( c4->index_memory, i4 ) ;
 | 
						|
#ifndef S4SINGLE
 | 
						|
  c4->lock_attempts = save_attempts ;
 | 
						|
#endif
 | 
						|
  e4set( c4, final_rc ) ;
 | 
						|
  return  final_rc ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
/* This function flushes all the tags corresponding with the index */
 | 
						|
int S4FUNCTION i4flush( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4FLUSH ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( i4lock_test( i4 ) )
 | 
						|
#endif
 | 
						|
    for ( tag_on = 0 ;; )
 | 
						|
    {
 | 
						|
      tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
      if ( tag_on == 0 )
 | 
						|
        break ;
 | 
						|
      if ( t4flush(tag_on) < 0 )
 | 
						|
        return -1 ;
 | 
						|
      tag_on->header.root = -1L ;
 | 
						|
    }
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION i4update( INDEX4 *i4 )
 | 
						|
{
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4UPDATE ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( i4lock_test( i4 ) )
 | 
						|
#endif
 | 
						|
    for ( tag_on = 0 ;; )
 | 
						|
    {
 | 
						|
      tag_on = (TAG4 *)l4next( &i4->tags, tag_on ) ;
 | 
						|
      if ( tag_on == 0 )
 | 
						|
        break ;
 | 
						|
      if ( t4update( tag_on ) < 0 )
 | 
						|
        return -1 ;
 | 
						|
      tag_on->header.root = -1L ;
 | 
						|
    }
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
INDEX4 *S4FUNCTION i4open( DATA4 *d4, char *file_name )
 | 
						|
{
 | 
						|
  INDEX4 *i4 ;
 | 
						|
  CODE4 *c4 ;
 | 
						|
  TAG4 *tag ;
 | 
						|
  int len, rc, i ;
 | 
						|
  char buf[258], tag_buf[258], ext[3] ;
 | 
						|
  int num_files ;
 | 
						|
  FILE4SEQ_READ seqread ;
 | 
						|
  char buffer[1024], t_names[258], first_byte ;
 | 
						|
  int pos, i_pos, save_len, temp_len, hold_len ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( d4, 2, E4_I4OPEN ) )
 | 
						|
    return 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( d4 == 0 )
 | 
						|
    e4severe( e4parm, E4_I4OPEN ) ;
 | 
						|
 | 
						|
  if ( file_name == 0 )
 | 
						|
    u4name_piece( buf, sizeof( buf ), d4->file.name, 0, 0 ) ;
 | 
						|
  else
 | 
						|
    u4name_piece( buf, sizeof( buf ), file_name, 0, 0 ) ;
 | 
						|
  if ( d4index( d4, buf ) )
 | 
						|
  {
 | 
						|
    e4( d4->code_base, e4info, E4_INFO_IAO ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  c4 = d4->code_base ;
 | 
						|
  if ( c4->error_code < 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  if ( file_name == 0 )
 | 
						|
  {
 | 
						|
    u4ncpy( buf, d4->file.name, sizeof( buf ) ) ;
 | 
						|
    u4name_ext( buf, sizeof( buf ), "CGP", 1 ) ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    u4ncpy( buf, file_name, sizeof(buf) ) ;
 | 
						|
    c4upper( buf ) ;
 | 
						|
    rc = u4name_ret_ext( ext, 3, buf ) ;
 | 
						|
    if ( rc )  /* extension provided */
 | 
						|
    {
 | 
						|
      if ( rc == 3 )  /* check for .ndx or .cdx */
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4UNIX
 | 
						|
        if ( memcmp( ext, "ndx", 3 ) == 0 )
 | 
						|
#else
 | 
						|
          if ( memcmp( ext, "NDX", 3 ) == 0 )
 | 
						|
#endif
 | 
						|
#else
 | 
						|
#ifdef S4UNIX
 | 
						|
            if ( memcmp( ext, "ntx", 3 ) == 0 )
 | 
						|
#else
 | 
						|
              if ( memcmp( ext, "NTX", 3 ) == 0 )
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
              {
 | 
						|
                tag = t4open( d4, (INDEX4 *)0, file_name ) ;
 | 
						|
                if ( tag == 0 )
 | 
						|
                  return 0 ;
 | 
						|
                return tag->index ;
 | 
						|
              }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      u4name_ext( buf, sizeof(buf), "CGP", 0 ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( c4->index_memory == 0 )
 | 
						|
  {
 | 
						|
    c4->index_memory = mem4create( c4, c4->mem_start_index, sizeof( INDEX4 ), c4->mem_expand_index, 0 ) ;
 | 
						|
    if ( c4->index_memory == 0 )
 | 
						|
      return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( c4->tag_memory == 0 )
 | 
						|
  {
 | 
						|
    c4->tag_memory = mem4create( c4, c4->mem_start_tag, sizeof( TAG4 ), c4->mem_expand_tag, 0 ) ;
 | 
						|
    if ( c4->tag_memory == 0 )
 | 
						|
      return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  i4 = (INDEX4 *)mem4alloc( c4->index_memory ) ;
 | 
						|
  if ( i4 == 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  i4->code_base = c4 ;
 | 
						|
  u4name_piece( i4->alias, sizeof( i4->alias ), buf, 0, 0 ) ;
 | 
						|
 | 
						|
  if ( file4open( &i4->file, c4, buf, 1 ) )
 | 
						|
  {
 | 
						|
    i4close( i4 ) ;
 | 
						|
    if ( c4->open_error )
 | 
						|
      e4( c4, e4open, E4_INFO_SET ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  file4seq_read_init( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
 | 
						|
 | 
						|
  pos = 0L ;
 | 
						|
  rc = file4seq_read_all( &seqread, &first_byte, sizeof( first_byte ) ) ;
 | 
						|
  if ( rc )
 | 
						|
  {
 | 
						|
    if ( c4->open_error )
 | 
						|
      e4( c4, e4info, E4_INFO_REA ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( first_byte < 65 )   /* old format - potential problem if >= 65 files in an old format file. */
 | 
						|
  {
 | 
						|
    num_files = first_byte ;
 | 
						|
    if ( file4seq_read_all( &seqread, &first_byte, sizeof( first_byte ) ) )
 | 
						|
    {
 | 
						|
      if ( c4->open_error )
 | 
						|
        e4( c4, e4info, E4_INFO_REA ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
 | 
						|
    for ( i = 0 ; i < num_files ; i++ )
 | 
						|
    {
 | 
						|
      if ( file4seq_read_all( &seqread, &len, sizeof( len ) ) )
 | 
						|
      {
 | 
						|
        file4close( &i4->file ) ;
 | 
						|
        i4close( i4 ) ;
 | 
						|
        if ( c4->open_error )
 | 
						|
          e4( c4, e4info, E4_INFO_REA ) ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
      pos += sizeof( len ) ;
 | 
						|
      rc = u4name_path( tag_buf, sizeof( tag_buf ), buf ) ;
 | 
						|
      tag_buf[rc+len] = '\0' ;
 | 
						|
      if ( sizeof( tag_buf ) > rc + len ) /* make sure room to read */
 | 
						|
        rc = file4seq_read_all( &seqread, tag_buf+rc, len ) ;
 | 
						|
      else
 | 
						|
        rc = -1 ;
 | 
						|
 | 
						|
      if ( rc )
 | 
						|
      {
 | 
						|
        if ( c4->open_error )
 | 
						|
          e4( c4, e4info, E4_INFO_REA ) ;
 | 
						|
        file4close( &i4->file ) ;
 | 
						|
        i4close( i4 ) ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
 | 
						|
      pos += len ;
 | 
						|
      if  ( t4open( d4, i4, tag_buf ) == 0 )
 | 
						|
      {
 | 
						|
        file4close( &i4->file ) ;
 | 
						|
        i4close( i4 ) ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    file4close( &i4->file ) ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    file4seq_read_init( &seqread, &i4->file, 0, buffer, sizeof(buffer) ) ;
 | 
						|
    save_len = 0 ;
 | 
						|
 | 
						|
    for( len = sizeof( t_names ) ; len == sizeof( t_names ) ; )
 | 
						|
    {
 | 
						|
      len = file4seq_read( &seqread, t_names, sizeof( t_names )) ;
 | 
						|
      if ( len < sizeof( t_names ) ) /* case where all read in now - free up this file handle for use */
 | 
						|
      {
 | 
						|
        if ( file4close ( &i4->file ) )
 | 
						|
        {
 | 
						|
          i4close( i4 ) ;
 | 
						|
          if ( c4->open_error )
 | 
						|
            e4( c4, e4info, E4_INFO_CLO ) ;
 | 
						|
          return 0 ;
 | 
						|
        }
 | 
						|
        if ( len == 0 )
 | 
						|
          break ;
 | 
						|
      }
 | 
						|
      for( i_pos = 0, pos = 0 ; pos < len ; )
 | 
						|
      {
 | 
						|
        switch( t_names[pos] )
 | 
						|
        {
 | 
						|
          /* cases where the values are ignored, or found name */
 | 
						|
        case ' ':
 | 
						|
        case '\r':
 | 
						|
        case '\n':
 | 
						|
        case '\t':
 | 
						|
        case '\x1A':
 | 
						|
          if ( i_pos < pos )  /* try to open the file */
 | 
						|
          {
 | 
						|
            temp_len = pos - i_pos ;
 | 
						|
            if ( save_len == 0 )
 | 
						|
            {
 | 
						|
              rc = u4name_path( tag_buf, sizeof( tag_buf ), buf ) ;
 | 
						|
              tag_buf[rc+temp_len] = '\0' ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
              rc = save_len ;
 | 
						|
            memcpy( tag_buf + rc, &t_names[i_pos], temp_len ) ;
 | 
						|
 | 
						|
            if  ( t4open( d4, i4, tag_buf ) == 0 )
 | 
						|
            {
 | 
						|
              file4close( &i4->file ) ;
 | 
						|
              i4close( i4 ) ;
 | 
						|
              return 0 ;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          i_pos = ++pos ;
 | 
						|
          break ;
 | 
						|
 | 
						|
          /* case where a name is attempted to be read in */
 | 
						|
        default:
 | 
						|
          pos++ ;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      temp_len = pos - i_pos ;
 | 
						|
      rc = u4name_path( tag_buf, sizeof( tag_buf ), buf ) ;
 | 
						|
      tag_buf[rc+temp_len] = '\0' ;
 | 
						|
      memcpy( tag_buf + rc, &t_names[i_pos], temp_len ) ;
 | 
						|
      save_len = rc + temp_len ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( ( save_len - rc ) > 0 )  /* try to open the file */
 | 
						|
    {
 | 
						|
      if  ( t4open( d4, i4, tag_buf ) == 0 )
 | 
						|
      {
 | 
						|
        file4close( &i4->file ) ;
 | 
						|
        i4close( i4 ) ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  l4add( &d4->indexes, i4 ) ;
 | 
						|
  i4->data = d4 ;
 | 
						|
  return i4 ;
 | 
						|
}
 | 
						|
 | 
						|
TAG4 *S4FUNCTION i4tag( INDEX4 *i4, char *tag_name )
 | 
						|
{
 | 
						|
  char tag_lookup[11] ;
 | 
						|
  TAG4 *tag_on ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( i4, 0, E4_I4TAG ) )
 | 
						|
    return 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4 == 0 || tag_name == 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  u4ncpy( tag_lookup, tag_name, sizeof(tag_lookup) ) ;
 | 
						|
  c4upper( tag_lookup ) ;
 | 
						|
 | 
						|
  for( tag_on = 0 ;; )
 | 
						|
  {
 | 
						|
    tag_on = (TAG4 *)l4next( &i4->tags, tag_on) ;
 | 
						|
    if ( tag_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( strcmp( tag_on->alias, tag_lookup) == 0 )
 | 
						|
      return tag_on ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( i4->code_base->tag_name_error )
 | 
						|
    e4( i4->code_base, e4tag_name, tag_name ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif   /*  ifdef N4OTHER  */
 | 
						|
 | 
						|
 | 
						|
int S4FUNCTION i4is_production( INDEX4 *i4 )
 | 
						|
{
 | 
						|
#ifdef N4OTHER
 | 
						|
  return 0 ;
 | 
						|
#else
 | 
						|
#ifdef S4MDX
 | 
						|
  return i4->header.is_production ;
 | 
						|
#endif
 | 
						|
#ifdef S4FOX
 | 
						|
  int l1, l2 ;
 | 
						|
 | 
						|
  if ( i4->data->has_mdx )
 | 
						|
  {
 | 
						|
    l1 = strlen( i4->file.name ) - 4 ;  /* remove extenstion */
 | 
						|
    l2 = strlen( i4->data->alias ) ;
 | 
						|
    if ( l1 == l2 )
 | 
						|
      return( memcmp( i4->file.name, i4->data->alias, l1 ) ? 0 : 1 ) ;
 | 
						|
  }
 | 
						|
  return 0 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* S4INDEX_OFF */
 | 
						|
 | 
						|
 | 
						|
#ifdef S4VB_DOS
 | 
						|
 | 
						|
INDEX4 * i4open_v( DATA4 *d4, char *name )
 | 
						|
{
 | 
						|
  char *name_ptr ;
 | 
						|
 | 
						|
  name_ptr = c4str(name) ;
 | 
						|
 | 
						|
  if (name_ptr[0] == '\0' )
 | 
						|
    return i4open( d4, 0 ) ;
 | 
						|
 | 
						|
  return i4open( d4, name_ptr ) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TAG4 *i4tag_v( INDEX4 *ind, char *tag_name )
 | 
						|
{
 | 
						|
  return i4tag( ind, c4str(tag_name) ) ;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |