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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_webserver/] [sym.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 
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                      symMax;                         /* One past the max symbol table */
37
static int                      symOpenCount = 0;        /* Count of apps using sym */
38
 
39
static int                      htIndex;                        /* Current location in table */
40
static sym_t*           next;                           /* Next symbol in iteration */
41
 
42
/**************************** Forward Declarations ****************************/
43
 
44
static int              hashIndex(sym_tabent_t *tp, char_t *name);
45
static sym_t    *hash(sym_tabent_t *tp, char_t *name);
46
static int              calcPrime(int size);
47
 
48
/*********************************** Code *************************************/
49
/*
50
 *      Open the symbol table subSystem.
51
 */
52
 
53
int 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
 
67
void symSubClose()
68
{
69
        if (--symOpenCount <= 0) {
70
                symOpenCount = 0;
71
        }
72
}
73
 
74
/******************************************************************************/
75
/*
76
 *      Create a symbol table.
77
 */
78
 
79
sym_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
 
124
void 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
 
159
sym_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
 
194
sym_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
 
231
sym_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
 
266
sym_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
 
346
int 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
 
399
static 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
 
413
static 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
 
438
static 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
 
458
static 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
 

powered by: WebSVN 2.1.0

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