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
		
			
				
	
	
		
			678 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			678 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* m4file.c   (c)Copyright Sequiter Software Inc., 1990-1994.  All rights reserved.  */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifndef S4UNIX
 | |
| #ifdef __TURBOC__
 | |
| #pragma hdrstop
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #ifndef S4MEMO_OFF
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| /* ndx/clipper versions have no free chain--do not lock memo file */
 | |
| #ifndef N4OTHER
 | |
| /* the lock is forced since a memo file lock only lasts if the .dbf file is locked */
 | |
| int S4FUNCTION memo4file_lock( MEMO4FILE *f4memo )
 | |
| {
 | |
|   int rc, old_attempts ;
 | |
| 
 | |
|   if ( f4memo->file_lock == 1 )
 | |
|     return 0 ;
 | |
| 
 | |
|   if ( f4memo->file.hand == -1 )
 | |
|     return -1 ;
 | |
| 
 | |
|   old_attempts = f4memo->file.code_base->lock_attempts ;
 | |
|   f4memo->file.code_base->lock_attempts = -1 ;
 | |
| 
 | |
| #ifdef S4MDX
 | |
|   rc = file4lock( &f4memo->file, L4LOCK_POS - 1L, 2L ) ;
 | |
| #endif
 | |
| 
 | |
| #ifdef S4FOX
 | |
|   rc = file4lock( &f4memo->file, L4LOCK_POS, 1L ) ;
 | |
| #endif
 | |
| 
 | |
|   f4memo->file.code_base->lock_attempts = old_attempts ;
 | |
|   if ( rc == 0 )
 | |
|     f4memo->file_lock = 1 ;
 | |
| #ifndef S4OPTIMIZE_OFF
 | |
|   file4refresh( &f4memo->file ) ;   /* make sure all up to date */
 | |
| #endif
 | |
|   return rc ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION memo4file_unlock( MEMO4FILE *f4memo )
 | |
| {
 | |
|   int rc ;
 | |
| 
 | |
|   if ( f4memo->file_lock == 0 )
 | |
|     return 0 ;
 | |
| #ifdef S4MDX
 | |
|   rc = file4unlock( &f4memo->file, L4LOCK_POS - 1L, 2L ) ;
 | |
| #endif
 | |
| #ifdef S4FOX
 | |
|   rc = file4unlock( &f4memo->file, L4LOCK_POS, 1L ) ;
 | |
| #endif
 | |
|   if ( rc == 0 )
 | |
|     f4memo->file_lock = 0 ;
 | |
|   return rc ;
 | |
| }
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| int memo4file_open( MEMO4FILE *f4memo, DATA4 *d4, char *name )
 | |
| {
 | |
|   MEMO4HEADER  header ;
 | |
|   int rc ;
 | |
| 
 | |
|   f4memo->data = d4 ;
 | |
| 
 | |
|   if ( file4open( &f4memo->file, d4->code_base, name, 1 ) )
 | |
|     return -1 ;
 | |
| 
 | |
| #ifndef S4OPTIMIZE_OFF
 | |
|   file4optimize( &f4memo->file, d4->code_base->optimize, OPT4OTHER ) ;
 | |
| #endif
 | |
| 
 | |
|   if ( (rc = file4read_all(&f4memo->file, 0L, &header, sizeof(header))) < 0 )
 | |
|     return -1 ;
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
|   header.next_block = x4reverse_long( (void *)&header.next_block ) ;
 | |
| #ifndef S4MNDX
 | |
| #ifndef S4MFOX
 | |
|   header.x102 = 0x201 ;
 | |
| #endif
 | |
|   header.block_size = x4reverse_short( (void *)&header.block_size ) ;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef S4MFOX
 | |
|   f4memo->block_size = x4reverse_short( (void *)&header.block_size ) ;
 | |
| #else
 | |
| #ifdef S4MNDX
 | |
|   f4memo->block_size = MEMO4SIZE ;
 | |
| #else
 | |
|   f4memo->block_size = header.block_size ;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|   return rc ;
 | |
| }
 | |
| 
 | |
| #ifdef S4MFOX
 | |
| /* offset is # bytes from start of memo that reading should begin, read_max is
 | |
|    the maximum possible that can be read (limited to an unsigned int, so is
 | |
|    16-bit/32-bit compiler dependent.
 | |
|    */
 | |
| int memo4file_read_part( MEMO4FILE *f4memo, long memo_id, char **ptr_ptr, unsigned *len_ptr, unsigned long offset, unsigned read_max )
 | |
| {
 | |
|   unsigned long pos, avail ;
 | |
|   MEMO4BLOCK memo_block ;
 | |
| 
 | |
|   if ( memo_id <= 0L )
 | |
|   {
 | |
|     *len_ptr = 0 ;
 | |
|     return 0 ;
 | |
|   }
 | |
| 
 | |
|   pos = memo_id * f4memo->block_size ;
 | |
| 
 | |
|   if ( file4read_all( &f4memo->file, pos, &memo_block, sizeof( MEMO4BLOCK ) ) < 0)
 | |
|     return -1 ;
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
| #ifdef S4MFOX
 | |
|   memo_block.type = x4reverse_long( (void *)&memo_block.type ) ;
 | |
| #else
 | |
|   memo_block.start_pos = x4reverse_short( (void *)&memo_block.start_pos ) ;
 | |
| #endif
 | |
|   memo_block.num_chars = x4reverse_long( (void *)&memo_block.num_chars ) ;
 | |
| #endif
 | |
| 
 | |
|   memo_block.num_chars = x4reverse_long( (void *)&memo_block.num_chars ) ;
 | |
| 
 | |
|   avail = memo_block.num_chars - offset ;
 | |
|   if ( avail > (unsigned long)read_max )
 | |
|     avail = read_max ;
 | |
| 
 | |
|   if ( avail > (unsigned long)*len_ptr )
 | |
|   {
 | |
|     if ( *len_ptr > 0 )
 | |
|       u4free( *ptr_ptr ) ;
 | |
|     *ptr_ptr = (char *)u4alloc_er( f4memo->file.code_base, memo_block.num_chars + 1 ) ;
 | |
|     if ( *ptr_ptr == 0 )
 | |
|       return e4memory ;
 | |
|   }
 | |
| 
 | |
|   *len_ptr = (unsigned)avail ;
 | |
| 
 | |
|   return (int)file4read_all( &f4memo->file, offset + pos + (long)(2*sizeof(S4LONG)), *ptr_ptr, *len_ptr ) ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int memo4file_read( MEMO4FILE *f4memo, long memo_id, char **ptr_ptr, unsigned *len_ptr )
 | |
| {
 | |
| #ifdef S4MFOX
 | |
|   return memo4file_read_part( f4memo, memo_id, ptr_ptr, len_ptr, 0L, UINT_MAX ) ;
 | |
| #else
 | |
|   long  pos ;
 | |
| #ifdef S4MNDX
 | |
|   long amt_read, read_max, len_read ;
 | |
|   char *t_ptr ;
 | |
| #else
 | |
|   MEMO4BLOCK  memo_block ;
 | |
|   unsigned final_len ;
 | |
| #endif
 | |
| 
 | |
|   if ( memo_id <= 0L )
 | |
|   {
 | |
|     *len_ptr = 0 ;
 | |
|     return 0 ;
 | |
|   }
 | |
| 
 | |
|   pos = memo_id * f4memo->block_size ;
 | |
| 
 | |
| #ifdef S4MNDX
 | |
|   amt_read = 0 ;
 | |
|   read_max = *len_ptr ;
 | |
| 
 | |
|   for(;;)
 | |
|   {
 | |
|     if ( MEMO4SIZE > read_max )  /* must increase the memo buffer size */
 | |
|     {
 | |
|       t_ptr = (char *)u4alloc_er( f4memo->file.code_base, amt_read + MEMO4SIZE + 1 ) ;
 | |
|       if ( t_ptr == 0 )
 | |
|         return e4memory ;
 | |
|       if ( *len_ptr > 0 )
 | |
|       {
 | |
|         memcpy( t_ptr, *ptr_ptr, *len_ptr ) ;
 | |
|         u4free( *ptr_ptr ) ;
 | |
|       }
 | |
|       *ptr_ptr = t_ptr ;
 | |
|       *len_ptr = (unsigned)( amt_read + MEMO4SIZE + 1 ) ;
 | |
|       read_max = MEMO4SIZE ;
 | |
|     }
 | |
| 
 | |
|     len_read = file4read( &f4memo->file, pos + amt_read, *ptr_ptr + amt_read, read_max ) ;
 | |
|     if ( len_read <= 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|     for ( ; len_read > 0 ; amt_read++, len_read-- )
 | |
|       if ( (*ptr_ptr)[amt_read] == 0x1A ) /* if done */
 | |
|       {
 | |
|         if ( amt_read > 0 )
 | |
|         {
 | |
|           t_ptr = (char *)u4alloc_free( f4memo->file.code_base, amt_read + 1 ) ;
 | |
|           if ( t_ptr == 0 )
 | |
|           {
 | |
|             /* this will result in a correct return, but extra */
 | |
|             /* space is still allocated at end of *ptr_ptr */
 | |
|             *ptr_ptr[amt_read] = 0 ;
 | |
|             *len_ptr = (unsigned)amt_read ;
 | |
|             return 0 ;
 | |
|           }
 | |
|           memcpy( t_ptr, *ptr_ptr, (int)amt_read ) ;
 | |
|           t_ptr[amt_read] = 0 ;
 | |
|         }
 | |
|         else
 | |
|           t_ptr = 0 ;
 | |
| 
 | |
|         u4free( *ptr_ptr ) ;
 | |
|         *ptr_ptr = t_ptr ;
 | |
|         *len_ptr = (unsigned)amt_read ;
 | |
|         return 0 ;
 | |
|       }
 | |
|     read_max = 0 ;
 | |
|   }
 | |
| #else
 | |
|   if ( file4read_all( &f4memo->file, pos, &memo_block, sizeof( MEMO4BLOCK ) ) < 0)
 | |
|     return -1 ;
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
|   memo_block.start_pos = x4reverse_short( (void *)&memo_block.start_pos ) ;
 | |
|   memo_block.num_chars = x4reverse_long( (void *)&memo_block.num_chars ) ;
 | |
| #endif
 | |
| 
 | |
|   if ( memo_block.minus_one != -1 )  /* must be an invalid entry, so return an empty entry */
 | |
|   {
 | |
|     *len_ptr = 0 ;
 | |
|     return 0 ;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if ( memo_block.num_chars >= USHRT_MAX )
 | |
|       return e4( f4memo->file.code_base, e4info, E4_MEMO4FILE_RD ) ;
 | |
| 
 | |
|     final_len = (unsigned)memo_block.num_chars - 2 * ( sizeof(short) ) - ( sizeof(S4LONG) ) ;
 | |
|     if ( final_len > *len_ptr )
 | |
|     {
 | |
|       if ( *len_ptr > 0 )
 | |
|         u4free( *ptr_ptr ) ;
 | |
|       *ptr_ptr = (char *)u4alloc_er( f4memo->file.code_base, final_len + 1 ) ;
 | |
|       if ( *ptr_ptr == 0 )
 | |
|         return e4memory ;
 | |
|     }
 | |
|     *len_ptr = final_len ;
 | |
| 
 | |
|     return file4read_all( &f4memo->file, pos+ memo_block.start_pos, *ptr_ptr, final_len ) ;
 | |
|   }
 | |
| #endif
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #ifdef S4MFOX
 | |
| /* Writes partial data to a memo record.
 | |
|    Usage rules:
 | |
|    Must call this function with an offset == 0 to write 1st part of block
 | |
|    before any additional writing.  In addition, the memo_len must be
 | |
|    accurately set during the first call in order to reserve the correct
 | |
|    amount of memo space ahead of time.  Later calls just fill in data to
 | |
|    the reserved disk space.
 | |
|    len_write is the amount of data to write, offset is the number of
 | |
|    bytes from the beginning of the memo in which to write the data
 | |
|    Secondary calls to this function assume that everything has been
 | |
|    previously set up, and merely performs a file write to the reserved
 | |
|    space.  The space is not checked to see whether or not it actually
 | |
|    is in the bounds specified, so use with care.
 | |
|    */
 | |
| int memo4file_write_part( MEMO4FILE *f4memo, long *memo_id_ptr, char *ptr, long memo_len, long offset, unsigned len_write )
 | |
| {
 | |
|   int str_num_blocks ;
 | |
|   long pos ;
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|   int rc, lock_cond ;
 | |
| #endif
 | |
| #endif
 | |
|   MEMO4BLOCK old_memo_block ;
 | |
|   MEMO4HEADER mh ;
 | |
|   unsigned len_read ;
 | |
|   long block_no ;
 | |
|   unsigned n_entry_blks = 0 ;
 | |
| 
 | |
| 
 | |
| #ifdef S4DEBUG
 | |
|   if ( memo_id_ptr == 0 )
 | |
|     e4severe( e4parm, E4_MEMO4FILE_WR ) ;
 | |
| #endif
 | |
| 
 | |
|   if ( offset == 0 )   /* must do the set-up work */
 | |
|   {
 | |
|     if ( memo_len == 0 )
 | |
|     {
 | |
|       *memo_id_ptr = 0L ;
 | |
|       return 0 ;
 | |
|     }
 | |
| 
 | |
| #ifdef S4DEBUG
 | |
|     if ( f4memo->block_size <= 1 )
 | |
|       e4severe( e4info, E4_INFO_IMS ) ;
 | |
| #endif
 | |
| 
 | |
|     str_num_blocks = (int) ((memo_len + sizeof(MEMO4BLOCK) + f4memo->block_size-1) / f4memo->block_size) ;
 | |
|     if ( *memo_id_ptr <= 0L )
 | |
|       block_no = 0L ;
 | |
|     else
 | |
|     {
 | |
|       block_no = *memo_id_ptr ;
 | |
|       pos = block_no * f4memo->block_size ;
 | |
| 
 | |
|       file4read_all( &f4memo->file, pos, (char *)&old_memo_block, sizeof(old_memo_block) ) ;
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
| #ifdef S4MFOX
 | |
|       old_memo_block.type = x4reverse_long( (void *)&old_memo_block.type ) ;
 | |
| #else
 | |
|       old_memo_block.start_pos = x4reverse_short( (void *)&old_memo_block.start_pos ) ;
 | |
| #endif
 | |
|       old_memo_block.num_chars = x4reverse_long( (void *)&old_memo_block.num_chars ) ;
 | |
| #endif
 | |
| 
 | |
|       old_memo_block.num_chars = x4reverse_long( (void *)&old_memo_block.num_chars ) ;
 | |
|       n_entry_blks = (unsigned) ((old_memo_block.num_chars + f4memo->block_size-1)/ f4memo->block_size ) ;
 | |
|     }
 | |
|     if ( n_entry_blks >= ((unsigned)str_num_blocks) && block_no )  /* write to existing position */
 | |
|       *memo_id_ptr = block_no ;
 | |
|     else  /* read in header record */
 | |
|     {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|       lock_cond = f4memo->data->memo_file.file_lock ;
 | |
|       rc = memo4file_lock( &f4memo->data->memo_file ) ;
 | |
|       if ( rc )
 | |
|         return rc ;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|       len_read = file4read( &f4memo->file, 0, &mh, sizeof( mh ) ) ;
 | |
| #ifdef S4BYTE_SWAP
 | |
|       mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
|       mh.block_size = x4reverse_short( (void *)&mh.block_size ) ;
 | |
| #endif
 | |
| 
 | |
|       if ( f4memo->data->code_base->error_code < 0 )
 | |
|       {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|         if ( !lock_cond )
 | |
|           memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
|         return -1 ;
 | |
|       }
 | |
| 
 | |
|       if ( len_read != sizeof( mh ) )
 | |
|       {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|         if ( !lock_cond )
 | |
|           memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
|         return file4read_error( &f4memo->file ) ;
 | |
|       }
 | |
| 
 | |
|       *memo_id_ptr = x4reverse_long( (void *)&mh.next_block ) ;
 | |
|       mh.next_block = *memo_id_ptr + str_num_blocks ;
 | |
|       mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
|       mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
|       mh.block_size = x4reverse_short( (void *)&mh.block_size ) ;
 | |
| #endif
 | |
| 
 | |
|       file4write( &f4memo->file, 0, &mh, sizeof( mh ) ) ;
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|       if ( !lock_cond )
 | |
|         memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
|     }
 | |
|     if ( memo4file_dump( f4memo, *memo_id_ptr, ptr, len_write ) < 0 )
 | |
|       return -1 ;
 | |
|   }
 | |
|   else
 | |
|     return file4write( &f4memo->file, *memo_id_ptr * f4memo->block_size + offset, ptr, len_write ) ;
 | |
| 
 | |
|   return 0 ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int memo4file_write( MEMO4FILE *f4memo, long *memo_id_ptr, char *ptr, unsigned ptr_len )
 | |
| {
 | |
| #ifdef S4MFOX
 | |
|   return memo4file_write_part( f4memo, memo_id_ptr, ptr, ptr_len, 0L, ptr_len ) ;
 | |
| #else
 | |
|   int str_num_blocks ;
 | |
|   long pos ;
 | |
| #ifndef S4MDX
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|   int rc, lock_cond ;
 | |
| #endif
 | |
| #endif
 | |
| #endif
 | |
| #ifdef S4MNDX
 | |
|   MEMO4HEADER mh ;
 | |
|   long len_read ;
 | |
|   char buf[MEMO4SIZE] ;
 | |
|   int read_size, i ;
 | |
| #else
 | |
|   MEMO4BLOCK old_memo_block ;
 | |
|   MEMO4CHAIN_ENTRY new_entry, cur, prev ;
 | |
|   int  str_written ;
 | |
|   long prev_prev_entry, prev_prev_num ;
 | |
|   long file_len, extra_len ;
 | |
| #endif
 | |
| 
 | |
| #ifdef S4DEBUG
 | |
|   if ( memo_id_ptr == 0 )
 | |
|     e4severe( e4parm, E4_MEMO4FILE_WR ) ;
 | |
| #endif
 | |
| 
 | |
| #ifdef S4MNDX
 | |
|   if ( ptr_len == 0 )
 | |
|   {
 | |
|     *memo_id_ptr = 0L ;
 | |
|     return 0 ;
 | |
|   }
 | |
| 
 | |
|   str_num_blocks = (ptr_len + f4memo->block_size-1) / f4memo->block_size ;
 | |
| 
 | |
|   if ( *memo_id_ptr <= 0L )
 | |
|     *memo_id_ptr = 0L ;
 | |
|   else    /* read in old record to see if new entry can fit */
 | |
|   {
 | |
|     read_size = 0 ;
 | |
|     pos = *memo_id_ptr * f4memo->block_size ;
 | |
| 
 | |
|     do
 | |
|     {
 | |
|       read_size += MEMO4SIZE ;
 | |
| 
 | |
|       len_read = file4read( &f4memo->file, pos, buf, MEMO4SIZE ) ;
 | |
|       if ( len_read <= 0 )
 | |
|         return file4read_error( &f4memo->file ) ;
 | |
| 
 | |
|       for ( i=0 ; ((unsigned) i) < len_read ; i++ )
 | |
|         if ( buf[i] == (char)0x1A )  break ;
 | |
| 
 | |
| #ifdef S4DEBUG
 | |
|       if ( buf[i] != (char)0x1A && len_read != MEMO4SIZE )
 | |
|         return e4( f4memo->file.code_base, e4info, E4_INFO_CMF ) ;
 | |
| #endif
 | |
| 
 | |
|       pos += MEMO4SIZE ;
 | |
|     } while ( i >= MEMO4SIZE && buf[i] != (char) 0x1A ) ;  /* Continue if Esc is not located */
 | |
| 
 | |
|     if ( ((unsigned)read_size) <= ptr_len )   /* there is not room */
 | |
|       *memo_id_ptr = 0 ;
 | |
|   }
 | |
| 
 | |
|   if ( *memo_id_ptr == 0 )   /* add entry at eof */
 | |
|   {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|     lock_cond = f4memo->data->memo_file.file_lock ;
 | |
|     rc = memo4file_lock( &f4memo->data->memo_file ) ;
 | |
|     if ( rc )
 | |
|       return rc ;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|     len_read = file4read( &f4memo->file, 0, &mh, sizeof( mh ) ) ;
 | |
| #ifdef S4BYTE_SWAP
 | |
|     mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
| #endif
 | |
|     if ( f4memo->data->code_base->error_code < 0 )
 | |
|     {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|       if ( !lock_cond )
 | |
|         memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
|       return -1 ;
 | |
|     }
 | |
| 
 | |
|     if ( len_read != sizeof( mh ) )
 | |
|     {
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|       if ( !lock_cond )
 | |
|         memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
|       return file4read_error( &f4memo->file ) ;
 | |
|     }
 | |
| 
 | |
|     *memo_id_ptr = mh.next_block ;
 | |
|     mh.next_block = *memo_id_ptr + str_num_blocks ;
 | |
| #ifdef S4BYTE_SWAP
 | |
|     mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
| #endif
 | |
| 
 | |
|     file4write( &f4memo->file, 0, &mh, sizeof( mh ) ) ;
 | |
| 
 | |
| #ifndef S4SINGLE
 | |
| #ifndef N4OTHER
 | |
|     if ( !lock_cond )
 | |
|       memo4file_unlock( &f4memo->data->memo_file ) ;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef S4BYTE_SWAP
 | |
|     mh.next_block = x4reverse_long( (void *)&mh.next_block ) ;
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| 
 | |
|   if ( memo4file_dump( f4memo, *memo_id_ptr, ptr, ptr_len ) < 0 )
 | |
|     return -1 ;
 | |
| 
 | |
|   return 0 ;
 | |
| #else
 | |
|   /* S4MMDX */
 | |
|   memset( (void *)&new_entry, 0, sizeof(new_entry) ) ;
 | |
|   new_entry.block_no = *memo_id_ptr ;
 | |
| 
 | |
|   str_written = 0 ;
 | |
|   if ( ptr_len == 0 )
 | |
|   {
 | |
|     str_written = 1 ;
 | |
|     *memo_id_ptr = 0 ;
 | |
|   }
 | |
| 
 | |
|   /* Initialize information about the old memo entry */
 | |
|   if ( new_entry.block_no <= 0L )
 | |
|   {
 | |
|     if ( str_written )
 | |
|     {
 | |
|       *memo_id_ptr = 0L ;
 | |
|       return 0 ;
 | |
|     }
 | |
|     new_entry.num = 0 ;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     pos = new_entry.block_no * f4memo->block_size ;
 | |
| 
 | |
|     file4read_all( &f4memo->file, pos, (char *)&old_memo_block, sizeof(old_memo_block) ) ;
 | |
| #ifdef S4BYTE_SWAP
 | |
|     old_memo_block.start_pos = x4reverse_short( (void *)&old_memo_block.start_pos ) ;
 | |
|     old_memo_block.num_chars = x4reverse_long( (void *)&old_memo_block.num_chars ) ;
 | |
| #endif
 | |
| 
 | |
|     new_entry.num = ((unsigned)old_memo_block.num_chars + f4memo->block_size-1)/ f4memo->block_size ;
 | |
|   }
 | |
| 
 | |
|   str_num_blocks = (ptr_len+2*(sizeof(short))+(sizeof(S4LONG))+ f4memo->block_size-1) / f4memo->block_size ;
 | |
| 
 | |
|   if ( new_entry.num >= str_num_blocks  &&  !str_written )
 | |
|   {
 | |
|     *memo_id_ptr = new_entry.block_no + new_entry.num - str_num_blocks ;
 | |
|     if ( memo4file_dump( f4memo, *memo_id_ptr, ptr, ptr_len ) < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|     str_written = 1 ;
 | |
|     if ( new_entry.num == str_num_blocks )
 | |
|       return 0 ;
 | |
| 
 | |
|     new_entry.num -= str_num_blocks ;
 | |
|   }
 | |
| 
 | |
|   /* Initialize 'chain' */
 | |
|   memset( (void *)&cur, 0, sizeof(cur) ) ;
 | |
|   memset( (void *)&prev, 0, sizeof(prev) ) ;
 | |
| 
 | |
|   for(;;)
 | |
|   {
 | |
|     if ( f4memo->data->code_base->error_code < 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|     memo4file_chain_flush( f4memo, &prev ) ;
 | |
|     prev_prev_entry = prev.block_no ;
 | |
|     prev_prev_num = prev.num ;
 | |
| 
 | |
|     memcpy( (void *)&prev, (void *)&cur, sizeof(prev) ) ;
 | |
| 
 | |
|     if ( new_entry.block_no > 0  &&  prev.next > new_entry.block_no )
 | |
|     {
 | |
|       /* See if the new entry fits in here */
 | |
|       memcpy( (void *)&cur, (void *)&new_entry, sizeof(cur) ) ;
 | |
|       new_entry.block_no = 0 ;
 | |
|       cur.next  = prev.next ;
 | |
|       prev.next = cur.block_no ;
 | |
|       cur.to_disk = prev.to_disk = 1 ;
 | |
|     }
 | |
|     else
 | |
|       memo4file_chain_skip( f4memo, &cur ) ;
 | |
| 
 | |
|     /* See if the entries can be combined. */
 | |
|     if ( prev.block_no + prev.num == cur.block_no && prev.num )
 | |
|     {
 | |
|       /* 'cur' becomes the combined groups. */
 | |
|       prev.to_disk = 0 ;
 | |
|       cur.to_disk  = 1 ;
 | |
| 
 | |
|       cur.block_no = prev.block_no ;
 | |
|       if ( cur.num >= 0 )
 | |
|         cur.num  += prev.num ;
 | |
|       prev.block_no = prev_prev_entry ;
 | |
|       prev.num = prev_prev_num ;
 | |
|     }
 | |
| 
 | |
|     if ( str_written )
 | |
|     {
 | |
|       if ( new_entry.block_no == 0 )
 | |
|       {
 | |
|         memo4file_chain_flush( f4memo, &prev ) ;
 | |
|         memo4file_chain_flush( f4memo, &cur ) ;
 | |
|         return 0 ;
 | |
|       }
 | |
|     }
 | |
|     else  /* 'str' is not yet written, try the current entry */
 | |
|     {
 | |
|       if ( cur.next == -1 )  /* End of file */
 | |
|         cur.num = str_num_blocks ;
 | |
| 
 | |
|       if ( cur.num >= str_num_blocks )
 | |
|       {
 | |
|         cur.num -= str_num_blocks ;
 | |
|         *memo_id_ptr = cur.block_no + cur.num ;
 | |
|         memo4file_dump( f4memo, *memo_id_ptr, ptr, ptr_len ) ;
 | |
|         if ( cur.next == -1 ) /* if end of file */
 | |
|         {
 | |
|           /* For dBASE IV compatibility */
 | |
|           file_len  = file4len( &f4memo->file ) ;
 | |
|           extra_len = f4memo->block_size -  file_len % f4memo->block_size ;
 | |
|           if ( extra_len != f4memo->block_size )
 | |
|             file4len_set( &f4memo->file, file_len+extra_len ) ;
 | |
|         }
 | |
| 
 | |
|         str_written = 1 ;
 | |
| 
 | |
|         if ( cur.num == 0 )
 | |
|         {
 | |
|           if ( cur.next == -1 ) /* End of file */
 | |
|             prev.next = cur.block_no + str_num_blocks ;
 | |
|           else
 | |
|             prev.next = cur.next ;
 | |
|           prev.to_disk = 1 ;
 | |
|           cur.to_disk = 0 ;
 | |
|         }
 | |
|         else
 | |
|           cur.to_disk = 1 ;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| #endif
 | |
| #endif
 | |
| }
 | |
| #endif
 |