📄 sflsymb.c
字号:
/* ----------------------------------------------------------------<Prolog>-
Name: sflsymb.c
Title: Symbol-table functions
Package: Standard Function Library (SFL)
Written: 1993/12/27 iMatix SFL project team <sfl@imatix.com>
Revised: 2000/01/19
Copyright: Copyright (c) 1996-2000 iMatix Corporation
License: This is free software; you can redistribute it and/or modify
it under the terms of the SFL License Agreement as provided
in the file LICENSE.TXT. This software is distributed in
the hope that it will be useful, but without any warranty.
------------------------------------------------------------------</Prolog>-*/
#include "prelude.h" /* Universal header file */
#include "sflstr.h" /* String functions */
#include "sflconv.h" /* Conversion functions */
#include "sfllist.h" /* Linked-list functions */
#include "sflmem.h" /* Memory allocation functions */
#include "sflprint.h" /* snprintf functions */
#include "sflsymb.h" /* Prototypes for functions */
static int sym_sort_by_name (const void *sym1, const void *sym2);
/* ---------------------------------------------------------------------[<]-
Function: sym_create_table_
Synopsis: Creates a new symbol table. Use the sym_create_table macro
to call this function! Returns a SYMTAB pointer which you must use in
all future references to the symbol table. The symbol table is
maintained in memory until the program ends or you use sym_delete_table()
to delete it. Returns null if there was not enough memory to create the
symbol table.
---------------------------------------------------------------------[>]-*/
SYMTAB *
sym_create_table_ (
const char *filename, /* Name of source file making call */
size_t lineno) /* Line number in calling source */
{
SYMTAB
*table; /* Pointer to created table */
int
hash_index; /* Index into hash bucket */
/* Allocate by going directly to mem_alloc_ function */
table = mem_alloc_ (NULL, sizeof (SYMTAB), filename, lineno);
if (table)
{
table-> symbols = NULL; /* No symbols attached yet */
table-> size = 0;
for (hash_index = 0; hash_index < SYM_HASH_SIZE; hash_index++)
table-> hash [hash_index] = NULL;
}
return (table);
}
/* ---------------------------------------------------------------------[<]-
Function: sym_delete_table
Synopsis: Deletes the given symbol table. First frees any memory space
used by the table and attached symbols, including the user data block
if that is not null. If the table argument is NULL, does nothing.
---------------------------------------------------------------------[>]-*/
void
sym_delete_table (
SYMTAB *table) /* Symbol table to delete */
{
SYMBOL
*symbol, /* Pointer to symbol */
*next = NULL; /* and to next symbol in list */
if (!table)
return; /* Do nothing if argument is null */
for (symbol = table-> symbols; symbol; symbol = next)
{
next = symbol-> next; /* Keep track of next in list */
mem_free (symbol-> value); /* Free value if used */
mem_free (symbol); /* Finally free symbol and name */
}
mem_free (table); /* Now free the table */
}
/* ---------------------------------------------------------------------[<]-
Function: sym_empty_table
Synopsis: Empties the given symbol table, by deleting all symbols. You
can then add new symbols. If the table argument is NULL, does nothing.
---------------------------------------------------------------------[>]-*/
void
sym_empty_table (
SYMTAB *table) /* Symbol table to empty */
{
SYMBOL
*symbol, /* Pointer to symbol */
*next = NULL; /* and to next symbol in list */
int
hash_index; /* Index into hash bucket */
if (!table)
return; /* Do nothing if argument is null */
for (symbol = table-> symbols; symbol; symbol = next)
{
next = symbol-> next; /* Keep track of next in list */
mem_free (symbol-> value); /* Free value if used */
mem_free (symbol); /* Finally free symbol and name */
}
table-> symbols = NULL; /* No symbols attached yet */
table-> size = 0;
for (hash_index = 0; hash_index < SYM_HASH_SIZE; hash_index++)
table-> hash [hash_index] = NULL;
}
/* ---------------------------------------------------------------------[<]-
Function: sym_merge_tables
Synopsis: Imports the contents of one symbol table into another. Will
overwrite symbols with the same name. Returns the number of symbols
imported. If there is a lack of available memory, will stop importing,
and return negative the number of symbols imported so far.
---------------------------------------------------------------------[>]-*/
int
sym_merge_tables (
SYMTAB *table, /* Symbol table to import into */
const SYMTAB *import) /* Symbol table to import from */
{
SYMBOL
*symbol; /* Next symbol in table */
int
count = 0;
ASSERT (table);
ASSERT (import);
for (symbol = import-> symbols; symbol; symbol = symbol-> next)
{
if (sym_assume_symbol (table, symbol-> name, symbol-> value) == NULL)
{
return (-(count)); /* Failed => negative value returned*/
}
count++;
}
return (count); /* Success => postive value returned*/
}
/* ---------------------------------------------------------------------[<]-
Function: sym_lookup_symbol
Synopsis: Searches for a symbol, by name, in the specified symbol table.
Returns a pointer to the symbol if found, or NULL if not found. If more
than one symbol with the same name exists, finds the latest entry.
---------------------------------------------------------------------[>]-*/
SYMBOL *
sym_lookup_symbol (
const SYMTAB *table, /* Symbol table to search */
const char *name) /* Symbol name to search for */
{
SYMBOL
*symbol; /* Search through hash bucket list */
ASSERT (table);
for (symbol = table-> hash [sym_hash (name)];
symbol;
symbol = symbol-> h_next)
{
if (streq (symbol-> name, name))
return (symbol);
}
return (NULL);
}
/* ---------------------------------------------------------------------[<]-
Function: sym_create_symbol_
Synopsis: Creates a new symbol in the specified table. Use the
sym_create_symbol macro to call this function! Returns a SYMBOL
pointer to the created symbol, or NULL if there was not enough memory to
create the symbol. Initialises the symbol name and value to the values
supplied. Sets symbol data to NULL. You can set this yourself if you
need to, after calling this function. Use mem_alloc() or mem_strdup()
to assign values to the data block, otherwise you may cause problems when
you delete the symbol or symbol table, since these functions free these
fields. You can create several symbols with the same name; the
last-defined is always placed before older instances and will be found
first by sym_lookup_symbol().
Examples:
SYMTAB
*symbol_table;
SYMBOL
*new_symbol;
symbol_table = sym_create_table ();
ASSERT (symbol_table);
new_symbol = sym_create_symbol (symbol_table, "This name", "This value");
if (new_symbol)
{
new_symbol-> data = mem_alloc (sizeof (my_block));
memcpy (new_symbol-> data, my_block);
}
---------------------------------------------------------------------[>]-*/
SYMBOL *
sym_create_symbol_ (
SYMTAB *table, /* Symbol table to insert into */
const char *name, /* Name of symbol to create */
const char *value, /* Value of symbol to create */
const char *filename, /* Name of source file making call */
size_t lineno) /* Line number in calling source */
{
SYMBOL
*symbol; /* Allocated symbol */
int
hash; /* Hash bucket no. for symbol */
ASSERT (table);
symbol = mem_alloc_ (NULL, sizeof (*symbol) + strlen (name) + 1,
filename, lineno);
if (symbol)
{
/* Set the symbol pointers and fields */
hash = sym_hash (name);
symbol-> next = table-> symbols;
symbol-> prev = NULL;
symbol-> h_next = table-> hash [hash];
symbol-> h_prev = NULL;
symbol-> name = (char *) symbol + sizeof (*symbol);
symbol-> value = mem_strdup (value);
symbol-> data = NULL;
symbol-> hash = (byte) hash;
strcpy (symbol-> name, name);
if (table-> symbols)
table-> symbols-> prev = symbol;
table-> symbols = symbol;
if (table-> hash [hash])
table-> hash [hash]-> h_prev = symbol;
table-> hash [hash] = symbol;
table-> size++;
}
return (symbol);
}
/* ---------------------------------------------------------------------[<]-
Function: sym_assume_symbol_
Synopsis: Searches for a symbol, by name, in the specified symbol table.
If the symbol does not exist, creates the symbol as specified. Returns
a SYMBOL pointer to the existing or new symbol, or NULL if a new symbol
could not be created. The lookup and creation follow the same rules as
sym_lookup_symbol() and sym_create_symbol(). The symbol's value is set
to the supplied value in all cases.
Do not call this function directly; pass through the sym_assume_symbol
macro.
---------------------------------------------------------------------[>]-*/
SYMBOL *
sym_assume_symbol_ (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -