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
		
			
				
	
	
		
			1099 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1099 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* r4save_2.c   (c)Copyright Sequiter Software Inc., 1991-1994.  All rights reserved. */
 | |
| #include "d4all.h"
 | |
| 
 | |
| extern int file_version;
 | |
| extern LIST4 name_list;
 | |
| 
 | |
| int save4long( FILE4SEQ_WRITE *seq, long *lval );
 | |
| int save4short( FILE4SEQ_WRITE *seq, short *sval );
 | |
| int ret4long( FILE4SEQ_READ *seq, long *lval );
 | |
| int ret4short( FILE4SEQ_READ *seq, short *sval );
 | |
| 
 | |
| /************************************************************
 | |
|  *
 | |
|  * Function:
 | |
|  *
 | |
|  *  PARAMETERS:
 | |
|  *    DATA4* data - data file
 | |
|  *    char* index_name - name of the index file to be checked for
 | |
|  *    char* index_lookup - buffer used in the function
 | |
|  *    char* current - buffer used in the function
 | |
|  *
 | |
|  *  DESCRIPTION:this function performs the same operation as d4index(), but
 | |
|  *   checks for an index file both with and without path names
 | |
|  *
 | |
|  *  RETURNS: 1 - on finding a matching index file, 0 - on failure
 | |
|  *
 | |
|  *  By: Raymond Cypher
 | |
|  *
 | |
|  *  HISTORY:
 | |
|  *
 | |
|  */
 | |
| 
 | |
| /* this function performs the same operation as d4index(), but checks for an
 | |
|    index file both with and without path names
 | |
|  */
 | |
| int S4FUNCTION r4index_lookup_foo( DATA4 *data, char *index_name,
 | |
|                                    char *index_lookup, char *current )
 | |
| {
 | |
|    INDEX4 *index_on ;
 | |
|    int ttype;
 | |
| 
 | |
| 
 | |
|    if ( data == 0 || index_name == 0 )
 | |
|       #ifdef S4DEBUG
 | |
|          e4severe( e4parm, E4_D4INDEX ) ;
 | |
|       #else
 | |
|          return 0 ;
 | |
|       #endif
 | |
| 
 | |
|    ttype = report4index_type();
 | |
|    u4name_piece( index_lookup, 257, index_name, 1, 0 ) ;
 | |
|    #ifndef S4UNIX
 | |
|       c4upper( index_lookup ) ;
 | |
|    #endif
 | |
| 
 | |
|    if( r4cli == ttype || r4ndx == ttype )
 | |
|    {
 | |
|       if( d4tag( data, index_lookup ) )
 | |
|          return 1;
 | |
|       u4name_piece( index_lookup, 257, index_name, 0, 0 ) ;
 | |
|       if( d4tag( data, index_lookup ) )
 | |
|          return 1;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       index_on = (INDEX4 *)l4first( &data->indexes );
 | |
|       while( index_on )
 | |
|       {
 | |
|          u4name_piece( current, 257, index_on->file.name, 1, 0 ) ;
 | |
|          #ifndef S4UNIX
 | |
|             c4upper( current ) ;
 | |
|          #endif
 | |
|          if ( !strcmp( current, index_lookup ) )    /* check out data->alias? */
 | |
|             return 1;
 | |
|          index_on = (INDEX4 *) l4next( &data->indexes, index_on) ;
 | |
|       }
 | |
| 
 | |
|       u4name_piece( index_lookup, 257, index_name, 0, 0 ) ;
 | |
|       #ifndef S4UNIX
 | |
|          c4upper( index_lookup ) ;
 | |
|       #endif
 | |
| 
 | |
|       index_on = (INDEX4 *)l4first( &data->indexes );
 | |
|       while( index_on )
 | |
|       {
 | |
|          u4name_piece( current, 257, index_on->file.name, 0, 0 ) ;
 | |
|          #ifndef S4UNIX
 | |
|             c4upper( current ) ;
 | |
|          #endif
 | |
|          if ( !strcmp( current, index_lookup ) )    /* check out data->alias? */
 | |
|             return 1;
 | |
|          index_on = (INDEX4 *) l4next( &data->indexes, index_on) ;
 | |
|       }
 | |
| 
 | |
|    }
 | |
| 
 | |
|    return( 0 );
 | |
| }
 | |
| 
 | |
| /* wrapper for above function */
 | |
| int S4FUNCTION r4index_lookup( DATA4 *data, char *index_name )
 | |
| {
 | |
|    char *index_lookup, *current;
 | |
|    int retvalue;
 | |
| 
 | |
|    index_lookup = (char *)u4alloc_free( data->code_base, 258 );
 | |
|    if( !index_lookup )
 | |
|       return 0;
 | |
| 
 | |
|    current = (char*)u4alloc_free( data->code_base, 258 );
 | |
|    if( !current )
 | |
|    {
 | |
|       u4free( index_lookup );
 | |
|       return 0;
 | |
|    }
 | |
| 
 | |
|    retvalue = r4index_lookup_foo( data, index_name, index_lookup, current );
 | |
| 
 | |
|    u4free( index_lookup );
 | |
|    u4free( current );
 | |
|    return retvalue;
 | |
| }
 | |
| 
 | |
