/* m4map.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 static void bitmaps4free( BITMAP4 * ) ; /* create a single bitmap structure */ BITMAP4 * S4FUNCTION bitmap4create( L4LOGICAL *log, RELATE4 *relate, char and_or, char branch ) { BITMAP4 *map ; map = (BITMAP4 *)mem4alloc( log->code_base->bitmap_memory ) ; if ( map == 0 ) /* must handle by freeing... */ return 0 ; memset( (void *)map, 0, sizeof( BITMAP4 ) ) ; map->log = log ; map->relate = relate ; map->and_or = and_or ; map->branch = branch ; return map ; } /* free up a single bitmap structure */ void S4FUNCTION bitmap4destroy( BITMAP4 *map ) { CONST4 *c_on, *c_next ; #ifdef S4DEBUG if ( map == 0 ) e4severe( e4parm, E4_BM4DESTROY ) ; #endif c_on = (CONST4 *)l4first( &map->ne ) ; while( c_on != 0 ) { c_next = (CONST4 *)l4next( &map->ne, c_on ) ; const4delete_ne( &map->ne, c_on ) ; c_on = c_next ; } mem4free( map->log->code_base->bitmap_memory, map ) ; } /* can a query or subquery be bitmap optimized? Also builds the bitmap representation */ static BITMAP4 *bitmap4can( L4LOGICAL *log, int *pos, RELATE4 *relate ) { E4INFO *info_ptr, *info_two ; int i, tag_pos, tag_pos2, const_pos ; BITMAP4 *map, *child_map ; CONST4 *temp, hold ; char c_temp ; info_ptr = log->expr->info + *pos ; if ( info_ptr->function_i == E4AND || info_ptr->function_i == E4OR ) { (*pos)-- ; if ( info_ptr->function_i == E4AND && relate == 0 ) relate = (RELATE4 *)log->info_report[*pos].data_list->pointers[0] ; if ( info_ptr->function_i == E4AND ) c_temp = 1 ; else c_temp = 2 ; map = bitmap4create( log, relate, c_temp, 1 ) ; if ( map == 0 ) return 0 ; for( i = 0 ; i < info_ptr->num_parms ; i++ ) { child_map = bitmap4can( log, pos, relate ) ; if ( child_map == 0 && log->code_base->error_code == e4memory ) { log->code_base->error_code = 0 ; bitmaps4free( map ) ; return 0 ; } if ( child_map != 0 ) { l4add( &map->children, child_map ) ; if ( child_map->and_or == 0 ) child_map->and_or = map->and_or ; } else if ( c_temp == 2 ) /* if an or case, then cannot create if any sub-expression is not bitmap optimizeable */ for ( ;; ) { child_map = (BITMAP4 *)l4first( &map->children ) ; if ( child_map == 0 ) { bitmap4destroy( map ) ; return 0 ; } l4remove( &map->children, child_map ) ; bitmap4destroy( child_map ) ; } } if ( map->children.n_link == 0 ) /* not bitmap optimizeable */ { bitmap4destroy( map ) ; return 0 ; } } else { if ( info_ptr->function_i >= E4COMPARE_START && info_ptr->function_i <= E4COMPARE_END ) { /* One must be a constant and the other a tag. */ info_ptr-- ; tag_pos = *pos - 1 ; tag_pos2 = tag_pos - info_ptr->num_entries ; info_two = info_ptr - info_ptr->num_entries ; (*pos) -= 1 + info_ptr->num_entries + info_two->num_entries ; if ( e4is_constant( info_ptr ) ) { if ( !e4is_tag( log->info_report + tag_pos2, log->expr, info_two, relate->data ) ) return 0 ; const_pos = tag_pos ; tag_pos = tag_pos2 ; } else { if ( e4is_constant( info_two ) == 0 || !e4is_tag( log->info_report + tag_pos, log->expr, info_ptr, relate->data ) ) return 0 ; const_pos = tag_pos2 ; info_ptr = info_two ; } map = bitmap4create( log, relate, 0, 0 ) ; if ( map == 0 ) return 0 ; map->tag = ( log->info_report + tag_pos )->tag ; info_ptr++ ; memset( (void *)&hold, 0, sizeof( CONST4 ) ) ; if ( const4get( &hold, map, log, const_pos ) < 0 ) { bitmap4destroy( map ) ; return 0 ; } if ( info_ptr->function_i >= E4COMPARE_START && info_ptr->function_i <= E4COMPARE_END ) { if ( info_ptr->function_i >= E4NOT_EQUAL && info_ptr->function_i < E4GREATER_EQ ) /* != */ { temp = (CONST4 *)u4alloc( sizeof( CONST4 ) ) ; if ( temp == 0 ) { log->code_base->error_code = 0 ; bitmaps4free( map ) ; return 0 ; } memcpy( (void *)temp, (void *)&hold, sizeof( CONST4 ) ) ; l4add( &map->ne, temp ) ; } if (info_ptr->function_i >= E4EQUAL && info_ptr->function_i < E4NOT_EQUAL) /* == */ memcpy( (void *)&map->eq, (void *)&hold, sizeof( CONST4 ) ) ; if ( info_ptr->function_i >= E4GREATER && info_ptr->function_i < E4LESS ) /* > */ { if ( map->type == r4str && hold.len < map->tag->header.key_len ) /* same as >= since a partial > */ memcpy( (void *)&map->ge, (void *)&hold, sizeof( CONST4 ) ) ; else memcpy( (void *)&map->gt, (void *)&hold, sizeof( CONST4 ) ) ; } if ( info_ptr->function_i >= E4GREATER_EQ && info_ptr->function_i < E4LESS_EQ ) /* >= */ memcpy( (void *)&map->ge, (void *)&hold, sizeof( CONST4 ) ) ; if ( info_ptr->function_i >= E4LESS && info_ptr->function_i < E4DEL ) /* < */ memcpy( (void *)&map->lt, (void *)&hold, sizeof( CONST4 ) ) ; if ( info_ptr->function_i >= E4LESS_EQ && info_ptr->function_i < E4GREATER ) /* <= */ memcpy( (void *)&map->le, (void *)&hold, sizeof( CONST4 ) ) ; } } else return 0 ; } return map ; } /* free the bitmap tree */ static void bitmaps4free( BITMAP4 *map ) { BITMAP4 *map_on, *map_next ; if ( map->branch == 1 ) { map_on = (BITMAP4 *)l4first( &map->children ) ; while( map_on != 0 ) { map_next = (BITMAP4 *)l4next( &map->children, map_on ) ; l4remove( &map->children, map_on ) ; bitmaps4free( map_on ) ; map_on = map_next ; } } bitmap4destroy( map ) ; } /* free all the bitmap info */ static void bitmap4free( L4LOGICAL *log, BITMAP4 *map ) { bitmaps4free( map ) ; u4free( log->buf ) ; log->buf = 0 ; log->buf_len = 0 ; log->buf_pos = 0 ; } /* initialize the bitmap structures, determine if bitmapping is possible */ static BITMAP4 *bitmap4init( L4LOGICAL *log, int pos ) { E4INFO *info_ptr ; int pass_pos ; BITMAP4 *map ; info_ptr = log->expr->info + pos ; /* for testing purposes only, allow bitmap disabling */ if ( log->code_base->bitmap_disable == 1 || ( d4reccount( log->relation->relate.data ) / 16 >= ( (unsigned long)INT_MAX - 2L) / 2L ) ) { log->relation->bitmaps_freed = 1 ; return 0 ; } if ( log->code_base->bitmap_memory == 0 ) { log->code_base->bitmap_memory = mem4create( log->code_base, 10, sizeof( BITMAP4 ), 5, 0 ) ; if ( log->code_base->bitmap_memory == 0 ) /* no memory available for bitmap optimization */ return 0 ; } pass_pos = pos ; if ( info_ptr->function_i == E4AND ) map = bitmap4can( log, &pass_pos, &log->relation->relate ) ; else map = bitmap4can( log, &pass_pos, &log->relation->relate ) ; if ( map == 0 && log->code_base->error_code == e4memory ) log->code_base->error_code = 0 ; return map ; } /* this function removes all bitmaps from the parent and marks the parent as zero */ static BITMAP4 *bitmap4collapse( BITMAP4 *parent ) { BITMAP4 *child_on, *child_next ; child_on = (BITMAP4 *)l4first( &parent->children ) ; if ( parent->tag == 0 && child_on->tag != 0 ) parent->tag = child_on->tag ; while( child_on != 0 ) { #ifdef S4DEBUG if ( child_on->tag == 0 && child_on->children.n_link == 0 ) e4severe( e4info, E4_BM4COLLAPSE ) ; #endif child_next = (BITMAP4 *)l4next( &parent->children, child_on ) ; l4remove( &parent->children, child_on ) ; bitmap4destroy( child_on ) ; child_on = child_next ; } parent->no_match = 1 ; return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_le( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next ; char eq_found ; if ( map1->eq.len ) { if ( const4less( &map2->le, &map1->eq, map1 ) ) return 1 ; else { memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->gt.len ) if ( const4less_eq( &map2->le, &map1->gt, map1 ) ) return 1 ; if ( map1->ge.len ) { if ( const4less( &map2->le, &map1->ge, map1 ) ) return 1 ; if ( const4eq( &map2->le, &map1->ge, map1 ) ) { if ( map2->eq.len ) if ( !const4eq( &map2->eq, &map2->le, map1 ) ) return 1 ; memcpy( (void *)&map2->eq, (void *)&map2->le, sizeof( CONST4 ) ) ; memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->ne.n_link != 0 ) /* special case */ { c_on = (CONST4 *)l4first( &map1->ne ) ; eq_found = 0 ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map1->ne, c_on ) ; if ( const4less( &map2->le, c_on, map1 ) ) const4delete_ne( &map1->ne, c_on ) ; else if ( eq_found == 0 ) if ( const4eq( &map2->le, c_on, map1 ) ) eq_found = 1 ; c_on = c_next ; } if ( eq_found ) { memcpy( (void *)&map2->lt, (void *)&map2->le, sizeof( CONST4 ) ) ; memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->lt.len ) { if ( const4less( &map2->le, &map1->lt, map1 ) ) { memcpy( (void *)&map1->le, (void *)&map2->le, sizeof( CONST4 ) ) ; memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; } } else { if ( map1->le.len ) { if ( const4less( &map2->le, &map1->le, map1 ) ) memcpy( (void *)&map1->le, (void *)&map2->le, sizeof( CONST4 ) ) ; } else memcpy( (void *)&map1->le, (void *)&map2->le, sizeof( CONST4 ) ) ; } memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_ge( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next ; char eq_found ; if ( map1->eq.len ) { if ( const4less( &map1->eq, &map2->ge, map1 ) ) return 1 ; else { memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->lt.len ) { if ( const4less_eq( &map1->lt, &map2->ge, map1 ) ) return 1 ; } else if ( map1->le.len ) { if ( const4less( &map1->le, &map2->ge, map1 ) ) return 1 ; if ( const4eq( &map1->le, &map2->ge, map1 ) ) { if ( map2->eq.len ) if ( !const4eq( &map2->eq, &map2->ge, map1 ) ) return 1 ; memcpy( (void *)&map2->eq, (void *)&map2->ge, sizeof( CONST4 ) ) ; memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->ne.n_link != 0 ) /* special case */ { c_on = (CONST4 *)l4first( &map1->ne ) ; eq_found = 0 ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map1->ne, c_on ) ; if ( const4less( c_on, &map2->ge, map1 ) ) const4delete_ne( &map1->ne, c_on ) ; else if ( eq_found == 0 ) if ( const4eq( c_on, &map2->ge, map1 ) ) eq_found = 1 ; c_on = c_next ; } if ( eq_found ) { memcpy( (void *)&map2->gt, (void *)&map2->ge, sizeof( CONST4 ) ) ; memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->gt.len ) { if ( const4less( &map1->gt, &map2->ge, map1 ) ) { memcpy( (void *)&map1->ge, (void *)&map2->ge, sizeof( CONST4 ) ) ; memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; } } else { if ( map1->ge.len ) { if ( const4less( &map1->ge, &map2->ge, map1 ) ) memcpy( (void *)&map1->ge, (void *)&map2->ge, sizeof( CONST4 ) ) ; } else memcpy( (void *)&map1->ge, (void *)&map2->ge, sizeof( CONST4 ) ) ; } memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_lt( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next ; if ( map1->eq.len ) { if ( const4less_eq( &map2->lt, &map1->eq, map1 ) ) return 1 ; else { memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->ne.n_link != 0 ) /* special case */ { c_on = (CONST4 *)l4first( &map1->ne ) ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map1->ne, c_on ) ; if ( const4less_eq( &map2->lt, c_on, map1 ) ) const4delete_ne( &map1->ne, c_on ) ; c_on = c_next ; } } if ( map1->gt.len ) { if ( const4less_eq( &map2->lt, &map1->gt, map1 ) ) return 1 ; } else if ( map1->ge.len ) if ( const4less_eq( &map2->lt, &map1->ge, map1 ) ) return 1 ; if ( map1->lt.len ) { if ( const4less_eq( &map2->lt, &map1->lt, map1 ) ) memcpy( (void *)&map1->lt, (void *)&map2->lt, sizeof( CONST4 ) ) ; } else { if ( map1->le.len ) { if ( const4less_eq( &map2->lt, &map1->le, map1 ) ) { memcpy( (void *)&map1->lt, (void *)&map2->lt, sizeof( CONST4 ) ) ; memset( (void *)&map1->le, 0, sizeof( CONST4 ) ) ; } } else memcpy( (void *)&map1->lt, (void *)&map2->lt, sizeof( CONST4 ) ) ; } memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_gt( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next ; if ( map1->eq.len ) { if ( const4less_eq( &map1->eq, &map2->gt, map1 ) ) return 1 ; else { memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->ne.n_link != 0 ) /* special case */ { c_on = (CONST4 *)l4first( &map1->ne ) ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map1->ne, c_on ) ; if ( const4less_eq( c_on, &map2->gt, map1 ) ) const4delete_ne( &map1->ne, c_on ) ; c_on = c_next ; } } if ( map1->lt.len ) { if ( const4less_eq( &map1->lt, &map2->gt, map1 ) ) return 1 ; } else if ( map1->le.len ) if ( const4less_eq( &map1->le, &map2->gt, map1 ) ) return 1 ; if ( map1->gt.len ) { if ( const4less( &map1->gt, &map2->gt, map1 ) ) memcpy( (void *)&map1->gt, (void *)&map2->gt, sizeof( CONST4 ) ) ; } else { if ( map1->ge.len ) { if ( const4less_eq( &map1->ge, &map2->gt, map1 ) ) { memcpy( (void *)&map1->gt, (void *)&map2->gt, sizeof( CONST4 ) ) ; memset( (void *)&map1->ge, 0, sizeof( CONST4 ) ) ; } } else memcpy( (void *)&map1->gt, (void *)&map2->gt, sizeof( CONST4 ) ) ; } memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_ne( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next, *c_on2, *c_next2 ; int eq_found ; c_on = (CONST4 *)l4first( &map2->ne ) ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map2->ne, c_on ) ; if ( map1->eq.len ) { if ( const4eq( c_on, &map1->eq, map1 ) ) return 1 ; else { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } } if ( map1->gt.len ) { if ( const4less_eq( c_on, &map1->gt, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } } else if ( map1->ge.len ) { if ( const4eq( c_on, &map1->ge, map1 ) ) { memcpy( (void *)&map1->gt, (void *)&map1->ge, sizeof( CONST4 ) ) ; memset( (void *)&map1->ge, 0, sizeof( CONST4 ) ) ; const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } if ( const4less_eq( c_on, &map1->ge, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } } if ( map1->lt.len ) { if ( const4less_eq( &map1->lt, c_on, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } } else if ( map1->le.len ) { if ( const4eq( c_on, &map1->le, map1 ) ) { memcpy( (void *)&map1->lt, (void *)&map1->le, sizeof( CONST4 ) ) ; memset( (void *)&map1->le, 0, sizeof( CONST4 ) ) ; const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } if ( const4less_eq( &map1->le, c_on, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; continue ; } } if ( map1->ne.n_link != 0 ) /* special case */ { c_on2 = (CONST4 *)l4first( &map1->ne ) ; eq_found = 0 ; while ( c_on2 != 0 ) { c_next2 = (CONST4 *)l4next( &map1->ne, c_on2 ) ; if ( const4eq( c_on, c_on2, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; c_on = c_next ; eq_found = 1 ; break ; } c_on2 = c_next2 ; } if ( eq_found != 1 ) { l4remove( &map2->ne, c_on ) ; l4add( &map1->ne, c_on ) ; } c_on = c_next ; continue ; } /* must add the ne */ l4remove( &map2->ne, c_on ) ; l4add( &map1->ne, c_on ) ; c_on = c_next ; } return 0 ; } /* 0 = successful merger, 1 means collaps because now no records belong to the set */ static int bitmap4combine_and_eq( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_next ; if ( map1->eq.len ) { if ( const4eq( &map2->eq, &map1->eq, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } else return 1 ; } if ( map1->ne.n_link != 0 ) /* special case */ { c_on = (CONST4 *)l4first( &map1->ne ) ; while ( c_on != 0 ) { c_next = (CONST4 *)l4next( &map1->ne, c_on ) ; if ( const4eq( &map2->eq, c_on, map1 ) ) return 1 ; else const4delete_ne( &map1->ne, c_on ) ; c_on = c_next ; } } if ( map1->le.len ) { if ( const4less( &map1->le, &map2->eq, map1 ) ) return 1 ; memset( (void *)&map1->le, 0, sizeof( CONST4 ) ) ; } else if ( map1->lt.len ) { if ( const4less_eq( &map1->lt, &map2->eq, map1 ) ) return 1 ; memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; } if ( map1->ge.len ) { if ( const4less( &map2->eq, &map1->ge, map1 ) ) return 1 ; memset( (void *)&map1->ge, 0, sizeof( CONST4 ) ) ; } else if ( map1->gt.len ) { if ( const4less_eq( &map2->eq, &map1->gt, map1 ) ) return 1 ; memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; } memcpy( (void *)&map1->eq, (void *)&map2->eq, sizeof( CONST4 ) ) ; memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } static int bitmap4combine_or_le( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on ; if ( map1->eq.len ) if ( const4less_eq( &map1->eq, &map2->le, map1 ) ) memset( (void *)&map1->eq, 0, sizeof( CONST4 ) ) ; if ( map1->gt.len ) { if ( const4less_eq( &map1->gt, &map2->le, map1 ) ) return 1 ; } else if ( map1->ge.len ) if ( const4less_eq( &map1->ge, &map2->le, map1 ) ) return 1 ; if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map1->ne ) ; if ( const4less_eq( c_on, &map2->le, map1 ) ) return 1 ; else { memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->lt.len ) { if ( const4less_eq( &map1->lt, &map2->le, map1 ) ) memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; else { memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->le.len ) if ( !const4less_eq( &map1->le, &map2->le, map1 ) ) { memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } memcpy( (void *)&map1->le, (void *)&map2->le, sizeof( CONST4 ) ) ; memset( (void *)&map2->le, 0, sizeof( CONST4 ) ) ; return 0 ; } static int bitmap4combine_or_ge( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on ; if ( map1->eq.len ) if ( const4less_eq( &map2->ge, &map1->eq, map1 ) ) memset( (void *)&map1->eq, 0, sizeof( CONST4 ) ) ; if ( map1->lt.len ) { if ( const4less_eq( &map2->ge, &map1->lt, map1 ) ) return 1 ; } else if ( map1->le.len ) if ( const4less_eq( &map2->ge, &map1->le, map1 ) ) return 1 ; if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map1->ne ) ; if ( const4less_eq( &map2->ge, c_on, map1 ) ) return 1 ; else { memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->gt.len ) { if ( const4less_eq( &map2->ge, &map1->gt, map1 ) ) memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; else { memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->ge.len ) if ( !const4less_eq( &map2->ge, &map1->ge, map1 ) ) { memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } memcpy( (void *)&map1->ge, (void *)&map2->ge, sizeof( CONST4 ) ) ; memset( (void *)&map2->ge, 0, sizeof( CONST4 ) ) ; return 0 ; } static int bitmap4combine_or_lt( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on ; if ( map1->eq.len ) { if ( const4eq( &map1->eq, &map2->lt, map1 ) ) { #ifdef S4DEBUG if ( map2->le.len != 0 ) e4severe( e4info, E4_BM4COMBINE ) ; #endif memcpy( (void *)&map2->le, (void *)&map2->lt, sizeof( CONST4 ) ) ; memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map1->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( const4less( &map1->eq, &map2->lt, map1 ) ) memset( (void *)&map1->eq, 0 , sizeof( CONST4 ) ) ; } if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map1->ne ) ; if ( const4less( c_on, &map2->lt, map1 ) ) return 1 ; else { memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->gt.len ) { if ( const4less( &map1->gt, &map2->lt, map1 ) ) return 1 ; if ( const4eq( &map1->gt, &map2->lt, map1 ) ) { const4add_ne( map1, &map2->lt ) ; memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->ge.len ) if ( const4less_eq( &map1->ge, &map2->lt, map1 ) ) return 1 ; if ( map1->lt.len ) { if ( !const4less( &map1->lt, &map2->lt, map1 ) ) { memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->le.len ) { if ( const4less_eq( &map2->lt, &map1->le, map1 ) ) { memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } else memset( (void *)&map1->le, 0, sizeof( CONST4 ) ) ; } memcpy( (void *)&map1->lt, (void *)&map2->lt, sizeof( CONST4 ) ) ; memset( (void *)&map2->lt, 0, sizeof( CONST4 ) ) ; return 0 ; } static int bitmap4combine_or_gt( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on ; if ( map1->eq.len ) { if ( const4eq( &map1->eq, &map2->gt, map1 ) ) { #ifdef S4DEBUG if ( map2->ge.len != 0 ) e4severe( e4info, E4_BM4COMBINE ) ; #endif memcpy( (void *)&map2->ge, (void *)&map2->gt, sizeof( CONST4 ) ) ; memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map1->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( const4less( &map2->gt, &map1->eq, map1 ) ) memset( (void *)&map1->eq, 0 , sizeof( CONST4 ) ) ; } if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map1->ne ) ; if ( const4less( &map2->gt, c_on, map1 ) ) return 1 ; else { memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->lt.len ) { if ( const4less( &map2->gt, &map1->lt, map1 ) ) return 1 ; if ( const4eq( &map2->gt, &map1->lt, map1 ) ) { const4add_ne( map1, &map2->gt ) ; memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->le.len ) if ( const4less_eq( &map2->gt, &map1->le, map1 ) ) return 1 ; if ( map1->gt.len ) { if ( const4less( &map1->gt, &map2->gt, map1 ) ) { memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->ge.len ) { if ( const4less_eq( &map1->ge, &map2->gt, map1 ) ) { memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } else memset( (void *)&map1->ge, 0, sizeof( CONST4 ) ) ; } memcpy( (void *)&map1->gt, (void *)&map2->gt, sizeof( CONST4 ) ) ; memset( (void *)&map2->gt, 0, sizeof( CONST4 ) ) ; return 0 ; } static int bitmap4combine_or_eq( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on ; if ( map1->eq.len ) { if ( const4eq( &map1->eq, &map2->eq, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } } if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map1->ne ) ; if ( const4eq( &map2->eq, c_on, map1 ) ) return 1 ; memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( map1->lt.len ) { if ( const4eq( &map1->lt, &map2->eq, map1 ) ) { memcpy( (void *)&map1->le, (void *)&map1->lt, sizeof( CONST4 ) ) ; memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( const4less( &map2->eq, &map1->lt, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->le.len ) if ( const4less_eq( &map2->eq, &map1->le, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( map1->gt.len ) { if ( const4eq( &map1->gt, &map2->eq, map1 ) ) { memcpy( (void *)&map1->ge, (void *)&map1->gt, sizeof( CONST4 ) ) ; memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( const4less( &map1->gt, &map2->eq, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } } else if ( map1->ge.len ) if ( const4less_eq( &map1->ge, &map2->eq, map1 ) ) { memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; return 0 ; } if ( map1->eq.len == 0 ) { memcpy( (void *)&map1->eq, (void *)&map2->eq, sizeof( CONST4 ) ) ; memset( (void *)&map2->eq, 0, sizeof( CONST4 ) ) ; } return 0 ; } static int bitmap4combine_or_ne( BITMAP4 *map1, BITMAP4 *map2 ) { CONST4 *c_on, *c_on2 ; #ifdef S4DEBUG if ( map2->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on = (CONST4 *)l4first( &map2->ne ) ; if ( map1->eq.len ) { if ( const4eq( &map1->eq, c_on, map1 ) ) return 1 ; memset( (void *)&map1->eq, 0, sizeof( CONST4 ) ) ; } if ( map1->ne.n_link != 0 ) /* special case */ { #ifdef S4DEBUG if ( map1->ne.n_link != 1 ) /* if 2 links, all must belong... */ e4severe( e4info, E4_BM4COMBINE ) ; #endif c_on2 = (CONST4 *)l4first( &map1->ne ) ; if ( const4eq( c_on2, c_on, map1 ) ) { const4delete_ne( &map2->ne, c_on ) ; return 0 ; } else return 1 ; } if ( map1->lt.len ) { if ( const4less( c_on, &map1->lt, map1 ) ) return 1 ; else memset( (void *)&map1->lt, 0, sizeof( CONST4 ) ) ; } else if ( map1->le.len ) { if ( const4less_eq( c_on, &map1->le, map1 ) ) return 1 ; else memset( (void *)&map1->le, 0, sizeof( CONST4 ) ) ; } if ( map1->gt.len ) { if ( const4less( &map1->gt, c_on, map1 ) ) return 1 ; else memset( (void *)&map1->gt, 0, sizeof( CONST4 ) ) ; } else if ( map1->ge.len ) { if ( const4less_eq( &map1->ge, c_on, map1 ) ) return 1 ; else memset( (void *)&map1->ge, 0, sizeof( CONST4 ) ) ; } l4remove( &map2->ne, c_on ) ; l4add( &map1->ne, c_on ) ; return 0 ; } /* merge two leaf maps together */ BITMAP4 * S4FUNCTION bitmap4combine_leafs( BITMAP4 *parent, BITMAP4 *map1, BITMAP4 *map2 ) { BITMAP4 *child_on ; #ifdef S4DEBUG if ( parent == 0 || map1 == 0 || map2 == 0 ) e4severe( e4parm, 0 ) ; if ( map1->type != map2->type ) e4severe( e4info, E4_BM4_IM ) ; #endif if ( parent->and_or == 1 ) /* and */ { if ( map2->le.len ) if ( bitmap4combine_and_le( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->ge.len ) if ( bitmap4combine_and_ge( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->lt.len ) if ( bitmap4combine_and_lt( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->gt.len ) if ( bitmap4combine_and_gt( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->ne.n_link != 0 ) /* special case */ if ( bitmap4combine_and_ne( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->eq.len ) if ( bitmap4combine_and_eq( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; #ifdef S4DEBUG if ( map2->le.len || map2->ge.len || map2->lt.len || map2->gt.len || map2->eq.len || map2->ne.n_link ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->eq.len ) if ( map1->le.len || map1->ge.len || map1->lt.len || map1->gt.len || map1->ne.n_link ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->ne.n_link ) if ( map1->eq.len ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->ge.len ) if ( map1->gt.len || map1->eq.len ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->gt.len ) if ( map1->ge.len || map1->eq.len ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->le.len ) if ( map1->lt.len || map1->eq.len ) e4severe( e4info, E4_BM4COMBINE_LF ) ; if ( map1->lt.len ) if ( map1->le.len || map1->eq.len ) e4severe( e4info, E4_BM4COMBINE_LF ) ; #endif l4remove( &parent->children, map2 ) ; bitmap4destroy( map2 ) ; return map1 ; } else if ( parent->and_or == 2 ) /* or */ { child_on = map2 ; while( child_on != 0 ) { if ( map2->lt.len ) if ( bitmap4combine_or_lt( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->gt.len ) if ( bitmap4combine_or_gt( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->le.len ) if ( bitmap4combine_or_le( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->ge.len ) if ( bitmap4combine_or_ge( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->ne.n_link != 0 ) /* special case */ if ( bitmap4combine_or_ne( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; if ( map2->eq.len ) if ( bitmap4combine_or_eq( map1, map2 ) == 1 ) return bitmap4collapse( parent ) ; child_on = (BITMAP4 *)l4next( &parent->children, child_on ) ; } if ( map2->le.len || map2->ge.len || map2->lt.len || map2->gt.len || map2->eq.len || map2->ne.n_link ) return map2 ; else { l4remove( &parent->children, map2 ) ; bitmap4destroy( map2 ) ; return map1 ; } } return 0 ; } void S4FUNCTION bitmap4copy( BITMAP4 *to, BITMAP4 *from ) { CONST4 *c_on, *temp ; #ifdef S4DEBUG if ( from->branch ) e4severe( e4info, E4_BM4COPY ) ; #endif memset( (void *)to, 0, sizeof( BITMAP4 ) ) ; to->and_or = from->and_or ; to->log = from->log ; to->relate = from->relate ; to->type = from->type ; to->tag = from->tag ; const4duplicate( &to->lt, &from->lt, from->log ) ; const4duplicate( &to->le, &from->le, from->log ) ; const4duplicate( &to->gt, &from->gt, from->log ) ; const4duplicate( &to->ge, &from->ge, from->log ) ; const4duplicate( &to->eq, &from->eq, from->log ) ; c_on = (CONST4 *)l4first( &from->ne ) ; while ( c_on != 0 ) { temp = (CONST4 *)u4alloc( sizeof( CONST4 ) ) ; if ( temp == 0 ) return ; const4duplicate( temp, c_on, from->log ) ; l4add( &to->ne, temp ) ; } } /* flags a range of bits for the given F4FLAG and map */ static long bitmap4flag_range( F4FLAG *flags, BITMAP4 *map, CONST4 *start_con, CONST4 *end_con, long do_flip, char start_val, char end_val, long check ) { long start, end, rc ; double pos1, pos2 ; TAG4 *tag ; #ifdef S4MDX int is_desc ; long do_skip ; #endif tag = map->tag ; #ifdef S4MDX is_desc = ( tag->header.type_code & 8 ) ? 1 : 0 ; #endif start = end = 0L ; if ( start_con != 0 ) { start = bitmap4seek( map, start_con, start_val, 0, 0 ) ; if ( start == -1L || t4eof( map->tag ) ) return -2L ; if ( start > 0L ) pos1 = t4positionDbl( tag ) ; } if ( end_con != 0 ) { end = bitmap4seek( map, end_con, end_val, start, (int)check ) ; if ( end == -1L ) return -2L ; if ( end > 0L ) pos2 = t4positionDbl( tag ) ; } #ifdef S4MDX if ( is_desc ) { if ( start > 0L ) { if ( end > 0L ) { if ( pos1 < pos2 ) /* wrap around case, no matches */ return do_flip ; if ( do_flip == 0 && ( pos1 - pos2 ) > 0.5 ) /* go around */ { rc = do_flip = -1L ; for(;;) { if ( t4skip( tag, -1L ) != -1L ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; } start = bitmap4seek( map, start_con, start_val, 0, 0 ) ; for(;;) { if ( t4skip( tag, 1L ) != 1L ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; } } else { if ( do_flip == 0 ) do_flip = 1 ; rc = do_flip ; for( ; rc == do_flip ; ) { if ( do_flip == -1 ) f4flag_reset( flags, (unsigned long)t4recno( tag ) ) ; else f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( t4recno( tag ) == start ) break ; rc = t4skip( tag, 1L ) == 1L ? do_flip : -do_flip ; } } } else { if ( do_flip == 0 ) { if ( pos1 > 0.5 ) { do_skip = 1L ; do_flip = -1L ; rc = t4skip( tag, 1L ) ; } else { rc = do_skip = -1L ; do_flip = 1L ; } } else rc = do_skip = -do_flip ; for( ; rc == do_skip ; ) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } } else { if ( end > 0L ) { if ( do_flip == 0 ) { if ( pos2 > .5 ) { rc = do_skip = 1L ; do_flip = 1L ; } else { do_flip = -1L ; do_skip = -1L ; rc = t4skip( tag, do_skip ) ; } } else rc = do_skip = -do_flip ; for( ; rc == do_skip ; ) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } else return -1L ; } } else { #endif if ( start > 0L ) { if ( end > 0L ) { if ( pos1 > pos2 ) /* wrap around case, no matches */ return do_flip ; if ( do_flip == 0 && ( pos2 - pos1 ) > 0.5 ) /* go around */ { rc = do_flip = -1L ; for(;;) { if ( t4skip( tag, 1L ) != 1L ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; } start = bitmap4seek( map, start_con, start_val, 0, 0 ) ; for(;;) { if ( t4skip( tag, -1L ) != -1L ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; } } else { if ( do_flip == 0 ) do_flip = 1 ; rc = do_flip ; for( ; rc == do_flip ; ) { if ( do_flip == -1 ) f4flag_reset( flags, (unsigned long)t4recno( tag ) ) ; else f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( t4recno( tag ) == start ) break ; rc = t4skip( tag, -1L ) == -1L ? do_flip : -do_flip ; } } } else { if ( do_flip == 0 ) { if ( pos1 < 0.5 ) { do_flip = -1L ; rc = t4skip( tag, do_flip ) ; } else rc = do_flip = 1L ; } else rc = do_flip ; for( ; rc == do_flip ; ) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_flip ) ; } } } else { if ( end > 0L ) { if ( do_flip == 0 ) { if ( pos2 < .5 ) rc = do_flip = -1L ; else { do_flip = 1L ; rc = t4skip( tag, do_flip ) ; } } else rc = do_flip ; for( ; rc == do_flip ; ) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_flip ) ; } do_flip = ( do_flip == -1L ) ? 1L : -1L ; } else return -1L ; } #ifdef S4MDX } #endif return do_flip ; } static int bmf4_and_eq( BITMAP4 *map, F4FLAG *flags, long do_flip ) { CONST4 *start_con, *end_con ; char start_val, end_val ; #ifdef S4DEBUG if ( map->gt.len || map->ge.len || map->le.len || map->lt.len || l4first( &map->ne ) != 0 ) e4severe( e4info, E4_BM4FLAG_GEN ) ; /* corrupt map detected */ #endif start_con = end_con = &map->eq ; start_val = 1 ; end_val = 2 ; return (int) bitmap4flag_range( flags, map, start_con, end_con, do_flip, start_val, end_val, 0L ) ; } static int bmf4_and_ot( BITMAP4 *map, F4FLAG *flags, long do_flip ) { CONST4 *start_con, *end_con, *c_on ; char start_val, end_val ; long prev_flip ; int do_check ; start_val = end_val = 0 ; start_con = end_con = 0 ; do_check = 0 ; if ( map->gt.len ) { start_con = &map->gt ; start_val = 3 ; } else if ( map->ge.len ) { start_con = &map->ge ; start_val = 1 ; do_check = 1 ; } if ( map->lt.len ) { end_con = &map->lt ; end_val = 0 ; } else if ( map->le.len ) { end_con = &map->le ; end_val = 2 ; if ( do_check == 1 ) do_check = 2 ; } if ( do_check == 0 ) do_check++ ; do_flip = bitmap4flag_range( flags, map, start_con, end_con, do_flip, start_val, end_val, do_check ) ; if ( do_flip == -2L ) /* no matches */ { f4flag_set_all( flags ) ; flags->is_flip = 1 ; return -999L ; } c_on = (CONST4 *)l4first( &map->ne ) ; if( c_on != 0 ) { if ( do_flip != 0L ) prev_flip = do_flip = ( do_flip == 1L ) ? -1L : 1L ; else prev_flip = 0L ; while ( c_on != 0 ) { start_con = end_con = c_on ; start_val = 1 ; end_val = 2 ; do_flip = bitmap4flag_range( flags, map, start_con, end_con, do_flip, start_val, end_val, 0L ) ; if ( do_flip == -2L ) { if ( prev_flip == 0L ) /* all records not equal, so mark as such */ { f4flag_set_all( flags ) ; do_flip = -1L ; } else /* otherwise no change since no un-equal records */ do_flip = prev_flip ; } c_on = (CONST4 *)l4next( &map->ne, c_on ) ; prev_flip = do_flip ; } do_flip = ( do_flip == 1L ) ? -1L : 1L ; } return (int)do_flip ; } static int bmf4_or_ne( BITMAP4 *map, F4FLAG *flags ) { CONST4 *start_con, *end_con, *c_on ; char start_val, end_val ; long do_flip ; c_on = (CONST4 *)l4first( &map->ne ) ; start_con = end_con = c_on ; start_val = 1 ; end_val = 2 ; do_flip = bitmap4flag_range( flags, map, start_con, end_con, do_flip, start_val, end_val, 0L ) ; if ( do_flip != -1 ) f4flag_flip_returns( flags ) ; #ifdef S4DEBUG c_on = (CONST4 *)l4next( &map->ne, c_on ) ; if ( c_on != 0 ) e4severe( e4info, E4_BM4FLAG_GEN ) ; /* corrupt map detected */ #endif return -999 ; } static int bmf4_or_ot( BITMAP4 *map, F4FLAG *flags, CODE4 *code_base ) { CONST4 *start_con, *end_con ; char start_val, end_val ; long start, end, do_flip, rc, prev_flip, do_skip ; double pos1, pos2 ; TAG4 *tag ; #ifdef S4MDX int is_desc ; #endif tag = map->tag ; #ifdef S4MDX is_desc = ( tag->header.type_code & 8 ) ? 1 : 0 ; #endif #ifdef S4DEBUG if ( tag == 0 ) e4severe( e4parm, E4_BM4FLAG_GEN ) ; #endif start = end = do_flip = do_skip = 0L ; if ( map->gt.len ) start = bitmap4seek( map, &map->gt, 3, 0, 0 ) ; else if ( map->ge.len ) start = bitmap4seek( map, &map->ge, 1, 0, 0 ) ; if ( start > 0L ) pos1 = (double)t4positionDbl( tag ) ; if ( map->lt.len ) end = bitmap4seek( map, &map->lt, 0, start, 1 ) ; else if ( map->le.len ) end = bitmap4seek( map, &map->le, 2, start, 1 ) ; if ( end == -1L ) /* no matches */ return -999L ; #ifdef S4MDX if ( is_desc ) { if ( start > 0L ) { if ( end > 0L ) { pos2 = (double)t4positionDbl( tag ) ; if ( ( pos1 - pos2 ) < 0.5 ) /* do between */ { if ( ( pos1 - pos2 ) < 0 ) { do_flip = -1 ; do_skip = -1 ; } else do_skip = do_flip = 1L ; if ( t4recno( tag ) != start ) { rc = t4skip( tag, do_skip ) ; for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000L ; if ( t4recno( tag ) == start ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } } else /* flip and do both ways */ { for(;;) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( code_base->error_code < 0 ) return -1000L ; if ( t4skip( tag, -1L ) != -1L ) break ; } if ( map->gt.len ) start = bitmap4seek( map, &map->gt, 1, 0, 0 ) ; else if ( map->ge.len ) start = bitmap4seek( map, &map->ge, 2, 0, 0 ) ; for(;;) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( code_base->error_code < 0 ) return -1000L ; if ( t4skip( tag, 1L ) != 1L ) break ; } do_skip = do_flip = -1L ; } } else { if ( pos1 > 0.5 ) { do_flip = -1 ; do_skip = 1 ; rc = t4skip( tag, do_skip ) ; } else { do_flip = 1 ; do_skip = rc = -1 ; } for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000 ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } } else { if ( end > 0L ) { if ( (double)t4positionDbl( tag ) > 0.5 ) { do_flip = 1 ; do_skip = 1 ; rc = 1 ; } else { do_flip = -1 ; do_skip = -1 ; rc = t4skip( tag, do_skip ) ; } for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000 ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } } } else { #endif if ( start > 0L ) { pos1 = (double)t4positionDbl( tag ) ; if ( end > 0L ) { pos2 = (double)t4positionDbl( tag ) ; if ( ( pos2 - pos1 ) < 0.5 ) /* flip and do between */ { do_skip = do_flip = 1L ; if ( t4recno( tag ) != start ) { rc = t4skip( tag, do_skip ) ; for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000L ; if ( t4recno( tag ) == start ) break ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } do_flip = do_skip = -1L ; } else /* do both ways */ { for(;;) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( code_base->error_code < 0 ) return -1000L ; if ( t4skip( tag, -1L ) != -1L ) break ; } if ( map->gt.len ) start = bitmap4seek( map, &map->gt, 1, 0, 0 ) ; else if ( map->ge.len ) start = bitmap4seek( map, &map->ge, 2, 0, 0 ) ; for(;;) { f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; if ( code_base->error_code < 0 ) return -1000L ; if ( t4skip( tag, 1L ) != 1L ) break ; } } } else { if ( pos1 < 0.5 ) { do_flip = do_skip = -1 ; rc = t4skip( tag, do_skip ) ; } else do_flip = do_skip = rc = 1 ; for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000 ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } } } else { if ( end > 0L ) { if ( (double)t4positionDbl( tag ) > 0.5 ) { do_skip = 1 ; do_flip = 1 ; rc = t4skip( tag, do_skip ) ; } else { do_flip = -1 ; rc = do_skip = -1 ; /* rc = t4skip( tag, do_skip ) ; */ } for( ; rc == do_skip ; ) { if ( code_base->error_code < 0 ) return -1000 ; f4flag_set( flags, (unsigned long)t4recno( tag ) ) ; rc = t4skip( tag, do_skip ) ; } do_flip = do_skip = ( do_flip == -1L ) ? 1L : -1L ; } } #ifdef S4MDX } #endif if ( map->eq.len ) { start_con = end_con = &map->eq ; start_val = 1 ; end_val = 2 ; prev_flip = do_flip ; do_flip = bitmap4flag_range( flags, map, start_con, end_con, do_flip, start_val, end_val, 0L ) ; if ( do_flip == -2L ) do_flip = prev_flip ; } return (int)do_flip ; } /* generate the flags for the bitmap tree */ static int bitmap4flag_generate( BITMAP4 *map, int mode, F4FLAG *flags ) { CODE4 *code_base ; CONST4 *c_on ; long do_flip ; int is_flipped ; #ifdef S4HAS_DESCENDING TAG4 *tag ; int old_desc ; #endif code_base = map->log->code_base ; #ifdef S4HAS_DESCENDING tag = map->tag ; #ifdef S4DEBUG if ( tag == 0 ) e4severe( e4parm, E4_BM4FLAG_GEN ) ; #endif old_desc = tag->header.descending ; #endif if ( flags->flags == 0 ) { if ( f4flag_init( flags, code_base, (unsigned long)d4reccount( map->relate->data ) + 1L ) < 0 ) { #ifndef S4OPTIMIZE_OFF if ( code_base->error_code == e4memory ) /* failed due to out of memory */ code_base->error_code = 0 ; if ( code_base->has_opt && code_base->opt.num_buffers != 0 ) { d4opt_suspend( code_base ) ; if ( code_base->opt.num_buffers > 8 ) code_base->opt.num_buffers-- ; } if ( f4flag_init( flags, code_base, (unsigned long)d4reccount( map->relate->data ) + 1L ) < 0 ) #endif { #ifdef S4HAS_DESCENDING t4descending( tag, old_desc ) ; #endif return -1 ; } } is_flipped = 0 ; do_flip = 0L ; } else { do_flip = ( flags->is_flip == 1L ) ? -1L : 1L ; is_flipped = 1 ; } if ( map->no_match == 1 ) { if ( mode == 2 ) { if ( is_flipped ) /* previous setting, so make all succeed */ { f4flag_set_all( flags ) ; flags->is_flip = 0 ; } else /* none set now, so make all succeed by simple flip */ flags->is_flip = 1 ; } #ifdef S4HAS_DESCENDING t4descending( tag, old_desc ) ; #endif return 0 ; } if ( mode == 1 ) /* and */ { if ( map->eq.len ) do_flip = bmf4_and_eq( map, flags, do_flip ) ; else do_flip = bmf4_and_ot( map, flags, do_flip ) ; } else /* or */ { c_on = (CONST4 *)l4first( &map->ne ) ; if ( c_on != 0 ) do_flip = bmf4_or_ne( map, flags ) ; else do_flip = bmf4_or_ot( map, flags, code_base ) ; } #ifdef S4HAS_DESCENDING t4descending( tag, old_desc ) ; #endif if ( do_flip == -999L ) return 0 ; if ( do_flip == -1000L ) return -1 ; if ( do_flip == -1L && !is_flipped ) f4flag_flip_returns( flags ) ; return 0 ; } /* generate the bitmaps */ static F4FLAG *bitmap4generate( BITMAP4 *map ) { BITMAP4 *map_on ; F4FLAG *flag1, *flag2 ; if ( map->branch == 0 ) { flag1 = (F4FLAG *)u4alloc( sizeof( F4FLAG ) ) ; if ( flag1 == 0 ) /* insufficient memory */ return 0 ; memset( (void *)flag1, 0, sizeof( F4FLAG ) ) ; if ( bitmap4flag_generate( map, map->and_or, flag1 ) < 0 ) { u4free( flag1->flags ) ; u4free( flag1 ) ; return 0 ; } return flag1 ; } flag1 = flag2 = 0 ; map_on = (BITMAP4 *)l4first( &map->children ) ; while( map_on != 0 ) { flag2 = bitmap4generate( map_on ) ; if ( flag1 == 0 ) flag1 = flag2 ; else { #ifdef S4DEBUG if ( map->and_or != 1 && map->and_or != 2 ) e4severe( e4info, E4_BM4FLAG_GEN ) ; #endif if ( map->and_or == 1 ) f4flag_and( flag1, flag2 ) ; else f4flag_or( flag1, flag2 ) ; u4free( flag2->flags ) ; u4free( flag2 ) ; } map_on = (BITMAP4 *)l4next( &map->children, map_on ) ; } return flag1 ; } /* performs an or minimalization of the tree in order to conform to the redistributable standard */ BITMAP4 *S4FUNCTION bitmap4minimalize( BITMAP4 *map ) { BITMAP4 *child_on, *child_next, *child_on2 ; if ( map->branch == 0 ) return map ; if ( map->and_or == 2 ) /* OR */ { child_on = (BITMAP4 *)l4first( &map->children ) ; for( ;; ) { if ( child_on == 0 ) break ; child_next = (BITMAP4 *)l4next( &map->children, child_on ) ; if ( child_on->and_or == 2 && child_on->branch == 1 ) { for ( ;; ) { child_on2 = (BITMAP4 *)l4first( &child_on->children ) ; if ( child_on2 == 0 ) break ; child_next = child_on2 ; /* for the parent map, next child... */ l4remove( &child_on->children, child_on2 ) ; l4add_after( &map->children, child_on, child_on2 ) ; } l4remove( &map->children, child_on ) ; bitmap4destroy( child_on ) ; } child_on = child_next ; } } child_on = (BITMAP4 *)l4first( &map->children ) ; for( ;; ) { if ( child_on == 0 ) break ; if ( child_on->branch == 1 ) child_on = bitmap4minimalize( child_on ) ; child_on = (BITMAP4 *)l4next( &map->children, child_on ) ; } return map ; } /* evaluate bitmaps out of the log */ int S4FUNCTION bitmap4evaluate( L4LOGICAL *log, int pos ) { BITMAP4 *map ; F4FLAG *flags ; map = bitmap4init( log, pos ) ; if ( map == 0 ) return 0 ; map = bitmap4minimalize( map ) ; if ( map == 0 ) return 0 ; map = bitmap4redistribute( 0, map, 1 ) ; if ( map == 0 ) return 0 ; map = bitmap4redistribute_branch( 0, map ) ; if ( map == 0 ) { if ( log->code_base->error_code == e4memory ) log->code_base->error_code = 0 ; return 0 ; } flags = bitmap4generate( map ) ; if ( flags != 0 ) { memcpy( (void *)&map->relate->set, (void *)flags, sizeof( F4FLAG ) ) ; u4free( flags ) ; } bitmap4free( log, map ) ; return 0 ; } #endif /* S4INDEX_OFF */