8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 17:23:03 +01:00
firebird-mirror/src/gpre/hsh.cpp

276 lines
5.9 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
//____________________________________________________________
//
2001-05-23 15:26:42 +02:00
// PROGRAM: C preprocessor
// MODULE: hsh.cpp
// DESCRIPTION: Hash table and symbol manager
//
2001-05-23 15:26:42 +02:00
// The contents of this file are subject to the Interbase Public
// License Version 1.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy
// of the License at http://www.Inprise.com/IPL.html
//
2001-05-23 15:26:42 +02:00
// Software distributed under the License is distributed on an
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
// or implied. See the License for the specific language governing
// rights and limitations under the License.
//
2001-05-23 15:26:42 +02:00
// The Original Code was created by Inprise Corporation
// and its predecessors. Portions created by Inprise Corporation are
// Copyright (C) Inprise Corporation.
//
2001-05-23 15:26:42 +02:00
// All Rights Reserved.
// Contributor(s): ______________________________________.
// TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
//
2001-05-23 15:26:42 +02:00
//
//____________________________________________________________
//
//
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../gpre/gpre.h"
#include "../gpre/hsh_proto.h"
#include "../gpre/gpre_proto.h"
#include "../gpre/msc_proto.h"
static int hash(const SCHAR*);
static bool scompare(const SCHAR*, const SCHAR*);
static bool scompare2(const SCHAR*, const SCHAR*);
2001-05-23 15:26:42 +02:00
2003-10-15 00:22:32 +02:00
const int HASH_SIZE = 211;
2001-05-23 15:26:42 +02:00
static gpre_sym* hash_table[HASH_SIZE];
static gpre_sym* key_symbols;
2001-05-23 15:26:42 +02:00
static struct word
{
const char* keyword;
kwwords_t id;
} keywords[] =
{
2001-05-23 15:26:42 +02:00
#include "../gpre/hsh.h"
};
2001-05-23 15:26:42 +02:00
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Release space used by keywords.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
void HSH_fini()
2001-05-23 15:26:42 +02:00
{
2009-06-25 12:44:37 +02:00
while (key_symbols)
{
gpre_sym* symbol = key_symbols;
key_symbols = (gpre_sym*) key_symbols->sym_object;
2001-05-23 15:26:42 +02:00
HSH_remove(symbol);
2008-03-10 09:31:35 +01:00
MSC_free(symbol);
2001-05-23 15:26:42 +02:00
}
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Initialize the hash table. This mostly involves
// inserting all known keywords.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
void HSH_init()
2001-05-23 15:26:42 +02:00
{
//const char *string;
2001-05-23 15:26:42 +02:00
int i = 0;
for (gpre_sym** ptr = hash_table; i < HASH_SIZE; i++)
2001-05-23 15:26:42 +02:00
*ptr++ = NULL;
fflush(stdout);
const word* a_word;
for (i = 0, a_word = keywords; i < FB_NELEM(keywords); i++, a_word++)
{
// Unused code: SYM_LEN is used always.
//for (string = a_word->keyword; *string; string++);
gpre_sym* symbol = (gpre_sym*) MSC_alloc(SYM_LEN);
2001-05-23 15:26:42 +02:00
symbol->sym_type = SYM_keyword;
2003-09-05 12:14:08 +02:00
symbol->sym_string = a_word->keyword;
symbol->sym_keyword = (int) a_word->id;
2001-05-23 15:26:42 +02:00
HSH_insert(symbol);
symbol->sym_object = (gpre_ctx*) key_symbols;
2001-05-23 15:26:42 +02:00
key_symbols = symbol;
}
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Insert a symbol into the hash table.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
void HSH_insert( gpre_sym* symbol)
2001-05-23 15:26:42 +02:00
{
const int h = hash(symbol->sym_string);
2001-05-23 15:26:42 +02:00
2008-01-16 08:15:01 +01:00
for (gpre_sym** next = &hash_table[h]; *next; next = &(*next)->sym_collision)
{
for (const gpre_sym* ptr = *next; ptr; ptr = ptr->sym_homonym)
2008-01-16 08:15:01 +01:00
{
2001-05-23 15:26:42 +02:00
if (ptr == symbol)
return;
2008-01-16 08:15:01 +01:00
}
2001-05-23 15:26:42 +02:00
if (scompare(symbol->sym_string, (*next)->sym_string))
{
// insert in most recently seen order;
// This is important for alias resolution in subqueries.
// BUT insert tokens AFTER keyword!
// In a lookup, keyword should be found first.
// This assumes that KEYWORDS are inserted before any other token.
// No one should be using a keywords as an alias anyway.
2001-05-23 15:26:42 +02:00
2009-06-25 12:44:37 +02:00
if ((*next)->sym_type == SYM_keyword)
{
2001-05-23 15:26:42 +02:00
symbol->sym_homonym = (*next)->sym_homonym;
symbol->sym_collision = NULL;
(*next)->sym_homonym = symbol;
}
2009-06-25 12:44:37 +02:00
else
{
2001-05-23 15:26:42 +02:00
symbol->sym_homonym = *next;
symbol->sym_collision = (*next)->sym_collision;
(*next)->sym_collision = NULL;
*next = symbol;
}
return;
}
}
symbol->sym_collision = hash_table[h];
hash_table[h] = symbol;
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Perform a string lookup against hash table.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
gpre_sym* HSH_lookup(const SCHAR* string)
2001-05-23 15:26:42 +02:00
{
for (gpre_sym* symbol = hash_table[hash(string)]; symbol; symbol = symbol->sym_collision)
{
2008-12-05 02:20:14 +01:00
if (scompare(string, symbol->sym_string))
return symbol;
}
2001-05-23 15:26:42 +02:00
return NULL;
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Perform a string lookup against hash table.
// Calls scompare2 which performs case insensitive
// compare.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
gpre_sym* HSH_lookup2(const SCHAR* string)
2001-05-23 15:26:42 +02:00
{
for (gpre_sym* symbol = hash_table[hash(string)]; symbol; symbol = symbol->sym_collision)
{
2008-12-05 02:20:14 +01:00
if (scompare2(string, symbol->sym_string))
return symbol;
}
2001-05-23 15:26:42 +02:00
return NULL;
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Remove a symbol from the hash table.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
void HSH_remove( gpre_sym* symbol)
2001-05-23 15:26:42 +02:00
{
const int h = hash(symbol->sym_string);
2001-05-23 15:26:42 +02:00
for (gpre_sym** next = &hash_table[h]; *next; next = &(*next)->sym_collision)
2008-01-16 08:15:01 +01:00
{
2001-05-23 15:26:42 +02:00
if (symbol == *next)
2008-01-16 08:15:01 +01:00
{
gpre_sym* homonym = symbol->sym_homonym;
2009-06-25 12:44:37 +02:00
if (homonym)
{
2001-05-23 15:26:42 +02:00
homonym->sym_collision = symbol->sym_collision;
*next = homonym;
}
else {
*next = symbol->sym_collision;
2008-01-16 08:15:01 +01:00
}
return;
}
for (gpre_sym** ptr = &(*next)->sym_homonym; *ptr; ptr = &(*ptr)->sym_homonym)
2008-01-16 08:15:01 +01:00
{
2009-06-25 12:44:37 +02:00
if (symbol == *ptr)
{
2008-01-16 08:15:01 +01:00
*ptr = symbol->sym_homonym;
2001-05-23 15:26:42 +02:00
return;
}
2008-01-16 08:15:01 +01:00
}
}
2001-05-23 15:26:42 +02:00
CPR_error("HSH_remove failed");
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Returns the hash function of a string.
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
static int hash(const SCHAR* string)
2001-05-23 15:26:42 +02:00
{
SCHAR c;
SLONG value = 0;
2001-05-23 15:26:42 +02:00
while (c = *string++)
value = (value << 1) + UPPER(c);
return ((value >= 0) ? value : -value) % HASH_SIZE;
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
// case sensitive Compare
//
2001-05-23 15:26:42 +02:00
static bool scompare(const SCHAR* string1, const SCHAR* string2)
2001-05-23 15:26:42 +02:00
{
2008-01-16 08:15:01 +01:00
return strcmp(string1, string2) == 0;
2001-05-23 15:26:42 +02:00
}
//____________________________________________________________
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
// Compare two strings
2008-12-05 02:20:14 +01:00
//
2001-05-23 15:26:42 +02:00
static bool scompare2(const SCHAR* string1, const SCHAR* string2)
2001-05-23 15:26:42 +02:00
{
SCHAR c1;
2001-05-23 15:26:42 +02:00
while (c1 = *string1++)
2008-01-16 08:15:01 +01:00
{
SCHAR c2;
2001-05-23 15:26:42 +02:00
if (!(c2 = *string2++) || (UPPER(c1) != UPPER(c2)))
return false;
2008-01-16 08:15:01 +01:00
}
2008-12-05 02:20:14 +01:00
2001-05-23 15:26:42 +02:00
if (*string2)
return false;
2001-05-23 15:26:42 +02:00
return true;
2001-05-23 15:26:42 +02:00
}