campo-sirio/cb5/i4addtag.c

880 lines
26 KiB
C
Raw Normal View History

/* i4addtag.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
#include "d4all.h"
#ifndef S4UNIX
#ifdef __TURBOC__
#pragma hdrstop
#endif
#endif
#ifndef S4INDEX_OFF
#ifndef S4OFF_WRITE
#ifdef S4NDX
int S4FUNCTION i4get_last_key( TAG4 *t4, char *key_data, long for_block )
{
int rc = 0 ;
B4BLOCK *temp_block ;
#ifdef S4DEBUG
if ( for_block <= 0 || t4 == 0 || key_data == 0 )
e4severe( e4parm, E4_I4GET_LAST_KEY ) ;
#endif
/* must get block for_block, then find the last key */
temp_block = b4alloc( t4, for_block ) ;
if ( temp_block == 0 )
return -1 ;
if ( file4read_all( &t4->file, I4MULTIPLY * for_block, &temp_block->n_keys, B4BLOCK_SIZE ) < 0 )
return -1 ;
b4go_eof( temp_block ) ;
if ( b4leaf( temp_block ) )
rc = 2 ;
else
rc = b4get_last_key( temp_block, key_data ) ;
b4free( temp_block ) ;
return rc ;
}
#endif
#ifndef N4OTHER
#ifdef S4FOX
/* (temporary) fix for FoxPro multi-user compatibility
swaps parent and right blocks */
#ifndef S4SINGLE
static long t4swap( B4BLOCK *parent, B4BLOCK *left )
{
long temp_fb ;
#ifdef S4BYTE_SWAP
S4LONG long_val ;
#endif
temp_fb = left->file_block ;
left->file_block = parent->file_block ;
parent->file_block = temp_fb ;
/* now update neighbours */
if ( left->header.right_node != -1 )
{
#ifdef S4BYTE_SWAP
long_val = x4reverse_long( (void *)&left->file_block ) ;
file4write( &parent->tag->index->file, left->header.right_node + 2*sizeof(short),
&long_val, sizeof( left->header.left_node ) ) ;
#else
file4write( &parent->tag->index->file, left->header.right_node + 2*sizeof(short),
&left->file_block, sizeof( left->header.left_node ) ) ;
#endif
}
if ( left->header.left_node != -1 )
{
#ifdef S4BYTE_SWAP
long_val = x4reverse_long( (void *)&left->file_block ) ;
file4write( &parent->tag->index->file, left->header.left_node + 2*sizeof(short),
&long_val, sizeof( left->header.right_node ) ) ;
#else
file4write( &parent->tag->index->file, left->header.left_node + 2*sizeof(short),
&left->file_block, sizeof( left->header.right_node ) ) ;
#endif
}
if ( parent->header.right_node != -1 )
{
#ifdef S4BYTE_SWAP
long_val = x4reverse_long( (void *)&parent->file_block ) ;
file4write( &parent->tag->index->file, parent->header.right_node + 2*sizeof(short),
&long_val, sizeof( parent->header.left_node ) ) ;
#else
file4write( &parent->tag->index->file, parent->header.right_node + 2*sizeof(short),
&parent->file_block, sizeof( parent->header.left_node ) ) ;
#endif
}
if ( parent->header.left_node != -1 )
{
#ifdef S4BYTE_SWAP
long_val = x4reverse_long( (void *)&parent->file_block ) ;
file4write( &parent->tag->index->file, parent->header.left_node + 2*sizeof(short),
&long_val, sizeof( parent->header.right_node ) ) ;
#else
file4write( &parent->tag->index->file, parent->header.left_node + 2*sizeof(short),
&parent->file_block, sizeof( parent->header.right_node ) ) ;
#endif
}
return left->file_block ;
}
#endif
#endif
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
{
CODE4 *c4 ;
INDEX4 *i4 ;
B4BLOCK *old_block, *root_block, *new_block ;
int rc ;
long old_file_block, extend_block ;
#ifdef S4FOX
int key_on ;
long rec1 = 0L ;
long rec2 = 0L ;
unsigned char *temp_key ;
int do_insert, update_reqd ;
#else
int is_branch ;
#endif
#ifdef S4DEBUG
if ( t4 == 0 || key_info == 0 || rec < 1 )
e4severe( e4parm, E4_T4ADD ) ;
#endif
c4 = t4->code_base ;
i4 = t4->index ;
if ( c4->error_code < 0 )
return -1 ;
#ifdef S4FOX
rc = t4go( t4, (char *)key_info, rec ) ;
#else
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
#endif
if ( rc < 0 )
return -1 ;
#ifdef S4FOX
if ( rc == 0 && t4->unique_error == e4unique )
{
e4( c4, e4unique, i4->file.name ) ;
return e4unique ;
}
#endif
#ifdef S4FOX
if ( (t4->header.type_code & 0x01) && rc == r4found )
#else
if ( t4->header.unique && rc == 0 )
#endif
{
switch ( t4->unique_error )
{
case e4unique:
return e4( c4, e4unique, i4->file.name ) ;
case r4unique:
return r4unique ;
case r4unique_continue:
return r4unique_continue ;
default:
break ;
}
}
if ( t4->filter && !t4->has_keys )
{
file4write(&t4->index->file, t4->header_offset+sizeof(t4->header)+222, (char *) "\0", (int) 1 ) ;
t4->has_keys = (char)1 ;
#ifdef S4MDX
t4->had_keys = (char)0 ;
#endif
}
old_block = t4block(t4) ;
old_file_block = 0 ;
#ifdef S4FOX
do_insert = 1 ;
update_reqd = 0 ;
for( ;; )
{
if ( do_insert == 1 )
{
i4->tag_index->header.version = i4->version_old+1 ;
if ( old_block == 0 )
{
/* Must create a new root block */
extend_block = i4extend(i4) ;
if ( extend_block < 0 )
return (int)extend_block ;
root_block = b4alloc( t4, extend_block) ;
if ( root_block == 0 )
return -1 ;
root_block->header.left_node = -1 ;
root_block->header.right_node = -1 ;
root_block->header.node_attribute = 1 ;
l4add( &t4->blocks, root_block ) ;
#ifndef S4SINGLE
if ( t4->index->file.is_exclusive == 0 )
{
old_file_block = t4swap( root_block, (B4BLOCK *)l4last( &t4->saved ) ) ;
if ( old_file_block < 0 )
return -1 ;
}
#endif
b4top( root_block ) ;
b4insert( root_block, temp_key, rec, rec2, 1 ) ;
b4insert( root_block, key_info, old_file_block, rec1, 1 ) ;
rec1 = 0L ;
rec2 = 0L ;
t4->header.root = root_block->file_block ;
t4->root_write = 1 ;
return 0 ;
}
if ( (rc = b4insert( old_block, key_info, rec, rec1, 0 )) != 1 )
{
if ( rc == 0 )
{
if ( b4leaf( old_block ) )
{
temp_key = key_info ;
rec2 = rec ;
}
if ( old_block->key_on == old_block->header.n_keys - 1 )
update_reqd = 1 ;
do_insert = 0 ;
continue ;
}
else
return rc ;
}
else
{
l4pop( &t4->blocks ) ;
key_on = old_block->key_on ;
/* The new block's end key gets added to the block just up */
new_block= t4split( t4, old_block ) ;
if ( new_block == 0 )
return -1 ;
l4add( &t4->saved, old_block ) ;
if ( key_on < old_block->header.n_keys )
{
b4go( old_block, key_on ) ;
b4insert( old_block, key_info, rec, rec1, 0 ) ;
}
else
{
b4go( new_block, key_on - old_block->header.n_keys ) ;
b4insert( new_block, key_info, rec, rec1, 0 ) ;
if ( new_block->key_on == new_block->header.n_keys - 1 )
update_reqd = 1 ;
}
#ifdef S4INDEX_VERIFY
if ( b4verify( old_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
if ( b4verify( new_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
#endif
/* Now add to the block just up */
b4go_eof( old_block ) ;
old_block->key_on-- ;
key_info = b4key_key( old_block, old_block->key_on ) ;
old_file_block = old_block->file_block ;
rec1 = b4recno( old_block, old_block->key_on ) ;
rec = new_block->file_block ;
if ( b4flush(new_block) < 0 )
return -1 ;
b4go_eof( new_block ) ;
new_block->key_on-- ;
temp_key = (unsigned char *)c4->saved_key ;
memcpy( (void *)temp_key, (void *)b4key_key( new_block, new_block->key_on ), t4->header.key_len ) ;
rec2 = b4recno( new_block, new_block->key_on ) ;
if( new_block->key_on == new_block->header.n_keys - 1 )
update_reqd = 1 ;
b4free( new_block ) ;
}
}
else
l4add( &t4->saved, l4pop( &t4->blocks ) ) ;
old_block = (B4BLOCK *)t4->blocks.last_node ;
if ( old_block == 0 )
{
if ( do_insert == 0 )
return 0 ;
}
else
if ( update_reqd ) /* may have to update a parent block */
{
b4br_replace( old_block, (char *)temp_key, rec2 ) ;
if ( old_block->key_on != old_block->header.n_keys - 1 ) /* done reqd updates */
update_reqd = 0 ;
}
}
#else /* if not S4FOX */
i4->changed = 1 ;
t4->changed = 1 ;
t4->header.version++ ;
for(;;)
{
if ( old_block == 0 )
{
/* Must create a new root block */
extend_block = i4extend(i4) ;
if ( extend_block < 0 )
return (int) extend_block ;
root_block = b4alloc( t4, extend_block) ;
if ( root_block == 0 )
return -1 ;
l4add( &t4->blocks, root_block ) ;
b4insert( root_block, key_info, old_file_block ) ;
b4insert( root_block, key_info, rec ) ;
root_block->n_keys-- ;
t4->header.root = root_block->file_block ;
t4->root_write = 1 ;
return 0 ;
}
if ( old_block->n_keys < old_block->tag->header.keys_max )
{
b4insert( old_block, key_info, rec ) ;
return 0 ;
}
l4pop( &t4->blocks ) ;
is_branch = b4leaf( old_block ) ? 0 : 1 ;
/* NNNNOOOO N - New, O - Old */
/* The new block's end key gets added to the block just up */
new_block= t4split( t4, old_block ) ;
if ( new_block == 0 )
return -1 ;
l4add( &t4->saved, new_block ) ;
new_block->n_keys -= (short)is_branch ;
if ( new_block->key_on < (new_block->n_keys+is_branch) )
b4insert( new_block, key_info, rec ) ;
else
b4insert( old_block, key_info, rec ) ;
#ifdef S4INDEX_VERIFY
if ( b4verify( old_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
if ( b4verify( new_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
#endif
/* Now add to the block just up */
new_block->key_on = b4lastpos(new_block) ;
key_info = b4key_key( new_block, new_block->key_on ) ;
rec = new_block->file_block ;
old_file_block = old_block->file_block ;
if ( b4flush(old_block) < 0 )
return -1 ;
b4free( old_block ) ;
old_block = (B4BLOCK *) t4->blocks.last_node ;
}
#endif
}
int S4FUNCTION t4add_calc( TAG4 *t4, long rec )
{
int len ;
char *ptr ;
#ifdef S4DEBUG
if ( t4 == 0 || rec < 1 )
e4severe( e4parm, E4_T4ADD_CALC ) ;
#endif
if ( t4->code_base->error_code < 0 )
return -1 ;
if ( t4->filter )
if ( !expr4true( t4->filter ) )
return 0;
len = t4expr_key( t4, &ptr ) ;
if ( len < 0 )
return -1 ;
#ifdef S4DEBUG
if ( len != t4->header.key_len )
e4severe( e4result, E4_T4ADD_CALC ) ;
#endif
return t4add( t4, (unsigned char *)ptr, rec ) ;
}
#endif /* ifndef N4OTHER */
#ifdef N4OTHER
#ifdef S4NDX
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
{
CODE4 *c4 ;
INDEX4 *i4 ;
B4BLOCK *old_block, *root_block, *new_block, *wch_block ;
int rc, is_branch ;
long old_file_block, extend_block ;
char key_data[I4MAX_KEY_SIZE+1] ; /* temporary storage for the key data (max size 100) */
char key2_data[I4MAX_KEY_SIZE+1] ;
B4KEY_DATA *at_new ;
#ifdef S4DEBUG
if ( t4 == 0 || key_info == 0 || rec < 1 )
e4severe( e4parm, E4_T4ADD ) ;
#endif
c4 = t4->code_base ;
i4 = t4->index ;
if ( c4->error_code < 0 )
return -1 ;
rc = t4go( t4, (char *)key_info, rec ) ;
if ( rc < 0 )
return -1 ;
if ( rc == 0 && t4->unique_error == e4unique )
{
e4( c4, e4unique, i4->file.name ) ;
return e4unique ;
}
if ( rc == r4found || rc == 0 )
{
switch ( t4->unique_error )
{
case e4unique:
return e4( c4, e4unique, i4->file.name ) ;
case r4unique:
return r4unique ;
case r4unique_continue:
return r4unique_continue ;
default:
break ;
}
}
old_block = t4block( t4 ) ;
old_file_block = 0 ;
t4->header.version = t4->header.old_version + 1 ;
for(;;)
{
if ( old_block == 0 )
{
/* Must create a new root block */
extend_block = t4extend( t4 ) ;
if ( extend_block < 0 )
return (int)extend_block ;
root_block = b4alloc( t4, extend_block ) ;
if ( root_block == 0 )
return -1 ;
l4add( &t4->blocks, root_block ) ;
i4get_last_key( t4, key_data, old_file_block ) ;
b4insert( root_block, key_data, 0L, old_file_block ) ;
b4append( root_block, rec ) ;
t4->header.root = root_block->file_block ;
t4->root_write = 1 ;
return 0 ;
}
if ( b4room( old_block ) )
{
if ( b4leaf( old_block ) )
b4insert( old_block, key_info, rec, 0L ) ;
else
{
b4get_last_key( old_block, key_data ) ;
if ( old_block->key_on >= old_block->n_keys ) /*insert at end done different */
{
b4insert( old_block, key_data, 0L, old_file_block ) ;
b4append( old_block, rec ) ;
}
else
{
at_new = b4key( old_block, old_block->key_on ) ;
at_new->pointer = rec ;
b4insert( old_block, key_data, 0L, old_file_block ) ;
}
}
return 0 ;
}
l4pop( &t4->blocks ) ;
is_branch = b4leaf( old_block ) ? 0 : 1 ;
/* NNNNOOOO N - New, O - Old */
/* The new block's end key gets added to the block just up */
new_block= t4split( t4, old_block ) ;
if ( new_block == 0 )
return -1 ;
l4add( &t4->saved, new_block ) ;
/* which block should do the insertion ? */
if ( old_block->key_on < (old_block->n_keys + is_branch) )
wch_block = old_block ;
else wch_block = new_block ;
if ( b4leaf( wch_block ) )
b4insert( wch_block, key_info, rec, 0L ) ;
else
{
b4get_last_key( wch_block, key_data ) ;
if ( wch_block->key_on >= wch_block->n_keys ) /* insert at end done different */
{
b4insert( wch_block, key_data, 0L, old_file_block ) ;
b4append( wch_block, rec ) ;
}
else
{
at_new = b4key( wch_block, wch_block->key_on ) ;
at_new->pointer = rec ;
b4insert( wch_block, key_data, 0L, old_file_block ) ;
}
}
#ifdef S4INDEX_VERIFY
if ( b4verify( old_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
if ( b4verify( new_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
#endif
/* Now add to the block just up */
new_block->key_on = b4lastpos(new_block) ;
key_info = b4key_key( new_block, new_block->key_on ) ;
rec = new_block->file_block ;
if( !b4leaf( new_block ) )
if ( b4get_last_key( new_block, key2_data ) != 4)
key_info = (unsigned char *)key2_data ;
old_block->key_on = b4lastpos( old_block ) ;
memcpy( key_data, b4key_key( old_block, old_block->key_on ), t4->header.key_len ) ;
old_file_block = old_block->file_block ;
if ( b4flush( old_block ) < 0 )
return -1 ;
b4free( old_block ) ;
old_block = (B4BLOCK *) t4->blocks.last_node ;
}
}
#else
#ifdef S4CLIPPER
int S4FUNCTION t4add( TAG4 *t4, unsigned char *key_info, long rec )
{
CODE4 *c4 ;
INDEX4 *i4 ;
B4BLOCK *old_block, *root_block, *new_block, *wch_block ;
int rc, is_branch ;
long old_file_block, extend_block, new_file_block ;
B4KEY_DATA *at_new ;
unsigned char old_key_ptr[ I4MAX_KEY_SIZE ] ;
unsigned char key_data[I4MAX_KEY_SIZE+1] ; /* temporary storage for the key data (max size 100) */
int old_desc, inc_pos ;
#ifndef S4SINGLE
int d_set ;
#ifdef S4DEBUG_DEV
long findVal ;
int trc ;
#endif
#endif
#ifdef S4DEBUG
if ( t4 == 0 || key_info == 0 || rec < 1 )
e4severe( e4parm, E4_T4ADD ) ;
#endif
c4 = t4->code_base ;
i4 = t4->index ;
if ( c4->error_code < 0 )
return -1 ;
old_desc = t4->header.descending ;
t4descending( t4, 0 ) ;
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
#ifndef S4SINGLE
if ( rc == 0 && t4->unique_error == 0 )
{
for( d_set = 0, inc_pos = t4->header.key_len - 1 ; d_set == 0 && inc_pos >=0 ; inc_pos-- )
if ( key_info[inc_pos] != 0xFF )
{
key_info[inc_pos]++ ;
d_set = 1 ;
if ( t4seek( t4, (char *)key_info, t4->header.key_len ) < 0 )
return -1 ;
key_info[inc_pos]-- ;
#ifdef S4DEBUG_DEV
findVal = t4recno( t4 ) ;
#endif
}
#ifdef S4DEBUG_DEV
rc = t4seek( t4, (char *)key_info, t4->header.key_len ) ;
if ( rc != 0 || t4->unique_error != 0 )
findVal = -2L ;
for(;;)
{
if ( (*t4->cmp)( t4key_data( t4 )->value, key_info, t4->header.key_len ) == 0 )
{
trc = t4skip( t4, 1L ) ;
if ( trc == 0L )
{
b4go_eof( t4block( t4 ) ) ;
break ;
}
}
else
break ;
}
if ( t4recno( t4 ) != findVal )
e4severe( e4index, "i4addtag() - record number mismatch" ) ;
#endif
}
#endif
t4descending( t4, old_desc ) ;
if ( rc < 0 )
return -1 ;
if ( rc == 0 )
{
switch ( t4->unique_error )
{
case e4unique:
return e4( c4, e4unique, i4->file.name ) ;
case r4unique:
return r4unique ;
case r4unique_continue:
return r4unique_continue ;
default:
break ;
}
}
old_block = t4block(t4) ;
old_file_block = 0 ;
new_file_block = 0 ;
t4->header.version = (short)(t4->header.old_version + 1L) ;
while( !b4leaf( old_block ) )
{
rc = t4down( t4 ) ;
if ( rc < 0 || rc == 2 )
return -1 ;
old_block = t4block( t4 ) ;
if ( b4leaf( old_block ) )
old_block->key_on = b4lastpos( old_block ) + 1 ;
else
old_block->key_on = b4lastpos( old_block ) ;
}
for(;;)
{
if ( old_block == 0 )
{
/* Must create a new root block */
extend_block = t4extend( t4 ) ;
if ( extend_block < 0 )
return (int) extend_block ;
root_block = b4alloc( t4, extend_block) ;
if ( root_block == 0 )
return -1 ;
l4add( &t4->blocks, root_block ) ;
b4insert( root_block, key_info, rec, old_file_block ) ;
t4->header.root = root_block->file_block * 512 ; /* line order here so that the index validation works */
b4append( root_block, new_file_block ) ;
t4->root_write = 1 ;
return 0 ;
}
if ( b4room( old_block ) )
{
if ( b4leaf( old_block ) )
b4insert( old_block, key_info, rec, 0L ) ;
else /* update the current pointer, add the new branch */
{
#ifdef S4DEBUG
if ( old_block->n_keys == 0 )
e4severe( e4info, E4_T4ADD ) ;
/*
{
b4insert( old_block, key_info, rec, old_file_block ) ;
at_new = b4key( old_block, 1 ) ;
at_new->pointer = new_file_block * 512 ;
}
else
{
...
}
*/
#endif
at_new = b4key( old_block, old_block->key_on ) ;
at_new->pointer = new_file_block * 512 ;
b4insert( old_block, key_info, rec, old_file_block ) ;
}
return 0 ;
}
l4pop( &t4->blocks ) ;
is_branch = b4leaf( old_block ) ? 0 : 1 ;
/* NNNNOOOO N - New, O - Old */
/* The new block's end key gets added to the block just up */
if ( old_block->key_on < (t4->header.keys_half + is_branch) )
{
new_block= t4split( t4, old_block, 0 ) ;
if ( new_block == 0 )
return -1 ;
wch_block = old_block ;
}
else
{
new_block= t4split( t4, old_block, 1 ) ;
if ( new_block == 0 )
return -1 ;
wch_block = new_block ;
}
if ( b4leaf( wch_block ) )
{
b4insert( wch_block, key_info, rec, 0L ) ;
if ( new_block->n_keys <= t4->header.keys_half ) /* add a key from the old block!, must have info in new_block because old_block gets deleted below */
{
#ifdef S4DEBUG
if ( old_block->n_keys <= t4->header.keys_half ) /* impossible */
e4severe( e4info, E4_INFO_CIF ) ;
#endif
old_block->key_on = old_block->n_keys - 1 ;
memcpy( key_data, b4key_key( old_block, old_block->key_on ), t4->header.key_len ) ;
key_info = key_data ;
rec = b4key( old_block, old_block->key_on )->num ;
b4remove( old_block ) ;
new_block->key_on = 0 ;
b4insert( new_block, key_info, rec, 0 ) ;
}
new_block->key_on = 0 ;
memcpy( key_data, b4key_key( new_block, new_block->key_on ), t4->header.key_len ) ;
key_info = key_data ;
rec = b4key( new_block, new_block->key_on )->num ;
b4remove( new_block ) ;
}
else
{
/* now get the key to place upwards */
if ( wch_block->n_keys == 0 ) /* treat like a root block */
{
#ifdef S4DEBUG
if ( wch_block == old_block )
e4severe( e4info, "t4add - split distribution incorrect" ) ;
#endif
b4insert( wch_block, key_info, rec, old_file_block ) ;
b4append( wch_block, new_file_block ) ;
}
else
{
if ( wch_block->key_on > wch_block->n_keys && wch_block == old_block )
{
at_new = b4key( new_block, 0 ) ;
at_new->pointer = new_file_block * 512 ;
}
else
{
at_new = b4key( wch_block, wch_block->key_on ) ;
at_new->pointer = new_file_block * 512 ;
}
b4insert( wch_block, key_info, rec, old_file_block ) ;
}
memcpy( old_key_ptr, b4key_key( old_block, b4lastpos( old_block )), t4->header.key_len ) ;
key_info = old_key_ptr ;
rec = b4key( old_block, b4lastpos( old_block ) )->num ;
}
#ifdef S4INDEX_VERIFY
if ( b4verify( old_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-old after split", "" ) ;
if ( b4verify( new_block ) == -1 )
e4describe( t4->code_base, e4index, t4->alias, "t4split()-new after split", "" ) ;
#endif
l4add( &t4->saved, new_block ) ;
new_file_block = new_block->file_block ;
old_file_block = old_block->file_block ;
if ( b4flush( old_block ) < 0 )
return -1 ;
b4free( old_block ) ;
old_block = (B4BLOCK *) t4->blocks.last_node ;
}
}
#endif /* ifdef S4CLIPPER */
#endif /* ifdef S4NDX */
int S4FUNCTION t4add_calc( TAG4 *t4, long rec )
{
char *ptr ;
#ifdef S4DEBUG
if ( t4 == 0 || rec < 1 )
e4severe( e4parm, E4_T4ADD_CALC ) ;
#endif
if ( t4->code_base->error_code < 0 )
return -1 ;
#ifdef S4CLIPPER
if ( t4->filter )
if ( !expr4true( t4->filter ) )
return 0;
#endif
if ( t4expr_key( t4, &ptr ) < 0 )
return -1 ;
return t4add( t4, (unsigned char *)ptr, rec ) ;
}
#endif /* ifdef N4OTHER */
#endif /* S4OFF_WRITE */
#endif /* S4INDEX_OFF */