880 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			880 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* c4const.c  (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
 | 
						|
#ifndef S4UNIX
 | 
						|
   #ifdef __TURBOC__
 | 
						|
      #pragma hdrstop
 | 
						|
   #endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4CLIENT
 | 
						|
#ifndef S4INDEX_OFF
 | 
						|
 | 
						|
/* This function creates a branch out of the input constant, and combines it with the input map */
 | 
						|
static int bitmap4constantCombine( BITMAP4 *parent, BITMAP4 *oldAndMap, CONST4 *con, int conType )
 | 
						|
{
 | 
						|
   BITMAP4 *tempLeaf, *andMap, *newBranch ;
 | 
						|
   CONST4 *temp ;
 | 
						|
 | 
						|
   if ( con->len == 0 || error4code( parent->log->codeBase ) == e4memory )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   newBranch = bitmap4create( parent->log, parent->relate, 1, 1 ) ;
 | 
						|
   if ( newBranch == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   andMap = bitmap4create( parent->log, parent->relate, 0, 0 ) ;
 | 
						|
   if ( andMap == 0 )
 | 
						|
      return 0 ;
 | 
						|
   bitmap4copy( andMap, oldAndMap ) ;
 | 
						|
   l4add( &newBranch->children, andMap ) ;
 | 
						|
 | 
						|
   tempLeaf = bitmap4create( parent->log, parent->relate, 1, 0 ) ;
 | 
						|
   if ( tempLeaf == 0 )
 | 
						|
      return 0 ;
 | 
						|
   tempLeaf->type = andMap->type ;
 | 
						|
   tempLeaf->tag = andMap->tag ;
 | 
						|
   l4add( &newBranch->children, tempLeaf ) ;
 | 
						|
 | 
						|
   switch( conType )
 | 
						|
   {
 | 
						|
      case 1:
 | 
						|
         memcpy( (void *)&tempLeaf->lt, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         break ;
 | 
						|
      case 2:
 | 
						|
         memcpy( (void *)&tempLeaf->le, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         break ;
 | 
						|
      case 3:
 | 
						|
         memcpy( (void *)&tempLeaf->gt, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         break ;
 | 
						|
      case 4:
 | 
						|
         memcpy( (void *)&tempLeaf->ge, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         break ;
 | 
						|
      case 5:
 | 
						|
         memcpy( (void *)&tempLeaf->eq, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         break ;
 | 
						|
      case 6:
 | 
						|
         temp = (CONST4 *)u4alloc( (long)sizeof( CONST4 ) ) ;
 | 
						|
         if ( temp == 0 )
 | 
						|
            return 0 ;
 | 
						|
         memcpy( (void *)temp, (void *)con, sizeof( CONST4 ) ) ;
 | 
						|
         l4add( &tempLeaf->ne, temp ) ;
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
         return error4( parent->log->codeBase, e4info, E93701 ) ;
 | 
						|
   }
 | 
						|
   memset( (void *)con, 0 ,sizeof( CONST4 ) ) ;
 | 
						|
   newBranch = bitmap4redistribute( 0, newBranch, 0 ) ;
 | 
						|
 | 
						|
   if ( error4code( parent->log->codeBase ) < 0 )
 | 
						|
      return error4code( parent->log->codeBase ) ;
 | 
						|
 | 
						|
   if ( newBranch->children.nLink == 0 )
 | 
						|
      bitmap4destroy( newBranch ) ;
 | 
						|
   else
 | 
						|
      l4add( &parent->children, newBranch ) ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* this function redistributes (splits and combines) and/and, or/or block sequences */
 | 
						|
BITMAP4 * bitmap4redistribute( BITMAP4 *parent, BITMAP4 *map, const char doShrink )
 | 
						|
{
 | 
						|
   BITMAP4 *childMap, *childOn, *parent2map ;
 | 
						|
   char split ;
 | 
						|
 | 
						|
   if ( map->branch == 0 )
 | 
						|
      return map ;
 | 
						|
 | 
						|
   /* first combine all the children of this map */
 | 
						|
   childOn = childMap = (BITMAP4 *)l4first( &map->children ) ;
 | 
						|
   for( ;; )
 | 
						|
   {
 | 
						|
      if ( childOn == 0 )
 | 
						|
         break ;
 | 
						|
      childOn = bitmap4redistribute( map, childOn, 0 ) ;
 | 
						|
      childOn = (BITMAP4 *)l4next( &map->children, childOn ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   /* now combine all leaf children where possible */
 | 
						|
   if ( parent != 0 )
 | 
						|
      if ( parent->andOr != map->andOr )  /* case where no combos possible */
 | 
						|
         return map ;
 | 
						|
 | 
						|
   parent2map = 0 ;
 | 
						|
   childMap = (BITMAP4 *)l4first( &map->children ) ;
 | 
						|
   for( ; childMap != 0 ; )
 | 
						|
   {
 | 
						|
      childOn = (BITMAP4 *)l4next( &map->children, childMap ) ;
 | 
						|
      if ( childOn == 0 )
 | 
						|
         break ;
 | 
						|
 | 
						|
      split = 0 ;
 | 
						|
      if ( childOn->tag != childMap->tag || childOn->andOr != childMap->andOr )
 | 
						|
        split = 1 ;
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if ( map != 0 )
 | 
						|
           if ( map->andOr != childOn->andOr )
 | 
						|
              split = 1 ;
 | 
						|
      }
 | 
						|
 | 
						|
      if ( split == 1 )
 | 
						|
      {
 | 
						|
         if ( parent2map == 0 )
 | 
						|
         {
 | 
						|
            parent2map = bitmap4create( map->log, map->relate, map->andOr, 1 ) ;
 | 
						|
            if ( parent2map == 0 )  /* must handle by freeing... */
 | 
						|
               return 0 ;
 | 
						|
            if ( parent == 0 )
 | 
						|
            {
 | 
						|
               parent = bitmap4create( map->log, map->relate, map->andOr, 1 ) ;
 | 
						|
               if ( parent == 0 )  /* must handle by freeing... */
 | 
						|
                  return 0 ;
 | 
						|
               l4add( &parent->children, map ) ;
 | 
						|
            }
 | 
						|
            l4add( &parent->children, parent2map ) ;
 | 
						|
         }
 | 
						|
         l4remove( &map->children, childOn ) ;
 | 
						|
         l4add( &parent2map->children, childOn ) ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         childMap = bitmap4combineLeafs( map, childMap, childOn ) ;
 | 
						|
         if ( error4code( map->log->codeBase ) < 0 )
 | 
						|
            return 0 ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( parent2map != 0 )
 | 
						|
   {
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( parent == 0 )
 | 
						|
         {
 | 
						|
            error4( map->log->codeBase, e4info, E93701 ) ;
 | 
						|
            return 0 ;
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
      bitmap4redistribute( parent, parent2map, 1 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( doShrink )
 | 
						|
   {
 | 
						|
      if ( map->children.nLink == 1 )   /* just a child, so remove myself */
 | 
						|
      {
 | 
						|
         childMap = (BITMAP4 *)l4first( &map->children ) ;
 | 
						|
         l4remove( &map->children, childMap ) ;
 | 
						|
         if ( parent != 0 )
 | 
						|
         {
 | 
						|
            #ifdef E4ANALYZE
 | 
						|
               if ( childMap->tag == 0 && childMap->children.nLink == 0 )
 | 
						|
               {
 | 
						|
                  error4( childMap->log->codeBase, e4info, E93701 ) ;
 | 
						|
                  return 0 ;
 | 
						|
               }
 | 
						|
            #endif
 | 
						|
            if ( parent->tag == 0 && childMap->tag != 0 )
 | 
						|
               parent->tag = childMap->tag ;
 | 
						|
            l4addAfter( &parent->children, map, childMap ) ;
 | 
						|
            l4remove( &parent->children, map ) ;
 | 
						|
         }
 | 
						|
         bitmap4destroy( map ) ;
 | 
						|
         map = childMap ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   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 *bitmap4redistributeLeaf( BITMAP4 *parent, BITMAP4 *map1, BITMAP4 *map2 )
 | 
						|
{
 | 
						|
   BITMAP4 *newBranch, *orMap, *place, *andMap, *temp ;
 | 
						|
   CONST4 *cOn ;
 | 
						|
 | 
						|
   newBranch = bitmap4create( parent->log, parent->relate, 1, 1 ) ;
 | 
						|
   if ( newBranch == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   place = bitmap4create( parent->log, parent->relate, 0, 0 ) ;
 | 
						|
   if ( place == 0 )
 | 
						|
      return 0 ;
 | 
						|
   l4addAfter( &parent->children, map1, place ) ;
 | 
						|
 | 
						|
   l4remove( &parent->children, map1 ) ;
 | 
						|
   l4remove( &parent->children, map2 ) ;
 | 
						|
 | 
						|
   if ( map1->andOr == 1 )
 | 
						|
   {
 | 
						|
      andMap = map1 ;
 | 
						|
      orMap = map2 ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      andMap = map2 ;
 | 
						|
      orMap = map1 ;
 | 
						|
   }
 | 
						|
 | 
						|
   bitmap4constantCombine( newBranch, andMap, &orMap->lt, 1 ) ;
 | 
						|
   bitmap4constantCombine( newBranch, andMap, &orMap->le, 2 ) ;
 | 
						|
   bitmap4constantCombine( newBranch, andMap, &orMap->gt, 3 ) ;
 | 
						|
   bitmap4constantCombine( newBranch, andMap, &orMap->ge, 4 ) ;
 | 
						|
   bitmap4constantCombine( newBranch, andMap, &orMap->eq, 5 ) ;
 | 
						|
   for( ;; )
 | 
						|
   {
 | 
						|
      cOn = (CONST4 *)l4first( &orMap->ne ) ;
 | 
						|
      if ( cOn == 0 )
 | 
						|
         break ;
 | 
						|
      bitmap4constantCombine( newBranch, andMap, cOn, 6 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( error4code( parent->log->codeBase ) == e4memory )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   if ( newBranch->children.nLink == 0 )   /* collapsed */
 | 
						|
   {
 | 
						|
      if ( parent->tag == 0 && andMap->tag != 0 )
 | 
						|
         parent->tag = andMap->tag ;
 | 
						|
      bitmap4destroy( newBranch ) ;
 | 
						|
      newBranch = 0 ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      while( newBranch->branch == 1 && newBranch->children.nLink == 1 )
 | 
						|
      {
 | 
						|
         temp = (BITMAP4 *)l4first( &newBranch->children ) ;
 | 
						|
         bitmap4destroy( newBranch ) ;
 | 
						|
         newBranch = temp ;
 | 
						|
      }
 | 
						|
      l4addAfter( &parent->children, place, newBranch ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   l4remove( &parent->children, place ) ;
 | 
						|
   bitmap4destroy( place ) ;
 | 
						|
   bitmap4destroy( orMap ) ;
 | 
						|
   bitmap4destroy( andMap ) ;
 | 
						|
 | 
						|
   return newBranch ;
 | 
						|
}
 | 
						|
 | 
						|
/* this function splits and combines and/or, or/and block sequences */
 | 
						|
/* all bitmaps must be in standard bitmap4redistribute format prior to call */
 | 
						|
BITMAP4 * bitmap4redistributeBranch( BITMAP4 *parent, BITMAP4 *map )
 | 
						|
{
 | 
						|
   BITMAP4 *childOn2, *childOn, *childNext2 ;
 | 
						|
 | 
						|
   if ( map->branch == 0 )
 | 
						|
      return map ;
 | 
						|
 | 
						|
   childOn = (BITMAP4 *)l4first( &map->children ) ;
 | 
						|
 | 
						|
   for( ;; )
 | 
						|
   {
 | 
						|
      if ( childOn == 0 )
 | 
						|
         break ;
 | 
						|
      if ( childOn->branch )
 | 
						|
      {
 | 
						|
         childOn = bitmap4redistributeBranch( map, childOn ) ;
 | 
						|
         if ( childOn == 0 && error4code( parent->log->codeBase ) == e4memory )
 | 
						|
            return 0 ;
 | 
						|
      }
 | 
						|
      if ( childOn->branch == 0 )
 | 
						|
      {
 | 
						|
         childOn2 = (BITMAP4 *)l4next( &map->children, childOn ) ;
 | 
						|
         while( childOn2 != 0 )
 | 
						|
         {
 | 
						|
            if ( childOn2->branch )
 | 
						|
            {
 | 
						|
               childOn2 = bitmap4redistributeBranch( map, childOn2 ) ;
 | 
						|
               if ( childOn2 == 0 && error4code( parent->log->codeBase ) == e4memory )
 | 
						|
                  return 0 ;
 | 
						|
            }
 | 
						|
            childNext2 = (BITMAP4 *)l4next( &map->children, childOn2 ) ;
 | 
						|
            if ( childOn->branch == 0 && map->andOr == 1 && childOn->tag == childOn2->tag &&  childOn->andOr != childOn2->andOr )
 | 
						|
            {
 | 
						|
               childOn = bitmap4redistributeLeaf( map, childOn, childOn2 ) ;
 | 
						|
               if ( childOn == 0 && error4code( parent->log->codeBase ) == e4memory )
 | 
						|
                  return 0 ;
 | 
						|
            }
 | 
						|
            childOn2 = childNext2 ;
 | 
						|
         }
 | 
						|
      }
 | 
						|
      childOn = (BITMAP4 *)l4next( &map->children, childOn ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( map->branch == 1 )
 | 
						|
   {
 | 
						|
      if ( map->children.nLink == 0 )   /* mark ourselves as a leaf with no match */
 | 
						|
      {
 | 
						|
         map->branch = 0 ;
 | 
						|
         map->noMatch = 1 ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
         if ( map->children.nLink == 1 )   /* just a child, so remove myself */
 | 
						|
         {
 | 
						|
            childOn = (BITMAP4 *)l4first( &map->children ) ;
 | 
						|
            l4remove( &map->children, childOn ) ;
 | 
						|
            if ( parent != 0 )
 | 
						|
            {
 | 
						|
               l4addAfter( &parent->children, map, childOn ) ;
 | 
						|
               l4remove( &parent->children, map ) ;
 | 
						|
            }
 | 
						|
            bitmap4destroy( map ) ;
 | 
						|
            map = childOn ;
 | 
						|
         }
 | 
						|
   }
 | 
						|
 | 
						|
   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 bitmap4seek( BITMAP4 *map, const CONST4 *con, const char location, const long check, const int doCheck )
 | 
						|
{
 | 
						|
   int len, rc ;
 | 
						|
   TAG4FILE *tag ;
 | 
						|
   char *result ;
 | 
						|
   #ifdef S4CLIPPER
 | 
						|
      int oldDec ;
 | 
						|
      char holdResult[20] ;  /* enough space for a numerical key */
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4VFP_KEY
 | 
						|
      char buf[I4MAX_KEY_SIZE] ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   tag = map->tag ;
 | 
						|
   result = (char *)const4return( map->log, con ) ;
 | 
						|
 | 
						|
   /* must convert to a proper key */
 | 
						|
   if ( map->type != r4str )
 | 
						|
   {
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
         {
 | 
						|
            oldDec = tag->codeBase->decimals ;
 | 
						|
            tag->codeBase->decimals = tag->header.keyDec ;
 | 
						|
            memcpy( holdResult, result, con->len ) ;
 | 
						|
            result = holdResult ;
 | 
						|
      #endif
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( expr4len( tag->expr ) == -1 )
 | 
						|
            return error4( map->log->codeBase, e4info, E83701 ) ;
 | 
						|
      #endif
 | 
						|
      len = expr4keyConvert( tag->expr, (char **)&result, con->len, map->type ) ;
 | 
						|
      #ifdef S4CLIPPER
 | 
						|
            tag->codeBase->decimals = oldDec ;
 | 
						|
         }
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      len = con->len ;
 | 
						|
      #ifdef S4VFP_KEY
 | 
						|
      if ( tfile4vfpKey( tag ) )
 | 
						|
      {
 | 
						|
         if ( len*2 > sizeof(buf) )
 | 
						|
            return error4( map->log->codeBase, e4info, E82102 ) ;
 | 
						|
         len = t4strToVFPKey( buf, result, len, len*2, &tag->vfpInfo ) ;
 | 
						|
         if ( len < 0 )
 | 
						|
            return error4( map->log->codeBase, e4info, E85404 ) ;
 | 
						|
         result = buf ;
 | 
						|
      }
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
 | 
						|
   if ( location > 1 )
 | 
						|
      tfile4descending( tag, 1 ) ;
 | 
						|
   else
 | 
						|
      tfile4descending( tag, 0 ) ;
 | 
						|
   tfile4seek( tag, result, len ) ;
 | 
						|
   tfile4descending( tag, 0 ) ;
 | 
						|
 | 
						|
   if ( !tfile4eof( tag ) )
 | 
						|
      if ( doCheck == 1 )
 | 
						|
        if ( check == tfile4recNo( tag ) )
 | 
						|
           return -1 ;
 | 
						|
 | 
						|
   switch ( location )
 | 
						|
   {
 | 
						|
      case 0:
 | 
						|
         if ( tfile4skip( tag, -1L ) != -1L )   /* at top already */
 | 
						|
            return -1 ;
 | 
						|
         break ;
 | 
						|
      case 1:
 | 
						|
         if ( tfile4eof( tag ) )
 | 
						|
            return -1 ;
 | 
						|
         break ;
 | 
						|
      case 2:
 | 
						|
         if ( !tfile4eof( tag ) )
 | 
						|
         #ifdef S4FOX
 | 
						|
            if( u4keycmp( tfile4keyData(tag)->value, result, (unsigned int)len, (unsigned int)tag->header.keyLen, 0, &tag->vfpInfo ) != 0 )
 | 
						|
          #else
 | 
						|
            if( (*tag->cmp)( tfile4keyData(tag)->value, result, (unsigned int)len ) != 0 )  /* last one is too far, go back one for a closure */
 | 
						|
         #endif
 | 
						|
         {
 | 
						|
            if ( doCheck == 1 )
 | 
						|
               if ( check == tfile4recNo( tag ) )   /* case where none belong, so break now */
 | 
						|
                  return -1 ;
 | 
						|
         }
 | 
						|
         break ;
 | 
						|
      case 3:
 | 
						|
         if ( tfile4eof( tag ) )
 | 
						|
         {
 | 
						|
            rc = tfile4top( tag ) ;
 | 
						|
            if ( rc != 0 )  /* no records */
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            rc = (int)tfile4skip( tag, 1L ) ;
 | 
						|
            if ( rc == 0L )
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
         return error4( map->log->codeBase, e4info, E93701 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return tfile4recNo( tag ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#ifdef S4NDX
 | 
						|
long bitmap4seek( BITMAP4 *map, CONST4 *con, char location, long check, int doCheck )
 | 
						|
{
 | 
						|
   int len, rc ;
 | 
						|
   TAG4FILE *tag ;
 | 
						|
   char *result ;
 | 
						|
   char didSkip ;
 | 
						|
   int seekRc ;
 | 
						|
 | 
						|
   tag = map->tag ;
 | 
						|
   result = (char *)const4return( map->log, con ) ;
 | 
						|
 | 
						|
   if ( map->type != r4str )   /* must convert to a proper key */
 | 
						|
   {
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( expr4len( tag->expr ) == -1 )
 | 
						|
            return error4( map->log->codeBase, e4info, 83701 ) ;
 | 
						|
      #endif
 | 
						|
      len = expr4keyConvert( tag->expr, (char **)&result, con->len, map->type ) ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      len = con->len ;
 | 
						|
 | 
						|
   seekRc = tfile4seek( tag, result, len ) ;
 | 
						|
 | 
						|
   if ( !tfile4eof( tag ) )
 | 
						|
      if ( doCheck && location < 2 )
 | 
						|
        if ( check == tfile4recNo( tag ) )
 | 
						|
           return -1 ;
 | 
						|
 | 
						|
   switch ( location )
 | 
						|
   {
 | 
						|
      case 0:
 | 
						|
         if ( tfile4skip( tag, -1L ) != -1L )   /* at top already */
 | 
						|
           return -1 ;
 | 
						|
         break ;
 | 
						|
      case 1:
 | 
						|
         if ( tfile4eof( tag ) )
 | 
						|
            return -1 ;
 | 
						|
         break ;
 | 
						|
      case 2:
 | 
						|
         if( (*tag->cmp)( tfile4keyData(tag)->value, result, len ) != 0 )  /* last one is too far, go back one for a closure */
 | 
						|
         {
 | 
						|
            if ( !tfile4eof( tag ) )
 | 
						|
               if ( check == tfile4recNo( tag ) )   /* case where none belong, so break now */
 | 
						|
                  return -1 ;
 | 
						|
            if ( tfile4skip( tag, -1L ) != -1L )
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
      case 3:
 | 
						|
         didSkip = 0 ;
 | 
						|
 | 
						|
         for(; (*tag->cmp)( tfile4keyData(tag)->value, result, len ) == 0; )
 | 
						|
         {
 | 
						|
            rc = (int)tfile4skip( 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 */
 | 
						|
                  didSkip = 0 ;
 | 
						|
               if ( location == 3 )   /* on last record not far enough, so none match */
 | 
						|
                  return -1 ;
 | 
						|
               break ;
 | 
						|
            }
 | 
						|
            didSkip = 1 ;
 | 
						|
         }
 | 
						|
 | 
						|
         if ( location == 3 )
 | 
						|
         {
 | 
						|
            if ( didSkip == 0 && seekRc != 2 )
 | 
						|
               if ( tfile4skip( tag, 1L ) != 1L )
 | 
						|
                  return -1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            if ( didSkip == 1 )
 | 
						|
               if ( tfile4skip( tag, -1L ) != -1L )
 | 
						|
                  return -1 ;
 | 
						|
        break ;
 | 
						|
      default:
 | 
						|
         return error4( map->log->codeBase, e4info, E93701 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return tfile4recNo( tag ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#ifdef S4MDX
 | 
						|
long bitmap4seek( BITMAP4 *map, const CONST4 *con, const char location, const long check, const int doCheck )
 | 
						|
{
 | 
						|
   int len, rc, seekRc, isDesc ;
 | 
						|
   TAG4FILE *tag ;
 | 
						|
   char *result ;
 | 
						|
   char didSkip ;
 | 
						|
 | 
						|
   tag = map->tag ;
 | 
						|
   result = (char *)const4return( map->log, con ) ;
 | 
						|
   isDesc = ( tag->header.typeCode & 8 ) ? 1 : 0 ;
 | 
						|
 | 
						|
   if ( map->type != r4str )   /* must convert to a proper key */
 | 
						|
   {
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( expr4len( tag->expr ) == -1 )
 | 
						|
            return error4( map->log->codeBase, e4info, E83701 ) ;
 | 
						|
      #endif
 | 
						|
      len = expr4keyConvert( tag->expr, (char **)&result, con->len, map->type ) ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      len = con->len ;
 | 
						|
 | 
						|
   seekRc = tfile4seek( tag, result, len ) ;
 | 
						|
 | 
						|
   if ( !tfile4eof( tag ) )
 | 
						|
      if ( doCheck && location < 2 )
 | 
						|
         if ( check == tfile4recNo( tag ) )
 | 
						|
            return -1 ;
 | 
						|
 | 
						|
   switch ( location )
 | 
						|
   {
 | 
						|
      case 0:
 | 
						|
         if ( isDesc )
 | 
						|
         {
 | 
						|
            if ( tfile4eof( tag ) )
 | 
						|
               return -1 ;
 | 
						|
            for(; (*tag->cmp)( tfile4keyData(tag)->value, result, len ) == 0; )
 | 
						|
            {
 | 
						|
               rc = (int)tfile4skip( tag, 1L ) ;
 | 
						|
               if ( rc < 0 )
 | 
						|
                 return -1 ;
 | 
						|
               if ( rc != 1 )
 | 
						|
               {
 | 
						|
                 if ( rc == 0 )
 | 
						|
                    return -1 ;
 | 
						|
                 break ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
            if ( tfile4skip( tag, -1L ) != -1L )   /* at top already */
 | 
						|
               return -1 ;
 | 
						|
         break ;
 | 
						|
       case 1:
 | 
						|
         if ( isDesc )
 | 
						|
         {
 | 
						|
            if ( seekRc == 2 )
 | 
						|
            {
 | 
						|
               if ( !tfile4eof( tag ) )
 | 
						|
                 if ( check == tfile4recNo( tag ) )   /* case where none belong, so break now */
 | 
						|
                    return -1 ;
 | 
						|
               if ( tfile4skip( tag, -1L ) != -1L )
 | 
						|
                 return -1 ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
               rc = -1 ;
 | 
						|
               for(; (*tag->cmp)( tfile4keyData(tag)->value, result, len ) == 0; )
 | 
						|
               {
 | 
						|
                  rc = (int)tfile4skip( tag, 1L ) ;
 | 
						|
                  if ( rc < 0 )
 | 
						|
                     return -1 ;
 | 
						|
                  if ( rc != 1 )
 | 
						|
                     break ;
 | 
						|
               }
 | 
						|
               if ( rc == 0 )
 | 
						|
                  tfile4bottom( tag ) ;
 | 
						|
               else
 | 
						|
                  tfile4skip( tag, -1L ) ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            if ( tfile4eof( tag ) )
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
         break ;
 | 
						|
      case 2:
 | 
						|
         if ( isDesc )
 | 
						|
         {
 | 
						|
            if ( tfile4eof( tag ) )
 | 
						|
               return -1 ;
 | 
						|
            if ( seekRc == 2 )
 | 
						|
               if ( check == tfile4recNo( tag ) )   /* case where none belong, so break now */
 | 
						|
                  return -1 ;
 | 
						|
            break ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            if( (*tag->cmp)( tfile4keyData(tag)->value, result, len ) != 0 )  /* last one is too far, go back one for a closure */
 | 
						|
            {
 | 
						|
               if ( !tfile4eof( tag ) )
 | 
						|
                  if ( check == tfile4recNo( tag ) )   /* case where none belong, so break now */
 | 
						|
                     return -1 ;
 | 
						|
               if ( tfile4skip( tag, -1L ) != -1L )
 | 
						|
                  return -1 ;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      case 3:
 | 
						|
         if ( isDesc )
 | 
						|
         {
 | 
						|
            if ( tfile4skip( tag, -1L ) != -1L )   /* at top already */
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            didSkip = 0 ;
 | 
						|
 | 
						|
            for(; (*tag->cmp)( tfile4keyData(tag)->value, result, len ) == 0; )
 | 
						|
            {
 | 
						|
               rc = (int)tfile4skip( 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 */
 | 
						|
                     didSkip = 0 ;
 | 
						|
                  if ( location == 3 )   /* on last record not far enough, so none match */
 | 
						|
                     return -1 ;
 | 
						|
                  break ;
 | 
						|
               }
 | 
						|
               didSkip = 1 ;
 | 
						|
            }
 | 
						|
 | 
						|
            if ( location == 3 )
 | 
						|
            {
 | 
						|
               if ( didSkip == 0 && seekRc != 2 )
 | 
						|
                  if ( tfile4skip( tag, 1L ) != 1L )
 | 
						|
                     return -1 ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
               if ( didSkip == 1 )
 | 
						|
                 if ( tfile4skip( tag, -1L ) != -1L )
 | 
						|
                     return -1 ;
 | 
						|
         }
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
         return error4( map->log->codeBase, e4info, E93701 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return tfile4recNo( tag ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* returns a pointer to the constant value */
 | 
						|
void *const4return( L4LOGICAL *log, const CONST4 *c1 )
 | 
						|
{
 | 
						|
   return (void *)( log->buf + c1->offset ) ;
 | 
						|
}
 | 
						|
 | 
						|
/* updates the log's constant memory buffer, re-allocating memory if required */
 | 
						|
int const4memAlloc( L4LOGICAL *log, const unsigned len )
 | 
						|
{
 | 
						|
   if ( ( log->bufPos + len ) > log->bufLen )
 | 
						|
   {
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( (long)len + (long)log->bufLen != (long)(len + log->bufLen) )
 | 
						|
            return error4( log->codeBase, e4memory, E83702 ) ;
 | 
						|
      #endif
 | 
						|
      if ( u4allocAgain( log->codeBase, &log->buf, &log->bufLen, log->bufPos + len ) != 0 )
 | 
						|
         return error4( log->codeBase, e4memory, E93704 ) ;
 | 
						|
   }
 | 
						|
   log->bufPos += len ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* duplicate an existing constant */
 | 
						|
int const4duplicate( CONST4 *to, const CONST4 *from, L4LOGICAL *log )
 | 
						|
{
 | 
						|
   unsigned int len ;
 | 
						|
 | 
						|
   len = (unsigned int)from->len ;
 | 
						|
 | 
						|
   if ( len == 0 )
 | 
						|
      memset( (void *)to, 0, (unsigned int)sizeof( CONST4 ) ) ;
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if ( const4memAlloc( log, len ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
      memcpy( log->buf + log->bufPos - len, const4return( log, from ), len ) ;
 | 
						|
      to->offset = log->bufLen - len ;
 | 
						|
      to->len = len ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* get a constant from an expr. info structure */
 | 
						|
int const4get( CONST4 *con, BITMAP4 *map, L4LOGICAL *log, const int pos )
 | 
						|
{
 | 
						|
   unsigned int len ;
 | 
						|
   char *result ;
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   if ( expr4execute( log->expr, pos, (void **)&result ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   len = (unsigned int)log->expr->info[pos].len ;
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      if ( map->type != 0 && map->type != v4functions[log->expr->info[pos].functionI].returnType )
 | 
						|
         return error4( map->log->codeBase, e4info, E83703 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   rc = const4memAlloc( log, len ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( map->log->codeBase, rc, E93704 ) ;
 | 
						|
 | 
						|
   memcpy( log->buf + log->bufPos - len, result, len ) ;
 | 
						|
   map->type = v4functions[log->expr->info[pos].functionI].returnType ;
 | 
						|
   con->offset = log->bufLen - len ;
 | 
						|
   con->len = len ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int const4less( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
 | 
						|
{
 | 
						|
   switch( map->type )
 | 
						|
   {
 | 
						|
      case r4numDoub:
 | 
						|
      case r4dateDoub:
 | 
						|
         #ifdef E4ANALYZE
 | 
						|
            if ( p1->len != p2->len )
 | 
						|
               return error4( map->log->codeBase, e4struct, E93704 ) ;
 | 
						|
         #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 ( c4memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), (unsigned int)p1->len ) <= 0 )
 | 
						|
               return 1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            if ( c4memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), (unsigned int)p2->len ) < 0 )
 | 
						|
               return 1 ;
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
         return error4( map->log->codeBase, e4info, E93704 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int const4eq( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
 | 
						|
{
 | 
						|
   if ( p1->len < p2->len )
 | 
						|
   {
 | 
						|
      #ifdef E4ANALYZE
 | 
						|
         if ( map->type == r4numDoub || map->type == r4dateDoub )
 | 
						|
            return error4( map->log->codeBase, e4struct, E93704 ) ;
 | 
						|
      #endif
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef E4ANALYZE
 | 
						|
      switch( map->type )
 | 
						|
      {
 | 
						|
         case r4numDoub:
 | 
						|
         case r4dateDoub:
 | 
						|
         case r4num:
 | 
						|
         case r4str:
 | 
						|
         case r4log:
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            return error4( map->log->codeBase, e4info, E93704 ) ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( c4memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), (unsigned int)p1->len ) == 0 )
 | 
						|
      return 1 ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int const4lessEq( CONST4 *p1, CONST4 *p2, BITMAP4 *map )
 | 
						|
{
 | 
						|
   switch( map->type )
 | 
						|
   {
 | 
						|
      case r4numDoub:
 | 
						|
      case r4dateDoub:
 | 
						|
         #ifdef E4ANALYZE
 | 
						|
            if ( p1->len != p2->len )
 | 
						|
               return error4( map->log->codeBase, e4struct, E93704 ) ;
 | 
						|
         #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 ( c4memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), (unsigned int)p1->len ) <= 0 )
 | 
						|
               return 1 ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
            if ( c4memcmp( const4return( map->log, p1 ), const4return( map->log, p2 ), (unsigned int)p2->len ) < 0 )
 | 
						|
               return 1 ;
 | 
						|
         break ;
 | 
						|
      default:
 | 
						|
         return error4( map->log->codeBase, e4info, E93704 ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
void const4addNe( BITMAP4 *map, CONST4 *con )
 | 
						|
{
 | 
						|
   CONST4 *cOn ;
 | 
						|
 | 
						|
   cOn = (CONST4 *)l4first( &map->ne ) ;
 | 
						|
   while ( cOn != 0 )
 | 
						|
   {
 | 
						|
      if ( const4eq( con, cOn, map ) )  /* ne already exists, so ignore */
 | 
						|
         return ;
 | 
						|
      cOn = (CONST4 *)l4next( &map->ne, cOn ) ;
 | 
						|
   }
 | 
						|
   cOn = (CONST4 *) u4alloc( (long)sizeof( CONST4 ) ) ;
 | 
						|
   if ( cOn == 0 )
 | 
						|
      return ;
 | 
						|
   memcpy( (void *)cOn, (void *)con, (unsigned int)sizeof( CONST4 ) ) ;
 | 
						|
   l4add( &map->ne, cOn ) ;
 | 
						|
   memset( (void *)con, 0, (unsigned int)sizeof( CONST4 ) ) ;
 | 
						|
}
 | 
						|
 | 
						|
void const4deleteNe( LIST4 *list, CONST4 *con )
 | 
						|
{
 | 
						|
   l4remove( list, con ) ;
 | 
						|
   u4free( con ) ;
 | 
						|
}
 | 
						|
 | 
						|
#endif   /* S4INDEX_OFF */
 | 
						|
#endif   /* S4CLIENT */
 | 
						|
 |