source: rtems/c/src/libnetworking/rtems_webserver/sym.c @ 7a97f26

4.104.114.84.95
Last change on this file since 7a97f26 was a6b4c0df, checked in by Joel Sherrill <joel.sherrill@…>, on 09/01/00 at 10:57:21

2000-08-30 Joel Sherrill <joel@…>

  • Merged version 2.1 of GoAhead? webserver. This update was submitted by Antti P Miettinen <antti.p.miettinen@…>.
  • NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c, um.c, um.h: New files.
  • wbase64.c: Removed.
  • Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c, form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c, socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c, webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*
2 * sym.c -- Symbol Table module
3 *
4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 */
8
9/******************************** Description *********************************/
10/*
11 *      This module implements a highly efficient generic symbol table with
12 *      update and access routines. Symbols are simple character strings and
13 *      the values they take can be flexible types as defined by value_t.
14 *      This modules allows multiple symbol tables to be created.
15 */
16
17/********************************* Includes ***********************************/
18
19#if UEMF
20        #include        "uemf.h"
21#else
22        #include        "basic/basicInternal.h"
23#endif
24
25/********************************* Defines ************************************/
26
27typedef struct {                                                /* Symbol table descriptor */
28        int             inuse;                                          /* Is this entry in use */
29        int             hash_size;                                      /* Size of the table below */
30        sym_t   **hash_table;                           /* Allocated at run time */
31} sym_tabent_t;
32
33/********************************* Globals ************************************/
34
35static sym_tabent_t     **sym;                          /* List of symbol tables */
36static int                      symMax;                         /* One past the max symbol table */
37static int                      symOpenCount = 0;       /* Count of apps using sym */
38
39static int                      htIndex;                        /* Current location in table */
40static sym_t*           next;                           /* Next symbol in iteration */
41
42/**************************** Forward Declarations ****************************/
43
44static int              hashIndex(sym_tabent_t *tp, char_t *name);
45static sym_t    *hash(sym_tabent_t *tp, char_t *name);
46static int              calcPrime(int size);
47
48/*********************************** Code *************************************/
49/*
50 *      Open the symbol table subSystem.
51 */
52
53int symSubOpen()
54{
55        if (++symOpenCount == 1) {
56                symMax = 0;
57                sym = NULL;
58        }
59        return 0;
60}
61
62/******************************************************************************/
63/*
64 *      Close the symbol table subSystem.
65 */
66
67void symSubClose()
68{
69        if (--symOpenCount <= 0) {
70                symOpenCount = 0;
71        }
72}
73
74/******************************************************************************/
75/*
76 *      Create a symbol table.
77 */
78
79sym_fd_t symOpen(int hash_size)
80{
81        sym_fd_t                sd;
82        sym_tabent_t    *tp;
83
84        a_assert(hash_size > 2);
85
86/*
87 *      Create a new handle for this symbol table
88 */
89        if ((sd = hAlloc((void***) &sym)) < 0) {
90                return -1;
91        }
92
93/*
94 *      Create a new symbol table structure and zero
95 */
96        if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
97                symMax = hFree((void***) &sym, sd);
98                return -1;
99        }
100        memset(tp, 0, sizeof(sym_tabent_t));
101        if (sd >= symMax) {
102                symMax = sd + 1;
103        }
104        a_assert(0 <= sd && sd < symMax);
105        sym[sd] = tp;
106
107/*
108 *      Now create the hash table for fast indexing.
109 */
110        tp->hash_size = calcPrime(hash_size);
111        tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*));
112        a_assert(tp->hash_table);
113        memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
114
115        return sd;
116}
117
118/******************************************************************************/
119/*
120 *      Close this symbol table. Call a cleanup function to allow the caller
121 *      to free resources associated with each symbol table entry.
122 */
123
124void symClose(sym_fd_t sd)
125{
126        sym_tabent_t    *tp;
127        sym_t                   *sp, *forw;
128        int                             i;
129
130        a_assert(0 <= sd && sd < symMax);
131        tp = sym[sd];
132        a_assert(tp);
133
134/*
135 *      Free all symbols in the hash table, then the hash table itself.
136 */
137        for (i = 0; i < tp->hash_size; i++) {
138                for (sp = tp->hash_table[i]; sp; sp = forw) {
139                        forw = sp->forw;
140                        valueFree(&sp->name);
141                        valueFree(&sp->content);
142                        bfree(B_L, (void*) sp);
143                        sp = forw;
144                }
145        }
146        bfree(B_L, (void*) tp->hash_table);
147
148        symMax = hFree((void***) &sym, sd);
149        bfree(B_L, (void*) tp);
150}
151
152/******************************************************************************/
153/*
154 *      Return the first symbol in the hashtable if there is one. This call is used
155 *      as the first step in traversing the table. A call to symFirst should be
156 *      followed by calls to symNext to get all the rest of the entries.
157 */
158
159sym_t* symFirst(sym_fd_t sd)
160{
161        sym_tabent_t    *tp;
162        sym_t                   *sp, *forw;
163        int                             i;
164
165        a_assert(0 <= sd && sd < symMax);
166        tp = sym[sd];
167        a_assert(tp);
168
169/*
170 *      Find the first symbol in the hashtable and return a pointer to it.
171 */
172        for (i = 0; i < tp->hash_size; i++) {
173                for (sp = tp->hash_table[i]; sp; sp = forw) {
174                        forw = sp->forw;
175
176                        if (forw == NULL) {
177                                htIndex = i + 1;
178                                next = tp->hash_table[htIndex];
179                        } else {
180                                htIndex = i;
181                                next = forw;
182                        }
183                        return sp;
184                }
185        }
186        return NULL;
187}
188
189/******************************************************************************/
190/*
191 *      Return the next symbol in the hashtable if there is one. See symFirst.
192 */
193
194sym_t* symNext(sym_fd_t sd)
195{
196        sym_tabent_t    *tp;
197        sym_t                   *sp, *forw;
198        int                             i;
199
200        a_assert(0 <= sd && sd < symMax);
201        tp = sym[sd];
202        a_assert(tp);
203
204/*
205 *      Find the first symbol in the hashtable and return a pointer to it.
206 */
207        for (i = htIndex; i < tp->hash_size; i++) {
208                for (sp = next; sp; sp = forw) {
209                        forw = sp->forw;
210
211                        if (forw == NULL) {
212                                htIndex = i + 1;
213                                next = tp->hash_table[htIndex];
214                        } else {
215                                htIndex = i;
216                                next = forw;
217                        }
218                        return sp;
219                }
220                next = tp->hash_table[i + 1];
221        }
222        return NULL;
223}
224
225/******************************************************************************/
226/*
227 *      Lookup a symbol and return a pointer to the symbol entry. If not present
228 *      then return a NULL.
229 */
230
231sym_t *symLookup(sym_fd_t sd, char_t *name)
232{
233        sym_tabent_t    *tp;
234        sym_t                   *sp;
235        char_t                  *cp;
236
237        a_assert(0 <= sd && sd < symMax);
238        if ((tp = sym[sd]) == NULL) {
239                return NULL;
240        }
241
242        if (name == NULL || *name == '\0') {
243                return NULL;
244        }
245
246/*
247 *      Do an initial hash and then follow the link chain to find the right entry
248 */
249        for (sp = hash(tp, name); sp; sp = sp->forw) {
250                cp = sp->name.value.string;
251                if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
252                        break;
253                }
254        }
255        return sp;
256}
257
258/******************************************************************************/
259/*
260 *      Enter a symbol into the table. If already there, update its value.
261 *      Always succeeds if memory available. We allocate a copy of "name" here
262 *      so it can be a volatile variable. The value "v" is just a copy of the
263 *      passed in value, so it MUST be persistent.
264 */
265
266sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
267{
268        sym_tabent_t    *tp;
269        sym_t                   *sp, *last;
270        char_t                  *cp;
271        int                             hindex;
272
273        a_assert(name);
274        a_assert(0 <= sd && sd < symMax);
275        tp = sym[sd];
276        a_assert(tp);
277
278/*
279 *      Calculate the first daisy-chain from the hash table. If non-zero, then
280 *      we have daisy-chain, so scan it and look for the symbol.
281 */
282        last = NULL;
283        hindex = hashIndex(tp, name);
284        if ((sp = tp->hash_table[hindex]) != NULL) {
285                for (; sp; sp = sp->forw) {
286                        cp = sp->name.value.string;
287                        if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
288                                break;
289                        }
290                        last = sp;
291                }
292                if (sp) {
293/*
294 *                      Found, so update the value
295 *                      If the caller stores handles which require freeing, they
296 *                      will be lost here. It is the callers responsibility to free
297 *                      resources before overwriting existing contents. We will here
298 *                      free allocated strings which occur due to value_instring().
299 *                      We should consider providing the cleanup function on the open rather
300 *                      than the close and then we could call it here and solve the problem.
301 */
302                        if (sp->content.valid) {
303                                valueFree(&sp->content);
304                        }
305                        sp->content = v;
306                        sp->arg = arg;
307                        return sp;
308                }
309/*
310 *              Not found so allocate and append to the daisy-chain
311 */
312                sp = (sym_t*) balloc(B_L, sizeof(sym_t));
313                if (sp == NULL) {
314                        return NULL;
315                }
316                sp->name = valueString(name, VALUE_ALLOCATE);
317                sp->content = v;
318                sp->forw = (sym_t*) NULL;
319                sp->arg = arg;
320                last->forw = sp;
321
322        } else {
323/*
324 *              Daisy chain is empty so we need to start the chain
325 */
326                sp = (sym_t*) balloc(B_L, sizeof(sym_t));
327                if (sp == NULL) {
328                        return NULL;
329                }
330                tp->hash_table[hindex] = sp;
331                tp->hash_table[hashIndex(tp, name)] = sp;
332
333                sp->forw = (sym_t*) NULL;
334                sp->content = v;
335                sp->arg = arg;
336                sp->name = valueString(name, VALUE_ALLOCATE);
337        }
338        return sp;
339}
340
341/******************************************************************************/
342/*
343 *      Delete a symbol from a table
344 */
345
346int symDelete(sym_fd_t sd, char_t *name)
347{
348        sym_tabent_t    *tp;
349        sym_t                   *sp, *last;
350        char_t                  *cp;
351        int                             hindex;
352
353        a_assert(name && *name);
354        a_assert(0 <= sd && sd < symMax);
355        tp = sym[sd];
356        a_assert(tp);
357
358/*
359 *      Calculate the first daisy-chain from the hash table. If non-zero, then
360 *      we have daisy-chain, so scan it and look for the symbol.
361 */
362        last = NULL;
363        hindex = hashIndex(tp, name);
364        if ((sp = tp->hash_table[hindex]) != NULL) {
365                for ( ; sp; sp = sp->forw) {
366                        cp = sp->name.value.string;
367                        if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
368                                break;
369                        }
370                        last = sp;
371                }
372        }
373        if (sp == (sym_t*) NULL) {                              /* Not Found */
374                return -1;
375        }
376
377/*
378 *      Unlink and free the symbol. Last will be set if the element to be deleted
379 *      is not first in the chain.
380 */
381        if (last) {
382                last->forw = sp->forw;
383        } else {
384                tp->hash_table[hindex] = sp->forw;
385        }
386        valueFree(&sp->name);
387        valueFree(&sp->content);
388        bfree(B_L, (void*) sp);
389
390        return 0;
391}
392
393/******************************************************************************/
394/*
395 *      Hash a symbol and return a pointer to the hash daisy-chain list
396 *      All symbols reside on the chain (ie. none stored in the hash table itself)
397 */
398
399static sym_t *hash(sym_tabent_t *tp, char_t *name)
400{
401        a_assert(tp);
402
403        return tp->hash_table[hashIndex(tp, name)];
404}
405
406/******************************************************************************/
407/*
408 *      Compute the hash function and return an index into the hash table
409 *      We use a basic additive function that is then made modulo the size of the
410 *      table.
411 */
412
413static int hashIndex(sym_tabent_t *tp, char_t *name)
414{
415        unsigned int    sum;
416        int                             i;
417
418        a_assert(tp);
419/*
420 *      Add in each character shifted up progressively by 7 bits. The shift
421 *      amount is rounded so as to not shift too far. It thus cycles with each
422 *      new cycle placing character shifted up by one bit.
423 */
424        i = 0;
425        sum = 0;
426        while (*name) {
427                sum += (((int) *name++) << i);
428                i = (i + 7) % (BITS(int) - BITSPERBYTE);
429        }
430        return sum % tp->hash_size;
431}
432
433/******************************************************************************/
434/*
435 *      Check if this number is a prime
436 */
437
438static int isPrime(int n)
439{
440        int             i, max;
441
442        a_assert(n > 0);
443
444        max = n / 2;
445        for (i = 2; i <= max; i++) {
446                if (n % i == 0) {
447                        return 0;
448                }
449        }
450        return 1;
451}
452
453/******************************************************************************/
454/*
455 *      Calculate the largest prime smaller than size.
456 */
457
458static int calcPrime(int size)
459{
460        int count;
461
462        a_assert(size > 0);
463
464        for (count = size; count > 0; count--) {
465                if (isPrime(count)) {
466                        return count;
467                }
468        }
469        return 1;
470}
471
472/******************************************************************************/
473
Note: See TracBrowser for help on using the repository browser.