campo-sirio/cb5/r4total.c
alex a0f5e0898b This commit was generated by cvs2svn to compensate for changes in r975,
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
1995-02-06 15:33:45 +00:00

666 lines
15 KiB
C
Executable File

/* r4total.c (c)Copyright Sequiter Software Inc., 1991-1994. All rights reserved. */
#include "d4all.h"
#include <math.h>
/* resets the totals values */
void S4FUNCTION total4value_reset( TOTAL4 *t4 )
{
t4->low = 1.7 * pow(10.0, 308.0);
t4->high = -1.7 * pow(10.0, 308.0);
t4->count = 0;
t4->total = 0.0;
}
/* frees the TOTAL4 related memory, then deletes the calculation used to
create the total */
void S4FUNCTION total4free( TOTAL4 *total )
{
if( total->last_reset_value )
{
u4free( total->last_reset_value );
total->last_reset_value = NULL;
}
if( total->reset_expression )
{
expr4free( total->reset_expression );
total->reset_expression = NULL;
}
if( total->last_add_value )
{
u4free( total->last_add_value );
total->last_add_value = NULL;
}
if( total->add_condition )
{
expr4free( total->add_condition );
total->add_condition = NULL;
}
expr4calc_delete( total->calc_ptr );
}
/* creates a total */
TOTAL4 * S4FUNCTION total4create( REPORT4 *r4, char *name, char *expr_src, int total_type, char *reset_expr_src )
{
EXPR4 *expr, *rexpr;
TOTAL4 *t4;
if( !r4 )
return NULL;
if( !name || name[0] == '\0' || !expr_src )
{
e4describe( r4->code_base, e4parm, E4_REP_TCREATEVAL, 0, 0 );
return NULL;
}
/* parse the expression */
expr = expr4parse( r4->relate->data, expr_src );
if( !expr )
{
e4describe( r4->code_base, e4total_create, E4_REP_TEXPR, 0, 0 );
return NULL;
}
/* allocate the TOTAL4 structure */
t4 = (TOTAL4 *)mem4create_alloc( r4->code_base, &r4->code_base->total_memory,
5, sizeof(TOTAL4), 5, 0 );
if( !t4 )
{
e4describe( r4->code_base, e4total_create, E4_REP_TMEM, 0, 0 );
expr4free( expr );
return NULL;
}
/* create the calculation based on the expression */
t4->calc_ptr = expr4calc_create( r4->code_base, expr, name );
if( !t4->calc_ptr )
{
e4describe( r4->code_base, e4total_create, E4_REP_TCALC, 0, 0 );
u4free( t4 );
expr4free( expr );
return NULL;
}
/* set the flags and pointers */
t4->calc_ptr->total = t4;
t4->report = r4;
t4->total_type = total_type;
/* set the totals reset expression */
if( reset_expr_src && reset_expr_src[0] != '\0' )
{
rexpr = expr4parse( r4->relate->data, reset_expr_src );
if( !rexpr )
{
e4describe( r4->code_base, e4total_create, E4_REP_TREXPR, 0, 0 );
expr4free( expr );
u4free( t4 );
return NULL;
}
t4->reset_expression = rexpr;
}
l4add( &r4->code_base->total_list, t4 );
total4value_reset( t4 );
return t4;
}
/* This function is used for evaluating look ahead totals, it skips ahead
through the records incrementing the total appropriately until the reset
condition is met */
void total4evaluate_lookahead( PTOTAL4 total )
{
long reccount = 0;
int flag, len, addflag;
char *ptr;
double tvalue;
if( !total->reset_expression && total->donce )
return;
total->donce = 1;
addflag = 1;
/* check the conditional add */
if( total->add_condition )
{
addflag = 0;
if( total->logcon == 0 )
{
len = expr4vary( total->add_condition, &ptr );
if( memcmp( total->last_add_value, ptr, len ) != 0 )
{
memset( total->last_add_value, 0, len+1 );
memcpy( total->last_add_value, ptr, len );
addflag = 1;
}
}
else
{
if( expr4true( total->add_condition ) )
addflag = 1;
}
}
/* increment the total for the current record */
if( addflag == 1 )
{
tvalue = expr4double( total->calc_ptr->expr ) ;
total->total += tvalue ;
total->count += 1 ;
if ( tvalue < total->low )
total->low = tvalue ;
if( tvalue > total->high )
total->high = tvalue ;
}
/* start going through the records */
flag = 1;
while( flag )
{
if( relate4skip( total->report->relate, 1L ) != 0 )
{
reccount++;
break;
}
reccount++;
/* if this total has a reset expression */
if( total->reset_expression )
{
len = expr4vary( total->reset_expression, &ptr );
/* if the reset condition is not met */
if( memcmp( ptr, total->last_reset_value, len ) == 0 )
{
addflag = 1;
/* check for a conditional total */
if( total->add_condition )
{
addflag = 0;
if( total->logcon == 0 )
{
len = expr4vary( total->add_condition, &ptr );
if( memcmp( total->last_add_value, ptr, len ) != 0 )
{
memset( total->last_add_value, 0, len+1 );
memcpy( total->last_add_value, ptr, len );
addflag = 1;
}
}
else
{
if( expr4true( total->add_condition ) )
addflag = 1;
}
}
/* increment the total */
if( addflag == 1 )
{
tvalue = expr4double( total->calc_ptr->expr ) ;
total->total += tvalue ;
total->count += 1 ;
if ( tvalue < total->low )
total->low = tvalue ;
if( tvalue > total->high )
total->high = tvalue ;
}
}
else /* if the reset condition is met */
{
flag = 0;
}
}
else /* if no reset condition */
{
addflag = 1;
/* check for a conditional total */
if( total->add_condition )
{
addflag = 0;
if( total->logcon == 0 )
{
len = expr4vary( total->add_condition, &ptr );
if( memcmp( total->last_add_value, ptr, len ) != 0 )
{
memset( total->last_add_value, 0, len+1 );
memcpy( total->last_add_value, ptr, len );
addflag = 1;
}
}
else
{
if( expr4true( total->add_condition ) )
addflag = 1;
}
}
/* increment the total for the current record */
if( addflag == 1 )
{
tvalue = expr4double( total->calc_ptr->expr ) ;
total->total += tvalue ;
total->count += 1 ;
if ( tvalue < total->low )
total->low = tvalue ;
if( tvalue > total->high )
total->high = tvalue ;
}
}
}
/* skip back the appropriate number of records */
relate4skip( total->report->relate, (long)(-1 * reccount) );
}
/* updates the totals internals */
void total4value_update( TOTAL4 *total )
{
double tvalue;
int len, flag = 1;
char *ptr;
int addflag;
/* check for a reset on the total */
if( total->reset_expression )
{
len = expr4vary( total->reset_expression, &ptr );
if( (flag = memcmp(total->last_reset_value, ptr, len)) != 0 )
{
memset( total->last_reset_value, 0, len+1 );
memcpy( total->last_reset_value, ptr, len );
total->low = 1.7 * pow( 10,308 ) ;
total->high = -1.7 * pow( 10,308 ) ;
total->total = 0.0 ;
total->count = 0;
}
}
/* for non-lookahead totals */
if( !total->lookahead )
{
addflag = 1;
/* check for conditional total */
if( total->add_condition )
{
addflag = 0;
if( total->logcon == 0 )
{
len = expr4vary( total->add_condition, &ptr );
if( memcmp( total->last_add_value, ptr, len ) != 0 )
{
memset( total->last_add_value, 0, len+1 );
memcpy( total->last_add_value, ptr, len );
addflag = 1;
}
}
else
{
if( expr4true( total->add_condition ) )
addflag = 1;
}
}
/* increment the total */
if( addflag )
{
tvalue = expr4double( total->calc_ptr->expr ) ;
total->total += tvalue ;
total->count += 1 ;
if( tvalue < total->low )
total->low = tvalue ;
if( tvalue > total->high )
total->high = tvalue ;
}
}
/* evaluate the lookahead */
if( total->lookahead && flag != 0 )
{
total4evaluate_lookahead( total );
}
}
/* returns a pointer to the TOTAL4 with the given name */
TOTAL4 * S4FUNCTION total4lookup( REPORT4 *report, char *name )
{
TOTAL4 *total_on ;
if( !report )
return NULL;
if( !name || name[0] == '\0' )
{
e4describe( report->code_base, e4parm, E4_REP_TLKP, 0, 0 );
return NULL;
}
total_on = (TOTAL4 *) l4first( &report->code_base->total_list );
while(total_on)
{
if ( strcmp( name, total_on->calc_ptr->name ) == 0 )
return total_on ;
total_on = (TOTAL4 *) l4next( &report->code_base->total_list,total_on);
}
return NULL ;
}
/* this function is used when checking whether objects are dependant on a
certain total or calculation, also in deleting any dependant objects.
If the function is being used to check for dependancies (delflag = 0) it
simply returns 1 at the first dependant object found. If delflag = 1 any
dependant objects are delted */
int report4checkObjExpr( POBJ4 obj, int delflag )
{
EXPR4CALC *calc_on;
POBJ4 obj_on, obj_next;
EXPR4 *expr;
CODE4 *cb;
int rc;
cb = obj->area->report->code_base;
obj_on = (POBJ4)l4first( &obj->contained );
while( obj_on )
{
obj_next = (POBJ4)l4next( &obj->contained, obj_on );
rc = report4checkObjExpr( obj_on, delflag );
if( rc == 1 )
return rc;
obj_on = obj_next;
}
switch( obj->obj_type_num )
{
case obj4type_expr:
expr = expr4parse( obj->area->report->relate->data, expr4source((EXPR4 *)obj->data) );
if( expr )
{
expr4free( expr );
}
else
{
if( delflag )
obj4delete( obj );
else
return 1;
}
break;
case obj4type_total:
rc = 0;
calc_on = (EXPR4CALC *)l4first( &cb->calc_list );
while( calc_on )
{
if( calc_on == ((PTOTAL4)obj->data)->calc_ptr )
{
rc = 1;
calc_on = NULL;
}
else
calc_on = (EXPR4CALC *)l4next( &cb->calc_list, calc_on );
}
if( rc == 0 )
{
if( delflag )
{
obj->data = NULL;
obj4free( obj );
}
else
return 1;
}
break;
case obj4type_calc:
rc = 0;
calc_on = (EXPR4CALC *)l4first( &cb->calc_list );
while( calc_on )
{
if( calc_on == (EXPR4CALC *)obj->data )
{
rc = 1;
calc_on = NULL;
}
else
calc_on = (EXPR4CALC *)l4next( &cb->calc_list, calc_on );
}
if( rc == 0 )
{
if( delflag )
obj4delete( obj );
else
return 1;
}
break;
}
return 0;
}
/* USED to delete a calc/total from the report */
int S4FUNCTION report4deleteCalc( PREPORT4 report, EXPR4CALC S4PTR *del_calc )
{
POBJ4 obj_on, obj_next;
EXPR4 *expr;
LIST4 temp_calc_list;
CODE4 *code_base;
PGROUP4 group_on;
PAREA4 area_on;
EXPR4CALC *calc_on, *calc_next;
int calc_transfered = 1, expr_error, rc = 0;
if( report == NULL || del_calc == NULL )
{
return -1;
}
code_base = report->code_base;
/* separate the calculations so that a temporary list contains all
calculations dependant on the calculation to be deleted */
memcpy( &temp_calc_list, &code_base->calc_list, sizeof(temp_calc_list) );
memset( &code_base->calc_list, 0, sizeof(code_base->calc_list) );
if( l4seek( &temp_calc_list, del_calc ) != 0 )
l4remove( &temp_calc_list, del_calc );
expr_error = code_base->expr_error;
code_base->expr_error = 0;
while( calc_transfered )
{
calc_transfered = 0;
calc_on = (EXPR4CALC *)l4first( &temp_calc_list );
while( calc_on )
{
calc_next = (EXPR4CALC *)l4next( &temp_calc_list, calc_on );
expr = expr4parse( calc_on->expr->data, expr4source(calc_on->expr) );
if( expr )
{
expr4free( expr );
l4remove( &temp_calc_list, calc_on );
l4add( &code_base->calc_list, calc_on );
calc_transfered = 1;
}
calc_on = calc_next;
}
}
l4add( &code_base->calc_list, del_calc );
expr4calc_delete( del_calc );
calc_on = (EXPR4CALC *)l4pop( &temp_calc_list );
while( calc_on )
{
l4add( &code_base->calc_list, calc_on ) ;
expr4calc_delete( calc_on ) ;
calc_on = (EXPR4CALC *)l4pop( &temp_calc_list );
}
/* Now check on all the objects in the report */
/* start with the page header and footer */
group_on = report->page_header_footer;
if( group_on )
{
area_on = (PAREA4)l4first( &group_on->header_areas );
while( area_on )
{
obj_on = (POBJ4)l4first( &area_on->objects );
while( obj_on )
{
obj_next = (POBJ4)l4next( &area_on->objects, obj_on );
rc = report4checkObjExpr( obj_on, 1 );
if( rc == 1 )
obj_on = NULL;
else
obj_on = obj_next;
}
if( rc == 1 )
area_on = NULL;
else
area_on = (PAREA4)l4next( &group_on->header_areas, area_on );
}
area_on = (PAREA4)l4first( &group_on->footer_areas );
while( area_on )
{
obj_on = (POBJ4)l4first( &area_on->objects );
while( obj_on )
{
obj_next = (POBJ4)l4next( &area_on->objects, obj_on );
rc = report4checkObjExpr( obj_on, 1 );
if( rc == 1 )
obj_on = NULL;
else
obj_on = obj_next;
}
if( rc == 1 )
area_on = NULL;
else
area_on = (PAREA4)l4next( &group_on->footer_areas, area_on );
}
}
group_on = (PGROUP4)l4first( &report->groups );
if( rc == 1 )
group_on = NULL;
while( group_on )
{
area_on = (PAREA4)l4first( &group_on->header_areas );
while( area_on )
{
obj_on = (POBJ4)l4first( &area_on->objects );
while( obj_on )
{
obj_next = (POBJ4)l4next( &area_on->objects, obj_on );
rc = report4checkObjExpr( obj_on, 1 );
if( rc == 1 )
obj_on = NULL;
else
obj_on = obj_next;
}
if( rc == 1 )
area_on = NULL;
else
area_on = (PAREA4)l4next( &group_on->header_areas, area_on );
}
area_on = (PAREA4)l4first( &group_on->footer_areas );
while( area_on )
{
obj_on = (POBJ4)l4first( &area_on->objects );
while( obj_on )
{
obj_next = (POBJ4)l4next( &area_on->objects, obj_on );
rc = report4checkObjExpr( obj_on, 1 );
if( rc == 1 )
obj_on = NULL;
else
obj_on = obj_next;
}
if( rc == 1 )
area_on = NULL;
else
area_on = (PAREA4)l4next( &group_on->footer_areas, area_on );
}
if( rc == 1 )
group_on = NULL;
else
group_on = (PGROUP4)l4next( &report->groups, group_on );
}
report->code_base->expr_error = expr_error;
return 0;
}
/* SEE THE CODEREPORTER MANUAL */
int S4FUNCTION total4addCondition( PTOTAL4 total, char *add_condition_src, int logcon )
{
EXPR4 *expr;
if( !total || !add_condition_src || logcon < 0 )
return -1;
if( total->report == NULL )
return -1;
expr = expr4parse( total->report->relate->data, add_condition_src );
if( expr )
{
if( logcon && expr4type(expr) != r4log )
return -1;
if( total->add_condition )
expr4free( total->add_condition );
total->add_condition = expr;
if( total->last_add_value )
{
u4free( total->last_add_value );
total->last_add_value = NULL;
}
total->logcon = logcon;
return 0;
}
else
e4set( total->report->code_base, 0 );
return -1;
}