/*
dictutil.c
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
Copyright (C) 1995 Herb Chong
All rights reserved.
See the file LICENSE.TXT for full copyright and licensing information.
*/
/*************************************************************************
** Utilities for Dictionary Maintenence Functions
*************************************************************************/
static char sccsid[] = "%W% %G%";
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if !defined(OS2) && !defined(_WIN32)
#include <unistd.h>
#else
#include <io.h>
#include <fcntl.h>
#endif
#include "dict.h"
#include "dictutil.h"
#include "rogue.h"
int dict_trace;
FILE *ft;
/***********
** Read 'count' characters into 'buffer' at 'offset' in a binary file
** Return 0 on success; -1 on failure;
***********/
int block_read( FILE *fi , char *buffer , size_t count , long offset )
{
if ( fseek(fi,offset,SEEK_SET) == -1 )
return( -1 );
if ( fread(buffer,1,count,fi) != count )
return( -1 );
return( 0 );
}
/***********
** Write 'count' characters from 'buffer' to a binary file.
** Return -1 on failure; 0 on success.
***********/
int block_write( FILE *fo , char *buffer , size_t count )
{
if ( fwrite(buffer,1,count,fo) != count )
return( -1 );
return( 0 );
}
/***********
** Load a dictionary table entry with id TOC_id into memory pointed to by block.
** Update the dictionary TOC.
** If *block=NULL, allocate the block of memory.
** Return 0 on success; -1 on failure.
** Set dt_entry->ptr to where the block is stored.
***********/
void *dict_load_block( DICTIONARY *dict , char *toc_id ,
FILE *fi , void *block )
{ DICT_TOC_ENTRY *dt_entry;
static void *ptr;
int index, ret_code;
index = dict_toc_index( dict , toc_id );
if ( index != -1 ) { /* Found the id */
dt_entry = &(dict->toc[index]);
} else {
signal_error( "dict_load_block: could not find TOC_id" , toc_id , 1 );
return( NULL );
} /* endif */
if ( block == NULL ) {
ptr = malloc( dt_entry->size );
if ( dict_trace > 3 ) {
fprintf( ft , "\ndict_load_block allocates %lx bytes at location %p\n" ,
dt_entry->size , ptr );
} /* endif */
} else {
ptr = block;
if ( dict_trace > 3 ) {
fprintf( ft , "\ndict_load_block uses memory at location %p\n" , ptr );
} /* endif */
} /* endif */
if ( ptr == NULL ) {
signal_error( "dict_load_block: alloc failed " , toc_id , 1 );
return( NULL );
} /* endif */
ret_code = block_read( fi ,
(char*)ptr ,
dt_entry->size ,
dt_entry->offset );
if ( ret_code == -1 )
return( NULL );
if ( dt_entry->checksum !=
compute_checksum( dt_entry->size , (char*)ptr ) ) {
signal_error( "dict_load_block: invalid checksum ", toc_id, 1);
return( NULL );
} /* endif */
dt_entry->ptr = ptr;
if ( dict_trace > 3 ) {
fprintf( ft , "\nLoaded block\nTOC entry: id:%s offset:%lx size:%lx ptr:%p checksum:%lx type:%d\n" ,
dict->toc[index].id , dict->toc[index].offset ,
dict->toc[index].size , dict->toc[index].ptr ,
dict->toc[index].checksum , dict->toc[index].type );
} /* endif */
return( ptr );
}
/***********
** Save a dictionary table entry.
** Update the dictionary TOC entry offset and checksum fields.
** Return 0 on success, -1 on failure.
** Note: It is assumed that the size and pointer fields in TOC entry are
** already up to date; i.e., that they are consistent with the current
** location and size of the block being written. This is essential
** because the table of contents must have already been written
** into the file.
***********/
BOOLEANC dict_save_block( DICTIONARY *dict , char *toc_id , FILE *fo )
{ DICT_TOC_ENTRY *dt_entry;
int index, ret_code;
char *block;
index = dict_toc_index( dict , toc_id );
if ( index == -1 ) {
signal_error( "dict_save_block: id not found " , toc_id , 1 );
return( FALSE );
} /* endif */
dt_entry = &(dict->toc[index]);
block = (char*)(dt_entry->ptr);
if ( block == NULL ) {
signal_error( "dict_save_block: NULL block " , toc_id , 1 );
return( FALSE );
} /* endif */
/* dt_entry->offset = fseek( fo , 0 , SEEK_END ); */
dt_entry->checksum = compute_checksum( dt_entry->size , block );
ret_code = block_write( fo , dt_entry->ptr , dt_entry->size );
if ( ret_code == -1 ) {
signal_error( "dict_save_block: block_write failed " , toc_id , 1 );
return( FALSE );
} /* endif */
if ( dict_trace > 3 ) {
fprintf( ft , "\nStored block\nTOC entry: id:%s offset:%lx size:%lx ptr:%p checksum:%lx type:%d\n" ,
dict->toc[index].id , dict->toc[index].offset ,
dict->toc[index].size , dict->toc[index].ptr ,
dict->toc[index].checksum , dict->toc[index].type );
} /* endif */
return( TRUE );
}
/***********
** Look up and id in the table of contents.
** Return its index (-1 on failure).
***********/
int dict_toc_index( DICTIONARY *dict , char *toc_id )
{ int index;
for ( index = 0 ; index < dict->sig->toc_size ; index++ ) {
if ( strcmp(dict->toc[index].id,toc_id) == 0 )
return( index );
} /* endfor */
return( -1 );
}
/***********
** Compute a block checksum.
** (Currently just returns 0.)
***********/
unsigned long compute_checksum( size_t size , char *block )
{
NOOP(size);
NOOP(block);
return( 0 );
}
/***********
** Create a dictionary paramter entry.
***********/
DICT_PARM_ENTRY *dict_make_parm_entry( char *id , unsigned long value )
{ static DICT_PARM_ENTRY *entry;
entry = (DICT_PARM_ENTRY *) malloc( sizeof(DICT_PARM_ENTRY) );
if ( entry == NULL )
return(NULL);
strncpy( entry->id , id , 13 );
entry->value = value;
return( entry );
}
/***********
** Look up and id in the parameter array.
** Return its index (-1 on failure).
***********/
int dict_parm_index( DICTIONARY *dict , char *parm_id )
{ long index;
for ( index = 0 ; index < dict->sig->nparms ; index++ ) {
if ( strcmp( dict->parm[index].id , parm_id ) == 0 )
return( (int) index );
} /* endfor */
return( -1 );
}
/***********
** Reset table of contents offsets and checksums
** in preparation for dict_save().
***********/
BOOLEANC dict_reset_toc_offsets( DICTIONARY *dict )
{ int i;
long offset;
offset = sizeof(DICT_SIG)
+ dict->sig->toc_size * sizeof(DICT_TOC_ENTRY);
for ( i = 0 ; i < dict->sig->toc_size ; i++ ) {
dict->toc[i].offset = offset;
offset += dict->toc[i].size;
dict->toc[i].checksum =
compute_checksum( dict->toc[i].size , dict->toc[i].ptr );
} /* endfor */
return( TRUE );
}
/***********
** Load the names of the dictionary parameters.
** 14 parms
***********/
BOOLEANC dict_set_parm_ids( DICTIONARY *dict )
{
if ( dict==NULL || dict->sig == NULL ) {
signal_error( "dict_set_parm_ids: Allocate dict and signature first." , "" , 0 );
return( FALSE );
}
dict->sig->nparms = 14;
strcpy( dict->parm[0].id , "FLAGS_______" );
strcpy( dict->parm[1].id , "ENTRY_COUNT_" );
strcpy( dict->parm[2].id , "ARRAY_SIZE__" );
strcpy( dict->parm[3].id , "ARRAY_USED__" );
strcpy( dict->parm[4].id , "ARR_GROW_CT_" );
strcpy( dict->parm[5].id , "STRING_MAX__" );
strcpy( dict->parm[6].id , "STR_GROW_CT_" );
strcpy( dict->parm[7].id , "LONG_CHAIN__" );
strcpy( dict->parm[8].id , "ALLOW_CHAIN_" );
strcpy( dict->parm[9].id , "HASH_TAB_SIZ" );
strcpy( dict->parm[10].id , "HASH_MASK___" );
strcpy( dict->parm[11].id , "HASH_GROW_CT" );
strcpy( dict->parm[12].id , "CHECK_VALUE_" );
strcpy( dict->parm[13].id , "SCAN_STR_IX_" );
return( TRUE );
}
/***********
** Set the dictionary parm structure from the values in the dict structure.
** 14 parms
***********/
BOOLEANC dict_set_parm_values( DICTIONARY *dict )
{ int index;
if ( (index=dict_parm_index(dict,"FLAGS_______")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->flags;
if ( (index=dict_parm_index(dict,"ENTRY_COUNT_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->entry_count;
if ( (index=dict_parm_index(dict,"ARRAY_SIZE__")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->array_size;
if ( (index=dict_parm_index(dict,"ARRAY_USED__")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->array_used;
if ( (index=dict_parm_index(dict,"ARR_GROW_CT_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->array_growth_count;
if ( (index=dict_parm_index(dict,"STRING_MAX__")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->string_max;
if ( (index=dict_parm_index(dict,"STR_GROW_CT_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->string_growth_count;
if ( (index=dict_parm_index(dict,"LONG_CHAIN__")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->longest_chain_length;
if ( (index=dict_parm_index(dict,"ALLOW_CHAIN_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->allowable_chain_length;
if ( (index=dict_parm_index(dict,"HASH_TAB_SIZ")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->table_size;
if ( (index=dict_parm_index(dict,"HASH_MASK___")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->hash_mask;
if ( (index=dict_parm_index(dict,"HASH_GROW_CT")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->hash_growth_count;
if ( (index=dict_parm_index(dict,"CHECK_VALUE_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->check_value;
if ( (index=dict_parm_index(dict,"SCAN_STR_IX_")) == -1 )
return( FALSE );
dict->parm[index].value = (unsigned long)dict->scan_string_index;
return( TRUE );
}
/***********
** Set the values in the dict structure from the dictionary parm structure.
** 14 parms
***********/
BOOLEANC dict_set_parm_variables( DICTIONARY *dict )
{ int index;
if ( (index=dict_parm_index(dict,"FLAGS_______")) == -1 )
return( FALSE );
dict->flags = (unsigned long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"ENTRY_COUNT_")) == -1 )
return( FALSE );
dict->entry_count = (long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"ARRAY_SIZE__")) == -1 )
return( FALSE );
dict->array_size = (long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"ARRAY_USED__")) == -1 )
return( FALSE );
dict->array_used = (long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"ARR_GROW_CT_")) == -1 )
return( FALSE );
dict->array_growth_count = (int)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"STRING_MAX__")) == -1 )
return( FALSE );
dict->string_max = (long)dict->parm[index].value ;
if ( (index=dict_parm_index(dict,"STR_GROW_CT_")) == -1 )
return( FALSE );
dict->string_growth_count = (int)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"LONG_CHAIN__")) == -1 )
return( FALSE );
dict->longest_chain_length = (int)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"ALLOW_CHAIN_")) == -1 )
return( FALSE );
dict->allowable_chain_length = (int)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"HASH_TAB_SIZ")) == -1 )
return( FALSE );
dict->table_size = (long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"HASH_MASK___")) == -1 )
return( FALSE );
dict->hash_mask = (unsigned long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"HASH_GROW_CT")) == -1 )
return( FALSE );
dict->hash_growth_count = (int)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"CHECK_VALUE_")) == -1 )
return( FALSE );
dict->check_value = (unsigned long)dict->parm[index].value;
if ( (index=dict_parm_index(dict,"SCAN_STR_IX_")) == -1 )
return( FALSE );
dict->scan_string_index = (long)dict->parm[index].value;
return( TRUE );
}
/***********
** If dict_trace (global) > 0 , signal an error
** If severity > 0 , abort
***********/
void signal_error( char *header , char *message , int severity )
{
FILE *fpe;
if ( dict_trace > 0 ) {
printf( "%s: %s\n" , header , message );
fpe = fopen( "ERROR.FIL" , "a" );
fprintf( fpe , "\n%s: %s\n" , header , message );
fclose( fpe );
} /* endif */
if ( severity > 0 )
abort();
}