which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@1014 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1669 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1669 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* i4ntag.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
 | 
						|
 | 
						|
#include <time.h>
 | 
						|
 | 
						|
int S4FUNCTION t4type( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4FOX
 | 
						|
  return t4->expr->type ;
 | 
						|
#endif
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  return t4->expr->type ;
 | 
						|
#endif
 | 
						|
#ifdef S4NDX
 | 
						|
  return t4->header.type ;
 | 
						|
#endif
 | 
						|
#ifdef S4MDX
 | 
						|
  return t4->header.type ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#ifdef N4OTHER
 | 
						|
 | 
						|
B4BLOCK *S4FUNCTION t4block( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4BLOCK ) ;
 | 
						|
  if ( t4->blocks.last_node == 0 )
 | 
						|
    e4severe( e4info, E4_T4BLOCK ) ;
 | 
						|
#endif
 | 
						|
  return (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int S4FUNCTION t4rl_bottom( TAG4 *t4 )
 | 
						|
#else
 | 
						|
  int S4FUNCTION t4bottom( TAG4 *t4 )
 | 
						|
#endif
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4TOP ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  do
 | 
						|
  {
 | 
						|
    rc = t4up_to_root( t4 ) ;
 | 
						|
    if ( rc < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
    if ( rc != 2 )
 | 
						|
    {
 | 
						|
      b4go_eof( t4block( t4 ) ) ;
 | 
						|
      do
 | 
						|
      {
 | 
						|
        rc = t4down( t4 ) ;
 | 
						|
        if ( rc < 0 )
 | 
						|
          return -1 ;
 | 
						|
        b4go_eof( t4block( t4 ) ) ;
 | 
						|
      } while ( rc == 0 ) ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      t4out_of_date( t4 ) ;
 | 
						|
  } while ( rc == 2 ) ;
 | 
						|
 | 
						|
  block_on = t4block(t4) ;
 | 
						|
  if ( block_on->key_on > 0 )
 | 
						|
    block_on->key_on = block_on->n_keys-1 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( block_on->key_on < 0 )  e4severe( e4info, E4_T4BOTTOM ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int S4FUNCTION t4bottom( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4BOTTOM ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  if ( t4->header.descending )   /* if descending, go bottom means go top */
 | 
						|
    return t4rl_top( t4 ) ;
 | 
						|
  else
 | 
						|
    return t4rl_bottom( t4 ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4HAS_DESCENDING
 | 
						|
void S4FUNCTION t4descending( TAG4 *tag, int setting )
 | 
						|
{
 | 
						|
  tag->header.descending = setting ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
/* Returns  1 - Cannot move down; 0 - Success; -1 Error */
 | 
						|
int S4FUNCTION t4down( TAG4 *t4 )
 | 
						|
{
 | 
						|
  long block_down ;
 | 
						|
  B4BLOCK *block_on, *pop_block, *new_block, *parent ;
 | 
						|
  int rc ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  char *swap_ptr ;
 | 
						|
  int i ;
 | 
						|
  short short_val ;
 | 
						|
  long long_val ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4DOWN ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
 | 
						|
  if ( block_on == 0 )    /* Read the root block */
 | 
						|
  {
 | 
						|
    if ( t4->header.root <= 0L )
 | 
						|
    {
 | 
						|
#ifdef S4NDX
 | 
						|
      if ( file4read_all( &t4->file, t4->header.header_offset, &t4->header.root, 2*sizeof(long)) < 0 )
 | 
						|
        return -1 ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
      if ( file4read_all( &t4->file, t4->header.header_offset + 2*sizeof(short), &t4->header.root, 2*sizeof(long)) < 0 )
 | 
						|
        return -1 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
      t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
      t4->header.eof  = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    block_down = t4->header.root ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if ( b4leaf( block_on ) )
 | 
						|
      return 1 ;
 | 
						|
    block_down = b4key( block_on, block_on->key_on )->pointer ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( block_down <= 0L )
 | 
						|
      e4severe( e4info, E4_INFO_ILF ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  /* Get memory for the new block */
 | 
						|
  pop_block = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
  new_block = pop_block ;
 | 
						|
  if ( new_block == 0 )
 | 
						|
    new_block = b4alloc( t4, block_down ) ;
 | 
						|
  if ( new_block == 0 )
 | 
						|
    return -1 ;
 | 
						|
  parent = (B4BLOCK *)l4last( &t4->blocks ) ;
 | 
						|
  l4add( &t4->blocks, new_block ) ;
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
  if ( pop_block == 0  ||  new_block->file_block != block_down )
 | 
						|
#else
 | 
						|
    if ( pop_block == 0  ||  new_block->file_block*I4MULTIPLY != block_down )
 | 
						|
#endif
 | 
						|
    {
 | 
						|
      if ( new_block->changed == 1 )
 | 
						|
        if ( b4flush(new_block) < 0 )
 | 
						|
          return -1 ;
 | 
						|
 | 
						|
      rc = i4read_block( &t4->file, block_down, parent, new_block ) ;
 | 
						|
 | 
						|
      if ( rc < 0 )
 | 
						|
        return -1 ;
 | 
						|
 | 
						|
      if ( rc == 1 )
 | 
						|
      {
 | 
						|
        l4remove( &t4->blocks, new_block ) ;
 | 
						|
        l4add( &t4->saved, new_block ) ;
 | 
						|
        return 2 ;
 | 
						|
      }
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
#ifdef S4NDX
 | 
						|
      swap_ptr = (void *)&new_block->n_keys ;
 | 
						|
 | 
						|
      short_val = x4reverse_short( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
 | 
						|
      swap_ptr += 2 + sizeof(short) ;
 | 
						|
 | 
						|
      for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | 
						|
      {
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(long) ) ;
 | 
						|
        long_val = x4reverse_long( (void *)(swap_ptr+sizeof(long)) ) ;
 | 
						|
        memcpy( swap_ptr+sizeof(long), (void *) &long_val, sizeof(long) ) ;
 | 
						|
        swap_ptr += r4->group_len ;
 | 
						|
      }
 | 
						|
 | 
						|
      long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &long_val, sizeof(long) ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
      swap_ptr = (void *)&new_block->n_keys ;
 | 
						|
 | 
						|
      short_val = x4reverse_short( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
 | 
						|
      swap_ptr += 2 ;
 | 
						|
      /* swap the short pointers to B4KEY_DATA */
 | 
						|
      for ( i = 0 ; i <= t4->header.keys_max ; i++ )
 | 
						|
      {
 | 
						|
        short_val = x4reverse_short( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
        swap_ptr += sizeof(short) ;
 | 
						|
      }
 | 
						|
      /* swap the B4KEY_DATA's */
 | 
						|
      for ( i = 0 ; i < t4->header.keys_max ; i++ )
 | 
						|
      {
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(long) ) ;
 | 
						|
        long_val = x4reverse_long( (void *)(swap_ptr+sizeof(long)) ) ;
 | 
						|
        memcpy( swap_ptr+sizeof(long), (void *) &long_val, sizeof(long) ) ;
 | 
						|
        swap_ptr += t4->header.group_len ;
 | 
						|
      }
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
      for ( ;; )
 | 
						|
      {
 | 
						|
        block_on = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
        if ( block_on == 0 )
 | 
						|
          break ;
 | 
						|
        if ( b4flush(block_on) < 0 )
 | 
						|
          return -1 ;
 | 
						|
        b4free( block_on ) ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  new_block->key_on = 0 ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4eof( TAG4 *t4 )
 | 
						|
{
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4EOF ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  b4 = t4block( t4 ) ;
 | 
						|
  return ( b4->key_on >= b4->n_keys ) ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION t4flush( TAG4 *t4 )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4FLUSH ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = t4update( t4 ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( rc )
 | 
						|
    rc = file4flush( &t4->file ) ;
 | 
						|
#endif
 | 
						|
  return rc ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int S4FUNCTION t4free_all( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4FREE_ALL ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  while ( t4up( t4 ) == 0 ) ;
 | 
						|
  return t4free_saved( t4 ) ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4free_saved( TAG4 *t4 )
 | 
						|
{
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
 | 
						|
  if ( t4update( t4 ) < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  for ( ;; )
 | 
						|
  {
 | 
						|
    block_on = (B4BLOCK *)l4pop( &t4->saved ) ;
 | 
						|
    if ( block_on == 0 )
 | 
						|
      return 0 ;
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
    if ( b4flush( block_on ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
#endif
 | 
						|
    b4free( block_on ) ;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
B4KEY_DATA *S4FUNCTION t4key_data( TAG4 *t4 )
 | 
						|
{
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
 | 
						|
  b4 = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
  return b4key( b4, b4->key_on ) ;
 | 
						|
}
 | 
						|
 | 
						|
long S4FUNCTION t4recno( TAG4 *t4 )
 | 
						|
{
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4RECNO ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
  if ( block_on == 0 )
 | 
						|
    return -2L ;
 | 
						|
#ifdef S4NDX
 | 
						|
  if ( !b4leaf( block_on ) )
 | 
						|
    return -2L ;
 | 
						|
#else
 | 
						|
  if ( block_on->key_on >= block_on->n_keys )
 | 
						|
    return -1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  return b4recno( block_on, block_on->key_on ) ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4seek( TAG4 *t4, void *ptr, int len_ptr )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  int upper_fnd, upper_aft, inc_pos, d_set ;
 | 
						|
  unsigned char *c_ptr ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
  int sv_mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  d_set = 0 ;
 | 
						|
  c_ptr = (unsigned char *)ptr ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 || ptr == 0 )
 | 
						|
    e4severe( e4parm, E4_T4SEEK ) ;
 | 
						|
  if ( len_ptr != t4->header.key_len && t4type( t4 ) != r4str )
 | 
						|
    e4severe( e4parm, E4_T4SEEK ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
  t4->index->code_base->mode |= 0x08 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( len_ptr > t4->header.key_len )
 | 
						|
    len_ptr = t4->header.key_len ;
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  if ( t4->header.descending )   /* look for current item less one: */
 | 
						|
  {
 | 
						|
    for( inc_pos = len_ptr-1 ; d_set == 0 && inc_pos >=0 ; inc_pos-- )
 | 
						|
      if ( c_ptr[inc_pos] != 0xFF )
 | 
						|
      {
 | 
						|
        c_ptr[inc_pos]++ ;
 | 
						|
        d_set = 1 ;
 | 
						|
      }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = 3 ;
 | 
						|
  for(;;) /* Repeat until found */
 | 
						|
  {
 | 
						|
    while ( rc >= 2 )
 | 
						|
    {
 | 
						|
      if ( rc == 2 )
 | 
						|
        t4out_of_date( t4 ) ;
 | 
						|
      rc = t4up_to_root( t4 ) ;
 | 
						|
#ifdef S4CLIPPER
 | 
						|
      upper_fnd = 0 ;
 | 
						|
      upper_aft = 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
      if ( rc < 0 )
 | 
						|
        return -1 ;
 | 
						|
    }
 | 
						|
    block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( block_on == 0 )
 | 
						|
      e4severe( e4info, E4_T4SEEK ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    rc = b4seek( block_on, (char *)ptr, len_ptr ) ;
 | 
						|
#ifdef S4NDX
 | 
						|
    if ( b4leaf( block_on ) )
 | 
						|
      break ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    if ( b4leaf( block_on ) )
 | 
						|
    {
 | 
						|
      if ( rc == r4after && upper_aft && block_on->key_on >= block_on->n_keys )
 | 
						|
        while( upper_aft-- > 1 )
 | 
						|
          t4up( t4 ) ;
 | 
						|
      if ( rc == 0 || !upper_fnd )
 | 
						|
        break ;
 | 
						|
 | 
						|
      while( upper_fnd-- > 1 )
 | 
						|
        t4up( t4 ) ;
 | 
						|
      rc = 0 ;
 | 
						|
      break ;
 | 
						|
    }
 | 
						|
    if ( rc == 0 )
 | 
						|
    {
 | 
						|
      upper_fnd = 1 ;
 | 
						|
      upper_aft = 0 ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      if ( rc == r4after && !upper_fnd && !( block_on->key_on >= block_on->n_keys ) )
 | 
						|
        upper_aft = 1 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
    rc = t4down( t4 ) ;
 | 
						|
    if ( rc < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    if ( upper_fnd )
 | 
						|
      upper_fnd++ ;
 | 
						|
    if ( upper_aft )
 | 
						|
      upper_aft++ ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  if ( t4->header.descending )   /* must go back one! */
 | 
						|
  {
 | 
						|
    c_ptr[inc_pos+1]-- ; /* reset the search_ptr ; */
 | 
						|
    if ( d_set )
 | 
						|
    {
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
      sv_mode = t4->code_base->mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
      rc = (int)t4skip( t4, -1L ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
      t4->code_base->mode = sv_mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
      if ( rc == 0L )  /* bof = eof condition */
 | 
						|
      {
 | 
						|
        b4go_eof( block_on ) ;
 | 
						|
        rc = r4eof ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        /*               b4go( t4block( t4 ), t4block( t4 )->key_on ) ; */
 | 
						|
        if ( (u4memcmp)( b4key_key( t4block( t4 ), t4block( t4 )->key_on ), ptr, len_ptr ) )
 | 
						|
          rc = r4after ;
 | 
						|
        else
 | 
						|
          rc = 0 ;  /* successful find */
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if ( rc == 0 )  /* the item was found, so go top, */
 | 
						|
        t4top( t4 ) ;
 | 
						|
      else  /* otherwise want an eof type condition */
 | 
						|
      {
 | 
						|
        b4go_eof( block_on ) ;
 | 
						|
        rc = r4eof ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  return rc ;
 | 
						|
}
 | 
						|
 | 
						|
long S4FUNCTION t4skip( TAG4 *t4, long num_skip )
 | 
						|
{
 | 
						|
  int rc, sign ;
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
  long num_left = num_skip ;
 | 
						|
#endif
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  long j ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4SEEK ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
  t4->index->code_base->mode |= 0x04 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( num_skip < 0)
 | 
						|
    sign = -1 ;
 | 
						|
  else
 | 
						|
    sign = 1 ;
 | 
						|
 | 
						|
  block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
  if ( block_on == 0 )
 | 
						|
  {
 | 
						|
    rc = t4top( t4 ) ;
 | 
						|
    if ( rc < 0 )
 | 
						|
      return -num_skip ;
 | 
						|
    block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( !b4leaf( block_on ) )
 | 
						|
    e4severe( e4info, E4_T4SKIP ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  for(;;)
 | 
						|
  {
 | 
						|
    /* save the current key in case skip fails -- for leaf blocks only */
 | 
						|
    if ( b4leaf( block_on ) )
 | 
						|
      memcpy( t4->code_base->saved_key, b4key_key( block_on, block_on->key_on ), t4->header.key_len ) ;
 | 
						|
 | 
						|
    while ( (rc = t4down(t4)) == 0 )
 | 
						|
      if ( sign < 0 )
 | 
						|
      {
 | 
						|
        block_on = t4block(t4) ;
 | 
						|
        b4go_eof( block_on ) ;
 | 
						|
        if ( b4leaf(block_on) )
 | 
						|
        {
 | 
						|
          block_on->key_on-- ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
          if ( block_on->key_on < 0 )
 | 
						|
            e4severe( e4info, E4_T4SKIP ) ;
 | 
						|
#endif
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
    if ( rc < 0 )
 | 
						|
      return -num_skip ;
 | 
						|
 | 
						|
    if ( rc == 2 )   /* failed on i/o, seek current spot to make valid */
 | 
						|
    {
 | 
						|
      t4out_of_date( t4 ) ;
 | 
						|
      rc = t4seek( t4, t4->code_base->saved_key, t4->header.key_len ) ;
 | 
						|
      if ( rc < 0 )
 | 
						|
        return -num_skip ;
 | 
						|
      if ( rc == r4after )   /* means skipped 1 ahead */
 | 
						|
        num_left-- ;
 | 
						|
      continue ;
 | 
						|
    }
 | 
						|
 | 
						|
    block_on = t4block( t4 ) ;
 | 
						|
 | 
						|
    if ( rc < 0 )  /* Error */
 | 
						|
      return( -num_skip ) ;
 | 
						|
 | 
						|
    num_left -= b4skip( block_on, num_left ) ;
 | 
						|
    if ( num_left == 0 )  /* Success */
 | 
						|
      return( num_skip ) ;
 | 
						|
 | 
						|
    do  /* Skip 1 to the next leaf block  */
 | 
						|
    {
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( t4->blocks.last_node == 0 )
 | 
						|
        e4severe( e4result, E4_T4SKIP ) ;
 | 
						|
#endif
 | 
						|
      if ( l4prev( &t4->blocks, t4->blocks.last_node ) == 0 )  /* root block */
 | 
						|
      {
 | 
						|
        if ( num_skip > 0 )
 | 
						|
        {
 | 
						|
          if ( t4bottom( t4 ) < 0 )
 | 
						|
            return -num_skip ;
 | 
						|
        }
 | 
						|
        else
 | 
						|
          if ( t4top( t4 ) < 0 )
 | 
						|
            return -num_skip ;
 | 
						|
 | 
						|
        return( num_skip - num_left ) ;
 | 
						|
      }
 | 
						|
      t4up( t4 ) ;
 | 
						|
      block_on = (B4BLOCK *)t4->blocks.last_node ;
 | 
						|
    }  while ( b4skip( block_on, (long) sign) != sign) ;
 | 
						|
    num_left -= sign ;
 | 
						|
  }
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  for( j = num_skip; j != 0; j -= sign )  /* skip 1 * num_skip */
 | 
						|
  {
 | 
						|
    if ( b4leaf(block_on) )
 | 
						|
    {
 | 
						|
      if ( b4skip( block_on, (long) sign) != sign )  /* go up */
 | 
						|
      {
 | 
						|
        int go_on = 1 ;
 | 
						|
        while ( go_on )
 | 
						|
        {
 | 
						|
          if ( l4prev( &t4->blocks, t4->blocks.last_node ) == 0 )  /* root block */
 | 
						|
          {
 | 
						|
            if ( num_skip > 0 )
 | 
						|
            {
 | 
						|
              if ( t4bottom( t4 ) < 0 )  return -num_skip ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
              if ( t4top( t4 ) < 0 ) return -num_skip ;
 | 
						|
 | 
						|
            return ( num_skip - j ) ;
 | 
						|
          }
 | 
						|
 | 
						|
          rc = t4up( t4 ) ;
 | 
						|
          block_on = t4block( t4 ) ;
 | 
						|
          if ( rc != 0 ) return -1 ;
 | 
						|
 | 
						|
          if ( sign > 0 )  /* forward skipping */
 | 
						|
          {
 | 
						|
            if ( !( block_on->key_on >= block_on->n_keys ) )
 | 
						|
              go_on = 0 ;
 | 
						|
          }
 | 
						|
          else   /* backward skipping */
 | 
						|
          {
 | 
						|
            if ( ! (block_on->key_on == 0) )
 | 
						|
            {
 | 
						|
              b4skip( block_on, -1L ) ;
 | 
						|
              go_on = 0 ;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if ( sign > 0 )
 | 
						|
        b4skip( block_on, 1L ) ;
 | 
						|
 | 
						|
      /* save the current key in case skip fails -- for leaf blocks only */
 | 
						|
      if ( b4leaf( block_on ) )
 | 
						|
        memcpy( t4->code_base->saved_key, b4key_key( block_on, block_on->key_on ), t4->header.key_len ) ;
 | 
						|
 | 
						|
      while ( (rc = t4down( t4 ) ) == 0 )
 | 
						|
      {
 | 
						|
        if ( sign < 0 )
 | 
						|
        {
 | 
						|
          block_on = t4block( t4 ) ;
 | 
						|
          b4go_eof( block_on ) ;
 | 
						|
          if ( b4leaf( block_on ) )
 | 
						|
            block_on->key_on-- ;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if ( rc < 0 )
 | 
						|
        return -num_skip ;
 | 
						|
 | 
						|
      if ( rc == 2 )   /* failed on i/o, seek current spot to make valid */
 | 
						|
      {
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4SINGLE
 | 
						|
        file4refresh( &t4->file ) ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
        rc = t4seek( t4, t4->code_base->saved_key, t4->header.key_len ) ;
 | 
						|
        if ( rc < 0 )
 | 
						|
          return -num_skip ;
 | 
						|
        if ( rc == r4after )   /* means skipped 1 ahead */
 | 
						|
          j-- ;
 | 
						|
      }
 | 
						|
 | 
						|
      block_on = t4block( t4 ) ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return num_skip ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4NDX
 | 
						|
B4BLOCK *S4FUNCTION t4split( TAG4 *t4, B4BLOCK *old_block )
 | 
						|
{
 | 
						|
  long new_file_block ;
 | 
						|
  B4BLOCK *new_block ;
 | 
						|
  int new_len ;
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
  if ( b4verify( old_block ) == -1 )
 | 
						|
    e4describe( old_block->tag->code_base, e4index, old_block->tag->alias, "t4split()-before split", "" ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  new_file_block = t4extend( t4 ) ;
 | 
						|
  new_block = b4alloc( t4, new_file_block ) ;
 | 
						|
  if ( new_block == 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  new_block->changed = 1 ;
 | 
						|
  old_block->changed = 1 ;
 | 
						|
 | 
						|
  /* NNNNOOOO  N - New, O - Old */
 | 
						|
  new_block->n_keys = ( old_block->n_keys )/2 ;
 | 
						|
  old_block->n_keys -= new_block->n_keys ;
 | 
						|
 | 
						|
  new_len = new_block->n_keys * t4->header.group_len ;
 | 
						|
 | 
						|
  memmove(  b4key(new_block,0),  b4key(old_block, old_block->n_keys ), new_len+ (sizeof(long)*(!(b4leaf( old_block )) ) ) ) ;
 | 
						|
  new_block->key_on = old_block->key_on - old_block->n_keys ;
 | 
						|
 | 
						|
  old_block->n_keys -= !( b4leaf( old_block ) ) ;
 | 
						|
 | 
						|
  return new_block ;
 | 
						|
}
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
/* NTX only needs to do a copy and adjust the index pointers */
 | 
						|
/* if extra_old is true then the extra key is placed in old, otherwise in new */
 | 
						|
B4BLOCK *S4FUNCTION t4split( TAG4 *t4, B4BLOCK *old_block, int extra_old )
 | 
						|
{
 | 
						|
  long  new_file_block ;
 | 
						|
  B4BLOCK *new_block ;
 | 
						|
  int is_branch ;
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
  if ( b4verify( old_block ) == -1 )
 | 
						|
    e4describe( old_block->tag->code_base, e4index, old_block->tag->alias, "t4split()-before split", "" ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  new_file_block = t4extend( t4 ) ;
 | 
						|
  new_block = b4alloc( t4, new_file_block ) ;
 | 
						|
  if ( new_block == 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  new_block->changed = 1 ;
 | 
						|
  old_block->changed = 1 ;
 | 
						|
 | 
						|
  memcpy( new_block->data, old_block->data, B4BLOCK_SIZE - ( t4->header.keys_max + 2 ) * sizeof(short) ) ;
 | 
						|
 | 
						|
  if ( extra_old )
 | 
						|
  {
 | 
						|
    new_block->n_keys = old_block->n_keys / 2 ;
 | 
						|
    old_block->n_keys -= new_block->n_keys ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    new_block->n_keys = old_block->n_keys ;
 | 
						|
    old_block->n_keys = old_block->n_keys / 2 ;
 | 
						|
    new_block->n_keys -= old_block->n_keys ;
 | 
						|
    if ( old_block->n_keys == new_block->n_keys )
 | 
						|
    {
 | 
						|
      new_block->n_keys++ ;
 | 
						|
      old_block->n_keys-- ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  is_branch = !b4leaf( old_block ) ;
 | 
						|
 | 
						|
  memcpy( new_block->pointers, &old_block->pointers[old_block->n_keys + is_branch],
 | 
						|
         new_block->n_keys * sizeof(short) ) ;
 | 
						|
  memcpy( &new_block->pointers[new_block->n_keys], old_block->pointers,
 | 
						|
         (old_block->n_keys + is_branch) * sizeof(short) ) ;
 | 
						|
 | 
						|
  if ( is_branch == 0 )  /* leaf blocks need one more copy */
 | 
						|
    new_block->pointers[t4->header.keys_max] = old_block->pointers[t4->header.keys_max] ;
 | 
						|
 | 
						|
  new_block->key_on = old_block->key_on - old_block->n_keys - is_branch ;
 | 
						|
  new_block->n_keys -= is_branch ;
 | 
						|
 | 
						|
  return new_block ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int S4FUNCTION t4rl_top( TAG4 *t4 )
 | 
						|
#else
 | 
						|
  int S4FUNCTION t4top( TAG4 *t4 )
 | 
						|
#endif
 | 
						|
{
 | 
						|
  int  rc ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4TOP ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  do
 | 
						|
  {
 | 
						|
    rc = t4up_to_root( t4 ) ;
 | 
						|
    if ( rc < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
    if ( rc != 2 )
 | 
						|
    {
 | 
						|
      ((B4BLOCK *)t4->blocks.last_node)->key_on = 0 ;
 | 
						|
      do
 | 
						|
      {
 | 
						|
        if ( (rc = t4down(t4)) < 0 )
 | 
						|
          return -1 ;
 | 
						|
        ((B4BLOCK *)t4->blocks.last_node)->key_on = 0 ;
 | 
						|
      } while ( rc == 0 ) ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( rc == 2 )   /* failed due to read while locked */
 | 
						|
      t4out_of_date( t4 ) ;
 | 
						|
  } while ( rc == 2 ) ;
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int S4FUNCTION t4top( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4TOP ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  if ( t4->header.descending )   /* if descending, go top means go bottom */
 | 
						|
    return t4rl_bottom( t4 ) ;
 | 
						|
  else
 | 
						|
    return t4rl_top( t4 ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int S4FUNCTION t4up( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4UP ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->blocks.last_node == 0 )
 | 
						|
    return 1 ;
 | 
						|
  l4add( &t4->saved, l4pop(&t4->blocks) ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION t4update( TAG4 *t4 )
 | 
						|
{
 | 
						|
  B4BLOCK *block_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4UPDATE ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  if ( t4update_header( t4 ) < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  for( block_on = 0 ;; )
 | 
						|
  {
 | 
						|
    block_on = (B4BLOCK *)l4next( &t4->saved ,block_on ) ;
 | 
						|
    if ( block_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( b4flush(block_on) < 0 )
 | 
						|
      return -1 ;
 | 
						|
  }
 | 
						|
 | 
						|
  for( block_on = 0 ;; )
 | 
						|
  {
 | 
						|
    block_on = (B4BLOCK *)l4next( &t4->blocks, block_on ) ;
 | 
						|
    if ( block_on == 0 )
 | 
						|
      break ;
 | 
						|
    if ( b4flush( block_on ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( t4->root_write )
 | 
						|
  {
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
    t4->header.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
#endif
 | 
						|
#ifdef S4NDX
 | 
						|
    if ( file4write( &t4->file, t4->header_offset, &t4->header.root, 2 * sizeof(long) ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    if ( file4write( &t4->file, t4->header_offset + 2*sizeof( short ),
 | 
						|
                    &t4->header.root, 2*sizeof(long) ) < 0 )  return -1 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
    t4->header.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
#endif
 | 
						|
    t4->root_write = 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int  S4FUNCTION t4up_to_root( TAG4 *t4 )
 | 
						|
{
 | 
						|
  LINK4 *link_on ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4UP_TO_ROOT ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  for ( ;; )
 | 
						|
  {
 | 
						|
    link_on = (LINK4 *)l4pop( &t4->blocks ) ;
 | 
						|
    if ( link_on == 0 )
 | 
						|
      return t4down(t4) ;
 | 
						|
    l4add( &t4->saved, link_on ) ;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4close( TAG4 *t4 )
 | 
						|
{
 | 
						|
  int final_rc ;
 | 
						|
  int save_attempts ;
 | 
						|
  DATA4 *d4 ;
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( t4->code_base, 1, E4_T4CLOSE ) )
 | 
						|
    return -1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  final_rc = e4set( t4->code_base, 0 ) ;
 | 
						|
  save_attempts = t4->code_base->lock_attempts ;
 | 
						|
  d4 = t4->index->data ;
 | 
						|
 | 
						|
  t4->code_base->lock_attempts = -1 ;
 | 
						|
 | 
						|
  if ( d4 )
 | 
						|
    if ( d4update( d4 ) < 0 )
 | 
						|
      final_rc = e4set( t4->code_base, 0 ) ;
 | 
						|
 | 
						|
#ifndef S4SINGLE
 | 
						|
  if ( t4->file_locked )
 | 
						|
  {
 | 
						|
    file4unlock( &t4->file, L4LOCK_POS, L4LOCK_POS ) ;
 | 
						|
    t4->file_locked = 0 ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  t4free_all( t4 ) ;
 | 
						|
 | 
						|
  if ( file4open_test( &t4->file ) )
 | 
						|
    if ( file4close( &t4->file ) < 0 )
 | 
						|
      final_rc = e4set( t4->code_base, 0 ) ;
 | 
						|
 | 
						|
  t4->code_base->lock_attempts = save_attempts ;
 | 
						|
  e4set( t4->code_base, final_rc ) ;
 | 
						|
 | 
						|
  return final_rc ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
long S4FUNCTION t4extend( TAG4 *t4 )
 | 
						|
{
 | 
						|
  long old_eof ;
 | 
						|
  CODE4 *c4 = t4->index->code_base ;
 | 
						|
 | 
						|
  if ( c4->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4->header.version == t4->header.old_version )
 | 
						|
    e4severe( e4info, E4_T4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  old_eof = t4->header.eof ;
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if (old_eof <= 0L )  e4severe( e4info, E4_T4EXTEND ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  t4->header.eof += B4BLOCK_SIZE / I4MULTIPLY ;
 | 
						|
  t4->root_write = 1 ;
 | 
						|
  return old_eof ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4SINGLE
 | 
						|
  if ( old_eof != 0 )   /* case where free-list exists */
 | 
						|
    t4->header.eof = 0L ;
 | 
						|
  else
 | 
						|
  {
 | 
						|
#endif
 | 
						|
    old_eof = file4len( &t4->file ) ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( old_eof <= t4->check_eof )
 | 
						|
      e4severe( e4info, E4_T4EXTEND ) ;
 | 
						|
    t4->check_eof = old_eof ;
 | 
						|
#endif
 | 
						|
    file4len_set( &t4->file, file4len( &t4->file ) + 1024 ) ; /* and extend the file */
 | 
						|
#ifdef S4SINGLE
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  return old_eof/512 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int S4FUNCTION t4go2( TAG4 *t4, char *ptr, long rec_num )
 | 
						|
{
 | 
						|
  int  rc ;
 | 
						|
  long rec ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
  int sv_mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 || ptr == 0 || rec_num < 1 )
 | 
						|
    e4severe( e4parm, E4_T4GO ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  rc = t4seek( t4, ptr, t4->header.key_len ) ;
 | 
						|
  if ( rc )
 | 
						|
    return rc ;
 | 
						|
 | 
						|
  for(;;)
 | 
						|
  {
 | 
						|
    rec = t4recno( t4 ) ;
 | 
						|
    if (rec == rec_num )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
    sv_mode = t4->code_base->mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
    rc = (int)t4skip( t4, 1L ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
#ifndef S4DETECT_OFF
 | 
						|
    t4->code_base->mode = sv_mode ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
    if ( rc == -1 )
 | 
						|
      return -1 ;
 | 
						|
    if ( rc == 0 )
 | 
						|
    {
 | 
						|
      b4go_eof( t4block( t4 ) ) ;
 | 
						|
      return r4found ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( (*t4->cmp)( t4key_data( t4 )->value, ptr, t4->header.key_len ) )
 | 
						|
      return r4found ;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TAG4 *S4FUNCTION t4open( DATA4 *d4, INDEX4 *i4ndx, char *file_name )
 | 
						|
{
 | 
						|
  CODE4  *c4 ;
 | 
						|
  INDEX4 *i4 ;
 | 
						|
  char   buf[258], buffer[1024] ;
 | 
						|
  char expr_buf[I4MAX_EXPR_SIZE + 1] ;
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  char *ptr, garbage ;
 | 
						|
#endif
 | 
						|
  TAG4 *t4 ;
 | 
						|
  int rc, len ;
 | 
						|
  FILE4SEQ_READ seq_read ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
  int old_tag_err ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4VBASIC
 | 
						|
  if ( c4parm_check( d4, 2, E4_T4OPEN ) )
 | 
						|
    return 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( d4 == 0 || file_name == 0 )
 | 
						|
    e4severe( e4parm, E4_T4OPEN ) ;
 | 
						|
 | 
						|
  u4name_piece( buf, sizeof( buf ), file_name, 0, 0 ) ;
 | 
						|
  old_tag_err = d4->code_base->tag_name_error ;
 | 
						|
  d4->code_base->tag_name_error = 0 ;
 | 
						|
  if ( d4tag( d4, buf ) )
 | 
						|
  {
 | 
						|
    e4( d4->code_base, e4info, E4_INFO_TAO ) ;
 | 
						|
    d4->code_base->tag_name_error = old_tag_err ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
  d4->code_base->tag_name_error = old_tag_err ;
 | 
						|
  d4->code_base->error_code = 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( d4->code_base->error_code < 0 )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  c4 = d4->code_base ;
 | 
						|
 | 
						|
  if ( i4ndx == 0 )   /* must create an index for the tag */
 | 
						|
  {
 | 
						|
    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 ;
 | 
						|
    }
 | 
						|
 | 
						|
    i4 = (INDEX4 *)mem4alloc( c4->index_memory ) ;
 | 
						|
    if ( i4 == 0 )
 | 
						|
    {
 | 
						|
      e4( c4, e4memory, 0 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
 | 
						|
    i4->code_base = c4 = d4->code_base ;
 | 
						|
    u4name_piece( i4->alias, sizeof( i4->alias ), file_name, 0, 0 ) ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    i4 = i4ndx ;
 | 
						|
 | 
						|
  if ( i4->block_memory == 0 )
 | 
						|
    i4->block_memory = mem4create( c4, c4->mem_start_block,
 | 
						|
                                  (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
 | 
						|
                                  (sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])),
 | 
						|
                                  c4->mem_expand_block, 0 ) ;
 | 
						|
 | 
						|
  if ( i4->block_memory == 0 )
 | 
						|
  {
 | 
						|
    i4close( i4 ) ;
 | 
						|
    if ( i4ndx == 0 )
 | 
						|
      mem4free( c4->index_memory, i4 ) ;
 | 
						|
    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 )
 | 
						|
    {
 | 
						|
      if ( i4ndx == 0 )
 | 
						|
        mem4free( c4->index_memory, i4 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  t4 = (TAG4 *)mem4alloc( c4->tag_memory ) ;
 | 
						|
  if ( t4 == 0 )
 | 
						|
  {
 | 
						|
    e4( c4, e4memory, 0 ) ;
 | 
						|
    if ( i4ndx == 0 )
 | 
						|
      mem4free( c4->index_memory, i4 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  u4ncpy( buf, file_name, sizeof( buf ) ) ;
 | 
						|
  c4upper(buf) ;
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4UNIX
 | 
						|
  u4name_ext( buf, sizeof(buf), "ndx", 0 ) ;
 | 
						|
#else
 | 
						|
  u4name_ext( buf, sizeof(buf), "NDX", 0 ) ;
 | 
						|
#endif
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4UNIX
 | 
						|
  u4name_ext( buf, sizeof(buf), "ntx", 0 ) ;
 | 
						|
#else
 | 
						|
  u4name_ext( buf, sizeof(buf), "NTX", 0 ) ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = file4open( &t4->file, c4, buf, 1 ) ;
 | 
						|
  if ( rc != 0 )
 | 
						|
  {
 | 
						|
    if ( i4ndx == 0 )
 | 
						|
      mem4free( c4->index_memory, i4 ) ;
 | 
						|
    mem4free( c4->tag_memory, t4 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  file4seq_read_init( &seq_read, &t4->file, 0, buffer, 1024 ) ;
 | 
						|
#ifdef S4NDX
 | 
						|
  if ( file4seq_read_all( &seq_read, &t4->header.root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
  {
 | 
						|
    if ( i4ndx == 0 )
 | 
						|
      mem4free( c4->index_memory, i4 ) ;
 | 
						|
    file4close( &t4->file ) ;
 | 
						|
    mem4free( c4->tag_memory, t4 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
  t4->header.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
  t4->header.key_len = x4reverse_short( (void *)&t4->header.key_len ) ;
 | 
						|
  t4->header.keys_max = x4reverse_short( (void *)&t4->header.keys_max ) ;
 | 
						|
  t4->header.int_or_date = x4reverse_short( (void *)&t4->header.int_or_date ) ;
 | 
						|
  t4->header.group_len = x4reverse_short( (void *)&t4->header.group_len ) ;
 | 
						|
  t4->header.dummy = x4reverse_short( (void *)&t4->header.dummy ) ;
 | 
						|
  t4->header.unique = x4reverse_short( (void *)&t4->header.unique ) ;
 | 
						|
#endif
 | 
						|
  t4->header.type = 0 ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  if ( file4seq_read_all( &seq_read, &t4->header.sign, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
  {
 | 
						|
    if ( i4ndx == 0 )
 | 
						|
      mem4free( c4->index_memory, i4 ) ;
 | 
						|
    file4close( &t4->file ) ;
 | 
						|
    mem4free( c4->tag_memory, t4 ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  t4->header.sign = x4reverse_short( (void *)&t4->header.sign ) ;
 | 
						|
  t4->header.version = x4reverse_short( (void *)&t4->header.version ) ;
 | 
						|
  t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
  t4->header.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
  t4->header.group_len = x4reverse_short( (void *)&t4->header.group_len ) ;
 | 
						|
  t4->header.key_len = x4reverse_short( (void *)&t4->header.key_len ) ;
 | 
						|
  t4->header.key_dec = x4reverse_short( (void *)&t4->header.key_dec ) ;
 | 
						|
  t4->header.keys_max = x4reverse_short( (void *)&t4->header.keys_max ) ;
 | 
						|
  t4->header.keys_half = x4reverse_short( (void *)&t4->header.keys_half ) ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
  t4->header.header_offset = 0 ;
 | 
						|
 | 
						|
  /* Perform some checks */
 | 
						|
  if ( t4->header.key_len   > I4MAX_KEY_SIZE    ||
 | 
						|
      t4->header.key_len  <= 0  ||
 | 
						|
#ifdef S4CLIPPER
 | 
						|
      t4->header.keys_max  != 2* t4->header.keys_half  ||
 | 
						|
      t4->header.keys_half <= 0               ||
 | 
						|
      t4->header.group_len != t4->header.key_len+ 8  ||
 | 
						|
      (t4->header.sign != 0x6        &&  t4->header.sign != 0x106) )
 | 
						|
#else
 | 
						|
    t4->header.key_len+8 > t4->header.group_len  ||
 | 
						|
      t4->header.keys_max  < 4  ||
 | 
						|
        t4->header.keys_max  > 50  ||
 | 
						|
          t4->header.eof <= 0L )
 | 
						|
#endif
 | 
						|
{
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
  e4describe( c4, e4index, buf, "t4open()", "perform check failure" ) ;
 | 
						|
#endif
 | 
						|
  e4( c4, e4index, buf ) ;
 | 
						|
  if ( i4ndx == 0 )
 | 
						|
    mem4free( c4->index_memory, i4 ) ;
 | 
						|
  file4close( &t4->file ) ;
 | 
						|
  mem4free( c4->tag_memory, t4 ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
t4->index = i4 ;
 | 
						|
t4->code_base = c4 ;
 | 
						|
t4->cmp = (S4CMP_FUNCTION *)u4memcmp ;
 | 
						|
t4->header.root = -1 ;
 | 
						|
t4->header.old_version = t4->header.version ;
 | 
						|
 | 
						|
u4name_piece( t4->alias, sizeof(t4->alias), file_name, 0, 0 ) ;
 | 
						|
#ifdef S4UNIX
 | 
						|
c4upper( t4->alias ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
file4seq_read_all( &seq_read, expr_buf, sizeof( expr_buf ) - 1 ) ;
 | 
						|
c4trim_n( expr_buf, sizeof( expr_buf ) ) ;
 | 
						|
t4->expr = expr4parse( d4, expr_buf ) ;
 | 
						|
if ( t4->expr == 0 )
 | 
						|
{
 | 
						|
  if ( i4ndx == 0 )
 | 
						|
    mem4free( c4->index_memory, i4 ) ;
 | 
						|
  file4close( &t4->file ) ;
 | 
						|
  mem4free( c4->tag_memory, t4 ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#ifdef S4CLIPPER
 | 
						|
t4->expr->key_len = t4->header.key_len ;
 | 
						|
t4->expr->key_dec = t4->header.key_dec ;
 | 
						|
#endif
 | 
						|
 | 
						|
len = expr4key_len( t4->expr ) ;
 | 
						|
if ( len < 0 )
 | 
						|
{
 | 
						|
  e4describe( c4, e4info, E4_T4OPEN, E4_INFO_KEY, (char *)0 ) ;
 | 
						|
  if ( i4ndx == 0 )
 | 
						|
    mem4free( c4->index_memory, i4 ) ;
 | 
						|
  file4close( &t4->file ) ;
 | 
						|
  mem4free( c4->tag_memory, t4 ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
t4->header.type = (char) expr4type(t4->expr) ;
 | 
						|
if ( t4->header.key_len != (short) len )
 | 
						|
{
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
  e4describe( c4, e4index, i4->file.name, "t4open()", "expression/header length mismatch" ) ;
 | 
						|
#endif
 | 
						|
  e4( c4, e4index, i4->file.name ) ;
 | 
						|
  if ( i4ndx == 0 )
 | 
						|
    mem4free( c4->index_memory, i4 ) ;
 | 
						|
  file4close( &t4->file ) ;
 | 
						|
  mem4free( c4->tag_memory, t4 ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
file4seq_read_all( &seq_read, &t4->header.unique, sizeof( t4->header.unique ) ) ;
 | 
						|
file4seq_read_all( &seq_read, &garbage, sizeof( garbage ) ) ;
 | 
						|
file4seq_read_all( &seq_read, &t4->header.descending, sizeof( t4->header.descending ) ) ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
t4->header.unique = x4reverse_short( (void *)&t4->header.unique ) ;
 | 
						|
t4->header.descending = x4reverse_short( (void *)&t4->header.descending ) ;
 | 
						|
#endif
 | 
						|
file4seq_read_all( &seq_read, expr_buf, sizeof( expr_buf ) - 1 ) ;
 | 
						|
c4trim_n( expr_buf, sizeof( expr_buf ) ) ;
 | 
						|
if ( expr_buf[0] != 0 )
 | 
						|
{
 | 
						|
  t4->filter = expr4parse( d4, expr_buf ) ;
 | 
						|
  if ( t4->filter != 0 )
 | 
						|
  {
 | 
						|
    len = expr4key( t4->filter, &ptr ) ;
 | 
						|
    if ( len < 0 )
 | 
						|
    {
 | 
						|
      if ( i4ndx == 0 )
 | 
						|
        mem4free( c4->index_memory, i4 ) ;
 | 
						|
      file4close( &t4->file ) ;
 | 
						|
      mem4free( c4->tag_memory, t4 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
    if ( expr4type( t4->filter ) != 'L' )
 | 
						|
    {
 | 
						|
      if ( i4ndx == 0 )
 | 
						|
        mem4free( c4->index_memory, i4 ) ;
 | 
						|
      file4close( &t4->file ) ;
 | 
						|
      mem4free( c4->tag_memory, t4 ) ;
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
      e4describe( c4, e4index, E4_INDEX_FIL, i4->file.name, "Filter expression not logical" ) ;
 | 
						|
#endif
 | 
						|
      e4describe( c4, e4index, E4_INDEX_FIL, i4->file.name, (char *) 0 ) ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
if( t4->header.unique )
 | 
						|
  t4->unique_error = c4->default_unique_error ;
 | 
						|
  l4add( &i4->tags, t4 ) ;   /* add the tag to its index list */
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
  t4init_seek_conv(t4,t4->header.type) ;
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  t4init_seek_conv( t4, (char) expr4type(t4->expr) ) ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( i4->block_memory == 0 )
 | 
						|
  i4->block_memory = mem4create( c4, c4->mem_start_block,
 | 
						|
                                (sizeof(B4BLOCK)) + B4BLOCK_SIZE -
 | 
						|
                                (sizeof(B4KEY_DATA)) - (sizeof(short)) - (sizeof(char[2])),
 | 
						|
                                c4->mem_expand_block, 0 ) ;
 | 
						|
 | 
						|
                                if ( i4->block_memory == 0 )
 | 
						|
{
 | 
						|
  e4( c4, e4memory, E4_T4OPEN ) ;
 | 
						|
  if ( i4ndx == 0 )
 | 
						|
    mem4free( c4->index_memory, i4 ) ;
 | 
						|
  file4close( &t4->file ) ;
 | 
						|
  mem4free( c4->tag_memory, t4 ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
if ( i4ndx == 0 )
 | 
						|
{
 | 
						|
  i4->data = d4 ;
 | 
						|
  l4add( &d4->indexes, i4 ) ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
file4optimize( &t4->file, c4->optimize, OPT4INDEX ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
return t4 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4CLIPPER
 | 
						|
int S4FUNCTION t4shrink( TAG4 *t4, long block_no )
 | 
						|
{
 | 
						|
#ifdef S4SINGLE
 | 
						|
  t4->header.eof = block_no * 512 ;
 | 
						|
#endif
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int S4FUNCTION t4update_header( TAG4 *t4 )
 | 
						|
{
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  I4IND_HEAD_WRITE swap ;
 | 
						|
#endif
 | 
						|
  if ( t4->index->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  /*   t4->header.version = t4->header.old_version + 2 ; */
 | 
						|
 | 
						|
  if ( t4->header.old_version != t4->header.version )
 | 
						|
  {
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    swap.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
    swap.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
    swap.key_len = x4reverse_short( (void *)&t4->header.key_len ) ;
 | 
						|
    swap.keys_max = x4reverse_short( (void *)&t4->header.keys_max ) ;
 | 
						|
    swap.int_or_date = x4reverse_short( (void *)&t4->header.int_or_date ) ;
 | 
						|
    swap.group_len = x4reverse_short( (void *)&t4->header.group_len ) ;
 | 
						|
    swap.dummy = x4reverse_short( (void *)&t4->header.dummy ) ;
 | 
						|
    swap.unique = x4reverse_short( (void *)&t4->header.unique ) ;
 | 
						|
 | 
						|
    if ( file4write(&t4->file, 0L, &swap, sizeof(I4IND_HEAD_WRITE)) < 0) return -1 ;
 | 
						|
 | 
						|
    t4->header.version = x4reverse_long( (void *)&t4->header.version ) ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE,
 | 
						|
                    &t4->header.version, sizeof(t4->header.version)) < 0) return -1 ;
 | 
						|
    t4->header.version = x4reverse_long( (void *)&t4->header.version ) ;
 | 
						|
#else
 | 
						|
    if ( file4write(&t4->file, 0L, &t4->header.root, sizeof(I4IND_HEAD_WRITE) ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE,
 | 
						|
                    &t4->header.version, sizeof(t4->header.version)) < 0) return -1 ;
 | 
						|
#endif
 | 
						|
#else
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    swap.sign = x4reverse_short( (void *)&t4->header.sign ) ;
 | 
						|
    swap.version = x4reverse_short( (void *)&t4->header.version ) ;
 | 
						|
    swap.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
    swap.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
    swap.group_len = x4reverse_short( (void *)&t4->header.group_len ) ;
 | 
						|
    swap.key_len = x4reverse_short( (void *)&t4->header.key_len ) ;
 | 
						|
    swap.key_dec = x4reverse_short( (void *)&t4->header.key_dec ) ;
 | 
						|
    swap.keys_max = x4reverse_short( (void *)&t4->header.keys_max ) ;
 | 
						|
    swap.keys_half = x4reverse_short( (void *)&t4->header.keys_half ) ;
 | 
						|
 | 
						|
    if ( file4write(&t4->file, 0L, &swap, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0)
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
    t4->header.unique = x4reverse_short( (void *)&t4->header.unique ) ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &t4->header.unique, sizeof(t4->header.unique)) < 0)
 | 
						|
      return -1 ;
 | 
						|
    t4->header.unique = x4reverse_short( (void *)&t4->header.unique ) ;
 | 
						|
 | 
						|
    t4->header.descending = x4reverse_short( (void *)&t4->header.descending ) ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(t4->header.unique) + 1, &t4->header.descending, sizeof(t4->header.descending)) < 0)
 | 
						|
      return -1 ;
 | 
						|
    t4->header.descending = x4reverse_short( (void *)&t4->header.descending ) ;
 | 
						|
#else
 | 
						|
    if ( file4write(&t4->file, 0L, &t4->header.sign, 2 * sizeof( long ) + 2 * sizeof( short ) ) < 0)
 | 
						|
      return -1 ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE, &t4->header.unique, sizeof(t4->header.unique)) < 0)
 | 
						|
      return -1 ;
 | 
						|
    if ( file4write(&t4->file, sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE + sizeof(t4->header.unique) + 1, &t4->header.descending, sizeof(t4->header.descending)) < 0)
 | 
						|
      return -1 ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
    t4->header.old_version = t4->header.version ;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
int S4FUNCTION t4do_version_check( TAG4 *t4, int do_seek, int update_version )
 | 
						|
{
 | 
						|
#ifndef S4SINGLE
 | 
						|
  int rc, need_seek ;
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( t4 == 0 )
 | 
						|
    e4severe( e4parm, E4_T4DO_VERSION ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->code_base->error_code < 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  if ( t4->file.is_exclusive )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  /* make sure read from disk */
 | 
						|
  if ( t4->file.do_buffer )
 | 
						|
    t4->code_base->opt.force_current = 1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
  rc = file4read_all( &t4->file,  sizeof(I4IND_HEAD_WRITE) + I4MAX_EXPR_SIZE,
 | 
						|
                     &t4->header.version, sizeof(t4->header.version ) ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( t4->file.do_buffer )
 | 
						|
    t4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
  if ( rc < 0 )
 | 
						|
    return rc ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  t4->header.version = x4reverse_long( (void *)&t4->header.version ) ;
 | 
						|
#endif
 | 
						|
#else
 | 
						|
  rc = file4read_all( &t4->file, 0L, &t4->header.sign, 2 * sizeof( short ) + 2 * sizeof( long ) ) ;
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( t4->file.do_buffer )
 | 
						|
    t4->code_base->opt.force_current = 0 ;
 | 
						|
#endif
 | 
						|
  if ( rc < 0 )
 | 
						|
    return rc ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  t4->header.sign = x4reverse_short( (void *)&t4->header.sign ) ;
 | 
						|
  t4->header.version = x4reverse_short( (void *)&t4->header.version ) ;
 | 
						|
  t4->header.root = x4reverse_long( (void *)&t4->header.root ) ;
 | 
						|
  t4->header.eof = x4reverse_long( (void *)&t4->header.eof ) ;
 | 
						|
  t4->header.group_len = x4reverse_short( (void *)&t4->header.group_len ) ;
 | 
						|
  t4->header.key_len = x4reverse_short( (void *)&t4->header.key_len ) ;
 | 
						|
  t4->header.key_dec = x4reverse_short( (void *)&t4->header.key_dec ) ;
 | 
						|
  t4->header.keys_max = x4reverse_short( (void *)&t4->header.keys_max ) ;
 | 
						|
  t4->header.keys_half = x4reverse_short( (void *)&t4->header.keys_half ) ;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( t4->header.version == t4->header.old_version )
 | 
						|
    return 0 ;
 | 
						|
 | 
						|
  if ( update_version == 1 )
 | 
						|
    t4->header.old_version = t4->header.version ;
 | 
						|
  else
 | 
						|
    t4->header.version = t4->header.old_version ;
 | 
						|
 | 
						|
  /* remember the old position */
 | 
						|
  need_seek = 0 ;
 | 
						|
  if ( do_seek )
 | 
						|
  {
 | 
						|
    b4 = t4block( t4 ) ;
 | 
						|
    if ( b4 != 0 )
 | 
						|
    {
 | 
						|
      if ( t4eof( t4 ) )
 | 
						|
        need_seek = 2 ;
 | 
						|
      else
 | 
						|
        if ( b4leaf( b4 ) && b4->n_keys != 0 )
 | 
						|
        {
 | 
						|
          memcpy( t4->code_base->saved_key, b4key( b4, b4->key_on ), t4->header.key_len + 2 * sizeof( long ) ) ;
 | 
						|
          need_seek = 1 ;
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ( t4free_all( t4 ) < 0 )  /* Should be a memory operation only */
 | 
						|
    e4severe( e4result, E4_T4DO_VERSION ) ;
 | 
						|
 | 
						|
  switch( need_seek )
 | 
						|
  {
 | 
						|
  case 1:
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
    if ( t4go( t4, ((B4KEY_DATA *)t4->code_base->saved_key)->value, ((B4KEY_DATA *)t4->code_base->saved_key)->num ) != 0 )
 | 
						|
      e4severe( e4index, "t4go() failed in t4do_version_check()" ) ;
 | 
						|
#else
 | 
						|
    t4go( t4, ((B4KEY_DATA *)t4->code_base->saved_key)->value, ((B4KEY_DATA *)t4->code_base->saved_key)->num ) ;
 | 
						|
#endif
 | 
						|
    break ;
 | 
						|
  case 2:
 | 
						|
    t4go_eof( t4 ) ;
 | 
						|
    break ;
 | 
						|
  }
 | 
						|
 | 
						|
#endif
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION t4version_check( TAG4 *t4, int do_seek, int update_version )
 | 
						|
{
 | 
						|
#ifndef S4OPTIMIZE_OFF
 | 
						|
  if ( t4->index->file.do_buffer == 0 )
 | 
						|
#endif
 | 
						|
#ifndef S4SINGLE
 | 
						|
    if ( t4lock_test( t4 ) == 0 )
 | 
						|
#endif
 | 
						|
      return t4do_version_check( t4, do_seek, update_version ) ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* N4OTHER */
 | 
						|
#endif  /* S4INDEX_OFF */
 | 
						|
 | 
						|
 | 
						|
#ifdef S4VB_DOS
 | 
						|
#ifdef N4OTHER
 | 
						|
 | 
						|
TAG4 S4PTR* S4FUNCTION t4open_v(DATA4 *d4, char *name)
 | 
						|
{
 | 
						|
  return t4open( d4, 0, c4str(name) ) ;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
#endif
 |