1*16467b97STreehugger Robot /// \file
2*16467b97STreehugger Robot /// Provides a number of useful functions that are roughly equivalent
3*16467b97STreehugger Robot /// to java HashTable and List for the purposes of Antlr 3 C runtime.
4*16467b97STreehugger Robot /// Also useable by the C programmer for things like symbol tables pointers
5*16467b97STreehugger Robot /// and so on.
6*16467b97STreehugger Robot ///
7*16467b97STreehugger Robot ///
8*16467b97STreehugger Robot
9*16467b97STreehugger Robot // [The "BSD licence"]
10*16467b97STreehugger Robot // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
11*16467b97STreehugger Robot // http://www.temporal-wave.com
12*16467b97STreehugger Robot // http://www.linkedin.com/in/jimidle
13*16467b97STreehugger Robot //
14*16467b97STreehugger Robot // All rights reserved.
15*16467b97STreehugger Robot //
16*16467b97STreehugger Robot // Redistribution and use in source and binary forms, with or without
17*16467b97STreehugger Robot // modification, are permitted provided that the following conditions
18*16467b97STreehugger Robot // are met:
19*16467b97STreehugger Robot // 1. Redistributions of source code must retain the above copyright
20*16467b97STreehugger Robot // notice, this list of conditions and the following disclaimer.
21*16467b97STreehugger Robot // 2. Redistributions in binary form must reproduce the above copyright
22*16467b97STreehugger Robot // notice, this list of conditions and the following disclaimer in the
23*16467b97STreehugger Robot // documentation and/or other materials provided with the distribution.
24*16467b97STreehugger Robot // 3. The name of the author may not be used to endorse or promote products
25*16467b97STreehugger Robot // derived from this software without specific prior written permission.
26*16467b97STreehugger Robot //
27*16467b97STreehugger Robot // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28*16467b97STreehugger Robot // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29*16467b97STreehugger Robot // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30*16467b97STreehugger Robot // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31*16467b97STreehugger Robot // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32*16467b97STreehugger Robot // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33*16467b97STreehugger Robot // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34*16467b97STreehugger Robot // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35*16467b97STreehugger Robot // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36*16467b97STreehugger Robot // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*16467b97STreehugger Robot
38*16467b97STreehugger Robot #include <antlr3.h>
39*16467b97STreehugger Robot
40*16467b97STreehugger Robot #include "antlr3collections.h"
41*16467b97STreehugger Robot
42*16467b97STreehugger Robot // Interface functions for hash table
43*16467b97STreehugger Robot //
44*16467b97STreehugger Robot
45*16467b97STreehugger Robot // String based keys
46*16467b97STreehugger Robot //
47*16467b97STreehugger Robot static void antlr3HashDelete (pANTLR3_HASH_TABLE table, void * key);
48*16467b97STreehugger Robot static void * antlr3HashGet (pANTLR3_HASH_TABLE table, void * key);
49*16467b97STreehugger Robot static pANTLR3_HASH_ENTRY antlr3HashRemove (pANTLR3_HASH_TABLE table, void * key);
50*16467b97STreehugger Robot static ANTLR3_INT32 antlr3HashPut (pANTLR3_HASH_TABLE table, void * key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
51*16467b97STreehugger Robot
52*16467b97STreehugger Robot // Integer based keys (Lists and so on)
53*16467b97STreehugger Robot //
54*16467b97STreehugger Robot static void antlr3HashDeleteI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
55*16467b97STreehugger Robot static void * antlr3HashGetI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
56*16467b97STreehugger Robot static pANTLR3_HASH_ENTRY antlr3HashRemoveI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key);
57*16467b97STreehugger Robot static ANTLR3_INT32 antlr3HashPutI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
58*16467b97STreehugger Robot
59*16467b97STreehugger Robot static void antlr3HashFree (pANTLR3_HASH_TABLE table);
60*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3HashSize (pANTLR3_HASH_TABLE table);
61*16467b97STreehugger Robot
62*16467b97STreehugger Robot // -----------
63*16467b97STreehugger Robot
64*16467b97STreehugger Robot // Interface functions for enumeration
65*16467b97STreehugger Robot //
66*16467b97STreehugger Robot static int antlr3EnumNext (pANTLR3_HASH_ENUM en, pANTLR3_HASH_KEY * key, void ** data);
67*16467b97STreehugger Robot static void antlr3EnumFree (pANTLR3_HASH_ENUM en);
68*16467b97STreehugger Robot
69*16467b97STreehugger Robot // Interface functions for List
70*16467b97STreehugger Robot //
71*16467b97STreehugger Robot static void antlr3ListFree (pANTLR3_LIST list);
72*16467b97STreehugger Robot static void antlr3ListDelete(pANTLR3_LIST list, ANTLR3_INTKEY key);
73*16467b97STreehugger Robot static void * antlr3ListGet (pANTLR3_LIST list, ANTLR3_INTKEY key);
74*16467b97STreehugger Robot static ANTLR3_INT32 antlr3ListPut (pANTLR3_LIST list, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *));
75*16467b97STreehugger Robot static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (ANTLR3_CDECL *freeptr)(void *));
76*16467b97STreehugger Robot static void * antlr3ListRemove(pANTLR3_LIST list, ANTLR3_INTKEY key);
77*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3ListSize (pANTLR3_LIST list);
78*16467b97STreehugger Robot
79*16467b97STreehugger Robot // Interface functions for Stack
80*16467b97STreehugger Robot //
81*16467b97STreehugger Robot static void antlr3StackFree (pANTLR3_STACK stack);
82*16467b97STreehugger Robot static void * antlr3StackPop (pANTLR3_STACK stack);
83*16467b97STreehugger Robot static void * antlr3StackGet (pANTLR3_STACK stack, ANTLR3_INTKEY key);
84*16467b97STreehugger Robot static ANTLR3_BOOLEAN antlr3StackPush (pANTLR3_STACK stack, void * element, void (ANTLR3_CDECL *freeptr)(void *));
85*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3StackSize (pANTLR3_STACK stack);
86*16467b97STreehugger Robot static void * antlr3StackPeek (pANTLR3_STACK stack);
87*16467b97STreehugger Robot
88*16467b97STreehugger Robot // Interface functions for vectors
89*16467b97STreehugger Robot //
90*16467b97STreehugger Robot static void ANTLR3_CDECL antlr3VectorFree (pANTLR3_VECTOR vector);
91*16467b97STreehugger Robot static void antlr3VectorDel (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
92*16467b97STreehugger Robot static void * antlr3VectorGet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
93*16467b97STreehugger Robot static void * antrl3VectorRemove (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry);
94*16467b97STreehugger Robot static void antlr3VectorClear (pANTLR3_VECTOR vector);
95*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3VectorAdd (pANTLR3_VECTOR vector, void * element, void (ANTLR3_CDECL *freeptr)(void *));
96*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3VectorSet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry, void * element, void (ANTLR3_CDECL *freeptr)(void *), ANTLR3_BOOLEAN freeExisting);
97*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3VectorSize (pANTLR3_VECTOR vector);
98*16467b97STreehugger Robot static ANTLR3_BOOLEAN antlr3VectorSwap (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry1, ANTLR3_UINT32 entry2);
99*16467b97STreehugger Robot
100*16467b97STreehugger Robot static ANTLR3_BOOLEAN newPool (pANTLR3_VECTOR_FACTORY factory);
101*16467b97STreehugger Robot static void closeVectorFactory (pANTLR3_VECTOR_FACTORY factory);
102*16467b97STreehugger Robot static pANTLR3_VECTOR newVector (pANTLR3_VECTOR_FACTORY factory);
103*16467b97STreehugger Robot static void returnVector (pANTLR3_VECTOR_FACTORY factory, pANTLR3_VECTOR vector);
104*16467b97STreehugger Robot
105*16467b97STreehugger Robot
106*16467b97STreehugger Robot // Interface functions for int TRIE
107*16467b97STreehugger Robot //
108*16467b97STreehugger Robot static pANTLR3_TRIE_ENTRY intTrieGet (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key);
109*16467b97STreehugger Robot static ANTLR3_BOOLEAN intTrieDel (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key);
110*16467b97STreehugger Robot static ANTLR3_BOOLEAN intTrieAdd (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key, ANTLR3_UINT32 type, ANTLR3_INTKEY intType, void * data, void (ANTLR3_CDECL *freeptr)(void *));
111*16467b97STreehugger Robot static void intTrieFree (pANTLR3_INT_TRIE trie);
112*16467b97STreehugger Robot
113*16467b97STreehugger Robot
114*16467b97STreehugger Robot // Interface functions for topological sorter
115*16467b97STreehugger Robot //
116*16467b97STreehugger Robot static void addEdge (pANTLR3_TOPO topo, ANTLR3_UINT32 edge, ANTLR3_UINT32 dependency);
117*16467b97STreehugger Robot static pANTLR3_UINT32 sortToArray (pANTLR3_TOPO topo);
118*16467b97STreehugger Robot static void sortVector (pANTLR3_TOPO topo, pANTLR3_VECTOR v);
119*16467b97STreehugger Robot static void freeTopo (pANTLR3_TOPO topo);
120*16467b97STreehugger Robot
121*16467b97STreehugger Robot // Local function to advance enumeration structure pointers
122*16467b97STreehugger Robot //
123*16467b97STreehugger Robot static void antlr3EnumNextEntry(pANTLR3_HASH_ENUM en);
124*16467b97STreehugger Robot
125*16467b97STreehugger Robot pANTLR3_HASH_TABLE
antlr3HashTableNew(ANTLR3_UINT32 sizeHint)126*16467b97STreehugger Robot antlr3HashTableNew(ANTLR3_UINT32 sizeHint)
127*16467b97STreehugger Robot {
128*16467b97STreehugger Robot // All we have to do is create the hashtable tracking structure
129*16467b97STreehugger Robot // and allocate memory for the requested number of buckets.
130*16467b97STreehugger Robot //
131*16467b97STreehugger Robot pANTLR3_HASH_TABLE table;
132*16467b97STreehugger Robot
133*16467b97STreehugger Robot ANTLR3_UINT32 bucket; // Used to traverse the buckets
134*16467b97STreehugger Robot
135*16467b97STreehugger Robot table = (pANTLR3_HASH_TABLE)ANTLR3_MALLOC(sizeof(ANTLR3_HASH_TABLE));
136*16467b97STreehugger Robot
137*16467b97STreehugger Robot // Error out if no memory left
138*16467b97STreehugger Robot if (table == NULL)
139*16467b97STreehugger Robot {
140*16467b97STreehugger Robot return NULL;
141*16467b97STreehugger Robot }
142*16467b97STreehugger Robot
143*16467b97STreehugger Robot // Allocate memory for the buckets
144*16467b97STreehugger Robot //
145*16467b97STreehugger Robot table->buckets = (pANTLR3_HASH_BUCKET) ANTLR3_MALLOC((size_t) (sizeof(ANTLR3_HASH_BUCKET) * sizeHint));
146*16467b97STreehugger Robot
147*16467b97STreehugger Robot if (table->buckets == NULL)
148*16467b97STreehugger Robot {
149*16467b97STreehugger Robot ANTLR3_FREE((void *)table);
150*16467b97STreehugger Robot return NULL;
151*16467b97STreehugger Robot }
152*16467b97STreehugger Robot
153*16467b97STreehugger Robot // Modulo of the table, (bucket count).
154*16467b97STreehugger Robot //
155*16467b97STreehugger Robot table->modulo = sizeHint;
156*16467b97STreehugger Robot
157*16467b97STreehugger Robot table->count = 0; /* Nothing in there yet ( I hope) */
158*16467b97STreehugger Robot
159*16467b97STreehugger Robot /* Initialize the buckets to empty
160*16467b97STreehugger Robot */
161*16467b97STreehugger Robot for (bucket = 0; bucket < sizeHint; bucket++)
162*16467b97STreehugger Robot {
163*16467b97STreehugger Robot table->buckets[bucket].entries = NULL;
164*16467b97STreehugger Robot }
165*16467b97STreehugger Robot
166*16467b97STreehugger Robot /* Exclude duplicate entries by default
167*16467b97STreehugger Robot */
168*16467b97STreehugger Robot table->allowDups = ANTLR3_FALSE;
169*16467b97STreehugger Robot
170*16467b97STreehugger Robot /* Assume that keys should by strduped before they are
171*16467b97STreehugger Robot * entered in the table.
172*16467b97STreehugger Robot */
173*16467b97STreehugger Robot table->doStrdup = ANTLR3_TRUE;
174*16467b97STreehugger Robot
175*16467b97STreehugger Robot /* Install the interface
176*16467b97STreehugger Robot */
177*16467b97STreehugger Robot
178*16467b97STreehugger Robot table->get = antlr3HashGet;
179*16467b97STreehugger Robot table->put = antlr3HashPut;
180*16467b97STreehugger Robot table->del = antlr3HashDelete;
181*16467b97STreehugger Robot table->remove = antlr3HashRemove;
182*16467b97STreehugger Robot
183*16467b97STreehugger Robot table->getI = antlr3HashGetI;
184*16467b97STreehugger Robot table->putI = antlr3HashPutI;
185*16467b97STreehugger Robot table->delI = antlr3HashDeleteI;
186*16467b97STreehugger Robot table->removeI = antlr3HashRemoveI;
187*16467b97STreehugger Robot
188*16467b97STreehugger Robot table->size = antlr3HashSize;
189*16467b97STreehugger Robot table->free = antlr3HashFree;
190*16467b97STreehugger Robot
191*16467b97STreehugger Robot return table;
192*16467b97STreehugger Robot }
193*16467b97STreehugger Robot
194*16467b97STreehugger Robot static void
antlr3HashFree(pANTLR3_HASH_TABLE table)195*16467b97STreehugger Robot antlr3HashFree(pANTLR3_HASH_TABLE table)
196*16467b97STreehugger Robot {
197*16467b97STreehugger Robot ANTLR3_UINT32 bucket; /* Used to traverse the buckets */
198*16467b97STreehugger Robot
199*16467b97STreehugger Robot pANTLR3_HASH_BUCKET thisBucket;
200*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
201*16467b97STreehugger Robot pANTLR3_HASH_ENTRY nextEntry;
202*16467b97STreehugger Robot
203*16467b97STreehugger Robot /* Free the table, all buckets and all entries, and all the
204*16467b97STreehugger Robot * keys and data (if the table exists)
205*16467b97STreehugger Robot */
206*16467b97STreehugger Robot if (table != NULL)
207*16467b97STreehugger Robot {
208*16467b97STreehugger Robot for (bucket = 0; bucket < table->modulo; bucket++)
209*16467b97STreehugger Robot {
210*16467b97STreehugger Robot thisBucket = &(table->buckets[bucket]);
211*16467b97STreehugger Robot
212*16467b97STreehugger Robot /* Allow sparse tables, though we don't create them as such at present
213*16467b97STreehugger Robot */
214*16467b97STreehugger Robot if ( thisBucket != NULL)
215*16467b97STreehugger Robot {
216*16467b97STreehugger Robot entry = thisBucket->entries;
217*16467b97STreehugger Robot
218*16467b97STreehugger Robot /* Search all entries in the bucket and free them up
219*16467b97STreehugger Robot */
220*16467b97STreehugger Robot while (entry != NULL)
221*16467b97STreehugger Robot {
222*16467b97STreehugger Robot /* Save next entry - we do not want to access memory in entry after we
223*16467b97STreehugger Robot * have freed it.
224*16467b97STreehugger Robot */
225*16467b97STreehugger Robot nextEntry = entry->nextEntry;
226*16467b97STreehugger Robot
227*16467b97STreehugger Robot /* Free any data pointer, this only happens if the user supplied
228*16467b97STreehugger Robot * a pointer to a routine that knwos how to free the structure they
229*16467b97STreehugger Robot * added to the table.
230*16467b97STreehugger Robot */
231*16467b97STreehugger Robot if (entry->free != NULL)
232*16467b97STreehugger Robot {
233*16467b97STreehugger Robot entry->free(entry->data);
234*16467b97STreehugger Robot }
235*16467b97STreehugger Robot
236*16467b97STreehugger Robot /* Free the key memory - we know that we allocated this
237*16467b97STreehugger Robot */
238*16467b97STreehugger Robot if (entry->keybase.type == ANTLR3_HASH_TYPE_STR && entry->keybase.key.sKey != NULL)
239*16467b97STreehugger Robot {
240*16467b97STreehugger Robot ANTLR3_FREE(entry->keybase.key.sKey);
241*16467b97STreehugger Robot }
242*16467b97STreehugger Robot
243*16467b97STreehugger Robot /* Free this entry
244*16467b97STreehugger Robot */
245*16467b97STreehugger Robot ANTLR3_FREE(entry);
246*16467b97STreehugger Robot entry = nextEntry; /* Load next pointer to see if we shoud free it */
247*16467b97STreehugger Robot }
248*16467b97STreehugger Robot /* Invalidate the current pointer
249*16467b97STreehugger Robot */
250*16467b97STreehugger Robot thisBucket->entries = NULL;
251*16467b97STreehugger Robot }
252*16467b97STreehugger Robot }
253*16467b97STreehugger Robot
254*16467b97STreehugger Robot /* Now we can free the bucket memory
255*16467b97STreehugger Robot */
256*16467b97STreehugger Robot ANTLR3_FREE(table->buckets);
257*16467b97STreehugger Robot }
258*16467b97STreehugger Robot
259*16467b97STreehugger Robot /* Now we free teh memory for the table itself
260*16467b97STreehugger Robot */
261*16467b97STreehugger Robot ANTLR3_FREE(table);
262*16467b97STreehugger Robot }
263*16467b97STreehugger Robot
264*16467b97STreehugger Robot /** return the current size of the hash table
265*16467b97STreehugger Robot */
antlr3HashSize(pANTLR3_HASH_TABLE table)266*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3HashSize (pANTLR3_HASH_TABLE table)
267*16467b97STreehugger Robot {
268*16467b97STreehugger Robot return table->count;
269*16467b97STreehugger Robot }
270*16467b97STreehugger Robot
271*16467b97STreehugger Robot /** Remove a numeric keyed entry from a hash table if it exists,
272*16467b97STreehugger Robot * no error if it does not exist.
273*16467b97STreehugger Robot */
antlr3HashRemoveI(pANTLR3_HASH_TABLE table,ANTLR3_INTKEY key)274*16467b97STreehugger Robot static pANTLR3_HASH_ENTRY antlr3HashRemoveI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
275*16467b97STreehugger Robot {
276*16467b97STreehugger Robot ANTLR3_UINT32 hash;
277*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
278*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
279*16467b97STreehugger Robot pANTLR3_HASH_ENTRY * nextPointer;
280*16467b97STreehugger Robot
281*16467b97STreehugger Robot /* First we need to know the hash of the provided key
282*16467b97STreehugger Robot */
283*16467b97STreehugger Robot hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
284*16467b97STreehugger Robot
285*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
286*16467b97STreehugger Robot */
287*16467b97STreehugger Robot bucket = table->buckets + hash;
288*16467b97STreehugger Robot
289*16467b97STreehugger Robot /* Now, we traverse the entries in the bucket until
290*16467b97STreehugger Robot * we find the key or the end of the entries in the bucket.
291*16467b97STreehugger Robot * We track the element prior to the one we are examining
292*16467b97STreehugger Robot * as we need to set its next pointer to the next pointer
293*16467b97STreehugger Robot * of the entry we are deleting (if we find it).
294*16467b97STreehugger Robot */
295*16467b97STreehugger Robot entry = bucket->entries; /* Entry to examine */
296*16467b97STreehugger Robot nextPointer = & bucket->entries; /* Where to put the next pointer of the deleted entry */
297*16467b97STreehugger Robot
298*16467b97STreehugger Robot while (entry != NULL)
299*16467b97STreehugger Robot {
300*16467b97STreehugger Robot /* See if this is the entry we wish to delete
301*16467b97STreehugger Robot */
302*16467b97STreehugger Robot if (entry->keybase.key.iKey == key)
303*16467b97STreehugger Robot {
304*16467b97STreehugger Robot /* It was the correct entry, so we set the next pointer
305*16467b97STreehugger Robot * of the previous entry to the next pointer of this
306*16467b97STreehugger Robot * located one, which takes it out of the chain.
307*16467b97STreehugger Robot */
308*16467b97STreehugger Robot (*nextPointer) = entry->nextEntry;
309*16467b97STreehugger Robot
310*16467b97STreehugger Robot table->count--;
311*16467b97STreehugger Robot
312*16467b97STreehugger Robot return entry;
313*16467b97STreehugger Robot }
314*16467b97STreehugger Robot else
315*16467b97STreehugger Robot {
316*16467b97STreehugger Robot /* We found an entry but it wasn't the one that was wanted, so
317*16467b97STreehugger Robot * move to the next one, if any.
318*16467b97STreehugger Robot */
319*16467b97STreehugger Robot nextPointer = & (entry->nextEntry); /* Address of the next pointer in the current entry */
320*16467b97STreehugger Robot entry = entry->nextEntry; /* Address of the next element in the bucket (if any) */
321*16467b97STreehugger Robot }
322*16467b97STreehugger Robot }
323*16467b97STreehugger Robot
324*16467b97STreehugger Robot return NULL; /* Not found */
325*16467b97STreehugger Robot }
326*16467b97STreehugger Robot
327*16467b97STreehugger Robot /** Remove the element in the hash table for a particular
328*16467b97STreehugger Robot * key value, if it exists - no error if it does not.
329*16467b97STreehugger Robot */
330*16467b97STreehugger Robot static pANTLR3_HASH_ENTRY
antlr3HashRemove(pANTLR3_HASH_TABLE table,void * key)331*16467b97STreehugger Robot antlr3HashRemove(pANTLR3_HASH_TABLE table, void * key)
332*16467b97STreehugger Robot {
333*16467b97STreehugger Robot ANTLR3_UINT32 hash;
334*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
335*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
336*16467b97STreehugger Robot pANTLR3_HASH_ENTRY * nextPointer;
337*16467b97STreehugger Robot
338*16467b97STreehugger Robot /* First we need to know the hash of the provided key
339*16467b97STreehugger Robot */
340*16467b97STreehugger Robot hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
341*16467b97STreehugger Robot
342*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
343*16467b97STreehugger Robot */
344*16467b97STreehugger Robot bucket = table->buckets + (hash % table->modulo);
345*16467b97STreehugger Robot
346*16467b97STreehugger Robot /* Now, we traverse the entries in the bucket until
347*16467b97STreehugger Robot * we find the key or the end of the entires in the bucket.
348*16467b97STreehugger Robot * We track the element prior to the one we are exmaining
349*16467b97STreehugger Robot * as we need to set its next pointer to the next pointer
350*16467b97STreehugger Robot * of the entry we are deleting (if we find it).
351*16467b97STreehugger Robot */
352*16467b97STreehugger Robot entry = bucket->entries; /* Entry to examine */
353*16467b97STreehugger Robot nextPointer = & bucket->entries; /* Where to put the next pointer of the deleted entry */
354*16467b97STreehugger Robot
355*16467b97STreehugger Robot while (entry != NULL)
356*16467b97STreehugger Robot {
357*16467b97STreehugger Robot /* See if this is the entry we wish to delete
358*16467b97STreehugger Robot */
359*16467b97STreehugger Robot if (strcmp((const char *)key, (const char *)entry->keybase.key.sKey) == 0)
360*16467b97STreehugger Robot {
361*16467b97STreehugger Robot /* It was the correct entry, so we set the next pointer
362*16467b97STreehugger Robot * of the previous entry to the next pointer of this
363*16467b97STreehugger Robot * located one, which takes it out of the chain.
364*16467b97STreehugger Robot */
365*16467b97STreehugger Robot (*nextPointer) = entry->nextEntry;
366*16467b97STreehugger Robot
367*16467b97STreehugger Robot /* Release the key - if we allocated that
368*16467b97STreehugger Robot */
369*16467b97STreehugger Robot if (table->doStrdup == ANTLR3_TRUE)
370*16467b97STreehugger Robot {
371*16467b97STreehugger Robot ANTLR3_FREE(entry->keybase.key.sKey);
372*16467b97STreehugger Robot }
373*16467b97STreehugger Robot entry->keybase.key.sKey = NULL;
374*16467b97STreehugger Robot
375*16467b97STreehugger Robot table->count--;
376*16467b97STreehugger Robot
377*16467b97STreehugger Robot return entry;
378*16467b97STreehugger Robot }
379*16467b97STreehugger Robot else
380*16467b97STreehugger Robot {
381*16467b97STreehugger Robot /* We found an entry but it wasn't the one that was wanted, so
382*16467b97STreehugger Robot * move to the next one, if any.
383*16467b97STreehugger Robot */
384*16467b97STreehugger Robot nextPointer = & (entry->nextEntry); /* Address of the next pointer in the current entry */
385*16467b97STreehugger Robot entry = entry->nextEntry; /* Address of the next element in the bucket (if any) */
386*16467b97STreehugger Robot }
387*16467b97STreehugger Robot }
388*16467b97STreehugger Robot
389*16467b97STreehugger Robot return NULL; /* Not found */
390*16467b97STreehugger Robot }
391*16467b97STreehugger Robot
392*16467b97STreehugger Robot /** Takes the element with the supplied key out of the list, and deletes the data
393*16467b97STreehugger Robot * calling the supplied free() routine if any.
394*16467b97STreehugger Robot */
395*16467b97STreehugger Robot static void
antlr3HashDeleteI(pANTLR3_HASH_TABLE table,ANTLR3_INTKEY key)396*16467b97STreehugger Robot antlr3HashDeleteI (pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
397*16467b97STreehugger Robot {
398*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
399*16467b97STreehugger Robot
400*16467b97STreehugger Robot entry = antlr3HashRemoveI(table, key);
401*16467b97STreehugger Robot
402*16467b97STreehugger Robot /* Now we can free the elements and the entry in order
403*16467b97STreehugger Robot */
404*16467b97STreehugger Robot if (entry != NULL && entry->free != NULL)
405*16467b97STreehugger Robot {
406*16467b97STreehugger Robot /* Call programmer supplied function to release this entry data
407*16467b97STreehugger Robot */
408*16467b97STreehugger Robot entry->free(entry->data);
409*16467b97STreehugger Robot entry->data = NULL;
410*16467b97STreehugger Robot }
411*16467b97STreehugger Robot /* Finally release the space for this entry block.
412*16467b97STreehugger Robot */
413*16467b97STreehugger Robot ANTLR3_FREE(entry);
414*16467b97STreehugger Robot }
415*16467b97STreehugger Robot
416*16467b97STreehugger Robot /** Takes the element with the supplied key out of the list, and deletes the data
417*16467b97STreehugger Robot * calling the supplied free() routine if any.
418*16467b97STreehugger Robot */
419*16467b97STreehugger Robot static void
antlr3HashDelete(pANTLR3_HASH_TABLE table,void * key)420*16467b97STreehugger Robot antlr3HashDelete (pANTLR3_HASH_TABLE table, void * key)
421*16467b97STreehugger Robot {
422*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
423*16467b97STreehugger Robot
424*16467b97STreehugger Robot entry = antlr3HashRemove(table, key);
425*16467b97STreehugger Robot
426*16467b97STreehugger Robot /* Now we can free the elements and the entry in order
427*16467b97STreehugger Robot */
428*16467b97STreehugger Robot if (entry != NULL && entry->free != NULL)
429*16467b97STreehugger Robot {
430*16467b97STreehugger Robot /* Call programmer supplied function to release this entry data
431*16467b97STreehugger Robot */
432*16467b97STreehugger Robot entry->free(entry->data);
433*16467b97STreehugger Robot entry->data = NULL;
434*16467b97STreehugger Robot }
435*16467b97STreehugger Robot /* Finally release the space for this entry block.
436*16467b97STreehugger Robot */
437*16467b97STreehugger Robot ANTLR3_FREE(entry);
438*16467b97STreehugger Robot }
439*16467b97STreehugger Robot
440*16467b97STreehugger Robot /** Return the element pointer in the hash table for a particular
441*16467b97STreehugger Robot * key value, or NULL if it don't exist (or was itself NULL).
442*16467b97STreehugger Robot */
443*16467b97STreehugger Robot static void *
antlr3HashGetI(pANTLR3_HASH_TABLE table,ANTLR3_INTKEY key)444*16467b97STreehugger Robot antlr3HashGetI(pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key)
445*16467b97STreehugger Robot {
446*16467b97STreehugger Robot ANTLR3_UINT32 hash;
447*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
448*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
449*16467b97STreehugger Robot
450*16467b97STreehugger Robot /* First we need to know the hash of the provided key
451*16467b97STreehugger Robot */
452*16467b97STreehugger Robot hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
453*16467b97STreehugger Robot
454*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
455*16467b97STreehugger Robot */
456*16467b97STreehugger Robot bucket = table->buckets + hash;
457*16467b97STreehugger Robot
458*16467b97STreehugger Robot /* Now we can inspect the key at each entry in the bucket
459*16467b97STreehugger Robot * and see if we have a match.
460*16467b97STreehugger Robot */
461*16467b97STreehugger Robot entry = bucket->entries;
462*16467b97STreehugger Robot
463*16467b97STreehugger Robot while (entry != NULL)
464*16467b97STreehugger Robot {
465*16467b97STreehugger Robot if (entry->keybase.key.iKey == key)
466*16467b97STreehugger Robot {
467*16467b97STreehugger Robot /* Match was found, return the data pointer for this entry
468*16467b97STreehugger Robot */
469*16467b97STreehugger Robot return entry->data;
470*16467b97STreehugger Robot }
471*16467b97STreehugger Robot entry = entry->nextEntry;
472*16467b97STreehugger Robot }
473*16467b97STreehugger Robot
474*16467b97STreehugger Robot /* If we got here, then we did not find the key
475*16467b97STreehugger Robot */
476*16467b97STreehugger Robot return NULL;
477*16467b97STreehugger Robot }
478*16467b97STreehugger Robot
479*16467b97STreehugger Robot /** Return the element pointer in the hash table for a particular
480*16467b97STreehugger Robot * key value, or NULL if it don't exist (or was itself NULL).
481*16467b97STreehugger Robot */
482*16467b97STreehugger Robot static void *
antlr3HashGet(pANTLR3_HASH_TABLE table,void * key)483*16467b97STreehugger Robot antlr3HashGet(pANTLR3_HASH_TABLE table, void * key)
484*16467b97STreehugger Robot {
485*16467b97STreehugger Robot ANTLR3_UINT32 hash;
486*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
487*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
488*16467b97STreehugger Robot
489*16467b97STreehugger Robot
490*16467b97STreehugger Robot /* First we need to know the hash of the provided key
491*16467b97STreehugger Robot */
492*16467b97STreehugger Robot hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
493*16467b97STreehugger Robot
494*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
495*16467b97STreehugger Robot */
496*16467b97STreehugger Robot bucket = table->buckets + (hash % table->modulo);
497*16467b97STreehugger Robot
498*16467b97STreehugger Robot /* Now we can inspect the key at each entry in the bucket
499*16467b97STreehugger Robot * and see if we have a match.
500*16467b97STreehugger Robot */
501*16467b97STreehugger Robot entry = bucket->entries;
502*16467b97STreehugger Robot
503*16467b97STreehugger Robot while (entry != NULL)
504*16467b97STreehugger Robot {
505*16467b97STreehugger Robot if (strcmp((const char *)key, (const char *)entry->keybase.key.sKey) == 0)
506*16467b97STreehugger Robot {
507*16467b97STreehugger Robot /* Match was found, return the data pointer for this entry
508*16467b97STreehugger Robot */
509*16467b97STreehugger Robot return entry->data;
510*16467b97STreehugger Robot }
511*16467b97STreehugger Robot entry = entry->nextEntry;
512*16467b97STreehugger Robot }
513*16467b97STreehugger Robot
514*16467b97STreehugger Robot /* If we got here, then we did not find the key
515*16467b97STreehugger Robot */
516*16467b97STreehugger Robot return NULL;
517*16467b97STreehugger Robot }
518*16467b97STreehugger Robot
519*16467b97STreehugger Robot /** Add the element pointer in to the table, based upon the
520*16467b97STreehugger Robot * hash of the provided key.
521*16467b97STreehugger Robot */
522*16467b97STreehugger Robot static ANTLR3_INT32
antlr3HashPutI(pANTLR3_HASH_TABLE table,ANTLR3_INTKEY key,void * element,void (ANTLR3_CDECL * freeptr)(void *))523*16467b97STreehugger Robot antlr3HashPutI(pANTLR3_HASH_TABLE table, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
524*16467b97STreehugger Robot {
525*16467b97STreehugger Robot ANTLR3_UINT32 hash;
526*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
527*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
528*16467b97STreehugger Robot pANTLR3_HASH_ENTRY * newPointer;
529*16467b97STreehugger Robot
530*16467b97STreehugger Robot /* First we need to know the hash of the provided key
531*16467b97STreehugger Robot */
532*16467b97STreehugger Robot hash = (ANTLR3_UINT32)(key % (ANTLR3_INTKEY)(table->modulo));
533*16467b97STreehugger Robot
534*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
535*16467b97STreehugger Robot */
536*16467b97STreehugger Robot bucket = table->buckets + hash;
537*16467b97STreehugger Robot
538*16467b97STreehugger Robot /* Knowing the bucket, we can traverse the entries until we
539*16467b97STreehugger Robot * we find a NULL pointer or we find that this is already
540*16467b97STreehugger Robot * in the table and duplicates were not allowed.
541*16467b97STreehugger Robot */
542*16467b97STreehugger Robot newPointer = &bucket->entries;
543*16467b97STreehugger Robot
544*16467b97STreehugger Robot while (*newPointer != NULL)
545*16467b97STreehugger Robot {
546*16467b97STreehugger Robot /* The value at new pointer is pointing to an existing entry.
547*16467b97STreehugger Robot * If duplicates are allowed then we don't care what it is, but
548*16467b97STreehugger Robot * must reject this add if the key is the same as the one we are
549*16467b97STreehugger Robot * supplied with.
550*16467b97STreehugger Robot */
551*16467b97STreehugger Robot if (table->allowDups == ANTLR3_FALSE)
552*16467b97STreehugger Robot {
553*16467b97STreehugger Robot if ((*newPointer)->keybase.key.iKey == key)
554*16467b97STreehugger Robot {
555*16467b97STreehugger Robot return ANTLR3_ERR_HASHDUP;
556*16467b97STreehugger Robot }
557*16467b97STreehugger Robot }
558*16467b97STreehugger Robot
559*16467b97STreehugger Robot /* Point to the next entry pointer of the current entry we
560*16467b97STreehugger Robot * are traversing, if it is NULL we will create our new
561*16467b97STreehugger Robot * structure and point this to it.
562*16467b97STreehugger Robot */
563*16467b97STreehugger Robot newPointer = &((*newPointer)->nextEntry);
564*16467b97STreehugger Robot }
565*16467b97STreehugger Robot
566*16467b97STreehugger Robot /* newPointer is now pointing at the pointer where we need to
567*16467b97STreehugger Robot * add our new entry, so let's crate the entry and add it in.
568*16467b97STreehugger Robot */
569*16467b97STreehugger Robot entry = (pANTLR3_HASH_ENTRY)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENTRY));
570*16467b97STreehugger Robot
571*16467b97STreehugger Robot if (entry == NULL)
572*16467b97STreehugger Robot {
573*16467b97STreehugger Robot return ANTLR3_ERR_NOMEM;
574*16467b97STreehugger Robot }
575*16467b97STreehugger Robot
576*16467b97STreehugger Robot entry->data = element; /* Install the data element supplied */
577*16467b97STreehugger Robot entry->free = freeptr; /* Function that knows how to release the entry */
578*16467b97STreehugger Robot entry->keybase.type = ANTLR3_HASH_TYPE_INT; /* Indicate the key type stored here for when we free */
579*16467b97STreehugger Robot entry->keybase.key.iKey = key; /* Record the key value */
580*16467b97STreehugger Robot entry->nextEntry = NULL; /* Ensure that the forward pointer ends the chain */
581*16467b97STreehugger Robot
582*16467b97STreehugger Robot *newPointer = entry; /* Install the next entry in this bucket */
583*16467b97STreehugger Robot
584*16467b97STreehugger Robot table->count++;
585*16467b97STreehugger Robot
586*16467b97STreehugger Robot return ANTLR3_SUCCESS;
587*16467b97STreehugger Robot }
588*16467b97STreehugger Robot
589*16467b97STreehugger Robot
590*16467b97STreehugger Robot /** Add the element pointer in to the table, based upon the
591*16467b97STreehugger Robot * hash of the provided key.
592*16467b97STreehugger Robot */
593*16467b97STreehugger Robot static ANTLR3_INT32
antlr3HashPut(pANTLR3_HASH_TABLE table,void * key,void * element,void (ANTLR3_CDECL * freeptr)(void *))594*16467b97STreehugger Robot antlr3HashPut(pANTLR3_HASH_TABLE table, void * key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
595*16467b97STreehugger Robot {
596*16467b97STreehugger Robot ANTLR3_UINT32 hash;
597*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
598*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
599*16467b97STreehugger Robot pANTLR3_HASH_ENTRY * newPointer;
600*16467b97STreehugger Robot
601*16467b97STreehugger Robot /* First we need to know the hash of the provided key
602*16467b97STreehugger Robot */
603*16467b97STreehugger Robot hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key));
604*16467b97STreehugger Robot
605*16467b97STreehugger Robot /* Knowing the hash, we can find the bucket
606*16467b97STreehugger Robot */
607*16467b97STreehugger Robot bucket = table->buckets + (hash % table->modulo);
608*16467b97STreehugger Robot
609*16467b97STreehugger Robot /* Knowign the bucket, we can traverse the entries until we
610*16467b97STreehugger Robot * we find a NULL pointer ofr we find that this is already
611*16467b97STreehugger Robot * in the table and duplicates were not allowed.
612*16467b97STreehugger Robot */
613*16467b97STreehugger Robot newPointer = &bucket->entries;
614*16467b97STreehugger Robot
615*16467b97STreehugger Robot while (*newPointer != NULL)
616*16467b97STreehugger Robot {
617*16467b97STreehugger Robot /* The value at new pointer is pointing to an existing entry.
618*16467b97STreehugger Robot * If duplicates are allowed then we don't care what it is, but
619*16467b97STreehugger Robot * must reject this add if the key is the same as the one we are
620*16467b97STreehugger Robot * supplied with.
621*16467b97STreehugger Robot */
622*16467b97STreehugger Robot if (table->allowDups == ANTLR3_FALSE)
623*16467b97STreehugger Robot {
624*16467b97STreehugger Robot if (strcmp((const char*) key, (const char *)(*newPointer)->keybase.key.sKey) == 0)
625*16467b97STreehugger Robot {
626*16467b97STreehugger Robot return ANTLR3_ERR_HASHDUP;
627*16467b97STreehugger Robot }
628*16467b97STreehugger Robot }
629*16467b97STreehugger Robot
630*16467b97STreehugger Robot /* Point to the next entry pointer of the current entry we
631*16467b97STreehugger Robot * are traversing, if it is NULL we will create our new
632*16467b97STreehugger Robot * structure and point this to it.
633*16467b97STreehugger Robot */
634*16467b97STreehugger Robot newPointer = &((*newPointer)->nextEntry);
635*16467b97STreehugger Robot }
636*16467b97STreehugger Robot
637*16467b97STreehugger Robot /* newPointer is now poiting at the pointer where we need to
638*16467b97STreehugger Robot * add our new entry, so let's crate the entry and add it in.
639*16467b97STreehugger Robot */
640*16467b97STreehugger Robot entry = (pANTLR3_HASH_ENTRY)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENTRY));
641*16467b97STreehugger Robot
642*16467b97STreehugger Robot if (entry == NULL)
643*16467b97STreehugger Robot {
644*16467b97STreehugger Robot return ANTLR3_ERR_NOMEM;
645*16467b97STreehugger Robot }
646*16467b97STreehugger Robot
647*16467b97STreehugger Robot entry->data = element; /* Install the data element supplied */
648*16467b97STreehugger Robot entry->free = freeptr; /* Function that knows how to release the entry */
649*16467b97STreehugger Robot entry->keybase.type = ANTLR3_HASH_TYPE_STR; /* Indicate the key type stored here for free() */
650*16467b97STreehugger Robot if (table->doStrdup == ANTLR3_TRUE)
651*16467b97STreehugger Robot {
652*16467b97STreehugger Robot entry->keybase.key.sKey = ANTLR3_STRDUP(key); /* Record the key value */
653*16467b97STreehugger Robot }
654*16467b97STreehugger Robot else
655*16467b97STreehugger Robot {
656*16467b97STreehugger Robot entry->keybase.key.sKey = (pANTLR3_UINT8)key; /* Record the key value */
657*16467b97STreehugger Robot }
658*16467b97STreehugger Robot entry->nextEntry = NULL; /* Ensure that the forward pointer ends the chain */
659*16467b97STreehugger Robot
660*16467b97STreehugger Robot *newPointer = entry; /* Install the next entry in this bucket */
661*16467b97STreehugger Robot
662*16467b97STreehugger Robot table->count++;
663*16467b97STreehugger Robot
664*16467b97STreehugger Robot return ANTLR3_SUCCESS;
665*16467b97STreehugger Robot }
666*16467b97STreehugger Robot
667*16467b97STreehugger Robot /** \brief Creates an enumeration structure to traverse the hash table.
668*16467b97STreehugger Robot *
669*16467b97STreehugger Robot * \param table Table to enumerate
670*16467b97STreehugger Robot * \return Pointer to enumeration structure.
671*16467b97STreehugger Robot */
672*16467b97STreehugger Robot pANTLR3_HASH_ENUM
antlr3EnumNew(pANTLR3_HASH_TABLE table)673*16467b97STreehugger Robot antlr3EnumNew (pANTLR3_HASH_TABLE table)
674*16467b97STreehugger Robot {
675*16467b97STreehugger Robot pANTLR3_HASH_ENUM en;
676*16467b97STreehugger Robot
677*16467b97STreehugger Robot /* Allocate structure memory
678*16467b97STreehugger Robot */
679*16467b97STreehugger Robot en = (pANTLR3_HASH_ENUM) ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENUM));
680*16467b97STreehugger Robot
681*16467b97STreehugger Robot /* Check that the allocation was good
682*16467b97STreehugger Robot */
683*16467b97STreehugger Robot if (en == NULL)
684*16467b97STreehugger Robot {
685*16467b97STreehugger Robot return (pANTLR3_HASH_ENUM) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
686*16467b97STreehugger Robot }
687*16467b97STreehugger Robot
688*16467b97STreehugger Robot /* Initialize the start pointers
689*16467b97STreehugger Robot */
690*16467b97STreehugger Robot en->table = table;
691*16467b97STreehugger Robot en->bucket = 0; /* First bucket */
692*16467b97STreehugger Robot en->entry = en->table->buckets->entries; /* First entry to return */
693*16467b97STreehugger Robot
694*16467b97STreehugger Robot /* Special case in that the first bucket may not have anything in it
695*16467b97STreehugger Robot * but the antlr3EnumNext() function expects that the en->entry is
696*16467b97STreehugger Robot * set to the next valid pointer. Hence if it is not a valid element
697*16467b97STreehugger Robot * pointer, attempt to find the next one that is, (table may be empty
698*16467b97STreehugger Robot * of course.
699*16467b97STreehugger Robot */
700*16467b97STreehugger Robot if (en->entry == NULL)
701*16467b97STreehugger Robot {
702*16467b97STreehugger Robot antlr3EnumNextEntry(en);
703*16467b97STreehugger Robot }
704*16467b97STreehugger Robot
705*16467b97STreehugger Robot /* Install the interface
706*16467b97STreehugger Robot */
707*16467b97STreehugger Robot en->free = antlr3EnumFree;
708*16467b97STreehugger Robot en->next = antlr3EnumNext;
709*16467b97STreehugger Robot
710*16467b97STreehugger Robot /* All is good
711*16467b97STreehugger Robot */
712*16467b97STreehugger Robot return en;
713*16467b97STreehugger Robot }
714*16467b97STreehugger Robot
715*16467b97STreehugger Robot /** \brief Return the next entry in the hashtable being traversed by the supplied
716*16467b97STreehugger Robot * enumeration.
717*16467b97STreehugger Robot *
718*16467b97STreehugger Robot * \param[in] en Pointer to the enumeration tracking structure
719*16467b97STreehugger Robot * \param key Pointer to void pointer, where the key pointer is returned.
720*16467b97STreehugger Robot * \param data Pointer to void pointer where the data pointer is returned.
721*16467b97STreehugger Robot * \return
722*16467b97STreehugger Robot * - ANTLR3_SUCCESS if there was a next key
723*16467b97STreehugger Robot * - ANTLR3_FAIL if there were no more keys
724*16467b97STreehugger Robot *
725*16467b97STreehugger Robot * \remark
726*16467b97STreehugger Robot * No checking of input structure is performed!
727*16467b97STreehugger Robot */
728*16467b97STreehugger Robot static int
antlr3EnumNext(pANTLR3_HASH_ENUM en,pANTLR3_HASH_KEY * key,void ** data)729*16467b97STreehugger Robot antlr3EnumNext (pANTLR3_HASH_ENUM en, pANTLR3_HASH_KEY * key, void ** data)
730*16467b97STreehugger Robot {
731*16467b97STreehugger Robot /* If the current entry is valid, then use it
732*16467b97STreehugger Robot */
733*16467b97STreehugger Robot if (en->bucket >= en->table->modulo)
734*16467b97STreehugger Robot {
735*16467b97STreehugger Robot /* Already exhausted the table
736*16467b97STreehugger Robot */
737*16467b97STreehugger Robot return ANTLR3_FAIL;
738*16467b97STreehugger Robot }
739*16467b97STreehugger Robot
740*16467b97STreehugger Robot /* Pointers are already set to the current entry to return, or
741*16467b97STreehugger Robot * we would not be at this point in the logic flow.
742*16467b97STreehugger Robot */
743*16467b97STreehugger Robot *key = &(en->entry->keybase);
744*16467b97STreehugger Robot *data = en->entry->data;
745*16467b97STreehugger Robot
746*16467b97STreehugger Robot /* Return pointers are set up, so now we move the element
747*16467b97STreehugger Robot * pointer to the next in the table (if any).
748*16467b97STreehugger Robot */
749*16467b97STreehugger Robot antlr3EnumNextEntry(en);
750*16467b97STreehugger Robot
751*16467b97STreehugger Robot return ANTLR3_SUCCESS;
752*16467b97STreehugger Robot }
753*16467b97STreehugger Robot
754*16467b97STreehugger Robot /** \brief Local function to advance the entry pointer of an enumeration
755*16467b97STreehugger Robot * structure to the next valid entry (if there is one).
756*16467b97STreehugger Robot *
757*16467b97STreehugger Robot * \param[in] enum Pointer to ANTLR3 enumeration structure returned by antlr3EnumNew()
758*16467b97STreehugger Robot *
759*16467b97STreehugger Robot * \remark
760*16467b97STreehugger Robot * - The function always leaves the pointers pointing at a valid entry if there
761*16467b97STreehugger Robot * is one, so if the entry pointer is NULL when this function exits, there were
762*16467b97STreehugger Robot * no more entries in the table.
763*16467b97STreehugger Robot */
764*16467b97STreehugger Robot static void
antlr3EnumNextEntry(pANTLR3_HASH_ENUM en)765*16467b97STreehugger Robot antlr3EnumNextEntry(pANTLR3_HASH_ENUM en)
766*16467b97STreehugger Robot {
767*16467b97STreehugger Robot pANTLR3_HASH_BUCKET bucket;
768*16467b97STreehugger Robot
769*16467b97STreehugger Robot /* See if the current entry pointer is valid first of all
770*16467b97STreehugger Robot */
771*16467b97STreehugger Robot if (en->entry != NULL)
772*16467b97STreehugger Robot {
773*16467b97STreehugger Robot /* Current entry was a valid point, see if there is another
774*16467b97STreehugger Robot * one in the chain.
775*16467b97STreehugger Robot */
776*16467b97STreehugger Robot if (en->entry->nextEntry != NULL)
777*16467b97STreehugger Robot {
778*16467b97STreehugger Robot /* Next entry in the enumeration is just the next entry
779*16467b97STreehugger Robot * in the chain.
780*16467b97STreehugger Robot */
781*16467b97STreehugger Robot en->entry = en->entry->nextEntry;
782*16467b97STreehugger Robot return;
783*16467b97STreehugger Robot }
784*16467b97STreehugger Robot }
785*16467b97STreehugger Robot
786*16467b97STreehugger Robot /* There were no more entries in the current bucket, if there are
787*16467b97STreehugger Robot * more buckets then chase them until we find an entry.
788*16467b97STreehugger Robot */
789*16467b97STreehugger Robot en->bucket++;
790*16467b97STreehugger Robot
791*16467b97STreehugger Robot while (en->bucket < en->table->modulo)
792*16467b97STreehugger Robot {
793*16467b97STreehugger Robot /* There was one more bucket, see if it has any elements in it
794*16467b97STreehugger Robot */
795*16467b97STreehugger Robot bucket = en->table->buckets + en->bucket;
796*16467b97STreehugger Robot
797*16467b97STreehugger Robot if (bucket->entries != NULL)
798*16467b97STreehugger Robot {
799*16467b97STreehugger Robot /* There was an entry in this bucket, so we can use it
800*16467b97STreehugger Robot * for the next entry in the enumeration.
801*16467b97STreehugger Robot */
802*16467b97STreehugger Robot en->entry = bucket->entries;
803*16467b97STreehugger Robot return;
804*16467b97STreehugger Robot }
805*16467b97STreehugger Robot
806*16467b97STreehugger Robot /* There was nothing in the bucket we just examined, move to the
807*16467b97STreehugger Robot * next one.
808*16467b97STreehugger Robot */
809*16467b97STreehugger Robot en->bucket++;
810*16467b97STreehugger Robot }
811*16467b97STreehugger Robot
812*16467b97STreehugger Robot /* Here we have exhausted all buckets and the enumeration pointer will
813*16467b97STreehugger Robot * have its bucket count = table->modulo which signifies that we are done.
814*16467b97STreehugger Robot */
815*16467b97STreehugger Robot }
816*16467b97STreehugger Robot
817*16467b97STreehugger Robot /** \brief Frees up the memory structures that represent a hash table
818*16467b97STreehugger Robot * enumeration.
819*16467b97STreehugger Robot * \param[in] enum Pointer to ANTLR3 enumeration structure returned by antlr3EnumNew()
820*16467b97STreehugger Robot */
821*16467b97STreehugger Robot static void
antlr3EnumFree(pANTLR3_HASH_ENUM en)822*16467b97STreehugger Robot antlr3EnumFree (pANTLR3_HASH_ENUM en)
823*16467b97STreehugger Robot {
824*16467b97STreehugger Robot /* Nothing to check, we just free it.
825*16467b97STreehugger Robot */
826*16467b97STreehugger Robot ANTLR3_FREE(en);
827*16467b97STreehugger Robot }
828*16467b97STreehugger Robot
829*16467b97STreehugger Robot /** Given an input key of arbitrary length, return a hash value of
830*16467b97STreehugger Robot * it. This can then be used (with suitable modulo) to index other
831*16467b97STreehugger Robot * structures.
832*16467b97STreehugger Robot */
833*16467b97STreehugger Robot ANTLR3_API ANTLR3_UINT32
antlr3Hash(void * key,ANTLR3_UINT32 keylen)834*16467b97STreehugger Robot antlr3Hash(void * key, ANTLR3_UINT32 keylen)
835*16467b97STreehugger Robot {
836*16467b97STreehugger Robot /* Accumulate the hash value of the key
837*16467b97STreehugger Robot */
838*16467b97STreehugger Robot ANTLR3_UINT32 hash;
839*16467b97STreehugger Robot pANTLR3_UINT8 keyPtr;
840*16467b97STreehugger Robot ANTLR3_UINT32 i1;
841*16467b97STreehugger Robot
842*16467b97STreehugger Robot hash = 0;
843*16467b97STreehugger Robot keyPtr = (pANTLR3_UINT8) key;
844*16467b97STreehugger Robot
845*16467b97STreehugger Robot /* Iterate the key and accumulate the hash
846*16467b97STreehugger Robot */
847*16467b97STreehugger Robot while(keylen > 0)
848*16467b97STreehugger Robot {
849*16467b97STreehugger Robot hash = (hash << 4) + (*(keyPtr++));
850*16467b97STreehugger Robot
851*16467b97STreehugger Robot if ((i1=hash&0xf0000000) != 0)
852*16467b97STreehugger Robot {
853*16467b97STreehugger Robot hash = hash ^ (i1 >> 24);
854*16467b97STreehugger Robot hash = hash ^ i1;
855*16467b97STreehugger Robot }
856*16467b97STreehugger Robot keylen--;
857*16467b97STreehugger Robot }
858*16467b97STreehugger Robot
859*16467b97STreehugger Robot return hash;
860*16467b97STreehugger Robot }
861*16467b97STreehugger Robot
862*16467b97STreehugger Robot ANTLR3_API pANTLR3_LIST
antlr3ListNew(ANTLR3_UINT32 sizeHint)863*16467b97STreehugger Robot antlr3ListNew (ANTLR3_UINT32 sizeHint)
864*16467b97STreehugger Robot {
865*16467b97STreehugger Robot pANTLR3_LIST list;
866*16467b97STreehugger Robot
867*16467b97STreehugger Robot /* Allocate memory
868*16467b97STreehugger Robot */
869*16467b97STreehugger Robot list = (pANTLR3_LIST)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_LIST));
870*16467b97STreehugger Robot
871*16467b97STreehugger Robot if (list == NULL)
872*16467b97STreehugger Robot {
873*16467b97STreehugger Robot return (pANTLR3_LIST)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
874*16467b97STreehugger Robot }
875*16467b97STreehugger Robot
876*16467b97STreehugger Robot /* Now we need to add a new table
877*16467b97STreehugger Robot */
878*16467b97STreehugger Robot list->table = antlr3HashTableNew(sizeHint);
879*16467b97STreehugger Robot
880*16467b97STreehugger Robot if (list->table == (pANTLR3_HASH_TABLE)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM))
881*16467b97STreehugger Robot {
882*16467b97STreehugger Robot return (pANTLR3_LIST)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
883*16467b97STreehugger Robot }
884*16467b97STreehugger Robot
885*16467b97STreehugger Robot /* Allocation was good, install interface
886*16467b97STreehugger Robot */
887*16467b97STreehugger Robot list->free = antlr3ListFree;
888*16467b97STreehugger Robot list->del = antlr3ListDelete;
889*16467b97STreehugger Robot list->get = antlr3ListGet;
890*16467b97STreehugger Robot list->add = antlr3ListAdd;
891*16467b97STreehugger Robot list->remove = antlr3ListRemove;
892*16467b97STreehugger Robot list->put = antlr3ListPut;
893*16467b97STreehugger Robot list->size = antlr3ListSize;
894*16467b97STreehugger Robot
895*16467b97STreehugger Robot return list;
896*16467b97STreehugger Robot }
897*16467b97STreehugger Robot
antlr3ListSize(pANTLR3_LIST list)898*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3ListSize (pANTLR3_LIST list)
899*16467b97STreehugger Robot {
900*16467b97STreehugger Robot return list->table->size(list->table);
901*16467b97STreehugger Robot }
902*16467b97STreehugger Robot
903*16467b97STreehugger Robot static void
antlr3ListFree(pANTLR3_LIST list)904*16467b97STreehugger Robot antlr3ListFree (pANTLR3_LIST list)
905*16467b97STreehugger Robot {
906*16467b97STreehugger Robot /* Free the hashtable that stores the list
907*16467b97STreehugger Robot */
908*16467b97STreehugger Robot list->table->free(list->table);
909*16467b97STreehugger Robot
910*16467b97STreehugger Robot /* Free the allocation for the list itself
911*16467b97STreehugger Robot */
912*16467b97STreehugger Robot ANTLR3_FREE(list);
913*16467b97STreehugger Robot }
914*16467b97STreehugger Robot
915*16467b97STreehugger Robot static void
antlr3ListDelete(pANTLR3_LIST list,ANTLR3_INTKEY key)916*16467b97STreehugger Robot antlr3ListDelete (pANTLR3_LIST list, ANTLR3_INTKEY key)
917*16467b97STreehugger Robot {
918*16467b97STreehugger Robot list->table->delI(list->table, key);
919*16467b97STreehugger Robot }
920*16467b97STreehugger Robot
921*16467b97STreehugger Robot static void *
antlr3ListGet(pANTLR3_LIST list,ANTLR3_INTKEY key)922*16467b97STreehugger Robot antlr3ListGet (pANTLR3_LIST list, ANTLR3_INTKEY key)
923*16467b97STreehugger Robot {
924*16467b97STreehugger Robot return list->table->getI(list->table, key);
925*16467b97STreehugger Robot }
926*16467b97STreehugger Robot
927*16467b97STreehugger Robot /** Add the supplied element to the list, at the next available key
928*16467b97STreehugger Robot */
antlr3ListAdd(pANTLR3_LIST list,void * element,void (ANTLR3_CDECL * freeptr)(void *))929*16467b97STreehugger Robot static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (ANTLR3_CDECL *freeptr)(void *))
930*16467b97STreehugger Robot {
931*16467b97STreehugger Robot ANTLR3_INTKEY key;
932*16467b97STreehugger Robot
933*16467b97STreehugger Robot key = list->table->size(list->table) + 1;
934*16467b97STreehugger Robot return list->put(list, key, element, freeptr);
935*16467b97STreehugger Robot }
936*16467b97STreehugger Robot
937*16467b97STreehugger Robot /** Remove from the list, but don't free the element, just send it back to the
938*16467b97STreehugger Robot * caller.
939*16467b97STreehugger Robot */
940*16467b97STreehugger Robot static void *
antlr3ListRemove(pANTLR3_LIST list,ANTLR3_INTKEY key)941*16467b97STreehugger Robot antlr3ListRemove (pANTLR3_LIST list, ANTLR3_INTKEY key)
942*16467b97STreehugger Robot {
943*16467b97STreehugger Robot pANTLR3_HASH_ENTRY entry;
944*16467b97STreehugger Robot
945*16467b97STreehugger Robot entry = list->table->removeI(list->table, key);
946*16467b97STreehugger Robot
947*16467b97STreehugger Robot if (entry != NULL)
948*16467b97STreehugger Robot {
949*16467b97STreehugger Robot return entry->data;
950*16467b97STreehugger Robot }
951*16467b97STreehugger Robot else
952*16467b97STreehugger Robot {
953*16467b97STreehugger Robot return NULL;
954*16467b97STreehugger Robot }
955*16467b97STreehugger Robot }
956*16467b97STreehugger Robot
957*16467b97STreehugger Robot static ANTLR3_INT32
antlr3ListPut(pANTLR3_LIST list,ANTLR3_INTKEY key,void * element,void (ANTLR3_CDECL * freeptr)(void *))958*16467b97STreehugger Robot antlr3ListPut (pANTLR3_LIST list, ANTLR3_INTKEY key, void * element, void (ANTLR3_CDECL *freeptr)(void *))
959*16467b97STreehugger Robot {
960*16467b97STreehugger Robot return list->table->putI(list->table, key, element, freeptr);
961*16467b97STreehugger Robot }
962*16467b97STreehugger Robot
963*16467b97STreehugger Robot ANTLR3_API pANTLR3_STACK
antlr3StackNew(ANTLR3_UINT32 sizeHint)964*16467b97STreehugger Robot antlr3StackNew (ANTLR3_UINT32 sizeHint)
965*16467b97STreehugger Robot {
966*16467b97STreehugger Robot pANTLR3_STACK stack;
967*16467b97STreehugger Robot
968*16467b97STreehugger Robot /* Allocate memory
969*16467b97STreehugger Robot */
970*16467b97STreehugger Robot stack = (pANTLR3_STACK)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_STACK));
971*16467b97STreehugger Robot
972*16467b97STreehugger Robot if (stack == NULL)
973*16467b97STreehugger Robot {
974*16467b97STreehugger Robot return (pANTLR3_STACK)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
975*16467b97STreehugger Robot }
976*16467b97STreehugger Robot
977*16467b97STreehugger Robot /* Now we need to add a new table
978*16467b97STreehugger Robot */
979*16467b97STreehugger Robot stack->vector = antlr3VectorNew(sizeHint);
980*16467b97STreehugger Robot stack->top = NULL;
981*16467b97STreehugger Robot
982*16467b97STreehugger Robot if (stack->vector == (pANTLR3_VECTOR)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM))
983*16467b97STreehugger Robot {
984*16467b97STreehugger Robot return (pANTLR3_STACK)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
985*16467b97STreehugger Robot }
986*16467b97STreehugger Robot
987*16467b97STreehugger Robot /* Looks good, now add the interface
988*16467b97STreehugger Robot */
989*16467b97STreehugger Robot stack->get = antlr3StackGet;
990*16467b97STreehugger Robot stack->free = antlr3StackFree;
991*16467b97STreehugger Robot stack->pop = antlr3StackPop;
992*16467b97STreehugger Robot stack->push = antlr3StackPush;
993*16467b97STreehugger Robot stack->size = antlr3StackSize;
994*16467b97STreehugger Robot stack->peek = antlr3StackPeek;
995*16467b97STreehugger Robot
996*16467b97STreehugger Robot return stack;
997*16467b97STreehugger Robot }
998*16467b97STreehugger Robot
antlr3StackSize(pANTLR3_STACK stack)999*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3StackSize (pANTLR3_STACK stack)
1000*16467b97STreehugger Robot {
1001*16467b97STreehugger Robot return stack->vector->count;
1002*16467b97STreehugger Robot }
1003*16467b97STreehugger Robot
1004*16467b97STreehugger Robot
1005*16467b97STreehugger Robot static void
antlr3StackFree(pANTLR3_STACK stack)1006*16467b97STreehugger Robot antlr3StackFree (pANTLR3_STACK stack)
1007*16467b97STreehugger Robot {
1008*16467b97STreehugger Robot /* Free the list that supports the stack
1009*16467b97STreehugger Robot */
1010*16467b97STreehugger Robot stack->vector->free(stack->vector);
1011*16467b97STreehugger Robot stack->vector = NULL;
1012*16467b97STreehugger Robot stack->top = NULL;
1013*16467b97STreehugger Robot
1014*16467b97STreehugger Robot ANTLR3_FREE(stack);
1015*16467b97STreehugger Robot }
1016*16467b97STreehugger Robot
1017*16467b97STreehugger Robot static void *
antlr3StackPop(pANTLR3_STACK stack)1018*16467b97STreehugger Robot antlr3StackPop (pANTLR3_STACK stack)
1019*16467b97STreehugger Robot {
1020*16467b97STreehugger Robot // Delete the element that is currently at the top of the stack
1021*16467b97STreehugger Robot //
1022*16467b97STreehugger Robot stack->vector->del(stack->vector, stack->vector->count - 1);
1023*16467b97STreehugger Robot
1024*16467b97STreehugger Robot // And get the element that is the now the top of the stack (if anything)
1025*16467b97STreehugger Robot // NOTE! This is not quite like a 'real' stack, which would normally return you
1026*16467b97STreehugger Robot // the current top of the stack, then remove it from the stack.
1027*16467b97STreehugger Robot // TODO: Review this, it is correct for follow sets which is what this was done for
1028*16467b97STreehugger Robot // but is not as obvious when using it as a 'real'stack.
1029*16467b97STreehugger Robot //
1030*16467b97STreehugger Robot stack->top = stack->vector->get(stack->vector, stack->vector->count - 1);
1031*16467b97STreehugger Robot return stack->top;
1032*16467b97STreehugger Robot }
1033*16467b97STreehugger Robot
1034*16467b97STreehugger Robot static void *
antlr3StackGet(pANTLR3_STACK stack,ANTLR3_INTKEY key)1035*16467b97STreehugger Robot antlr3StackGet (pANTLR3_STACK stack, ANTLR3_INTKEY key)
1036*16467b97STreehugger Robot {
1037*16467b97STreehugger Robot return stack->vector->get(stack->vector, (ANTLR3_UINT32)key);
1038*16467b97STreehugger Robot }
1039*16467b97STreehugger Robot
1040*16467b97STreehugger Robot static void *
antlr3StackPeek(pANTLR3_STACK stack)1041*16467b97STreehugger Robot antlr3StackPeek (pANTLR3_STACK stack)
1042*16467b97STreehugger Robot {
1043*16467b97STreehugger Robot return stack->top;
1044*16467b97STreehugger Robot }
1045*16467b97STreehugger Robot
1046*16467b97STreehugger Robot static ANTLR3_BOOLEAN
antlr3StackPush(pANTLR3_STACK stack,void * element,void (ANTLR3_CDECL * freeptr)(void *))1047*16467b97STreehugger Robot antlr3StackPush (pANTLR3_STACK stack, void * element, void (ANTLR3_CDECL *freeptr)(void *))
1048*16467b97STreehugger Robot {
1049*16467b97STreehugger Robot stack->top = element;
1050*16467b97STreehugger Robot return (ANTLR3_BOOLEAN)(stack->vector->add(stack->vector, element, freeptr));
1051*16467b97STreehugger Robot }
1052*16467b97STreehugger Robot
1053*16467b97STreehugger Robot ANTLR3_API pANTLR3_VECTOR
antlr3VectorNew(ANTLR3_UINT32 sizeHint)1054*16467b97STreehugger Robot antlr3VectorNew (ANTLR3_UINT32 sizeHint)
1055*16467b97STreehugger Robot {
1056*16467b97STreehugger Robot pANTLR3_VECTOR vector;
1057*16467b97STreehugger Robot
1058*16467b97STreehugger Robot
1059*16467b97STreehugger Robot // Allocate memory for the vector structure itself
1060*16467b97STreehugger Robot //
1061*16467b97STreehugger Robot vector = (pANTLR3_VECTOR) ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR)));
1062*16467b97STreehugger Robot
1063*16467b97STreehugger Robot if (vector == NULL)
1064*16467b97STreehugger Robot {
1065*16467b97STreehugger Robot return (pANTLR3_VECTOR)ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
1066*16467b97STreehugger Robot }
1067*16467b97STreehugger Robot
1068*16467b97STreehugger Robot // Now fill in the defaults
1069*16467b97STreehugger Robot //
1070*16467b97STreehugger Robot antlr3SetVectorApi(vector, sizeHint);
1071*16467b97STreehugger Robot
1072*16467b97STreehugger Robot // And everything is hunky dory
1073*16467b97STreehugger Robot //
1074*16467b97STreehugger Robot return vector;
1075*16467b97STreehugger Robot }
1076*16467b97STreehugger Robot
1077*16467b97STreehugger Robot ANTLR3_API void
antlr3SetVectorApi(pANTLR3_VECTOR vector,ANTLR3_UINT32 sizeHint)1078*16467b97STreehugger Robot antlr3SetVectorApi (pANTLR3_VECTOR vector, ANTLR3_UINT32 sizeHint)
1079*16467b97STreehugger Robot {
1080*16467b97STreehugger Robot ANTLR3_UINT32 initialSize;
1081*16467b97STreehugger Robot
1082*16467b97STreehugger Robot // Allow vectors to be guessed by ourselves, so input size can be zero
1083*16467b97STreehugger Robot //
1084*16467b97STreehugger Robot if (sizeHint > ANTLR3_VECTOR_INTERNAL_SIZE)
1085*16467b97STreehugger Robot {
1086*16467b97STreehugger Robot initialSize = sizeHint;
1087*16467b97STreehugger Robot }
1088*16467b97STreehugger Robot else
1089*16467b97STreehugger Robot {
1090*16467b97STreehugger Robot initialSize = ANTLR3_VECTOR_INTERNAL_SIZE;
1091*16467b97STreehugger Robot }
1092*16467b97STreehugger Robot
1093*16467b97STreehugger Robot if (sizeHint > ANTLR3_VECTOR_INTERNAL_SIZE)
1094*16467b97STreehugger Robot {
1095*16467b97STreehugger Robot vector->elements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR_ELEMENT) * initialSize));
1096*16467b97STreehugger Robot }
1097*16467b97STreehugger Robot else
1098*16467b97STreehugger Robot {
1099*16467b97STreehugger Robot vector->elements = vector->internal;
1100*16467b97STreehugger Robot }
1101*16467b97STreehugger Robot
1102*16467b97STreehugger Robot if (vector->elements == NULL)
1103*16467b97STreehugger Robot {
1104*16467b97STreehugger Robot ANTLR3_FREE(vector);
1105*16467b97STreehugger Robot return;
1106*16467b97STreehugger Robot }
1107*16467b97STreehugger Robot
1108*16467b97STreehugger Robot // Memory allocated successfully
1109*16467b97STreehugger Robot //
1110*16467b97STreehugger Robot vector->count = 0; // No entries yet of course
1111*16467b97STreehugger Robot vector->elementsSize = initialSize; // Available entries
1112*16467b97STreehugger Robot
1113*16467b97STreehugger Robot // Now we can install the API
1114*16467b97STreehugger Robot //
1115*16467b97STreehugger Robot vector->add = antlr3VectorAdd;
1116*16467b97STreehugger Robot vector->del = antlr3VectorDel;
1117*16467b97STreehugger Robot vector->get = antlr3VectorGet;
1118*16467b97STreehugger Robot vector->free = antlr3VectorFree;
1119*16467b97STreehugger Robot vector->set = antlr3VectorSet;
1120*16467b97STreehugger Robot vector->remove = antrl3VectorRemove;
1121*16467b97STreehugger Robot vector->clear = antlr3VectorClear;
1122*16467b97STreehugger Robot vector->size = antlr3VectorSize;
1123*16467b97STreehugger Robot vector->swap = antlr3VectorSwap;
1124*16467b97STreehugger Robot
1125*16467b97STreehugger Robot // Assume that this is not a factory made vector
1126*16467b97STreehugger Robot //
1127*16467b97STreehugger Robot vector->factoryMade = ANTLR3_FALSE;
1128*16467b97STreehugger Robot }
1129*16467b97STreehugger Robot
1130*16467b97STreehugger Robot // Clear the entries in a vector.
1131*16467b97STreehugger Robot // Clearing the vector leaves its capacity the same but
1132*16467b97STreehugger Robot // it walks the entries first to see if any of them
1133*16467b97STreehugger Robot // have a free routine that must be called.
1134*16467b97STreehugger Robot //
1135*16467b97STreehugger Robot static void
antlr3VectorClear(pANTLR3_VECTOR vector)1136*16467b97STreehugger Robot antlr3VectorClear (pANTLR3_VECTOR vector)
1137*16467b97STreehugger Robot {
1138*16467b97STreehugger Robot ANTLR3_UINT32 entry;
1139*16467b97STreehugger Robot
1140*16467b97STreehugger Robot // We must traverse every entry in the vector and if it has
1141*16467b97STreehugger Robot // a pointer to a free function then we call it with the
1142*16467b97STreehugger Robot // the entry pointer
1143*16467b97STreehugger Robot //
1144*16467b97STreehugger Robot for (entry = 0; entry < vector->count; entry++)
1145*16467b97STreehugger Robot {
1146*16467b97STreehugger Robot if (vector->elements[entry].freeptr != NULL)
1147*16467b97STreehugger Robot {
1148*16467b97STreehugger Robot vector->elements[entry].freeptr(vector->elements[entry].element);
1149*16467b97STreehugger Robot }
1150*16467b97STreehugger Robot vector->elements[entry].freeptr = NULL;
1151*16467b97STreehugger Robot vector->elements[entry].element = NULL;
1152*16467b97STreehugger Robot }
1153*16467b97STreehugger Robot
1154*16467b97STreehugger Robot // Having called any free pointers, we just reset the entry count
1155*16467b97STreehugger Robot // back to zero.
1156*16467b97STreehugger Robot //
1157*16467b97STreehugger Robot vector->count = 0;
1158*16467b97STreehugger Robot }
1159*16467b97STreehugger Robot
1160*16467b97STreehugger Robot static
antlr3VectorFree(pANTLR3_VECTOR vector)1161*16467b97STreehugger Robot void ANTLR3_CDECL antlr3VectorFree (pANTLR3_VECTOR vector)
1162*16467b97STreehugger Robot {
1163*16467b97STreehugger Robot ANTLR3_UINT32 entry;
1164*16467b97STreehugger Robot
1165*16467b97STreehugger Robot // We must traverse every entry in the vector and if it has
1166*16467b97STreehugger Robot // a pointer to a free function then we call it with the
1167*16467b97STreehugger Robot // the entry pointer
1168*16467b97STreehugger Robot //
1169*16467b97STreehugger Robot for (entry = 0; entry < vector->count; entry++)
1170*16467b97STreehugger Robot {
1171*16467b97STreehugger Robot if (vector->elements[entry].freeptr != NULL)
1172*16467b97STreehugger Robot {
1173*16467b97STreehugger Robot vector->elements[entry].freeptr(vector->elements[entry].element);
1174*16467b97STreehugger Robot }
1175*16467b97STreehugger Robot vector->elements[entry].freeptr = NULL;
1176*16467b97STreehugger Robot vector->elements[entry].element = NULL;
1177*16467b97STreehugger Robot }
1178*16467b97STreehugger Robot
1179*16467b97STreehugger Robot if (vector->factoryMade == ANTLR3_FALSE)
1180*16467b97STreehugger Robot {
1181*16467b97STreehugger Robot // The entries are freed, so free the element allocation
1182*16467b97STreehugger Robot //
1183*16467b97STreehugger Robot if (vector->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
1184*16467b97STreehugger Robot {
1185*16467b97STreehugger Robot ANTLR3_FREE(vector->elements);
1186*16467b97STreehugger Robot }
1187*16467b97STreehugger Robot vector->elements = NULL;
1188*16467b97STreehugger Robot
1189*16467b97STreehugger Robot // Finally, free the allocation for the vector itself
1190*16467b97STreehugger Robot //
1191*16467b97STreehugger Robot ANTLR3_FREE(vector);
1192*16467b97STreehugger Robot }
1193*16467b97STreehugger Robot }
1194*16467b97STreehugger Robot
antlr3VectorDel(pANTLR3_VECTOR vector,ANTLR3_UINT32 entry)1195*16467b97STreehugger Robot static void antlr3VectorDel (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
1196*16467b97STreehugger Robot {
1197*16467b97STreehugger Robot // Check this is a valid request first
1198*16467b97STreehugger Robot //
1199*16467b97STreehugger Robot if (entry >= vector->count)
1200*16467b97STreehugger Robot {
1201*16467b97STreehugger Robot return;
1202*16467b97STreehugger Robot }
1203*16467b97STreehugger Robot
1204*16467b97STreehugger Robot // Valid request, check for free pointer and call it if present
1205*16467b97STreehugger Robot //
1206*16467b97STreehugger Robot if (vector->elements[entry].freeptr != NULL)
1207*16467b97STreehugger Robot {
1208*16467b97STreehugger Robot vector->elements[entry].freeptr(vector->elements[entry].element);
1209*16467b97STreehugger Robot vector->elements[entry].freeptr = NULL;
1210*16467b97STreehugger Robot }
1211*16467b97STreehugger Robot
1212*16467b97STreehugger Robot if (entry == vector->count - 1)
1213*16467b97STreehugger Robot {
1214*16467b97STreehugger Robot // Ensure the pointer is never reused by accident, but otherwise just
1215*16467b97STreehugger Robot // decrement the pointer.
1216*16467b97STreehugger Robot //
1217*16467b97STreehugger Robot vector->elements[entry].element = NULL;
1218*16467b97STreehugger Robot }
1219*16467b97STreehugger Robot else
1220*16467b97STreehugger Robot {
1221*16467b97STreehugger Robot // Need to shuffle trailing pointers back over the deleted entry
1222*16467b97STreehugger Robot //
1223*16467b97STreehugger Robot ANTLR3_MEMMOVE(vector->elements + entry, vector->elements + entry + 1, sizeof(ANTLR3_VECTOR_ELEMENT) * (vector->count - entry - 1));
1224*16467b97STreehugger Robot }
1225*16467b97STreehugger Robot
1226*16467b97STreehugger Robot // One less entry in the vector now
1227*16467b97STreehugger Robot //
1228*16467b97STreehugger Robot vector->count--;
1229*16467b97STreehugger Robot }
1230*16467b97STreehugger Robot
antlr3VectorGet(pANTLR3_VECTOR vector,ANTLR3_UINT32 entry)1231*16467b97STreehugger Robot static void * antlr3VectorGet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
1232*16467b97STreehugger Robot {
1233*16467b97STreehugger Robot // Ensure this is a valid request
1234*16467b97STreehugger Robot //
1235*16467b97STreehugger Robot if (entry < vector->count)
1236*16467b97STreehugger Robot {
1237*16467b97STreehugger Robot return vector->elements[entry].element;
1238*16467b97STreehugger Robot }
1239*16467b97STreehugger Robot else
1240*16467b97STreehugger Robot {
1241*16467b97STreehugger Robot // I know nothing, Mr. Fawlty!
1242*16467b97STreehugger Robot //
1243*16467b97STreehugger Robot return NULL;
1244*16467b97STreehugger Robot }
1245*16467b97STreehugger Robot }
1246*16467b97STreehugger Robot
1247*16467b97STreehugger Robot /// Remove the entry from the vector, but do not free any entry, even if it has
1248*16467b97STreehugger Robot /// a free pointer.
1249*16467b97STreehugger Robot ///
antrl3VectorRemove(pANTLR3_VECTOR vector,ANTLR3_UINT32 entry)1250*16467b97STreehugger Robot static void * antrl3VectorRemove (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry)
1251*16467b97STreehugger Robot {
1252*16467b97STreehugger Robot void * element;
1253*16467b97STreehugger Robot
1254*16467b97STreehugger Robot // Check this is a valid request first
1255*16467b97STreehugger Robot //
1256*16467b97STreehugger Robot if (entry >= vector->count)
1257*16467b97STreehugger Robot {
1258*16467b97STreehugger Robot return NULL;
1259*16467b97STreehugger Robot }
1260*16467b97STreehugger Robot
1261*16467b97STreehugger Robot // Valid request, return the sorted pointer
1262*16467b97STreehugger Robot //
1263*16467b97STreehugger Robot
1264*16467b97STreehugger Robot element = vector->elements[entry].element;
1265*16467b97STreehugger Robot
1266*16467b97STreehugger Robot if (entry == vector->count - 1)
1267*16467b97STreehugger Robot {
1268*16467b97STreehugger Robot // Ensure the pointer is never reused by accident, but otherwise just
1269*16467b97STreehugger Robot // decrement the pointer.
1270*16467b97STreehugger Robot ///
1271*16467b97STreehugger Robot vector->elements[entry].element = NULL;
1272*16467b97STreehugger Robot vector->elements[entry].freeptr = NULL;
1273*16467b97STreehugger Robot }
1274*16467b97STreehugger Robot else
1275*16467b97STreehugger Robot {
1276*16467b97STreehugger Robot // Need to shuffle trailing pointers back over the deleted entry
1277*16467b97STreehugger Robot //
1278*16467b97STreehugger Robot ANTLR3_MEMMOVE(vector->elements + entry, vector->elements + entry + 1, sizeof(ANTLR3_VECTOR_ELEMENT) * (vector->count - entry - 1));
1279*16467b97STreehugger Robot }
1280*16467b97STreehugger Robot
1281*16467b97STreehugger Robot // One less entry in the vector now
1282*16467b97STreehugger Robot //
1283*16467b97STreehugger Robot vector->count--;
1284*16467b97STreehugger Robot
1285*16467b97STreehugger Robot return element;
1286*16467b97STreehugger Robot }
1287*16467b97STreehugger Robot
1288*16467b97STreehugger Robot static ANTLR3_BOOLEAN
antlr3VectorResize(pANTLR3_VECTOR vector,ANTLR3_UINT32 hint)1289*16467b97STreehugger Robot antlr3VectorResize (pANTLR3_VECTOR vector, ANTLR3_UINT32 hint)
1290*16467b97STreehugger Robot {
1291*16467b97STreehugger Robot ANTLR3_UINT32 newSize;
1292*16467b97STreehugger Robot
1293*16467b97STreehugger Robot // Need to resize the element pointers. We double the allocation
1294*16467b97STreehugger Robot // we already have unless asked for a specific increase.
1295*16467b97STreehugger Robot //
1296*16467b97STreehugger Robot if (hint == 0 || hint < vector->elementsSize)
1297*16467b97STreehugger Robot {
1298*16467b97STreehugger Robot newSize = vector->elementsSize * 2;
1299*16467b97STreehugger Robot }
1300*16467b97STreehugger Robot else
1301*16467b97STreehugger Robot {
1302*16467b97STreehugger Robot newSize = hint * 2;
1303*16467b97STreehugger Robot }
1304*16467b97STreehugger Robot
1305*16467b97STreehugger Robot // Now we know how many we need, so we see if we have just expanded
1306*16467b97STreehugger Robot // past the built in vector elements or were already past that
1307*16467b97STreehugger Robot //
1308*16467b97STreehugger Robot if (vector->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
1309*16467b97STreehugger Robot {
1310*16467b97STreehugger Robot // We were already larger than the internal size, so we just
1311*16467b97STreehugger Robot // use realloc so that the pointers are copied for us
1312*16467b97STreehugger Robot //
1313*16467b97STreehugger Robot pANTLR3_VECTOR_ELEMENT newElements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_REALLOC(vector->elements, (sizeof(ANTLR3_VECTOR_ELEMENT)* newSize));
1314*16467b97STreehugger Robot if (newElements == NULL)
1315*16467b97STreehugger Robot {
1316*16467b97STreehugger Robot // realloc failed, but the old allocation is still there
1317*16467b97STreehugger Robot return ANTLR3_FALSE;
1318*16467b97STreehugger Robot }
1319*16467b97STreehugger Robot vector->elements = newElements;
1320*16467b97STreehugger Robot }
1321*16467b97STreehugger Robot else
1322*16467b97STreehugger Robot {
1323*16467b97STreehugger Robot // The current size was less than or equal to the internal array size and as we always start
1324*16467b97STreehugger Robot // with a size that is at least the maximum internal size, then we must need to allocate new memory
1325*16467b97STreehugger Robot // for external pointers. We don't want to take the time to calculate if a requested element
1326*16467b97STreehugger Robot // is part of the internal or external entries, so we copy the internal ones to the new space
1327*16467b97STreehugger Robot //
1328*16467b97STreehugger Robot vector->elements = (pANTLR3_VECTOR_ELEMENT)ANTLR3_MALLOC((sizeof(ANTLR3_VECTOR_ELEMENT)* newSize));
1329*16467b97STreehugger Robot if (vector->elements == NULL)
1330*16467b97STreehugger Robot {
1331*16467b97STreehugger Robot // malloc failed
1332*16467b97STreehugger Robot return ANTLR3_FALSE;
1333*16467b97STreehugger Robot }
1334*16467b97STreehugger Robot ANTLR3_MEMCPY(vector->elements, vector->internal, ANTLR3_VECTOR_INTERNAL_SIZE * sizeof(ANTLR3_VECTOR_ELEMENT));
1335*16467b97STreehugger Robot }
1336*16467b97STreehugger Robot
1337*16467b97STreehugger Robot vector->elementsSize = newSize;
1338*16467b97STreehugger Robot return ANTLR3_TRUE;
1339*16467b97STreehugger Robot }
1340*16467b97STreehugger Robot
1341*16467b97STreehugger Robot /// Add the supplied pointer and freeing function pointer to the list,
1342*16467b97STreehugger Robot /// expanding the vector if needed.
1343*16467b97STreehugger Robot ///
antlr3VectorAdd(pANTLR3_VECTOR vector,void * element,void (ANTLR3_CDECL * freeptr)(void *))1344*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3VectorAdd (pANTLR3_VECTOR vector, void * element, void (ANTLR3_CDECL *freeptr)(void *))
1345*16467b97STreehugger Robot {
1346*16467b97STreehugger Robot // Do we need to resize the vector table?
1347*16467b97STreehugger Robot //
1348*16467b97STreehugger Robot if (vector->count == vector->elementsSize)
1349*16467b97STreehugger Robot {
1350*16467b97STreehugger Robot // Give no hint, we let it add 1024 or double it
1351*16467b97STreehugger Robot if (!antlr3VectorResize(vector, 0))
1352*16467b97STreehugger Robot {
1353*16467b97STreehugger Robot // Resize failed
1354*16467b97STreehugger Robot return 0;
1355*16467b97STreehugger Robot }
1356*16467b97STreehugger Robot }
1357*16467b97STreehugger Robot
1358*16467b97STreehugger Robot // Insert the new entry
1359*16467b97STreehugger Robot //
1360*16467b97STreehugger Robot vector->elements[vector->count].element = element;
1361*16467b97STreehugger Robot vector->elements[vector->count].freeptr = freeptr;
1362*16467b97STreehugger Robot
1363*16467b97STreehugger Robot vector->count++; // One more element counted
1364*16467b97STreehugger Robot
1365*16467b97STreehugger Robot return (ANTLR3_UINT32)(vector->count);
1366*16467b97STreehugger Robot
1367*16467b97STreehugger Robot }
1368*16467b97STreehugger Robot
1369*16467b97STreehugger Robot /// Replace the element at the specified entry point with the supplied
1370*16467b97STreehugger Robot /// entry.
1371*16467b97STreehugger Robot ///
1372*16467b97STreehugger Robot static ANTLR3_UINT32
antlr3VectorSet(pANTLR3_VECTOR vector,ANTLR3_UINT32 entry,void * element,void (ANTLR3_CDECL * freeptr)(void *),ANTLR3_BOOLEAN freeExisting)1373*16467b97STreehugger Robot antlr3VectorSet (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry, void * element, void (ANTLR3_CDECL *freeptr)(void *), ANTLR3_BOOLEAN freeExisting)
1374*16467b97STreehugger Robot {
1375*16467b97STreehugger Robot
1376*16467b97STreehugger Robot // If the vector is currently not big enough, then we expand it
1377*16467b97STreehugger Robot //
1378*16467b97STreehugger Robot if (entry >= vector->elementsSize)
1379*16467b97STreehugger Robot {
1380*16467b97STreehugger Robot // We will get at least this many
1381*16467b97STreehugger Robot if (!antlr3VectorResize(vector, entry))
1382*16467b97STreehugger Robot {
1383*16467b97STreehugger Robot // Resize failed
1384*16467b97STreehugger Robot return 0;
1385*16467b97STreehugger Robot }
1386*16467b97STreehugger Robot }
1387*16467b97STreehugger Robot
1388*16467b97STreehugger Robot // Valid request, replace the current one, freeing any prior entry if told to
1389*16467b97STreehugger Robot //
1390*16467b97STreehugger Robot if ( entry < vector->count // If actually replacing an element
1391*16467b97STreehugger Robot && freeExisting // And told to free any existing element
1392*16467b97STreehugger Robot && vector->elements[entry].freeptr != NULL // And the existing element has a free pointer
1393*16467b97STreehugger Robot )
1394*16467b97STreehugger Robot {
1395*16467b97STreehugger Robot vector->elements[entry].freeptr(vector->elements[entry].element);
1396*16467b97STreehugger Robot }
1397*16467b97STreehugger Robot
1398*16467b97STreehugger Robot // Install the new pointers
1399*16467b97STreehugger Robot //
1400*16467b97STreehugger Robot vector->elements[entry].freeptr = freeptr;
1401*16467b97STreehugger Robot vector->elements[entry].element = element;
1402*16467b97STreehugger Robot
1403*16467b97STreehugger Robot if (entry >= vector->count)
1404*16467b97STreehugger Robot {
1405*16467b97STreehugger Robot vector->count = entry + 1;
1406*16467b97STreehugger Robot }
1407*16467b97STreehugger Robot return (ANTLR3_UINT32)(entry); // Indicates the replacement was successful
1408*16467b97STreehugger Robot
1409*16467b97STreehugger Robot }
1410*16467b97STreehugger Robot
1411*16467b97STreehugger Robot /// Replace the element at the specified entry point with the supplied
1412*16467b97STreehugger Robot /// entry.
1413*16467b97STreehugger Robot ///
1414*16467b97STreehugger Robot static ANTLR3_BOOLEAN
antlr3VectorSwap(pANTLR3_VECTOR vector,ANTLR3_UINT32 entry1,ANTLR3_UINT32 entry2)1415*16467b97STreehugger Robot antlr3VectorSwap (pANTLR3_VECTOR vector, ANTLR3_UINT32 entry1, ANTLR3_UINT32 entry2)
1416*16467b97STreehugger Robot {
1417*16467b97STreehugger Robot
1418*16467b97STreehugger Robot void * tempEntry;
1419*16467b97STreehugger Robot void (ANTLR3_CDECL *freeptr)(void *);
1420*16467b97STreehugger Robot
1421*16467b97STreehugger Robot // If the vector is currently not big enough, then we do nothing
1422*16467b97STreehugger Robot //
1423*16467b97STreehugger Robot if (entry1 >= vector->elementsSize || entry2 >= vector->elementsSize)
1424*16467b97STreehugger Robot {
1425*16467b97STreehugger Robot return ANTLR3_FALSE;
1426*16467b97STreehugger Robot }
1427*16467b97STreehugger Robot
1428*16467b97STreehugger Robot // Valid request, swap them
1429*16467b97STreehugger Robot //
1430*16467b97STreehugger Robot tempEntry = vector->elements[entry1].element;
1431*16467b97STreehugger Robot freeptr = vector->elements[entry1].freeptr;
1432*16467b97STreehugger Robot
1433*16467b97STreehugger Robot // Install the new pointers
1434*16467b97STreehugger Robot //
1435*16467b97STreehugger Robot vector->elements[entry1].freeptr = vector->elements[entry2].freeptr;
1436*16467b97STreehugger Robot vector->elements[entry1].element = vector->elements[entry2].element;
1437*16467b97STreehugger Robot
1438*16467b97STreehugger Robot vector->elements[entry2].freeptr = freeptr;
1439*16467b97STreehugger Robot vector->elements[entry2].element = tempEntry;
1440*16467b97STreehugger Robot
1441*16467b97STreehugger Robot return ANTLR3_TRUE;
1442*16467b97STreehugger Robot
1443*16467b97STreehugger Robot }
1444*16467b97STreehugger Robot
antlr3VectorSize(pANTLR3_VECTOR vector)1445*16467b97STreehugger Robot static ANTLR3_UINT32 antlr3VectorSize (pANTLR3_VECTOR vector)
1446*16467b97STreehugger Robot {
1447*16467b97STreehugger Robot return vector->count;
1448*16467b97STreehugger Robot }
1449*16467b97STreehugger Robot
1450*16467b97STreehugger Robot #ifdef ANTLR3_WINDOWS
1451*16467b97STreehugger Robot #pragma warning (push)
1452*16467b97STreehugger Robot #pragma warning (disable : 4100)
1453*16467b97STreehugger Robot #endif
1454*16467b97STreehugger Robot /// Vector factory creation
1455*16467b97STreehugger Robot ///
1456*16467b97STreehugger Robot ANTLR3_API pANTLR3_VECTOR_FACTORY
antlr3VectorFactoryNew(ANTLR3_UINT32 sizeHint)1457*16467b97STreehugger Robot antlr3VectorFactoryNew (ANTLR3_UINT32 sizeHint)
1458*16467b97STreehugger Robot {
1459*16467b97STreehugger Robot pANTLR3_VECTOR_FACTORY factory;
1460*16467b97STreehugger Robot
1461*16467b97STreehugger Robot // Allocate memory for the factory
1462*16467b97STreehugger Robot //
1463*16467b97STreehugger Robot factory = (pANTLR3_VECTOR_FACTORY)ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR_FACTORY)));
1464*16467b97STreehugger Robot
1465*16467b97STreehugger Robot if (factory == NULL)
1466*16467b97STreehugger Robot {
1467*16467b97STreehugger Robot return NULL;
1468*16467b97STreehugger Robot }
1469*16467b97STreehugger Robot
1470*16467b97STreehugger Robot // Factory memory is good, so create a new vector pool
1471*16467b97STreehugger Robot //
1472*16467b97STreehugger Robot factory->pools = NULL;
1473*16467b97STreehugger Robot factory->thisPool = -1;
1474*16467b97STreehugger Robot
1475*16467b97STreehugger Robot newPool(factory);
1476*16467b97STreehugger Robot
1477*16467b97STreehugger Robot // Initialize the API, ignore the hint as this algorithm does
1478*16467b97STreehugger Robot // a better job really.
1479*16467b97STreehugger Robot //
1480*16467b97STreehugger Robot antlr3SetVectorApi(&(factory->unTruc), ANTLR3_VECTOR_INTERNAL_SIZE);
1481*16467b97STreehugger Robot
1482*16467b97STreehugger Robot factory->unTruc.factoryMade = ANTLR3_TRUE;
1483*16467b97STreehugger Robot
1484*16467b97STreehugger Robot // Install the factory API
1485*16467b97STreehugger Robot //
1486*16467b97STreehugger Robot factory->close = closeVectorFactory;
1487*16467b97STreehugger Robot factory->newVector = newVector;
1488*16467b97STreehugger Robot factory->returnVector = returnVector;
1489*16467b97STreehugger Robot
1490*16467b97STreehugger Robot // Create a stack to accumulate reusable vectors
1491*16467b97STreehugger Robot //
1492*16467b97STreehugger Robot factory->freeStack = antlr3StackNew(16);
1493*16467b97STreehugger Robot return factory;
1494*16467b97STreehugger Robot }
1495*16467b97STreehugger Robot #ifdef ANTLR3_WINDOWS
1496*16467b97STreehugger Robot #pragma warning (pop)
1497*16467b97STreehugger Robot #endif
1498*16467b97STreehugger Robot
1499*16467b97STreehugger Robot static void
returnVector(pANTLR3_VECTOR_FACTORY factory,pANTLR3_VECTOR vector)1500*16467b97STreehugger Robot returnVector (pANTLR3_VECTOR_FACTORY factory, pANTLR3_VECTOR vector)
1501*16467b97STreehugger Robot {
1502*16467b97STreehugger Robot // First we need to clear out anything that is still in the vector
1503*16467b97STreehugger Robot //
1504*16467b97STreehugger Robot vector->clear(vector);
1505*16467b97STreehugger Robot
1506*16467b97STreehugger Robot // We have a free stack available so we can add the vector we were
1507*16467b97STreehugger Robot // given into the free chain. The vector has to have come from this
1508*16467b97STreehugger Robot // factory, so we already know how to release its memory when it
1509*16467b97STreehugger Robot // dies by virtue of the factory being closed.
1510*16467b97STreehugger Robot //
1511*16467b97STreehugger Robot factory->freeStack->push(factory->freeStack, vector, NULL);
1512*16467b97STreehugger Robot
1513*16467b97STreehugger Robot // TODO: remove this line once happy printf("Returned vector %08X to the pool, stack size is %d\n", vector, factory->freeStack->size(factory->freeStack));
1514*16467b97STreehugger Robot }
1515*16467b97STreehugger Robot
1516*16467b97STreehugger Robot static ANTLR3_BOOLEAN
newPool(pANTLR3_VECTOR_FACTORY factory)1517*16467b97STreehugger Robot newPool(pANTLR3_VECTOR_FACTORY factory)
1518*16467b97STreehugger Robot {
1519*16467b97STreehugger Robot pANTLR3_VECTOR *newPools;
1520*16467b97STreehugger Robot
1521*16467b97STreehugger Robot /* Increment factory count
1522*16467b97STreehugger Robot */
1523*16467b97STreehugger Robot ++factory->thisPool;
1524*16467b97STreehugger Robot
1525*16467b97STreehugger Robot /* Ensure we have enough pointers allocated
1526*16467b97STreehugger Robot */
1527*16467b97STreehugger Robot newPools = (pANTLR3_VECTOR *)
1528*16467b97STreehugger Robot ANTLR3_REALLOC( (void *)factory->pools, /* Current pools pointer (starts at NULL) */
1529*16467b97STreehugger Robot (ANTLR3_UINT32)((factory->thisPool + 1) * sizeof(pANTLR3_VECTOR *)) /* Memory for new pool pointers */
1530*16467b97STreehugger Robot );
1531*16467b97STreehugger Robot if (newPools == NULL)
1532*16467b97STreehugger Robot {
1533*16467b97STreehugger Robot // realloc failed, but we still have the old allocation
1534*16467b97STreehugger Robot --factory->thisPool;
1535*16467b97STreehugger Robot return ANTLR3_FALSE;
1536*16467b97STreehugger Robot }
1537*16467b97STreehugger Robot factory->pools = newPools;
1538*16467b97STreehugger Robot
1539*16467b97STreehugger Robot /* Allocate a new pool for the factory
1540*16467b97STreehugger Robot */
1541*16467b97STreehugger Robot factory->pools[factory->thisPool] =
1542*16467b97STreehugger Robot (pANTLR3_VECTOR)
1543*16467b97STreehugger Robot ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_VECTOR) * ANTLR3_FACTORY_VPOOL_SIZE));
1544*16467b97STreehugger Robot if (factory->pools[factory->thisPool] == NULL)
1545*16467b97STreehugger Robot {
1546*16467b97STreehugger Robot // malloc failed
1547*16467b97STreehugger Robot --factory->thisPool;
1548*16467b97STreehugger Robot return ANTLR3_FALSE;
1549*16467b97STreehugger Robot }
1550*16467b97STreehugger Robot
1551*16467b97STreehugger Robot
1552*16467b97STreehugger Robot /* Reset the counters
1553*16467b97STreehugger Robot */
1554*16467b97STreehugger Robot factory->nextVector = 0;
1555*16467b97STreehugger Robot
1556*16467b97STreehugger Robot /* Done
1557*16467b97STreehugger Robot */
1558*16467b97STreehugger Robot return ANTLR3_TRUE;
1559*16467b97STreehugger Robot }
1560*16467b97STreehugger Robot
1561*16467b97STreehugger Robot static void
closeVectorFactory(pANTLR3_VECTOR_FACTORY factory)1562*16467b97STreehugger Robot closeVectorFactory (pANTLR3_VECTOR_FACTORY factory)
1563*16467b97STreehugger Robot {
1564*16467b97STreehugger Robot pANTLR3_VECTOR pool;
1565*16467b97STreehugger Robot ANTLR3_INT32 poolCount;
1566*16467b97STreehugger Robot ANTLR3_UINT32 limit;
1567*16467b97STreehugger Robot ANTLR3_UINT32 vector;
1568*16467b97STreehugger Robot pANTLR3_VECTOR check;
1569*16467b97STreehugger Robot
1570*16467b97STreehugger Robot // First see if we have a free chain stack to release?
1571*16467b97STreehugger Robot //
1572*16467b97STreehugger Robot if (factory->freeStack != NULL)
1573*16467b97STreehugger Robot {
1574*16467b97STreehugger Robot factory->freeStack->free(factory->freeStack);
1575*16467b97STreehugger Robot }
1576*16467b97STreehugger Robot
1577*16467b97STreehugger Robot /* We iterate the vector pools one at a time
1578*16467b97STreehugger Robot */
1579*16467b97STreehugger Robot for (poolCount = 0; poolCount <= factory->thisPool; poolCount++)
1580*16467b97STreehugger Robot {
1581*16467b97STreehugger Robot /* Pointer to current pool
1582*16467b97STreehugger Robot */
1583*16467b97STreehugger Robot pool = factory->pools[poolCount];
1584*16467b97STreehugger Robot
1585*16467b97STreehugger Robot /* Work out how many tokens we need to check in this pool.
1586*16467b97STreehugger Robot */
1587*16467b97STreehugger Robot limit = (poolCount == factory->thisPool ? factory->nextVector : ANTLR3_FACTORY_VPOOL_SIZE);
1588*16467b97STreehugger Robot
1589*16467b97STreehugger Robot /* Marginal condition, we might be at the start of a brand new pool
1590*16467b97STreehugger Robot * where the nextToken is 0 and nothing has been allocated.
1591*16467b97STreehugger Robot */
1592*16467b97STreehugger Robot if (limit > 0)
1593*16467b97STreehugger Robot {
1594*16467b97STreehugger Robot /* We have some vectors allocated from this pool
1595*16467b97STreehugger Robot */
1596*16467b97STreehugger Robot for (vector = 0; vector < limit; vector++)
1597*16467b97STreehugger Robot {
1598*16467b97STreehugger Robot /* Next one in the chain
1599*16467b97STreehugger Robot */
1600*16467b97STreehugger Robot check = pool + vector;
1601*16467b97STreehugger Robot
1602*16467b97STreehugger Robot // Call the free function on each of the vectors in the pool,
1603*16467b97STreehugger Robot // which in turn will cause any elements it holds that also have a free
1604*16467b97STreehugger Robot // pointer to be freed. However, because any vector may be in any other
1605*16467b97STreehugger Robot // vector, we don't free the element allocations yet. We do that in a
1606*16467b97STreehugger Robot // a specific pass, coming up next. The vector free function knows that
1607*16467b97STreehugger Robot // this is a factory allocated pool vector and so it won't free things it
1608*16467b97STreehugger Robot // should not.
1609*16467b97STreehugger Robot //
1610*16467b97STreehugger Robot check->free(check);
1611*16467b97STreehugger Robot }
1612*16467b97STreehugger Robot }
1613*16467b97STreehugger Robot }
1614*16467b97STreehugger Robot
1615*16467b97STreehugger Robot /* We iterate the vector pools one at a time once again, but this time
1616*16467b97STreehugger Robot * we are going to free up any allocated element pointers. Note that we are doing this
1617*16467b97STreehugger Robot * so that we do not try to release vectors twice. When building ASTs we just copy
1618*16467b97STreehugger Robot * the vectors all over the place and they may be embedded in this vector pool
1619*16467b97STreehugger Robot * numerous times.
1620*16467b97STreehugger Robot */
1621*16467b97STreehugger Robot for (poolCount = 0; poolCount <= factory->thisPool; poolCount++)
1622*16467b97STreehugger Robot {
1623*16467b97STreehugger Robot /* Pointer to current pool
1624*16467b97STreehugger Robot */
1625*16467b97STreehugger Robot pool = factory->pools[poolCount];
1626*16467b97STreehugger Robot
1627*16467b97STreehugger Robot /* Work out how many tokens we need to check in this pool.
1628*16467b97STreehugger Robot */
1629*16467b97STreehugger Robot limit = (poolCount == factory->thisPool ? factory->nextVector : ANTLR3_FACTORY_VPOOL_SIZE);
1630*16467b97STreehugger Robot
1631*16467b97STreehugger Robot /* Marginal condition, we might be at the start of a brand new pool
1632*16467b97STreehugger Robot * where the nextToken is 0 and nothing has been allocated.
1633*16467b97STreehugger Robot */
1634*16467b97STreehugger Robot if (limit > 0)
1635*16467b97STreehugger Robot {
1636*16467b97STreehugger Robot /* We have some vectors allocated from this pool
1637*16467b97STreehugger Robot */
1638*16467b97STreehugger Robot for (vector = 0; vector < limit; vector++)
1639*16467b97STreehugger Robot {
1640*16467b97STreehugger Robot /* Next one in the chain
1641*16467b97STreehugger Robot */
1642*16467b97STreehugger Robot check = pool + vector;
1643*16467b97STreehugger Robot
1644*16467b97STreehugger Robot // Anything in here should be factory made, but we do this just
1645*16467b97STreehugger Robot // to triple check. We just free up the elements if they were
1646*16467b97STreehugger Robot // allocated beyond the internal size.
1647*16467b97STreehugger Robot //
1648*16467b97STreehugger Robot if (check->factoryMade == ANTLR3_TRUE && check->elementsSize > ANTLR3_VECTOR_INTERNAL_SIZE)
1649*16467b97STreehugger Robot {
1650*16467b97STreehugger Robot ANTLR3_FREE(check->elements);
1651*16467b97STreehugger Robot check->elements = NULL;
1652*16467b97STreehugger Robot }
1653*16467b97STreehugger Robot }
1654*16467b97STreehugger Robot }
1655*16467b97STreehugger Robot
1656*16467b97STreehugger Robot // We can now free this pool allocation as we have called free on every element in every vector
1657*16467b97STreehugger Robot // and freed any memory for pointers the grew beyond the internal size limit.
1658*16467b97STreehugger Robot //
1659*16467b97STreehugger Robot ANTLR3_FREE(factory->pools[poolCount]);
1660*16467b97STreehugger Robot factory->pools[poolCount] = NULL;
1661*16467b97STreehugger Robot }
1662*16467b97STreehugger Robot
1663*16467b97STreehugger Robot /* All the pools are deallocated we can free the pointers to the pools
1664*16467b97STreehugger Robot * now.
1665*16467b97STreehugger Robot */
1666*16467b97STreehugger Robot ANTLR3_FREE(factory->pools);
1667*16467b97STreehugger Robot
1668*16467b97STreehugger Robot /* Finally, we can free the space for the factory itself
1669*16467b97STreehugger Robot */
1670*16467b97STreehugger Robot ANTLR3_FREE(factory);
1671*16467b97STreehugger Robot
1672*16467b97STreehugger Robot }
1673*16467b97STreehugger Robot
1674*16467b97STreehugger Robot static pANTLR3_VECTOR
newVector(pANTLR3_VECTOR_FACTORY factory)1675*16467b97STreehugger Robot newVector(pANTLR3_VECTOR_FACTORY factory)
1676*16467b97STreehugger Robot {
1677*16467b97STreehugger Robot pANTLR3_VECTOR vector;
1678*16467b97STreehugger Robot
1679*16467b97STreehugger Robot // If we have anything on the re claim stack, reuse it
1680*16467b97STreehugger Robot //
1681*16467b97STreehugger Robot vector = (pANTLR3_VECTOR)factory->freeStack->peek(factory->freeStack);
1682*16467b97STreehugger Robot
1683*16467b97STreehugger Robot if (vector != NULL)
1684*16467b97STreehugger Robot {
1685*16467b97STreehugger Robot // Cool we got something we could reuse
1686*16467b97STreehugger Robot //
1687*16467b97STreehugger Robot factory->freeStack->pop(factory->freeStack);
1688*16467b97STreehugger Robot
1689*16467b97STreehugger Robot // TODO: remove this line once happy printf("Reused vector %08X from stack, size is now %d\n", vector, factory->freeStack->size(factory->freeStack));
1690*16467b97STreehugger Robot return vector;
1691*16467b97STreehugger Robot
1692*16467b97STreehugger Robot }
1693*16467b97STreehugger Robot
1694*16467b97STreehugger Robot // See if we need a new vector pool before allocating a new
1695*16467b97STreehugger Robot // one
1696*16467b97STreehugger Robot //
1697*16467b97STreehugger Robot if (factory->nextVector >= ANTLR3_FACTORY_VPOOL_SIZE)
1698*16467b97STreehugger Robot {
1699*16467b97STreehugger Robot // We ran out of vectors in the current pool, so we need a new pool
1700*16467b97STreehugger Robot //
1701*16467b97STreehugger Robot if (!newPool(factory))
1702*16467b97STreehugger Robot {
1703*16467b97STreehugger Robot // new pool creation failed
1704*16467b97STreehugger Robot return NULL;
1705*16467b97STreehugger Robot }
1706*16467b97STreehugger Robot }
1707*16467b97STreehugger Robot
1708*16467b97STreehugger Robot // Assuming everything went well (we are trying for performance here so doing minimal
1709*16467b97STreehugger Robot // error checking. Then we can work out what the pointer is to the next vector.
1710*16467b97STreehugger Robot //
1711*16467b97STreehugger Robot vector = factory->pools[factory->thisPool] + factory->nextVector;
1712*16467b97STreehugger Robot factory->nextVector++;
1713*16467b97STreehugger Robot
1714*16467b97STreehugger Robot // We have our token pointer now, so we can initialize it to the predefined model.
1715*16467b97STreehugger Robot //
1716*16467b97STreehugger Robot antlr3SetVectorApi(vector, ANTLR3_VECTOR_INTERNAL_SIZE);
1717*16467b97STreehugger Robot vector->factoryMade = ANTLR3_TRUE;
1718*16467b97STreehugger Robot
1719*16467b97STreehugger Robot // We know that the pool vectors are created at the default size, which means they
1720*16467b97STreehugger Robot // will start off using their internal entry pointers. We must initialize our pool vector
1721*16467b97STreehugger Robot // to point to its own internal entry table and not the pre-made one.
1722*16467b97STreehugger Robot //
1723*16467b97STreehugger Robot vector->elements = vector->internal;
1724*16467b97STreehugger Robot
1725*16467b97STreehugger Robot // TODO: remove this line once happy printf("Used a new vector at %08X from the pools as nothing on the reusue stack\n", vector);
1726*16467b97STreehugger Robot
1727*16467b97STreehugger Robot // And we are done
1728*16467b97STreehugger Robot //
1729*16467b97STreehugger Robot return vector;
1730*16467b97STreehugger Robot }
1731*16467b97STreehugger Robot
1732*16467b97STreehugger Robot /** Array of left most significant bit positions for an 8 bit
1733*16467b97STreehugger Robot * element provides an efficient way to find the highest bit
1734*16467b97STreehugger Robot * that is set in an n byte value (n>0). Assuming the values will all hit the data cache,
1735*16467b97STreehugger Robot * coding without conditional elements should allow branch
1736*16467b97STreehugger Robot * prediction to work well and of course a parallel instruction cache
1737*16467b97STreehugger Robot * will whip through this. Otherwise we must loop shifting a one
1738*16467b97STreehugger Robot * bit and masking. The values we tend to be placing in out integer
1739*16467b97STreehugger Robot * patricia trie are usually a lot lower than the 64 bits we
1740*16467b97STreehugger Robot * allow for the key allows. Hence there is a lot of redundant looping and
1741*16467b97STreehugger Robot * shifting in a while loop. Whereas, the lookup table is just
1742*16467b97STreehugger Robot * a few ands and indirect lookups, while testing for 0. This
1743*16467b97STreehugger Robot * is likely to be done in parallel on many processors available
1744*16467b97STreehugger Robot * when I wrote this. If this code survives as long as yacc, then
1745*16467b97STreehugger Robot * I may already be dead by the time you read this and maybe there is
1746*16467b97STreehugger Robot * a single machine instruction to perform the operation. What
1747*16467b97STreehugger Robot * else are you going to do with all those transistors? Jim 2007
1748*16467b97STreehugger Robot *
1749*16467b97STreehugger Robot * The table is probably obvious but it is just the number 0..7
1750*16467b97STreehugger Robot * of the MSB in each integer value 0..256
1751*16467b97STreehugger Robot */
1752*16467b97STreehugger Robot static ANTLR3_UINT8 bitIndex[256] =
1753*16467b97STreehugger Robot {
1754*16467b97STreehugger Robot 0, // 0 - Just for padding
1755*16467b97STreehugger Robot 0, // 1
1756*16467b97STreehugger Robot 1, 1, // 2..3
1757*16467b97STreehugger Robot 2, 2, 2, 2, // 4..7
1758*16467b97STreehugger Robot 3, 3, 3, 3, 3, 3, 3, 3, // 8+
1759*16467b97STreehugger Robot 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16+
1760*16467b97STreehugger Robot 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 32+
1761*16467b97STreehugger Robot 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1762*16467b97STreehugger Robot 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 64+
1763*16467b97STreehugger Robot 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1764*16467b97STreehugger Robot 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1765*16467b97STreehugger Robot 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1766*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 128+
1767*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1768*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1769*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1770*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1771*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1772*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1773*16467b97STreehugger Robot 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
1774*16467b97STreehugger Robot };
1775*16467b97STreehugger Robot
1776*16467b97STreehugger Robot /** Rather than use the bit index of a trie node to shift
1777*16467b97STreehugger Robot * 0x01 left that many times, then & with the result, it is
1778*16467b97STreehugger Robot * faster to use the bit index as an index into this table
1779*16467b97STreehugger Robot * which holds precomputed masks for any of the 64 bits
1780*16467b97STreehugger Robot * we need to mask off singly. The data values will stay in
1781*16467b97STreehugger Robot * cache while ever a trie is in heavy use, such as in
1782*16467b97STreehugger Robot * memoization. It is also pretty enough to be ASCII art.
1783*16467b97STreehugger Robot */
1784*16467b97STreehugger Robot static ANTLR3_UINT64 bitMask[64] =
1785*16467b97STreehugger Robot {
1786*16467b97STreehugger Robot 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000004ULL, 0x0000000000000008ULL,
1787*16467b97STreehugger Robot 0x0000000000000010ULL, 0x0000000000000020ULL, 0x0000000000000040ULL, 0x0000000000000080ULL,
1788*16467b97STreehugger Robot 0x0000000000000100ULL, 0x0000000000000200ULL, 0x0000000000000400ULL, 0x0000000000000800ULL,
1789*16467b97STreehugger Robot 0x0000000000001000ULL, 0x0000000000002000ULL, 0x0000000000004000ULL, 0x0000000000008000ULL,
1790*16467b97STreehugger Robot 0x0000000000010000ULL, 0x0000000000020000ULL, 0x0000000000040000ULL, 0x0000000000080000ULL,
1791*16467b97STreehugger Robot 0x0000000000100000ULL, 0x0000000000200000ULL, 0x0000000000400000ULL, 0x0000000000800000ULL,
1792*16467b97STreehugger Robot 0x0000000001000000ULL, 0x0000000002000000ULL, 0x0000000004000000ULL, 0x0000000008000000ULL,
1793*16467b97STreehugger Robot 0x0000000010000000ULL, 0x0000000020000000ULL, 0x0000000040000000ULL, 0x0000000080000000ULL,
1794*16467b97STreehugger Robot 0x0000000100000000ULL, 0x0000000200000000ULL, 0x0000000400000000ULL, 0x0000000800000000ULL,
1795*16467b97STreehugger Robot 0x0000001000000000ULL, 0x0000002000000000ULL, 0x0000004000000000ULL, 0x0000008000000000ULL,
1796*16467b97STreehugger Robot 0x0000010000000000ULL, 0x0000020000000000ULL, 0x0000040000000000ULL, 0x0000080000000000ULL,
1797*16467b97STreehugger Robot 0x0000100000000000ULL, 0x0000200000000000ULL, 0x0000400000000000ULL, 0x0000800000000000ULL,
1798*16467b97STreehugger Robot 0x0001000000000000ULL, 0x0002000000000000ULL, 0x0004000000000000ULL, 0x0008000000000000ULL,
1799*16467b97STreehugger Robot 0x0010000000000000ULL, 0x0020000000000000ULL, 0x0040000000000000ULL, 0x0080000000000000ULL,
1800*16467b97STreehugger Robot 0x0100000000000000ULL, 0x0200000000000000ULL, 0x0400000000000000ULL, 0x0800000000000000ULL,
1801*16467b97STreehugger Robot 0x1000000000000000ULL, 0x2000000000000000ULL, 0x4000000000000000ULL, 0x8000000000000000ULL
1802*16467b97STreehugger Robot };
1803*16467b97STreehugger Robot
1804*16467b97STreehugger Robot /* INT TRIE Implementation of depth 64 bits, being the number of bits
1805*16467b97STreehugger Robot * in a 64 bit integer.
1806*16467b97STreehugger Robot */
1807*16467b97STreehugger Robot
1808*16467b97STreehugger Robot pANTLR3_INT_TRIE
antlr3IntTrieNew(ANTLR3_UINT32 depth)1809*16467b97STreehugger Robot antlr3IntTrieNew(ANTLR3_UINT32 depth)
1810*16467b97STreehugger Robot {
1811*16467b97STreehugger Robot pANTLR3_INT_TRIE trie;
1812*16467b97STreehugger Robot
1813*16467b97STreehugger Robot trie = (pANTLR3_INT_TRIE) ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE)); /* Base memory required */
1814*16467b97STreehugger Robot
1815*16467b97STreehugger Robot if (trie == NULL)
1816*16467b97STreehugger Robot {
1817*16467b97STreehugger Robot return (pANTLR3_INT_TRIE) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
1818*16467b97STreehugger Robot }
1819*16467b97STreehugger Robot
1820*16467b97STreehugger Robot /* Now we need to allocate the root node. This makes it easier
1821*16467b97STreehugger Robot * to use the tree as we don't have to do anything special
1822*16467b97STreehugger Robot * for the root node.
1823*16467b97STreehugger Robot */
1824*16467b97STreehugger Robot trie->root = (pANTLR3_INT_TRIE_NODE) ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE));
1825*16467b97STreehugger Robot
1826*16467b97STreehugger Robot if (trie->root == NULL)
1827*16467b97STreehugger Robot {
1828*16467b97STreehugger Robot ANTLR3_FREE(trie);
1829*16467b97STreehugger Robot return (pANTLR3_INT_TRIE) ANTLR3_FUNC_PTR(ANTLR3_ERR_NOMEM);
1830*16467b97STreehugger Robot }
1831*16467b97STreehugger Robot
1832*16467b97STreehugger Robot trie->add = intTrieAdd;
1833*16467b97STreehugger Robot trie->del = intTrieDel;
1834*16467b97STreehugger Robot trie->free = intTrieFree;
1835*16467b97STreehugger Robot trie->get = intTrieGet;
1836*16467b97STreehugger Robot
1837*16467b97STreehugger Robot /* Now we seed the root node with the index being the
1838*16467b97STreehugger Robot * highest left most bit we want to test, which limits the
1839*16467b97STreehugger Robot * keys in the trie. This is the trie 'depth'. The limit for
1840*16467b97STreehugger Robot * this implementation is 63 (bits 0..63).
1841*16467b97STreehugger Robot */
1842*16467b97STreehugger Robot trie->root->bitNum = depth;
1843*16467b97STreehugger Robot
1844*16467b97STreehugger Robot /* And as we have nothing in here yet, we set both child pointers
1845*16467b97STreehugger Robot * of the root node to point back to itself.
1846*16467b97STreehugger Robot */
1847*16467b97STreehugger Robot trie->root->leftN = trie->root;
1848*16467b97STreehugger Robot trie->root->rightN = trie->root;
1849*16467b97STreehugger Robot trie->count = 0;
1850*16467b97STreehugger Robot
1851*16467b97STreehugger Robot /* Finally, note that the key for this root node is 0 because
1852*16467b97STreehugger Robot * we use calloc() to initialise it.
1853*16467b97STreehugger Robot */
1854*16467b97STreehugger Robot
1855*16467b97STreehugger Robot return trie;
1856*16467b97STreehugger Robot }
1857*16467b97STreehugger Robot
1858*16467b97STreehugger Robot /** Search the int Trie and return a pointer to the first bucket indexed
1859*16467b97STreehugger Robot * by the key if it is contained in the trie, otherwise NULL.
1860*16467b97STreehugger Robot */
1861*16467b97STreehugger Robot static pANTLR3_TRIE_ENTRY
intTrieGet(pANTLR3_INT_TRIE trie,ANTLR3_INTKEY key)1862*16467b97STreehugger Robot intTrieGet (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key)
1863*16467b97STreehugger Robot {
1864*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE thisNode;
1865*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE nextNode;
1866*16467b97STreehugger Robot
1867*16467b97STreehugger Robot if (trie->count == 0)
1868*16467b97STreehugger Robot {
1869*16467b97STreehugger Robot return NULL; /* Nothing in this trie yet */
1870*16467b97STreehugger Robot }
1871*16467b97STreehugger Robot /* Starting at the root node in the trie, compare the bit index
1872*16467b97STreehugger Robot * of the current node with its next child node (starts left from root).
1873*16467b97STreehugger Robot * When the bit index of the child node is greater than the bit index of the current node
1874*16467b97STreehugger Robot * then by definition (as the bit index decreases as we descent the trie)
1875*16467b97STreehugger Robot * we have reached a 'backward' pointer. A backward pointer means we
1876*16467b97STreehugger Robot * have reached the only node that can be reached by the bits given us so far
1877*16467b97STreehugger Robot * and it must either be the key we are looking for, or if not then it
1878*16467b97STreehugger Robot * means the entry was not in the trie, and we return NULL. A backward pointer
1879*16467b97STreehugger Robot * points back in to the tree structure rather than down (deeper) within the
1880*16467b97STreehugger Robot * tree branches.
1881*16467b97STreehugger Robot */
1882*16467b97STreehugger Robot thisNode = trie->root; /* Start at the root node */
1883*16467b97STreehugger Robot nextNode = thisNode->leftN; /* Examine the left node from the root */
1884*16467b97STreehugger Robot
1885*16467b97STreehugger Robot /* While we are descending the tree nodes...
1886*16467b97STreehugger Robot */
1887*16467b97STreehugger Robot while (thisNode->bitNum > nextNode->bitNum)
1888*16467b97STreehugger Robot {
1889*16467b97STreehugger Robot /* Next node now becomes the new 'current' node
1890*16467b97STreehugger Robot */
1891*16467b97STreehugger Robot thisNode = nextNode;
1892*16467b97STreehugger Robot
1893*16467b97STreehugger Robot /* We now test the bit indicated by the bitmap in the next node
1894*16467b97STreehugger Robot * in the key we are searching for. The new next node is the
1895*16467b97STreehugger Robot * right node if that bit is set and the left node it is not.
1896*16467b97STreehugger Robot */
1897*16467b97STreehugger Robot if (key & bitMask[nextNode->bitNum])
1898*16467b97STreehugger Robot {
1899*16467b97STreehugger Robot nextNode = nextNode->rightN; /* 1 is right */
1900*16467b97STreehugger Robot }
1901*16467b97STreehugger Robot else
1902*16467b97STreehugger Robot {
1903*16467b97STreehugger Robot nextNode = nextNode->leftN; /* 0 is left */
1904*16467b97STreehugger Robot }
1905*16467b97STreehugger Robot }
1906*16467b97STreehugger Robot
1907*16467b97STreehugger Robot /* Here we have reached a node where the bitMap index is lower than
1908*16467b97STreehugger Robot * its parent. This means it is pointing backward in the tree and
1909*16467b97STreehugger Robot * must therefore be a terminal node, being the only point than can
1910*16467b97STreehugger Robot * be reached with the bits seen so far. It is either the actual key
1911*16467b97STreehugger Robot * we wanted, or if that key is not in the trie it is another key
1912*16467b97STreehugger Robot * that is currently the only one that can be reached by those bits.
1913*16467b97STreehugger Robot * That situation would obviously change if the key was to be added
1914*16467b97STreehugger Robot * to the trie.
1915*16467b97STreehugger Robot *
1916*16467b97STreehugger Robot * Hence it only remains to test whether this is actually the key or not.
1917*16467b97STreehugger Robot */
1918*16467b97STreehugger Robot if (nextNode->key == key)
1919*16467b97STreehugger Robot {
1920*16467b97STreehugger Robot /* This was the key, so return the entry pointer
1921*16467b97STreehugger Robot */
1922*16467b97STreehugger Robot return nextNode->buckets;
1923*16467b97STreehugger Robot }
1924*16467b97STreehugger Robot else
1925*16467b97STreehugger Robot {
1926*16467b97STreehugger Robot return NULL; /* That key is not in the trie (note that we set the pointer to -1 if no payload) */
1927*16467b97STreehugger Robot }
1928*16467b97STreehugger Robot }
1929*16467b97STreehugger Robot
1930*16467b97STreehugger Robot
1931*16467b97STreehugger Robot static ANTLR3_BOOLEAN
intTrieDel(pANTLR3_INT_TRIE trie,ANTLR3_INTKEY key)1932*16467b97STreehugger Robot intTrieDel (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key)
1933*16467b97STreehugger Robot {
1934*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE p;
1935*16467b97STreehugger Robot
1936*16467b97STreehugger Robot p=trie->root;
1937*16467b97STreehugger Robot
1938*16467b97STreehugger Robot return ANTLR3_FALSE;
1939*16467b97STreehugger Robot }
1940*16467b97STreehugger Robot
1941*16467b97STreehugger Robot /** Add an entry into the INT trie.
1942*16467b97STreehugger Robot * Basically we descend the trie as we do when searching it, which will
1943*16467b97STreehugger Robot * locate the only node in the trie that can be reached by the bit pattern of the
1944*16467b97STreehugger Robot * key. If the key is actually at that node, then if the trie accepts duplicates
1945*16467b97STreehugger Robot * we add the supplied data in a new chained bucket to that data node. If it does
1946*16467b97STreehugger Robot * not accept duplicates then we merely return FALSE in case the caller wants to know
1947*16467b97STreehugger Robot * whether the key was already in the trie.
1948*16467b97STreehugger Robot * If the node we locate is not the key we are looking to add, then we insert a new node
1949*16467b97STreehugger Robot * into the trie with a bit index of the leftmost differing bit and the left or right
1950*16467b97STreehugger Robot * node pointing to itself or the data node we are inserting 'before'.
1951*16467b97STreehugger Robot */
1952*16467b97STreehugger Robot static ANTLR3_BOOLEAN
intTrieAdd(pANTLR3_INT_TRIE trie,ANTLR3_INTKEY key,ANTLR3_UINT32 type,ANTLR3_INTKEY intVal,void * data,void (ANTLR3_CDECL * freeptr)(void *))1953*16467b97STreehugger Robot intTrieAdd (pANTLR3_INT_TRIE trie, ANTLR3_INTKEY key, ANTLR3_UINT32 type, ANTLR3_INTKEY intVal, void * data, void (ANTLR3_CDECL *freeptr)(void *))
1954*16467b97STreehugger Robot {
1955*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE thisNode;
1956*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE nextNode;
1957*16467b97STreehugger Robot pANTLR3_INT_TRIE_NODE entNode;
1958*16467b97STreehugger Robot ANTLR3_UINT32 depth;
1959*16467b97STreehugger Robot pANTLR3_TRIE_ENTRY newEnt;
1960*16467b97STreehugger Robot pANTLR3_TRIE_ENTRY nextEnt;
1961*16467b97STreehugger Robot ANTLR3_INTKEY xorKey;
1962*16467b97STreehugger Robot
1963*16467b97STreehugger Robot /* Cache the bit depth of this trie, which is always the highest index,
1964*16467b97STreehugger Robot * which is in the root node
1965*16467b97STreehugger Robot */
1966*16467b97STreehugger Robot depth = trie->root->bitNum;
1967*16467b97STreehugger Robot
1968*16467b97STreehugger Robot thisNode = trie->root; /* Start with the root node */
1969*16467b97STreehugger Robot nextNode = trie->root->leftN; /* And assume we start to the left */
1970*16467b97STreehugger Robot
1971*16467b97STreehugger Robot /* Now find the only node that can be currently reached by the bits in the
1972*16467b97STreehugger Robot * key we are being asked to insert.
1973*16467b97STreehugger Robot */
1974*16467b97STreehugger Robot while (thisNode->bitNum > nextNode->bitNum)
1975*16467b97STreehugger Robot {
1976*16467b97STreehugger Robot /* Still descending the structure, next node becomes current.
1977*16467b97STreehugger Robot */
1978*16467b97STreehugger Robot thisNode = nextNode;
1979*16467b97STreehugger Robot
1980*16467b97STreehugger Robot if (key & bitMask[nextNode->bitNum])
1981*16467b97STreehugger Robot {
1982*16467b97STreehugger Robot /* Bit at the required index was 1, so travers the right node from here
1983*16467b97STreehugger Robot */
1984*16467b97STreehugger Robot nextNode = nextNode->rightN;
1985*16467b97STreehugger Robot }
1986*16467b97STreehugger Robot else
1987*16467b97STreehugger Robot {
1988*16467b97STreehugger Robot /* Bit at the required index was 0, so we traverse to the left
1989*16467b97STreehugger Robot */
1990*16467b97STreehugger Robot nextNode = nextNode->leftN;
1991*16467b97STreehugger Robot }
1992*16467b97STreehugger Robot }
1993*16467b97STreehugger Robot /* Here we have located the only node that can be reached by the
1994*16467b97STreehugger Robot * bits in the requested key. It could in fact be that key or the node
1995*16467b97STreehugger Robot * we need to use to insert the new key.
1996*16467b97STreehugger Robot */
1997*16467b97STreehugger Robot if (nextNode->key == key)
1998*16467b97STreehugger Robot {
1999*16467b97STreehugger Robot /* We have located an exact match, but we will only append to the bucket chain
2000*16467b97STreehugger Robot * if this trie accepts duplicate keys.
2001*16467b97STreehugger Robot */
2002*16467b97STreehugger Robot if (trie->allowDups ==ANTLR3_TRUE)
2003*16467b97STreehugger Robot {
2004*16467b97STreehugger Robot /* Yes, we are accepting duplicates
2005*16467b97STreehugger Robot */
2006*16467b97STreehugger Robot newEnt = (pANTLR3_TRIE_ENTRY)ANTLR3_CALLOC(1, sizeof(ANTLR3_TRIE_ENTRY));
2007*16467b97STreehugger Robot
2008*16467b97STreehugger Robot if (newEnt == NULL)
2009*16467b97STreehugger Robot {
2010*16467b97STreehugger Robot /* Out of memory, all we can do is return the fact that the insert failed.
2011*16467b97STreehugger Robot */
2012*16467b97STreehugger Robot return ANTLR3_FALSE;
2013*16467b97STreehugger Robot }
2014*16467b97STreehugger Robot
2015*16467b97STreehugger Robot /* Otherwise insert this in the chain
2016*16467b97STreehugger Robot */
2017*16467b97STreehugger Robot newEnt->type = type;
2018*16467b97STreehugger Robot newEnt->freeptr = freeptr;
2019*16467b97STreehugger Robot if (type == ANTLR3_HASH_TYPE_STR)
2020*16467b97STreehugger Robot {
2021*16467b97STreehugger Robot newEnt->data.ptr = data;
2022*16467b97STreehugger Robot }
2023*16467b97STreehugger Robot else
2024*16467b97STreehugger Robot {
2025*16467b97STreehugger Robot newEnt->data.intVal = intVal;
2026*16467b97STreehugger Robot }
2027*16467b97STreehugger Robot
2028*16467b97STreehugger Robot /* We want to be able to traverse the stored elements in the order that they were
2029*16467b97STreehugger Robot * added as duplicate keys. We might need to revise this opinion if we end up having many duplicate keys
2030*16467b97STreehugger Robot * as perhaps reverse order is just as good, so long as it is ordered.
2031*16467b97STreehugger Robot */
2032*16467b97STreehugger Robot nextEnt = nextNode->buckets;
2033*16467b97STreehugger Robot while (nextEnt->next != NULL)
2034*16467b97STreehugger Robot {
2035*16467b97STreehugger Robot nextEnt = nextEnt->next;
2036*16467b97STreehugger Robot }
2037*16467b97STreehugger Robot nextEnt->next = newEnt;
2038*16467b97STreehugger Robot
2039*16467b97STreehugger Robot trie->count++;
2040*16467b97STreehugger Robot return ANTLR3_TRUE;
2041*16467b97STreehugger Robot }
2042*16467b97STreehugger Robot else
2043*16467b97STreehugger Robot {
2044*16467b97STreehugger Robot /* We found the key is already there and we are not allowed duplicates in this
2045*16467b97STreehugger Robot * trie.
2046*16467b97STreehugger Robot */
2047*16467b97STreehugger Robot return ANTLR3_FALSE;
2048*16467b97STreehugger Robot }
2049*16467b97STreehugger Robot }
2050*16467b97STreehugger Robot
2051*16467b97STreehugger Robot /* Here we have discovered the only node that can be reached by the bits in the key
2052*16467b97STreehugger Robot * but we have found that this node is not the key we need to insert. We must find the
2053*16467b97STreehugger Robot * the leftmost bit by which the current key for that node and the new key we are going
2054*16467b97STreehugger Robot * to insert, differ. While this nested series of ifs may look a bit strange, experimentation
2055*16467b97STreehugger Robot * showed that it allows a machine code path that works well with predicated execution
2056*16467b97STreehugger Robot */
2057*16467b97STreehugger Robot xorKey = (key ^ nextNode->key); /* Gives 1 bits only where they differ then we find the left most 1 bit*/
2058*16467b97STreehugger Robot
2059*16467b97STreehugger Robot /* Most common case is a 32 bit key really
2060*16467b97STreehugger Robot */
2061*16467b97STreehugger Robot #ifdef ANTLR3_USE_64BIT
2062*16467b97STreehugger Robot if (xorKey & 0xFFFFFFFF00000000)
2063*16467b97STreehugger Robot {
2064*16467b97STreehugger Robot if (xorKey & 0xFFFF000000000000)
2065*16467b97STreehugger Robot {
2066*16467b97STreehugger Robot if (xorKey & 0xFF00000000000000)
2067*16467b97STreehugger Robot {
2068*16467b97STreehugger Robot depth = 56 + bitIndex[((xorKey & 0xFF00000000000000)>>56)];
2069*16467b97STreehugger Robot }
2070*16467b97STreehugger Robot else
2071*16467b97STreehugger Robot {
2072*16467b97STreehugger Robot depth = 48 + bitIndex[((xorKey & 0x00FF000000000000)>>48)];
2073*16467b97STreehugger Robot }
2074*16467b97STreehugger Robot }
2075*16467b97STreehugger Robot else
2076*16467b97STreehugger Robot {
2077*16467b97STreehugger Robot if (xorKey & 0x0000FF0000000000)
2078*16467b97STreehugger Robot {
2079*16467b97STreehugger Robot depth = 40 + bitIndex[((xorKey & 0x0000FF0000000000)>>40)];
2080*16467b97STreehugger Robot }
2081*16467b97STreehugger Robot else
2082*16467b97STreehugger Robot {
2083*16467b97STreehugger Robot depth = 32 + bitIndex[((xorKey & 0x000000FF00000000)>>32)];
2084*16467b97STreehugger Robot }
2085*16467b97STreehugger Robot }
2086*16467b97STreehugger Robot }
2087*16467b97STreehugger Robot else
2088*16467b97STreehugger Robot #endif
2089*16467b97STreehugger Robot {
2090*16467b97STreehugger Robot if (xorKey & 0x00000000FFFF0000)
2091*16467b97STreehugger Robot {
2092*16467b97STreehugger Robot if (xorKey & 0x00000000FF000000)
2093*16467b97STreehugger Robot {
2094*16467b97STreehugger Robot depth = 24 + bitIndex[((xorKey & 0x00000000FF000000)>>24)];
2095*16467b97STreehugger Robot }
2096*16467b97STreehugger Robot else
2097*16467b97STreehugger Robot {
2098*16467b97STreehugger Robot depth = 16 + bitIndex[((xorKey & 0x0000000000FF0000)>>16)];
2099*16467b97STreehugger Robot }
2100*16467b97STreehugger Robot }
2101*16467b97STreehugger Robot else
2102*16467b97STreehugger Robot {
2103*16467b97STreehugger Robot if (xorKey & 0x000000000000FF00)
2104*16467b97STreehugger Robot {
2105*16467b97STreehugger Robot depth = 8 + bitIndex[((xorKey & 0x0000000000000FF00)>>8)];
2106*16467b97STreehugger Robot }
2107*16467b97STreehugger Robot else
2108*16467b97STreehugger Robot {
2109*16467b97STreehugger Robot depth = bitIndex[xorKey & 0x00000000000000FF];
2110*16467b97STreehugger Robot }
2111*16467b97STreehugger Robot }
2112*16467b97STreehugger Robot }
2113*16467b97STreehugger Robot
2114*16467b97STreehugger Robot /* We have located the leftmost differing bit, indicated by the depth variable. So, we know what
2115*16467b97STreehugger Robot * bit index we are to insert the new entry at. There are two cases, being where the two keys
2116*16467b97STreehugger Robot * differ at a bit position that is not currently part of the bit testing, where they differ on a bit
2117*16467b97STreehugger Robot * that is currently being skipped in the indexed comparisons, and where they differ on a bit
2118*16467b97STreehugger Robot * that is merely lower down in the current bit search. If the bit index went bit 4, bit 2 and they differ
2119*16467b97STreehugger Robot * 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
2120*16467b97STreehugger Robot * then we have the easy bit <pun>.
2121*16467b97STreehugger Robot *
2122*16467b97STreehugger Robot * So, set up to descend the tree again, but this time looking for the insert point
2123*16467b97STreehugger Robot * according to whether we skip the bit that differs or not.
2124*16467b97STreehugger Robot */
2125*16467b97STreehugger Robot thisNode = trie->root;
2126*16467b97STreehugger Robot entNode = trie->root->leftN;
2127*16467b97STreehugger Robot
2128*16467b97STreehugger Robot /* Note the slight difference in the checks here to cover both cases
2129*16467b97STreehugger Robot */
2130*16467b97STreehugger Robot while (thisNode->bitNum > entNode->bitNum && entNode->bitNum > depth)
2131*16467b97STreehugger Robot {
2132*16467b97STreehugger Robot /* Still descending the structure, next node becomes current.
2133*16467b97STreehugger Robot */
2134*16467b97STreehugger Robot thisNode = entNode;
2135*16467b97STreehugger Robot
2136*16467b97STreehugger Robot if (key & bitMask[entNode->bitNum])
2137*16467b97STreehugger Robot {
2138*16467b97STreehugger Robot /* Bit at the required index was 1, so traverse the right node from here
2139*16467b97STreehugger Robot */
2140*16467b97STreehugger Robot entNode = entNode->rightN;
2141*16467b97STreehugger Robot }
2142*16467b97STreehugger Robot else
2143*16467b97STreehugger Robot {
2144*16467b97STreehugger Robot /* Bit at the required index was 0, so we traverse to the left
2145*16467b97STreehugger Robot */
2146*16467b97STreehugger Robot entNode = entNode->leftN;
2147*16467b97STreehugger Robot }
2148*16467b97STreehugger Robot }
2149*16467b97STreehugger Robot
2150*16467b97STreehugger Robot /* We have located the correct insert point for this new key, so we need
2151*16467b97STreehugger Robot * to allocate our entry and insert it etc.
2152*16467b97STreehugger Robot */
2153*16467b97STreehugger Robot nextNode = (pANTLR3_INT_TRIE_NODE)ANTLR3_CALLOC(1, sizeof(ANTLR3_INT_TRIE_NODE));
2154*16467b97STreehugger Robot if (nextNode == NULL)
2155*16467b97STreehugger Robot {
2156*16467b97STreehugger Robot /* All that work and no memory - bummer.
2157*16467b97STreehugger Robot */
2158*16467b97STreehugger Robot return ANTLR3_FALSE;
2159*16467b97STreehugger Robot }
2160*16467b97STreehugger Robot
2161*16467b97STreehugger Robot /* Build a new entry block for the new node
2162*16467b97STreehugger Robot */
2163*16467b97STreehugger Robot newEnt = (pANTLR3_TRIE_ENTRY)ANTLR3_CALLOC(1, sizeof(ANTLR3_TRIE_ENTRY));
2164*16467b97STreehugger Robot
2165*16467b97STreehugger Robot if (newEnt == NULL)
2166*16467b97STreehugger Robot {
2167*16467b97STreehugger Robot /* Out of memory, all we can do is return the fact that the insert failed.
2168*16467b97STreehugger Robot */
2169*16467b97STreehugger Robot return ANTLR3_FALSE;
2170*16467b97STreehugger Robot }
2171*16467b97STreehugger Robot
2172*16467b97STreehugger Robot /* Otherwise enter this in our new node
2173*16467b97STreehugger Robot */
2174*16467b97STreehugger Robot newEnt->type = type;
2175*16467b97STreehugger Robot newEnt->freeptr = freeptr;
2176*16467b97STreehugger Robot if (type == ANTLR3_HASH_TYPE_STR)
2177*16467b97STreehugger Robot {
2178*16467b97STreehugger Robot newEnt->data.ptr = data;
2179*16467b97STreehugger Robot }
2180*16467b97STreehugger Robot else
2181*16467b97STreehugger Robot {
2182*16467b97STreehugger Robot newEnt->data.intVal = intVal;
2183*16467b97STreehugger Robot }
2184*16467b97STreehugger Robot /* Install it
2185*16467b97STreehugger Robot */
2186*16467b97STreehugger Robot nextNode->buckets = newEnt;
2187*16467b97STreehugger Robot nextNode->key = key;
2188*16467b97STreehugger Robot nextNode->bitNum = depth;
2189*16467b97STreehugger Robot
2190*16467b97STreehugger Robot /* Work out the right and left pointers for this new node, which involve
2191*16467b97STreehugger Robot * terminating with the current found node either right or left according
2192*16467b97STreehugger Robot * to whether the current index bit is 1 or 0
2193*16467b97STreehugger Robot */
2194*16467b97STreehugger Robot if (key & bitMask[depth])
2195*16467b97STreehugger Robot {
2196*16467b97STreehugger Robot nextNode->leftN = entNode; /* Terminates at previous position */
2197*16467b97STreehugger Robot nextNode->rightN = nextNode; /* Terminates with itself */
2198*16467b97STreehugger Robot }
2199*16467b97STreehugger Robot else
2200*16467b97STreehugger Robot {
2201*16467b97STreehugger Robot nextNode->rightN = entNode; /* Terminates at previous position */
2202*16467b97STreehugger Robot nextNode->leftN = nextNode; /* Terminates with itself */
2203*16467b97STreehugger Robot }
2204*16467b97STreehugger Robot
2205*16467b97STreehugger Robot /* Finally, we need to change the pointers at the node we located
2206*16467b97STreehugger Robot * for inserting. If the key bit at its index is set then the right
2207*16467b97STreehugger Robot * pointer for that node becomes the newly created node, otherwise the left
2208*16467b97STreehugger Robot * pointer does.
2209*16467b97STreehugger Robot */
2210*16467b97STreehugger Robot if (key & bitMask[thisNode->bitNum] )
2211*16467b97STreehugger Robot {
2212*16467b97STreehugger Robot thisNode->rightN = nextNode;
2213*16467b97STreehugger Robot }
2214*16467b97STreehugger Robot else
2215*16467b97STreehugger Robot {
2216*16467b97STreehugger Robot thisNode->leftN = nextNode;
2217*16467b97STreehugger Robot }
2218*16467b97STreehugger Robot
2219*16467b97STreehugger Robot /* Et voila
2220*16467b97STreehugger Robot */
2221*16467b97STreehugger Robot trie->count++;
2222*16467b97STreehugger Robot return ANTLR3_TRUE;
2223*16467b97STreehugger Robot
2224*16467b97STreehugger Robot }
2225*16467b97STreehugger Robot /** Release memory allocated to this tree.
2226*16467b97STreehugger Robot * Basic algorithm is that we do a depth first left descent and free
2227*16467b97STreehugger Robot * up any nodes that are not backward pointers.
2228*16467b97STreehugger Robot */
2229*16467b97STreehugger Robot static void
freeIntNode(pANTLR3_INT_TRIE_NODE node)2230*16467b97STreehugger Robot freeIntNode(pANTLR3_INT_TRIE_NODE node)
2231*16467b97STreehugger Robot {
2232*16467b97STreehugger Robot pANTLR3_TRIE_ENTRY thisEntry;
2233*16467b97STreehugger Robot pANTLR3_TRIE_ENTRY nextEntry;
2234*16467b97STreehugger Robot
2235*16467b97STreehugger Robot /* If this node has a left pointer that is not a back pointer
2236*16467b97STreehugger Robot * then recursively call to free this
2237*16467b97STreehugger Robot */
2238*16467b97STreehugger Robot if (node->bitNum > node->leftN->bitNum)
2239*16467b97STreehugger Robot {
2240*16467b97STreehugger Robot /* We have a left node that needs descending, so do it.
2241*16467b97STreehugger Robot */
2242*16467b97STreehugger Robot freeIntNode(node->leftN);
2243*16467b97STreehugger Robot }
2244*16467b97STreehugger Robot
2245*16467b97STreehugger Robot /* The left nodes from here should now be dealt with, so
2246*16467b97STreehugger Robot * we need to descend any right nodes that are not back pointers
2247*16467b97STreehugger Robot */
2248*16467b97STreehugger Robot if (node->bitNum > node->rightN->bitNum)
2249*16467b97STreehugger Robot {
2250*16467b97STreehugger Robot /* There are some right nodes to descend and deal with.
2251*16467b97STreehugger Robot */
2252*16467b97STreehugger Robot freeIntNode(node->rightN);
2253*16467b97STreehugger Robot }
2254*16467b97STreehugger Robot
2255*16467b97STreehugger Robot /* Now all the children are dealt with, we can destroy
2256*16467b97STreehugger Robot * this node too
2257*16467b97STreehugger Robot */
2258*16467b97STreehugger Robot thisEntry = node->buckets;
2259*16467b97STreehugger Robot
2260*16467b97STreehugger Robot while (thisEntry != NULL)
2261*16467b97STreehugger Robot {
2262*16467b97STreehugger Robot nextEntry = thisEntry->next;
2263*16467b97STreehugger Robot
2264*16467b97STreehugger Robot /* Do we need to call a custom free pointer for this string entry?
2265*16467b97STreehugger Robot */
2266*16467b97STreehugger Robot if (thisEntry->type == ANTLR3_HASH_TYPE_STR && thisEntry->freeptr != NULL)
2267*16467b97STreehugger Robot {
2268*16467b97STreehugger Robot thisEntry->freeptr(thisEntry->data.ptr);
2269*16467b97STreehugger Robot }
2270*16467b97STreehugger Robot
2271*16467b97STreehugger Robot /* Now free the data for this bucket entry
2272*16467b97STreehugger Robot */
2273*16467b97STreehugger Robot ANTLR3_FREE(thisEntry);
2274*16467b97STreehugger Robot thisEntry = nextEntry; /* See if there are any more to free */
2275*16467b97STreehugger Robot }
2276*16467b97STreehugger Robot
2277*16467b97STreehugger Robot /* The bucket entry is now gone, so we can free the memory for
2278*16467b97STreehugger Robot * the entry itself.
2279*16467b97STreehugger Robot */
2280*16467b97STreehugger Robot ANTLR3_FREE(node);
2281*16467b97STreehugger Robot
2282*16467b97STreehugger Robot /* And that should be it for everything under this node and itself
2283*16467b97STreehugger Robot */
2284*16467b97STreehugger Robot }
2285*16467b97STreehugger Robot
2286*16467b97STreehugger Robot /** Called to free all nodes and the structure itself.
2287*16467b97STreehugger Robot */
2288*16467b97STreehugger Robot static void
intTrieFree(pANTLR3_INT_TRIE trie)2289*16467b97STreehugger Robot intTrieFree (pANTLR3_INT_TRIE trie)
2290*16467b97STreehugger Robot {
2291*16467b97STreehugger Robot /* Descend from the root and free all the nodes
2292*16467b97STreehugger Robot */
2293*16467b97STreehugger Robot freeIntNode(trie->root);
2294*16467b97STreehugger Robot
2295*16467b97STreehugger Robot /* the nodes are all gone now, so we need only free the memory
2296*16467b97STreehugger Robot * for the structure itself
2297*16467b97STreehugger Robot */
2298*16467b97STreehugger Robot ANTLR3_FREE(trie);
2299*16467b97STreehugger Robot }
2300*16467b97STreehugger Robot
2301*16467b97STreehugger Robot
2302*16467b97STreehugger Robot /**
2303*16467b97STreehugger Robot * Allocate and initialize a new ANTLR3 topological sorter, which can be
2304*16467b97STreehugger Robot * used to define edges that identify numerical node indexes that depend on other
2305*16467b97STreehugger Robot * numerical node indexes, which can then be sorted topologically such that
2306*16467b97STreehugger Robot * any node is sorted after all its dependent nodes.
2307*16467b97STreehugger Robot *
2308*16467b97STreehugger Robot * Use:
2309*16467b97STreehugger Robot *
2310*16467b97STreehugger Robot * /verbatim
2311*16467b97STreehugger Robot
2312*16467b97STreehugger Robot pANTLR3_TOPO topo;
2313*16467b97STreehugger Robot topo = antlr3NewTopo();
2314*16467b97STreehugger Robot
2315*16467b97STreehugger Robot if (topo == NULL) { out of memory }
2316*16467b97STreehugger Robot
2317*16467b97STreehugger Robot topo->addEdge(topo, 3, 0); // Node 3 depends on node 0
2318*16467b97STreehugger Robot topo->addEdge(topo, 0, 1); // Node - depends on node 1
2319*16467b97STreehugger Robot topo->sortVector(topo, myVector); // Sort the vector in place (node numbers are the vector entry numbers)
2320*16467b97STreehugger Robot
2321*16467b97STreehugger Robot * /verbatim
2322*16467b97STreehugger Robot */
2323*16467b97STreehugger Robot ANTLR3_API pANTLR3_TOPO
antlr3TopoNew()2324*16467b97STreehugger Robot antlr3TopoNew()
2325*16467b97STreehugger Robot {
2326*16467b97STreehugger Robot pANTLR3_TOPO topo = (pANTLR3_TOPO)ANTLR3_MALLOC(sizeof(ANTLR3_TOPO));
2327*16467b97STreehugger Robot
2328*16467b97STreehugger Robot if (topo == NULL)
2329*16467b97STreehugger Robot {
2330*16467b97STreehugger Robot return NULL;
2331*16467b97STreehugger Robot }
2332*16467b97STreehugger Robot
2333*16467b97STreehugger Robot // Initialize variables
2334*16467b97STreehugger Robot //
2335*16467b97STreehugger Robot
2336*16467b97STreehugger Robot topo->visited = NULL; // Don't know how big it is yet
2337*16467b97STreehugger Robot topo->limit = 1; // No edges added yet
2338*16467b97STreehugger Robot topo->edges = NULL; // No edges added yet
2339*16467b97STreehugger Robot topo->sorted = NULL; // Nothing sorted at the start
2340*16467b97STreehugger Robot topo->cycle = NULL; // No cycles at the start
2341*16467b97STreehugger Robot topo->cycleMark = 0; // No cycles at the start
2342*16467b97STreehugger Robot topo->hasCycle = ANTLR3_FALSE; // No cycle at the start
2343*16467b97STreehugger Robot
2344*16467b97STreehugger Robot // API
2345*16467b97STreehugger Robot //
2346*16467b97STreehugger Robot topo->addEdge = addEdge;
2347*16467b97STreehugger Robot topo->sortToArray = sortToArray;
2348*16467b97STreehugger Robot topo->sortVector = sortVector;
2349*16467b97STreehugger Robot topo->free = freeTopo;
2350*16467b97STreehugger Robot
2351*16467b97STreehugger Robot return topo;
2352*16467b97STreehugger Robot }
2353*16467b97STreehugger Robot // Topological sorter
2354*16467b97STreehugger Robot //
2355*16467b97STreehugger Robot static void
addEdge(pANTLR3_TOPO topo,ANTLR3_UINT32 edge,ANTLR3_UINT32 dependency)2356*16467b97STreehugger Robot addEdge (pANTLR3_TOPO topo, ANTLR3_UINT32 edge, ANTLR3_UINT32 dependency)
2357*16467b97STreehugger Robot {
2358*16467b97STreehugger Robot ANTLR3_UINT32 i;
2359*16467b97STreehugger Robot ANTLR3_UINT32 maxEdge;
2360*16467b97STreehugger Robot pANTLR3_BITSET edgeDeps;
2361*16467b97STreehugger Robot
2362*16467b97STreehugger Robot if (edge>dependency)
2363*16467b97STreehugger Robot {
2364*16467b97STreehugger Robot maxEdge = edge;
2365*16467b97STreehugger Robot }
2366*16467b97STreehugger Robot else
2367*16467b97STreehugger Robot {
2368*16467b97STreehugger Robot maxEdge = dependency;
2369*16467b97STreehugger Robot }
2370*16467b97STreehugger Robot // We need to add an edge to says that the node indexed by 'edge' is
2371*16467b97STreehugger Robot // dependent on the node indexed by 'dependency'
2372*16467b97STreehugger Robot //
2373*16467b97STreehugger Robot
2374*16467b97STreehugger Robot // First see if we have enough room in the edges array to add the edge?
2375*16467b97STreehugger Robot //
2376*16467b97STreehugger Robot if (topo->edges == NULL)
2377*16467b97STreehugger Robot {
2378*16467b97STreehugger Robot // We don't have any edges yet, so create an array to hold them
2379*16467b97STreehugger Robot //
2380*16467b97STreehugger Robot topo->edges = (pANTLR3_BITSET*)ANTLR3_CALLOC(sizeof(pANTLR3_BITSET) * (maxEdge + 1), 1);
2381*16467b97STreehugger Robot if (topo->edges == NULL)
2382*16467b97STreehugger Robot {
2383*16467b97STreehugger Robot return;
2384*16467b97STreehugger Robot }
2385*16467b97STreehugger Robot
2386*16467b97STreehugger Robot // Set the limit to what we have now
2387*16467b97STreehugger Robot //
2388*16467b97STreehugger Robot topo->limit = maxEdge + 1;
2389*16467b97STreehugger Robot }
2390*16467b97STreehugger Robot else if (topo->limit <= maxEdge)
2391*16467b97STreehugger Robot {
2392*16467b97STreehugger Robot // WE have some edges but not enough
2393*16467b97STreehugger Robot //
2394*16467b97STreehugger Robot topo->edges = (pANTLR3_BITSET*)ANTLR3_REALLOC(topo->edges, sizeof(pANTLR3_BITSET) * (maxEdge + 1));
2395*16467b97STreehugger Robot if (topo->edges == NULL)
2396*16467b97STreehugger Robot {
2397*16467b97STreehugger Robot return;
2398*16467b97STreehugger Robot }
2399*16467b97STreehugger Robot
2400*16467b97STreehugger Robot // Initialize the new bitmaps to ;indicate we have no edges defined yet
2401*16467b97STreehugger Robot //
2402*16467b97STreehugger Robot for (i = topo->limit; i <= maxEdge; i++)
2403*16467b97STreehugger Robot {
2404*16467b97STreehugger Robot *((topo->edges) + i) = NULL;
2405*16467b97STreehugger Robot }
2406*16467b97STreehugger Robot
2407*16467b97STreehugger Robot // Set the limit to what we have now
2408*16467b97STreehugger Robot //
2409*16467b97STreehugger Robot topo->limit = maxEdge + 1;
2410*16467b97STreehugger Robot }
2411*16467b97STreehugger Robot
2412*16467b97STreehugger Robot // If the edge was flagged as depending on itself, then we just
2413*16467b97STreehugger Robot // do nothing as it means this routine was just called to add it
2414*16467b97STreehugger Robot // in to the list of nodes.
2415*16467b97STreehugger Robot //
2416*16467b97STreehugger Robot if (edge == dependency)
2417*16467b97STreehugger Robot {
2418*16467b97STreehugger Robot return;
2419*16467b97STreehugger Robot }
2420*16467b97STreehugger Robot
2421*16467b97STreehugger Robot // Pick up the bit map for the requested edge
2422*16467b97STreehugger Robot //
2423*16467b97STreehugger Robot edgeDeps = *((topo->edges) + edge);
2424*16467b97STreehugger Robot
2425*16467b97STreehugger Robot if (edgeDeps == NULL)
2426*16467b97STreehugger Robot {
2427*16467b97STreehugger Robot // No edges are defined yet for this node
2428*16467b97STreehugger Robot //
2429*16467b97STreehugger Robot edgeDeps = antlr3BitsetNew(0);
2430*16467b97STreehugger Robot *((topo->edges) + edge) = edgeDeps;
2431*16467b97STreehugger Robot if (edgeDeps == NULL )
2432*16467b97STreehugger Robot {
2433*16467b97STreehugger Robot return; // Out of memory
2434*16467b97STreehugger Robot }
2435*16467b97STreehugger Robot }
2436*16467b97STreehugger Robot
2437*16467b97STreehugger Robot // Set the bit in the bitmap that corresponds to the requested
2438*16467b97STreehugger Robot // dependency.
2439*16467b97STreehugger Robot //
2440*16467b97STreehugger Robot edgeDeps->add(edgeDeps, dependency);
2441*16467b97STreehugger Robot
2442*16467b97STreehugger Robot // And we are all set
2443*16467b97STreehugger Robot //
2444*16467b97STreehugger Robot return;
2445*16467b97STreehugger Robot }
2446*16467b97STreehugger Robot
2447*16467b97STreehugger Robot
2448*16467b97STreehugger Robot /**
2449*16467b97STreehugger Robot * Given a starting node, descend its dependent nodes (ones that it has edges
2450*16467b97STreehugger Robot * to) until we find one without edges. Having found a node without edges, we have
2451*16467b97STreehugger Robot * discovered the bottom of a depth first search, which we can then ascend, adding
2452*16467b97STreehugger Robot * the nodes in order from the bottom, which gives us the dependency order.
2453*16467b97STreehugger Robot */
2454*16467b97STreehugger Robot static void
DFS(pANTLR3_TOPO topo,ANTLR3_UINT32 node)2455*16467b97STreehugger Robot DFS(pANTLR3_TOPO topo, ANTLR3_UINT32 node)
2456*16467b97STreehugger Robot {
2457*16467b97STreehugger Robot pANTLR3_BITSET edges;
2458*16467b97STreehugger Robot
2459*16467b97STreehugger Robot // Guard against a revisit and check for cycles
2460*16467b97STreehugger Robot //
2461*16467b97STreehugger Robot if (topo->hasCycle == ANTLR3_TRUE)
2462*16467b97STreehugger Robot {
2463*16467b97STreehugger Robot return; // We don't do anything else if we found a cycle
2464*16467b97STreehugger Robot }
2465*16467b97STreehugger Robot
2466*16467b97STreehugger Robot if (topo->visited->isMember(topo->visited, node))
2467*16467b97STreehugger Robot {
2468*16467b97STreehugger Robot // Check to see if we found a cycle. To do this we search the
2469*16467b97STreehugger Robot // current cycle stack and see if we find this node already in the stack.
2470*16467b97STreehugger Robot //
2471*16467b97STreehugger Robot ANTLR3_UINT32 i;
2472*16467b97STreehugger Robot
2473*16467b97STreehugger Robot for (i=0; i<topo->cycleMark; i++)
2474*16467b97STreehugger Robot {
2475*16467b97STreehugger Robot if (topo->cycle[i] == node)
2476*16467b97STreehugger Robot {
2477*16467b97STreehugger Robot // Stop! We found a cycle in the input, so rejig the cycle
2478*16467b97STreehugger Robot // stack so that it only contains the cycle and set the cycle flag
2479*16467b97STreehugger Robot // which will tell the caller what happened
2480*16467b97STreehugger Robot //
2481*16467b97STreehugger Robot ANTLR3_UINT32 l;
2482*16467b97STreehugger Robot
2483*16467b97STreehugger Robot for (l = i; l < topo->cycleMark; l++)
2484*16467b97STreehugger Robot {
2485*16467b97STreehugger Robot topo->cycle[l - i] = topo->cycle[l]; // Move to zero base in the cycle list
2486*16467b97STreehugger Robot }
2487*16467b97STreehugger Robot
2488*16467b97STreehugger Robot // Recalculate the limit
2489*16467b97STreehugger Robot //
2490*16467b97STreehugger Robot topo->cycleMark -= i;
2491*16467b97STreehugger Robot
2492*16467b97STreehugger Robot // Signal disaster
2493*16467b97STreehugger Robot //
2494*16467b97STreehugger Robot topo->hasCycle = ANTLR3_TRUE;
2495*16467b97STreehugger Robot }
2496*16467b97STreehugger Robot }
2497*16467b97STreehugger Robot return;
2498*16467b97STreehugger Robot }
2499*16467b97STreehugger Robot
2500*16467b97STreehugger Robot // So far, no cycles have been found and we have not visited this node yet,
2501*16467b97STreehugger Robot // so this node needs to go into the cycle stack before we continue
2502*16467b97STreehugger Robot // then we will take it out of the stack once we have descended all its
2503*16467b97STreehugger Robot // dependencies.
2504*16467b97STreehugger Robot //
2505*16467b97STreehugger Robot topo->cycle[topo->cycleMark++] = node;
2506*16467b97STreehugger Robot
2507*16467b97STreehugger Robot // First flag that we have visited this node
2508*16467b97STreehugger Robot //
2509*16467b97STreehugger Robot topo->visited->add(topo->visited, node);
2510*16467b97STreehugger Robot
2511*16467b97STreehugger Robot // Now, if this node has edges, then we want to ensure we visit
2512*16467b97STreehugger Robot // them all before we drop through and add this node into the sorted
2513*16467b97STreehugger Robot // list.
2514*16467b97STreehugger Robot //
2515*16467b97STreehugger Robot edges = *((topo->edges) + node);
2516*16467b97STreehugger Robot if (edges != NULL)
2517*16467b97STreehugger Robot {
2518*16467b97STreehugger Robot // We have some edges, so visit each of the edge nodes
2519*16467b97STreehugger Robot // that have not already been visited.
2520*16467b97STreehugger Robot //
2521*16467b97STreehugger Robot ANTLR3_UINT32 numBits; // How many bits are in the set
2522*16467b97STreehugger Robot ANTLR3_UINT32 i;
2523*16467b97STreehugger Robot ANTLR3_UINT32 range;
2524*16467b97STreehugger Robot
2525*16467b97STreehugger Robot numBits = edges->numBits(edges);
2526*16467b97STreehugger Robot range = edges->size(edges); // Number of set bits
2527*16467b97STreehugger Robot
2528*16467b97STreehugger Robot // Stop if we exahust the bit list or have checked the
2529*16467b97STreehugger Robot // number of edges that this node refers to (so we don't
2530*16467b97STreehugger Robot // check bits at the end that cannot possibly be set).
2531*16467b97STreehugger Robot //
2532*16467b97STreehugger Robot for (i=0; i<= numBits && range > 0; i++)
2533*16467b97STreehugger Robot {
2534*16467b97STreehugger Robot if (edges->isMember(edges, i))
2535*16467b97STreehugger Robot {
2536*16467b97STreehugger Robot range--; // About to check another one
2537*16467b97STreehugger Robot
2538*16467b97STreehugger Robot // Found an edge, make sure we visit and descend it
2539*16467b97STreehugger Robot //
2540*16467b97STreehugger Robot DFS(topo, i);
2541*16467b97STreehugger Robot }
2542*16467b97STreehugger Robot }
2543*16467b97STreehugger Robot }
2544*16467b97STreehugger Robot
2545*16467b97STreehugger Robot // At this point we will have visited all the dependencies
2546*16467b97STreehugger Robot // of this node and they will be ordered (even if there are cycles)
2547*16467b97STreehugger Robot // So we just add the node into the sorted list at the
2548*16467b97STreehugger Robot // current index position.
2549*16467b97STreehugger Robot //
2550*16467b97STreehugger Robot topo->sorted[topo->limit++] = node;
2551*16467b97STreehugger Robot
2552*16467b97STreehugger Robot // Remove this node from the cycle list if we have not detected a cycle
2553*16467b97STreehugger Robot //
2554*16467b97STreehugger Robot if (topo->hasCycle == ANTLR3_FALSE)
2555*16467b97STreehugger Robot {
2556*16467b97STreehugger Robot topo->cycleMark--;
2557*16467b97STreehugger Robot }
2558*16467b97STreehugger Robot
2559*16467b97STreehugger Robot return;
2560*16467b97STreehugger Robot }
2561*16467b97STreehugger Robot
2562*16467b97STreehugger Robot static pANTLR3_UINT32
sortToArray(pANTLR3_TOPO topo)2563*16467b97STreehugger Robot sortToArray (pANTLR3_TOPO topo)
2564*16467b97STreehugger Robot {
2565*16467b97STreehugger Robot ANTLR3_UINT32 v;
2566*16467b97STreehugger Robot ANTLR3_UINT32 oldLimit;
2567*16467b97STreehugger Robot
2568*16467b97STreehugger Robot // Guard against being called with no edges defined
2569*16467b97STreehugger Robot //
2570*16467b97STreehugger Robot if (topo->edges == NULL)
2571*16467b97STreehugger Robot {
2572*16467b97STreehugger Robot return NULL;
2573*16467b97STreehugger Robot }
2574*16467b97STreehugger Robot // First we need a vector to populate with enough
2575*16467b97STreehugger Robot // entries to accommodate the sorted list and another to accommodate
2576*16467b97STreehugger Robot // the maximum cycle we could detect which is all nodes such as 0->1->2->3->0
2577*16467b97STreehugger Robot //
2578*16467b97STreehugger Robot topo->sorted = (pANTLR3_UINT32)ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
2579*16467b97STreehugger Robot if (topo->sorted == NULL)
2580*16467b97STreehugger Robot {
2581*16467b97STreehugger Robot return NULL;
2582*16467b97STreehugger Robot }
2583*16467b97STreehugger Robot topo->cycle = (pANTLR3_UINT32)ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
2584*16467b97STreehugger Robot if (topo->cycle == NULL)
2585*16467b97STreehugger Robot {
2586*16467b97STreehugger Robot return NULL;
2587*16467b97STreehugger Robot }
2588*16467b97STreehugger Robot
2589*16467b97STreehugger Robot // Next we need an empty bitset to show whether we have visited a node
2590*16467b97STreehugger Robot // or not. This is the bit that gives us linear time of course as we are essentially
2591*16467b97STreehugger Robot // dropping through the nodes in depth first order and when we get to a node that
2592*16467b97STreehugger Robot // has no edges, we pop back up the stack adding the nodes we traversed in reverse
2593*16467b97STreehugger Robot // order.
2594*16467b97STreehugger Robot //
2595*16467b97STreehugger Robot topo->visited = antlr3BitsetNew(0);
2596*16467b97STreehugger Robot
2597*16467b97STreehugger Robot // Now traverse the nodes as if we were just going left to right, but
2598*16467b97STreehugger Robot // then descend each node unless it has already been visited.
2599*16467b97STreehugger Robot //
2600*16467b97STreehugger Robot oldLimit = topo->limit; // Number of nodes to traverse linearly
2601*16467b97STreehugger Robot topo->limit = 0; // Next entry in the sorted table
2602*16467b97STreehugger Robot
2603*16467b97STreehugger Robot for (v = 0; v < oldLimit; v++)
2604*16467b97STreehugger Robot {
2605*16467b97STreehugger Robot // If we did not already visit this node, then descend it until we
2606*16467b97STreehugger Robot // get a node without edges or arrive at a node we have already visited.
2607*16467b97STreehugger Robot //
2608*16467b97STreehugger Robot if (topo->visited->isMember(topo->visited, v) == ANTLR3_FALSE)
2609*16467b97STreehugger Robot {
2610*16467b97STreehugger Robot // We have not visited this one so descend it
2611*16467b97STreehugger Robot //
2612*16467b97STreehugger Robot DFS(topo, v);
2613*16467b97STreehugger Robot }
2614*16467b97STreehugger Robot
2615*16467b97STreehugger Robot // Break the loop if we detect a cycle as we have no need to go any
2616*16467b97STreehugger Robot // further
2617*16467b97STreehugger Robot //
2618*16467b97STreehugger Robot if (topo->hasCycle == ANTLR3_TRUE)
2619*16467b97STreehugger Robot {
2620*16467b97STreehugger Robot break;
2621*16467b97STreehugger Robot }
2622*16467b97STreehugger Robot }
2623*16467b97STreehugger Robot
2624*16467b97STreehugger Robot // Reset the limit to the number we recorded as if we hit a
2625*16467b97STreehugger Robot // cycle, then limit will have stopped at the node where we
2626*16467b97STreehugger Robot // discovered the cycle, but in order to free the edge bitmaps
2627*16467b97STreehugger Robot // we need to know how many we may have allocated and traverse them all.
2628*16467b97STreehugger Robot //
2629*16467b97STreehugger Robot topo->limit = oldLimit;
2630*16467b97STreehugger Robot
2631*16467b97STreehugger Robot // Having traversed all the nodes we were given, we
2632*16467b97STreehugger Robot // are guaranteed to have ordered all the nodes or detected a
2633*16467b97STreehugger Robot // cycle.
2634*16467b97STreehugger Robot //
2635*16467b97STreehugger Robot return topo->sorted;
2636*16467b97STreehugger Robot }
2637*16467b97STreehugger Robot
2638*16467b97STreehugger Robot static void
sortVector(pANTLR3_TOPO topo,pANTLR3_VECTOR v)2639*16467b97STreehugger Robot sortVector (pANTLR3_TOPO topo, pANTLR3_VECTOR v)
2640*16467b97STreehugger Robot {
2641*16467b97STreehugger Robot // To sort a vector, we first perform the
2642*16467b97STreehugger Robot // sort to an array, then use the results to reorder the vector
2643*16467b97STreehugger Robot // we are given. This is just a convenience routine that allows you to
2644*16467b97STreehugger Robot // sort the children of a tree node into topological order before or
2645*16467b97STreehugger Robot // during an AST walk. This can be useful for optimizations that require
2646*16467b97STreehugger Robot // dag reorders and also when the input stream defines things that are
2647*16467b97STreehugger Robot // interdependent and you want to walk the list of the generated trees
2648*16467b97STreehugger Robot // for those things in topological order so you can ignore the interdependencies
2649*16467b97STreehugger Robot // at that point.
2650*16467b97STreehugger Robot //
2651*16467b97STreehugger Robot ANTLR3_UINT32 i;
2652*16467b97STreehugger Robot
2653*16467b97STreehugger Robot // Used as a lookup index to find the current location in the vector of
2654*16467b97STreehugger Robot // the vector entry that was originally at position [0], [1], [2] etc
2655*16467b97STreehugger Robot //
2656*16467b97STreehugger Robot pANTLR3_UINT32 vIndex;
2657*16467b97STreehugger Robot
2658*16467b97STreehugger Robot // Sort into an array, then we can use the array that is
2659*16467b97STreehugger Robot // stored in the topo
2660*16467b97STreehugger Robot //
2661*16467b97STreehugger Robot if (topo->sortToArray(topo) == 0)
2662*16467b97STreehugger Robot {
2663*16467b97STreehugger Robot return; // There were no edges
2664*16467b97STreehugger Robot }
2665*16467b97STreehugger Robot
2666*16467b97STreehugger Robot if (topo->hasCycle == ANTLR3_TRUE)
2667*16467b97STreehugger Robot {
2668*16467b97STreehugger Robot return; // Do nothing if we detected a cycle
2669*16467b97STreehugger Robot }
2670*16467b97STreehugger Robot
2671*16467b97STreehugger Robot // Ensure that the vector we are sorting is at least as big as the
2672*16467b97STreehugger Robot // the input sequence we were asked to sort. It does not matter if it is
2673*16467b97STreehugger Robot // bigger as that probably just means that nodes numbered higher than the
2674*16467b97STreehugger Robot // limit had no dependencies and so can be left alone.
2675*16467b97STreehugger Robot //
2676*16467b97STreehugger Robot if (topo->limit > v->count)
2677*16467b97STreehugger Robot {
2678*16467b97STreehugger Robot // We can only sort the entries that we have dude! The caller is
2679*16467b97STreehugger Robot // responsible for ensuring the vector is the correct one and is the
2680*16467b97STreehugger Robot // correct size etc.
2681*16467b97STreehugger Robot //
2682*16467b97STreehugger Robot topo->limit = v->count;
2683*16467b97STreehugger Robot }
2684*16467b97STreehugger Robot // We need to know the locations of each of the entries
2685*16467b97STreehugger Robot // in the vector as we don't want to duplicate them in a new vector. We
2686*16467b97STreehugger Robot // just use an indirection table to get the vector entry for a particular sequence
2687*16467b97STreehugger Robot // according to where we moved it last. Then we can just swap vector entries until
2688*16467b97STreehugger Robot // we are done :-)
2689*16467b97STreehugger Robot //
2690*16467b97STreehugger Robot vIndex = (pANTLR3_UINT32)ANTLR3_MALLOC(topo->limit * sizeof(ANTLR3_UINT32));
2691*16467b97STreehugger Robot if (vIndex == NULL)
2692*16467b97STreehugger Robot {
2693*16467b97STreehugger Robot // malloc failed
2694*16467b97STreehugger Robot return;
2695*16467b97STreehugger Robot }
2696*16467b97STreehugger Robot
2697*16467b97STreehugger Robot // Start index, each vector entry is located where you think it is
2698*16467b97STreehugger Robot //
2699*16467b97STreehugger Robot for (i = 0; i < topo->limit; i++)
2700*16467b97STreehugger Robot {
2701*16467b97STreehugger Robot vIndex[i] = i;
2702*16467b97STreehugger Robot }
2703*16467b97STreehugger Robot
2704*16467b97STreehugger Robot // Now we traverse the sorted array and moved the entries of
2705*16467b97STreehugger Robot // the vector around according to the sort order and the indirection
2706*16467b97STreehugger Robot // table we just created. The index telsl us where in the vector the
2707*16467b97STreehugger Robot // original element entry n is now located via vIndex[n].
2708*16467b97STreehugger Robot //
2709*16467b97STreehugger Robot for (i=0; i < topo->limit; i++)
2710*16467b97STreehugger Robot {
2711*16467b97STreehugger Robot ANTLR3_UINT32 ind;
2712*16467b97STreehugger Robot
2713*16467b97STreehugger Robot // If the vector entry at i is already the one that it
2714*16467b97STreehugger Robot // should be, then we skip moving it of course.
2715*16467b97STreehugger Robot //
2716*16467b97STreehugger Robot if (vIndex[topo->sorted[i]] == i)
2717*16467b97STreehugger Robot {
2718*16467b97STreehugger Robot continue;
2719*16467b97STreehugger Robot }
2720*16467b97STreehugger Robot
2721*16467b97STreehugger Robot // The vector entry at i, should be replaced with the
2722*16467b97STreehugger Robot // vector entry indicated by topo->sorted[i]. The vector entry
2723*16467b97STreehugger Robot // at topo->sorted[i] may have already been swapped out though, so we
2724*16467b97STreehugger Robot // find where it is now and move it from there to i.
2725*16467b97STreehugger Robot //
2726*16467b97STreehugger Robot ind = vIndex[topo->sorted[i]];
2727*16467b97STreehugger Robot v->swap(v, i, ind);
2728*16467b97STreehugger Robot
2729*16467b97STreehugger Robot // Update our index. The element at i is now the one we wanted
2730*16467b97STreehugger Robot // to be sorted here and the element we swapped out is now the
2731*16467b97STreehugger Robot // element that was at i just before we swapped it. If you are lost now
2732*16467b97STreehugger Robot // don't worry about it, we are just reindexing on the fly is all.
2733*16467b97STreehugger Robot //
2734*16467b97STreehugger Robot vIndex[topo->sorted[i]] = i;
2735*16467b97STreehugger Robot vIndex[i] = ind;
2736*16467b97STreehugger Robot }
2737*16467b97STreehugger Robot
2738*16467b97STreehugger Robot // Having traversed all the entries, we have sorted the vector in place.
2739*16467b97STreehugger Robot //
2740*16467b97STreehugger Robot ANTLR3_FREE(vIndex);
2741*16467b97STreehugger Robot return;
2742*16467b97STreehugger Robot }
2743*16467b97STreehugger Robot
2744*16467b97STreehugger Robot static void
freeTopo(pANTLR3_TOPO topo)2745*16467b97STreehugger Robot freeTopo (pANTLR3_TOPO topo)
2746*16467b97STreehugger Robot {
2747*16467b97STreehugger Robot ANTLR3_UINT32 i;
2748*16467b97STreehugger Robot
2749*16467b97STreehugger Robot // Free the result vector
2750*16467b97STreehugger Robot //
2751*16467b97STreehugger Robot if (topo->sorted != NULL)
2752*16467b97STreehugger Robot {
2753*16467b97STreehugger Robot ANTLR3_FREE(topo->sorted);
2754*16467b97STreehugger Robot topo->sorted = NULL;
2755*16467b97STreehugger Robot }
2756*16467b97STreehugger Robot
2757*16467b97STreehugger Robot // Free the visited map
2758*16467b97STreehugger Robot //
2759*16467b97STreehugger Robot if (topo->visited != NULL)
2760*16467b97STreehugger Robot {
2761*16467b97STreehugger Robot
2762*16467b97STreehugger Robot topo->visited->free(topo->visited);
2763*16467b97STreehugger Robot topo->visited = NULL;
2764*16467b97STreehugger Robot }
2765*16467b97STreehugger Robot
2766*16467b97STreehugger Robot // Free any edgemaps
2767*16467b97STreehugger Robot //
2768*16467b97STreehugger Robot if (topo->edges != NULL)
2769*16467b97STreehugger Robot {
2770*16467b97STreehugger Robot pANTLR3_BITSET edgeList;
2771*16467b97STreehugger Robot
2772*16467b97STreehugger Robot
2773*16467b97STreehugger Robot for (i=0; i<topo->limit; i++)
2774*16467b97STreehugger Robot {
2775*16467b97STreehugger Robot edgeList = *((topo->edges) + i);
2776*16467b97STreehugger Robot if (edgeList != NULL)
2777*16467b97STreehugger Robot {
2778*16467b97STreehugger Robot edgeList->free(edgeList);
2779*16467b97STreehugger Robot }
2780*16467b97STreehugger Robot }
2781*16467b97STreehugger Robot
2782*16467b97STreehugger Robot ANTLR3_FREE(topo->edges);
2783*16467b97STreehugger Robot }
2784*16467b97STreehugger Robot topo->edges = NULL;
2785*16467b97STreehugger Robot
2786*16467b97STreehugger Robot // Free any cycle map
2787*16467b97STreehugger Robot //
2788*16467b97STreehugger Robot if (topo->cycle != NULL)
2789*16467b97STreehugger Robot {
2790*16467b97STreehugger Robot ANTLR3_FREE(topo->cycle);
2791*16467b97STreehugger Robot }
2792*16467b97STreehugger Robot
2793*16467b97STreehugger Robot ANTLR3_FREE(topo);
2794*16467b97STreehugger Robot }
2795