which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@1078 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1992 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1992 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* b4block.c  (c)Copyright Sequiter Software Inc., 1990-1994.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifndef S4UNIX
 | 
						|
#ifdef __TURBOC__
 | 
						|
#pragma hdrstop
 | 
						|
#endif  /* __TURBOC__ */
 | 
						|
#endif  /* S4UNIX */
 | 
						|
 | 
						|
#ifndef S4INDEX_OFF
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
#define S4REVERSE_FUNC
 | 
						|
#endif
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
#define S4REVERSE_FUNC
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4REVERSE_FUNC
 | 
						|
short S4FUNCTION x4reverse_short( void * val )
 | 
						|
{
 | 
						|
  unsigned char out[2], *at_val ;
 | 
						|
  at_val = (unsigned char *)val ;
 | 
						|
 | 
						|
  out[0] = at_val[1] ;
 | 
						|
  out[1] = at_val[0] ;
 | 
						|
 | 
						|
  return (*(short *)out ) ;
 | 
						|
}
 | 
						|
 | 
						|
S4LONG S4FUNCTION x4reverse_long( void * val )
 | 
						|
{
 | 
						|
  unsigned char out[4], *at_val ;
 | 
						|
  at_val = (unsigned char *)val ;
 | 
						|
 | 
						|
#ifdef S4BYTEORDER_2301
 | 
						|
  out[0] = at_val[2] ;
 | 
						|
  out[1] = at_val[3] ;
 | 
						|
  out[2] = at_val[0] ;
 | 
						|
  out[3] = at_val[1] ;
 | 
						|
#else
 | 
						|
  out[0] = at_val[3] ;
 | 
						|
  out[1] = at_val[2] ;
 | 
						|
  out[2] = at_val[1] ;
 | 
						|
  out[3] = at_val[0] ;
 | 
						|
#endif
 | 
						|
 | 
						|
  return *(S4LONG *)out ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
B4BLOCK * S4FUNCTION b4alloc( TAG4 *t4, long fb )
 | 
						|
{
 | 
						|
  B4BLOCK *b4 ;
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  short offset ;
 | 
						|
  int i ;
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
 | 
						|
  b4 = (B4BLOCK *)mem4alloc2( t4->index->block_memory, t4->code_base ) ;
 | 
						|
  if ( b4 == 0 )
 | 
						|
  {
 | 
						|
    e4( t4->code_base, e4memory, E4_B4ALLOC ) ;
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  b4->tag = t4 ;
 | 
						|
  b4->file_block = fb ;
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  offset = ( b4->tag->header.keys_max + 2 +
 | 
						|
            (( b4->tag->header.keys_max / 2) * 2 != b4->tag->header.keys_max ) )
 | 
						|
    * sizeof(short) ;
 | 
						|
  for ( i = 0 ; i <= b4->tag->header.keys_max ; i++ )
 | 
						|
    b4->pointers[i] = (short)(( b4->tag->header.group_len * i )) + offset ;
 | 
						|
  b4->data = (B4KEY_DATA *) ((char *)&b4->n_keys + b4->pointers[0]) ;  /* first entry */
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
  b4->built_key = (B4KEY_DATA *)u4alloc_er( t4->code_base, sizeof(long) + t4->header.key_len + 1 ) ;
 | 
						|
  b4->built_on = -1 ;
 | 
						|
#endif  /* S4FOX */
 | 
						|
 | 
						|
  return b4 ;
 | 
						|
}
 | 
						|
 | 
						|
void S4FUNCTION b4free( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
#ifdef S4FOX
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( b4->changed )
 | 
						|
    e4severe( e4info, E4_B4FREE ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
  u4free( b4->built_key ) ;
 | 
						|
#endif /* S4FOX */
 | 
						|
 | 
						|
  mem4free( b4->tag->index->block_memory, b4 ) ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION b4find( TAG4 *tag, long f_block, B4BLOCK *out_block )
 | 
						|
{
 | 
						|
  B4BLOCK *cur_block ;
 | 
						|
 | 
						|
  cur_block = (B4BLOCK *)l4first( &tag->blocks ) ;
 | 
						|
  if ( cur_block != 0 )
 | 
						|
    do
 | 
						|
    {
 | 
						|
      if ( cur_block->file_block == f_block )
 | 
						|
      {
 | 
						|
        memcpy( &(out_block->changed), &(cur_block->changed), (B4BLOCK_SIZE + 2*sizeof(int)) ) ;
 | 
						|
        out_block->changed = 0 ;
 | 
						|
        return( 0 ) ;
 | 
						|
      }
 | 
						|
      cur_block = (B4BLOCK *)l4next( &tag->blocks, cur_block ) ;
 | 
						|
    } while ( cur_block != 0 ) ;
 | 
						|
 | 
						|
  cur_block = (B4BLOCK *)l4first( &tag->saved ) ;
 | 
						|
 | 
						|
  if ( cur_block != 0 )
 | 
						|
    do
 | 
						|
    {
 | 
						|
      if ( cur_block->file_block == f_block )
 | 
						|
      {
 | 
						|
        memcpy( &(out_block->changed), &(cur_block->changed), (B4BLOCK_SIZE + 2*sizeof(int)) ) ;
 | 
						|
        out_block->changed = 0 ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
      cur_block = (B4BLOCK *)l4next( &tag->saved, cur_block ) ;
 | 
						|
    } while ( cur_block != 0 ) ;
 | 
						|
 | 
						|
  return -1 ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION b4get_last_key( B4BLOCK *b4, char *key_info )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
  long block_down ;
 | 
						|
  B4BLOCK *temp_block ;
 | 
						|
  char *key_data ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( b4leaf( b4 ) )
 | 
						|
    e4severe( e4info, E4_B4GET_LK ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  block_down = b4key( b4, b4->key_on )->pointer ;
 | 
						|
 | 
						|
  temp_block = b4alloc( b4->tag, block_down ) ;
 | 
						|
  if ( temp_block == 0 )
 | 
						|
    return -1 ;
 | 
						|
 | 
						|
  do
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( block_down <= 0L )
 | 
						|
      e4severe( e4info, E4_B4GET_LK ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    if ( b4find( b4->tag, block_down, temp_block ) < 0 )
 | 
						|
    {
 | 
						|
      if ( file4len( &b4->tag->file ) <= I4MULTIPLY * block_down )
 | 
						|
      {
 | 
						|
        b4free(temp_block) ;
 | 
						|
        return -1 ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if ( file4read_all( &b4->tag->file, I4MULTIPLY * block_down, &temp_block->n_keys, B4BLOCK_SIZE ) < 0 )
 | 
						|
        {
 | 
						|
          b4free(temp_block) ;
 | 
						|
          return -1 ;
 | 
						|
        }
 | 
						|
        temp_block->file_block = block_down ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    temp_block->key_on = b4lastpos( temp_block ) ;
 | 
						|
    block_down = b4key( temp_block, temp_block->key_on )->pointer ;
 | 
						|
  } while( !( b4leaf( temp_block ) ) ) ;
 | 
						|
 | 
						|
  key_data = (char *)b4key_key( temp_block, temp_block->key_on ) ;
 | 
						|
 | 
						|
  if( strcmp( key_info, key_data ) != 0 )
 | 
						|
  {
 | 
						|
    strcpy( key_info, key_data ) ;
 | 
						|
    rc = 1 ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    rc = 0 ;
 | 
						|
 | 
						|
  b4free( temp_block ) ;
 | 
						|
 | 
						|
  return rc ;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_WRITE */
 | 
						|
 | 
						|
#endif  /* S4NDX */
 | 
						|
 | 
						|
#ifdef S4MDX
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION b4flush( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
  INDEX4 *i4 ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  char *swap, *swap_ptr ;
 | 
						|
  int i ;
 | 
						|
  S4LONG long_val ;
 | 
						|
  short short_val ;
 | 
						|
#endif  /* S4BYTE_SWAP */
 | 
						|
 | 
						|
  if ( b4->changed )
 | 
						|
  {
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
    if ( b4verify( b4 ) == -1 )
 | 
						|
      e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4flush()", "" ) ;
 | 
						|
#endif
 | 
						|
    i4 = b4->tag->index ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    swap = (char *) u4alloc_er( b4->tag->code_base, b4->tag->index->header.block_rw ) ;
 | 
						|
    if ( swap == 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
    memcpy( (void *)swap, (void *)&b4->n_keys, b4->tag->index->header.block_rw ) ;
 | 
						|
    /* position swap_ptr at beginning of B4KEY's */
 | 
						|
    swap_ptr = swap ;
 | 
						|
    swap_ptr += 6 + sizeof(short) ;
 | 
						|
    /* move through all B4KEY's to swap 'long' */
 | 
						|
    for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | 
						|
    {
 | 
						|
      long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
      swap_ptr += b4->tag->header.group_len ;
 | 
						|
    }
 | 
						|
    /* mark last_pointer */
 | 
						|
    if ( !b4leaf( b4 ) )
 | 
						|
    {
 | 
						|
      long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
    }
 | 
						|
    /* swap the num_keys value */
 | 
						|
    short_val = x4reverse_short( (void *)swap ) ;
 | 
						|
    memcpy( swap, (void *) &short_val, sizeof(short) ) ;
 | 
						|
 | 
						|
    rc = file4write( &i4->file, (long)b4->file_block*I4MULTIPLY, swap, i4->header.block_rw) ;
 | 
						|
    u4free( swap ) ;
 | 
						|
#else
 | 
						|
    rc = file4write( &i4->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, i4->header.block_rw) ;
 | 
						|
#endif  /* S4BYTE_SWAP */
 | 
						|
 | 
						|
    if ( rc < 0 )
 | 
						|
      return rc ;
 | 
						|
    b4->changed = 0 ;
 | 
						|
  }
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
void S4FUNCTION b4go_eof( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  b4->key_on = b4->n_keys ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
void S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r )
 | 
						|
{
 | 
						|
#ifdef S464BIT
 | 
						|
  S4LONG temp_r ;
 | 
						|
#endif
 | 
						|
  int left_len ;
 | 
						|
  B4KEY_DATA *data_ptr, *next_ptr ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( k == 0 || r <= 0L )
 | 
						|
    e4severe( e4parm, E4_B4INSERT ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  data_ptr = b4key( b4, b4->key_on ) ;
 | 
						|
  next_ptr = b4key( b4, b4->key_on+1 ) ;
 | 
						|
  left_len = b4->tag->index->header.block_rw - ( b4->key_on + 1 ) * b4->tag->header.group_len - sizeof(short) - sizeof(char[6]) ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( b4->key_on < 0  ||  b4->key_on > b4->n_keys  ||  left_len < 0 )
 | 
						|
    e4severe( e4info, E4_B4INSERT ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  memmove( next_ptr, data_ptr, left_len ) ;
 | 
						|
  b4->n_keys++ ;
 | 
						|
  memcpy( data_ptr->value, k, b4->tag->header.key_len ) ;
 | 
						|
#ifdef S464BIT
 | 
						|
  temp_r = (S4LONG) r ;
 | 
						|
  memcpy( (void *)&data_ptr->num, (void *)&temp_r, sizeof(temp_r) ) ;
 | 
						|
#else
 | 
						|
  memcpy( (void *)&data_ptr->num, (void *)&r, sizeof(r) ) ;
 | 
						|
#endif
 | 
						|
  b4->changed = 1 ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
 | 
						|
{
 | 
						|
  return  (B4KEY_DATA *) ((char *) &b4->info.num + b4->tag->header.group_len * i_key) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
 | 
						|
{
 | 
						|
  return (unsigned char *)( ( (B4KEY_DATA *)( (char *)&b4->info.num + b4->tag->header.group_len * i_key ) )->value ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
int S4FUNCTION b4lastpos( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  if ( b4leaf(b4) )
 | 
						|
    return b4->n_keys - 1 ;
 | 
						|
  else
 | 
						|
    return b4->n_keys ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
int S4FUNCTION b4leaf( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  return( b4key( b4, b4->n_keys )->num == 0L ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
long S4FUNCTION b4recno( B4BLOCK *b4, int i )
 | 
						|
{
 | 
						|
  return b4key( b4, i )->num ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
void S4FUNCTION b4remove( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  B4KEY_DATA *key_cur, *key_next ;
 | 
						|
  int left_len ;
 | 
						|
 | 
						|
  key_cur = b4key( b4, b4->key_on ) ;
 | 
						|
  key_next = b4key( b4, b4->key_on + 1 ) ;
 | 
						|
 | 
						|
  left_len = b4->tag->index->header.block_rw - sizeof(b4->n_keys) - sizeof(b4->dummy)
 | 
						|
    - (b4->key_on+1) * b4->tag->header.group_len ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( b4->key_on < 0  ||  b4->key_on > b4lastpos(b4) )
 | 
						|
    e4severe( e4info, E4_B4REMOVE ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  if ( left_len > 0 )
 | 
						|
    memmove( key_cur, key_next, left_len ) ;
 | 
						|
 | 
						|
  b4->n_keys-- ;
 | 
						|
  b4->changed = 1 ;
 | 
						|
 | 
						|
  if ( b4leaf( b4 ) )
 | 
						|
    memset( b4key_key( b4, b4->n_keys ), 0, b4->tag->header.key_len ) ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
  else
 | 
						|
    if ( b4->n_keys < b4->tag->header.keys_max )
 | 
						|
      memset( b4key_key( b4, b4->n_keys ), 0, b4->tag->header.key_len ) ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
int S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
 | 
						|
{
 | 
						|
  int rc, key_lower, key_upper, save_rc, key_cur ;
 | 
						|
  S4CMP_FUNCTION *cmp;
 | 
						|
 | 
						|
  /* key_cur must be between  key_lower and  key_upper */
 | 
						|
  key_lower = -1 ;
 | 
						|
  key_upper = b4->n_keys ;
 | 
						|
 | 
						|
  cmp = b4->tag->cmp ;
 | 
						|
 | 
						|
  if ( key_upper == 0 )
 | 
						|
  {
 | 
						|
    b4->key_on = 0 ;
 | 
						|
    return r4after ;
 | 
						|
  }
 | 
						|
 | 
						|
  save_rc = 1 ;
 | 
						|
 | 
						|
  for(;;)  /* Repeat until the key is found */
 | 
						|
  {
 | 
						|
    key_cur  = (key_upper + key_lower) / 2  ;
 | 
						|
    rc = (*cmp)( b4key_key(b4,key_cur), search_value, len ) ;
 | 
						|
 | 
						|
    if ( rc >= 0 )
 | 
						|
    {
 | 
						|
      key_upper = key_cur ;
 | 
						|
      save_rc = rc ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      key_lower = key_cur ;
 | 
						|
 | 
						|
    if ( key_lower >= (key_upper-1) )  /* then there is no exact match */
 | 
						|
    {
 | 
						|
      b4->key_on =  key_upper ;
 | 
						|
      if ( save_rc )
 | 
						|
        return r4after ;
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* S4MDX */
 | 
						|
int S4FUNCTION b4skip( B4BLOCK *b4, long n )
 | 
						|
{
 | 
						|
  int num_left ;
 | 
						|
 | 
						|
  if ( n > 0 )
 | 
						|
  {
 | 
						|
    num_left = b4->n_keys - b4->key_on ;
 | 
						|
    if ( b4leaf(b4) )
 | 
						|
      if ( num_left != 0 )
 | 
						|
        num_left -- ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    num_left = -b4->key_on ;
 | 
						|
 | 
						|
  if ( ( n <= 0L ) ?  ((long) num_left <= n)  :  ((long) num_left >= n)  )
 | 
						|
  {
 | 
						|
    b4->key_on = b4->key_on+ (int)n ;
 | 
						|
    return (int)n ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    b4->key_on = b4->key_on + num_left ;
 | 
						|
    return num_left ;
 | 
						|
  }
 | 
						|
}
 | 
						|
#endif  /* S4MDX */
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
void S4FUNCTION b4leaf_init( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  TAG4 *t4 ;
 | 
						|
  int t_len ;
 | 
						|
  unsigned c_len, key_len ;
 | 
						|
  unsigned long ff, r_len ;
 | 
						|
 | 
						|
  t4 = b4->tag ;
 | 
						|
  key_len = t4->header.key_len ;
 | 
						|
  ff = 0xFFFFFFFF ;
 | 
						|
 | 
						|
  for ( c_len = 0 ; key_len ; key_len >>= 1, c_len++ ) ;
 | 
						|
 | 
						|
  key_len = t4->header.key_len ;
 | 
						|
  b4->node_hdr.trail_cnt_len = b4->node_hdr.dup_cnt_len = (unsigned char)c_len ;
 | 
						|
 | 
						|
  b4->node_hdr.trail_byte_cnt = (unsigned char)((unsigned char)0xFF >> (8 - c_len % 8) ) ;
 | 
						|
  b4->node_hdr.dup_byte_cnt = b4->node_hdr.trail_byte_cnt ;
 | 
						|
 | 
						|
  r_len = d4reccount( b4->tag->index->data ) ;
 | 
						|
 | 
						|
  for ( c_len = 0 ; r_len ; r_len>>=1, c_len++ ) ;
 | 
						|
 | 
						|
  b4->node_hdr.rec_num_len = (unsigned char) (c_len + (( 8 - ( 2 * (unsigned int)b4->node_hdr.trail_cnt_len % 8 )) % 8)) ;
 | 
						|
  if ( b4->node_hdr.rec_num_len < 12 )
 | 
						|
    b4->node_hdr.rec_num_len = 12 ;
 | 
						|
 | 
						|
  for( t_len = b4->node_hdr.rec_num_len + b4->node_hdr.trail_cnt_len + b4->node_hdr.dup_cnt_len ;
 | 
						|
      (t_len / 8)*8 != t_len ; t_len++, b4->node_hdr.rec_num_len++ ) ;  /* make at an 8-bit offset */
 | 
						|
 | 
						|
  r_len = ff >> ( sizeof(long)*8 - b4->node_hdr.rec_num_len ) ;
 | 
						|
  memcpy( (void *)&b4->node_hdr.rec_num_mask[0], (void *)&r_len, sizeof(long) ) ;
 | 
						|
 | 
						|
  b4->node_hdr.info_len = (unsigned char)((unsigned int)(b4->node_hdr.rec_num_len + b4->node_hdr.trail_cnt_len + b4->node_hdr.dup_cnt_len) / 8) ;
 | 
						|
  b4->node_hdr.free_space = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - sizeof( B4NODE_HEADER ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4calc_blanks( char *key_val, int len, char p_char )
 | 
						|
{
 | 
						|
  int a ;
 | 
						|
 | 
						|
  for ( a = len ; a > 0; a-- )
 | 
						|
    if ( key_val[a-1] != p_char )
 | 
						|
      return ( len - a ) ;
 | 
						|
  return len ;  /* all blanks */
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4calc_dups( char *ptr1, char *ptr2, int len )
 | 
						|
{
 | 
						|
  int a ;
 | 
						|
  for ( a = 0 ; a < len; a++ )
 | 
						|
    if ( ptr1[a] != ptr2[a] )
 | 
						|
      return a ;
 | 
						|
  return len ;  /* all duplicates */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
long S4FUNCTION x4recno( B4BLOCK *b4, int num_in_block )
 | 
						|
{
 | 
						|
#ifdef S4UNIX
 | 
						|
  unsigned long long_ptr ;
 | 
						|
  unsigned long long_val ;
 | 
						|
 | 
						|
  memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long_ptr = x4reverse_long( (void *)&long_ptr ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  memcpy( (void *)&long_val , (void *)&b4->node_hdr.rec_num_mask[0], sizeof(long) ) ;
 | 
						|
  return ( long_ptr & long_val ) ;
 | 
						|
#else
 | 
						|
  unsigned long * l_ptr ;
 | 
						|
 | 
						|
  l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
 | 
						|
  return ( *l_ptr & *(long *)&b4->node_hdr.rec_num_mask[0] ) ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION x4dup_cnt( B4BLOCK *b4, int num_in_block )
 | 
						|
{
 | 
						|
  int pos ;
 | 
						|
#ifdef S4UNIX
 | 
						|
  unsigned long long_ptr ;
 | 
						|
#else
 | 
						|
  unsigned long * l_ptr ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( b4->node_hdr.info_len > 4 )  /* > size of long, so must do careful shifting and copying */
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( b4->node_hdr.rec_num_len <= 16 )
 | 
						|
      e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
#ifdef S4UNIX
 | 
						|
    memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len + 2, sizeof(long) ) ;
 | 
						|
#else
 | 
						|
    l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len + 2 ) ;
 | 
						|
#endif
 | 
						|
    pos = b4->node_hdr.rec_num_len - 16 ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
#ifdef S4UNIX
 | 
						|
    memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
 | 
						|
#else
 | 
						|
    l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
 | 
						|
#endif
 | 
						|
    pos = b4->node_hdr.rec_num_len ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4UNIX
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long_ptr = x4reverse_long( (void *)&long_ptr ) ;
 | 
						|
#endif
 | 
						|
  return (int)( ( long_ptr >> pos ) & b4->node_hdr.dup_byte_cnt ) ;
 | 
						|
#else
 | 
						|
  return (int)( ( *l_ptr >> pos ) & b4->node_hdr.dup_byte_cnt ) ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION x4trail_cnt( B4BLOCK *b4, int num_in_block )
 | 
						|
{
 | 
						|
  int pos ;
 | 
						|
#ifdef S4UNIX
 | 
						|
  unsigned long long_ptr ;
 | 
						|
#else
 | 
						|
  unsigned long * l_ptr ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( b4->node_hdr.info_len > 4 )  /* > size of long, so must do careful shifting and copying */
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( b4->node_hdr.rec_num_len <= 16 )
 | 
						|
      e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
#ifdef S4UNIX
 | 
						|
    memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len + 2, sizeof(long) ) ;
 | 
						|
#else
 | 
						|
    l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len + 2 ) ;
 | 
						|
#endif
 | 
						|
    pos = b4->node_hdr.rec_num_len - 16 + b4->node_hdr.dup_cnt_len ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
#ifdef S4UNIX
 | 
						|
    memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
 | 
						|
#else
 | 
						|
    l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
 | 
						|
#endif
 | 
						|
    pos = b4->node_hdr.rec_num_len + b4->node_hdr.dup_cnt_len;
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef S4UNIX
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long_ptr = x4reverse_long( (void *)&long_ptr ) ;
 | 
						|
#endif
 | 
						|
  return (int)( ( long_ptr >> pos ) & b4->node_hdr.trail_byte_cnt ) ;
 | 
						|
#else
 | 
						|
  return (int)( ( *l_ptr >> pos ) & b4->node_hdr.trail_byte_cnt ) ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
 | 
						|
void S4FUNCTION x4put_info( B4NODE_HEADER *b4node_hdr, void *buffer, long rec, int trail, int dup_cnt )
 | 
						|
{
 | 
						|
  int pos ;
 | 
						|
  unsigned char *buf ;
 | 
						|
  unsigned long *l_ptr ;
 | 
						|
#ifdef S4UNIX
 | 
						|
  char unix_buf[6] ;
 | 
						|
  char unix_buf2[4] ;
 | 
						|
  long long_val, long_temp ;
 | 
						|
  int do_shift = 0 ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4UNIX
 | 
						|
  memset( unix_buf, 0, 6 ) ;
 | 
						|
  memcpy( (void *)&long_temp , (void *)&b4node_hdr->rec_num_mask[0], sizeof(long) ) ;
 | 
						|
  long_val = rec & long_temp ;
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long_val = x4reverse_long( (void *)&long_val ) ;
 | 
						|
#endif
 | 
						|
  memcpy( unix_buf, (void *)&long_val, sizeof(long) ) ;
 | 
						|
#else
 | 
						|
  buf = (unsigned char *) buffer ;
 | 
						|
  l_ptr = (unsigned long *)buf ;
 | 
						|
  memset( buf, 0, 6 ) ;
 | 
						|
  *l_ptr = rec & *(long *)&b4node_hdr->rec_num_mask[0] ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( b4node_hdr->info_len > 4 )  /* > size of long, so must do careful shifting and copying */
 | 
						|
  {
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( b4node_hdr->rec_num_len <= 16 )
 | 
						|
      e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
#ifndef S4UNIX
 | 
						|
    l_ptr = (unsigned long *)( buf + 2 ) ;  /* start at new pos */
 | 
						|
#endif
 | 
						|
    pos = b4node_hdr->rec_num_len - 16 ;
 | 
						|
#ifdef S4UNIX
 | 
						|
    do_shift = 1 ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  else
 | 
						|
    pos = b4node_hdr->rec_num_len ;
 | 
						|
 | 
						|
#ifdef S4UNIX
 | 
						|
  long_val = ((unsigned long)dup_cnt) << pos ;
 | 
						|
  pos += b4node_hdr->dup_cnt_len ;
 | 
						|
  long_val |= ((unsigned long)trail) << pos ;
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long_val = x4reverse_long( (void *)&long_val ) ;
 | 
						|
#endif
 | 
						|
  memcpy( unix_buf2, (void *)&long_val, sizeof(long) ) ;
 | 
						|
  if (do_shift)
 | 
						|
  {
 | 
						|
    unix_buf[2] |= unix_buf2[0] ;  /* must OR bytes 2 and 3 of 'buf' */
 | 
						|
    unix_buf[3] |= unix_buf2[1] ;
 | 
						|
    unix_buf[4] = unix_buf2[2] ;
 | 
						|
    unix_buf[5] = unix_buf2[3] ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    unix_buf[0] |= unix_buf2[0] ;
 | 
						|
    unix_buf[1] |= unix_buf2[1] ;
 | 
						|
    unix_buf[2] |= unix_buf2[2] ;
 | 
						|
    unix_buf[3] |= unix_buf2[3] ;
 | 
						|
  }
 | 
						|
  memcpy( (void *)buffer, unix_buf, 6 ) ;
 | 
						|
#else
 | 
						|
  *l_ptr |= ((unsigned long)dup_cnt) << pos ;
 | 
						|
  pos += b4node_hdr->dup_cnt_len ;
 | 
						|
  *l_ptr |= ((unsigned long)trail) << pos ;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4insert_leaf( B4BLOCK *b4, void *vkey_data, long rec )
 | 
						|
{
 | 
						|
  int left_blanks, right_blanks, left_dups, right_dups, left_len, right_len, reqd_len, mov_len, old_rec, rc, old_right_dups, extra_dups, save_dups ;
 | 
						|
  unsigned char buffer[6], i_len ;
 | 
						|
  char *key_data, *info_pos, a, b ;
 | 
						|
  int key_len ;
 | 
						|
  unsigned int rec_len ;
 | 
						|
  unsigned long mask ;
 | 
						|
#ifdef S4UNIX
 | 
						|
  long long_val ;
 | 
						|
#endif
 | 
						|
 | 
						|
  i_len = b4->node_hdr.info_len ;
 | 
						|
  key_data = (char *)vkey_data ;
 | 
						|
  key_len = b4->tag->header.key_len ;
 | 
						|
  b4->built_on = -1 ;
 | 
						|
 | 
						|
  if ( b4->header.n_keys == 0 )
 | 
						|
  {
 | 
						|
    if( b4->node_hdr.free_space == 0 )  /* block needs initialization */
 | 
						|
    {
 | 
						|
      b4leaf_init( b4 ) ;
 | 
						|
      i_len = b4->node_hdr.info_len ;
 | 
						|
    }
 | 
						|
    left_blanks = b4calc_blanks( key_data, key_len, b4->tag->p_char ) ;
 | 
						|
    left_dups = 0 ;
 | 
						|
    reqd_len = key_len - left_blanks ;
 | 
						|
    b4->key_on = 0 ;
 | 
						|
    b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE - reqd_len ;
 | 
						|
    memcpy( b4->cur_pos, key_data, reqd_len ) ;  /* key */
 | 
						|
    x4put_info( &b4->node_hdr, buffer, rec, left_blanks, 0 ) ;
 | 
						|
    memcpy( b4->data, (void *)buffer, i_len ) ;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    /* if the record is > than the mask, must reset the block with new parameters: */
 | 
						|
    b = sizeof( long ) * 8 ;
 | 
						|
    mask = 0x01L << (b-1) ;    /* set leftmost bit  */
 | 
						|
 | 
						|
    for( rec_len = 0, a = 0 ; a < b ; a++ )
 | 
						|
    {
 | 
						|
      if ( rec & mask )
 | 
						|
      {
 | 
						|
        rec_len = b - a ;
 | 
						|
        break ;
 | 
						|
      }
 | 
						|
      mask >>= 1 ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( rec_len > b4->node_hdr.rec_num_len )
 | 
						|
    {
 | 
						|
      old_rec = b4->key_on ;
 | 
						|
      save_dups = b4->cur_dup_cnt ;
 | 
						|
      rc = b4reindex( b4 ) ;
 | 
						|
      if (rc )
 | 
						|
        return rc ;
 | 
						|
      i_len = b4->node_hdr.info_len ;
 | 
						|
      b4top( b4 ) ;
 | 
						|
      b4skip( b4, old_rec ) ;
 | 
						|
      b4->cur_dup_cnt = save_dups ;
 | 
						|
    }
 | 
						|
 | 
						|
    left_blanks = b4calc_blanks( key_data, key_len, b4->tag->p_char ) ;
 | 
						|
 | 
						|
    if ( b4->key_on == b4->header.n_keys )  /* at end */
 | 
						|
    {
 | 
						|
      left_dups = b4->cur_dup_cnt ;
 | 
						|
      reqd_len = key_len - left_blanks - b4->cur_dup_cnt ;
 | 
						|
      if ( (int)b4->node_hdr.free_space < ( reqd_len + (int)i_len ) )  /* no room to add */
 | 
						|
        return 1 ;
 | 
						|
      b4->cur_pos -= reqd_len ;
 | 
						|
      memcpy( b4->cur_pos, key_data + b4->cur_dup_cnt, reqd_len ) ;  /* key */
 | 
						|
      x4put_info( &b4->node_hdr, buffer, rec, left_blanks, left_dups ) ;
 | 
						|
      memcpy( b4->data + b4->key_on * i_len , (void *)buffer, i_len ) ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      right_blanks = x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
 | 
						|
      if ( b4->key_on == 0 )   /* insert at top */
 | 
						|
      {
 | 
						|
        old_right_dups = 0 ;
 | 
						|
        right_dups = b4calc_dups( key_data, b4->cur_pos, key_len - ( right_blanks > left_blanks ? right_blanks : left_blanks ) ) ;
 | 
						|
        extra_dups = right_dups ;
 | 
						|
        left_dups = 0 ;
 | 
						|
      }
 | 
						|
      else /* insert in middle of block */
 | 
						|
      {
 | 
						|
        old_right_dups = x4dup_cnt( b4, b4->key_on) ;
 | 
						|
        extra_dups = b4calc_dups( key_data + old_right_dups, b4->cur_pos, key_len - ( right_blanks > left_blanks ? right_blanks : left_blanks ) - old_right_dups ) ;
 | 
						|
        right_dups = old_right_dups + extra_dups ;
 | 
						|
        left_dups = b4->cur_dup_cnt ;
 | 
						|
      }
 | 
						|
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
      if ( b4->tag->header.type_code & 0x01 )
 | 
						|
        if ( left_dups == b4->tag->header.key_len || right_dups == b4->tag->header.key_len )
 | 
						|
          e4severe( e4info, "b4insert_leaf() - duplicate key being inserted in unique index" ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
      right_len = key_len - right_blanks - right_dups ;
 | 
						|
      left_len = key_len - left_dups - left_blanks ;
 | 
						|
      reqd_len = left_len - extra_dups ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( reqd_len < 0 )
 | 
						|
        e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
      if ( (int)b4->node_hdr.free_space < (reqd_len + (int)i_len) )  /* no room to add */
 | 
						|
        return 1 ;
 | 
						|
 | 
						|
 | 
						|
      if ( reqd_len != 0 )  /* shift data over */
 | 
						|
      {
 | 
						|
        mov_len = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - i_len * b4->header.n_keys
 | 
						|
          - sizeof( B4NODE_HEADER ) - b4->node_hdr.free_space
 | 
						|
            - ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->cur_pos ) ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
        if ( mov_len < 0 )
 | 
						|
          e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
        /* move and put keys */
 | 
						|
        memmove( b4->cur_pos - mov_len - reqd_len, b4->cur_pos - mov_len, mov_len ) ;
 | 
						|
      }
 | 
						|
      b4->cur_pos += ( key_len - right_blanks - old_right_dups ) ;
 | 
						|
      memcpy( b4->cur_pos - left_len - right_len, b4->cur_pos - ( key_len - right_dups - right_blanks ), right_len ) ;
 | 
						|
      b4->cur_pos -= left_len ;
 | 
						|
      memcpy( b4->cur_pos, key_data + left_dups, left_len ) ;
 | 
						|
 | 
						|
      /* move and put info */
 | 
						|
      info_pos = b4->data + ( b4->key_on ) * i_len ;
 | 
						|
      memmove( info_pos + i_len, info_pos ,i_len * ( b4->header.n_keys - b4->key_on ) ) ;
 | 
						|
      x4put_info( &b4->node_hdr, buffer, rec, left_blanks, left_dups ) ;
 | 
						|
      memcpy( info_pos, (void *)buffer, i_len ) ;
 | 
						|
      x4put_info( &b4->node_hdr, buffer, x4recno( b4, b4->key_on + 1 ), right_blanks, right_dups ) ;
 | 
						|
      memcpy( info_pos + i_len, (void *)buffer, i_len ) ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  b4->changed = 1 ;
 | 
						|
  b4->header.n_keys++ ;
 | 
						|
  b4->node_hdr.free_space -= (short) (reqd_len + (int)i_len ) ;
 | 
						|
  b4->cur_dup_cnt = left_dups ;
 | 
						|
  b4->cur_trail_cnt = left_blanks ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4insert_branch( B4BLOCK *b4, void *k, long r, long r2, char new_flag )
 | 
						|
{
 | 
						|
  int left_len, move_len, g_len ;
 | 
						|
  char *data_ptr, *next_ptr ;
 | 
						|
 | 
						|
  g_len = b4->tag->header.key_len + 2 * sizeof(long) ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( k == 0 || r <= 0L )
 | 
						|
    e4severe( e4parm, E4_B4INSERT_BR ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  data_ptr = ((char *)&b4->node_hdr) + b4->key_on * g_len ;
 | 
						|
  next_ptr = data_ptr + g_len ;
 | 
						|
 | 
						|
  left_len = B4BLOCK_SIZE - sizeof( b4->header ) - g_len * b4->header.n_keys ;
 | 
						|
  if ( left_len < g_len )  /* not enough room */
 | 
						|
    return 1 ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( b4->key_on < 0  ||  b4->key_on > b4->header.n_keys )
 | 
						|
    e4severe( e4info, E4_B4INSERT_BR ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  move_len = g_len * (b4->header.n_keys - b4->key_on) ;
 | 
						|
 | 
						|
  memmove( next_ptr, data_ptr, move_len ) ;
 | 
						|
  b4->header.n_keys++ ;
 | 
						|
  memcpy( data_ptr, k, b4->tag->header.key_len ) ;
 | 
						|
  memset( data_ptr + g_len - 2*sizeof(long), 0, sizeof(long) ) ;
 | 
						|
 | 
						|
  r2 = x4reverse_long( (void *)&r2 ) ;
 | 
						|
  memcpy( data_ptr + g_len - 2*sizeof(long), (void *)&r2, sizeof(long) ) ;
 | 
						|
 | 
						|
  r = x4reverse_long( (void *)&r ) ;
 | 
						|
 | 
						|
  if ( !new_flag &&  (b4->key_on + 1) != b4->header.n_keys )
 | 
						|
    memcpy(  next_ptr + g_len - sizeof(long), (void *)&r, sizeof(long) ) ;
 | 
						|
  else
 | 
						|
    memcpy( data_ptr + g_len - sizeof(long), (void *)&r, sizeof(long) ) ;
 | 
						|
 | 
						|
  b4->changed = 1 ;
 | 
						|
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4insert( B4BLOCK *b4, void *key_data, long rec, long rec2, char new_flag )
 | 
						|
{
 | 
						|
  if( b4->header.node_attribute >= 2 ) /* leaf */
 | 
						|
    return b4insert_leaf( b4, key_data, rec ) ;
 | 
						|
  else
 | 
						|
    return b4insert_branch( b4, key_data, rec, rec2, new_flag ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4reindex( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  int i, dup_cnt, trail ;
 | 
						|
  int ni_len = b4->node_hdr.info_len + 1 ;
 | 
						|
  unsigned char buffer[6] ;
 | 
						|
  long rec ;
 | 
						|
  int space_reqd = b4->header.n_keys ;   /* 1 byte extra for each record */
 | 
						|
  if ( space_reqd > b4->node_hdr.free_space )  /* not enough room */
 | 
						|
    return 1 ;
 | 
						|
 | 
						|
  for ( i = b4->header.n_keys-1 ; i >= 0 ; i-- )
 | 
						|
  {
 | 
						|
    dup_cnt = x4dup_cnt( b4, i ) ;
 | 
						|
    trail = x4trail_cnt( b4, i ) ;
 | 
						|
    rec = x4recno( b4, i ) ;
 | 
						|
    memset( b4->data + i * ni_len, 0, ni_len ) ;
 | 
						|
 | 
						|
    b4->node_hdr.rec_num_len += 8 ;  /* for the new info */
 | 
						|
    b4->node_hdr.info_len++ ;
 | 
						|
    x4put_info( &b4->node_hdr, buffer, rec, trail, dup_cnt ) ;
 | 
						|
    b4->node_hdr.rec_num_len -= 8 ;  /* to get the old info */
 | 
						|
    b4->node_hdr.info_len-- ;
 | 
						|
    memcpy( b4->data + i * ni_len, (void *)buffer, ni_len ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  memcpy( (void *)&rec, (void *)&b4->node_hdr.rec_num_mask[0], sizeof(long) ) ;
 | 
						|
  rec |= (0x000000FFL << b4->node_hdr.rec_num_len ) ;
 | 
						|
  memcpy( (void *)&b4->node_hdr.rec_num_mask[0], (void *)&rec, sizeof(long) ) ;
 | 
						|
 | 
						|
  b4->node_hdr.info_len++ ;
 | 
						|
  b4->node_hdr.rec_num_len += 8 ;
 | 
						|
  b4->node_hdr.free_space -= b4->header.n_keys ;
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4flush( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  int rc ;
 | 
						|
  INDEX4 *i4 ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
  char swap[B4BLOCK_SIZE] ;
 | 
						|
  char *swap_ptr ;
 | 
						|
  int i ;
 | 
						|
  S4LONG long_val ;
 | 
						|
  short short_val ;
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( b4->changed )
 | 
						|
  {
 | 
						|
    i4 = b4->tag->index ;
 | 
						|
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    memcpy( (void *)swap, (void *)&b4->header.node_attribute, B4BLOCK_SIZE ) ;
 | 
						|
 | 
						|
    /* position at either B4NODE_HEADER (leaf) or data (branch) */
 | 
						|
    swap_ptr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
 | 
						|
 | 
						|
    /* if block is a leaf */
 | 
						|
    if (b4->header.node_attribute >= 2 )
 | 
						|
    {
 | 
						|
      /* swap B4NODE_HEADER members */
 | 
						|
      short_val = x4reverse_short( (void *)swap_ptr ) ; /* free_space */
 | 
						|
      memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
      swap_ptr += sizeof(short) ;
 | 
						|
 | 
						|
      long_val = x4reverse_long( (void *)swap_ptr ) ;   /* rec_num_mask */
 | 
						|
      memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
    }
 | 
						|
    else                /* if block is a branch */
 | 
						|
    {
 | 
						|
      short_val = b4->tag->header.key_len + sizeof(S4LONG) ;
 | 
						|
 | 
						|
      /* position swap_ptr to end of first key expression */
 | 
						|
      swap_ptr += b4->tag->header.key_len ;
 | 
						|
 | 
						|
      /* move through all B4KEY's to swap 'long's */
 | 
						|
      for ( i = 0 ; i < (int) b4->header.n_keys ; i++ )
 | 
						|
      {
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        swap_ptr += sizeof(S4LONG) ;
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        swap_ptr += short_val ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    /* reposition to B4STD_HEADER and swap members */
 | 
						|
    swap_ptr = swap ;
 | 
						|
 | 
						|
    short_val = x4reverse_short( (void *)swap_ptr ) ; /* node_attribute */
 | 
						|
    memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
    swap_ptr += sizeof(short) ;
 | 
						|
 | 
						|
    short_val = x4reverse_short( (void *)swap_ptr ) ; /* n_keys */
 | 
						|
    memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
 | 
						|
    swap_ptr += sizeof(short) ;
 | 
						|
 | 
						|
    long_val = x4reverse_long( (void *)swap_ptr ) ;   /* left_node */
 | 
						|
    memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
    swap_ptr += sizeof(S4LONG) ;
 | 
						|
 | 
						|
    long_val = x4reverse_long( (void *)swap_ptr ) ;   /* right_node */
 | 
						|
    memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
    swap_ptr += sizeof(S4LONG) ;
 | 
						|
 | 
						|
    rc = file4write( &i4->file, (long)b4->file_block * I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
 | 
						|
#else
 | 
						|
    rc = file4write( &i4->file, (long)b4->file_block * I4MULTIPLY, &b4->header.node_attribute, B4BLOCK_SIZE ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( rc < 0 )
 | 
						|
      return rc ;
 | 
						|
    b4->changed = 0 ;
 | 
						|
  }
 | 
						|
  return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
void S4FUNCTION b4go( B4BLOCK *b4, int i_key )
 | 
						|
{
 | 
						|
  b4skip( b4, i_key - b4->key_on ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
void S4FUNCTION b4top( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  b4->key_on = 0 ;
 | 
						|
  if ( b4leaf( b4 ) )
 | 
						|
  {
 | 
						|
    b4->cur_dup_cnt = 0 ;
 | 
						|
    b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE - b4->tag->header.key_len + x4trail_cnt( b4, 0 ) ;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
void S4FUNCTION b4go_eof( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  b4->key_on = b4->header.n_keys ;
 | 
						|
  b4->cur_pos = ((char *)&b4->header) + sizeof( B4STD_HEADER ) + sizeof( B4NODE_HEADER )
 | 
						|
    + b4->header.n_keys * b4->node_hdr.info_len + b4->node_hdr.free_space ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
 | 
						|
{
 | 
						|
  int len ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
  if ( i_key > b4->header.n_keys || i_key < 0 )
 | 
						|
    e4severe( e4info, E4_INFO_CIF ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
  if ( i_key == b4->built_on )   /* already there! */
 | 
						|
    return b4->built_key ;
 | 
						|
 | 
						|
  if ( b4->header.node_attribute >= 2 ) /* leaf */
 | 
						|
  {
 | 
						|
    if ( b4->built_on > i_key || b4->built_on == -1 )
 | 
						|
    {
 | 
						|
      b4->built_on = -1 ;
 | 
						|
      b4->built_pos = ((char *)&b4->header) + B4BLOCK_SIZE ;
 | 
						|
    }
 | 
						|
 | 
						|
    for ( ; b4->built_on != i_key ; )
 | 
						|
    {
 | 
						|
      b4->built_on++ ;
 | 
						|
      b4->cur_dup_cnt = x4dup_cnt( b4, b4->built_on ) ;
 | 
						|
      b4->cur_trail_cnt = x4trail_cnt( b4, b4->built_on ) ;
 | 
						|
      len = b4->tag->header.key_len - b4->cur_dup_cnt - b4->cur_trail_cnt ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if (len < 0 || len > b4->tag->header.key_len || ( b4->built_pos - len ) < b4->data )
 | 
						|
        e4severe( e4info, E4_INFO_CIF ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
      b4->built_pos -= len ;
 | 
						|
      memcpy( b4->built_key->value + b4->cur_dup_cnt, b4->built_pos, len ) ;
 | 
						|
      memset( b4->built_key->value + b4->tag->header.key_len - b4->cur_trail_cnt, b4->tag->p_char, b4->cur_trail_cnt ) ;
 | 
						|
    }
 | 
						|
    b4->built_key->num = x4recno( b4, b4->key_on ) ;
 | 
						|
  }
 | 
						|
  else /* branch */
 | 
						|
  {
 | 
						|
    memcpy( b4->built_key->value, (((char *)&b4->node_hdr) + i_key*(2*sizeof( long ) + b4->tag->header.key_len ) ), b4->tag->header.key_len ) ;
 | 
						|
    b4->built_key->num = x4reverse_long( (void *)( ((unsigned char *)&b4->node_hdr)
 | 
						|
                                                  + (i_key+1)*(2*sizeof(long) + b4->tag->header.key_len)
 | 
						|
                                                  - sizeof(long) ) ) ;
 | 
						|
  }
 | 
						|
  return b4->built_key ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
 | 
						|
{
 | 
						|
  return (unsigned char *)b4key( b4, i_key )->value ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4lastpos( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  return b4->header.n_keys - 1 ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4leaf( B4BLOCK *b4 )
 | 
						|
{
 | 
						|
  return( b4->header.node_attribute >= 2 ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
long S4FUNCTION b4recno( B4BLOCK *b4, int i )
 | 
						|
{
 | 
						|
  if ( b4->header.node_attribute >= 2 ) /* leaf */
 | 
						|
    return x4recno( b4, i ) ;
 | 
						|
  else /* branch */
 | 
						|
    return x4reverse_long( (void *)(((unsigned char *)&b4->node_hdr) +
 | 
						|
                                    i * (2*sizeof(long) + b4->tag->header.key_len) + b4->tag->header.key_len ) ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
void S4FUNCTION b4br_replace( B4BLOCK *b4, char *str, long rec )
 | 
						|
{
 | 
						|
  int key_len ;
 | 
						|
  char *put_pl ;
 | 
						|
 | 
						|
  key_len = b4->tag->header.key_len ;
 | 
						|
  put_pl = ( (char *)&b4->node_hdr ) + b4->key_on * ( 2 * sizeof( long ) + key_len ) ;
 | 
						|
  memcpy( put_pl, str, key_len ) ;
 | 
						|
  memcpy( b4->built_key->value, str, key_len ) ;
 | 
						|
  memset( put_pl + key_len, 0, sizeof(long) ) ;
 | 
						|
  rec = x4reverse_long( (void *)&rec ) ;
 | 
						|
  memcpy( put_pl + key_len, (void *)&rec, sizeof(long) ) ;
 | 
						|
 | 
						|
  b4->changed = 1 ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
/* S4FOX */
 | 
						|
int S4FUNCTION b4r_brseek( B4BLOCK *b4, char *search_value, int len, long recno )
 | 
						|
{
 | 
						|
  int rc, key_len ;
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
  long long_val, lrecno ;
 | 
						|
#endif
 | 
						|
 | 
						|
  rc = b4seek( b4, search_value, len ) ;
 | 
						|
  key_len = b4->tag->header.key_len ;
 | 
						|
 | 
						|
  if ( rc == 0 )   /* string matches, so search on recno */
 | 
						|
    for(;;)
 | 
						|
    {
 | 
						|
#ifdef S4DO_BYTEORDER
 | 
						|
      lrecno = x4reverse_long( (void *)&recno ) ;
 | 
						|
      long_val = x4reverse_long( (void *)(((char *)&b4->node_hdr) + b4->key_on * ( 2 * sizeof(long) + key_len) + key_len ) ) ;
 | 
						|
      if ( u4memcmp( (void *)&lrecno, (void *)&long_val, sizeof(long) ) <= 0
 | 
						|
#else
 | 
						|
          if ( u4memcmp( (void *)&recno, ((char *)&b4->node_hdr) + b4->key_on * ( 2 * sizeof(long) + key_len) + key_len, sizeof(long) ) <= 0
 | 
						|
#endif
 | 
						|
              || b4->key_on >= ( b4->header.n_keys - 1 ) )  /* best match, so done */
 | 
						|
          break ;
 | 
						|
          else
 | 
						|
          if( b4->key_on < b4->header.n_keys )
 | 
						|
          b4skip( b4, 1L ) ;
 | 
						|
 | 
						|
          if ( u4memcmp( (void *)b4key_key(b4,b4->key_on), search_value, len ) )  /* the key has changed, so stop here */
 | 
						|
          break ;
 | 
						|
        }
 | 
						|
 | 
						|
      return rc ;
 | 
						|
    }
 | 
						|
 | 
						|
  /* S4FOX */
 | 
						|
  int S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
 | 
						|
  {
 | 
						|
    int rc, key_lower, key_upper, save_rc, key_cur, group_val ;
 | 
						|
    if ( b4->header.n_keys == 0 )
 | 
						|
    {
 | 
						|
      b4->key_on = 0 ;
 | 
						|
      return r4after ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( b4leaf( b4 ) )
 | 
						|
      return b4leaf_seek( b4, search_value, len ) ;
 | 
						|
 | 
						|
    /* key_cur must be between  key_lower and  key_upper */
 | 
						|
    key_lower = -1 ;
 | 
						|
    key_upper = b4->header.n_keys - 1 ;
 | 
						|
 | 
						|
    save_rc = 1 ;
 | 
						|
    group_val = 2 * sizeof( long ) + b4->tag->header.key_len ;
 | 
						|
 | 
						|
    for(;;)  /* Repeat until the key is found */
 | 
						|
    {
 | 
						|
      key_cur = (key_upper + key_lower) / 2 ;
 | 
						|
      /* only memcmp for branch blocks */
 | 
						|
      rc = u4memcmp( (((char *)&b4->node_hdr) + key_cur * group_val ), search_value, len ) ;
 | 
						|
 | 
						|
      if ( rc >= 0 )
 | 
						|
      {
 | 
						|
        key_upper = key_cur ;
 | 
						|
        save_rc = rc ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        key_lower = key_cur ;
 | 
						|
 | 
						|
      if ( key_lower >= (key_upper-1) )  /* then there is no exact match */
 | 
						|
      {
 | 
						|
        b4->key_on = key_upper ;   /* branch block, just change key_on */
 | 
						|
        if ( save_rc )
 | 
						|
          return r4after ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* S4FOX */
 | 
						|
  int S4FUNCTION b4leaf_seek( B4BLOCK *b4, char *search_value, int len )
 | 
						|
  {
 | 
						|
    int duplicates, bytes_same, compare_len, key_len, original_len, significant_bytes, trail_cnt, done ;
 | 
						|
    char all_blank ;
 | 
						|
 | 
						|
    original_len = len ;
 | 
						|
    key_len = b4->tag->header.key_len ;
 | 
						|
    len -= b4calc_blanks( search_value, len, b4->tag->p_char ) ;  /* don't compare blank bytes */
 | 
						|
    if ( len == 0 )   /* if all blanks, watch for records < blank */
 | 
						|
    {
 | 
						|
      len = original_len ;
 | 
						|
      all_blank = 1 ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      all_blank = 0 ;
 | 
						|
    duplicates = 0 ;
 | 
						|
    b4top( b4 ) ;
 | 
						|
 | 
						|
    for(;;)
 | 
						|
    {
 | 
						|
      if ( b4->cur_dup_cnt == duplicates )
 | 
						|
      {
 | 
						|
        significant_bytes = key_len - x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
        if ( all_blank && significant_bytes == 0 )   /* found a blank record */
 | 
						|
          len = 0 ;
 | 
						|
        compare_len = ( len < significant_bytes ? len : significant_bytes ) - b4->cur_dup_cnt ;
 | 
						|
        bytes_same = (*b4->tag->cmp)( b4->cur_pos, search_value + b4->cur_dup_cnt, compare_len ) ;
 | 
						|
 | 
						|
        if ( bytes_same == -1 )
 | 
						|
          return r4after ;
 | 
						|
        if ( bytes_same == compare_len )
 | 
						|
        {
 | 
						|
          if ( b4->cur_dup_cnt + bytes_same == len )  /* unless binary, for sure done */
 | 
						|
          {
 | 
						|
            if ( len == original_len )
 | 
						|
              done = 1 ;
 | 
						|
            else  /* in case of binary, we may not be done if values < blank */
 | 
						|
            {
 | 
						|
              trail_cnt = x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
              if ( significant_bytes > trail_cnt + len )  /* significant bytes beyond the trail, so check binary */
 | 
						|
              {
 | 
						|
                if ( memcmp( b4->cur_pos + compare_len, search_value + len, key_len - trail_cnt ) < 0 )  /* binaries */
 | 
						|
                  done = 0 ;
 | 
						|
                else
 | 
						|
                  done = 1 ;
 | 
						|
 | 
						|
              }
 | 
						|
              else
 | 
						|
                done = 1 ;
 | 
						|
            }   
 | 
						|
 | 
						|
            if ( done == 1 )
 | 
						|
            {
 | 
						|
              if ( len != original_len && significant_bytes > len )
 | 
						|
              {
 | 
						|
                if ( significant_bytes < original_len )
 | 
						|
                  return r4after ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
                if ( len > original_len )
 | 
						|
                  e4severe( e4info, E4_B4LEAF_SEEK ) ;
 | 
						|
#endif
 | 
						|
                if ( (*b4->tag->cmp)( b4->cur_pos + compare_len, search_value + len, (original_len - len) ) != (original_len - len) )
 | 
						|
                  return r4after ;
 | 
						|
              }
 | 
						|
              if ( all_blank != 1 )   /* not all blanks, so significants matter */
 | 
						|
                b4->cur_dup_cnt += bytes_same ;
 | 
						|
              else
 | 
						|
                b4->cur_dup_cnt = 0 ;
 | 
						|
              return 0 ;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        b4->cur_dup_cnt += bytes_same ;
 | 
						|
      }
 | 
						|
 | 
						|
      b4->key_on++ ;
 | 
						|
      if ( b4->key_on >= b4->header.n_keys )
 | 
						|
        return r4after ;
 | 
						|
      duplicates = x4dup_cnt( b4, b4->key_on ) ;
 | 
						|
      b4->cur_pos -= key_len - duplicates - x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
      if ( b4->cur_dup_cnt > duplicates )
 | 
						|
        return r4after ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* S4FOX */
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
  void S4FUNCTION b4remove_leaf( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    int old_dup, left_dup, left_trail, key_len, remove_len, new_dup, old_bytes, new_bytes, mov_len, left_bytes ;
 | 
						|
    unsigned char buffer[6], i_len ;
 | 
						|
    char *old_pos, *info_pos ;
 | 
						|
 | 
						|
    b4->built_on = -1 ;
 | 
						|
 | 
						|
    if ( b4->header.n_keys == 1 )  /* removing last key */
 | 
						|
    {
 | 
						|
      b4->node_hdr.free_space = B4BLOCK_SIZE - sizeof( B4NODE_HEADER ) - sizeof( B4STD_HEADER ) ;
 | 
						|
      memset( b4->data, 0, b4->node_hdr.free_space ) ;
 | 
						|
      b4->header.n_keys = 0 ;
 | 
						|
      b4->key_on = 0 ;
 | 
						|
      b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE ;
 | 
						|
      b4->changed = 1 ;
 | 
						|
      return ;
 | 
						|
    }
 | 
						|
 | 
						|
    key_len = b4->tag->header.key_len ;
 | 
						|
    i_len = b4->node_hdr.info_len ;
 | 
						|
    old_dup = x4dup_cnt( b4, b4->key_on) ;
 | 
						|
 | 
						|
    if ( b4->key_on == b4->header.n_keys - 1 )  /* at end */
 | 
						|
    {
 | 
						|
      remove_len = key_len - old_dup - x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( remove_len < 0 )
 | 
						|
        e4severe( e4info, E4_INFO_CIF ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
      memset( b4->cur_pos, 0, remove_len ) ;
 | 
						|
      memset( b4->data + b4->key_on * i_len, 0, i_len ) ;
 | 
						|
      b4->key_on-- ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      old_bytes = key_len - old_dup - x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
      old_pos = b4->cur_pos ;
 | 
						|
      b4skip( b4, 1 ) ;
 | 
						|
      left_dup = x4dup_cnt( b4, b4->key_on) ;
 | 
						|
      left_trail = x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
      new_dup = old_dup < left_dup ? old_dup : left_dup ;
 | 
						|
      left_bytes = key_len - left_trail - left_dup ;
 | 
						|
      new_bytes = key_len - left_trail - new_dup ;
 | 
						|
 | 
						|
      memcpy( b4->built_key->value, old_pos, left_dup - new_dup ) ;  /* copy prev dup bytes between the 2 keys only */
 | 
						|
      memcpy( b4->built_key->value + ( left_dup - new_dup ), b4->cur_pos, left_bytes ) ;
 | 
						|
      memcpy( old_pos + old_bytes - new_bytes, b4->built_key->value, new_bytes ) ;
 | 
						|
 | 
						|
      remove_len = old_bytes + left_bytes - new_bytes ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( remove_len < 0 )
 | 
						|
        e4severe( e4info, E4_INFO_CIF ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
      mov_len = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - i_len * b4->header.n_keys
 | 
						|
        - sizeof( B4NODE_HEADER ) - b4->node_hdr.free_space
 | 
						|
          - ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->cur_pos ) ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( mov_len < 0 )
 | 
						|
        e4severe( e4info, E4_INFO_CIB ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
      memmove( b4->cur_pos - mov_len + remove_len, b4->cur_pos - mov_len, mov_len ) ;
 | 
						|
 | 
						|
      memset( b4->cur_pos - mov_len, 0, remove_len ) ;
 | 
						|
      b4->key_on-- ;
 | 
						|
 | 
						|
      /* move and put info */
 | 
						|
      info_pos = b4->data + ( b4->key_on ) * i_len ;
 | 
						|
      memmove( info_pos, info_pos + i_len ,i_len * ( b4->header.n_keys - b4->key_on ) ) ;
 | 
						|
      x4put_info( &b4->node_hdr, buffer, x4recno( b4, b4->key_on ), left_trail, new_dup ) ;
 | 
						|
      memcpy( info_pos, (void *)buffer, i_len ) ;
 | 
						|
      memset( b4->data + (b4->header.n_keys - 1 ) * i_len, 0, i_len ) ;
 | 
						|
    }
 | 
						|
    b4->changed = 1 ;
 | 
						|
    b4->cur_pos += remove_len ;
 | 
						|
    b4->header.n_keys-- ;
 | 
						|
    b4->node_hdr.free_space += (short) ((int)i_len + remove_len) ;
 | 
						|
  }
 | 
						|
 | 
						|
  /* S4FOX */
 | 
						|
  void S4FUNCTION b4remove( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    char *key_cur ;
 | 
						|
    int len, i_len ;
 | 
						|
 | 
						|
    if( b4->header.node_attribute >= 2 ) /* leaf */
 | 
						|
      b4remove_leaf( b4 ) ;
 | 
						|
    else
 | 
						|
    {
 | 
						|
      i_len = b4->tag->header.key_len + 2 * sizeof( long ) ;
 | 
						|
      key_cur = ((char *)&b4->node_hdr) + i_len * b4->key_on ;
 | 
						|
      len = (b4->header.n_keys - b4->key_on - 1) * i_len ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
      if ( b4->key_on < 0  || b4->key_on > b4lastpos( b4 ) ||
 | 
						|
          len < 0 || (unsigned)len > (B4BLOCK_SIZE - sizeof(B4STD_HEADER) - (unsigned)i_len ))
 | 
						|
        e4severe( e4info, E4_B4REMOVE ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
      if ( len > 0 )
 | 
						|
        memmove( key_cur, key_cur + i_len, len ) ;
 | 
						|
 | 
						|
      b4->header.n_keys-- ;
 | 
						|
      memset( ((char *)&b4->node_hdr) + b4->header.n_keys * i_len, 0, i_len ) ;
 | 
						|
      b4->changed = 1 ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
  /* S4FOX */
 | 
						|
  int S4FUNCTION b4skip( B4BLOCK *b4, long n )
 | 
						|
  {
 | 
						|
    int num_skipped ;
 | 
						|
 | 
						|
    if ( b4->header.node_attribute < 2 )  /* branch */
 | 
						|
    {
 | 
						|
      if ( n > 0 )
 | 
						|
        num_skipped = b4->header.n_keys - b4->key_on ;
 | 
						|
      else
 | 
						|
        num_skipped = -b4->key_on ;
 | 
						|
 | 
						|
      if ( ( n <= 0L ) ?  (num_skipped <= (int)n)  :  (num_skipped >= (int)n)  )
 | 
						|
      {
 | 
						|
        b4->key_on += (int) n ;
 | 
						|
        return (int) n ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        b4->key_on += num_skipped ;
 | 
						|
        return num_skipped ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else  /* leaf */
 | 
						|
    {
 | 
						|
      if ( b4->header.n_keys == 0 )
 | 
						|
        return 0 ;
 | 
						|
      if (n > 0 )
 | 
						|
      {
 | 
						|
        if ( b4->key_on + n >= b4->header.n_keys )
 | 
						|
        {
 | 
						|
          b4->cur_pos = ((char *)&b4->header ) + sizeof( B4STD_HEADER )
 | 
						|
            + sizeof( B4NODE_HEADER ) + b4->node_hdr.info_len * b4->header.n_keys
 | 
						|
              + b4->node_hdr.free_space ;
 | 
						|
          n = b4->header.n_keys - b4->key_on - ( b4->key_on != b4->header.n_keys ) ;
 | 
						|
          b4->key_on = b4->header.n_keys ;
 | 
						|
          return (int)n ;
 | 
						|
        }
 | 
						|
        for( num_skipped = (int)n ; num_skipped != 0 ; num_skipped-- )
 | 
						|
        {
 | 
						|
          b4->key_on++ ;
 | 
						|
          b4->cur_pos -= ( b4->tag->header.key_len - x4dup_cnt( b4, b4->key_on ) - x4trail_cnt( b4, b4->key_on ) ) ;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if ( b4->key_on + n < 0 )
 | 
						|
        {
 | 
						|
          n = -b4->key_on ;
 | 
						|
          b4->key_on = 0 ;
 | 
						|
          b4->cur_pos = ((char *)&b4->header ) + B4BLOCK_SIZE - b4->tag->header.key_len + x4trail_cnt( b4, b4->key_on ) ;
 | 
						|
          return (int) n ;
 | 
						|
        }
 | 
						|
        for( num_skipped = (int)n ; num_skipped != 0 ; num_skipped++ )
 | 
						|
        {
 | 
						|
          b4->cur_pos += ( b4->tag->header.key_len - x4dup_cnt( b4, b4->key_on ) - x4trail_cnt( b4, b4->key_on ) ) ;
 | 
						|
          b4->key_on-- ;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      return (int) n ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif  /* S4FOX */
 | 
						|
 | 
						|
#ifdef N4OTHER
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
  int S4FUNCTION b4flush( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    int rc ;
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
    char *swap, *swap_ptr ;
 | 
						|
    int i ;
 | 
						|
    S4LONG long_val ;
 | 
						|
    short short_val ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( b4->changed )
 | 
						|
    {
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
      if ( b4verify( b4 ) == -1 )
 | 
						|
        e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4flush()", "" ) ;
 | 
						|
#endif
 | 
						|
#ifdef S4NDX
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
      swap = (char *) u4alloc_er( b4->tag->code_base, B4BLOCK_SIZE ) ;
 | 
						|
      if ( swap == 0 )
 | 
						|
        return -1 ;
 | 
						|
 | 
						|
      memcpy( (void *)swap, (void *)&b4->n_keys, B4BLOCK_SIZE ) ;
 | 
						|
      /* position swap_ptr at beginning of pointers */
 | 
						|
 | 
						|
      swap_ptr += swap + 2 + sizeof(short) ;
 | 
						|
 | 
						|
      for ( i = 0 ; i < (*(short *)swap) ; i++ )
 | 
						|
      {
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr+sizeof(S4LONG) ) ;
 | 
						|
        memcpy( swap_ptr+sizeof(S4LONG), (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        swap_ptr += r4->data->indexes->tags.header->group_len ;
 | 
						|
      }
 | 
						|
 | 
						|
      long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
      memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
 | 
						|
      short_val = x4reverse_short( (void *)swap ) ;
 | 
						|
      memcpy( swap, (void *) &short_val, sizeof(short) ) ;
 | 
						|
 | 
						|
      rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
 | 
						|
      u4free( swap ) ;
 | 
						|
#else
 | 
						|
      rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, B4BLOCK_SIZE ) ;
 | 
						|
#endif
 | 
						|
#endif  /* S4NDX */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4BYTE_SWAP
 | 
						|
      swap = (char *)u4alloc_er( b4->tag->code_base, B4BLOCK_SIZE ) ;
 | 
						|
      if ( swap == 0 )
 | 
						|
        return -1 ;
 | 
						|
 | 
						|
      memcpy( (void *)swap, (void *)&b4->n_keys, B4BLOCK_SIZE ) ;
 | 
						|
 | 
						|
      /* position swap_ptr at beginning of pointers */
 | 
						|
      short_val = x4reverse_short( (void *)swap ) ;
 | 
						|
      memcpy( swap, (void *) &short_val, sizeof(short) ) ;
 | 
						|
 | 
						|
      swap_ptr = swap + 2 ;
 | 
						|
 | 
						|
      /* swap the short pointers to B4KEY_DATA */
 | 
						|
      for ( i = 0 ; i < b4->tag->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 < b4->tag->header.keys_max ; i++ )
 | 
						|
      {
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr ) ;
 | 
						|
        memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        long_val = x4reverse_long( (void *)swap_ptr+sizeof(S4LONG) ) ;
 | 
						|
        memcpy( swap_ptr+sizeof(S4LONG), (void *) &long_val, sizeof(S4LONG) ) ;
 | 
						|
        swap_ptr += b4->tag->header.group_len ;
 | 
						|
      }
 | 
						|
 | 
						|
      rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
 | 
						|
      u4free( swap ) ;
 | 
						|
#else
 | 
						|
      rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, B4BLOCK_SIZE ) ;
 | 
						|
#endif
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
 | 
						|
      if ( rc < 0 )  return rc ;
 | 
						|
      b4->changed = 0 ;
 | 
						|
    }
 | 
						|
    return 0 ;
 | 
						|
  }
 | 
						|
 | 
						|
  void S4FUNCTION b4append( B4BLOCK *b4, long pointer )
 | 
						|
  {
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    long adj_pointer = pointer * 512 ;
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
    B4KEY_DATA *data_ptr ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    int left_len ;
 | 
						|
    if ( b4leaf( b4 ) || pointer <1L )
 | 
						|
      e4severe( e4parm, E4_B4APPEND ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    b4go_eof( b4 ) ;
 | 
						|
    data_ptr = b4key( b4, b4->key_on ) ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
    left_len = B4BLOCK_SIZE - b4->key_on * b4->tag->header.group_len -
 | 
						|
      sizeof(short) - sizeof(char[2]) - sizeof(pointer) ;
 | 
						|
    if ( b4->key_on < 0  ||  b4->key_on != b4->n_keys ||  left_len < 0 )
 | 
						|
      e4severe( e4info, E4_B4APPEND ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
    memcpy( &data_ptr->pointer, &pointer, sizeof(pointer) ) ;
 | 
						|
#endif  /* S4NDX */
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    memcpy( &data_ptr->pointer, &adj_pointer, sizeof(pointer) ) ;
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
    b4->changed = 1 ;
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
    if ( b4verify( b4 ) == -1 )
 | 
						|
      e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4append()-after append", "" ) ;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  void S4FUNCTION b4append2( B4BLOCK *b4, void *k, long r, long pointer )
 | 
						|
  {
 | 
						|
    unsigned short temp ;
 | 
						|
    B4KEY_DATA *data_ptr ;
 | 
						|
    long adj_pointer ;
 | 
						|
 | 
						|
    b4go_eof( b4 ) ;
 | 
						|
 | 
						|
    if ( b4->n_keys > 0 )
 | 
						|
    {
 | 
						|
      if ( !b4leaf( b4 ) )   /* insert after branch */
 | 
						|
        b4->key_on++ ;
 | 
						|
      else
 | 
						|
        if ( b4->key_on + !b4leaf( b4 ) < b4->tag->header.keys_max )
 | 
						|
        {
 | 
						|
          temp = b4->pointers[b4->n_keys+1] ;
 | 
						|
          b4->pointers[b4->n_keys+1] = b4->pointers[b4->n_keys] ;
 | 
						|
          b4->pointers[b4->n_keys] = temp ;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    data_ptr  = b4key( b4, b4->key_on ) ;
 | 
						|
    adj_pointer = pointer * 512 ;
 | 
						|
    b4->n_keys++ ;
 | 
						|
 | 
						|
    memcpy( data_ptr->value, k, b4->tag->header.group_len-2*sizeof(long) ) ;
 | 
						|
    memcpy( &data_ptr->num, &r, sizeof(r) ) ;
 | 
						|
    memcpy( &data_ptr->pointer, &adj_pointer, sizeof(pointer) ) ;
 | 
						|
    b4->changed = 1 ;
 | 
						|
  }
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
 | 
						|
#ifdef S4NDX
 | 
						|
 | 
						|
  /* S4NDX */
 | 
						|
  void  S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r, long pointer )
 | 
						|
  {
 | 
						|
    B4KEY_DATA *data_ptr, *next_ptr ;
 | 
						|
    int left_len ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( k == 0 || r < 0L || pointer <0L )
 | 
						|
      e4severe( e4parm, E4_B4INSERT ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    data_ptr = b4key( b4, b4->key_on ) ;
 | 
						|
    next_ptr= b4key( b4, b4->key_on + 1 ) ;
 | 
						|
 | 
						|
    left_len = B4BLOCK_SIZE -  (b4->key_on + 1) * b4->tag->header.group_len -
 | 
						|
      sizeof(short) - sizeof(char[2]) ;   /* 2 for S4NDX version, not 6 */
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( b4->key_on < 0  ||  ( b4->key_on >  b4->n_keys && b4leaf( b4 ) )  ||
 | 
						|
        ( b4->key_on > (b4->n_keys+1)  &&  !b4leaf( b4 ) )  || left_len < 0 )
 | 
						|
      e4severe( e4info, E4_B4INSERT ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    memmove( next_ptr, data_ptr, left_len ) ;
 | 
						|
    b4->n_keys++ ;
 | 
						|
    memcpy( data_ptr->value, k, b4->tag->header.key_len ) ;
 | 
						|
    memcpy( &data_ptr->num, &r, sizeof(r) ) ;
 | 
						|
    memcpy( &data_ptr->pointer, &pointer, sizeof(pointer) ) ;
 | 
						|
    b4->changed = 1 ;
 | 
						|
  }
 | 
						|
#endif  /* S4NDX */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  /* clipper just puts at end and inserts into the index part */
 | 
						|
  void  S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r, long pointer )
 | 
						|
  {
 | 
						|
    short temp, insert_pos ;
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( k == 0 || r < 0L || pointer <0L )
 | 
						|
      e4severe( e4parm, E4_B4INSERT ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    insert_pos = b4->key_on ;
 | 
						|
 | 
						|
    /* put at block end: */
 | 
						|
    b4append2( b4, k, r, pointer ) ;
 | 
						|
 | 
						|
    temp = b4->pointers[b4->key_on] ;   /* save the placed position */
 | 
						|
    memmove( &b4->pointers[insert_pos+1], &b4->pointers[insert_pos], sizeof(short) * ( b4lastpos( b4 ) - insert_pos - (!b4leaf( b4 ) && b4->n_keys < 2) ) ) ;
 | 
						|
    b4->pointers[insert_pos] = temp ;
 | 
						|
    if ( b4leaf( b4 ) )
 | 
						|
      if ( b4key( b4, b4->n_keys )->pointer != 0 )
 | 
						|
        b4key( b4, b4->n_keys )->pointer = 0L ;
 | 
						|
  }
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
  /* goes to one past the end of the block */
 | 
						|
  void S4FUNCTION b4go_eof( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    b4->key_on = b4->n_keys ;
 | 
						|
  }
 | 
						|
 | 
						|
  B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
 | 
						|
  {
 | 
						|
#ifdef S4NDX
 | 
						|
    return  (B4KEY_DATA *) ((char *) &b4->data + b4->tag->header.group_len * i_key) ;
 | 
						|
#endif  /* S4NDX */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( i_key > 2 + b4->tag->header.keys_max )
 | 
						|
      e4severe( e4parm, E4_B4KEY ) ;
 | 
						|
    if ( ( b4->pointers[i_key] < (sizeof(short)) * ( b4->tag->header.keys_max + 1 ) ) ||
 | 
						|
        ( b4->pointers[i_key] > B4BLOCK_SIZE - b4->tag->header.key_len ) )
 | 
						|
      e4severe( e4info, E4_B4KEY ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
    return  (B4KEY_DATA *) ((char *) &b4->n_keys + b4->pointers[i_key] ) ;
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
  }
 | 
						|
 | 
						|
  unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
 | 
						|
  {
 | 
						|
    return  (unsigned char *) b4key( b4, i_key )->value ;
 | 
						|
  }
 | 
						|
 | 
						|
  int S4FUNCTION b4lastpos( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    if ( !b4leaf( b4 ) )
 | 
						|
      return b4->n_keys ;
 | 
						|
    else
 | 
						|
      return b4->n_keys - 1 ;
 | 
						|
  }
 | 
						|
 | 
						|
  int S4FUNCTION b4leaf( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    return( b4key( b4, 0 )->pointer == 0L ) ;
 | 
						|
  }
 | 
						|
 | 
						|
  long  S4FUNCTION b4recno( B4BLOCK *b4, int i )
 | 
						|
  {
 | 
						|
    return b4key( b4, i )->num ;
 | 
						|
  }
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
#ifdef S4NDX
 | 
						|
  void  S4FUNCTION b4remove( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    B4KEY_DATA *key_on ;
 | 
						|
    int left_len = -1 ;
 | 
						|
 | 
						|
    key_on = b4key( b4, b4->key_on ) ;
 | 
						|
 | 
						|
    if( !b4leaf( b4 ) )
 | 
						|
    {
 | 
						|
      if ( b4->key_on >= b4->n_keys )
 | 
						|
        left_len = 0 ;
 | 
						|
      else   /* on last pos, so copy only the rec_num */
 | 
						|
        if ( b4lastpos( b4 ) + 1 == b4->n_keys )
 | 
						|
          left_len = sizeof( long ) ;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( left_len == -1 )
 | 
						|
      left_len = B4BLOCK_SIZE - sizeof(b4->n_keys) - sizeof(b4->dummy) - (b4->key_on+1) * b4->tag->header.group_len ;
 | 
						|
 | 
						|
#ifdef S4DEBUG
 | 
						|
    if ( b4->key_on < 0  ||  b4->key_on > b4lastpos( b4 )  ||  left_len < 0 )
 | 
						|
      e4severe( e4info, E4_B4REMOVE ) ;
 | 
						|
#endif  /* S4DEBUG */
 | 
						|
 | 
						|
    if ( left_len > 0 )
 | 
						|
    {
 | 
						|
      B4KEY_DATA *key_next= b4key( b4, b4->key_on+1 ) ;
 | 
						|
      memmove( key_on, key_next, left_len ) ;
 | 
						|
    }
 | 
						|
    b4->n_keys-- ;
 | 
						|
    b4->changed = 1 ;
 | 
						|
  }
 | 
						|
#endif  /* S4NDX */
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
  void  S4FUNCTION b4remove( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    short temp ;
 | 
						|
 | 
						|
    /* just delete this entry */
 | 
						|
    temp = b4->pointers[b4->key_on] ;
 | 
						|
    if ( b4leaf( b4 ) && ( b4->key_on + !b4leaf( b4 ) < b4->tag->header.keys_max ) )
 | 
						|
    {
 | 
						|
      memmove( &b4->pointers[b4->key_on], &b4->pointers[b4->key_on+1],
 | 
						|
              sizeof(short) * (b4lastpos( b4 ) - b4->key_on + 1) ) ;
 | 
						|
      b4->pointers[b4lastpos( b4 )+1] = temp ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      memmove( &b4->pointers[b4->key_on], &b4->pointers[b4->key_on+1],
 | 
						|
              sizeof(short) * (b4lastpos( b4 ) - b4->key_on) ) ;
 | 
						|
      b4->pointers[b4lastpos( b4 )] = temp ;
 | 
						|
    }
 | 
						|
    b4->n_keys-- ;
 | 
						|
    b4->changed = 1 ;
 | 
						|
 | 
						|
    if ( b4leaf( b4 ) )
 | 
						|
      memset( b4key( b4, b4lastpos( b4 ) + 1 ), 0, b4->tag->header.key_len + 2 * sizeof( long ) ) ;
 | 
						|
  }
 | 
						|
#endif  /* S4CLIPPER */
 | 
						|
 | 
						|
  int S4FUNCTION b4room( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    if ( b4leaf( b4 ) )
 | 
						|
      return ( b4->n_keys < b4->tag->header.keys_max ) ;
 | 
						|
 | 
						|
    return( ( b4->n_keys < b4->tag->header.keys_max ) && ( ( B4BLOCK_SIZE -
 | 
						|
                                                            b4->n_keys * b4->tag->header.group_len - sizeof(short) - 2*sizeof(char)) >= sizeof(long) ) ) ;
 | 
						|
  }
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
  int  S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
 | 
						|
  {
 | 
						|
    int rc, save_rc, key_cur ;
 | 
						|
    S4CMP_FUNCTION *cmp = b4->tag->cmp ;
 | 
						|
 | 
						|
    /* key_on must be between  key_lower and  key_upper */
 | 
						|
    int key_lower = -1 ;
 | 
						|
    int key_upper = b4->n_keys ;
 | 
						|
 | 
						|
    if ( key_upper == 0 )
 | 
						|
    {
 | 
						|
      b4->key_on = 0 ;
 | 
						|
      return r4after ;
 | 
						|
    }
 | 
						|
 | 
						|
    save_rc = 1 ;
 | 
						|
 | 
						|
    for(;;)  /* Repeat until the key is found */
 | 
						|
    {
 | 
						|
      key_cur  = (key_upper + key_lower) / 2  ;
 | 
						|
      rc = (*cmp)( b4key_key(b4,key_cur), search_value, len ) ;
 | 
						|
 | 
						|
      if ( rc >= 0 )
 | 
						|
      {
 | 
						|
        key_upper = key_cur ;
 | 
						|
        save_rc = rc ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        key_lower = key_cur ;
 | 
						|
 | 
						|
      if ( key_lower >= (key_upper-1) )  /* then there is no exact match */
 | 
						|
      {
 | 
						|
        b4->key_on = key_upper ;
 | 
						|
        if ( save_rc )
 | 
						|
          return r4after ;
 | 
						|
        return 0 ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  int S4FUNCTION b4skip( B4BLOCK *b4, long n )
 | 
						|
  {
 | 
						|
    int num_left ;
 | 
						|
 | 
						|
    if ( n > 0 )
 | 
						|
    {
 | 
						|
      num_left = b4->n_keys - b4->key_on ;
 | 
						|
      if ( b4leaf( b4 ) )
 | 
						|
        if ( num_left != 0 )
 | 
						|
          num_left -- ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      num_left = -b4->key_on ;
 | 
						|
 | 
						|
    if ( ( n <= 0L ) ? ( (long)num_left <= n ) : ( (long)num_left >= n ) )
 | 
						|
    {
 | 
						|
      b4->key_on = b4->key_on + (int) n ;
 | 
						|
      return (int) n ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      b4->key_on = b4->key_on + num_left ;
 | 
						|
      return num_left ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
#endif  /* N4OTHER */
 | 
						|
#endif  /* S4INDEX_OFF */
 | 
						|
 | 
						|
#ifdef S4INDEX_VERIFY
 | 
						|
  int S4FUNCTION b4verify( B4BLOCK *b4 )
 | 
						|
  {
 | 
						|
    int i, j, type ;
 | 
						|
    long val ;
 | 
						|
#ifdef S4FOX
 | 
						|
    int hold_dup, hold_trail ;
 | 
						|
 | 
						|
    hold_dup = b4->cur_dup_cnt ;
 | 
						|
    hold_trail = b4->cur_trail_cnt ;
 | 
						|
#endif
 | 
						|
 | 
						|
    if ( b4->tag->code_base->do_index_verify == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
#ifdef S4CLIPPER
 | 
						|
    /* block internal verification... */
 | 
						|
    for ( i = 0 ; i < b4->tag->header.keys_max ; i++ )
 | 
						|
      for ( j = i + 1 ; j <= b4->tag->header.keys_max ; j++ )
 | 
						|
        if ( b4->pointers[i] == b4->pointers[j] )
 | 
						|
        {
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
          e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 pointer duplication error" ) ;
 | 
						|
#endif
 | 
						|
          e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
 | 
						|
          return -1 ;
 | 
						|
        }
 | 
						|
 | 
						|
    /* validate key count */
 | 
						|
    if ( b4->n_keys < b4->tag->header.keys_half && b4->tag->header.root / 512 != b4->file_block )
 | 
						|
      return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", E4_RESULT_CII ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
    /*      #ifdef S4FOX */
 | 
						|
    /*          */
 | 
						|
    /*         if ( b4->node_hdr.free_space != B4BLOCK_SIZE - sizeof( B4STD_HEADER ) */
 | 
						|
    /*              - sizeof( B4NODE_HEADER ) -  ) */
 | 
						|
    /*            return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", E4_RESULT_CII ) ; */
 | 
						|
    /*      #endif */
 | 
						|
 | 
						|
    /* all keys in a given block should be of the same type... - branch = 1 */
 | 
						|
#ifndef S4FOX
 | 
						|
    type = b4leaf( b4 ) ? 0 : 1 ;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* key order verification */
 | 
						|
#ifdef N4OTHER
 | 
						|
    for ( i = 0 ; i <= b4->n_keys ; i++ )
 | 
						|
    {
 | 
						|
#ifdef S4CLIPPER
 | 
						|
      val = b4key( b4, i )->pointer ;
 | 
						|
      if ( ( b4key( b4, i )->pointer ? 1 : 0 ) != type )
 | 
						|
#endif
 | 
						|
#ifdef S4NDX
 | 
						|
        if ( b4key( b4, i )->pointer >= b4->tag->header.eof )
 | 
						|
          return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "block pointer value exceeds index eof value" ) ;
 | 
						|
      if ( ( b4key( b4, i )->pointer ? 1 : 0 ) != type )
 | 
						|
#endif
 | 
						|
      {
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
        e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 branch/leaf block type inconsistent" ) ;
 | 
						|
#endif
 | 
						|
        e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
 | 
						|
        return -1 ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
    for ( i = 0 ; i < b4->header.n_keys - 1 ; i++ )
 | 
						|
    {
 | 
						|
      if ( (u4memcmp)( b4key_key( b4, i ), b4key_key( b4, i + 1 ), b4->tag->header.key_len ) > 0 )
 | 
						|
#else
 | 
						|
        for ( i = 0 ; i < b4->n_keys - 1 ; i++ )
 | 
						|
        {
 | 
						|
          if ( (*b4->tag->cmp)( b4key_key( b4, i ), b4key_key( b4, i + 1 ), b4->tag->header.key_len ) > 0 )
 | 
						|
#endif
 | 
						|
          {
 | 
						|
#ifdef S4DEBUG_DEV
 | 
						|
            e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 block ordering invalid" ) ;
 | 
						|
#endif
 | 
						|
            e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
 | 
						|
            return -1 ;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
#ifdef S4FOX
 | 
						|
      b4->cur_dup_cnt = hold_dup ;
 | 
						|
      b4->cur_trail_cnt = hold_trail ;
 | 
						|
#endif
 | 
						|
 | 
						|
      return 0 ;
 | 
						|
    }
 | 
						|
#endif
 |