OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [sym.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * sym.c -- Symbol Table module
3
 *
4
 * Copyright (c) GoAhead Software Inc., 1995-1999. 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
 
27
typedef 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
 
35
static sym_tabent_t             **sym;                  /* List of symbol tables */
36
static int                              sym_max;                /* One past the max symbol table */
37
 
38
static int              htIndex;                                /* Current location in table */
39
static sym_t*   next;                                   /* Next symbol in iteration */
40
 
41
/**************************** Forward Declarations ****************************/
42
 
43
static int              hashIndex(sym_tabent_t *tp, char_t *name);
44
static sym_t    *hash(sym_tabent_t *tp, char_t *name);
45
static int              calc_prime(int size);
46
 
47
/*********************************** Code *************************************/
48
/*
49
 *      Create a symbol table.
50
 */
51
 
52
sym_fd_t symOpen(int hash_size)
53
{
54
        sym_fd_t                sd;
55
        sym_tabent_t    *tp;
56
 
57
        a_assert(hash_size > 2);
58
 
59
/*
60
 *      Create a new handle for this symbol table
61
 */
62
        if ((sd = hAlloc((void***) &sym)) < 0) {
63
                return -1;
64
        }
65
 
66
/*
67
 *      Create a new symbol table structure and zero
68
 */
69
        if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
70
                sym_max = hFree((void***) &sym, sd);
71
                return -1;
72
        }
73
        memset(tp, 0, sizeof(sym_tabent_t));
74
        if (sd >= sym_max) {
75
                sym_max = sd + 1;
76
        }
77
        a_assert(0 <= sd && sd < sym_max);
78
        sym[sd] = tp;
79
 
80
/*
81
 *      Now create the hash table for fast indexing.
82
 */
83
        tp->hash_size = calc_prime(hash_size);
84
        tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*));
85
        a_assert(tp->hash_table);
86
        memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
87
 
88
        return sd;
89
}
90
 
91
/******************************************************************************/
92
/*
93
 *      Close this symbol table. Call a cleanup function to allow the caller
94
 *      to free resources associated with each symbol table entry.
95
 */
96
 
97
void symClose(sym_fd_t sd, void (*cleanup)(sym_t *symp))
98
{
99
        sym_tabent_t    *tp;
100
        sym_t                   *sp, *forw;
101
        int                     i;
102
 
103
        a_assert(0 <= sd && sd < sym_max);
104
        tp = sym[sd];
105
        a_assert(tp);
106
 
107
/*
108
 *      Free all symbols in the hash table, then the hash table itself.
109
 */
110
        for (i = 0; i < tp->hash_size; i++) {
111
                for (sp = tp->hash_table[i]; sp; sp = forw) {
112
                        forw = sp->forw;
113
                        if (cleanup) {
114
                                (*cleanup)(sp);
115
                        }
116
                        valueFree(&sp->name);
117
                        bfree(B_L, (void*) sp);
118
                        sp = forw;
119
                }
120
        }
121
        bfree(B_L, (void*) tp->hash_table);
122
 
123
        sym_max = hFree((void***) &sym, sd);
124
        bfree(B_L, (void*) tp);
125
}
126
 
127
/******************************************************************************/
128
/*
129
 *      Default callback for freeing the value.
130
 */
131
 
132
void symFreeVar(sym_t* sp)
133
{
134
        valueFree(&sp->content);
135
}
136
 
137
/******************************************************************************/
138
/*
139
 *      Return the first symbol in the hashtable if there is one. This call is used
140
 *      as the first step in traversing the table. A call to symFirst should be
141
 *      followed by calls to symNext to get all the rest of the entries.
142
 */
143
 
144
sym_t* symFirst(sym_fd_t sd)
145
{
146
        sym_tabent_t    *tp;
147
        sym_t                   *sp, *forw;
148
        int                     i;
149
 
150
        a_assert(0 <= sd && sd < sym_max);
151
        tp = sym[sd];
152
        a_assert(tp);
153
 
154
/*
155
 *      Find the first symbol in the hashtable and return a pointer to it.
156
 */
157
        for (i = 0; i < tp->hash_size; i++) {
158
                for (sp = tp->hash_table[i]; sp; sp = forw) {
159
                        forw = sp->forw;
160
 
161
                        if (forw == NULL) {
162
                                htIndex = i + 1;
163
                                next = tp->hash_table[htIndex];
164
                        } else {
165
                                htIndex = i;
166
                                next = forw;
167
                        }
168
                        return sp;
169
                }
170
        }
171
        return NULL;
172
}
173
 
