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