2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * File: Symbolic.c $XConsortium: Symbolic.c /main/5 1996/09/27 19:00:23 drk $
27 * (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
29 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
30 * (c) Copyright 1993, 1994 International Business Machines Corp. *
31 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
32 * (c) Copyright 1993, 1994 Novell, Inc. *
35 #include <Dt/UserMsg.h>
37 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
42 #include <bms/XeUserMsg.h>
43 #include <bms/MemoryMgr.h>
44 #include <bms/Symbolic.h>
46 #include <codelibs/stringx.h> /* strhash */
47 #include "DtSvcLock.h"
49 /******************************************************************************/
52 /* This is the default symbol table to use */
53 /* --------------------------------------- */
54 #define XE_END_OF_HASH_TABLE (XeSymtabList) -1
56 static XeSymTable D_sym_table = NULL;
58 typedef struct _unknown_entry_data {
60 } *unknown_entry_data;
63 /******************************************************************************/
64 /* Symbol (hash) Table */
66 /*------------------------------------------------------------------------+*/
68 keyhash(XeSymTable t, void *key)
69 /*------------------------------------------------------------------------+*/
75 hash = t->hash_fn( key, t->hashsize );
76 if (hash >= t->hashsize)
77 _DtSimpleError(XeProgName, XeInternalError, NULL,
78 (XeString) "Symbolic.c: Hash value from user hash function out of range",
80 /* We don't come back from the error routine */
84 hash = strhash( (const char *) key );
85 hash = hash & (t->hashsize - 1);
93 /*------------------------------------------------------------------------+*/
95 trap_bad_hash_fn(void * UNUSED_PARM(ptr), unsigned int UNUSED_PARM(size))
96 /*------------------------------------------------------------------------+*/
98 _DtSimpleError(XeProgName, XeInternalError, NULL,
99 (XeString) "Symbolic.c: Hash table at must be power of 2",
101 /* We don't come back from the error routine */
105 /*------------------------------------------------------------------------+*/
107 Xe_new_symtab(unsigned int hashsize)
108 /*------------------------------------------------------------------------+*/
110 /* Note, hashsize must be power of 2 if using default hash function */
115 XeSymTable t = (XeSymTable) XeMalloc( sizeof (struct _XeSymTable) );
116 t->hashsize = hashsize;
118 t->list = (XeSymtabList *)XeMalloc( sizeof( XeSymtabList ) * hashsize );
120 for (i = 0; i < hashsize; i++)
121 t->list[i] = (XeSymtabList)NULL;
123 t->curr_list = XE_END_OF_HASH_TABLE;
132 /* If not a power of two, user better have a hash function */
133 /* that handles that. Install hash function trap so that if */
134 /* he does not install one, we catch it. */
135 /* --------------------------------------------------------- */
136 if (hashsize & (hashsize - 1))
137 t->hash_fn = trap_bad_hash_fn;
142 /*------------------------------------------------------------------------+*/
144 Xe_default_symtab(void)
145 /*------------------------------------------------------------------------+*/
147 #define D_HASHSIZE 256
151 _DtSvcProcessUnlock();
155 D_sym_table = Xe_new_symtab(D_HASHSIZE);
156 _DtSvcProcessUnlock();
159 /*------------------------------------------------------------------------+*/
161 NukeOneItem(XeSymTable t, XeSymtabList l)
162 /*------------------------------------------------------------------------+*/
166 /* For standard XeSymbols: */
167 /* 1) Free the name */
168 /* 2) Call free function if configured */
169 /* 3) Free the XeSymbol entry */
170 /* ---------------------------------------- */
171 if (l->data_is_XeSymbol)
173 XeFree( ((XeSymbol)l->data)->name );
175 t->clean_fn( ((XeSymbol)l->data)->value );
178 /* For "anysym" symbols: */
179 /* 1) Call free function if configured */
180 /* 2) If we malloced the data, free it */
181 /* ---------------------------------------- */
185 t->clean_fn( l->data );
187 if (l->data_is_malloc_mem)
196 /*------------------------------------------------------------------------+*/
198 Xe_set_sym_fns(XeSymTable t,
200 XeSymFn_init init_fn,
201 XeSymFn_clean clean_fn,
202 XeSymFn_hash hash_fn)
203 /*------------------------------------------------------------------------+*/
206 if (!t) t = Xe_default_symtab();
209 t->init_fn = init_fn;
210 t->clean_fn = clean_fn;
211 t->hash_fn = hash_fn;
215 /*------------------------------------------------------------------------+*/
217 make_sym(XeString name)
218 /*------------------------------------------------------------------------+*/
220 XeSymbol sym = Xe_make_struct(_XeSymbol);
222 sym->name = strdup( name );
223 sym->value = (void*)NULL;
227 /*------------------------------------------------------------------------+*/
229 intern_something(XeSymTable t,
235 /*------------------------------------------------------------------------+*/
244 /* If no cmp function assume first item of "data" is a string pointer */
245 /* ------------------------------------------------------------------ */
249 hash_key = (t->hash_fn) ? data : ((unknown_entry_data) data)->name;
251 hash = keyhash( t, hash_key );
257 for (l0 = NULL; l; l0 = l, l = l->rest)
265 cmp_key = (t->cmp_fn) ? data : ((unknown_entry_data) data)->name;
267 if (l->data_is_XeSymbol)
268 cmp_key2 = ((XeSymbol) l->data)->name;
270 cmp_key2 = (t->cmp_fn) ? l->data : ((unknown_entry_data) l->data)->name;
272 /* Use the "compare" function to see if we have a match on our key */
273 /* --------------------------------------------------------------- */
275 match = (t->cmp_fn( cmp_key, cmp_key2 ) == 0);
277 match = (strcmp((const char *) cmp_key, (const char *)cmp_key2 ) == 0);
283 /* If just doing a lookup, don't add a new symbol */
284 /* ---------------------------------------------- */
285 if (lookup_only) return (void *) NULL;
287 /* There was no match. We need to create an entry in the hash table. */
288 /* ------------------------------------------------------------------ */
289 l = (XeSymtabList) XeMalloc( sizeof(struct _XeSymtabList) );
290 l->rest = (XeSymtabList)NULL;
291 l->data_is_XeSymbol = is_XeSymbol;
292 l->data_is_malloc_mem = FALSE;
300 /* If we have a standard symbol, make the XeSymbol entry. */
301 /* -------------------------------------------------------- */
304 XeSymbol sym = make_sym((XeString)data);
305 l->data = (void*) sym;
307 sym->value = t->init_fn( l->data, size /* will be 0 */ );
311 /* 1) If "size" != 0, */
312 /* - malloc "size" bytes, */
313 /* - copy "data" into malloced space, */
314 /* - Save pointer to malloc space as user's data pointer */
316 /* - Save "data" as pointer to user's data */
317 /* 2) If a "init_fn" is configured, */
318 /* - call init_fn( user's data pointer, "size" ) */
319 /* - set user's data pointer to return value of init_fn */
320 /* ONLY if "size" was zero. */
322 /* If size is non zero AND there is a user's malloc function, */
323 /* beware that the return value from the malloc function is not*/
324 /* save anywhere by these routines. If size was zero, the */
325 /* return value of the user's function is kept. */
326 /* ------------------------------------------------------------------ */
329 l->data = XeMalloc( size );
330 memcpy(l->data, data, size);
331 l->data_is_malloc_mem = TRUE;
338 void * new_data = t->init_fn( l->data, size );
347 /* appended to the end of the hash chain (if any). */
348 /* --------------------------------------------------------------- */
354 printf("Added data %p in list[%d] @ %p\n", l->data, hash, l);
360 /*------------------------------------------------------------------------+*/
362 Xe_intern(XeSymTable t, ConstXeString const name)
363 /*------------------------------------------------------------------------+*/
365 if (!name) return (XeSymbol)NULL;
367 if (!t) t = Xe_default_symtab();
369 return (XeSymbol)intern_something(t, (void *)name, 0, TRUE, FALSE, (int*)NULL);
372 /*------------------------------------------------------------------------+*/
374 Xe_lookup(XeSymTable t, ConstXeString const name)
375 /*------------------------------------------------------------------------+*/
377 if (!name) return (XeSymbol)NULL;
379 if (!t) t = Xe_default_symtab();
381 return (XeSymbol)intern_something(t, (void *)name, 0, TRUE, TRUE, (int*)NULL);
384 /******************************************************************************/
387 /*------------------------------------------------------------------------+*/
389 Xe_make_list(void * data, XeList rest)
390 /*------------------------------------------------------------------------+*/
392 XeList temp = Xe_make_struct(_XeList);
400 /******************************************************************************/
403 /*------------------------------------------------------------------------+*/
405 Xe_init_queue(XeQueue q, void * nullval)
406 /*------------------------------------------------------------------------+*/
413 /*------------------------------------------------------------------------+*/
415 Xe_make_queue(void * nullval)
416 /*------------------------------------------------------------------------+*/
418 return Xe_init_queue(Xe_make_struct(_XeQueue), nullval);
421 /*------------------------------------------------------------------------+*/
423 Xe_pop_queue(XeQueue q)
424 /*------------------------------------------------------------------------+*/
426 XeList head = q->head;
429 void * val = head->data;
431 q->head = head->rest;
438 /*------------------------------------------------------------------------+*/
440 Xe_delete_queue_element(XeQueue q, void * val)
441 /*------------------------------------------------------------------------+*/
443 XeList last = 0, head = q->head;
446 if (head->data == val) {
448 last->rest = head->rest;
450 q->head = head->rest;
456 last = head, head = head->rest;
460 /*------------------------------------------------------------------------+*/
462 Xe_push_queue(XeQueue q, void * val)
463 /*------------------------------------------------------------------------+*/
465 XeList new_ptr = Xe_make_list(val, 0);
468 q->tail->rest = new_ptr;
474 /*------------------------------------------------------------------------+*/
476 Xe_release_queue(XeQueue q)
477 /*------------------------------------------------------------------------+*/