539 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			539 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* r4log.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifdef __TURBOC__
 | 
						|
   #pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4CLIENT
 | 
						|
 | 
						|
static int dataList4isIn( DATA4LIST *, const RELATE4 * ) ;
 | 
						|
static int log4swapEntries( L4LOGICAL *, const int, const int ) ;
 | 
						|
 | 
						|
int e4isConstant( E4INFO *infoPtr )
 | 
						|
{
 | 
						|
   int pos ;
 | 
						|
 | 
						|
   if ( infoPtr->functionI == E4DOUBLE || infoPtr->functionI == E4STRING ||
 | 
						|
        ( infoPtr->functionI >= E4LOG_LOW && infoPtr->functionI <= E4LOG_HIGH )  )
 | 
						|
      return 1 ;
 | 
						|
 | 
						|
   if ( infoPtr->functionI == E4STOD || infoPtr->functionI == E4CTOD )   /* might be a constant */
 | 
						|
   {
 | 
						|
      for ( pos = infoPtr->numEntries - 1 ; pos >= 0 ; pos -- )
 | 
						|
         if ( (infoPtr-pos)->fieldPtr != 0 || (infoPtr-pos)->functionI >= E4CALC_FUNCTION )
 | 
						|
            return 0 ;
 | 
						|
      return 1 ;
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* returns true if there is a tag that matches the desired condition type,
 | 
						|
   AND if there is no filter on that tag */
 | 
						|
#ifdef P4ARGS_USED
 | 
						|
   #pragma argsused
 | 
						|
#endif
 | 
						|
int e4isTag( E4INFO_REPORT *reportPtr, EXPR4 *expr, E4INFO *infoPtr, DATA4 *data )
 | 
						|
{
 | 
						|
   #ifndef S4INDEX_OFF
 | 
						|
      TAG4 *tagOn ;
 | 
						|
      int isSame, i ;
 | 
						|
      E4INFO *infoOn, *tagInfo ;
 | 
						|
 | 
						|
      for( tagOn = 0;; )
 | 
						|
      {
 | 
						|
         tagOn = d4tagNext( data, tagOn ) ;
 | 
						|
         if ( tagOn == 0 )
 | 
						|
            break ;
 | 
						|
         #ifdef S4NDX
 | 
						|
            if (  t4unique( tagOn ) != r4uniqueContinue )  /* if unique, can't filter */
 | 
						|
         #else
 | 
						|
            if ( tagOn->tagFile->filter == 0 && ( t4unique( tagOn ) != r4uniqueContinue ) )  /* if unique a filter, than cannot bitmap optimize */
 | 
						|
         #endif
 | 
						|
         {
 | 
						|
            tagInfo = tagOn->tagFile->expr->info + tagOn->tagFile->expr->infoN -1 ;
 | 
						|
            if ( tagInfo->numEntries == infoPtr->numEntries )
 | 
						|
            {
 | 
						|
               isSame =  1 ;
 | 
						|
               infoOn = infoPtr ;
 | 
						|
               for( i = 0; i < infoPtr->numEntries && isSame; i++, infoOn--, tagInfo-- )
 | 
						|
               {
 | 
						|
                  /* verify the general info structure */
 | 
						|
                  if ((infoOn->len != tagInfo->len) || (infoOn->numEntries != tagInfo->numEntries) || (infoOn->numParms != tagInfo->numParms))
 | 
						|
                  {
 | 
						|
                     isSame = 0 ;
 | 
						|
                     break ;
 | 
						|
                  }
 | 
						|
 | 
						|
                  /* general match, so ensure a field match if appropriate */
 | 
						|
                  if ( infoOn->fieldPtr == 0 )
 | 
						|
                  {
 | 
						|
                     if ( tagInfo->fieldPtr != 0 )
 | 
						|
                     {
 | 
						|
                        isSame = 0 ;
 | 
						|
                        break ;
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                  {
 | 
						|
                     if ( tagInfo->fieldPtr == 0 )
 | 
						|
                     {
 | 
						|
                        isSame = 0 ;
 | 
						|
                        break ;
 | 
						|
                     }
 | 
						|
                     if ( c4memcmp( infoOn->fieldPtr, tagInfo->fieldPtr, sizeof( tagInfo->fieldPtr->name )
 | 
						|
                          + sizeof( tagInfo->fieldPtr->len ) + sizeof( tagInfo->fieldPtr->dec )
 | 
						|
                          + sizeof( tagInfo->fieldPtr->type ) + sizeof( tagInfo->fieldPtr->offset ) ) )
 | 
						|
                     {
 | 
						|
                        isSame = 0 ;
 | 
						|
                        break ;
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
 | 
						|
                  switch( infoOn->functionI )
 | 
						|
                  {
 | 
						|
                     case E4DOUBLE:
 | 
						|
                     case E4STRING:
 | 
						|
                     case E4CTOD:
 | 
						|
                     case E4DTOC:
 | 
						|
                     case E4DTOC+1:
 | 
						|
                        /* Compare Constant */
 | 
						|
                        if( c4memcmp( tagOn->tagFile->expr->constants + tagInfo->i1, expr->constants + infoOn->i1, (unsigned int)tagInfo->len ) != 0 )
 | 
						|
                           isSame = 0 ;
 | 
						|
                        break ;
 | 
						|
 | 
						|
                     default:
 | 
						|
                        isSame =  (infoOn->i1 == tagInfo->i1) ;
 | 
						|
                        break ;
 | 
						|
                  }
 | 
						|
                  if( infoOn->functionI != tagInfo->functionI )
 | 
						|
                     if( infoOn->functionI > E4LAST_FIELD
 | 
						|
                                     || tagInfo->functionI > E4LAST_FIELD )
 | 
						|
                        isSame = 0 ;
 | 
						|
               }
 | 
						|
               if( isSame )
 | 
						|
               {
 | 
						|
                  reportPtr->tag = tagOn->tagFile ;
 | 
						|
                  return 1 ;
 | 
						|
               }
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int dataList4add( DATA4LIST *list, CODE4 *codeBase, RELATE4 *newPointer )
 | 
						|
{
 | 
						|
   if ( error4code( codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   if ( newPointer == 0 )
 | 
						|
      return 0 ;
 | 
						|
   if ( dataList4isIn( list, newPointer ) )
 | 
						|
      return 0 ;
 | 
						|
   if( list->pointersTot <= list->pointersUsed )
 | 
						|
   {
 | 
						|
      list->pointersTot += 5 ;
 | 
						|
      if ( u4allocAgain( codeBase, (char **)&list->pointers, &list->memAllocated, list->pointersTot * sizeof(RELATE4 *)) < 0 )
 | 
						|
         return -1 ;
 | 
						|
   }
 | 
						|
   list->pointers[list->pointersUsed++] = newPointer ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int dataList4expandFromDbTree( DATA4LIST *list, CODE4 *codeBase )
 | 
						|
{
 | 
						|
   int i ;
 | 
						|
   RELATE4 *relateParent ;
 | 
						|
 | 
						|
   for( i = list->pointersUsed-1; i >= 0; i-- )
 | 
						|
   {
 | 
						|
      relateParent = list->pointers[i]->master ;
 | 
						|
      while( relateParent != 0 )
 | 
						|
      {
 | 
						|
         if ( dataList4add( list, codeBase, relateParent ) < 0 )
 | 
						|
            return -1 ;
 | 
						|
         relateParent = relateParent->master ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   if ( error4code( codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int dataList4isIn( DATA4LIST *list, const RELATE4 *newPointer )
 | 
						|
{
 | 
						|
   int i ;
 | 
						|
   for( i = 0 ; i < list->pointersTot ; i++ )
 | 
						|
      if ( list->pointers[i] == newPointer )
 | 
						|
         return 1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int dataList4readRecords( DATA4LIST *dList )
 | 
						|
{
 | 
						|
   RELATE4 *cur ;
 | 
						|
   int i, rc ;
 | 
						|
 | 
						|
   if ( dList == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   for( i = dList->pointersUsed-1 ; i >= 0 ; i-- )
 | 
						|
   {
 | 
						|
      cur = dList->pointers[i] ;
 | 
						|
      rc = relate4readIn( cur ) ;
 | 
						|
      if ( rc  == relate4filterRecord || rc == r4terminate )
 | 
						|
         return rc ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
   }
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int dataList4remove( DATA4LIST *thisList, DATA4LIST *removeList )
 | 
						|
{
 | 
						|
   int i ;
 | 
						|
 | 
						|
   #ifdef E4PARM_LOW
 | 
						|
      if ( thisList == 0 || removeList == 0 )
 | 
						|
         return error4( 0, e4parm_null, E96001 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   for( i = 0; i < thisList->pointersUsed; i++ )
 | 
						|
      if( dataList4isIn( removeList, thisList->pointers[i]) )
 | 
						|
         thisList->pointers[i--] = thisList->pointers[--thisList->pointersUsed] ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int log4addToList( L4LOGICAL *log, E4INFO *infoPtr, DATA4LIST *list )
 | 
						|
{
 | 
						|
   int numParms, i ;
 | 
						|
 | 
						|
   if ( infoPtr->functionI <= E4LAST_FIELD )
 | 
						|
      if ( dataList4add( list, log->codeBase, relate4lookupRelate( (RELATE4 *)&log->relation->relate, f4data(infoPtr->fieldPtr)) ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
   if ( infoPtr->numEntries == 1 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   numParms = infoPtr->numParms ;
 | 
						|
   infoPtr-- ;
 | 
						|
 | 
						|
   for ( i = 0; i < numParms; i++ )
 | 
						|
   {
 | 
						|
      if ( log4addToList( log, infoPtr, list ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
      infoPtr -= infoPtr->numEntries ;
 | 
						|
   }
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int log4buildDatabaseLists( L4LOGICAL *log )
 | 
						|
{
 | 
						|
   int lastPos, pos, i ;
 | 
						|
   E4INFO *infoLast ;
 | 
						|
 | 
						|
   log->infoReport = (E4INFO_REPORT *)u4allocEr( log->codeBase, (long)sizeof(E4INFO_REPORT) * log->expr->infoN ) ;
 | 
						|
   if ( log->infoReport == 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   lastPos = log->expr->infoN - 1 ;
 | 
						|
   infoLast = (E4INFO *)log->expr->info + lastPos ;
 | 
						|
 | 
						|
   if ( infoLast->functionI == E4AND )
 | 
						|
   {
 | 
						|
      pos = lastPos - 1 ;
 | 
						|
 | 
						|
      for ( i = 0; i < infoLast->numParms; i++ )
 | 
						|
      {
 | 
						|
         if ( log->infoReport[pos].relateDataList == 0 )
 | 
						|
         {
 | 
						|
            log->infoReport[pos].relateDataList = (DATA4LIST *)mem4createAlloc( log->codeBase,
 | 
						|
                   &log->codeBase->dataListMemory, 5, sizeof(DATA4LIST), 5, 0 ) ;
 | 
						|
            if ( log->infoReport[pos].relateDataList == 0 )
 | 
						|
               return -1 ;
 | 
						|
         }
 | 
						|
         if ( log4addToList( log, log->expr->info+pos, log->infoReport[pos].relateDataList ) < 0 )
 | 
						|
            return -1 ;
 | 
						|
         pos -= log->expr->info[pos].numEntries ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if ( log->infoReport[lastPos].relateDataList == 0 )
 | 
						|
      {
 | 
						|
         log->infoReport[lastPos].relateDataList = (DATA4LIST *)mem4createAlloc( log->codeBase,
 | 
						|
            &log->codeBase->dataListMemory, 5, sizeof( DATA4LIST ), 5, 0 ) ;
 | 
						|
         if ( log->infoReport[lastPos].relateDataList == 0 )
 | 
						|
            return -1 ;
 | 
						|
      }
 | 
						|
      log4addToList( log, infoLast, log->infoReport[lastPos].relateDataList ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int log4bitmapDo( L4LOGICAL *log )
 | 
						|
{
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   log4buildDatabaseLists( log ) ;
 | 
						|
   #ifndef S4INDEX_OFF
 | 
						|
      if ( bitmap4evaluate( log, log->expr->infoN - 1 ) < 0 )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int log4determineEvaluationOrder( L4LOGICAL *log )
 | 
						|
{
 | 
						|
   /* Expand Lists due to Database Tree */
 | 
						|
   int i, pos, numLeft, curSmallestPos, curSmallestNum, curPos ;
 | 
						|
   int numCompare, lastPos = log->expr->infoN -1 ;
 | 
						|
   E4INFO *infoLast, *infoPtr ;
 | 
						|
   E4INFO_REPORT *reportLast, *report, *curReport ;
 | 
						|
 | 
						|
   infoLast = (E4INFO *)log->expr->info + lastPos ;
 | 
						|
   reportLast = log->infoReport + lastPos ;
 | 
						|
 | 
						|
   if ( infoLast->functionI != E4AND )
 | 
						|
      return dataList4expandFromDbTree( reportLast->relateDataList, log->codeBase ) ;
 | 
						|
 | 
						|
   infoPtr = infoLast-1 ;
 | 
						|
   report = reportLast-1 ;
 | 
						|
   for ( i = 0; i < infoLast->numParms; i++ )
 | 
						|
   {
 | 
						|
      if ( dataList4expandFromDbTree(report->relateDataList, log->codeBase) < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
      report -= infoPtr->numEntries ;
 | 
						|
      infoPtr -= infoPtr->numEntries ;
 | 
						|
   }
 | 
						|
 | 
						|
   /* Change the evaluation orders by repeatedly determining the
 | 
						|
      list with the smallest number of entries and puting it at the end.
 | 
						|
      The idea is that we want the conditions which causes the fewest
 | 
						|
      additional database records to be read in, to be evaluated first.
 | 
						|
   */
 | 
						|
   pos = lastPos - 1 ;  /* Position currently being made into the fewest. */
 | 
						|
 | 
						|
   for( numLeft = infoLast->numParms; numLeft > 1; numLeft-- )
 | 
						|
   {
 | 
						|
      report = log->infoReport + pos ;
 | 
						|
      infoPtr = (E4INFO *)log->expr->info + pos ;
 | 
						|
 | 
						|
      /* Now determine which is the entry with the fewest data files. */
 | 
						|
      curSmallestPos = pos ;
 | 
						|
      curSmallestNum = report->relateDataList->pointersUsed ;
 | 
						|
 | 
						|
      curPos = pos - infoPtr->numEntries ;
 | 
						|
      for( numCompare = numLeft-1; numCompare > 0; numCompare-- )
 | 
						|
      {
 | 
						|
         curReport = log->infoReport + curPos ;
 | 
						|
 | 
						|
         if ( curReport->relateDataList->pointersUsed < curSmallestNum )
 | 
						|
         {
 | 
						|
            curSmallestNum = curReport->relateDataList->pointersUsed ;
 | 
						|
            curSmallestPos = curPos ;
 | 
						|
         }
 | 
						|
 | 
						|
         curPos -= log->expr->info[curPos].numEntries ;
 | 
						|
      }
 | 
						|
 | 
						|
      if( pos != curSmallestPos )
 | 
						|
          if ( log4swapEntries( log, pos, curSmallestPos ) < 0 )
 | 
						|
             return -1 ;
 | 
						|
 | 
						|
      /* The next step is to remove the data list for the first evaluated
 | 
						|
         condition from the data list of the rest of the conditions. */
 | 
						|
      curPos = pos - infoPtr->numEntries ;
 | 
						|
      for( i = numLeft-1; i > 0; i-- )
 | 
						|
      {
 | 
						|
         curReport = log->infoReport + curPos ;
 | 
						|
         dataList4remove( curReport->relateDataList, report->relateDataList ) ;
 | 
						|
         curPos -= log->expr->info[curPos].numEntries ;
 | 
						|
      }
 | 
						|
 | 
						|
      pos -= infoPtr->numEntries ;
 | 
						|
   }
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
static int log4swapEntries( L4LOGICAL *log, const int a, const int b )
 | 
						|
{
 | 
						|
   int largeEntries, smallEntries ;
 | 
						|
   char   *saveBuf ;
 | 
						|
   E4INFO  *aPtr, *bPtr, *small1, *large1, *middle1;
 | 
						|
   E4INFO_REPORT *small2, *large2, *middle2 ;
 | 
						|
   int  smallPos, largePos, middlePos, middleEntries, movePositions ;
 | 
						|
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   aPtr = log->expr->info + a ;
 | 
						|
   bPtr = log->expr->info + b ;
 | 
						|
 | 
						|
   if ( aPtr->numEntries > bPtr->numEntries )
 | 
						|
   {
 | 
						|
      small1= bPtr ;
 | 
						|
      large1= aPtr ;
 | 
						|
      smallPos = b ;
 | 
						|
      largePos = a ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      small1= aPtr ;
 | 
						|
      large1= bPtr ;
 | 
						|
      smallPos = a ;
 | 
						|
      largePos = b ;
 | 
						|
   }
 | 
						|
 | 
						|
   /* make copies of large and small entries because the info may be later
 | 
						|
      lost as swaps take place... */
 | 
						|
   largeEntries = large1->numEntries ;
 | 
						|
   smallEntries = small1->numEntries ;
 | 
						|
   saveBuf = (char *)u4allocFree( log->codeBase, (long)sizeof(E4INFO) * largeEntries ) ;
 | 
						|
   if ( saveBuf == 0 )
 | 
						|
      return error4( log->codeBase, e4memory, E86001 ) ;
 | 
						|
 | 
						|
   movePositions = largeEntries - smallEntries ;
 | 
						|
   if ( smallPos < largePos )
 | 
						|
   {
 | 
						|
      middlePos = smallPos + 1 ;
 | 
						|
      middleEntries = largePos - smallPos - largeEntries ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      middlePos = largePos + 1 ;
 | 
						|
      middleEntries = smallPos - largePos - smallEntries ;
 | 
						|
      movePositions = -movePositions ;
 | 
						|
   }
 | 
						|
   middle1= log->expr->info + middlePos ;
 | 
						|
 | 
						|
   memcpy( saveBuf, (void *)(large1- largeEntries + 1), sizeof(E4INFO) * largeEntries ) ;
 | 
						|
   if ( largePos > smallPos )  /* want to move small to end of large pos... */
 | 
						|
   {
 | 
						|
      memcpy( (void *)(large1- smallEntries + 1 ), (void *)(small1- smallEntries + 1),
 | 
						|
                  sizeof(E4INFO) *smallEntries ) ;
 | 
						|
      c4memmove( (void *)(middle1+ movePositions), middle1, sizeof(E4INFO) * middleEntries ) ;
 | 
						|
      memcpy( (void *)(small1- smallEntries + 1), saveBuf, sizeof(E4INFO) * largeEntries ) ;
 | 
						|
   }
 | 
						|
   else  /* want to move small to start of large pos... */
 | 
						|
   {
 | 
						|
      memcpy( (void *)(large1- largeEntries + 1 ), (void *)(small1- smallEntries + 1),
 | 
						|
                  sizeof(E4INFO) *smallEntries ) ;
 | 
						|
      c4memmove( (void *)(middle1+ movePositions), middle1, sizeof(E4INFO) * middleEntries ) ;
 | 
						|
      memcpy( (void *)(small1- largeEntries + 1), saveBuf, sizeof(E4INFO) * largeEntries ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   large2  = log->infoReport + largePos ;
 | 
						|
   small2  = log->infoReport + smallPos ;
 | 
						|
   middle2 = log->infoReport + middlePos ;
 | 
						|
 | 
						|
   memcpy( saveBuf, (void *)(large2 - largeEntries + 1), sizeof(E4INFO_REPORT) * largeEntries ) ;
 | 
						|
   if ( largePos > smallPos )  /* want to move small to end of large pos... */
 | 
						|
   {
 | 
						|
      memcpy( (void *)(large2 - smallEntries + 1), (void *)(small2 - smallEntries + 1),
 | 
						|
                  sizeof(E4INFO_REPORT) *smallEntries ) ;
 | 
						|
      c4memmove( middle2 + movePositions, middle2, sizeof(E4INFO_REPORT) * middleEntries ) ;
 | 
						|
      memcpy( (void *)(small2 - smallEntries + 1), saveBuf, sizeof(E4INFO_REPORT) * largeEntries ) ;
 | 
						|
   }
 | 
						|
   else  /* want to move small to start of large pos... */
 | 
						|
   {
 | 
						|
      memcpy( (void *)(large2 - largeEntries + 1), (void *)(small2 - smallEntries + 1),
 | 
						|
                  sizeof(E4INFO_REPORT) *smallEntries ) ;
 | 
						|
      c4memmove( middle2 + movePositions, middle2, sizeof(E4INFO_REPORT) * middleEntries ) ;
 | 
						|
      memcpy( (void *)(small2 - largeEntries + 1), saveBuf, sizeof(E4INFO_REPORT) * largeEntries ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   u4free( saveBuf ) ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
/* Must read in records, as appropriate, to evaluate the different parts of */
 | 
						|
/* the expression. */
 | 
						|
int log4true( L4LOGICAL *log )
 | 
						|
{
 | 
						|
   int curPos, rc, i, *resultPtr ;
 | 
						|
   E4INFO *infoPtr ;
 | 
						|
   E4INFO_REPORT *infoReportPtr ;
 | 
						|
   int nParms = 1 ;
 | 
						|
   curPos = log->expr->infoN - 1 ;
 | 
						|
 | 
						|
   if( log->expr->info[curPos].functionI == E4AND )
 | 
						|
   {
 | 
						|
      nParms = log->expr->info[curPos].numParms ;
 | 
						|
      curPos-- ;
 | 
						|
   }
 | 
						|
 | 
						|
   /* Go through each of the & sub-expressions and evaluate them, first */
 | 
						|
   /* reading in the appropriate database records for the sub-expression. */
 | 
						|
 | 
						|
   if ( expr4context( log->expr, log->expr->data ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
 | 
						|
   for( i = 0; i < nParms; i++ )
 | 
						|
   {
 | 
						|
      infoPtr = log->expr->info + curPos ;
 | 
						|
      infoReportPtr = log->infoReport + curPos ;
 | 
						|
 | 
						|
      rc = dataList4readRecords( infoReportPtr->relateDataList ) ;
 | 
						|
      if ( rc == relate4filterRecord )
 | 
						|
         return 0 ;
 | 
						|
      if ( rc == r4terminate )
 | 
						|
         return rc ;
 | 
						|
      if ( rc < 0 )
 | 
						|
         return -1 ;
 | 
						|
 | 
						|
      if ( log->expr->info[curPos].numParms < 2 )
 | 
						|
      {
 | 
						|
         if ( expr4execute( log->expr, curPos, (void **)&resultPtr ) < 0 )
 | 
						|
            return -1 ;
 | 
						|
         if ( *resultPtr == 0 )
 | 
						|
            return 0 ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         #ifdef S4TEST
 | 
						|
         #ifdef S4DEBUG
 | 
						|
            /* in debug case, if tag, the result must always be true if we get here... */
 | 
						|
            if ( log->codeBase->bitmap_disable == 0 && !log->relation->bitmapsFreed )   /* then do check */
 | 
						|
            {
 | 
						|
               if ( expr4execute( log->expr, curPos, (void **)&resultPtr ) < 0 )
 | 
						|
                  return -1 ;
 | 
						|
               if ( ( (infoReportPtr-1)->tag || (infoReportPtr-2)->tag ) )
 | 
						|
                  if ( *resultPtr == 0 )
 | 
						|
                     return error4( log->codeBase, e4info, E96002 ) ;
 | 
						|
            }
 | 
						|
         #endif
 | 
						|
         #endif
 | 
						|
 | 
						|
         if ( ( (infoReportPtr-1)->tag == 0 && (infoReportPtr-2)->tag == 0 ) || log->relation->bitmapsFreed )
 | 
						|
         {
 | 
						|
            if ( expr4execute( log->expr, curPos, (void **)&resultPtr ) < 0 )
 | 
						|
               return -1 ;
 | 
						|
            if ( *resultPtr == 0 )
 | 
						|
               return 0 ;
 | 
						|
         }
 | 
						|
      }
 | 
						|
      curPos -= infoPtr->numEntries ;
 | 
						|
   }
 | 
						|
   if ( error4code( log->codeBase ) < 0 )
 | 
						|
      return -1 ;
 | 
						|
   return 1 ;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* S4CLIENT */
 |