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 */
 | |
| 
 |