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
 |