| /************************************************************
 | |
|  *
 | |
|  * Function: r4open_data_foo()
 | |
|  *
 | |
|  *  PARAMETERS:
 | |
|  *    char* file_name - full name of the file, potentially including path
 | |
|  *    char* alias - alias to set for the data file
 | |
|  *    RELATE4* relate - the relate associated with the current report
 | |
|  *    CODE4* code_base - CODE4 structure for the app
 | |
|  *    char* fnbuf - a buffer used by the function
 | |
|  *
 | |
|  *  DESCRIPTION: opens a data file, if the file is already open in the relate
 | |
|  *   appropriate aliasing is performed to open the file a second time
 | |
|  *
 | |
|  *  RETURNS: a DATA4 pointer on success, NULL on failure
 | |
|  *
 | |
|  *  By: Raymond Cypher
 | |
|  *
 | |
|  *  HISTORY:
 | |
|  *
 | |
|  */
 | |
| DATA4 *r4open_data_foo( char *file_name, char *alias, RELATE4 *relate, CODE4 *code_base, char *fnbuf )
 | |
| {
 | |
|    DATA4   *old, *nnew;
 | |
|    RELATE4 *relate_on;
 | |
|    char    abuf[11];
 | |
| 
 | |
|    if( !file_name || !alias )
 | |
|       return NULL;
 | |
| 
 | |
|    nnew = old = NULL;
 | |
|    /* if no alias or no relate do a simple d4open() */
 | |
|    if( alias[0] == '\0' || !relate )
 | |
|    {
 | |
|       nnew = d4open( code_base, file_name );
 | |
|       return nnew;
 | |
|    }
 | |
| 
 | |
|    #ifndef S4UNIX
 | |
|       c4upper( file_name );
 | |
|       c4upper( alias );
 | |
|    #endif
 | |
| 
 | |
|    /* check to see if the file is already open */
 | |
|    relate_on = relate;
 | |
|    while( relate_on )
 | |
|    {
 | |
|       strcpy( fnbuf, relate_on->data->file.name );
 | |
|       #ifndef S4UNIX
 | |
|          c4upper( fnbuf );
 | |
|       #endif
 | |
|       strcpy( abuf, d4alias( relate_on->data ) );
 | |
|       #ifndef S4UNIX
 | |
|          c4upper( abuf );
 | |
|       #endif
 | |
|       if( strcmp( fnbuf, file_name ) == 0 && strcmp(abuf, alias) == 0 )
 | |
|          old = relate_on->data;
 | |
| 
 | |
|       relate4next( &relate_on );
 | |
|    }
 | |
| 
 | |
|    /* if the file is not already open do a d4open() and set the alias */
 | |
|    if( old == NULL )
 | |
|    {
 | |
|       nnew = d4open( code_base, file_name );
 | |
|       if( nnew && alias[0] != '\0' )
 | |
|          d4alias_set( nnew, alias );
 | |
|       return nnew;
 | |
|    }
 | |
| 
 | |
|    /* save the existing files alias, reset it to xxxxxxx open the new file,
 | |
|       set the new files alias, then restore the old files alias  */
 | |
|    strcpy( abuf, d4alias(old) );
 | |
|    d4alias_set( old, "XXXXXXXXXX" );
 | |
|    nnew = d4open( code_base, file_name );
 | |
|    if( nnew )
 | |
|       d4alias_set( nnew, alias );
 | |
|    d4alias_set( old, abuf );
 | |
| 
 | |
|    return nnew;
 | |
| 
 | |
| }
 | |
| 
 | |
| /* wrapper for above function */
 | |
| DATA4 *r4open_data( char *file_name, char *alias, RELATE4 *relate, CODE4 *code_base )
 | |
