Mercurial > hg > early-roguelike
diff urogue/dictutil.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | c4b12d2d1dcd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/dictutil.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,438 @@ +/* + 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 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 ( trace > 3 ) { + fprintf( ft , "\ndict_load_block allocates %lx bytes at location %p\n" , + dt_entry->size , ptr ); + } /* endif */ + } else { + ptr = block; + if ( 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 ( 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 ( 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 trace (global) > 0 , signal an error +** If severity > 0 , abort +***********/ + +void signal_error( char *header , char *message , int severity ) +{ + FILE *fpe; + + if ( 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(); +}