174
/******************************************************************************/
175
/*
176
 *      Return the next symbol in the hashtable if there is one. See symFirst.
177
 */
178
 
179
sym_t* symNext(sym_fd_t sd)
180
{
181
        sym_tabent_t    *tp;
182
        sym_t                   *sp, *forw;
183
        int                     i;
184
 
185
        a_assert(0 <= sd && sd < sym_max);
186
        tp = sym[sd];
187
        a_assert(tp);
188
 
189
/*
190
 *      Find the first symbol in the hashtable and return a pointer to it.
191
 */
192
        for (i = htIndex; i < tp->hash_size; i++) {
193
                for (sp = next; sp; sp = forw) {
194
                        forw = sp->forw;
195
 
196
                        if (forw == NULL) {
197
                                htIndex = i + 1;
198
                                next = tp->hash_table[htIndex];
199
                        } else {
200
                                htIndex = i;
201
                                next = forw;
202
                        }
203
                        return sp;
204
                }
205
                next = tp->hash_table[i + 1];
206
        }
207
        return NULL;
208
}
209
 
210
/******************************************************************************/
211
/*
212
 *      Lookup a symbol and return a pointer to the symbol entry. If not present
213
 *      then return a NULL.
214
 */
215
 
216
sym_t *symLookup(sym_fd_t sd, char_t *name)
217
{
218
        sym_tabent_t    *tp;
219
        sym_t                   *sp;
220
        char_t                  *cp;
221
 
222
        a_assert(0 <= sd && sd < sym_max);
223
        tp = sym[sd];
224
        a_assert(tp);
225
 
226
        if (name == NULL || *name == '\0') {
227
                return NULL;
228
        }
229
 
230
/*
231
 *      Do an initial hash and then follow the link chain to find the right entry
232
 */
233
        for (sp = hash(tp, name); sp; sp = sp->forw) {
234
                cp = sp->name.value.string;
235
                if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
236
                        break;
237
                }
238
        }
239
        return sp;
240
}
241
 
242
/******************************************************************************/
243
/*
244
 *      Enter a symbol into the table.  If already there, update its value.
245
 *      Always succeeds if memory available.
246
 */
247
 
248
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
249
{
250
        sym_tabent_t    *tp;
251
        sym_t                   *sp, *last;
252
        char_t                  *cp;
253
        int                             hindex;
254
 
255
        a_assert(name && *name);
256
        a_assert(0 <= sd && sd < sym_max);
257
        tp = sym[sd];
258
        a_assert(tp);
259
 
260
/*
261
 *      Calculate the first daisy-chain from the hash table.  If non-zero, then
262
 *      we have daisy-chain, so scan it and look for the symbol.
263
 */
264
        last = NULL;
265
        hindex = hashIndex(tp, name);
266
        if ((sp = tp->hash_table[hindex]) != NULL) {
267
                for (; sp; sp = sp->forw) {
268
                        cp = sp->name.value.string;
269
                        if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
270
                                break;
271
                        }
272
                        last = sp;
273
                }
274
                if (sp) {
275
/*
276
 *                      Found, so update the value
277
 *                      If the caller stores handles which require freeing, they
278
 *                      will be lost here. It is the callers responsibility to free
279
 *                      resources before overwriting existing contents. We will here
280
 *                      free allocated strings which occur due to value_instring().
281
 *                      We should consider providing the cleanup function on the open rather
282
 *                      than the close and then we could call it here and solve the problem.
283
 */
284
                        if (sp->content.valid) {
285
                                valueFree(&sp->content);
286
                        }
287
                        sp->content = v;
288
                        sp->arg = arg;
289
                        return sp;
290
                }
291
/*
292
 *              Not found so allocate and append to the daisy-chain
293
 */
294
                sp = (sym_t*) balloc(B_L, sizeof(sym_t));
295
                if (sp == NULL) {
296
                        return NULL;
297
                }
298
                sp->name = valueString(name, VALUE_ALLOCATE);
299
                sp->content = v;
300
                sp->forw = (sym_t*) NULL;
301
                sp->arg = arg;
302
                last->forw = sp;
303
 
304
        } else {
305
/*
306
 *              Daisy chain is empty so we need to start the chain
307
 */
308
                sp = (sym_t*) balloc(B_L, sizeof(sym_t));
309
                if (sp == NULL) {
310
                        return NULL;
311
                }
312
                tp->hash_table[hindex] = sp;
313
                tp->hash_table[hashIndex(tp, name)] = sp;
314
 
315
                sp->forw = (sym_t*) NULL;
316
                sp->content = v;
317
                sp->arg = arg;
318
                sp->name = valueString(name, VALUE_ALLOCATE);
319
        }