| {
 | |
|    DATA4 *retvalue;
 | |
|    char *fnbuf;
 | |
| 
 | |
|    fnbuf = (char *)u4alloc_free( code_base, 256 );
 | |
|    if( !fnbuf )
 | |
|       return NULL;
 | |
| 
 | |
|    retvalue = r4open_data_foo( file_name, alias, relate, code_base, fnbuf );
 | |
| 
 | |
|    u4free( fnbuf );
 | |
|    return retvalue;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* frees the list of N4CHANGE structures */
 | |
| void report4free_name_list()
 | |
| {
 | |
|    PN4CHANGE nchange;
 | |
| 
 | |
|    while( (nchange = (PN4CHANGE)l4pop( &name_list )) != NULL )
 | |
|    {
 | |
|       if( nchange->old_name )
 | |
|          u4free( nchange->old_name );
 | |
| 
 | |
|       if( nchange->new_name )
 | |
|          u4free( nchange->new_name );
 | |
| 
 | |
|       u4free( nchange );
 | |
|    }
 | |
| }
 | |
| 
 | |
| /* simple memcompare function that first capitalizes the buffers being compared */
 | |
| int r4memicmp_foo( char *str1, char *str2, int len, char *buffer )
 | |
| {
 | |
|    memset( buffer, 0, len + 1 );
 | |
|    memcpy( buffer, str1, len );
 | |
|    #ifndef S4UNIX
 | |
|       c4upper( buffer );
 | |
|       c4upper( str2 );
 | |
|    #endif
 | |
|    return memcmp( str1, str2, len );
 | |
| }
 | |
| 
 | |
| /* wrapper for above function */
 | |
| int r4memicmp( char *str1, char *str2, int len )
 | |
| {
 | |
|    char *buffer;
 | |
|    int retvalue;
 | |
| 
 | |
|    buffer = (char *)u4alloc( len+2 );
 | |
|    if( !buffer )
 | |
|       return 1;
 | |
| 
 | |
|    retvalue = r4memicmp_foo( str1, str2, len, buffer );
 | |
|    u4free( buffer );
 | |
|    return retvalue;
 | |
| }
 | |
| 
 | |
| /************************************************************
 | |
|  *
 | |
|  * Function: report4nchange()
 | |
|  *
 | |
|  *  PARAMETERS:
 | |
|  *    CODE4* c4 - apps code4 struct
 | |
|  *    char** psrc - pointer to a pointer to the source string
 | |
|  *    int can_alloc - flag specifying whether or not to allocate additional
 | |
|  *     memory as needed
 | |
|  *    int s_size - size of the source string
 | |
|  *
 | |
|  *  DESCRIPTION: in CR when opening a report file, if a data or index file
 | |
|  *   cannot be found the user is prompted to enter a new path and/or name.
 | |
|  *   If the name of a data file has changed the name must also be changed in
 | |
|  *   all the expressions within the report.  To do this a list of N4CHANGE
 | |
|  *   structures is maintained.  N4CHANGE simply contains the old and new names
 | |
|  *   for a data file.  This function is passed an expression source and is
 | |
|  *   responsible for swapping the names.
 | |
|  *
 | |
|  *  RETURNS: none
 | |
|  *
 | |
|  *  By: Raymond Cypher
 | |
|  *
 | |
|  *  HISTORY:
 | |
|  *
 | |
|  */
 | |
| void report4nchange( CODE4 *c4, char **psrc, int can_alloc, int s_size )
 | |
| {
 | |
|    char      *orig = NULL, *src = *psrc;
 | |
|    PN4CHANGE nchange;
 | |
|    int       pos, src_pos, orig_len;
 | |
|    int       old_name_len, new_name_len;
 | |
|    unsigned  src_size = s_size;
 | |
| 
 | |
|    if( strlen(src) == 0 )
 | |
|       return;
 | |
| 
 | |
|    /* for ever N4CHANGE struct in the name list */
 | |
|    nchange = (PN4CHANGE)l4first( &name_list );
 | |
|    while( nchange )
 | |
|    {
 | |
|       /* if no names continue */
 | |
|       if( !nchange->new_name || !nchange->old_name )
 | |
|          continue;
 | |
| 
 | |
|       old_name_len = strlen(nchange->old_name);
 | |
| 
 | |
|       /* create a buffer to duplicate the expression source */
 | |
|       orig = (char *)u4alloc_free( c4, strlen(src) + 1 );
 | |
|       if( !orig )
 | |
|          return;
 | |
| 
 | |
|       /* copy the expression source */
 | |
|       src_pos = 0;
 | |
|       strcpy( orig, src );
 | |
|       orig_len = strlen(orig);
 | |
| 
 | |
|       /* run through the copy of the expression source */
 | |
|       for( pos = 0; orig[pos]; pos++ )
 | |
|       {
 | |
|          /* we are copying the duplicated expression source back into the
 | |
|             original buffer, with appropriate insertions */
 | |
|          src[src_pos++] = orig[pos];
 | |
| 
 | |
|          /* if the expression source buffer is too small due to changes
 | |
|             do a re-allocation */
 | |
|          if( src_pos == (int)src_size )
 | |
|          {
 | |
|             if( !can_alloc )
 | |
|             {
 | |
|                u4free( orig );
 | |
|                return;
 | |
|             }
 | |
|             u4alloc_again( c4, &src, &src_size, src_size+50 );
 | |
|             if( !src )
 | |
|                return;
 | |
|          }
 | |
| 
 | |
|          /* if we're at the end of the expression source, continue */
 | |
|          if( (orig_len - pos) < old_name_len )
 | |
|             continue;
 | |
| 
 | |
|          /* is this piece of the expression the current old name */
 | |
|          if( r4memicmp( orig+pos, nchange->old_name, old_name_len ) != 0 )
 | |
|             continue;
 | |
| 
 | |
|          if( u4name_char( orig[pos+old_name_len] ) )
 | |
|             continue;
 | |
| 
 | |
|          if( pos > 0 )
 | |
|             if( u4name_char( orig[pos-1]) )
 | |
|                continue;
 | |
| 
 | |
|          /* insert the new name into the expression source, re-allocating space
 | |
|             if necessary */
 | |
|          new_name_len = strlen( nchange->new_name );
 | |
|          if( (int)src_size <= (pos+new_name_len) )
 | |
|          {
 | |
|             if( !can_alloc )
 | |
|             {
 | |
|                u4free( orig );
 | |
|                return;
 | |
|             }
 | |
| 
 | |
|             u4alloc_again( c4, &src, &src_size, src_size + 50 );
 | |
|             if( !src )
 | |
|             {
 | |
|                u4free( orig );
 | |
|                return;
 | |
|             }
 | |
|          }
 | |
|          memcpy( src+(--src_pos), nchange->new_name, new_name_len );
 | |
|          src_pos += new_name_len;
 | |
|          pos += (old_name_len - 1);
 | |
|       } /* end of loop through copy of expression source */
 | |
| 
 | |
|       /* end the string */
 | |
|       src[src_pos++] = '\0';
 | |
| 
 | |
|       /* next change name */
 | |
|       nchange = (PN4CHANGE)l4next( &name_list, nchange );
 | |
|       /* free the source duplicate buffer */
 | |
|       if( orig )
 | |
|       {
 | |
|          u4free( orig );
 | |
|          orig = NULL;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if( orig )
 | |
|    {
 | |
|       u4free( orig );
 | |
|       orig = NULL;
 | |
|    }
 | |
| 
 | |
|    /* set the pointer to the new source buffer */
 | |
|    *psrc = src;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /************************************************************
 | |
|  *
 | |
|  * Function: relate4retrieve_relate_foo()
 | |
|  *
 | |
|  *  PARAMETERS:
 | |
|  *   FILE4SEQ_READ* seq - sequential read struture for the file i/o
 | |
|  *   int open_files - should the data files for the relate be opened
 | |
|  *   char* spath - path to look for the data files
 | |
|  *   the rest of the parameters are simply character buffers used in the fctn
 | |
|  *
 | |
|  *  DESCRIPTION: retrieves a relation from a file.  Note: this file and the
 | |
|  *   r4save.c source file are compiled directly into the CR executable, as well
 | |
|  *   as into the CodeBase DLL.  As a result certain sections of this code
 | |
|  *   are specific the the executable and call functions in the executable
 | |
|  *
 | |
|  *  RETURNS: a RELATE4 pointer on success, NULL on failure
 | |
|  *
 | |
|  *  By: Raymond Cypher
 | |
|  *
 | |
|  *  HISTORY:
 | |
|  *
 | |
|  */
 | |
| RELATE4 * S4FUNCTION   relate4retrieve_relate_foo( FILE4SEQ_READ *seq, int open_files, char *spath,
 | |
|                           char *dname_buf, char *iname_buf, char *tname_buf,
 | |
|                           char *str_buf, char *master_expr_buf,
 | |
|                           char *slave_expr_buf, char *tempname_buf )
 | |
| {
 | |
|    RELATE4 *relate = NULL, *master = NULL;
 | |
|    DATA4   *data;
 | |
|    TAG4    *tag;
 | |
|    INDEX4  *index;
 | |
|    LIST4   indexes;
 | |
|    CODE4   *c4;
 | |
|    INAME4  *iname, *nname;
 | |
|    EXPR4   *expr;
 | |
|    char alias_buf[11], *cptr;
 | |
|    short match_len, relation_type, sort_type, error_action, n_links, code;
 | |
|    int i, err_code, err_flag, repeat_flag, error_code = 0, iindex, tname_err;
 | |
|    long lExt;
 | |
|    #ifdef S4CR2
 | |
|       PN4CHANGE nchange;
 | |
|       int rc;
 | |
|    #endif
 | |
| 
 | |
|    /* reset the changed name list */
 | |
|    memset( &name_list, 0, sizeof(name_list) );
 | |
| 
 | |
|    c4 = seq->file->code_base;
 | |
| 
 | |
|    /* reset the index name list */
 | |
|    memset( &indexes, 0, sizeof(indexes) );
 | |
|    err_code = err_flag = 0;
 | |
| 
 | |
|    while( 1 )
 | |
|    {
 | |
|       /* get the data file name */
 | |
|       if( retrieve4string( seq, dname_buf, 256 ) < 0 )
 | |
|       {
 | |
|          /* the error codes are used to allow the continued retrieval of
 | |
|             the relation tree, even if a part of it is not retrievable due
 | |
|             to a missing data or index file */
 | |
|          error_code = 1;
 | |
|          goto CLEANUP;
 | |
|       }
 | |
| 
 | |
|       /* get the files alias */
 | |
|       memset( alias_buf, 0, sizeof(alias_buf) );
 | |
|       if( file_version >= 0x24 )
 | |
|       {
 | |
|          if( retrieve4string( seq, alias_buf, sizeof(alias_buf) ) < 0 )
 | |
|          {
 | |
|             error_code = 1;
 | |
|             goto CLEANUP;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       /* retrieve the internal flags of the RELATE4 */
 | |
|       ret4short( seq, &match_len );
 | |
|       ret4short( seq, &relation_type );
 | |
|       ret4short( seq, &sort_type );
 | |
|       ret4short( seq, &error_action );
 | |
| 
 | |
|       /* retrieve the names of the index files and place them in the index list
 | |
|        */
 | |
|       ret4short( seq, &n_links );
 | |
|       for( i = 0; i < n_links; i++ )
 | |
|       {
 | |
|          iname = (INAME4 *)u4alloc_free( c4, sizeof(INAME4) );
 | |
|          if( retrieve4string( seq, iname_buf, 256 ) < 0 )
 | |
|          {
 | |
|             error_code = 1;
 | |
|             goto CLEANUP;
 | |
|          }
 | |
|          iname->index_name = (char *)u4alloc_free( c4, strlen(iname_buf) + 1 );
 | |
|          iname->name_length = strlen(iname_buf) + 1;
 | |
|          #ifdef S4WINDOWS
 | |
|             lstrcpy( iname->index_name, iname_buf );
 | |
|          #else
 | |
|             strcpy( iname->index_name, iname_buf );
 | |
|          #endif
 | |
|          l4add( &indexes, iname );
 | |
|       }
 | |
| 
 | |
|       /* get the tag name */
 | |
|       if( retrieve4string( seq, tname_buf, 256 ) < 0 )
 | |
|       {
 | |
|          error_code = 1;
 | |
|          goto CLEANUP;
 | |
|       }
 | |
| 
 | |
|       /* retrieve the source for the master expression */
 | |
|       if( retrieve4string( seq, master_expr_buf, 1024 ) < 0 )
 | |
|       {
 | |
|          error_code = 1;
 | |
|          goto CLEANUP;
 | |
|       }
 | |
| 
 | |
|       /* check for changed names */
 | |
|       cptr = master_expr_buf;
 | |
|       report4nchange( c4, &cptr, 0, 1024 );
 | |
| 
 | |
|       /* the code indicates where the new relate should fall in the tree with
 | |
|          respect to the last relate.  The code used is the same as the return
 | |
|          values from relate4next() */
 | |
|       ret4short( seq, &code );
 | |
| 
 | |
|       if( !err_flag && !err_code )
 | |
|       {
 | |
|          repeat_flag = 1;
 | |
|          while( repeat_flag )
 | |
|          {
 | |
|             repeat_flag = 0;
 | |
|             /* see if data file is already open */
 | |
|             data = 0;
 | |
|             u4name_piece( str_buf, 256, dname_buf, 0, 0 );
 | |
|             data = d4data( c4, alias_buf );
 | |
|             /* if not already open try to open */
 | |
|             if( !data )
 | |
|             {
 | |
|                /* if not allowed to open, error */
 | |
|                if( !open_files )
 | |
|                {
 | |
|                   e4describe( c4, e4result, E4_RESULT_LCF, dname_buf, (char *)0 );
 | |
|                   err_flag = 1;
 | |
|                }
 | |
| 
 | |
|                /* check for an alternate path */
 | |
|                if( spath && spath[0] != '\0' )
 | |
|                {
 | |
|                   u4name_piece( str_buf, 256, dname_buf, 0, 1 );
 | |
|                   strcpy( tempname_buf, spath );
 | |
|                   strcat( tempname_buf, "\\" );
 | |
|                   strcat( tempname_buf, str_buf );
 | |
|                   /* open the data file */
 | |
|                   data = r4open_data( tempname_buf, alias_buf, master, c4 );
 | |
|                }
 | |
|                else
 | |
|                {
 | |
|                   /* open the data file */
 | |
|                   data = r4open_data( dname_buf, alias_buf, master, c4 );
 | |
|                }
 | |
| 
 | |
|                /* if the open failed */
 | |
|                if( !data )
 | |
|                {
 | |
|                   /* if this is for the CR executable interactively get an
 | |
|                      alternate file name */
 | |
|                   #ifdef S4CR2
 | |
|                   nchange = (PN4CHANGE)u4alloc_free( c4, sizeof(N4CHANGE) );
 | |
|                   if( nchange )
 | |
|                   {
 | |
|                      u4name_piece( str_buf, 256, dname_buf, 0, 0 );
 | |
|                      nchange->old_name = (char *)u4alloc_free( c4, strlen(str_buf)+1 );
 | |
|                      if( nchange->old_name )
 | |
|                      {
 | |
|                         strcpy( nchange->old_name, str_buf );
 | |
|                         rc = AlternateDataFile( dname_buf, 256 );
 | |
|                         if( rc == 0 )
 | |
|                         {
 | |
|                            u4name_piece( str_buf, 256, dname_buf, 0, 0 );
 | |
|                            nchange->new_name = (char *)u4alloc_free(c4,strlen(str_buf)+1 );
 | |
|                            if( nchange->new_name )
 | |
|                            {
 | |
|                               strcpy( nchange->new_name, str_buf );
 | |
|                               l4add( &name_list, nchange );
 | |
|                               repeat_flag  = 1;
 | |
|                            }
 | |
|                            else
 | |
|                            {
 | |
|                               u4free( nchange->old_name );
 | |
|                               u4free( nchange );
 | |
|                               err_flag = 1;
 | |
|                            }
 | |
|                         }
 | |
|                         else
 | |
|                            err_flag = 1;
 | |
|                      }
 | |
|                      else
 | |
|                      {
 | |
|                         u4free( nchange );
 | |
|                         err_flag = 1;
 | |
|                      }
 | |
|                   }
 | |
|                   else
 | |
|                      err_flag = 1;
 | |
|                   #else
 | |
|                   /* if not in the executable report an error */
 | |
|                   if( spath && spath[0] != '\0' )
 | |
|                      e4describe( c4, e4report, E4_REP_DFILE, tempname_buf, (char *)0 );
 | |
|                   else
 | |
|                      e4describe( c4, e4report, E4_REP_DFILE, dname_buf, (char *)0 );
 | |
|                   err_flag = 1;
 | |
|                   #endif
 | |
|                }
 | |
|                e4set( c4, 0 );
 | |
|             }
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       if( !err_flag && !err_code )
 | |
|       {
 | |
|          /* loop through index file names */
 | |
|          iname = (INAME4 *)l4first( &indexes );
 | |
|          while( iname )
 | |
|          {
 | |
|             repeat_flag = 1;
 | |
|             while( repeat_flag )
 | |
|             {
 | |
|                repeat_flag = 0;
 | |
|                index = NULL;
 | |
|                iindex = 0;
 | |
| 
 | |
|                u4name_piece( str_buf, 256, iname->index_name, 0, 0 );
 | |
|                tname_err = c4->tag_name_error;
 | |
|                c4->tag_name_error = 0;
 | |
| 
 | |
|                /* check to see if the index is already open */
 | |
|                iindex = r4index_lookup( data, str_buf );
 | |
|                c4->tag_name_error = tname_err;
 | |
|                e4set( c4, 0 );
 | |
| 
 | |
|                /* if not already open */
 | |
|                if( !iindex )
 | |
|                {
 | |
|                   /* if not allowed to open files report an error */
 | |
|                   if( !open_files )
 | |
|                   {
 | |
|                      e4describe( c4, e4result, E4_RESULT_LCF, iname_buf, (char *)0 );
 | |
|                      err_flag = 1;
 | |
|                   }
 | |
| 
 | |
|                   /* by default this compile switch is defined in r4report.h
 | |
|                      it forces the index file name to have the default extension
 | |
|                      for the compile flag, regardless of the extension saved in
 | |
|                      the report.  IF the user is using a different extension
 | |
|                      he should undefine this switch */
 | |
|                   #ifdef S4DEFAULT_INDEX
 | |
|                   lExt = u4switch();
 | |
|                   if( lExt & 1 )
 | |
|                      u4name_ext( iname->index_name, strlen(iname->index_name)+1, "cdx", 1 );
 | |
|                   else
 | |
|                      if( lExt & 2 )
 | |
|                         u4name_ext( iname->index_name, strlen(iname->index_name)+1, "ntx", 1 );
 | |
|                      else
 | |
|                         if( lExt & 4 )
 | |
|                            u4name_ext( iname->index_name, strlen(iname->index_name)+1, "mdx", 1 );
 | |
|                         else
 | |
|                            if( lExt & 8 )
 | |
|                               u4name_ext( iname->index_name, strlen(iname->index_name)+1, "ndx", 1 );
 | |
|                   #endif
 | |
| 
 | |
|                   /* attempt to open the index file */
 | |
|                   if( spath && spath[0] != '\0' )
 | |
|                   {
 | |
|                      u4name_piece( str_buf, 256, iname->index_name, 0, 1 );
 | |
|                      strcpy( tempname_buf, spath );
 | |
|                      strcat( tempname_buf, "\\" );
 | |
|                      strcat( tempname_buf, str_buf );
 | |
|                      index = i4open( data, tempname_buf );
 | |
|                   }
 | |
|                   else
 | |
|                      index = i4open( data, iname->index_name );
 | |
| 
 | |
|                   /* if open fails */
 | |
|                   if( !index )
 | |
|                   {
 | |
|                      /* if in CR executable prompt for alternate */
 | |
|                      #ifdef S4CR2
 | |
|                      lstrcpy( str_buf, iname->index_name );
 | |
|                      rc = AlternateIndexFile( str_buf, 256 );
 | |
|                      if( rc == 0 )
 | |
|                      {
 | |
|                         repeat_flag = 1;
 | |
|                         u4free( iname->index_name );
 | |
|                         iname->index_name = NULL;
 | |
|                         iname->index_name = (char *)u4alloc( lstrlen(str_buf)+1 );
 | |
|                         if( iname->index_name )
 | |
|                            lstrcpy( iname->index_name, str_buf );
 | |
|                      }
 | |
|                      else
 | |
|                         err_flag = 1;
 | |
|                      #else
 | |
|                      /* report an error */
 | |
|                      if( spath && spath[0] != '\0' )
 | |
|                         e4describe( c4, e4report, E4_REP_IFILE, tempname_buf, (char *)0 );
 | |
|                      else
 | |
|                         e4describe( c4, e4report, E4_REP_IFILE, iname_buf, (char *)0 );
 | |
|                      err_flag = 1;
 | |
|                      #endif
 | |
|                   }
 | |
|                   e4set( c4, 0 );
 | |
|                }
 | |
|             }
 | |
|             iname = (INAME4 *)l4next( &indexes, iname );
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       if( !err_flag && !err_code )
 | |
|       {
 | |
|          tag = NULL;
 | |
| 
 | |
|          /* if this is the first relate do a relate4init() */
 | |
|          if( !relate )
 | |
|          {
 | |
|             master = relate = relate4init( data );
 | |
|             if( !relate )
 | |
|                goto CLEANUP;
 | |
| 
 | |
|             /* set the internal flags */
 | |
|             relate->match_len = match_len;
 | |
|             relate->sort_type = sort_type;
 | |
|             relate->relation_type = relation_type;
 | |
|             relate->error_action = error_action;
 | |
| 
 | |
|             /* if a tag was specified set it */
 | |
|             if( strlen(tname_buf) )
 | |
|             {
 | |
|                repeat_flag = 1;
 | |
|                while( repeat_flag )
 | |
|                {
 | |
|                   repeat_flag = 0;
 | |
|                   tag = NULL;
 | |
|                   tag = d4tag( data, tname_buf );
 | |
|                   if( tag )
 | |
|                   {
 | |
|                      relate->data_tag = tag;
 | |
|                      d4tag_select( data, tag );
 | |
|                   }
 | |
|                   #ifdef S4CR2
 | |
|                   else
 | |
|                   {
 | |
|                      /* if the specified tag is not available and this is the
 | |
|                         .exe prompt for an alternate */
 | |
|                      e4set( c4, 0 );
 | |
|                      rc = AlternateTagName( tname_buf, 256 );
 | |
|                      if( rc == 0 )
 | |
|                         repeat_flag = 1;
 | |
|                   }
 | |
|                   #else
 | |
|                   else
 | |
|                      e4set( c4, 0 );
 | |
|                   #endif
 | |
|                }
 | |
|             }
 | |
|          }
 | |
|          else
 | |
|          {
 | |
|             /* if not the first relate do a create slave */
 | |
|             /* start by getting a tag pointer from the tag name */
 | |
|             if( strlen(tname_buf) )
 | |
|             {
 | |
|                repeat_flag = 1;
 | |
|                while( repeat_flag )
 | |
|                {
 | |
|                   repeat_flag = 0;
 | |
|                   tag = NULL;
 | |
|                   tag = d4tag( data, tname_buf );
 | |
|                   if( !tag )
 | |
|                   #ifdef S4CR2
 | |
|                   {
 | |
|                      e4set( c4, 0 );
 | |
|                      rc = AlternateTagName( tname_buf, 256 );
 | |
|                      if( rc == 0 )
 | |
|                         repeat_flag = 1;
 | |
|                      else
 | |
|                      {
 | |
|                         goto CLEANUP;
 | |
|                      }
 | |
|                   }
 | |
|                   #else
 | |
|                   {
 | |
|                      e4describe( c4, e4report, E4_REP_NOTAG, (char *)tname_buf, 0 );
 | |
|                      e4set( c4, 0 );
 | |
|                      goto CLEANUP;
 | |
|                   }
 | |
|                   #endif
 | |
|                }
 | |
|             }
 | |
| 
 | |
|             /* try to create the slave */
 | |
|             repeat_flag = 1;
 | |
|             while( repeat_flag )
 | |
|             {
 | |
|                repeat_flag = 0;
 | |
|                expr = expr4parse( master->data, master_expr_buf );
 | |
|                if( expr )
 | |
|                {
 | |
|                   expr4free( expr );
 | |
|                   relate = relate4create_slave( master, data, master_expr_buf, tag );
 | |
|                }
 | |
|                #ifdef S4CR2
 | |
|                else
 | |
|                {
 | |
|                   /* if create slave fales prompt for a different master expr */
 | |
|                   e4set( c4, 0 );
 | |
|                   rc = AlternateMasterExpression( master_expr_buf, master, 1024 );
 | |
|                   if( rc == 0 )
 | |
|                      repeat_flag = 1;
 | |
|                   else
 | |
|                      relate = NULL;
 | |
|                }
 | |
|                #else
 | |
|                else
 | |
|                {
 | |
|                   /* report an error */
 | |
|                   e4describe( c4, e4report, E4_REP_NOMEXPR, 0, 0 );
 | |
|                   e4set( c4, 0 );
 | |
|                   relate = NULL;
 | |
|                }
 | |
|                #endif
 | |
|             }
 | |
| 
 | |
|             if( !relate )
 | |
|                goto CLEANUP;
 | |
|             relate->match_len = match_len;
 | |
|             relate->sort_type = sort_type;
 | |
|             relate->relation_type = relation_type;
 | |
|             relate->error_action = error_action;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       /* free the index name list */
 | |
|       iname = (INAME4 *)l4first( &indexes );
 | |
|       while( iname )
 | |
|       {
 | |
|          nname = (INAME4 *)l4next( &indexes, iname );
 | |
|          l4remove( &indexes, iname );
 | |
|          u4free( iname->index_name );
 | |
|          u4free( iname );
 | |
|          iname = nname;
 | |
|       }
 | |
| 
 | |
|       /* if end of relates leave the loop */
 | |
|       if( code == 2 )
 | |
|          break;
 | |
| 
 | |
|       if( err_flag == 0 && err_code > 0 )
 | |
|       {
 | |
|          err_code += code;
 | |
|          if( err_code <= 0 )
 | |
|          {
 | |
|             err_code = 0;
 | |
|             code = 1;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       if( err_flag == 1 )
 | |
|       {
 | |
|          err_flag = 0;
 | |
|          err_code = 1;
 | |
|       }
 | |
| 
 | |
|       if( err_code <= 0 )
 | |
|       {
 | |
|          master = relate;
 | |
|          while( code++ <= 0 )
 | |
|             master = master->master;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /* deal with the sort and query expressions */
 | |
|    memset( master_expr_buf, 0, 1024 );
 | |
|    memset( slave_expr_buf, 0, 1024 );
 | |
|    retrieve4string( seq, master_expr_buf, 1024 );
 | |
|    cptr = master_expr_buf;
 | |
|    report4nchange( c4, &cptr, 0, 1024 );
 | |
|    retrieve4string( seq, slave_expr_buf, 1024 );
 | |
|    cptr = slave_expr_buf;
 | |
|    report4nchange( c4, &cptr, 0, 1024 );
 | |
|    if( master )
 | |
|    {
 | |
|       repeat_flag = 1;
 | |
|       if( strlen( slave_expr_buf) > 0 )
 | |
|       while( repeat_flag )
 | |
|       {
 | |
|          repeat_flag = 0;
 | |
|          expr = expr4parse( master->data, slave_expr_buf );
 | |
|          if( expr )
 | |
|          {
 | |
|             expr4free( expr );
 | |
|             relate4sort_set( master, slave_expr_buf );
 | |
|          }
 | |
|          #ifdef S4CR2
 | |
|          else
 | |
|          {
 | |
|             e4set( c4, 0 );
 | |
|             rc = AlternateSortExpression( slave_expr_buf, master, 1024 );
 | |
|             if( rc == 0 )
 | |
|                repeat_flag = 1;
 | |
|          }
 | |
|          #else
 | |
|          else
 | |
|          {
 | |
|             e4describe( c4, e4report, E4_REP_NOSORT, 0, 0 );
 | |
|             e4set( c4, 0 );
 | |
|          }
 | |
|          #endif
 | |
|       }
 | |
| 
 | |
|       repeat_flag = 1;
 | |
|       if( strlen( master_expr_buf ) > 0 )
 | |
|       while( repeat_flag )
 | |
|       {
 | |
|          repeat_flag = 0;
 | |
|          expr = expr4parse( master->data, master_expr_buf );
 | |
|          if( expr )
 | |
|          {
 | |
|             expr4free( expr );
 | |
|             relate4query_set( master, master_expr_buf );
 | |
|          }
 | |
|          #ifdef S4CR2
 | |
|          else
 | |
|          {
 | |
|             e4set( c4, 0 );
 | |
|             rc = AlternateQueryExpression( master_expr_buf, master, 1024 );
 | |
|             if( rc == 0 )
 | |
|                repeat_flag = 1;
 | |
|          }
 | |
|          #else
 | |
|          else
 | |
|          {
 | |
|             e4describe( c4, e4report, E4_REP_NOQUERY, 0, 0 );
 | |
|             e4set( c4, 0 );
 | |
|          }
 | |
|          #endif
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if( relate )
 | |
|       return( &relate->relation->relate );
 | |
|    else
 | |
|       return NULL;
 | |
| 
 | |
| CLEANUP:
 | |
|    iname = (INAME4 *)l4first( &indexes );
 | |
|    while( iname )
 | |
|    {
 | |
|       nname = (INAME4 *)l4next( &indexes, iname );
 | |
|       l4remove( &indexes, iname );
 | |
|       u4free( iname->index_name );
 | |
|       u4free( iname );
 | |
|       iname = nname;
 | |
|    }
 | |
| 
 | |
|    if( master )
 | |
|    {
 | |
|       relate4free( master, open_files );
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       if( relate )
 | |
|          relate4free( relate, open_files );
 | |
|    }
 | |
| 
 | |
|    if( error_code )
 | |
|    {
 | |
|       e4describe( c4, e4report, E4_REP_RELERR, 0, 0 );
 | |
|    }
 | |
|    return NULL;
 | |
| }
 | |
| 
 | |
| /* wrapper for above function */
 | |
| RELATE4 * S4FUNCTION   relate4retrieve_relate( FILE4SEQ_READ *seq, int open_files, char *spath )
 | |
| {
 | |
|    char *dname_buf = NULL, *iname_buf = NULL, *tname_buf = NULL, *str_buf = NULL;
 | |
|    char *master_expr_buf = NULL, *slave_expr_buf = NULL, *tempname_buf = NULL;
 | |
|    RELATE4 *retvalue = NULL;
 | |
| 
 | |
|    dname_buf = (char *)u4alloc_free( seq->file->code_base, 256 );
 | |
|    iname_buf = (char *)u4alloc_free( seq->file->code_base, 256 );
 | |
|    tname_buf = (char *)u4alloc_free( seq->file->code_base, 256 );
 | |
|    str_buf = (char *)u4alloc_free( seq->file->code_base, 256 );
 | |
|    master_expr_buf = (char *)u4alloc_free( seq->file->code_base, 1024 );
 | |
|    slave_expr_buf = (char *)u4alloc_free( seq->file->code_base, 1024 );
 | |
|    tempname_buf = (char *)u4alloc_free( seq->file->code_base, 512 );
 | |
|    if( !dname_buf || !iname_buf || !tname_buf || !str_buf ||
 | |
|        !master_expr_buf || !slave_expr_buf || !tempname_buf )
 | |
|       goto R4LEAVE;
 | |
| 
 | |
|    retvalue = relate4retrieve_relate_foo( seq, open_files, spath,
 | |
|                  dname_buf, iname_buf, tname_buf, str_buf, master_expr_buf,
 | |
|                  slave_expr_buf, tempname_buf );
 | |
| 
 | |
| R4LEAVE:
 | |
|    if( dname_buf )
 | |
|       u4free( dname_buf );
 | |
|    if( iname_buf )
 | |
|       u4free( iname_buf );
 | |
|    if( tname_buf )
 | |
|       u4free( tname_buf );
 | |
|    if( str_buf )
 | |
|       u4free( str_buf );
 | |
|    if( master_expr_buf )
 | |
|       u4free( master_expr_buf );
 | |
|    if( slave_expr_buf )
 | |
|       u4free( slave_expr_buf );
 | |
|    if( tempname_buf )
 | |
|       u4free( tempname_buf );
 | |
| 
 | |
|    return retvalue;
 | |
| 
 | |
| }
 | |
| 
 | |
| /* see the CodeReporter manual */
 | |
| int S4FUNCTION obj4dataFieldSet( POBJ4 obj, char *fname, char ftype, int flength, int fdec )
 | |
| {
 | |
|    POUT4OBJ oobj;
 | |
|    PREPORT4 report;
 | |
| 
 | |
|    if( !obj )
 | |
|       return -1;
 | |
| 
 | |
|    report = obj->area->report;
 | |
|    obj->field_type = ftype;
 | |
|    obj->field_len = flength;
 | |
|    obj->field_dec = fdec;
 | |
|    if( fname )
 | |
|       u4ncpy( obj->field_name, fname, sizeof(obj->field_name) );
 | |
|    else
 | |
| 
 | |
|    oobj = (POUT4OBJ)l4first( &report->output_objs );
 | |
|    while( oobj )
 | |
|    {
 | |
|       if( oobj->obj == obj )
 | |
|       {
 | |
|          if( fname == NULL || ftype == 0 || flength == 0 )
 | |
|             l4remove( &report->output_objs, oobj );
 | |
|          return 0;
 | |
|       }
 | |
|       oobj = (POUT4OBJ)l4next( &report->output_objs, oobj );
 | |
|    }
 | |
| 
 | |
|    oobj = (POUT4OBJ)u4alloc_free( obj->area->report->code_base, sizeof(OUT4OBJ) );
 | |
|    if( !oobj )
 | |
|       return -1;
 | |
|    oobj->obj = obj;
 | |
|    l4add( &report->output_objs, oobj );
 | |
|    return 0;
 | |
| }
 | |
| 
 | |
| /* see the CodeReporter manual */
 | |
| int S4FUNCTION report4dataFileSet( PREPORT4 report, char *fname )
 | |
| {
 | |
|    if( !report )
 | |
|       return -1;
 | |
| 
 | |
|    if( report->dfile_name )
 | |
|       u4free( report->dfile_name );
 | |
|    report->dfile_name = NULL;
 | |
| 
 | |
|    if( fname == NULL )
 | |
|       return 0;
 | |
| 
 | |
|    report->dfile_name = (char *)u4alloc_er( report->code_base, strlen(fname)+1 );
 | |
|    if( !report->dfile_name )
 | |
|       return -1;
 | |
| 
 | |
|    u4ncpy( report->dfile_name, fname, strlen(fname)+1 );
 | |
|    return 0;
 | |
| }
 | |
| 
 | |
| /* see the CodeReporter manual */
 | |
| int S4FUNCTION report4dataGroup( PREPORT4 report, PGROUP4 group )
 | |
| {
 | |
|    if( !report )
 | |
|       return -1;
 | |
| 
 | |
|    report->output_group = group;
 | |
|    return 0;
 | |
| }
 |