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
846 lines
21 KiB
C
Executable File
846 lines
21 KiB
C
Executable File
/* c4const.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
|
|
|
|
/* This function creates a branch out of the input constant, and combines it with the input map */
|
|
static void bitmap4constant_combine( BITMAP4 *parent, BITMAP4 *old_and_map, CONST4 *con, int con_type )
|
|
{
|
|
BITMAP4 *temp_leaf, *and_map, *new_branch ;
|
|
CONST4 *temp ;
|
|
|
|
if ( con->len == 0 || parent->log->code_base->error_code == e4memory )
|
|
return ;
|
|
|
|
new_branch = bitmap4create( parent->log, parent->relate, 1, 1 ) ;
|
|
if ( new_branch == 0 )
|
|
return ;
|
|
|
|
and_map = bitmap4create( parent->log, parent->relate, 0, 0 ) ;
|
|
if ( and_map == 0 )
|
|
return ;
|
|
bitmap4copy( and_map, old_and_map ) ;
|
|
l4add( &new_branch->children, and_map ) ;
|
|
|
|
temp_leaf = bitmap4create( parent->log, parent->relate, 1, 0 ) ;
|
|
if ( temp_leaf == 0 )
|
|
return ;
|
|
temp_leaf->type = and_map->type ;
|
|
temp_leaf->tag = and_map->tag ;
|
|
l4add( &new_branch->children, temp_leaf ) ;
|
|
|
|
switch( con_type )
|
|
{
|
|
case 1:
|
|
memcpy( (void *)&temp_leaf->lt, (void *)con, sizeof( CONST4 ) ) ;
|
|
break ;
|
|
case 2:
|
|
memcpy( (void *)&temp_leaf->le, (void *)con, sizeof( CONST4 ) ) ;
|
|
break ;
|
|
case 3:
|
|
memcpy( (void *)&temp_leaf->gt, (void *)con, sizeof( CONST4 ) ) ;
|
|
break ;
|
|
case 4:
|
|
memcpy( (void *)&temp_leaf->ge, (void *)con, sizeof( CONST4 ) ) ;
|
|
break ;
|
|
case 5:
|
|
memcpy( (void *)&temp_leaf->eq, (void *)con, sizeof( CONST4 ) ) ;
|
|
break ;
|
|
case 6:
|
|
temp = (CONST4 *)u4alloc( sizeof( CONST4 ) ) ;
|
|
if ( temp == 0 )
|
|
return ;
|
|
memcpy( (void *)temp, (void *)con, sizeof( CONST4 ) ) ;
|
|
l4add( &temp_leaf->ne, temp ) ;
|
|
break ;
|
|
default:
|
|
#ifdef S4DEBUG
|
|
e4severe( e4info, E4_BM4CON_COMBINE ) ;
|
|
#endif
|
|
return ;
|
|
}
|
|
memset( (void *)con, 0 ,sizeof( CONST4 ) ) ;
|
|
new_branch = bitmap4redistribute( 0, new_branch, 0 ) ;
|
|
|
|
if ( new_branch->children.n_link == 0 )
|
|
bitmap4destroy( new_branch ) ;
|
|
else
|
|
l4add( &parent->children, new_branch ) ;
|
|
}
|
|
|
|
/* this function redistributes (splits and combines) and/and, or/or block sequences */
|
|
BITMAP4 * S4FUNCTION bitmap4redistribute( BITMAP4 *parent, BITMAP4 *map, char do_shrink )
|
|
{
|
|
BITMAP4 *child_map, *child_on, *parent2map ;
|
|
char split ;
|
|
|
|
if ( map->branch == 0 )
|
|
return map ;
|
|
|
|
/* first combine all the children of this map */
|
|
child_on = child_map = (BITMAP4 *)l4first( &map->children ) ;
|
|
for( ;; )
|
|
{
|
|
if ( child_on == 0 )
|
|
break ;
|
|
child_on = bitmap4redistribute( map, child_on, 0 ) ;
|
|
child_on = (BITMAP4 *)l4next( &map->children, child_on ) ;
|
|
}
|
|
|
|
/* now combine all leaf children where possible */
|
|
if ( parent != 0 )
|
|
if ( parent->and_or != map->and_or ) /* case where no combos possible */
|
|
return map ;
|
|
|
|
parent2map = 0 ;
|
|
child_on = child_map = (BITMAP4 *)l4first( &map->children ) ;
|
|
for( ; child_map != 0 ; )
|
|
{
|
|
child_on = (BITMAP4 *)l4next( &map->children, child_map ) ;
|
|
if ( child_on == 0 )
|
|
break ;
|
|
|
|
split = 0 ;
|
|
if ( child_on->tag != child_map->tag || child_on->and_or != child_map->and_or )
|
|
split = 1 ;
|
|
else
|
|
{
|
|
if ( map != 0 )
|
|
if ( map->and_or != child_on->and_or )
|
|
split = 1 ;
|
|
}
|
|
|
|
if ( split == 1 )
|
|
{
|
|
if ( parent2map == 0 )
|
|
{
|
|
parent2map = bitmap4create( map->log, map->relate, map->and_or, 1 ) ;
|
|
if ( parent2map == 0 ) /* must handle by freeing... */
|
|
return 0 ;
|
|
if ( parent == 0 )
|
|
{
|
|
parent = bitmap4create( map->log, map->relate, map->and_or, 1 ) ;
|
|
if ( parent == 0 ) /* must handle by freeing... */
|
|
return 0 ;
|
|
l4add( &parent->children, map ) ;
|
|
}
|
|
l4add( &parent->children, parent2map ) ;
|
|
}
|
|
l4remove( &map->children, child_on ) ;
|
|
l4add( &parent2map->children, child_on ) ;
|
|
}
|
|
else
|
|
child_map = bitmap4combine_leafs( map, child_map, child_on ) ;
|
|
}
|
|
|
|
if ( parent2map != 0 )
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( parent == 0 )
|
|
e4severe( e4info, E4_BM4REDIST ) ;
|
|
#endif
|
|
bitmap4redistribute( parent, parent2map, 1 ) ;
|
|
}
|
|
|
|
if ( do_shrink )
|
|
{
|
|
if ( map->children.n_link == 1 ) /* just a child, so remove myself */
|
|
{
|
|
child_map = (BITMAP4 *)l4first( &map->children ) ;
|
|
l4remove( &map->children, child_map ) ;
|
|
if ( parent != 0 )
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( child_map->tag == 0 && child_map->children.n_link == 0 )
|
|
e4severe( e4info, E4_BM4REDIST ) ;
|
|
#endif
|
|
if ( parent->tag == 0 && child_map->tag != 0 )
|
|
parent->tag = child_map->tag ;
|
|
l4add_after( &parent->children, map, child_map ) ;
|
|
l4remove( &parent->children, map ) ;
|
|
}
|
|
bitmap4destroy( map ) ;
|
|
map = child_map ;
|
|
}
|
|
}
|
|
|
|
if ( parent2map != 0 && parent != 0 )
|
|
return parent ;
|
|
|
|
return map ;
|
|
}
|
|
|
|
/* this function redistributes the input maps by breaking the one up into constants and creating maps for each */
|
|
BITMAP4 * S4FUNCTION bitmap4redistribute_leaf( BITMAP4 *parent, BITMAP4 *map1, BITMAP4 *map2 )
|
|
{
|
|
BITMAP4 *new_branch, *or_map, *place, *and_map, *temp ;
|
|
CONST4 *c_on ;
|
|
|
|
new_branch = bitmap4create( parent->log, parent->relate, 1, 1 ) ;
|
|
if ( new_branch == 0 )
|
|
return 0 ;
|
|
|
|
place = bitmap4create( parent->log, parent->relate, 0, 0 ) ;
|
|
if ( place == 0 )
|
|
return 0 ;
|
|
l4add_after( &parent->children, map1, place ) ;
|
|
|
|
l4remove( &parent->children, map1 ) ;
|
|
l4remove( &parent->children, map2 ) ;
|
|
|
|
if ( map1->and_or == 1 )
|
|
{
|
|
and_map = map1 ;
|
|
or_map = map2 ;
|
|
}
|
|
else
|
|
{
|
|
and_map = map2 ;
|
|
or_map = map1 ;
|
|
}
|
|
|
|
bitmap4constant_combine( new_branch, and_map, &or_map->lt, 1 ) ;
|
|
bitmap4constant_combine( new_branch, and_map, &or_map->le, 2 ) ;
|
|
bitmap4constant_combine( new_branch, and_map, &or_map->gt, 3 ) ;
|
|
bitmap4constant_combine( new_branch, and_map, &or_map->ge, 4 ) ;
|
|
bitmap4constant_combine( new_branch, and_map, &or_map->eq, 5 ) ;
|
|
for( ;; )
|
|
{
|
|
c_on = (CONST4 *)l4first( &or_map->ne ) ;
|
|
if ( c_on == 0 )
|
|
break ;
|
|
bitmap4constant_combine( new_branch, and_map, c_on, 6 ) ;
|
|
}
|
|
|
|
if ( parent->log->code_base->error_code == e4memory )
|
|
return 0 ;
|
|
|
|
if ( new_branch->children.n_link == 0 ) /* collapsed */
|
|
{
|
|
if ( parent->tag == 0 && and_map->tag != 0 )
|
|
parent->tag = and_map->tag ;
|
|
bitmap4destroy( new_branch ) ;
|
|
new_branch = 0 ;
|
|
}
|
|
else
|
|
{
|
|
while( new_branch->branch == 1 && new_branch->children.n_link == 1 )
|
|
{
|
|
temp = (BITMAP4 *)l4first( &new_branch->children ) ;
|
|
bitmap4destroy( new_branch ) ;
|
|
new_branch = temp ;
|
|
}
|
|
l4add_after( &parent->children, place, new_branch ) ;
|
|
}
|
|
|
|
l4remove( &parent->children, place ) ;
|
|
bitmap4destroy( place ) ;
|
|
bitmap4destroy( or_map ) ;
|
|
bitmap4destroy( and_map ) ;
|
|
|
|
return new_branch ;
|
|
}
|
|
|
|
/* this function splits and combines and/or, or/and block sequences */
|
|
/* all bitmaps must be in standard bitmap4redistribute format prior to call */
|
|
BITMAP4 * S4FUNCTION bitmap4redistribute_branch( BITMAP4 *parent, BITMAP4 *map )
|
|
{
|
|
BITMAP4 *child_on2, *child_on, *child_next2 ;
|
|
|
|
if ( map->branch == 0 )
|
|
return map ;
|
|
|
|
child_on = (BITMAP4 *)l4first( &map->children ) ;
|
|
|
|
for( ;; )
|
|
{
|
|
if ( child_on == 0 )
|
|
break ;
|
|
if ( child_on->branch )
|
|
{
|
|
child_on = bitmap4redistribute_branch( map, child_on ) ;
|
|
if ( child_on == 0 && parent->log->code_base->error_code == e4memory )
|
|
return 0 ;
|
|
}
|
|
if ( child_on->branch == 0 )
|
|
{
|
|
child_on2 = (BITMAP4 *)l4next( &map->children, child_on ) ;
|
|
while( child_on2 != 0 )
|
|
{
|
|
if ( child_on2->branch )
|
|
{
|
|
child_on2 = bitmap4redistribute_branch( map, child_on2 ) ;
|
|
if ( child_on2 == 0 && parent->log->code_base->error_code == e4memory )
|
|
return 0 ;
|
|
}
|
|
child_next2 = (BITMAP4 *)l4next( &map->children, child_on2 ) ;
|
|
if ( child_on->branch == 0 && map->and_or == 1 && child_on->tag == child_on2->tag && child_on->and_or != child_on2->and_or )
|
|
{
|
|
child_on = bitmap4redistribute_leaf( map, child_on, child_on2 ) ;
|
|
if ( child_on == 0 && parent->log->code_base->error_code == e4memory )
|
|
return 0 ;
|
|
}
|
|
child_on2 = child_next2 ;
|
|
}
|
|
}
|
|
child_on = (BITMAP4 *)l4next( &map->children, child_on ) ;
|
|
}
|
|
|
|
if ( map->branch == 1 )
|
|
{
|
|
if ( map->children.n_link == 0 ) /* mark ourselves as a leaf with no match */
|
|
{
|
|
map->branch = 0 ;
|
|
map->no_match = 1 ;
|
|
}
|
|
else
|
|
if ( map->children.n_link == 1 ) /* just a child, so remove myself */
|
|
{
|
|
child_on = (BITMAP4 *)l4first( &map->children ) ;
|
|
l4remove( &map->children, child_on ) ;
|
|
if ( parent != 0 )
|
|
{
|
|
l4add_after( &parent->children, map, child_on ) ;
|
|
l4remove( &parent->children, map ) ;
|
|
}
|
|
bitmap4destroy( map ) ;
|
|
map = child_on ;
|
|
}
|
|
}
|
|
|
|
return map ;
|
|
}
|
|
|
|
/* location = 0 if seek_before, 1 if seek 1st, 2 if seek last, 3 if seek_after, */
|
|
/* add 10 if it is to be an approximate seek */
|
|
/* returns record number */
|
|
#ifdef S4HAS_DESCENDING
|
|
long S4FUNCTION bitmap4seek( BITMAP4 *map, CONST4 *con, char location, long check, int do_check )
|
|
{
|
|
int len, rc ;
|
|
TAG4 *tag ;
|
|
char *result ;
|
|
#ifdef S4CLIPPER
|
|
int old_dec ;
|
|
char hold_result[20] ; /* enough space for a numerical key */
|
|
#endif
|
|
|
|
tag = map->tag ;
|
|
result = (char *)const4return( map->log, con ) ;
|
|
|
|
if ( map->type != r4str ) /* must convert to a proper key */
|
|
{
|
|
#ifdef S4CLIPPER
|
|
{
|
|
old_dec = tag->code_base->decimals ;
|
|
tag->code_base->decimals = tag->header.key_dec ;
|
|
memcpy( hold_result, result, con->len ) ;
|
|
result = hold_result ;
|
|
#endif
|
|
#ifdef S4DEBUG
|
|
if ( expr4len( tag->expr ) == -1 )
|
|
e4severe( e4info, E4_BM4_IEL ) ;
|
|
#endif
|
|
len = expr4key_convert( tag->expr, (char **)&result, con->len, map->type ) ;
|
|
#ifdef S4CLIPPER
|
|
tag->code_base->decimals = old_dec ;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
len = con->len ;
|
|
|
|
if ( location > 1 )
|
|
t4descending( tag, 1 ) ;
|
|
else
|
|
t4descending( tag, 0 ) ;
|
|
t4seek( tag, result, len ) ;
|
|
t4descending( tag, 0 ) ;
|
|
|
|
if ( !t4eof( tag ) )
|
|
if ( do_check == 1 )
|
|
if ( check == t4recno( tag ) )
|
|
return -1 ;
|
|
|
|
switch ( location )
|
|
{
|
|
case 0:
|
|
if ( t4skip( tag, -1L ) != -1L ) /* at top already */
|
|
return -1 ;
|
|
break ;
|
|
case 1:
|
|
if ( t4eof( tag ) )
|
|
return -1 ;
|
|
break ;
|
|
case 2:
|
|
#ifdef S4FOX
|
|
if( u4memcmp( t4key_data(tag)->value, result, len ) != 0 ) /* last one is too far, go back one for a closure */
|
|
#else
|
|
if( (*tag->cmp)( t4key_data(tag)->value, result, len ) != 0 ) /* last one is too far, go back one for a closure */
|
|
#endif
|
|
{
|
|
if ( !t4eof( tag ) )
|
|
if ( do_check == 1 )
|
|
if ( check == t4recno( tag ) ) /* case where none belong, so break now */
|
|
return -1 ;
|
|
}
|
|
break ;
|
|
case 3:
|
|
rc = (int)t4skip( tag, 1L ) ;
|
|
if ( rc == 0L )
|
|
return -1 ;
|
|
break ;
|
|
default:
|
|
#ifdef S4DEBUG
|
|
e4severe( e4info, E4_BM4SEEK ) ;
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
return t4recno( tag ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4NDX
|
|
long S4FUNCTION bitmap4seek( BITMAP4 *map, CONST4 *con, char location, long check, int do_check )
|
|
{
|
|
int len, rc ;
|
|
TAG4 *tag ;
|
|
char *result ;
|
|
char did_skip ;
|
|
int seek_rc ;
|
|
|
|
tag = map->tag ;
|
|
result = (char *)const4return( map->log, con ) ;
|
|
|
|
if ( map->type != r4str ) /* must convert to a proper key */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( expr4len( tag->expr ) == -1 )
|
|
e4severe( e4info, E4_BM4_IEL ) ;
|
|
#endif
|
|
len = expr4key_convert( tag->expr, (char **)&result, con->len, map->type ) ;
|
|
}
|
|
else
|
|
len = con->len ;
|
|
|
|
seek_rc = t4seek( tag, result, len ) ;
|
|
|
|
if ( !t4eof( tag ) )
|
|
if ( do_check )
|
|
if ( check == t4recno( tag ) )
|
|
return -1 ;
|
|
|
|
switch ( location )
|
|
{
|
|
case 0:
|
|
if ( t4skip( tag, -1L ) != -1L ) /* at top already */
|
|
return -1 ;
|
|
break ;
|
|
case 1:
|
|
if ( t4eof( tag ) )
|
|
return -1 ;
|
|
break ;
|
|
case 2:
|
|
if( (*tag->cmp)( t4key_data(tag)->value, result, len ) != 0 ) /* last one is too far, go back one for a closure */
|
|
{
|
|
if ( !t4eof( tag ) )
|
|
if ( check == t4recno( tag ) ) /* case where none belong, so break now */
|
|
return -1 ;
|
|
if ( t4skip( tag, -1L ) != -1L )
|
|
return -1 ;
|
|
}
|
|
case 3:
|
|
did_skip = 0 ;
|
|
|
|
for(; (*tag->cmp)( t4key_data(tag)->value, result, len ) == 0; )
|
|
{
|
|
rc = (int)t4skip( tag, 1L ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
if ( rc != 1 )
|
|
{
|
|
if ( location == 2 ) /* on last record, but it still belongs, so don't skip back */
|
|
did_skip = 0 ;
|
|
if ( location == 3 ) /* on last record not far enough, so none match */
|
|
return -1 ;
|
|
break ;
|
|
}
|
|
did_skip = 1 ;
|
|
}
|
|
|
|
if ( location == 3 )
|
|
{
|
|
if ( did_skip == 0 && seek_rc != 2 )
|
|
if ( t4skip( tag, 1L ) != 1L )
|
|
return -1 ;
|
|
}
|
|
else
|
|
if ( did_skip == 1 )
|
|
if ( t4skip( tag, -1L ) != -1L )
|
|
return -1 ;
|
|
break ;
|
|
default:
|
|
#ifdef S4DEBUG
|
|
e4severe( e4info, E4_BM4SEEK ) ;
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
return t4recno( tag ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4MDX
|
|
long S4FUNCTION bitmap4seek( BITMAP4 *map, CONST4 *con, char location, long check, int do_check )
|
|
{
|
|
int len, rc, seek_rc, is_desc ;
|
|
TAG4 *tag ;
|
|
char *result ;
|
|
char did_skip ;
|
|
|
|
tag = map->tag ;
|
|
result = (char *)const4return( map->log, con ) ;
|
|
is_desc = ( tag->header.type_code & 8 ) ? 1 : 0 ;
|
|
|
|
if ( map->type != r4str ) /* must convert to a proper key */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( expr4len( tag->expr ) == -1 )
|
|
e4severe( e4info, E4_BM4_IEL ) ;
|
|
#endif
|
|
len = expr4key_convert( tag->expr, (char **)&result, con->len, map->type ) ;
|
|
}
|
|
else
|
|
len = con->len ;
|
|
|
|
seek_rc = t4seek( tag, result, len ) ;
|
|
|
|
if ( !t4eof( tag ) )
|
|
if ( do_check )
|
|
if ( check == t4recno( tag ) )
|
|
return -1 ;
|
|
|
|
switch ( location )
|
|
{
|
|
case 0:
|
|
if ( is_desc )
|
|
{
|
|
if ( t4eof( tag ) )
|
|
return -1 ;
|
|
for(; (*tag->cmp)( t4key_data(tag)->value, result, len ) == 0; )
|
|
{
|
|
rc = (int)t4skip( tag, 1L ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
if ( rc != 1 )
|
|
{
|
|
if ( rc == 0 )
|
|
return -1 ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if ( t4skip( tag, -1L ) != -1L ) /* at top already */
|
|
return -1 ;
|
|
break ;
|
|
case 1:
|
|
if ( is_desc )
|
|
{
|
|
if ( seek_rc == 2 )
|
|
{
|
|
if ( !t4eof( tag ) )
|
|
if ( check == t4recno( tag ) ) /* case where none belong, so break now */
|
|
return -1 ;
|
|
if ( t4skip( tag, -1L ) != -1L )
|
|
return -1 ;
|
|
}
|
|
else
|
|
{
|
|
rc = -1 ;
|
|
for(; (*tag->cmp)( t4key_data(tag)->value, result, len ) == 0; )
|
|
{
|
|
rc = (int)t4skip( tag, 1L ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
if ( rc != 1 )
|
|
break ;
|
|
}
|
|
if ( rc == 0 )
|
|
t4bottom( tag ) ;
|
|
else
|
|
t4skip( tag, -1L ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( t4eof( tag ) )
|
|
return -1 ;
|
|
}
|
|
break ;
|
|
case 2:
|
|
if ( is_desc )
|
|
{
|
|
if ( t4eof( tag ) )
|
|
return -1 ;
|
|
if ( seek_rc == 2 )
|
|
if ( check == t4recno( tag ) ) /* case where none belong, so break now */
|
|
return -1 ;
|
|
break ;
|
|
}
|
|
else
|
|
{
|
|
if( (*tag->cmp)( t4key_data(tag)->value, result, len ) != 0 ) /* last one is too far, go back one for a closure */
|
|
{
|
|
if ( !t4eof( tag ) )
|
|
if ( check == t4recno( tag ) ) /* case where none belong, so break now */
|
|
return -1 ;
|
|
if ( t4skip( tag, -1L ) != -1L )
|
|
return -1 ;
|
|
}
|
|
}
|
|
case 3:
|
|
if ( is_desc )
|
|
{
|
|
if ( t4skip( tag, -1L ) != -1L ) /* at top already */
|
|
return -1 ;
|
|
}
|
|
else
|
|
{
|
|
did_skip = 0 ;
|
|
|
|
for(; (*tag->cmp)( t4key_data(tag)->value, result, len ) == 0; )
|
|
{
|
|
rc = (int)t4skip( tag, 1L ) ;
|
|
if ( rc < 0 )
|
|
return -1 ;
|
|
if ( rc != 1 )
|
|
{
|
|
if ( location == 2 ) /* on last record, but it still belongs, so don't skip back */
|
|
did_skip = 0 ;
|
|
if ( location == 3 ) /* on last record not far enough, so none match */
|
|
return -1 ;
|
|
break ;
|
|
}
|
|
did_skip = 1 ;
|
|
}
|
|
|
|
if ( location == 3 )
|
|
{
|
|
if ( did_skip == 0 && seek_rc != 2 )
|
|
if ( t4skip( tag, 1L ) != 1L )
|
|
return -1 ;
|
|
}
|
|
else
|
|
if ( did_skip == 1 )
|
|
if ( t4skip( tag, -1L ) != -1L )
|
|
return -1 ;
|
|
}
|
|
break ;
|
|
default:
|
|
#ifdef S4DEBUG
|
|
e4severe( e4info, E4_BM4SEEK ) ;
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
return t4recno( tag ) ;
|
|
}
|
|
#endif
|
|
|
|
/* returns a pointer to the constant value */
|
|
void *S4FUNCTION const4return( L4LOGICAL *log, CONST4 *c1 )
|
|
{
|
|
return (void *)( log->buf + c1->offset ) ;
|
|
}
|
|
|
|
/* updates the log's constant memory buffer, re-allocating memory if required */
|
|
int S4FUNCTION const4mem_alloc( L4LOGICAL *log, unsigned len )
|
|
{
|
|
if ( ( log->buf_pos + len ) > log->buf_len )
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( (long)len + (long)log->buf_len != (long)(len + log->buf_len) )
|
|
e4severe( e4memory, E4_MEMORY_OOR ) ;
|
|
#endif
|
|
if ( u4alloc_again( log->code_base, &log->buf, &log->buf_len, log->buf_pos + len ) != 0 )
|
|
return -1 ;
|
|
}
|
|
log->buf_pos += len ;
|
|
return 0 ;
|
|
}
|
|
|
|
/* duplicate an existing constant */
|
|
int S4FUNCTION const4duplicate( CONST4 *to, CONST4 *from, L4LOGICAL *log )
|
|
{
|
|
unsigned len ;
|
|
|
|
len = from->len ;
|
|
|
|
if ( len == 0 )
|
|
memset( (void *)to, 0, sizeof( CONST4 ) ) ;
|
|
else
|
|
{
|
|
if ( const4mem_alloc( log, len ) < 0 )
|
|
return -1 ;
|
|
memcpy( log->buf + log->buf_pos - len, const4return( log, from ), len ) ;
|
|
to->offset = log->buf_len - len ;
|
|
to->len = len ;
|
|
}
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
/* get a constant from an expr. info structure */
|
|
int S4FUNCTION const4get( CONST4 *con, BITMAP4 *map, L4LOGICAL *log, int pos )
|
|
{
|
|
unsigned len ;
|
|
char *result ;
|
|
|
|
if ( expr4execute( log->expr, pos, (void **)&result ) < 0 )
|
|
return -1 ;
|
|
len = log->expr->info[pos].len ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( map->type != 0 && map->type != v4functions[log->expr->info[pos].function_i].return_type )
|
|
e4severe( e4info, E4_CONST_EIN ) ;
|
|
#endif
|
|
|
|
if ( const4mem_alloc( log, len ) < 0 )
|
|
return -1 ;
|
|
|
|
memcpy( log->buf + log->buf_pos - len, result, len ) ;
|
|
map->type = v4functions[log->expr->info[pos].function_i].return_type ;
|
|
con->offset = log->buf_len - len ;
|
|
con->len = len ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
int S4FUNCTION const4less( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
|
|
{
|
|
switch( map->type )
|
|
{
|
|
case r4num_doub:
|
|
case r4date_doub:
|
|
#ifdef S4DEBUG
|
|
if ( p1->len != p2->len )
|
|
e4severe( e4info, E4_CONST4LESS ) ;
|
|
#endif
|
|
if ( *(double *)const4return( map->log, p1 ) < *(double *)const4return( map->log, p2 ) )
|
|
return 1 ;
|
|
break ;
|
|
case r4num:
|
|
case r4str:
|
|
if ( p1->len < p2->len )
|
|
{
|
|
if ( memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), p1->len ) <= 0 )
|
|
return 1 ;
|
|
}
|
|
else
|
|
if ( memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), p2->len ) < 0 )
|
|
return 1 ;
|
|
break ;
|
|
default:
|
|
e4severe( e4info, E4_CONST4LESS ) ;
|
|
}
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
int S4FUNCTION const4eq( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
|
|
{
|
|
if ( p1->len < p2->len )
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( map->type == r4num_doub || map->type == r4date_doub )
|
|
e4severe( e4info, E4_CONST4EQ ) ;
|
|
#endif
|
|
return 0 ;
|
|
}
|
|
|
|
#ifdef S4DEBUG
|
|
switch( map->type )
|
|
{
|
|
case r4num_doub:
|
|
case r4date_doub:
|
|
case r4num:
|
|
case r4str:
|
|
case r4log:
|
|
break ;
|
|
default:
|
|
e4severe( e4info, E4_CONST4EQ ) ;
|
|
}
|
|
#endif
|
|
|
|
if ( memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), p1->len ) == 0 )
|
|
return 1 ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
int S4FUNCTION const4less_eq( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
|
|
{
|
|
switch( map->type )
|
|
{
|
|
case r4num_doub:
|
|
case r4date_doub:
|
|
#ifdef S4DEBUG
|
|
if ( p1->len != p2->len )
|
|
e4severe( e4info, E4_CONST4LESS_EQ ) ;
|
|
#endif
|
|
if ( *(double *)const4return( map->log, p1 ) <= *(double *)const4return( map->log, p2 ) )
|
|
return 1 ;
|
|
break ;
|
|
case r4num:
|
|
case r4str:
|
|
if ( p1->len <= p2->len )
|
|
{
|
|
if ( memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), p1->len ) <= 0 )
|
|
return 1 ;
|
|
}
|
|
else
|
|
if ( memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), p2->len ) < 0 )
|
|
return 1 ;
|
|
break ;
|
|
default:
|
|
e4severe( e4info, E4_CONST4LESS_EQ ) ;
|
|
}
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
void S4FUNCTION const4add_ne( BITMAP4 *map, CONST4 *con )
|
|
{
|
|
CONST4 *c_on ;
|
|
|
|
c_on = (CONST4 *)l4first( &map->ne ) ;
|
|
while ( c_on != 0 )
|
|
{
|
|
if ( const4eq( con, c_on, map ) ) /* ne already exists, so ignore */
|
|
return ;
|
|
c_on = (CONST4 *)l4next( &map->ne, c_on ) ;
|
|
}
|
|
c_on = (CONST4 *) u4alloc( sizeof( CONST4 ) ) ;
|
|
if ( c_on == 0 )
|
|
return ;
|
|
memcpy( (void *)c_on, (void *)con, sizeof( CONST4 ) ) ;
|
|
l4add( &map->ne, c_on ) ;
|
|
memset( (void *)con, 0, sizeof( CONST4 ) ) ;
|
|
}
|
|
|
|
void S4FUNCTION const4delete_ne( LIST4 *list, CONST4 *con )
|
|
{
|
|
l4remove( list, con ) ;
|
|
u4free( con ) ;
|
|
}
|
|
|
|
#endif /* S4INDEX_OFF */
|
|
|