215 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* e4calc.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifdef ___TURBOC__
 | |
|    #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| void S4FUNCTION expr4calcMassage( EXPR4CALC *calc )
 | |
| {
 | |
|    EXPR4 *exp4 = calc->expr;
 | |
| 
 | |
|    if( exp4->type == r4num )
 | |
|    {
 | |
|       /* Must consist of a single numeric field */
 | |
|       exp4->type =  r4numDoub ;
 | |
|       exp4->len =  sizeof(double) ;
 | |
|       exp4->info->len =  f4len( exp4->info->fieldPtr ) ;
 | |
|       exp4->info->functionI =  E4FIELD_NUM_D ;
 | |
|       exp4->info->function =  (S4OPERATOR *)v4functions[E4FIELD_NUM_D].functionPtr ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| EXPR4CALC *S4FUNCTION code4calcCreate( CODE4 *c4, EXPR4 *exp4, const char *name )
 | |
| {
 | |
|    #ifdef S4CLIENT
 | |
|       CONNECTION4 *connection ;
 | |
|       CONNECTION4CALC_CREATE_INFO_IN infoIn ;
 | |
|       DATA4 *data ;
 | |
|       int rc ;
 | |
|    #endif
 | |
|    EXPR4CALC *calcPtr ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( c4 == 0 || exp4 == 0 || name == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90920 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    calcPtr = (EXPR4CALC *)mem4createAlloc( c4, &c4->calcMemory, 5, sizeof(EXPR4CALC), 5, 0 ) ;
 | |
|    if ( calcPtr == 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    #ifdef S4SERVER
 | |
|       l4add( &c4->currentClient->calcList, calcPtr ) ;
 | |
|    #else
 | |
|       l4add( &c4->calcList, calcPtr ) ;
 | |
|    #endif
 | |
|    calcPtr->expr = exp4 ;
 | |
|    u4ncpy( calcPtr->name, name, sizeof(calcPtr->name) ) ;
 | |
|    c4upper( calcPtr->name ) ;
 | |
| 
 | |
|    expr4calcMassage( calcPtr ) ;
 | |
| 
 | |
|    #ifdef S4CLIENT
 | |
|       if ( calcPtr != 0 )   /* need to register calc on server */
 | |
|       {
 | |
|          data = exp4->data ;
 | |
|          connection = data->dataFile->connection ;
 | |
|          rc = connection4assign( connection, CON4CALC_CREATE, data4clientId( data ), data4serverId( data ) ) ;
 | |
|          if ( rc < 0 )
 | |
|             return 0 ;
 | |
|          memset( &infoIn, 0, sizeof( infoIn ) ) ;
 | |
|          u4ncpy( infoIn.calcName, name, sizeof( calcPtr->name ) ) ;
 | |
|          connection4addData( connection, &infoIn, sizeof( infoIn ), 0 ) ;
 | |
|          connection4addData( connection, exp4->source, strlen( exp4->source ) + 1, 0 ) ;
 | |
|          connection4send( connection ) ;
 | |
|          rc = connection4receive( connection ) ;
 | |
|          if ( rc < 0 )
 | |
|             return 0 ;
 | |
| 
 | |
|          rc = connection4status( connection ) ;
 | |
|          if ( rc < 0 )
 | |
|          {
 | |
|             connection4error( connection, c4, rc, E90920 ) ;
 | |
|             return 0 ;
 | |
|          }
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return calcPtr ;
 | |
| }
 | |
| 
 | |
| EXPR4CALC *S4FUNCTION expr4calcLookup( CODE4 *c4, const char *name, const unsigned int nameLenIn )
 | |
| {
 | |
|    EXPR4CALC *calcOn ;
 | |
|    char buf[sizeof(calcOn->name)] ;
 | |
|    unsigned int nameLen ;
 | |
| 
 | |
|    nameLen = nameLenIn ;
 | |
| 
 | |
|    if ( nameLen >= sizeof(calcOn->name) )
 | |
|       nameLen = sizeof(calcOn->name)-1 ;
 | |
|    u4ncpy( buf, name, nameLen+1 ) ;
 | |
|    c4upper( buf ) ;
 | |
|    for( calcOn = 0 ;; )
 | |
|    {
 | |
|       #ifdef S4SERVER
 | |
|          calcOn = (EXPR4CALC *)l4next( &c4->currentClient->calcList, calcOn ) ;
 | |
|       #else
 | |
|          calcOn = (EXPR4CALC *)l4next( &c4->calcList, calcOn ) ;
 | |
|       #endif
 | |
|       if ( calcOn == 0 )
 | |
|          return 0 ;
 | |
|       if ( strcmp( calcOn->name, buf) == 0 )
 | |
|          return calcOn ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| void S4FUNCTION expr4calcResultPos( EXPR4CALC *calcPtr, const int newResultPos )
 | |
| {
 | |
|    E4INFO *info ;
 | |
|    int i, offset = newResultPos - calcPtr->curResultPos ;
 | |
|    if ( offset == 0 )
 | |
|       return ;
 | |
| 
 | |
|    calcPtr->curResultPos = newResultPos ;
 | |
| 
 | |
|    info = calcPtr->expr->info ;
 | |
|    for( i = calcPtr->expr->infoN; --i >= 0; )
 | |
|       info[i].resultPos += offset ;
 | |
| }
 | |
| 
 | |
| #ifdef S4WINTEL
 | |
| /* Expression source must be updated to refect the fact that a calculation had a name change */
 | |
| /* Caller must ensure names are trimmed in front and back & are upper case */
 | |
| int S4FUNCTION expr4calcNameChange( EXPR4 **exprOn, const char *oldName, const char *newName )
 | |
| {
 | |
|    EXPR4 *newExpr ;
 | |
|    char bufMem[50] ;
 | |
|    char *buf ;
 | |
|    unsigned pos, bufLen ;
 | |
|    int oldNameLen, ptrLen, newNameLen, didAlloc, bufPos, didChange ;
 | |
|    const char *ptr ;
 | |
| 
 | |
|    ptr = expr4source( *exprOn ) ;
 | |
|    oldNameLen = strlen( oldName ) ;
 | |
|    ptrLen = strlen( ptr ) ;
 | |
|    bufLen = sizeof( bufMem ) ;
 | |
|    buf = bufMem ;
 | |
|    didAlloc = bufPos = didChange = 0 ;
 | |
| 
 | |
|    for( pos = 0; ptr[pos]; pos++)
 | |
|    {
 | |
|       buf[bufPos++] = ptr[pos] ;
 | |
|       if( (unsigned)bufPos == bufLen )
 | |
|       {
 | |
|          if( didAlloc )
 | |
|          {
 | |
|             u4allocAgain( (*exprOn)->codeBase, &buf, &bufLen, bufLen+50 ) ;
 | |
|             if( buf == 0 )
 | |
|                return -1 ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             bufLen += 50 ;
 | |
|             buf = (char *) u4allocEr( (*exprOn)->codeBase, bufLen + 50 ) ;
 | |
|             if( buf == 0 )
 | |
|                return -1 ;
 | |
|             memcpy( buf, bufMem, sizeof(bufMem) ) ;
 | |
|             didAlloc = 1 ;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       if( ((unsigned) ptrLen - pos) < (unsigned) oldNameLen )  continue ;
 | |
|       if( memicmp( (void *)(ptr+pos), (void *)oldName, oldNameLen ) != 0 )  continue ;
 | |
|       if( u4nameChar( ptr[pos+oldNameLen] )  )  continue ;
 | |
|       if( pos > 0 )
 | |
|          if( u4nameChar(ptr[pos-1]) )  continue ;
 | |
| 
 | |
|       didChange = 1 ;
 | |
|       newNameLen = strlen(newName) ;
 | |
|       if( bufLen <= (unsigned) (bufPos + newNameLen) )
 | |
|       {
 | |
|          if( didAlloc )
 | |
|          {
 | |
|             u4allocAgain( (*exprOn)->codeBase, &buf, &bufLen, bufLen+ newNameLen + 50 ) ;
 | |
|             if( buf == 0 )
 | |
|                return -1 ;
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             bufLen += newNameLen + 50 ;
 | |
|             buf = (char *)u4allocEr( (*exprOn)->codeBase, bufLen ) ;
 | |
|             if( buf == 0 )
 | |
|                return -1 ;
 | |
|             memcpy( buf, bufMem, sizeof(bufMem) ) ;
 | |
|             didAlloc = 1 ;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       memcpy( buf+(--bufPos), newName, newNameLen ) ;
 | |
|       bufPos += newNameLen ;
 | |
|       pos += oldNameLen-1 ;
 | |
|    }
 | |
| 
 | |
|    if( didChange )
 | |
|    {
 | |
|       buf[bufPos] = 0 ;
 | |
|       newExpr = expr4parseLow( (*exprOn)->data, buf, 0 ) ;
 | |
|       if( newExpr )
 | |
|       {
 | |
|          expr4free( *exprOn ) ;
 | |
|          *exprOn = newExpr ;
 | |
|       }
 | |
|       if( didAlloc )
 | |
|          u4free( buf ) ;
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    return 1 ;
 | |
| }
 | |
| #endif  /* S4WINTEL */
 |