/* Copyright (C) 1995 Bjoern Beutel. */
/* Description. =============================================================*/
/* This module administrates the name and atoms for each symbol. */
/* Includes. ================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <setjmp.h>
#include <glib.h>
#include "basic.h"
#include "pools.h"
#include "values.h"
#include "files.h"
#include "malaga_files.h"
#include "symbols.h"
/* Variables. ===============================================================*/
static struct /* This is the symbol table. */
{
int_t symbol_count; /* Number of symbols in this table. */
symbol_entry_t *symbols; /* The names and atoms of all symbols. */
symbol_t *symbols_by_name; /* All symbols sorted by their names. */
symbol_t *symbols_by_atoms; /* All symbols sorted by their atom lists. */
int_t values_size;
symbol_t *values; /* Contains the lists of atomic symbols. */
int_t strings_size;
char_t *strings; /* Contains the symbol names. */
} symbol_table;
/* Functions. ===============================================================*/
string_t
get_symbol_name( symbol_t symbol )
/* Return the name of SYMBOL. */
{
return symbol_table.strings + symbol_table.symbols[ symbol ].name;
}
/*---------------------------------------------------------------------------*/
value_t
get_atoms( symbol_t symbol )
/* Return the atom list of SYMBOL. */
{
return symbol_table.values + symbol_table.symbols[ symbol ].atoms;
}
/*---------------------------------------------------------------------------*/
symbol_t
find_symbol( string_t name )
/* Find a symbol NAME in the symbol table and return its code.
* If there is no symbol NAME, report an error. */
{
int_t lower, upper, middle, result;
symbol_t symbol;
/* We do a binary search in SYMBOLS_BY_NAME. */
lower = 0;
upper = symbol_table.symbol_count - 1;
while (lower <= upper)
{
middle = (lower + upper) / 2;
symbol = symbol_table.symbols_by_name[ middle ];
result = strcmp_no_case( name, get_symbol_name( symbol ) );
if (result < 0)
upper = middle - 1;
else if (result > 0)
lower = middle + 1;
else
return symbol;
}
complain( "Unknown symbol \"%s\".", name );
}
/*---------------------------------------------------------------------------*/
symbol_t
find_multi_symbol( value_t atoms )
/* Find a symbol by its atoms in the symbol table and return its code.
* If there is no multi-symbol for ATOMS, report an error. */
{
int_t lower, upper, middle, result;
symbol_t symbol;
/* We do a binary search in SYMBOLS_BY_ATOMS. */
lower = 0;
upper = symbol_table.symbol_count - 1;
while (lower <= upper)
{
middle = (lower + upper) / 2;
symbol = symbol_table.symbols_by_atoms[ middle ];
result = compare_atom_lists( atoms, get_atoms( symbol ) );
if (result < 0)
upper = middle - 1;
else if (result > 0)
lower = middle + 1;
else
return symbol;
}
complain( "No multi symbol for this atom list." );
}
/*---------------------------------------------------------------------------*/
int_t
symbol_count( void )
/* Return the number of symbols defined. */
{
return symbol_table.symbol_count;
}
/*---------------------------------------------------------------------------*/
static int
compare_symbols_by_name( const void *symbol1, const void *symbol2 )
/* Return -1 if name( SYMBOL1 ) < name( SYMBOL2 )
* 0 if name( SYMBOL1 ) == name( SYMBOL2 )
* 1 if name( SYMBOL1 ) > name( SYMBOL2 ). */
{
return strcmp_no_case( get_symbol_name( *(symbol_t *) symbol1 ),
get_symbol_name( *(symbol_t *) symbol2 ) );
}
/*---------------------------------------------------------------------------*/
static int
compare_symbols_by_atoms( const void *symbol1, const void *symbol2 )
/* Return -1 if atoms( SYMBOL1 ) < atoms( SYMBOL2 )
* 0 if atoms( SYMBOL1 ) == atoms( SYMBOL2 )
* 1 if atoms( SYMBOL1 ) > atoms( SYMBOL2 ). */
{
return compare_atom_lists( get_atoms( *(symbol_t *) symbol1 ),
get_atoms( *(symbol_t *) symbol2 ) );
}
/*---------------------------------------------------------------------------*/
void
init_symbols( string_t file_name )
/* Initialise this module. Read SYMBOL_TABLE from file FILE_NAME. */
{
FILE *stream;
symbol_header_t header;
int_t i;
stream = open_stream( file_name, "rb" );
read_vector( &header, sizeof( header ), 1, stream, file_name );
check_header( &header.common_header, file_name,
SYMBOL_FILE, MIN_SYMBOL_CODE_VERSION, SYMBOL_CODE_VERSION );
symbol_table.symbol_count = header.symbol_count;
symbol_table.symbols = read_new_vector( sizeof( symbol_entry_t ),
header.symbol_count,
stream, file_name );
symbol_table.values_size = header.values_size;
symbol_table.values = read_new_vector( sizeof( cell_t ), header.values_size,
stream, file_name );
symbol_table.strings_size = header.strings_size;
symbol_table.strings = read_new_vector( sizeof( char_t ),
header.strings_size,
stream, file_name );
close_stream( &stream, file_name );
/* Build a list of all symbols sorted by their names
* and a list of all symbols sorted by their atom lists. */
symbol_table.symbols_by_name = new_vector( sizeof( symbol_t ),
header.symbol_count );
symbol_table.symbols_by_atoms = new_vector( sizeof( symbol_t ),
header.symbol_count );
for (i = 0; i < header.symbol_count; i++)
{
symbol_table.symbols_by_name[i] = i;
symbol_table.symbols_by_atoms[i] = i;
}
qsort( symbol_table.symbols_by_name, header.symbol_count,
sizeof( symbol_t ), compare_symbols_by_name );
qsort( symbol_table.symbols_by_atoms, header.symbol_count,
sizeof( symbol_t ), compare_symbols_by_atoms );
values_get_symbol_name = get_symbol_name;
values_get_atoms = get_atoms;
}
/*---------------------------------------------------------------------------*/
void
terminate_symbols( void )
/* Terminate this module. */
{
free_mem( &symbol_table.symbols );
free_mem( &symbol_table.symbols_by_name );
free_mem( &symbol_table.symbols_by_atoms );
free_mem( &symbol_table.values );
free_mem( &symbol_table.strings );
}
/* End of file. =============================================================*/