campo-sirio/cb5/i4index.c
alex a0f5e0898b This commit was generated by cvs2svn to compensate for changes in r975,
which included commits to RCS files with non-trunk default branches.

git-svn-id: svn://10.65.10.50/trunk@976 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-02-06 15:33:45 +00:00

1381 lines
32 KiB
C
Executable File

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