summaryrefslogtreecommitdiff
path: root/impl/antlr/libantlr3c-3.4/src/antlr3collections.c
diff options
context:
space:
mode:
Diffstat (limited to 'impl/antlr/libantlr3c-3.4/src/antlr3collections.c')
-rw-r--r--impl/antlr/libantlr3c-3.4/src/antlr3collections.c2741
1 files changed, 0 insertions, 2741 deletions
diff --git a/impl/antlr/libantlr3c-3.4/src/antlr3collections.c b/impl/antlr/libantlr3c-3.4/src/antlr3collections.c
deleted file mode 100644
index d9e22e9..0000000
--- a/impl/antlr/libantlr3c-3.4/src/antlr3collections.c
+++ /dev/null
@@ -1,2741 +0,0 @@
-/// \file
-/// Provides a number of useful functions that are roughly equivalent
-/// to java HashTable and List for the purposes of Antlr 3 C runtime.
-/// Also useable by the C programmer for things like symbol tables pointers
-/// and so on.
-///
-///
-
-// [The "BSD licence"]
-// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
-// http://www.temporal-wave.com
-// http://www.linkedin.com/in/jimidle
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// 3. The name of the author may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <antlr3.h>
-
-#include "antlr3collections.h"
-
-// Interface functions for hash table
-//
-
-// String based keys
-//
-static void antlr3HashDelete (pANTLR3_HASH_TABLE table, void * key);
-static void * antlr3HashGet (pANTLR3_HASH_TABLE table, void * key);
-static pANTLR3_HASH_ENTRY antlr3HashRemove (pANTLR3_HASH_TABLE table, void * key);
-static ANTLR3_INT32 antlr3HashPut (pANTLR3_HASH_TABLE table, void * key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-
-// Integer based keys (Lists and so on)
-//
-static void antlr3HashDeleteI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
-static void * antlr3HashGetI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
-static pANTLR3_HASH_ENTRY antlr3HashRemoveI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
-static ANTLR3_INT32 antlr3HashPutI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-
-static void antlr3HashFree (pANTLR3_HASH_TABLE table);
-static ANTLR3_UINT32 antlr3HashSize (pANTLR3_HASH_TABLE table);
-
-// -----------
-
-// Interface functions for enumeration
-//
-static int antlr3EnumNext (pANTLR3_HASH_ENUM en, pANTLR3_HASH_KEY * key, void ** data);
-static void antlr3EnumFree (pANTLR3_HASH_ENUM en);
-
-// Interface functions for List
-//
-static void antlr3ListFree (pANTLR3_LIST list);
-static void antlr3ListDelete(pANTLR3_LIST list, ANTLR3_INTKEY key);
-static void * antlr3ListGet (pANTLR3_LIST list, ANTLR3_INTKEY key);
-static ANTLR3_INT32 antlr3ListPut (pANTLR3_LIST list, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-static void * antlr3ListRemove(pANTLR3_LIST list, ANTLR3_INTKEY key);
-static ANTLR3_UINT32 antlr3ListSize (pANTLR3_LIST list);
-
-// Interface functions for Stack
-//
-static void antlr3StackFree (pANTLR3_STACK stack);
-static void * antlr3StackPop (pANTLR3_STACK stack);
-static void * antlr3StackGet (pANTLR3_STACK stack, ANTLR3_INTKEY key);
-static ANTLR3_BOOLEAN antlr3StackPush (pANTLR3_STACK stack, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-static ANTLR3_UINT32 antlr3StackSize (pANTLR3_STACK stack);
-static void * antlr3StackPeek (pANTLR3_STACK stack);
-
-// Interface functions for vectors
-//
-static void ANTLR3_CDECL antlr3VectorFree (pANTLR3_VECTOR vector);
-static void antlr3VectorDel (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
-static void * antlr3VectorGet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
-static void * antrl3VectorRemove (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
-static void antlr3VectorClear (pANTLR3_VECTOR vector);
-static ANTLR3_UINT32 antlr3VectorAdd (pANTLR3_VECTOR vector, void * element, void (ANTLR3_CDECL *freeptr)(void *));
-static ANTLR3_UINT32 antlr3VectorSet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry, void * element, void (ANTLR3_CDECL *freeptr)(void *), ANTLR3_BOOLEAN freeExisting);
-static ANTLR3_UINT32 antlr3VectorSize (pANTLR3_VECTOR vector);
-static ANTLR3_BOOLEAN antlr3VectorSwap (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry1, ANTLR3_UINT32 entry2);
-
-static void newPool (pANTLR3_VECTOR_FACTORY factory);
-static void closeVectorFactory (pANTLR3_VECTOR_FACTORY factory);
-static pANTLR3_VECTOR newVector (pANTLR3_VECTOR_FACTORY factory);
-static void returnVector (pANTLR3_VECTOR_FACTORY factory, pANTLR3_VECTOR vector);
-
-
-// Interface functions for int TRIE
-//
-static pANTLR3_TRIE_ENTRY intTrieGet (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key);
-static ANTLR3_BOOLEAN intTrieDel (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key);
-static ANTLR3_BOOLEAN intTrieAdd (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key, ANTLR3_UINT32 type, ANTLR3_INTKEY intType, void * data, void (ANTLR3_CDECL *freeptr)(void *));
-static void intTrieFree (pANTLR3_INT_TRIE trie);
-
-
-// Interface functions for topological sorter
-//
-static void addEdge (pANTLR3_TOPO topo, ANTLR3_UINT32 edge, ANTLR3_UINT32 dependency);
-static pANTLR3_UINT32 sortToArray (pANTLR3_TOPO topo);
-static void sortVector (pANTLR3_TOPO topo, pANTLR3_VECTOR v);
-static void freeTopo (pANTLR3_TOPO topo);
-
-// Local function to advance enumeration structure pointers
-//
-static void antlr3EnumNextEntry(pANTLR3_HASH_ENUM en);
-
-pANTLR3_HASH_TABLE
-antlr3HashTableNew(ANTLR3_UINT32 sizeHint)
-{
- // All we have to do is create the hashtable tracking structure
- // and allocate memory for the requested number of buckets.
- //
- pANTLR3_HASH_TABLE table;
-
- ANTLR3_UINT32 bucket; // Used to traverse the buckets
-
- table = ANTLR3_MALLOC(sizeof(ANTLR3_HASH_TABLE));
-
- // Error out if no memory left
- if (table == NULL)
- {
- return NULL;
- }
-
- // Allocate memory for the buckets
- //
- table->buckets = (pANTLR3_HASH_BUCKET) ANTLR3_MALLOC((size_t) (sizeof(ANTLR3_HASH_BUCKET) * sizeHint));
-
- if (table->buckets == NULL)
- {
- ANTLR3_FREE((void *)table);
- return NULL;
- }
-
- // Modulo of the table, (bucket count).
- //
- table->modulo = sizeHint;
-
- table->count = 0; /* Nothing in there yet ( I hope) */
-
- /* Initialize the buckets to empty
- */
- for (bucket = 0; bucket < sizeHint; bucket++)
- {
- table->buckets[bucket].entries = NULL;
- }
-
- /* Exclude duplicate entries by default
- */
- table->allowDups = ANTLR3_FALSE;
-
- /* Assume that keys should by strduped before they are
- * entered in the table.
- */
- table->doStrdup = ANTLR3_TRUE;
-
- /* Install the interface
- */
-
- table->get = antlr3HashGet;
- table->put = antlr3HashPut;
- table->del = antlr3HashDelete;
- table->remove = antlr3HashRemove;
-
- table->getI = antlr3HashGetI;
- table->putI = antlr3HashPutI;
- table->delI = antlr3HashDeleteI;
- table->removeI = antlr3HashRemoveI;
-
- table->size = antlr3HashSize;
- table->free = antlr3HashFree;
-
- return table;
-}
-
-static void
-antlr3HashFree(pANTLR3_HASH_TABLE table)
-{
- ANTLR3_UINT32 bucket; /* Used to traverse the buckets */
-
- pANTLR3_HASH_BUCKET thisBucket;
- pANTLR3_HASH_ENTRY entry;
- pANTLR3_HASH_ENTRY nextEntry;
-
- /* Free the table, all buckets and all entries, and all the
- * keys and data (if the table exists)
- */
- if (table != NULL)
- {
- for (bucket = 0; bucket < table->modulo; bucket++)
- {
- thisBucket = &(table->buckets[bucket]);
-
- /* Allow sparse tables, though we don't create them as such at present
- */
- if ( thisBucket != NULL)
- {
- entry = thisBucket->entries;
-
- /* Search all entries in the bucket and free them up
- */
- while (entry != NULL)
- {
- /* Save next entry - we do not want to access memory in entry after we
- * have freed it.
- */
- nextEntry = entry->nextEntry;
-
- /* Free any data pointer, this only happens if the user supplied
- * a pointer to a routine that knwos how to free the structure they
- * added to the table.
- */
- if (entry->free != NULL)
- {
- entry->free(entry->data);
- }
-
- /* Free the key memory - we know that we allocated this
- */
- if (entry->keybase.type == ANTLR3_HASH_TYPE_STR && entry->keybase.key.sKey != NULL)
- {
- ANTLR3_FREE(entry->keybase.key.sKey);
- }
-
- /* Free this entry
- */
- ANTLR3_FREE(entry);
- entry = nextEntry; /* Load next pointer to see if we shoud free it */
- }
- /* Invalidate the current pointer
- */
- thisBucket->entries = NULL;
- }
- }
-
- /* Now we can free the bucket memory
- */
- ANTLR3_FREE(table->buckets);
- }
-
- /* Now we free teh memory for the table itself
- */
- ANTLR3_FREE(table);
-}
-
-/** return the current size of the hash table
- */
-static ANTLR3_UINT32 antlr3HashSize (pANTLR3_HASH_TABLE table)
-{
- return table->count;
-}
-
-/** Remove a numeric keyed entry from a hash table if it exists,
- * no error if it does not exist.
- */
-static pANTLR3_HASH_ENTRY antlr3HashRemoveI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
- pANTLR3_HASH_ENTRY * nextPointer;
-
- /* First we need to know the hash of the provided key
- */
- hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + hash;
-
- /* Now, we traverse the entries in the bucket until
- * we find the key or the end of the entries in the bucket.
- * We track the element prior to the one we are examining
- * as we need to set its next pointer to the next pointer
- * of the entry we are deleting (if we find it).
- */
- entry = bucket->entries; /* Entry to examine */
- nextPointer = & bucket->entries; /* Where to put the next pointer of the deleted entry */
-
- while (entry != NULL)
- {
- /* See if this is the entry we wish to delete
- */
- if (entry->keybase.key.iKey == key)
- {
- /* It was the correct entry, so we set the next pointer
- * of the previous entry to the next pointer of this
- * located one, which takes it out of the chain.
- */
- (*nextPointer) = entry->nextEntry;
-
- table->count--;
-
- return entry;
- }
- else
- {
- /* We found an entry but it wasn't the one that was wanted, so
- * move to the next one, if any.
- */
- nextPointer = & (entry->nextEntry); /* Address of the next pointer in the current entry */
- entry = entry->nextEntry; /* Address of the next element in the bucket (if any) */
- }
- }
-
- return NULL; /* Not found */
-}
-
-/** Remove the element in the hash table for a particular
- * key value, if it exists - no error if it does not.
- */
-static pANTLR3_HASH_ENTRY
-antlr3HashRemove(pANTLR3_HASH_TABLE table, void * key)
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
- pANTLR3_HASH_ENTRY * nextPointer;
-
- /* First we need to know the hash of the provided key
- */
- hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + (hash % table->modulo);
-
- /* Now, we traverse the entries in the bucket until
- * we find the key or the end of the entires in the bucket.
- * We track the element prior to the one we are exmaining
- * as we need to set its next pointer to the next pointer
- * of the entry we are deleting (if we find it).
- */
- entry = bucket->entries; /* Entry to examine */
- nextPointer = & bucket->entries; /* Where to put the next pointer of the deleted entry */
-
- while (entry != NULL)
- {
- /* See if this is the entry we wish to delete
- */
- if (strcmp((const char *)key, (const char *)entry->keybase.key.sKey) == 0)
- {
- /* It was the correct entry, so we set the next pointer
- * of the previous entry to the next pointer of this
- * located one, which takes it out of the chain.
- */
- (*nextPointer) = entry->nextEntry;
-
- /* Release the key - if we allocated that
- */
- if (table->doStrdup == ANTLR3_TRUE)
- {
- ANTLR3_FREE(entry->keybase.key.sKey);
- }
- entry->keybase.key.sKey = NULL;
-
- table->count--;
-
- return entry;
- }
- else
- {
- /* We found an entry but it wasn't the one that was wanted, so
- * move to the next one, if any.
- */
- nextPointer = & (entry->nextEntry); /* Address of the next pointer in the current entry */
- entry = entry->nextEntry; /* Address of the next element in the bucket (if any) */
- }
- }
-
- return NULL; /* Not found */
-}
-
-/** Takes the element with the supplied key out of the list, and deletes the data
- * calling the supplied free() routine if any.
- */
-static void
-antlr3HashDeleteI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
-{
- pANTLR3_HASH_ENTRY entry;
-
- entry = antlr3HashRemoveI(table, key);
-
- /* Now we can free the elements and the entry in order
- */
- if (entry != NULL && entry->free != NULL)
- {
- /* Call programmer supplied function to release this entry data
- */
- entry->free(entry->data);
- entry->data = NULL;
- }
- /* Finally release the space for this entry block.
- */
- ANTLR3_FREE(entry);
-}
-
-/** Takes the element with the supplied key out of the list, and deletes the data
- * calling the supplied free() routine if any.
- */
-static void
-antlr3HashDelete (pANTLR3_HASH_TABLE table, void * key)
-{
- pANTLR3_HASH_ENTRY entry;
-
- entry = antlr3HashRemove(table, key);
-
- /* Now we can free the elements and the entry in order
- */
- if (entry != NULL && entry->free != NULL)
- {
- /* Call programmer supplied function to release this entry data
- */
- entry->free(entry->data);
- entry->data = NULL;
- }
- /* Finally release the space for this entry block.
- */
- ANTLR3_FREE(entry);
-}
-
-/** Return the element pointer in the hash table for a particular
- * key value, or NULL if it don't exist (or was itself NULL).
- */
-static void *
-antlr3HashGetI(pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
-
- /* First we need to know the hash of the provided key
- */
- hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + hash;
-
- /* Now we can inspect the key at each entry in the bucket
- * and see if we have a match.
- */
- entry = bucket->entries;
-
- while (entry != NULL)
- {
- if (entry->keybase.key.iKey == key)
- {
- /* Match was found, return the data pointer for this entry
- */
- return entry->data;
- }
- entry = entry->nextEntry;
- }
-
- /* If we got here, then we did not find the key
- */
- return NULL;
-}
-
-/** Return the element pointer in the hash table for a particular
- * key value, or NULL if it don't exist (or was itself NULL).
- */
-static void *
-antlr3HashGet(pANTLR3_HASH_TABLE table, void * key)
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
-
-
- /* First we need to know the hash of the provided key
- */
- hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + (hash % table->modulo);
-
- /* Now we can inspect the key at each entry in the bucket
- * and see if we have a match.
- */
- entry = bucket->entries;
-
- while (entry != NULL)
- {
- if (strcmp((const char *)key, (const char *)entry->keybase.key.sKey) == 0)
- {
- /* Match was found, return the data pointer for this entry
- */
- return entry->data;
- }
- entry = entry->nextEntry;
- }
-
- /* If we got here, then we did not find the key
- */
- return NULL;
-}
-
-/** Add the element pointer in to the table, based upon the
- * hash of the provided key.
- */
-static ANTLR3_INT32
-antlr3HashPutI(pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
- pANTLR3_HASH_ENTRY * newPointer;
-
- /* First we need to know the hash of the provided key
- */
- hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + hash;
-
- /* Knowing the bucket, we can traverse the entries until we
- * we find a NULL pointer or we find that this is already
- * in the table and duplicates were not allowed.
- */
- newPointer = &bucket->entries;
-
- while (*newPointer != NULL)
- {
- /* The value at new pointer is pointing to an existing entry.
- * If duplicates are allowed then we don't care what it is, but
- * must reject this add if the key is the same as the one we are
- * supplied with.
- */
- if (table->allowDups == ANTLR3_FALSE)
- {
- if ((*newPointer)->keybase.key.iKey == key)
- {
- return ANTLR3_ERR_HASHDUP;
- }
- }
-
- /* Point to the next entry pointer of the current entry we
- * are traversing, if it is NULL we will create our new
- * structure and point this to it.
- */
- newPointer = &((*newPointer)->nextEntry);
- }
-
- /* newPointer is now pointing at the pointer where we need to
- * add our new entry, so let's crate the entry and add it in.
- */
- entry = (pANTLR3_HASH_ENTRY)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENTRY));
-
- if (entry == NULL)
- {
- return ANTLR3_ERR_NOMEM;
- }
-
- entry->data = element; /* Install the data element supplied */
- entry->free = freeptr; /* Function that knows how to release the entry */
- entry->keybase.type = ANTLR3_HASH_TYPE_INT; /* Indicate the key type stored here for when we free */
- entry->keybase.key.iKey = key; /* Record the key value */
- entry->nextEntry = NULL; /* Ensure that the forward pointer ends the chain */
-
- *newPointer = entry; /* Install the next entry in this bucket */
-
- table->count++;
-
- return ANTLR3_SUCCESS;
-}
-
-
-/** Add the element pointer in to the table, based upon the
- * hash of the provided key.
- */
-static ANTLR3_INT32
-antlr3HashPut(pANTLR3_HASH_TABLE table, void * key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- ANTLR3_UINT32 hash;
- pANTLR3_HASH_BUCKET bucket;
- pANTLR3_HASH_ENTRY entry;
- pANTLR3_HASH_ENTRY * newPointer;
-
- /* First we need to know the hash of the provided key
- */
- hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
-
- /* Knowing the hash, we can find the bucket
- */
- bucket = table->buckets + (hash % table->modulo);
-
- /* Knowign the bucket, we can traverse the entries until we
- * we find a NULL pointer ofr we find that this is already
- * in the table and duplicates were not allowed.
- */
- newPointer = &bucket->entries;
-
- while (*newPointer != NULL)
- {
- /* The value at new pointer is pointing to an existing entry.
- * If duplicates are allowed then we don't care what it is, but
- * must reject this add if the key is the same as the one we are
- * supplied with.
- */
- if (table->allowDups == ANTLR3_FALSE)
- {
- if (strcmp((const char*) key, (const char *)(*newPointer)->keybase.key.sKey) == 0)
- {
- return ANTLR3_ERR_HASHDUP;
- }
- }
-
- /* Point to the next entry pointer of the current entry we
- * are traversing, if it is NULL we will create our new
- * structure and point this to it.
- */
- newPointer = &((*newPointer)->nextEntry);
- }
-
- /* newPointer is now poiting at the pointer where we need to
- * add our new entry, so let's crate the entry and add it in.
- */
- entry = (pANTLR3_HASH_ENTRY)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENTRY));
-
- if (entry == NULL)
- {
- return ANTLR3_ERR_NOMEM;
- }
-
- entry->data = element; /* Install the data element supplied */
- entry->free = freeptr; /* Function that knows how to release the entry */
- entry->keybase.type = ANTLR3_HASH_TYPE_STR; /* Indicate the key type stored here for free() */
- if (table->doStrdup == ANTLR3_TRUE)
- {
- entry->keybase.key.sKey = ANTLR3_STRDUP(key); /* Record the key value */
- }
- else
- {
- entry->keybase.key.sKey = key; /* Record the key value */
- }
- entry->nextEntry = NULL; /* Ensure that the forward pointer ends the chain */
-
- *newPointer = entry; /* Install the next entry in this bucket */
-
- table->count++;
-
- return ANTLR3_SUCCESS;
-}
-
-/** \brief Creates an enumeration structure to traverse the hash table.
- *
- * \param table Table to enumerate
- * \return Pointer to enumeration structure.
- */
-pANTLR3_HASH_ENUM
-antlr3EnumNew (pANTLR3_HASH_TABLE table)
-{
- pANTLR3_HASH_ENUM en;
-
- /* Allocate structure memory
- */
- en = (pANTLR3_HASH_ENUM) ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENUM));
-
- /* Check that the allocation was good
- */
- if (en == NULL)
- {
- return (pANTLR3_HASH_ENUM) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Initialize the start pointers
- */
- en->table = table;
- en->bucket = 0; /* First bucket */
- en->entry = en->table->buckets->entries; /* First entry to return */
-
- /* Special case in that the first bucket may not have anything in it
- * but the antlr3EnumNext() function expects that the en->entry is
- * set to the next valid pointer. Hence if it is not a valid element
- * pointer, attempt to find the next one that is, (table may be empty
- * of course.
- */
- if (en->entry == NULL)
- {
- antlr3EnumNextEntry(en);
- }
-
- /* Install the interface
- */
- en->free = antlr3EnumFree;
- en->next = antlr3EnumNext;
-
- /* All is good
- */
- return en;
-}
-
-/** \brief Return the next entry in the hashtable being traversed by the supplied
- * enumeration.
- *
- * \param[in] en Pointer to the enumeration tracking structure
- * \param key Pointer to void pointer, where the key pointer is returned.
- * \param data Pointer to void pointer where the data pointer is returned.
- * \return
- * - ANTLR3_SUCCESS if there was a next key
- * - ANTLR3_FAIL if there were no more keys
- *
- * \remark
- * No checking of input structure is performed!
- */
-static int
-antlr3EnumNext (pANTLR3_HASH_ENUM en, pANTLR3_HASH_KEY * key, void ** data)
-{
- /* If the current entry is valid, then use it
- */
- if (en->bucket >= en->table->modulo)
- {
- /* Already exhausted the table
- */
- return ANTLR3_FAIL;
- }
-
- /* Pointers are already set to the current entry to return, or
- * we would not be at this point in the logic flow.
- */
- *key = &(en->entry->keybase);
- *data = en->entry->data;
-
- /* Return pointers are set up, so now we move the element
- * pointer to the next in the table (if any).
- */
- antlr3EnumNextEntry(en);
-
- return ANTLR3_SUCCESS;
-}
-
-/** \brief Local function to advance the entry pointer of an enumeration
- * structure to the next valid entry (if there is one).
- *
- * \param[in] enum Pointer to ANTLR3 enumeration structure returned by antlr3EnumNew()
- *
- * \remark
- * - The function always leaves the pointers pointing at a valid entry if there
- * is one, so if the entry pointer is NULL when this function exits, there were
- * no more entries in the table.
- */
-static void
-antlr3EnumNextEntry(pANTLR3_HASH_ENUM en)
-{
- pANTLR3_HASH_BUCKET bucket;
-
- /* See if the current entry pointer is valid first of all
- */
- if (en->entry != NULL)
- {
- /* Current entry was a valid point, see if there is another
- * one in the chain.
- */
- if (en->entry->nextEntry != NULL)
- {
- /* Next entry in the enumeration is just the next entry
- * in the chain.
- */
- en->entry = en->entry->nextEntry;
- return;
- }
- }
-
- /* There were no more entries in the current bucket, if there are
- * more buckets then chase them until we find an entry.
- */
- en->bucket++;
-
- while (en->bucket < en->table->modulo)
- {
- /* There was one more bucket, see if it has any elements in it
- */
- bucket = en->table->buckets + en->bucket;
-
- if (bucket->entries != NULL)
- {
- /* There was an entry in this bucket, so we can use it
- * for the next entry in the enumeration.
- */
- en->entry = bucket->entries;
- return;
- }
-
- /* There was nothing in the bucket we just examined, move to the
- * next one.
- */
- en->bucket++;
- }
-
- /* Here we have exhausted all buckets and the enumeration pointer will
- * have its bucket count = table->modulo which signifies that we are done.
- */
-}
-
-/** \brief Frees up the memory structures that represent a hash table
- * enumeration.
- * \param[in] enum Pointer to ANTLR3 enumeration structure returned by antlr3EnumNew()
- */
-static void
-antlr3EnumFree (pANTLR3_HASH_ENUM en)
-{
- /* Nothing to check, we just free it.
- */
- ANTLR3_FREE(en);
-}
-
-/** Given an input key of arbitrary length, return a hash value of
- * it. This can then be used (with suitable modulo) to index other
- * structures.
- */
-ANTLR3_API ANTLR3_UINT32
-antlr3Hash(void * key, ANTLR3_UINT32 keylen)
-{
- /* Accumulate the hash value of the key
- */
- ANTLR3_UINT32 hash;
- pANTLR3_UINT8 keyPtr;
- ANTLR3_UINT32 i1;
-
- hash = 0;
- keyPtr = (pANTLR3_UINT8) key;
-
- /* Iterate the key and accumulate the hash
- */
- while(keylen > 0)
- {
- hash = (hash << 4) + (*(keyPtr++));
-
- if ((i1=hash&0xf0000000) != 0)
- {
- hash = hash ^ (i1 >> 24);
- hash = hash ^ i1;
- }
- keylen--;
- }
-
- return hash;
-}
-
-ANTLR3_API pANTLR3_LIST
-antlr3ListNew (ANTLR3_UINT32 sizeHint)
-{
- pANTLR3_LIST list;
-
- /* Allocate memory
- */
- list = (pANTLR3_LIST)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_LIST));
-
- if (list == NULL)
- {
- return (pANTLR3_LIST)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Now we need to add a new table
- */
- list->table = antlr3HashTableNew(sizeHint);
-
- if (list->table == (pANTLR3_HASH_TABLE)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM))
- {
- return (pANTLR3_LIST)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Allocation was good, install interface
- */
- list->free = antlr3ListFree;
- list->del = antlr3ListDelete;
- list->get = antlr3ListGet;
- list->add = antlr3ListAdd;
- list->remove = antlr3ListRemove;
- list->put = antlr3ListPut;
- list->size = antlr3ListSize;
-
- return list;
-}
-
-static ANTLR3_UINT32 antlr3ListSize (pANTLR3_LIST list)
-{
- return list->table->size(list->table);
-}
-
-static void
-antlr3ListFree (pANTLR3_LIST list)
-{
- /* Free the hashtable that stores the list
- */
- list->table->free(list->table);
-
- /* Free the allocation for the list itself
- */
- ANTLR3_FREE(list);
-}
-
-static void
-antlr3ListDelete (pANTLR3_LIST list, ANTLR3_INTKEY key)
-{
- list->table->delI(list->table, key);
-}
-
-static void *
-antlr3ListGet (pANTLR3_LIST list, ANTLR3_INTKEY key)
-{
- return list->table->getI(list->table, key);
-}
-
-/** Add the supplied element to the list, at the next available key
- */
-static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- ANTLR3_INTKEY key;
-
- key = list->table->size(list->table) + 1;
- return list->put(list, key, element, freeptr);
-}
-
-/** Remove from the list, but don't free the element, just send it back to the
- * caller.
- */
-static void *
-antlr3ListRemove (pANTLR3_LIST list, ANTLR3_INTKEY key)
-{
- pANTLR3_HASH_ENTRY entry;
-
- entry = list->table->removeI(list->table, key);
-
- if (entry != NULL)
- {
- return entry->data;
- }
- else
- {
- return NULL;
- }
-}
-
-static ANTLR3_INT32
-antlr3ListPut (pANTLR3_LIST list, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- return list->table->putI(list->table, key, element, freeptr);
-}
-
-ANTLR3_API pANTLR3_STACK
-antlr3StackNew (ANTLR3_UINT32 sizeHint)
-{
- pANTLR3_STACK stack;
-
- /* Allocate memory
- */
- stack = (pANTLR3_STACK)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_STACK));
-
- if (stack == NULL)
- {
- return (pANTLR3_STACK)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Now we need to add a new table
- */
- stack->vector = antlr3VectorNew(sizeHint);
- stack->top = NULL;
-
- if (stack->vector == (pANTLR3_VECTOR)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM))
- {
- return (pANTLR3_STACK)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Looks good, now add the interface
- */
- stack->get = antlr3StackGet;
- stack->free = antlr3StackFree;
- stack->pop = antlr3StackPop;
- stack->push = antlr3StackPush;
- stack->size = antlr3StackSize;
- stack->peek = antlr3StackPeek;
-
- return stack;
-}
-
-static ANTLR3_UINT32 antlr3StackSize (pANTLR3_STACK stack)
-{
- return stack->vector->count;
-}
-
-
-static void
-antlr3StackFree (pANTLR3_STACK stack)
-{
- /* Free the list that supports the stack
- */
- stack->vector->free(stack->vector);
- stack->vector = NULL;
- stack->top = NULL;
-
- ANTLR3_FREE(stack);
-}
-
-static void *
-antlr3StackPop (pANTLR3_STACK stack)
-{
- // Delete the element that is currently at the top of the stack
- //
- stack->vector->del(stack->vector, stack->vector->count - 1);
-
- // And get the element that is the now the top of the stack (if anything)
- // NOTE! This is not quite like a 'real' stack, which would normally return you
- // the current top of the stack, then remove it from the stack.
- // TODO: Review this, it is correct for follow sets which is what this was done for
- // but is not as obvious when using it as a 'real'stack.
- //
- stack->top = stack->vector->get(stack->vector, stack->vector->count - 1);
- return stack->top;
-}
-
-static void *
-antlr3StackGet (pANTLR3_STACK stack, ANTLR3_INTKEY key)
-{
- return stack->vector->get(stack->vector, (ANTLR3_UINT32)key);
-}
-
-static void *
-antlr3StackPeek (pANTLR3_STACK stack)
-{
- return stack->top;
-}
-
-static ANTLR3_BOOLEAN
-antlr3StackPush (pANTLR3_STACK stack, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- stack->top = element;
- return (ANTLR3_BOOLEAN)(stack->vector->add(stack->vector, element, freeptr));
-}
-
-ANTLR3_API pANTLR3_VECTOR
-antlr3VectorNew (ANTLR3_UINT32 sizeHint)
-{
- pANTLR3_VECTOR vector;
-
-
- // Allocate memory for the vector structure itself
- //
- vector = (pANTLR3_VECTOR) ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR)));
-
- if (vector == NULL)
- {
- return (pANTLR3_VECTOR)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- // Now fill in the defaults
- //
- antlr3SetVectorApi(vector, sizeHint);
-
- // And everything is hunky dory
- //
- return vector;
-}
-
-ANTLR3_API void
-antlr3SetVectorApi (pANTLR3_VECTOR vector, ANTLR3_UINT32 sizeHint)
-{
- ANTLR3_UINT32 initialSize;
-
- // Allow vectors to be guessed by ourselves, so input size can be zero
- //
- if (sizeHint > ANTLR3_VECTOR_INTERNAL_SIZE)
- {
- initialSize = sizeHint;
- }
- else
- {
- initialSize = ANTLR3_VECTOR_INTERNAL_SIZE;
- }
-
- if (sizeHint > ANTLR3_VECTOR_INTERNAL_SIZE)
- {
- vector->elements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR_ELEMENT) * initialSize));
- }
- else
- {
- vector->elements = vector->internal;
- }
-
- if (vector->elements == NULL)
- {
- ANTLR3_FREE(vector);
- return;
- }
-
- // Memory allocated successfully
- //
- vector->count = 0; // No entries yet of course
- vector->elementsSize = initialSize; // Available entries
-
- // Now we can install the API
- //
- vector->add = antlr3VectorAdd;
- vector->del = antlr3VectorDel;
- vector->get = antlr3VectorGet;
- vector->free = antlr3VectorFree;
- vector->set = antlr3VectorSet;
- vector->remove = antrl3VectorRemove;
- vector->clear = antlr3VectorClear;
- vector->size = antlr3VectorSize;
- vector->swap = antlr3VectorSwap;
-
- // Assume that this is not a factory made vector
- //
- vector->factoryMade = ANTLR3_FALSE;
-}
-
-// Clear the entries in a vector.
-// Clearing the vector leaves its capacity the same but
-// it walks the entries first to see if any of them
-// have a free routine that must be called.
-//
-static void
-antlr3VectorClear (pANTLR3_VECTOR vector)
-{
- ANTLR3_UINT32 entry;
-
- // We must traverse every entry in the vector and if it has
- // a pointer to a free function then we call it with the
- // the entry pointer
- //
- for (entry = 0; entry < vector->count; entry++)
- {
- if (vector->elements[entry].freeptr != NULL)
- {
- vector->elements[entry].freeptr(vector->elements[entry].element);
- }
- vector->elements[entry].freeptr = NULL;
- vector->elements[entry].element = NULL;
- }
-
- // Having called any free pointers, we just reset the entry count
- // back to zero.
- //
- vector->count = 0;
-}
-
-static
-void ANTLR3_CDECL antlr3VectorFree (pANTLR3_VECTOR vector)
-{
- ANTLR3_UINT32 entry;
-
- // We must traverse every entry in the vector and if it has
- // a pointer to a free function then we call it with the
- // the entry pointer
- //
- for (entry = 0; entry < vector->count; entry++)
- {
- if (vector->elements[entry].freeptr != NULL)
- {
- vector->elements[entry].freeptr(vector->elements[entry].element);
- }
- vector->elements[entry].freeptr = NULL;
- vector->elements[entry].element = NULL;
- }
-
- if (vector->factoryMade == ANTLR3_FALSE)
- {
- // The entries are freed, so free the element allocation
- //
- if (vector->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
- {
- ANTLR3_FREE(vector->elements);
- }
- vector->elements = NULL;
-
- // Finally, free the allocation for the vector itself
- //
- ANTLR3_FREE(vector);
- }
-}
-
-static void antlr3VectorDel (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
-{
- // Check this is a valid request first
- //
- if (entry >= vector->count)
- {
- return;
- }
-
- // Valid request, check for free pointer and call it if present
- //
- if (vector->elements[entry].freeptr != NULL)
- {
- vector->elements[entry].freeptr(vector->elements[entry].element);
- vector->elements[entry].freeptr = NULL;
- }
-
- if (entry == vector->count - 1)
- {
- // Ensure the pointer is never reused by accident, but otherwise just
- // decrement the pointer.
- //
- vector->elements[entry].element = NULL;
- }
- else
- {
- // Need to shuffle trailing pointers back over the deleted entry
- //
- ANTLR3_MEMMOVE(vector->elements + entry, vector->elements + entry + 1, sizeof(ANTLR3_VECTOR_ELEMENT) * (vector->count - entry - 1));
- }
-
- // One less entry in the vector now
- //
- vector->count--;
-}
-
-static void * antlr3VectorGet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
-{
- // Ensure this is a valid request
- //
- if (entry < vector->count)
- {
- return vector->elements[entry].element;
- }
- else
- {
- // I know nothing, Mr. Fawlty!
- //
- return NULL;
- }
-}
-
-/// Remove the entry from the vector, but do not free any entry, even if it has
-/// a free pointer.
-///
-static void * antrl3VectorRemove (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
-{
- void * element;
-
- // Check this is a valid request first
- //
- if (entry >= vector->count)
- {
- return NULL;
- }
-
- // Valid request, return the sorted pointer
- //
-
- element = vector->elements[entry].element;
-
- if (entry == vector->count - 1)
- {
- // Ensure the pointer is never reused by accident, but otherwise just
- // decrement the pointer.
- ///
- vector->elements[entry].element = NULL;
- vector->elements[entry].freeptr = NULL;
- }
- else
- {
- // Need to shuffle trailing pointers back over the deleted entry
- //
- ANTLR3_MEMMOVE(vector->elements + entry, vector->elements + entry + 1, sizeof(ANTLR3_VECTOR_ELEMENT) * (vector->count - entry - 1));
- }
-
- // One less entry in the vector now
- //
- vector->count--;
-
- return element;
-}
-
-static void
-antlr3VectorResize (pANTLR3_VECTOR vector, ANTLR3_UINT32 hint)
-{
- ANTLR3_UINT32 newSize;
-
- // Need to resize the element pointers. We double the allocation
- // we already have unless asked for a specific increase.
- //
- if (hint == 0 || hint < vector->elementsSize)
- {
- newSize = vector->elementsSize * 2;
- }
- else
- {
- newSize = hint * 2;
- }
-
- // Now we know how many we need, so we see if we have just expanded
- // past the built in vector elements or were already past that
- //
- if (vector->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
- {
- // We were already larger than the internal size, so we just
- // use realloc so that the pointers are copied for us
- //
- vector->elements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_REALLOC(vector->elements, (sizeof(ANTLR3_VECTOR_ELEMENT)* newSize));
- }
- else
- {
- // The current size was less than or equal to the internal array size and as we always start
- // with a size that is at least the maximum internal size, then we must need to allocate new memory
- // for external pointers. We don't want to take the time to calculate if a requested element
- // is part of the internal or external entries, so we copy the internal ones to the new space
- //
- vector->elements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_MALLOC((sizeof(ANTLR3_VECTOR_ELEMENT)* newSize));
- ANTLR3_MEMCPY(vector->elements, vector->internal, ANTLR3_VECTOR_INTERNAL_SIZE * sizeof(ANTLR3_VECTOR_ELEMENT));
- }
-
- vector->elementsSize = newSize;
-}
-
-/// Add the supplied pointer and freeing function pointer to the list,
-/// expanding the vector if needed.
-///
-static ANTLR3_UINT32 antlr3VectorAdd (pANTLR3_VECTOR vector, void * element, void (ANTLR3_CDECL *freeptr)(void *))
-{
- // Do we need to resize the vector table?
- //
- if (vector->count == vector->elementsSize)
- {
- antlr3VectorResize(vector, 0); // Give no hint, we let it add 1024 or double it
- }
-
- // Insert the new entry
- //
- vector->elements[vector->count].element = element;
- vector->elements[vector->count].freeptr = freeptr;
-
- vector->count++; // One more element counted
-
- return (ANTLR3_UINT32)(vector->count);
-
-}
-
-/// Replace the element at the specified entry point with the supplied
-/// entry.
-///
-static ANTLR3_UINT32
-antlr3VectorSet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry, void * element, void (ANTLR3_CDECL *freeptr)(void *), ANTLR3_BOOLEAN freeExisting)
-{
-
- // If the vector is currently not big enough, then we expand it
- //
- if (entry >= vector->elementsSize)
- {
- antlr3VectorResize(vector, entry); // We will get at least this many
- }
-
- // Valid request, replace the current one, freeing any prior entry if told to
- //
- if ( entry < vector->count // If actually replacing an element
- && freeExisting // And told to free any existing element
- && vector->elements[entry].freeptr != NULL // And the existing element has a free pointer
- )
- {
- vector->elements[entry].freeptr(vector->elements[entry].element);
- }
-
- // Install the new pointers
- //
- vector->elements[entry].freeptr = freeptr;
- vector->elements[entry].element = element;
-
- if (entry >= vector->count)
- {
- vector->count = entry + 1;
- }
- return (ANTLR3_UINT32)(entry); // Indicates the replacement was successful
-
-}
-
-/// Replace the element at the specified entry point with the supplied
-/// entry.
-///
-static ANTLR3_BOOLEAN
-antlr3VectorSwap (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry1, ANTLR3_UINT32 entry2)
-{
-
- void * tempEntry;
- void (ANTLR3_CDECL *freeptr)(void *);
-
- // If the vector is currently not big enough, then we do nothing
- //
- if (entry1 >= vector->elementsSize || entry2 >= vector->elementsSize)
- {
- return ANTLR3_FALSE;
- }
-
- // Valid request, swap them
- //
- tempEntry = vector->elements[entry1].element;
- freeptr = vector->elements[entry1].freeptr;
-
- // Install the new pointers
- //
- vector->elements[entry1].freeptr = vector->elements[entry2].freeptr;
- vector->elements[entry1].element = vector->elements[entry2].element;
-
- vector->elements[entry2].freeptr = freeptr;
- vector->elements[entry2].element = tempEntry;
-
- return ANTLR3_TRUE;
-
-}
-
-static ANTLR3_UINT32 antlr3VectorSize (pANTLR3_VECTOR vector)
-{
- return vector->count;
-}
-
-#ifdef ANTLR3_WINDOWS
-#pragma warning (push)
-#pragma warning (disable : 4100)
-#endif
-/// Vector factory creation
-///
-ANTLR3_API pANTLR3_VECTOR_FACTORY
-antlr3VectorFactoryNew (ANTLR3_UINT32 sizeHint)
-{
- pANTLR3_VECTOR_FACTORY factory;
-
- // Allocate memory for the factory
- //
- factory = (pANTLR3_VECTOR_FACTORY)ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR_FACTORY)));
-
- if (factory == NULL)
- {
- return NULL;
- }
-
- // Factory memory is good, so create a new vector pool
- //
- factory->pools = NULL;
- factory->thisPool = -1;
-
- newPool(factory);
-
- // Initialize the API, ignore the hint as this algorithm does
- // a better job really.
- //
- antlr3SetVectorApi(&(factory->unTruc), ANTLR3_VECTOR_INTERNAL_SIZE);
-
- factory->unTruc.factoryMade = ANTLR3_TRUE;
-
- // Install the factory API
- //
- factory->close = closeVectorFactory;
- factory->newVector = newVector;
- factory->returnVector = returnVector;
-
- // Create a stack to accumulate reusable vectors
- //
- factory->freeStack = antlr3StackNew(16);
- return factory;
-}
-#ifdef ANTLR3_WINDOWS
-#pragma warning (pop)
-#endif
-
-static void
-returnVector (pANTLR3_VECTOR_FACTORY factory, pANTLR3_VECTOR vector)
-{
- // First we need to clear out anything that is still in the vector
- //
- vector->clear(vector);
-
- // We have a free stack available so we can add the vector we were
- // given into the free chain. The vector has to have come from this
- // factory, so we already know how to release its memory when it
- // dies by virtue of the factory being closed.
- //
- factory->freeStack->push(factory->freeStack, vector, NULL);
-
- // TODO: remove this line once happy printf("Returned vector %08X to the pool, stack size is %d\n", vector, factory->freeStack->size(factory->freeStack));
-}
-
-static void
-newPool(pANTLR3_VECTOR_FACTORY factory)
-{
- /* Increment factory count
- */
- factory->thisPool++;
-
- /* Ensure we have enough pointers allocated
- */
- factory->pools = (pANTLR3_VECTOR *)
- ANTLR3_REALLOC( (void *)factory->pools, /* Current pools pointer (starts at NULL) */
- (ANTLR3_UINT32)((factory->thisPool + 1) * sizeof(pANTLR3_VECTOR *)) /* Memory for new pool pointers */
- );
-
- /* Allocate a new pool for the factory
- */
- factory->pools[factory->thisPool] =
- (pANTLR3_VECTOR)
- ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR) * ANTLR3_FACTORY_VPOOL_SIZE));
-
-
- /* Reset the counters
- */
- factory->nextVector = 0;
-
- /* Done
- */
- return;
-}
-
-static void
-closeVectorFactory (pANTLR3_VECTOR_FACTORY factory)
-{
- pANTLR3_VECTOR pool;
- ANTLR3_INT32 poolCount;
- ANTLR3_UINT32 limit;
- ANTLR3_UINT32 vector;
- pANTLR3_VECTOR check;
-
- // First see if we have a free chain stack to release?
- //
- if (factory->freeStack != NULL)
- {
- factory->freeStack->free(factory->freeStack);
- }
-
- /* We iterate the vector pools one at a time
- */
- for (poolCount = 0; poolCount <= factory->thisPool; poolCount++)
- {
- /* Pointer to current pool
- */
- pool = factory->pools[poolCount];
-
- /* Work out how many tokens we need to check in this pool.
- */
- limit = (poolCount == factory->thisPool ? factory->nextVector : ANTLR3_FACTORY_VPOOL_SIZE);
-
- /* Marginal condition, we might be at the start of a brand new pool
- * where the nextToken is 0 and nothing has been allocated.
- */
- if (limit > 0)
- {
- /* We have some vectors allocated from this pool
- */
- for (vector = 0; vector < limit; vector++)
- {
- /* Next one in the chain
- */
- check = pool + vector;
-
- // Call the free function on each of the vectors in the pool,
- // which in turn will cause any elements it holds that also have a free
- // pointer to be freed. However, because any vector may be in any other
- // vector, we don't free the element allocations yet. We do that in a
- // a specific pass, coming up next. The vector free function knows that
- // this is a factory allocated pool vector and so it won't free things it
- // should not.
- //
- check->free(check);
- }
- }
- }
-
- /* We iterate the vector pools one at a time once again, but this time
- * we are going to free up any allocated element pointers. Note that we are doing this
- * so that we do not try to release vectors twice. When building ASTs we just copy
- * the vectors all over the place and they may be embedded in this vector pool
- * numerous times.
- */
- for (poolCount = 0; poolCount <= factory->thisPool; poolCount++)
- {
- /* Pointer to current pool
- */
- pool = factory->pools[poolCount];
-
- /* Work out how many tokens we need to check in this pool.
- */
- limit = (poolCount == factory->thisPool ? factory->nextVector : ANTLR3_FACTORY_VPOOL_SIZE);
-
- /* Marginal condition, we might be at the start of a brand new pool
- * where the nextToken is 0 and nothing has been allocated.
- */
- if (limit > 0)
- {
- /* We have some vectors allocated from this pool
- */
- for (vector = 0; vector < limit; vector++)
- {
- /* Next one in the chain
- */
- check = pool + vector;
-
- // Anything in here should be factory made, but we do this just
- // to triple check. We just free up the elements if they were
- // allocated beyond the internal size.
- //
- if (check->factoryMade == ANTLR3_TRUE && check->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
- {
- ANTLR3_FREE(check->elements);
- check->elements = NULL;
- }
- }
- }
-
- // We can now free this pool allocation as we have called free on every element in every vector
- // and freed any memory for pointers the grew beyond the internal size limit.
- //
- ANTLR3_FREE(factory->pools[poolCount]);
- factory->pools[poolCount] = NULL;
- }
-
- /* All the pools are deallocated we can free the pointers to the pools
- * now.
- */
- ANTLR3_FREE(factory->pools);
-
- /* Finally, we can free the space for the factory itself
- */
- ANTLR3_FREE(factory);
-
-}
-
-static pANTLR3_VECTOR
-newVector(pANTLR3_VECTOR_FACTORY factory)
-{
- pANTLR3_VECTOR vector;
-
- // If we have anything on the re claim stack, reuse it
- //
- vector = factory->freeStack->peek(factory->freeStack);
-
- if (vector != NULL)
- {
- // Cool we got something we could reuse
- //
- factory->freeStack->pop(factory->freeStack);
-
- // TODO: remove this line once happy printf("Reused vector %08X from stack, size is now %d\n", vector, factory->freeStack->size(factory->freeStack));
- return vector;
-
- }
-
- // See if we need a new vector pool before allocating a new
- // one
- //
- if (factory->nextVector >= ANTLR3_FACTORY_VPOOL_SIZE)
- {
- // We ran out of vectors in the current pool, so we need a new pool
- //
- newPool(factory);
- }
-
- // Assuming everything went well (we are trying for performance here so doing minimal
- // error checking. Then we can work out what the pointer is to the next vector.
- //
- vector = factory->pools[factory->thisPool] + factory->nextVector;
- factory->nextVector++;
-
- // We have our token pointer now, so we can initialize it to the predefined model.
- //
- antlr3SetVectorApi(vector, ANTLR3_VECTOR_INTERNAL_SIZE);
- vector->factoryMade = ANTLR3_TRUE;
-
- // We know that the pool vectors are created at the default size, which means they
- // will start off using their internal entry pointers. We must intialize our pool vector
- // to point to its own internal entry table and not the pre-made one.
- //
- vector->elements = vector->internal;
-
- // TODO: remove this line once happy printf("Used a new vector at %08X from the pools as nothing on the reusue stack\n", vector);
-
- // And we are done
- //
- return vector;
-}
-
-/** Array of left most significant bit positions for an 8 bit
- * element provides an efficient way to find the highest bit
- * that is set in an n byte value (n>0). Assuming the values will all hit the data cache,
- * coding without conditional elements should allow branch
- * prediction to work well and of course a parallel instruction cache
- * will whip through this. Otherwise we must loop shifting a one
- * bit and masking. The values we tend to be placing in out integer
- * patricia trie are usually a lot lower than the 64 bits we
- * allow for the key allows. Hence there is a lot of redundant looping and
- * shifting in a while loop. Whereas, the lookup table is just
- * a few ands and indirect lookups, while testing for 0. This
- * is likely to be done in parallel on many processors available
- * when I wrote this. If this code survives as long as yacc, then
- * I may already be dead by the time you read this and maybe there is
- * a single machine instruction to perform the operation. What
- * else are you going to do with all those transistors? Jim 2007
- *
- * The table is probably obvious but it is just the number 0..7
- * of the MSB in each integer value 0..256
- */
-static ANTLR3_UINT8 bitIndex[256] =
-{
- 0, // 0 - Just for padding
- 0, // 1
- 1, 1, // 2..3
- 2, 2, 2, 2, // 4..7
- 3, 3, 3, 3, 3, 3, 3, 3, // 8+
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16+
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 32+
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 64+
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 128+
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-};
-
-/** Rather than use the bit index of a trie node to shift
- * 0x01 left that many times, then & with the result, it is
- * faster to use the bit index as an index into this table
- * which holds precomputed masks for any of the 64 bits
- * we need to mask off singly. The data values will stay in
- * cache while ever a trie is in heavy use, such as in
- * memoization. It is also pretty enough to be ASCII art.
- */
-static ANTLR3_UINT64 bitMask[64] =
-{
- 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000004ULL, 0x0000000000000008ULL,
- 0x0000000000000010ULL, 0x0000000000000020ULL, 0x0000000000000040ULL, 0x0000000000000080ULL,
- 0x0000000000000100ULL, 0x0000000000000200ULL, 0x0000000000000400ULL, 0x0000000000000800ULL,
- 0x0000000000001000ULL, 0x0000000000002000ULL, 0x0000000000004000ULL, 0x0000000000008000ULL,
- 0x0000000000010000ULL, 0x0000000000020000ULL, 0x0000000000040000ULL, 0x0000000000080000ULL,
- 0x0000000000100000ULL, 0x0000000000200000ULL, 0x0000000000400000ULL, 0x0000000000800000ULL,
- 0x0000000001000000ULL, 0x0000000002000000ULL, 0x0000000004000000ULL, 0x0000000008000000ULL,
- 0x0000000010000000ULL, 0x0000000020000000ULL, 0x0000000040000000ULL, 0x0000000080000000ULL,
- 0x0000000100000000ULL, 0x0000000200000000ULL, 0x0000000400000000ULL, 0x0000000800000000ULL,
- 0x0000001000000000ULL, 0x0000002000000000ULL, 0x0000004000000000ULL, 0x0000008000000000ULL,
- 0x0000010000000000ULL, 0x0000020000000000ULL, 0x0000040000000000ULL, 0x0000080000000000ULL,
- 0x0000100000000000ULL, 0x0000200000000000ULL, 0x0000400000000000ULL, 0x0000800000000000ULL,
- 0x0001000000000000ULL, 0x0002000000000000ULL, 0x0004000000000000ULL, 0x0008000000000000ULL,
- 0x0010000000000000ULL, 0x0020000000000000ULL, 0x0040000000000000ULL, 0x0080000000000000ULL,
- 0x0100000000000000ULL, 0x0200000000000000ULL, 0x0400000000000000ULL, 0x0800000000000000ULL,
- 0x1000000000000000ULL, 0x2000000000000000ULL, 0x4000000000000000ULL, 0x8000000000000000ULL
-};
-
-/* INT TRIE Implementation of depth 64 bits, being the number of bits
- * in a 64 bit integer.
- */
-
-pANTLR3_INT_TRIE
-antlr3IntTrieNew(ANTLR3_UINT32 depth)
-{
- pANTLR3_INT_TRIE trie;
-
- trie = (pANTLR3_INT_TRIE) ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE)); /* Base memory required */
-
- if (trie == NULL)
- {
- return (pANTLR3_INT_TRIE) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- /* Now we need to allocate the root node. This makes it easier
- * to use the tree as we don't have to do anything special
- * for the root node.
- */
- trie->root = (pANTLR3_INT_TRIE_NODE) ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE));
-
- if (trie->root == NULL)
- {
- ANTLR3_FREE(trie);
- return (pANTLR3_INT_TRIE) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
- }
-
- trie->add = intTrieAdd;
- trie->del = intTrieDel;
- trie->free = intTrieFree;
- trie->get = intTrieGet;
-
- /* Now we seed the root node with the index being the
- * highest left most bit we want to test, which limits the
- * keys in the trie. This is the trie 'depth'. The limit for
- * this implementation is 63 (bits 0..63).
- */
- trie->root->bitNum = depth;
-
- /* And as we have nothing in here yet, we set both child pointers
- * of the root node to point back to itself.
- */
- trie->root->leftN = trie->root;
- trie->root->rightN = trie->root;
- trie->count = 0;
-
- /* Finally, note that the key for this root node is 0 because
- * we use calloc() to initialise it.
- */
-
- return trie;
-}
-
-/** Search the int Trie and return a pointer to the first bucket indexed
- * by the key if it is contained in the trie, otherwise NULL.
- */
-static pANTLR3_TRIE_ENTRY
-intTrieGet (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key)
-{
- pANTLR3_INT_TRIE_NODE thisNode;
- pANTLR3_INT_TRIE_NODE nextNode;
-
- if (trie->count == 0)
- {
- return NULL; /* Nothing in this trie yet */
- }
- /* Starting at the root node in the trie, compare the bit index
- * of the current node with its next child node (starts left from root).
- * When the bit index of the child node is greater than the bit index of the current node
- * then by definition (as the bit index decreases as we descent the trie)
- * we have reached a 'backward' pointer. A backward pointer means we
- * have reached the only node that can be reached by the bits given us so far
- * and it must either be the key we are looking for, or if not then it
- * means the entry was not in the trie, and we return NULL. A backward pointer
- * points back in to the tree structure rather than down (deeper) within the
- * tree branches.
- */
- thisNode = trie->root; /* Start at the root node */
- nextNode = thisNode->leftN; /* Examine the left node from the root */
-
- /* While we are descending the tree nodes...
- */
- while (thisNode->bitNum > nextNode->bitNum)
- {
- /* Next node now becomes the new 'current' node
- */
- thisNode = nextNode;
-
- /* We now test the bit indicated by the bitmap in the next node
- * in the key we are searching for. The new next node is the
- * right node if that bit is set and the left node it is not.
- */
- if (key & bitMask[nextNode->bitNum])
- {
- nextNode = nextNode->rightN; /* 1 is right */
- }
- else
- {
- nextNode = nextNode->leftN; /* 0 is left */
- }
- }
-
- /* Here we have reached a node where the bitMap index is lower than
- * its parent. This means it is pointing backward in the tree and
- * must therefore be a terminal node, being the only point than can
- * be reached with the bits seen so far. It is either the actual key
- * we wanted, or if that key is not in the trie it is another key
- * that is currently the only one that can be reached by those bits.
- * That situation would obviously change if the key was to be added
- * to the trie.
- *
- * Hence it only remains to test whether this is actually the key or not.
- */
- if (nextNode->key == key)
- {
- /* This was the key, so return the entry pointer
- */
- return nextNode->buckets;
- }
- else
- {
- return NULL; /* That key is not in the trie (note that we set the pointer to -1 if no payload) */
- }
-}
-
-
-static ANTLR3_BOOLEAN
-intTrieDel (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key)
-{
- pANTLR3_INT_TRIE_NODE p;
-
- p=trie->root;
- key = key;
-
- return ANTLR3_FALSE;
-}
-
-/** Add an entry into the INT trie.
- * Basically we descend the trie as we do when searching it, which will
- * locate the only node in the trie that can be reached by the bit pattern of the
- * key. If the key is actually at that node, then if the trie accepts duplicates
- * we add the supplied data in a new chained bucket to that data node. If it does
- * not accept duplicates then we merely return FALSE in case the caller wants to know
- * whether the key was already in the trie.
- * If the node we locate is not the key we are looking to add, then we insert a new node
- * into the trie with a bit index of the leftmost differing bit and the left or right
- * node pointing to itself or the data node we are inserting 'before'.
- */
-static ANTLR3_BOOLEAN
-intTrieAdd (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key, ANTLR3_UINT32 type, ANTLR3_INTKEY intVal, void * data, void (ANTLR3_CDECL *freeptr)(void *))
-{
- pANTLR3_INT_TRIE_NODE thisNode;
- pANTLR3_INT_TRIE_NODE nextNode;
- pANTLR3_INT_TRIE_NODE entNode;
- ANTLR3_UINT32 depth;
- pANTLR3_TRIE_ENTRY newEnt;
- pANTLR3_TRIE_ENTRY nextEnt;
- ANTLR3_INTKEY xorKey;
-
- /* Cache the bit depth of this trie, which is always the highest index,
- * which is in the root node
- */
- depth = trie->root->bitNum;
-
- thisNode = trie->root; /* Start with the root node */
- nextNode = trie->root->leftN; /* And assume we start to the left */
-
- /* Now find the only node that can be currently reached by the bits in the
- * key we are being asked to insert.
- */
- while (thisNode->bitNum > nextNode->bitNum)
- {
- /* Still descending the structure, next node becomes current.
- */
- thisNode = nextNode;
-
- if (key & bitMask[nextNode->bitNum])
- {
- /* Bit at the required index was 1, so travers the right node from here
- */
- nextNode = nextNode->rightN;
- }
- else
- {
- /* Bit at the required index was 0, so we traverse to the left
- */
- nextNode = nextNode->leftN;
- }
- }
- /* Here we have located the only node that can be reached by the
- * bits in the requested key. It could in fact be that key or the node
- * we need to use to insert the new key.
- */
- if (nextNode->key == key)
- {
- /* We have located an exact match, but we will only append to the bucket chain
- * if this trie accepts duplicate keys.
- */
- if (trie->allowDups ==ANTLR3_TRUE)
- {
- /* Yes, we are accepting duplicates
- */
- newEnt = (pANTLR3_TRIE_ENTRY)ANTLR3_CALLOC(1, sizeof(ANTLR3_TRIE_ENTRY));
-
- if (newEnt == NULL)
- {
- /* Out of memory, all we can do is return the fact that the insert failed.
- */
- return ANTLR3_FALSE;
- }
-
- /* Otherwise insert this in the chain
- */
- newEnt->type = type;
- newEnt->freeptr = freeptr;
- if (type == ANTLR3_HASH_TYPE_STR)
- {
- newEnt->data.ptr = data;
- }
- else
- {
- newEnt->data.intVal = intVal;
- }
-
- /* We want to be able to traverse the stored elements in the order that they were
- * added as duplicate keys. We might need to revise this opinion if we end up having many duplicate keys
- * as perhaps reverse order is just as good, so long as it is ordered.
- */
- nextEnt = nextNode->buckets;
- while (nextEnt->next != NULL)
- {
- nextEnt = nextEnt->next;
- }
- nextEnt->next = newEnt;
-
- trie->count++;
- return ANTLR3_TRUE;
- }
- else
- {
- /* We found the key is already there and we are not allowed duplicates in this
- * trie.
- */
- return ANTLR3_FALSE;
- }
- }
-
- /* Here we have discovered the only node that can be reached by the bits in the key
- * but we have found that this node is not the key we need to insert. We must find the
- * the leftmost bit by which the current key for that node and the new key we are going
- * to insert, differ. While this nested series of ifs may look a bit strange, experimentation
- * showed that it allows a machine code path that works well with predicated execution
- */
- xorKey = (key ^ nextNode->key); /* Gives 1 bits only where they differ then we find the left most 1 bit*/
-
- /* Most common case is a 32 bit key really
- */
-#ifdef ANTLR3_USE_64BIT
- if (xorKey & 0xFFFFFFFF00000000)
- {
- if (xorKey & 0xFFFF000000000000)
- {
- if (xorKey & 0xFF00000000000000)
- {
- depth = 56 + bitIndex[((xorKey & 0xFF00000000000000)>>56)];
- }
- else
- {
- depth = 48 + bitIndex[((xorKey & 0x00FF000000000000)>>48)];
- }
- }
- else
- {
- if (xorKey & 0x0000FF0000000000)
- {
- depth = 40 + bitIndex[((xorKey & 0x0000FF0000000000)>>40)];
- }
- else
- {
- depth = 32 + bitIndex[((xorKey & 0x000000FF00000000)>>32)];
- }
- }
- }
- else
-#endif
- {
- if (xorKey & 0x00000000FFFF0000)
- {
- if (xorKey & 0x00000000FF000000)
- {
- depth = 24 + bitIndex[((xorKey & 0x00000000FF000000)>>24)];
- }
- else
- {
- depth = 16 + bitIndex[((xorKey & 0x0000000000FF0000)>>16)];
- }
- }
- else
- {
- if (xorKey & 0x000000000000FF00)
- {
- depth = 8 + bitIndex[((xorKey & 0x0000000000000FF00)>>8)];
- }
- else
- {
- depth = bitIndex[xorKey & 0x00000000000000FF];
- }
- }
- }
-
- /* We have located the leftmost differing bit, indicated by the depth variable. So, we know what
- * bit index we are to insert the new entry at. There are two cases, being where the two keys
- * differ at a bit position that is not currently part of the bit testing, where they differ on a bit
- * that is currently being skipped in the indexed comparisons, and where they differ on a bit
- * that is merely lower down in the current bit search. If the bit index went bit 4, bit 2 and they differ
- * at bit 3, then we have the "skipped" bit case. But if that chain was Bit 4, Bit 2 and they differ at bit 1
- * then we have the easy bit <pun>.
- *
- * So, set up to descend the tree again, but this time looking for the insert point
- * according to whether we skip the bit that differs or not.
- */
- thisNode = trie->root;
- entNode = trie->root->leftN;
-
- /* Note the slight difference in the checks here to cover both cases
- */
- while (thisNode->bitNum > entNode->bitNum && entNode->bitNum > depth)
- {
- /* Still descending the structure, next node becomes current.
- */
- thisNode = entNode;
-
- if (key & bitMask[entNode->bitNum])
- {
- /* Bit at the required index was 1, so traverse the right node from here
- */
- entNode = entNode->rightN;
- }
- else
- {
- /* Bit at the required index was 0, so we traverse to the left
- */
- entNode = entNode->leftN;
- }
- }
-
- /* We have located the correct insert point for this new key, so we need
- * to allocate our entry and insert it etc.
- */
- nextNode = (pANTLR3_INT_TRIE_NODE)ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE_NODE));
- if (nextNode == NULL)
- {
- /* All that work and no memory - bummer.
- */
- return ANTLR3_FALSE;
- }
-
- /* Build a new entry block for the new node
- */
- newEnt = (pANTLR3_TRIE_ENTRY)ANTLR3_CALLOC(1, sizeof(ANTLR3_TRIE_ENTRY));
-
- if (newEnt == NULL)
- {
- /* Out of memory, all we can do is return the fact that the insert failed.
- */
- return ANTLR3_FALSE;
- }
-
- /* Otherwise enter this in our new node
- */
- newEnt->type = type;
- newEnt->freeptr = freeptr;
- if (type == ANTLR3_HASH_TYPE_STR)
- {
- newEnt->data.ptr = data;
- }
- else
- {
- newEnt->data.intVal = intVal;
- }
- /* Install it
- */
- nextNode->buckets = newEnt;
- nextNode->key = key;
- nextNode->bitNum = depth;
-
- /* Work out the right and left pointers for this new node, which involve
- * terminating with the current found node either right or left according
- * to whether the current index bit is 1 or 0
- */
- if (key & bitMask[depth])
- {
- nextNode->leftN = entNode; /* Terminates at previous position */
- nextNode->rightN = nextNode; /* Terminates with itself */
- }
- else
- {
- nextNode->rightN = entNode; /* Terminates at previous position */
- nextNode->leftN = nextNode; /* Terminates with itself */
- }
-
- /* Finally, we need to change the pointers at the node we located
- * for inserting. If the key bit at its index is set then the right
- * pointer for that node becomes the newly created node, otherwise the left
- * pointer does.
- */
- if (key & bitMask[thisNode->bitNum] )
- {
- thisNode->rightN = nextNode;
- }
- else
- {
- thisNode->leftN = nextNode;
- }
-
- /* Et voila
- */
- trie->count++;
- return ANTLR3_TRUE;
-
-}
-/** Release memory allocated to this tree.
- * Basic algorithm is that we do a depth first left descent and free
- * up any nodes that are not backward pointers.
- */
-static void
-freeIntNode(pANTLR3_INT_TRIE_NODE node)
-{
- pANTLR3_TRIE_ENTRY thisEntry;
- pANTLR3_TRIE_ENTRY nextEntry;
-
- /* If this node has a left pointer that is not a back pointer
- * then recursively call to free this
- */
- if (node->bitNum > node->leftN->bitNum)
- {
- /* We have a left node that needs descending, so do it.
- */
- freeIntNode(node->leftN);
- }
-
- /* The left nodes from here should now be dealt with, so
- * we need to descend any right nodes that are not back pointers
- */
- if (node->bitNum > node->rightN->bitNum)
- {
- /* There are some right nodes to descend and deal with.
- */
- freeIntNode(node->rightN);
- }
-
- /* Now all the children are dealt with, we can destroy
- * this node too
- */
- thisEntry = node->buckets;
-
- while (thisEntry != NULL)
- {
- nextEntry = thisEntry->next;
-
- /* Do we need to call a custom free pointer for this string entry?
- */
- if (thisEntry->type == ANTLR3_HASH_TYPE_STR && thisEntry->freeptr != NULL)
- {
- thisEntry->freeptr(thisEntry->data.ptr);
- }
-
- /* Now free the data for this bucket entry
- */
- ANTLR3_FREE(thisEntry);
- thisEntry = nextEntry; /* See if there are any more to free */
- }
-
- /* The bucket entry is now gone, so we can free the memory for
- * the entry itself.
- */
- ANTLR3_FREE(node);
-
- /* And that should be it for everything under this node and itself
- */
-}
-
-/** Called to free all nodes and the structure itself.
- */
-static void
-intTrieFree (pANTLR3_INT_TRIE trie)
-{
- /* Descend from the root and free all the nodes
- */
- freeIntNode(trie->root);
-
- /* the nodes are all gone now, so we need only free the memory
- * for the structure itself
- */
- ANTLR3_FREE(trie);
-}
-
-
-/**
- * Allocate and initialize a new ANTLR3 topological sorter, which can be
- * used to define edges that identify numerical node indexes that depend on other
- * numerical node indexes, which can then be sorted topologically such that
- * any node is sorted after all its dependent nodes.
- *
- * Use:
- *
- * /verbatim
-
- pANTLR3_TOPO topo;
- topo = antlr3NewTopo();
-
- if (topo == NULL) { out of memory }
-
- topo->addEdge(topo, 3, 0); // Node 3 depends on node 0
- topo->addEdge(topo, 0, 1); // Node - depends on node 1
- topo->sortVector(topo, myVector); // Sort the vector in place (node numbers are the vector entry numbers)
-
- * /verbatim
- */
-ANTLR3_API pANTLR3_TOPO
-antlr3TopoNew()
-{
- pANTLR3_TOPO topo = (pANTLR3_TOPO)ANTLR3_MALLOC(sizeof(ANTLR3_TOPO));
-
- if (topo == NULL)
- {
- return NULL;
- }
-
- // Initialize variables
- //
-
- topo->visited = NULL; // Don't know how big it is yet
- topo->limit = 1; // No edges added yet
- topo->edges = NULL; // No edges added yet
- topo->sorted = NULL; // Nothing sorted at the start
- topo->cycle = NULL; // No cycles at the start
- topo->cycleMark = 0; // No cycles at the start
- topo->hasCycle = ANTLR3_FALSE; // No cycle at the start
-
- // API
- //
- topo->addEdge = addEdge;
- topo->sortToArray = sortToArray;
- topo->sortVector = sortVector;
- topo->free = freeTopo;
-
- return topo;
-}
-// Topological sorter
-//
-static void
-addEdge (pANTLR3_TOPO topo, ANTLR3_UINT32 edge, ANTLR3_UINT32 dependency)
-{
- ANTLR3_UINT32 i;
- ANTLR3_UINT32 maxEdge;
- pANTLR3_BITSET edgeDeps;
-
- if (edge>dependency)
- {
- maxEdge = edge;
- }
- else
- {
- maxEdge = dependency;
- }
- // We need to add an edge to says that the node indexed by 'edge' is
- // dependent on the node indexed by 'dependency'
- //
-
- // First see if we have enough room in the edges array to add the edge?
- //
- if (topo->edges == NULL)
- {
- // We don't have any edges yet, so create an array to hold them
- //
- topo->edges = ANTLR3_CALLOC(sizeof(pANTLR3_BITSET) * (maxEdge + 1), 1);
- if (topo->edges == NULL)
- {
- return;
- }
-
- // Set the limit to what we have now
- //
- topo->limit = maxEdge + 1;
- }
- else if (topo->limit <= maxEdge)
- {
- // WE have some edges but not enough
- //
- topo->edges = ANTLR3_REALLOC(topo->edges, sizeof(pANTLR3_BITSET) * (maxEdge + 1));
- if (topo->edges == NULL)
- {
- return;
- }
-
- // Initialize the new bitmaps to ;indicate we have no edges defined yet
- //
- for (i = topo->limit; i <= maxEdge; i++)
- {
- *((topo->edges) + i) = NULL;
- }
-
- // Set the limit to what we have now
- //
- topo->limit = maxEdge + 1;
- }
-
- // If the edge was flagged as depending on itself, then we just
- // do nothing as it means this routine was just called to add it
- // in to the list of nodes.
- //
- if (edge == dependency)
- {
- return;
- }
-
- // Pick up the bit map for the requested edge
- //
- edgeDeps = *((topo->edges) + edge);
-
- if (edgeDeps == NULL)
- {
- // No edges are defined yet for this node
- //
- edgeDeps = antlr3BitsetNew(0);
- *((topo->edges) + edge) = edgeDeps;
- if (edgeDeps == NULL )
- {
- return; // Out of memory
- }
- }
-
- // Set the bit in the bitmap that corresponds to the requested
- // dependency.
- //
- edgeDeps->add(edgeDeps, dependency);
-
- // And we are all set
- //
- return;
-}
-
-
-/**
- * Given a starting node, descend its dependent nodes (ones that it has edges
- * to) until we find one without edges. Having found a node without edges, we have
- * discovered the bottom of a depth first search, which we can then ascend, adding
- * the nodes in order from the bottom, which gives us the dependency order.
- */
-static void
-DFS(pANTLR3_TOPO topo, ANTLR3_UINT32 node)
-{
- pANTLR3_BITSET edges;
-
- // Guard against a revisit and check for cycles
- //
- if (topo->hasCycle == ANTLR3_TRUE)
- {
- return; // We don't do anything else if we found a cycle
- }
-
- if (topo->visited->isMember(topo->visited, node))
- {
- // Check to see if we found a cycle. To do this we search the
- // current cycle stack and see if we find this node already in the stack.
- //
- ANTLR3_UINT32 i;
-
- for (i=0; i<topo->cycleMark; i++)
- {
- if (topo->cycle[i] == node)
- {
- // Stop! We found a cycle in the input, so rejig the cycle
- // stack so that it only contains the cycle and set the cycle flag
- // which will tell the caller what happened
- //
- ANTLR3_UINT32 l;
-
- for (l = i; l < topo->cycleMark; l++)
- {
- topo->cycle[l - i] = topo->cycle[l]; // Move to zero base in the cycle list
- }
-
- // Recalculate the limit
- //
- topo->cycleMark -= i;
-
- // Signal disaster
- //
- topo->hasCycle = ANTLR3_TRUE;
- }
- }
- return;
- }
-
- // So far, no cycles have been found and we have not visited this node yet,
- // so this node needs to go into the cycle stack before we continue
- // then we will take it out of the stack once we have descended all its
- // dependencies.
- //
- topo->cycle[topo->cycleMark++] = node;
-
- // First flag that we have visited this node
- //
- topo->visited->add(topo->visited, node);
-
- // Now, if this node has edges, then we want to ensure we visit
- // them all before we drop through and add this node into the sorted
- // list.
- //
- edges = *((topo->edges) + node);
- if (edges != NULL)
- {
- // We have some edges, so visit each of the edge nodes
- // that have not already been visited.
- //
- ANTLR3_UINT32 numBits; // How many bits are in the set
- ANTLR3_UINT32 i;
- ANTLR3_UINT32 range;
-
- numBits = edges->numBits(edges);
- range = edges->size(edges); // Number of set bits
-
- // Stop if we exahust the bit list or have checked the
- // number of edges that this node refers to (so we don't
- // check bits at the end that cannot possibly be set).
- //
- for (i=0; i<= numBits && range > 0; i++)
- {
- if (edges->isMember(edges, i))
- {
- range--; // About to check another one
-
- // Found an edge, make sure we visit and descend it
- //
- DFS(topo, i);
- }
- }
- }
-
- // At this point we will have visited all the dependencies
- // of this node and they will be ordered (even if there are cycles)
- // So we just add the node into the sorted list at the
- // current index position.
- //
- topo->sorted[topo->limit++] = node;
-
- // Remove this node from the cycle list if we have not detected a cycle
- //
- if (topo->hasCycle == ANTLR3_FALSE)
- {
- topo->cycleMark--;
- }
-
- return;
-}
-
-static pANTLR3_UINT32
-sortToArray (pANTLR3_TOPO topo)
-{
- ANTLR3_UINT32 v;
- ANTLR3_UINT32 oldLimit;
-
- // Guard against being called with no edges defined
- //
- if (topo->edges == NULL)
- {
- return 0;
- }
- // First we need a vector to populate with enough
- // entries to accomodate the sorted list and another to accomodate
- // the maximum cycle we could detect which is all nodes such as 0->1->2->3->0
- //
- topo->sorted = ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
- topo->cycle = ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
-
- // Next we need an empty bitset to show whether we have visited a node
- // or not. This is the bit that gives us linear time of course as we are essentially
- // dropping through the nodes in depth first order and when we get to a node that
- // has no edges, we pop back up the stack adding the nodes we traversed in reverse
- // order.
- //
- topo->visited = antlr3BitsetNew(0);
-
- // Now traverse the nodes as if we were just going left to right, but
- // then descend each node unless it has already been visited.
- //
- oldLimit = topo->limit; // Number of nodes to traverse linearly
- topo->limit = 0; // Next entry in the sorted table
-
- for (v = 0; v < oldLimit; v++)
- {
- // If we did not already visit this node, then descend it until we
- // get a node without edges or arrive at a node we have already visited.
- //
- if (topo->visited->isMember(topo->visited, v) == ANTLR3_FALSE)
- {
- // We have not visited this one so descend it
- //
- DFS(topo, v);
- }
-
- // Break the loop if we detect a cycle as we have no need to go any
- // further
- //
- if (topo->hasCycle == ANTLR3_TRUE)
- {
- break;
- }
- }
-
- // Reset the limit to the number we recorded as if we hit a
- // cycle, then limit will have stopped at the node where we
- // discovered the cycle, but in order to free the edge bitmaps
- // we need to know how many we may have allocated and traverse them all.
- //
- topo->limit = oldLimit;
-
- // Having traversed all the nodes we were given, we
- // are guaranteed to have ordered all the nodes or detected a
- // cycle.
- //
- return topo->sorted;
-}
-
-static void
-sortVector (pANTLR3_TOPO topo, pANTLR3_VECTOR v)
-{
- // To sort a vector, we first perform the
- // sort to an array, then use the results to reorder the vector
- // we are given. This is just a convenience routine that allows you to
- // sort the children of a tree node into topological order before or
- // during an AST walk. This can be useful for optimizations that require
- // dag reorders and also when the input stream defines thigns that are
- // interdependent and you want to walk the list of the generated trees
- // for those things in topological order so you can ignore the interdependencies
- // at that point.
- //
- ANTLR3_UINT32 i;
-
- // Used as a lookup index to find the current location in the vector of
- // the vector entry that was originally at position [0], [1], [2] etc
- //
- pANTLR3_UINT32 vIndex;
-
- // Sort into an array, then we can use the array that is
- // stored in the topo
- //
- if (topo->sortToArray(topo) == 0)
- {
- return; // There were no edges
- }
-
- if (topo->hasCycle == ANTLR3_TRUE)
- {
- return; // Do nothing if we detected a cycle
- }
-
- // Ensure that the vector we are sorting is at least as big as the
- // the input sequence we were adsked to sort. It does not matter if it is
- // bigger as thaat probably just means that nodes numbered higher than the
- // limit had no dependencies and so can be left alone.
- //
- if (topo->limit > v->count)
- {
- // We can only sort the entries that we have dude! The caller is
- // responsible for ensuring the vector is the correct one and is the
- // correct size etc.
- //
- topo->limit = v->count;
- }
- // We need to know the locations of each of the entries
- // in the vector as we don't want to duplicate them in a new vector. We
- // just use an indirection table to get the vector entry for a particular sequence
- // acording to where we moved it last. Then we can just swap vector entries until
- // we are done :-)
- //
- vIndex = ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
-
- // Start index, each vector entry is located where you think it is
- //
- for (i = 0; i < topo->limit; i++)
- {
- vIndex[i] = i;
- }
-
- // Now we traverse the sorted array and moved the entries of
- // the vector around according to the sort order and the indirection
- // table we just created. The index telsl us where in the vector the
- // original element entry n is now located via vIndex[n].
- //
- for (i=0; i < topo->limit; i++)
- {
- ANTLR3_UINT32 ind;
-
- // If the vector entry at i is already the one that it
- // should be, then we skip moving it of course.
- //
- if (vIndex[topo->sorted[i]] == i)
- {
- continue;
- }
-
- // The vector entry at i, should be replaced with the
- // vector entry indicated by topo->sorted[i]. The vector entry
- // at topo->sorted[i] may have already been swapped out though, so we
- // find where it is now and move it from there to i.
- //
- ind = vIndex[topo->sorted[i]];
- v->swap(v, i, ind);
-
- // Update our index. The element at i is now the one we wanted
- // to be sorted here and the element we swapped out is now the
- // element that was at i just before we swapped it. If you are lost now
- // don't worry about it, we are just reindexing on the fly is all.
- //
- vIndex[topo->sorted[i]] = i;
- vIndex[i] = ind;
- }
-
- // Having traversed all the entries, we have sorted the vector in place.
- //
- ANTLR3_FREE(vIndex);
- return;
-}
-
-static void
-freeTopo (pANTLR3_TOPO topo)
-{
- ANTLR3_UINT32 i;
-
- // Free the result vector
- //
- if (topo->sorted != NULL)
- {
- ANTLR3_FREE(topo->sorted);
- topo->sorted = NULL;
- }
-
- // Free the visited map
- //
- if (topo->visited != NULL)
- {
-
- topo->visited->free(topo->visited);
- topo->visited = NULL;
- }
-
- // Free any edgemaps
- //
- if (topo->edges != NULL)
- {
- pANTLR3_BITSET edgeList;
-
-
- for (i=0; i<topo->limit; i++)
- {
- edgeList = *((topo->edges) + i);
- if (edgeList != NULL)
- {
- edgeList->free(edgeList);
- }
- }
-
- ANTLR3_FREE(topo->edges);
- }
- topo->edges = NULL;
-
- // Free any cycle map
- //
- if (topo->cycle != NULL)
- {
- ANTLR3_FREE(topo->cycle);
- }
-
- ANTLR3_FREE(topo);
-}