8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 06:03:02 +01:00
firebird-mirror/src/dudley/hsh.cpp
2004-12-24 08:52:39 +00:00

469 lines
11 KiB
C++

/*
* PROGRAM: JRD Data Definition Language
* MODULE: hsh.cpp
* DESCRIPTION: Hash table and symbol manager
*
* 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
*
* 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.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
#include "../dudley/ddl.h"
#include "../dudley/parse.h"
#include "../dudley/ddl_proto.h"
#include "../dudley/hsh_proto.h"
const int HASH_SIZE = 101;
static USHORT hash(const SCHAR*, USHORT);
static bool scompare(const SCHAR*, USHORT, const SCHAR*, const USHORT);
static SYM hash_table[HASH_SIZE];
static SYM key_symbols;
struct word {
enum kwwords id;
const char* keyword;
} keywords[] = {
{KW_OR, "||"},
{KW_AND, "&&"},
{KW_GE, ">="},
{KW_LE, "<="},
{KW_NE, "<>"},
{KW_NE, "!="},
{KW_NE, "~="},
{KW_EQ, "=="},
{KW_GT, ">"},
{KW_LT, "<"},
{KW_PERCENT, "%"},
{KW_EQUALS, "="},
{KW_COMMA, ","},
{KW_DOT, "."},
{KW_L_BRCKET, "["},
{KW_LEFT_PAREN, "("},
{KW_MINUS, "-"},
{KW_R_BRCKET, "]"},
{KW_RIGHT_PAREN, ")"},
{KW_PLUS, "+"},
{KW_SEMI, ";"},
{KW_SLASH, "/"},
{KW_ASTERISK, "*"},
{KW_BAR, "|"},
{KW_COLON, ":"},
{KW_ABORT, "ABORT"},
{KW_ACL, "ACL"},
{KW_ACTIVE, "ACTIVE"},
{KW_ADD, "ADD"},
{KW_ALL, "ALL"},
{KW_ARRAY, "ARRAY"},
{KW_AT, "AT"},
{KW_AUTO, "AUTO"},
{KW_BASED, "BASED"},
// {KW_BASE_NAME, "BASE_NAME"},
{KW_BEGIN, "BEGIN"},
{KW_BLOB, "BLOB"},
{KW_BLR, "BLR"},
// {KW_CACHE, "CACHE"},
// {KW_CASCADE, "CASCADE"},
{KW_CHAR, "CHAR"},
// {KW_CHECK_POINT_LEN, "CHECK_POINT_LENGTH"},
{KW_COMPUTED, "COMPUTED_BY"},
{KW_COMPUTED, "COMPUTED"},
{KW_CONDITIONAL, "CONDITIONAL"},
{KW_CONSTRAINT, "CONSTRAINT"},
{KW_CSTRING, "CSTRING"},
{KW_DATABASE, "DATABASE"},
{KW_DATE, "DATE"},
{KW_DEFINE, "DEFINE"},
{KW_DEFAULT, "DEFAULT"},
{KW_DELETE, "DELETE"},
{KW_DESCRIP, "DESCRIPTION"},
{KW_DESCRIPTION, "{"},
{KW_DOUBLE, "DOUBLE"},
{KW_DROP, "DROP"},
{KW_DROP, "DELETE"},
{KW_DUPLICATES, "DUPLICATE"},
{KW_DUPLICATES, "DUPLICATES"},
{KW_EDIT_STRING, "EDIT_STRING"},
{KW_ELSE, "ELSE"},
{KW_END, "END"},
{KW_END_DESCRIPTION, "}"},
{KW_END_FOR, "END_FOR"},
{KW_END_MODIFY, "END_MODIFY"},
{KW_END_STORE, "END_STORE"},
{KW_END_TRIGGER, "END_TRIGGER"},
{KW_ERASE, "ERASE"},
{KW_EXIT, "EXIT"},
{KW_EXTERNAL_FILE, "EXTERNAL_FILE"},
{KW_FIELD, "FIELD"},
{KW_FILE, "FILE"},
{KW_FILTER, "FILTER"},
{KW_FIXED, "FIXED"},
{KW_FLOAT, "FLOAT"},
{KW_FOR, "FOR"},
{KW_FUNCTION, "FUNCTION"},
{KW_FUNCTION_ENTRY_POINT, "ENTRY_POINT"},
{KW_FUNCTION_MODULE_NAME, "MODULE_NAME"},
{KW_GENERATOR, "GENERATOR"},
{KW_GRANT, "GRANT"},
{KW_GROUP, "GROUP"},
// {KW_GROUP_COMMIT_WAIT, "GROUP_COMMIT_WAIT_TIME"},
{KW_IF, "IF"},
{KW_INACTIVE, "INACTIVE"},
{KW_INDEX, "INDEX"},
{KW_INPUT_TYPE, "INPUT_TYPE"},
{KW_INSERT, "INSERT"},
{KW_IS, "IS"},
{KW_LENGTH, "LENGTH"},
// {KW_LOG_BUF_SIZE, "LOG_BUFFER_SIZE"},
// {KW_LOG_FILE, "LOGFILE"},
{KW_LONG, "LONG"},
{KW_MANUAL, "MANUAL"},
{KW_MESSAGE, "MESSAGE"},
{KW_MISSING, "MISSING_VALUE"},
{KW_MISSING, "MISSING"},
{KW_MODIFY, "MODIFY"},
{KW_MSGADD, "MSGADD"},
{KW_MSGDROP, "MSGDROP"},
{KW_MSGMODIFY, "MSGMODIFY"},
{KW_NULL, "NULL"},
// {KW_NUM_LOG_BUFS, "NUM_LOG_BUFFERS"},
{KW_OFFSET, "OFFSET"},
{KW_ON, "ON"},
{KW_OPTION, "OPTION"},
{KW_OUTPUT_TYPE, "OUTPUT_TYPE"},
// {KW_OVERFLOW, "OVERFLOW"},
{KW_OVERWRITE, "OVERWRITE"},
{KW_PAGE, "PAGE"},
{KW_PAGES, "PAGES"},
{KW_PAGE_NUMBER, "PAGE_NUMBER"},
{KW_PAGE_SIZE, "PAGE_SIZE"},
{KW_PARTITIONS, "PARTITIONS"},
{KW_PASSWORD, "PASSWORD"},
{KW_POSITION, "POSITION"},
{KW_POST, "POST"},
{KW_POST_ERASE, "POST_ERASE"},
{KW_POST_MODIFY, "POST_MODIFY"},
{KW_POST_STORE, "POST_STORE"},
{KW_PRE, "PRE"},
{KW_PRE_ALLOCATE, "PRE_ALLOCATE"},
{KW_PRE_ERASE, "PRE_ERASE"},
{KW_PRE_MODIFY, "PRE_MODIFY"},
{KW_PRE_STORE, "PRE_STORE"},
{KW_PRIVILEGES, "PRIVILEGES"},
{KW_QUAD, "QUAD"},
{KW_QUERY_NAME, "QUERY_NAME"},
{KW_QUERY_HEADER, "QUERY_HEADER"},
// {KW_RAW, "RAW"},
// {KW_RAW_PARTITIONS, "RAW_PARTITIONS"},
{KW_REFERENCE, "REFERENCE"},
{KW_RELATION, "RELATION"},
{KW_RETURN_ARGUMENT, "RETURN_ARGUMENT"}, /* function argument return_mode */
{KW_RETURN_VALUE, "RETURN_VALUE"}, /* function argument return_mode */
{KW_REVOKE, "REVOKE"},
{KW_SCALAR_ARRAY_DESCRIPTOR, "SCALAR_ARRAY_DESCRIPTOR"},
{KW_SCALE, "SCALE"},
{KW_SELECT, "SELECT"},
{KW_SECURITY_CLASS, "SECURITY_CLASS"},
{KW_SEGMENT_LENGTH, "SEGMENT_LENGTH"},
{KW_SET, "SET"},
{KW_SET_GENERATOR, "SET_GENERATOR"},
{KW_SHADOW, "SHADOW"},
{KW_SHORT, "SHORT"},
// {KW_SIZE, "SIZE"},
{KW_SORTED, "SORTED"},
{KW_STATISTICS, "STATISTICS"},
{KW_STORE, "STORE"},
{KW_SUB_TYPE, "SUB_TYPE"},
{KW_SYSTEM_FLAG, "SYSTEM_FLAG"},
{KW_TEXT, "TEXT"},
{KW_THEN, "THEN"},
{KW_TO, "TO"},
{KW_TRIGGER, "TRIGGER"},
{KW_TYPES, "TYPES"},
{KW_UPDATE, "UPDATE"},
{KW_USER, "USER"},
{KW_USER_NAME, "RDB$USER_NAME"},
{KW_USING, "USING"},
{KW_VALID_IF, "VALID_IF"},
{KW_VALID_IF, "VALID"},
{KW_VALUE, "VALUE"},
{KW_VARYING, "VARYING"},
{KW_VIEW, "VIEW"},
{KW_AND, "AND"},
{KW_ANY, "ANY"},
{KW_ASCENDING, "ASC"},
{KW_ASCENDING, "ASCENDING"},
{KW_ASTERISK, "ASTERISK"},
{KW_AVERAGE, "AVERAGE"},
{KW_BETWEEN, "BETWEEN"},
{KW_BY, "BY"},
{KW_CONTAINING, "CONTAINING"},
{KW_COUNT, "COUNT"},
{KW_CROSS, "CROSS"},
{KW_DESCENDING, "DESC"},
{KW_DESCENDING, "DESCENDING"},
{KW_ELSE, "ELSE"},
{KW_EQ, "EQ"},
{KW_FIRST, "FIRST"},
{KW_FROM, "FROM"},
{KW_GEN_ID, "GEN_ID"},
{KW_GE, "GE"},
{KW_GT, "GT"},
{KW_IN, "IN"},
{KW_LE, "LE"},
{KW_LT, "LT"},
{KW_MATCHES, "MATCHES"},
{KW_MATCHES, "MATCHING"},
{KW_MIN, "MIN"},
{KW_MINUS, "MINUS"},
{KW_MISSING, "MISSING"},
{KW_NE, "NE"},
{KW_NOT, "NOT"},
{KW_OF, "OF"},
{KW_OR, "OR"},
{KW_OVER, "OVER"},
{KW_QUIT, "QUIT"},
{KW_REDUCED, "REDUCED"},
{KW_SLASH, "SLASH"},
{KW_SORTED, "SORTED"},
{KW_STARTS, "STARTS"},
{KW_STARTS, "STARTING"},
{KW_STARTS, "STARTS_WITH"},
{KW_STARTS, "STARTING_WITH"},
{KW_MAX, "MAX"},
{KW_TO, "TO"},
{KW_TOTAL, "TOTAL"},
{KW_UNIQUE, "UNIQUE"},
{KW_UPPERCASE, "UPPERCASE"},
{KW_WITH, "WITH"}
};
void HSH_init(void)
{
/**************************************
*
* H S H _ i n i t
*
**************************************
*
* Functional description
* Initialize the hash table. This mostly involves
* inserting all known keywords.
*
**************************************/
SYM symbol;
int i;
SSHORT length;
for (i = 0; i < FB_NELEM(keywords); i++) {
const char* string = keywords[i].keyword;
for (length = 0; string[length] != '\0'; length++);
symbol = (SYM) DDL_alloc(SYM_LEN);
symbol->sym_type = SYM_keyword;
symbol->sym_length = length;
symbol->sym_string = keywords[i].keyword;
symbol->sym_keyword = (int) keywords[i].id;
HSH_insert(symbol);
symbol->sym_object = (DUDLEY_CTX) key_symbols;
key_symbols = symbol;
}
}
void HSH_insert( SYM symbol)
{
/**************************************
*
* H S H _ i n s e r t
*
**************************************
*
* Functional description
* Insert a symbol into the hash table.
*
**************************************/
USHORT h;
SYM old;
h = hash(symbol->sym_string, symbol->sym_length);
for (old = hash_table[h]; old; old = old->sym_collision)
if (scompare(symbol->sym_string, symbol->sym_length,
old->sym_string, old->sym_length))
{
symbol->sym_homonym = old->sym_homonym;
old->sym_homonym = symbol;
return;
}
symbol->sym_collision = hash_table[h];
hash_table[h] = symbol;
}
SYM HSH_lookup(const SCHAR* string, USHORT length)
{
/**************************************
*
* H S H _ l o o k u p
*
**************************************
*
* Functional description
* Perform a string lookup against hash table.
*
**************************************/
SYM symbol;
for (symbol = hash_table[hash(string, length)]; symbol;
symbol = symbol->sym_collision)
if (scompare
(string, length, symbol->sym_string,
symbol->sym_length)) return symbol;
return NULL;
}
void HSH_remove( SYM symbol)
{
/**************************************
*
* H S H _ r e m o v e
*
**************************************
*
* Functional description
* Remove a symbol from the hash table.
*
**************************************/
USHORT h;
SYM *next, *ptr, homonym;
h = hash(symbol->sym_string, symbol->sym_length);
for (next = &hash_table[h]; *next; next = &(*next)->sym_collision)
if (symbol == *next)
if (homonym = symbol->sym_homonym) {
homonym->sym_collision = symbol->sym_collision;
*next = homonym;
return;
}
else {
*next = symbol->sym_collision;
return;
}
else
for (ptr = &(*next)->sym_homonym; *ptr; ptr = &(*ptr)->sym_homonym)
if (symbol == *ptr) {
*ptr = symbol->sym_homonym;
return;
}
DDL_err(280, NULL, NULL, NULL, NULL, NULL); /* msg 280: HSH_remove failed */
}
SYM HSH_typed_lookup(const TEXT* string,
USHORT length, enum sym_t type)
{
/**************************************
*
* H S H _ t y p e d _ l o o k u p
*
**************************************
*
* Functional description
* Perform a string lookup against hash table
* considering the object type. If length is
* 0, assume that the string is terminated by
* a null or space and compute the length.
*
**************************************/
if (!length) {
const TEXT* p;
for (p = string; *p && *p != ' '; p++)
if ((p - string) >= 32)
break;
length = p - string;
}
SYM symbol = HSH_lookup(string, length);
for (; symbol; symbol = symbol->sym_homonym)
if (symbol->sym_type == type)
break;
return symbol;
}
static USHORT hash(const SCHAR* string, USHORT length)
{
/**************************************
*
* h a s h
*
**************************************
*
* Functional description
* Returns the hash function of a string.
*
**************************************/
USHORT value = 0;
while (length--) {
const SCHAR c = *string++;
value = (value << 1) + UPPER(c);
}
return value % HASH_SIZE;
}
static bool scompare(const SCHAR* string1,
USHORT length1,
const SCHAR* string2,
const USHORT length2)
{
/**************************************
*
* s c o m p a r e
*
**************************************
*
* Functional description
* Compare two strings
*
**************************************/
SCHAR c1, c2;
if (length1 != length2)
return false;
while (length1--)
if ((c1 = *string1++) != (c2 = *string2++) && UPPER(c1) != UPPER(c2))
return false;
return true;
}