320
        return sp;
321
}
322
 
323
/******************************************************************************/
324
/*
325
 *      Delete a symbol from a table
326
 */
327
 
328
int symDelete(sym_fd_t sd, char_t *name)
329
{
330
        sym_tabent_t    *tp;
331
        sym_t                   *sp, *last;
332
        char_t                  *cp;
333
        int                             hindex;
334
 
335
        a_assert(name && *name);
336
        a_assert(0 <= sd && sd < sym_max);
337
        tp = sym[sd];
338
        a_assert(tp);
339
 
340
/*
341
 *      Calculate the first daisy-chain from the hash table.  If non-zero, then
342
 *      we have daisy-chain, so scan it and look for the symbol.
343
 */
344
        last = NULL;
345
        hindex = hashIndex(tp, name);
346
        if ((sp = tp->hash_table[hindex]) != NULL) {
347
                for ( ; sp; sp = sp->forw) {
348
                        cp = sp->name.value.string;
349
                        if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
350
                                break;
351
                        }
352
                        last = sp;
353
                }
354
        }
355
        if (sp == (sym_t*) NULL) {                              /* Not Found */
356
                return -1;
357
        }
358
 
359
/*
360
 *      Unlink and free the symbol. Last will be set if the element to be deleted
361
 *      is not first in the chain.
362
 */
363
        if (last) {
364
                last->forw = sp->forw;
365
        } else {
366
                tp->hash_table[hindex] = sp->forw;
367
        }
368
        valueFree(&sp->name);
369
        bfree(B_L, (void*) sp);
370
 
371
        return 0;
372
}
373
 
374
/******************************************************************************/
375
/*
376
 *      Hash a symbol and return a pointer to the hash daisy-chain list
377
 *      All symbols reside on the chain (ie. none stored in the hash table itself)
378
 */
379
 
380
static sym_t *hash(sym_tabent_t *tp, char_t *name)
381
{
382
        a_assert(tp);
383
 
384
        return tp->hash_table[hashIndex(tp, name)];
385
}
386
 
387
/******************************************************************************/
388
/*
389
 *      Compute the hash function and return an index into the hash table
390
 *      We use a basic additive function that is then made modulo the size of the
391
 *      table.
392
 */
393
 
394
static int hashIndex(sym_tabent_t *tp, char_t *name)
395
{
396
        unsigned int    sum;
397
        int                     i;
398
 
399
        a_assert(tp);
400
/*
401
 *      Add in each character shifted up progressively by 7 bits. The shift
402
 *      amount is rounded so as to not shift too far.  It thus cycles with each
403
 *      new cycle placing character shifted up by one bit.
404
 */
405
        i = 0;
406
        sum = 0;
407
        while (*name) {
408
                sum += (((int) *name++) << i);
409
                i = (i + 7) % (BITS(int) - BITSPERBYTE);
410
        }
411
        return sum % tp->hash_size;
412
}
413
 
414
/******************************************************************************/
415
/*
416
 *      Check if this number is a prime
417
 */
418
 
419
static int is_prime(int n)
420
{
421
        int     i;
422
 
423
        a_assert(n > 0);
424
 
425
        for (i = 2; i < n; i++) {
426
                if (n % i == 0) {
427
                        return 0;
428
                }
429
        }
430
        return 1;
431
}
432
 
433
/******************************************************************************/
434
/*
435
 *      Calculate the largest prime smaller than size.
436
 */
437
 
438
static int calc_prime(int size)
439
{
440
        int count;
441
 
442
        a_assert(size > 0);
443
 
444
        for (count = size; count > 0; count--) {
445
                if (is_prime(count)) {
446
                        return count;
447
                }
448
        }
449
        return 1;
450
}
451
 
452
/******************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.