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